/* helper – robust coord access */ function cx(c) { return c.x ?? c[0] } function cy(c) { return c.y ?? c[1] } /* simple move-shape checks */ var deltas = { pawn: function (pc, dx, dy, grid, to) { var dir = (pc.colour == 'white') ? -1 : 1; var base = (pc.colour == 'white') ? 6 : 1; var one = (dy == dir && dx == 0 && grid.at(to).length == 0); var two = (dy == 2 * dir && dx == 0 && cy(pc.coord) == base && grid.at({ x: cx(pc.coord), y: cy(pc.coord)+dir }).length == 0 && grid.at(to).length == 0); var cap = (dy == dir && Math.abs(dx) == 1 && grid.at(to).length); return one || two || cap; }, rook : function (pc, dx, dy) { return (dx == 0 || dy == 0); }, bishop: function (pc, dx, dy) { return Math.abs(dx) == Math.abs(dy); }, queen : function (pc, dx, dy) { return (dx == 0 || dy == 0 || Math.abs(dx) == Math.abs(dy)); }, knight: function (pc, dx, dy) { return (Math.abs(dx) == 1 && Math.abs(dy) == 2) || (Math.abs(dx) == 2 && Math.abs(dy) == 1); }, king : function (pc, dx, dy) { return Math.max(Math.abs(dx), Math.abs(dy)) == 1; } }; function clearLine(from, to, grid) { var dx = Math.sign(cx(to) - cx(from)); var dy = Math.sign(cy(to) - cy(from)); var x = cx(from) + dx, y = cy(from) + dy; while (x != cx(to) || y != cy(to)) { if (grid.at({ x: x, y: y }).length) return false; x += dx; y += dy; } return true; } function canMove(piece, from, to, grid) { var dx = cx(to) - cx(from); var dy = cy(to) - cy(from); var f = deltas[piece.kind]; if (!f || !f(piece, dx, dy, grid, to)) return false; if (piece.kind == 'knight') return true; return clearLine(from, to, grid); } return { canMove };