import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; const BLACK = 0; const WHITE = 1; const PAWN = 0; const ROOK = 1; const KNIGHT = 2; const BISHOP = 3; const QUEEN = 4; const KING = 5; 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 != null && piece.color === BLACK; } function isWhite(piece) { return piece != null && piece.color === WHITE; } function isPawn(piece) { return piece != null && piece.type === PAWN; } function isRook(piece) { return piece != null && piece.type === ROOK; } function isBishop(piece) { return piece != null && piece.type === BISHOP; } function isQueen(piece) { return piece != null && piece.type === QUEEN; } function isKnight(piece) { return piece != null && piece.type === KNIGHT; } function isKing(piece) { return piece != null && piece.type === KING; } function imageFromPiece(piece) { if (piece) { const image = piece.color === WHITE ? piece.type : piece.type + 6; return Images[image]; } return null; } function Square(props) { return ( ); } class Piece { constructor(color, type) { this.color = color; this.type = type; } } 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() { console.log("RESET"); let whiteRow = [ new Piece(WHITE, ROOK), new Piece(WHITE, KNIGHT), new Piece(WHITE, BISHOP), new Piece(WHITE, QUEEN), new Piece(WHITE, KING), new Piece(WHITE, BISHOP), new Piece(WHITE, KNIGHT), new Piece(WHITE, ROOK), ]; let blackRow = [ new Piece(BLACK, ROOK), new Piece(BLACK, KNIGHT), new Piece(BLACK, BISHOP), new Piece(BLACK, QUEEN), new Piece(BLACK, KING), new Piece(BLACK, BISHOP), new Piece(BLACK, KNIGHT), new Piece(BLACK, ROOK) ]; let squares = whiteRow.concat( Array(8).fill(new Piece(WHITE, PAWN)), Array(32).fill(null), Array(8).fill(new Piece(BLACK, PAWN)), blackRow); 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) ? [new Piece(BLACK, ROOK), new Piece(BLACK, BISHOP)] : [new Piece(WHITE, ROOK), new Piece(WHITE, BISHOP)]; moves = moves.concat(this.getValidMovesAt(rook, x, y)); moves = moves.concat(this.getValidMovesAt(bishop, x, y)); } else if (isKnight(piece)) { let deltas = [ [2, 1], [2, -1], [-2, 1], [-2, -1], [1, 2], [1, -2], [-1, 2], [-1, -2], ]; deltas.forEach(delta => tryAddMove(x + delta[0], y + delta[1])); } else if (isKing(piece)) { let deltas = [ [1, 1], [1, -1], [-1, 1], [-1, -1], [0, 1], [0, -1], [1, 0], [-1, 0] ]; deltas.forEach(delta => tryAddMove(x + delta[0], y + delta[1])); } return moves; } findIndex(piece) { console.log("founding"); for(var i = 0; i < this.squareCount(); i++) { let check = this.state.squares[i]; if(check && check.type === piece.type && check.color === piece.color) { console.log("found"); return i; } } return null; } distanceBetween(i1, i2) { let [pos1X, pos1Y] = this.getXandY(i1); let [pos2X, pos2Y] = this.getXandY(i2); var a = pos1X - pos2X; a = a * a; var b = pos1Y - pos2Y; b = b * b; return Math.sqrt(a + b); } inCheck(piece) { var i; var kingPos = this.getXandY(this.findIndex(piece)); 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(new Piece(BLACK, KING)); return blackKing ? blackKing : this.inCheck(new Piece(WHITE, KING)); } 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.state.squares[to] = board.state.squares[from]; board.state.squares[from] = null; 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.setState({ squares: squares, blackIsNext: !this.state.blackIsNext, hand: { heldPiece: null, } }); return 0; } return 1; } handleClick(i) { if (this.checkmate()) { return; } 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! " : ""; let isCheckmate = this.checkmate(); var namedPlayer = isCheckmate ? !this.state.blackIsNext : this.state.blackIsNext let color = namedPlayer ? 'Black' : 'White'; const status = this.checkmate() ? "Checkmate! " + color + " Wins!" : checkMsg + color + "'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') );