var core = use('core') var camera = use('camera') var compositor = use('compositor') var input = use('input') var Grid = use('examples/chess/grid') var MovementSystem = use('examples/chess/movement') var startingPos = use('examples/chess/pieces').startingPosition var rules = use('examples/chess/rules') var board_view = use('examples/chess/board_view') var grid = Grid(8, 8) grid.width = 8 grid.height = 8 var mover = MovementSystem(grid, rules) startingPos(grid) board_view.init(grid) var S = board_view.S, GW = board_view.GW, GH = board_view.GH var move_history = [] var game_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}}) var hud_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}}) input.configure({ action_map: { select: ['mouse_button_left'], cancel: ['escape', 'mouse_button_right'] } }) var selectPos = null var validMoves = [] var hover_gx = -1, hover_gy = -1 var file_letters = "abcdefgh" function sq_name(x, y) { return text(file_letters, x, x + 1) + text(y + 1) } function compute_valid_moves(from) { validMoves = [] var piece = grid.at(from)[0] if (!piece) return var x = 0, y = 0, to = null, dest = null for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { to = [x, y] dest = grid.at(to) if (length(dest) && dest[0].colour == piece.colour) continue if (rules.canMove(piece, from, to, grid)) validMoves[] = to } } } var game_input = { on_input: function(action, data) { var clicked = null, cell = null, is_valid = false, i = 0, src_piece = null if (!data.pressed) return if (action == 'cancel') { selectPos = null validMoves = [] board_view.highlight(selectPos, validMoves, hover_gx, hover_gy) return } if (action == 'select' && hover_gx >= 0 && hover_gx < 8 && hover_gy >= 0 && hover_gy < 8) { clicked = [hover_gx, hover_gy] cell = grid.at(clicked) if (selectPos) { is_valid = false for (i = 0; i < length(validMoves); i++) { if (validMoves[i][0] == clicked[0] && validMoves[i][1] == clicked[1]) { is_valid = true break } } if (is_valid) { src_piece = grid.at(selectPos)[0] if (src_piece && mover.tryMove(src_piece, clicked)) { move_history[] = sq_name(selectPos[0], selectPos[1]) + "-" + sq_name(clicked[0], clicked[1]) log.chess("move " + sq_name(selectPos[0], selectPos[1]) + "-" + sq_name(clicked[0], clicked[1]) + " turn=" + mover.turn) board_view.sync_pieces(grid) board_view.set_status(mover.turn + "'s turn") } selectPos = null validMoves = [] } else if (length(cell) && cell[0].colour == mover.turn) { selectPos = clicked compute_valid_moves(selectPos) } else { selectPos = null validMoves = [] } } else { if (length(cell) && cell[0].colour == mover.turn) { selectPos = clicked compute_valid_moves(selectPos) } } board_view.highlight(selectPos, validMoves, hover_gx, hover_gy) } } } input.player1().possess(game_input) // --- Probe endpoints for AI play --- var probe = use('probe') function piece_char(p) { var chars = {king: "K", queen: "Q", rook: "R", bishop: "B", knight: "N", pawn: "P"} var c = chars[p.kind] if (p.colour == 'black') c = lower(c) return c } probe.register("chess", { board: function(a) { var rows = [] var y = 0, x = 0, cell = null, row = null for (y = 7; y >= 0; y--) { row = "" for (x = 0; x < 8; x++) { cell = grid.at([x, y]) if (length(cell)) { row = row + piece_char(cell[0]) } else { row = row + "." } if (x < 7) row = row + " " } rows[] = row } return {turn: mover.turn, moves: move_history, board: rows} }, move: function(a) { var fx = a.fx, fy = a.fy, tx = a.tx, ty = a.ty if (is_null(fx) || is_null(fy) || is_null(tx) || is_null(ty)) return {ok: false, error: "need fx fy tx ty"} var from = [fx, fy] var to = [tx, ty] var cell = grid.at(from) if (!length(cell)) return {ok: false, error: "no piece at " + sq_name(fx, fy)} var piece = cell[0] if (piece.colour != mover.turn) return {ok: false, error: "not " + piece.colour + "'s turn"} if (!rules.canMove(piece, from, to, grid)) return {ok: false, error: "illegal move"} if (mover.tryMove(piece, to)) { move_history[] = sq_name(fx, fy) + "-" + sq_name(tx, ty) log.chess("move " + sq_name(fx, fy) + "-" + sq_name(tx, ty) + " turn=" + mover.turn) board_view.sync_pieces(grid) board_view.set_status(mover.turn + "'s turn") return {ok: true, move: sq_name(fx, fy) + "-" + sq_name(tx, ty)} } return {ok: false, error: "move rejected"} } }) var comp_config = { clear: {r: 0.15, g: 0.15, b: 0.2, a: 1}, planes: [ {name: 'game', camera: game_cam, resolution: {width: GW, height: GH}, presentation: 'letterbox'}, {name: 'hud', camera: hud_cam, resolution: {width: GW, height: GH}, presentation: 'stretch'} ] } core.start({ width: 640, height: 640, title: "Chess", probe: true, input: function(ev) { var wp = null if (ev.type == 'mouse_motion') { wp = game_cam.window_to_world(ev.pos[0], ev.pos[1]) if (wp) { hover_gx = floor(wp.x / S) hover_gy = floor(wp.y / S) } } }, update: function(dt) { board_view.highlight(selectPos, validMoves, hover_gx, hover_gy) }, render: function() { return compositor.execute(compositor.compile(comp_config)) } })