/* main.js – runs the demo with your prototype-based grid */ var json = use('json') var draw2d = use('prosperon/draw2d') var blob = use('blob') /*──── import our pieces + systems ───────────────────────────────────*/ var Grid = use('grid'); // your new ctor var MovementSystem = use('movement').MovementSystem; var startingPos = use('pieces').startingPosition; var rules = use('rules'); /*──── build board ───────────────────────────────────────────────────*/ var grid = new Grid(8, 8); grid.width = 8; // (the ctor didn't store them) grid.height = 8; var mover = new MovementSystem(grid, rules); startingPos(grid); /*──── networking and game state ─────────────────────────────────────*/ var gameState = 'waiting'; // 'waiting', 'searching', 'server_waiting', 'connected' var isServer = false; var opponent = null; var myColor = null; // 'white' or 'black' var isMyTurn = false; function updateTitle() { var title = "Misty Chess - "; switch(gameState) { case 'waiting': title += "Press S to start server or J to join"; break; case 'searching': title += "Searching for server..."; break; case 'server_waiting': title += "Waiting for player to join..."; break; case 'connected': if (myColor) { title += (mover.turn == myColor ? "Your turn (" + myColor + ")" : "Opponent's turn (" + mover.turn + ")"); } else { title += mover.turn + " turn"; } break; } log.console(title) } // Initialize title updateTitle(); /*──── mouse → click-to-move ─────────────────────────────────────────*/ var selectPos = null; var hoverPos = null; var holdingPiece = false; var opponentMousePos = null; var opponentHoldingPiece = false; var opponentSelectPos = null; function handleMouseButtonDown(e) { if (e.which != 0) return; // Don't allow piece selection unless we have an opponent if (gameState != 'connected' || !opponent) return; var mx = e.mouse.x; var my = e.mouse.y; var c = [Math.floor(mx / 60), Math.floor(my / 60)]; if (!grid.inBounds(c)) return; var cell = grid.at(c); if (cell.length && cell[0].colour == mover.turn) { selectPos = c; holdingPiece = true; // Send pickup notification to opponent if (opponent) { send(opponent, { type: 'piece_pickup', pos: c }); } } else { selectPos = null; } } function handleMouseButtonUp(e) { if (e.which != 0 || !holdingPiece || !selectPos) return; // Don't allow moves unless we have an opponent and it's our turn if (gameState != 'connected' || !opponent || !isMyTurn) { holdingPiece = false; return; } var mx = e.mouse.x; var my = e.mouse.y; var c = [Math.floor(mx / 60), Math.floor(my / 60)]; if (!grid.inBounds(c)) { holdingPiece = false; return; } if (mover.tryMove(grid.at(selectPos)[0], c)) { log.console("Made move from", selectPos, "to", c); // Send move to opponent log.console("Sending move to opponent:", opponent); send(opponent, { type: 'move', from: selectPos, to: c }); isMyTurn = false; // It's now opponent's turn log.console("Move sent, now opponent's turn"); selectPos = null; updateTitle(); } holdingPiece = false; // Send piece drop notification to opponent if (opponent) { send(opponent, { type: 'piece_drop' }); } } function handleMouseMotion(e) { var mx = e.pos.x; var my = e.pos.y; var c = [Math.floor(mx / 60), Math.floor(my / 60)]; if (!grid.inBounds(c)) { hoverPos = null; return; } hoverPos = c; // Send mouse position to opponent in real-time if (opponent && gameState == 'connected') { send(opponent, { type: 'mouse_move', pos: c, holding: holdingPiece, selectPos: selectPos }); } } function handleKeyDown(e) { // S key - start server if (e.scancode == 22 && gameState == 'waiting') { // S key startServer(); } // J key - join server else if (e.scancode == 13 && gameState == 'waiting') { // J key joinServer(); } } /*──── drawing helpers ───────────────────────────────────────────────*/ /* ── constants ─────────────────────────────────────────────────── */ var S = 60; // square size in px var light = [0.93,0.93,0.93,1]; var dark = [0.25,0.25,0.25,1]; var allowedColor = [1.0, 0.84, 0.0, 1.0]; // Gold for allowed moves var myMouseColor = [0.0, 1.0, 0.0, 1.0]; // Green for my mouse var opponentMouseColor = [1.0, 0.0, 0.0, 1.0]; // Red for opponent mouse /* ── draw one 8×8 chess board ──────────────────────────────────── */ function drawBoard() { for (var y = 0; y < 8; ++y) for (var x = 0; x < 8; ++x) { var isMyHover = hoverPos && hoverPos[0] == x && hoverPos[1] == y; var isOpponentHover = opponentMousePos && opponentMousePos[0] == x && opponentMousePos[1] == y; var isValidMove = selectPos && holdingPiece && isValidMoveForTurn(selectPos, [x, y]); var color = ((x+y)&1) ? dark : light; if (isValidMove) { color = allowedColor; // Gold for allowed moves } else if (isMyHover && !isOpponentHover) { color = myMouseColor; // Green for my mouse } else if (isOpponentHover) { color = opponentMouseColor; // Red for opponent mouse } draw2d.rectangle( { x: x*S, y: y*S, width: S, height: S }, { thickness: 0 }, { color: color } ); } } function isValidMoveForTurn(from, to) { if (!grid.inBounds(to)) return false; var piece = grid.at(from)[0]; if (!piece) return false; // Check if the destination has a piece of the same color var destCell = grid.at(to); if (destCell.length && destCell[0].colour == piece.colour) { return false; } return rules.canMove(piece, from, to, grid); } /* ── draw every live piece ─────────────────────────────────────── */ function drawPieces() { grid.each(function (piece) { if (piece.captured) return; // Skip drawing the piece being held (by me or opponent) if (holdingPiece && selectPos && piece.coord[0] == selectPos[0] && piece.coord[1] == selectPos[1]) { return; } // Skip drawing the piece being held by opponent if (opponentHoldingPiece && opponentSelectPos && piece.coord[0] == opponentSelectPos[0] && piece.coord[1] == opponentSelectPos[1]) { return; } var r = { x: piece.coord[0]*S, y: piece.coord[1]*S, width:S, height:S }; draw2d.image(piece.sprite, r); }); // Draw the held piece at the mouse position if we're holding one if (holdingPiece && selectPos && hoverPos) { var piece = grid.at(selectPos)[0]; if (piece) { var r = { x: hoverPos[0]*S, y: hoverPos[1]*S, width:S, height:S }; draw2d.image(piece.sprite, r); } } // Draw opponent's held piece if they're dragging one if (opponentHoldingPiece && opponentSelectPos && opponentMousePos) { var opponentPiece = grid.at(opponentSelectPos)[0]; if (opponentPiece) { var r = { x: opponentMousePos[0]*S, y: opponentMousePos[1]*S, width:S, height:S }; // Draw with slight transparency to show it's the opponent's piece draw2d.image(opponentPiece.sprite, r); } } } function update(dt) { return {} } function draw() { draw2d.clear() drawBoard() drawPieces() return draw2d.get_commands() } function startServer() { gameState = 'server_waiting'; isServer = true; myColor = 'white'; isMyTurn = true; updateTitle(); $_.portal(e => { log.console("Portal received contact message"); // Reply with this actor to establish connection log.console (json.encode($_)) send(e, $_); log.console("Portal replied with server actor"); }, 5678); } function joinServer() { gameState = 'searching'; updateTitle(); function contact_fn(actor, reason) { log.console("CONTACTED!", actor ? "SUCCESS" : "FAILED", reason); if (actor) { opponent = actor; log.console("Connection established with server, sending join request"); // Send a greet message with our actor object send(opponent, { type: 'greet', client_actor: $_ }); } else { log.console(`Failed to connect: ${json.encode(reason)}`); gameState = 'waiting'; updateTitle(); } } $_.contact(contact_fn, { address: "192.168.0.149", port: 5678 }); } $_.receiver(e => { if (e.kind == 'update') send(e, update(e.dt)) else if (e.kind == 'draw') send(e, draw()) else if (e.type == 'game_start' || e.type == 'move' || e.type == 'greet') log.console("Receiver got message:", e.type, e); if (e.type == 'greet') { log.console("Server received greet from client"); // Store the client's actor object for ongoing communication opponent = e.client_actor; log.console("Stored client actor:", json.encode(opponent)); gameState = 'connected'; updateTitle(); // Send game_start to the client log.console("Sending game_start to client"); send(opponent, { type: 'game_start', your_color: 'black' }); log.console("game_start message sent to client"); } else if (e.type == 'game_start') { log.console("Game starting, I am:", e.your_color); myColor = e.your_color; isMyTurn = (myColor == 'white'); gameState = 'connected'; updateTitle(); } else if (e.type == 'move') { log.console("Received move from opponent:", e.from, "to", e.to); // Apply opponent's move var fromCell = grid.at(e.from); if (fromCell.length) { var piece = fromCell[0]; if (mover.tryMove(piece, e.to)) { isMyTurn = true; // It's now our turn updateTitle(); log.console("Applied opponent move, now my turn"); } else { log.console("Failed to apply opponent move"); } } else { log.console("No piece found at from position"); } } else if (e.type == 'mouse_move') { // Update opponent's mouse position opponentMousePos = e.pos; opponentHoldingPiece = e.holding; opponentSelectPos = e.selectPos; } else if (e.type == 'piece_pickup') { // Opponent picked up a piece opponentSelectPos = e.pos; opponentHoldingPiece = true; } else if (e.type == 'piece_drop') { // Opponent dropped their piece opponentHoldingPiece = false; opponentSelectPos = null; } else if (e.type == 'mouse_button_down') { handleMouseButtonDown(e) } else if (e.type == 'mouse_button_up') { handleMouseButtonUp(e) } else if (e.type == 'mouse_motion') { handleMouseMotion(e) } else if (e.type == 'key_down') { handleKeyDown(e) } })