import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; const Pieces = { WhitePawn: 0, WhiteRook: 1, WhiteKnight: 2, WhiteBishop: 3, WhiteQueen: 4, WhiteKing: 5, BlackPawn: 6, BlackRook: 7, BlackKnight: 8, BlackBishop: 9, BlackQueen: 10, BlackKing: 11 }; const Images = [ './white_pawn.svg', './white_rook.svg', './white_knight.svg', './white_bishop.svg', './white_queen.svg', './white_king.svg', './black_pawn.svg', './black_rook.svg', './black_knight.svg', './black_bishop.svg', './black_queen.svg', './black_king.svg', ]; function isBlack(piece) { return piece >= Pieces.BlackPawn; } function isWhite(piece) { return !isBlack(piece); } function isPawn(piece) { return piece === Pieces.WhitePawn || piece === Pieces.BlackPawn; } function isRook(piece) { return piece === Pieces.WhiteRook || piece === Pieces.BlackRook; } function isBishop(piece) { return piece === Pieces.WhiteBishop || piece === Pieces.BlackBishop; } function isQueen(piece) { return piece === Pieces.WhiteQueen || piece === Pieces.BlackQueen; } function isKnight(piece) { return piece === Pieces.WhiteKnight || piece === Pieces.BlackKnight; } function isKing(piece) { return piece === Pieces.WhiteKing || piece === Pieces.BlackKing; } function Square(props) { return ( ); } class Board extends React.Component { constructor(props) { super(props); this.state = { squares: this.reset(), blackIsNext: true, hand: { heldPiece: null, }, }; } setHand(hand) { this.setState({ squares: this.state.squares, blackIsNext: this.state.blackIsNext, hand: hand, }); } reset() { let whiteRow = [ Pieces.WhiteRook, Pieces.WhiteKnight, Pieces.WhiteBishop, Pieces.WhiteQueen, Pieces.WhiteKing, Pieces.WhiteBishop, Pieces.WhiteKnight, Pieces.WhiteRook ]; let blackRow = [ Pieces.BlackRook, Pieces.BlackKnight, Pieces.BlackBishop, Pieces.BlackQueen, Pieces.BlackKing, Pieces.BlackBishop, Pieces.BlackKnight, Pieces.BlackRook ]; let squares = whiteRow.slice(); squares = squares.concat(Array(8).fill(Pieces.WhitePawn)); squares = squares.concat(Array(32).fill(null)); squares = squares.concat(Array(8).fill(Pieces.BlackPawn)); squares = squares.concat(blackRow.slice()); return squares; } getXandY(i) { let x = i % 8; let y = Math.floor(i / 8); return [x, y]; } pieceAt(x, y) { let i = x + (y * 8); if (i < 64 && x < 8 && y < 8) { return this.state.squares[x + (y * 8)]; } else { return null; } } whiteAt(x, y) { let square = this.pieceAt(x, y); if (square == null) { return false; } return isWhite(square); } blackAt(x, y) { let square = this.pieceAt(x, y); if (square == null) { return false; } return isBlack(square); } isEnemyOf(piece, x, y) { let pieceIsBlack = isBlack(piece); return pieceIsBlack ? this.whiteAt(x, y) : this.blackAt(x, y); } getValidMovesAt(piece, x, y) { var i; var moves = []; let tryAddMove = (x, y) => { if (this.pieceAt(x, y) == null) { moves.push([x, y]); // Keep searching return 0; } else if (this.isEnemyOf(piece, x, y)) { moves.push([x, y]); } // Stop searching return 1; }; if (isPawn(piece)) { let pieceIsBlack = isBlack(piece); let shift = pieceIsBlack ? -1 : 1; let startLine = pieceIsBlack ? 6 : 1; if (this.pieceAt(x, y + shift) == null) { moves.push([x, y + shift]); if (y === startLine && this.pieceAt(x, y + (shift * 2)) == null) { moves.push([x, y + (shift * 2)]); } } [x + 1, x - 1].forEach((x) => { if (this.isEnemyOf(piece, x, y + shift)) { moves.push([x, y + shift]); } }); } else if (isRook(piece)) { // Down for (i = y + 1; i < 8; i++) { if (tryAddMove(x, i) !== 0) { break; } } // Up for (i = y - 1; i >= 0; i--) { if (tryAddMove(x, i) !== 0) { break; } } // Right for (i = x + 1; i < 8; i++) { if (tryAddMove(i, y) !== 0) { break; } } // Left for (i = x - 1; i >= 0; i--) { if (tryAddMove(i, y) !== 0) { break; } } } else if (isBishop(piece)) { // Down-Right for (i = 1; i < 8; i++) { if (tryAddMove(x + i, y + i) !== 0) { break; } } // Up-Right for (i = 1; i < 8; i++) { if (tryAddMove(x + i, y - i) !== 0) { break; } } // Down-Left for (i = 1; i < 8; i++) { if (tryAddMove(x - i, y + i) !== 0) { break; } } // Up-Left for (i = 1; i < 8; i++) { if (tryAddMove(x - i, y - i) !== 0) { break; } } } else if (isQueen(piece)) { let [rook, bishop] = isBlack(piece) ? [Pieces.BlackRook, Pieces.BlackBishop] : [Pieces.WhiteRook, Pieces.WhiteBishop]; moves = moves.concat(this.getValidMovesAt(rook, x, y)); moves = moves.concat(this.getValidMovesAt(bishop, x, y)); } else if (isKnight(piece)) { tryAddMove(x + 2, y + 1); tryAddMove(x + 2, y - 1); tryAddMove(x - 2, y + 1); tryAddMove(x - 2, y - 1); tryAddMove(x + 1, y + 2); tryAddMove(x + 1, y - 2); tryAddMove(x - 1, y + 2); tryAddMove(x - 1, y - 2); } else if (isKing(piece)) { tryAddMove(x + 1, y + 1); tryAddMove(x + 1, y - 1); tryAddMove(x - 1, y + 1); tryAddMove(x - 1, y - 1); tryAddMove(x, y + 1); tryAddMove(x, y - 1); tryAddMove(x + 1, y); tryAddMove(x - 1, y); } return moves; } inCheck(piece) { var kingPos; for(var i = 0; i < this.squareCount(); i++) { if(this.state.squares[i] === piece) { kingPos = this.getXandY(i); } } for(i = 0; i < this.squareCount(); i++) { let [x, y] = this.getXandY(i); if(this.isEnemyOf(piece, x, y)) { let moves = this.getValidMoves(i); for(var j = 0; j < moves.length; j++) { if(moves[j][0] === kingPos[0] && moves[j][1] === kingPos[1]) { return piece; } } } } return null; } whoInCheck() { let blackKing = this.inCheck(Pieces.BlackKing); return blackKing ? blackKing : this.inCheck(Pieces.WhiteKing); } squareCount() { return this.state.squares.length; } squareAt(i) { return i >= 0 && i < 64 ? this.state.squares[i] : null; } checkmate() { let checkedKing = this.whoInCheck(); if (checkedKing != null) { // For piece in board // If piece is on the checked team, // Copy the board // Make one of the piece's moves on the board // Return false if the king is no longer in check // For each square console.log("Square count: " + this.squareCount()); for(var i = 0; i < this.squareCount(); i++) { let piece = this.squareAt(i); // If that piece is on the checked team if (piece != null && isBlack(piece) === isBlack(checkedKing)) { console.log("Trying moves for " + Images[piece]) // Copy the board var board = new Board(); board.state.squares = this.state.squares.slice(); // For each move of the above piece let moves = board.getValidMoves(i) for(var j = 0; j < moves.length; j++) { let [from, to] = moves[j]; board.makeMove(from, to); if (board.inCheck(checkedKing) !== checkedKing) { return false; } } } } return true; } return false; } getValidMoves(source) { let [x, y] = this.getXandY(source); let piece = this.state.squares[source]; return this.getValidMovesAt(piece, x, y); } isValidMove(source, dest) { let [destX, destY] = this.getXandY(dest); let validMoves = this.getValidMoves(source); if (validMoves == null) { return false; } for (var move of this.getValidMoves(source)) { let [x, y] = move; if (destX === x && destY === y) { return true; } } return false; } isHoldingPiece() { return this.heldPiece() != null; } heldPiece() { return this.state.hand.heldPiece; } makeMove(from, to) { const squares = this.state.squares.slice(); if (this.isValidMove(from, to)) { squares[to] = squares[from]; squares[from] = null; this.setHand({ heldPiece: null, }); this.setState({ squares: squares, blackIsNext: !this.state.blackIsNext, }); return 0; } return 1; } handleClick(i) { if (this.isHoldingPiece()) { if (this.makeMove(this.heldPiece(), i) !== 0) { this.setHand({ heldPiece: null, }); } return; } if (this.state.squares[i] != null) { let isSquareBlack = isBlack(this.state.squares[i]); if(isSquareBlack === this.state.blackIsNext) { this.setHand({ heldPiece: i, }); } } } renderSquare(i) { let plainBg = (i + (Math.floor(i / 8))) % 2 === 0 ? "white" : "#666"; let bgColor = this.heldPiece() === i ? "#5D98E6" : plainBg; return ( this.handleClick(i)} bgColor={bgColor} /> ); } row(row) { let i = row * 8; return (
{this.renderSquare(i)} {this.renderSquare(i + 1)} {this.renderSquare(i + 2)} {this.renderSquare(i + 3)} {this.renderSquare(i + 4)} {this.renderSquare(i + 5)} {this.renderSquare(i + 6)} {this.renderSquare(i + 7)}
); } render() { let checkMsg = this.whoInCheck() ? "Check! " : ""; const status = this.checkmate() ? "CHECKMATE" : checkMsg + (this.state.blackIsNext ? 'Black' : 'White') + "'s Turn"; var texttext =

{status}

{this.row(0)} {this.row(1)} {this.row(2)} {this.row(3)} {this.row(4)} {this.row(5)} {this.row(6)} {this.row(7)}
; return ( texttext ); } } class Game extends React.Component { render() { return (
{/* status */}
    {/* TODO */}
); } } // ======================================== ReactDOM.render( , document.getElementById('root') );