diff --git a/src-web/components/Board.tsx b/src-web/components/Board.tsx index 7b60ccb..f3d3cab 100644 --- a/src-web/components/Board.tsx +++ b/src-web/components/Board.tsx @@ -1,11 +1,13 @@ import { Accessor, Component, createSignal, For, Show } from "solid-js"; -import { Board as BoardData, Coordinate, Move, PieceType } from "../events"; +import { Board as BoardData, Coordinate, Move, PieceType, Side } from "../events"; import './Board.css'; +import Button, { ButtonContainer } from "./Button"; interface Props { board: Accessor; moves: Accessor; makeMove: (move: Move) => void; + side: Side; } const PIECE_CHARS: Record = { @@ -19,6 +21,7 @@ const PIECE_CHARS: Record = { const Board: Component = (props) => { const [selectedSquare, setSelectedSquare] = createSignal(null); + const [promotionMove, setPromotionMove] = createSignal(null); const validMoves = () => { const selected = selectedSquare(); @@ -29,45 +32,80 @@ const Board: Component = (props) => { } }; - return
- {props.board().map((piece, i) => { - const coord: Coordinate = { - rank: Math.floor(i / 8), - file: i % 8, - }; - const isLight = () => ((i % 8) + Math.floor(i / 8)) % 2 == 0; - const hasMoves = () => props.moves().find((move) => move.from.rank === coord.rank && move.from.file === coord.file) !== undefined; - const targetMove = () => validMoves().find(move => move.to.rank === coord.rank && move.to.file === coord.file); - const isTarget = () => targetMove() !== undefined; + const board = () => { + if (props.side === 'white') { + return props.board().slice().reverse(); + } else { + return props.board(); + } + }; - return
{ - if (hasMoves()) { - if (selectedSquare() === i) { + return <> +
+ {board().map((piece, i_) => { + const i = props.side === 'white' ? 63 - i_ : i_; + const coord: Coordinate = { + rank: Math.floor(i / 8), + file: i % 8, + }; + const isLight = () => ((i % 8) + Math.floor(i / 8)) % 2 == 0; + const hasMoves = () => props.moves().find((move) => move.from.rank === coord.rank && move.from.file === coord.file) !== undefined; + const targetMove = () => validMoves().find(move => move.to.rank === coord.rank && move.to.file === coord.file); + const isTarget = () => targetMove() !== undefined; + + return <> +
{ + if (hasMoves()) { + if (selectedSquare() === i) { + setSelectedSquare(null); + } else { + setSelectedSquare(i); + } + } else { + const target = targetMove(); + console.log(target); + if (target) { + if (target.promotions) { + setPromotionMove(target); + } else { + props.makeMove(target); + setSelectedSquare(null); + setPromotionMove(null); + } + } + } + }}> +
+
+ {PIECE_CHARS[piece!.ty]} +
+ + })} +
+ + + + {(promotion, i) => } + + + + } export default Board; diff --git a/src/chess/mv.rs b/src/chess/mv.rs index 79bc500..7c1e1b4 100644 --- a/src/chess/mv.rs +++ b/src/chess/mv.rs @@ -400,7 +400,13 @@ pub fn generate_legal(board: &Board) -> Vec { return false; } } - let test_board = mv.make(board); + let test_board = if mv.promotions.is_some() { + let mut fake_move = mv.clone(); + fake_move.promotions = None; + fake_move.make(board) + } else { + mv.make(board) + }; !*test_board.calc_check_state().get(board.to_move) }) .collect::>() diff --git a/src/game.rs b/src/game.rs index c60dae6..55576f4 100644 --- a/src/game.rs +++ b/src/game.rs @@ -110,7 +110,23 @@ impl Handler for ChessGame { return; } let legal_moves = generate_legal(&self.board); - if legal_moves.contains(&mv) { + let legal = if let Some(promotions) = &mv.promotions { + if promotions.len() == 1 { + legal_moves.iter().any(|m| { + m.from == mv.from + && m.to == mv.to + && m.set_en_passant == mv.set_en_passant + && m.other == mv.other + && matches!(&m.promotions, Some(p) if p.contains(&promotions[0])) + }) + } else { + tracing::warn!(?incoming_event.side, ?mv, "cannot promote to more than one piece"); + false + } + } else { + legal_moves.contains(&mv) + }; + if legal { self.board = mv.make(&self.board); self.broadcast_new_board(); self.send_possible_moves();