public void HandleInput(ChessGameController gameController) { if (piecePromotionIsActive) { HandlePromotion(gameController); return; } ChessPlayer player = gameController.ActivePlayer; Board board = gameController.Board; if (board.TurnIsActive || (gameController.State != GameState.Normal && gameController.State != GameState.Check)) { return; } ChessPlayer playerCopy = new ChessPlayer(null, player.TeamColor); ChessPlayer enemyCopy = new ChessPlayer(null, gameController.GetOppositeToActivePlayer().TeamColor); ChessGridInfo gridCopy = playerCopy.TeamColor == TeamColor.White ? ChessGridInfo.CopyGrid(board.ChessGrid, playerCopy, enemyCopy) : ChessGridInfo.CopyGrid(board.ChessGrid, enemyCopy, playerCopy); Move foundMove = FindBestMove(gridCopy, playerCopy, enemyCopy); Move bestMove = new Move(board.ChessGrid.GetPieceOnSquareIndex(foundMove.MovingPiece), foundMove.TargetSquare, board.ChessGrid.GetPieceOnSquareIndex(foundMove.TargetPiece), foundMove.PromotionFlag, foundMove.CastlingFlag, board.ChessGrid.GetPieceOnSquareIndex(foundMove.CastlingPiece), foundMove.CastlingTargetSquare); board.OnSelectPiece(bestMove.MovingPiece); board.OnSelectedPieceMove(bestMove); gameController.OnEnteredNormalMode(); board.OnDeselectActivePiece(); }
private Move FindBestMove(ChessGridInfo grid, ChessPlayer player, ChessPlayer enemy) { bool isMaximazing = player.TeamColor == TeamColor.White ? true : false; int bestScore = player.TeamColor == TeamColor.White ? int.MinValue : int.MaxValue; player.GenerateAllPossibleMoves(grid, true, true); enemy.GenerateAllPossibleMoves(grid, false, false); List <Move> possibleMoves = OrderMoves(player.AllPossibleMoves, enemy.AllPossibleMoves); Move bestMove = possibleMoves[0]; for (int i = 0; i < possibleMoves.Count; i++) { grid.MakeMove(possibleMoves[i], player, enemy, true); int score = MiniMax(grid, enemy, player, !isMaximazing, MAX_DEPTH, int.MinValue, int.MaxValue); if ((isMaximazing && score > bestScore) || (!isMaximazing && score < bestScore)) { bestScore = score; bestMove = possibleMoves[i]; } grid.UndoMove(player, enemy); } return(bestMove); }
private int MiniMax(ChessGridInfo grid, ChessPlayer player, ChessPlayer enemy, bool isMaximazing, int depth, int alpha, int beta) { player.GenerateAllPossibleMoves(grid, true, true); enemy.GenerateAllPossibleMoves(grid, false, false); if (depth == 0 || !player.HasAnyMoves()) { return(EvaluateGrid(grid, player, enemy)); } List <Move> possibleMoves = OrderMoves(player.AllPossibleMoves, enemy.AllPossibleMoves); if (isMaximazing) { int bestScore = int.MinValue; for (int i = 0; i < possibleMoves.Count; i++) { grid.MakeMove(possibleMoves[i], player, enemy, true); int score = MiniMax(grid, enemy, player, !isMaximazing, depth - 1, alpha, beta); bestScore = Mathf.Max(score, bestScore); alpha = Mathf.Max(alpha, bestScore); grid.UndoMove(player, enemy); if (alpha <= beta) { break; } } return(bestScore); } else { int bestScore = int.MaxValue; for (int i = 0; i < possibleMoves.Count; i++) { grid.MakeMove(possibleMoves[i], player, enemy, true); int score = MiniMax(grid, enemy, player, !isMaximazing, depth - 1, alpha, beta); bestScore = Mathf.Min(score, bestScore); beta = Mathf.Min(beta, bestScore); grid.UndoMove(player, enemy); if (alpha <= beta) { break; } } return(bestScore); } }
public override void GeneratePossibleMoves(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity, bool checkSpecialMoves) { base.GeneratePossibleMoves(grid, gridCopy, playerCopy, enemyCopy, checkMovesValidity, checkSpecialMoves); if (checkSpecialMoves) { Castling(grid, gridCopy, enemyCopy); } }
public static void CreatePiecePrefabAndInitialize(Vector2Int squareIndex, PieceType pieceType, TeamColor teamColor, ChessGridInfo grid, ChessPlayer player) { Piece newPiece = CreateChessPiece(squareIndex, pieceType, grid, player); PieceEntity entity = PieceFactory.CreatePiecePrefab(pieceType.ToString()).GetComponent <PieceEntity>(); IMovable pieceMovementType = PieceFactory.GetMovementType(pieceType.ToString()) == MovementType.MovesInLine ? new MoveInLine() as IMovable : new Jump(); newPiece.SetData(squareIndex, squareIndex, pieceType, teamColor, false, pieceMovementType, entity); player.AddPiece(newPiece); }
public bool CheckIfMoveIsValid(ChessGridInfo grid, ChessPlayer player, ChessPlayer enemy, Move pieceMove) { grid.MakeMove(pieceMove, player, enemy, true); enemy.GenerateAllPossibleMoves(grid, false, false); Piece king = player.FindFirstPieceOfType(PieceType.King); bool isMoveValid = !(enemy.IsFieldUnderAttack(king.SquareIndex)); grid.UndoMove(player, enemy); return(isMoveValid); }
public override void GeneratePossibleMoves(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity, bool checkSpecialMoves) { AvailableMoves.Clear(); Vector2Int newSquare = Vector2Int.zero; for (int i = 0; i < possibleDirections.GetLength(0); i++) { if (i == 1 && MovedFirstTime) { break; } int newX = SquareIndex.x + possibleDirections[i, 0]; int newY = SquareIndex.y + possibleDirections[i, 1]; newSquare.Set(newX, newY); if (grid.CheckIfSquareIndexIsValid(newSquare)) { Piece piece = grid.GetPieceOnSquareIndex(newSquare); Move move = CheckPromotionFlag(newSquare, piece); if (checkMovesValidity && piece == null) { Piece attackedPieceCopy = piece == null ? null : gridCopy.GetPieceOnSquareIndex(piece.SquareIndex); Move moveCopy = new Move(gridCopy.GetPieceOnSquareIndex(SquareIndex), newSquare, attackedPieceCopy, move.PromotionFlag); bool areMovesValid = CheckIfMoveIsValid(gridCopy, playerCopy, enemyCopy, moveCopy); if (!areMovesValid) { continue; } } if (piece == null) { AvailableMoves.Add(move); } else { break; } } } PieceAttack(grid, gridCopy, playerCopy, enemyCopy, checkMovesValidity); EnPassant(grid, gridCopy, playerCopy, enemyCopy, checkMovesValidity); }
public override void GeneratePossibleMoves(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity, bool checkSpecialMoves) { AvailableMoves.Clear(); Vector2Int newSquare = Vector2Int.zero; for (int i = 0; i < possibleDirections.GetLength(0); i++) { int newX = SquareIndex.x + possibleDirections[i, 0]; int newY = SquareIndex.y + possibleDirections[i, 1]; newSquare.Set(newX, newY); if (grid.CheckIfSquareIndexIsValid(newSquare)) { Piece piece = grid.GetPieceOnSquareIndex(newSquare); Move move = new Move(this, newSquare, piece); if (checkMovesValidity && piece != null && piece.PieceType == PieceType.King) { continue; } if (checkMovesValidity && (piece == null || (piece != null && piece.TeamColor != TeamColor))) { Piece attackedPieceCopy = piece == null ? null : gridCopy.GetPieceOnSquareIndex(piece.SquareIndex); Move moveCopy = new Move(gridCopy.GetPieceOnSquareIndex(SquareIndex), newSquare, attackedPieceCopy); bool areMovesValid = CheckIfMoveIsValid(gridCopy, playerCopy, enemyCopy, moveCopy); if (!areMovesValid) { continue; } } if (piece == null) { AvailableMoves.Add(move); } else if (piece != null && TeamColor != piece.TeamColor) { AvailableMoves.Add(move); } } } }
private void PieceAttack(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity) { Vector2Int newSquare = Vector2Int.zero; for (int i = 0; i < possibleAttacks.GetLength(0); i++) { int newX = SquareIndex.x + possibleAttacks[i, 0]; int newY = SquareIndex.y + possibleAttacks[i, 1]; newSquare.Set(newX, newY); if (grid.CheckIfSquareIndexIsValid(newSquare)) { Piece piece = grid.GetPieceOnSquareIndex(newSquare); Move move = CheckPromotionFlag(newSquare, piece); if (checkMovesValidity && piece != null && piece.PieceType == PieceType.King) { continue; } if (checkMovesValidity && (piece != null && piece.TeamColor != TeamColor)) { Piece attackedPieceCopy = piece == null ? null : gridCopy.GetPieceOnSquareIndex(piece.SquareIndex); Move moveCopy = new Move(gridCopy.GetPieceOnSquareIndex(SquareIndex), newSquare, attackedPieceCopy, move.PromotionFlag); bool areMovesValid = CheckIfMoveIsValid(gridCopy, playerCopy, enemyCopy, moveCopy); if (!areMovesValid) { continue; } } if (piece != null && TeamColor != piece.TeamColor) { AvailableMoves.Add(move); } } } }
private void EnPassant(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity) { int[,] directions = { { -1, 0 }, { 1, 0 } }; Vector2Int newSquare = Vector2Int.zero; for (int i = 0; i < directions.GetLength(0); i++) { int newX = SquareIndex.x + directions[i, 0]; int newY = SquareIndex.y + directions[i, 1]; newSquare.Set(newX, newY); if (grid.CheckIfSquareIndexIsValid(newSquare)) { Piece piece = grid.GetPieceOnSquareIndex(newSquare); Vector2Int square = new Vector2Int(SquareIndex.x + enPassantMoves[i, 0], SquareIndex.y + enPassantMoves[i, 1]); Move move = CheckPromotionFlag(square, piece); if (checkMovesValidity && piece != null && piece.PieceType == PieceType.Pawn && piece == grid.PieceMovedInPreviousTurn && Mathf.Abs(piece.SquareIndex.y - piece.PreviousSquareIndex.y) == 2 && piece.SquareIndex.x == piece.PreviousSquareIndex.x) { Piece attackedPieceCopy = piece == null ? null : gridCopy.GetPieceOnSquareIndex(piece.SquareIndex); Move moveCopy = new Move(gridCopy.GetPieceOnSquareIndex(SquareIndex), square, attackedPieceCopy, move.PromotionFlag); bool areMovesValid = CheckIfMoveIsValid(gridCopy, playerCopy, enemyCopy, moveCopy); if (!areMovesValid) { continue; } } if (piece != null && piece.PieceType == PieceType.Pawn && piece == grid.PieceMovedInPreviousTurn && Mathf.Abs(piece.SquareIndex.y - piece.PreviousSquareIndex.y) == 2 && piece.SquareIndex.x == piece.PreviousSquareIndex.x) { AvailableMoves.Add(move); break; } } } }
private int EvaluateGrid(ChessGridInfo grid, ChessPlayer player, ChessPlayer enemy) { int score = 0; bool isKingInCheck = player.IsKingInCheck(enemy); if (!isKingInCheck && player.AllPossibleMoves.Count == 0) { return(0); } if (player.TeamColor == TeamColor.White && player.AllPossibleMoves.Count == 0 && isKingInCheck) { return(BLACK_VICTORY); } if (player.TeamColor == TeamColor.Black && player.AllPossibleMoves.Count == 0 && isKingInCheck) { return(WHITE_VICTORY); } Vector2Int square = Vector2Int.zero; for (int i = 0; i < ChessGridInfo.GRID_SIZE; i++) { for (int j = 0; j < ChessGridInfo.GRID_SIZE; j++) { square.Set(j, i); Piece piece = grid.GetPieceOnSquareIndex(square); if (piece != null) { if (piece.TeamColor == TeamColor.White) { score += PiecePositionEvaluation.PieceValue[piece.PieceType]; } else { score -= PiecePositionEvaluation.PieceValue[piece.PieceType]; } score += PiecePositionEvaluation.PositionEvaluation[(piece.PieceType, piece.TeamColor)][i, j];
public void GenerateAllPossibleMoves(ChessGridInfo grid, bool checkMovesValidity, bool checkSpecialMoves) { ChessGridInfo gridCopy = null; ChessPlayer enemyCopy = null; ChessPlayer playerCopy = null; if (checkMovesValidity) { TeamColor opponentColor = TeamColor == TeamColor.White ? TeamColor.Black : TeamColor.White; playerCopy = new ChessPlayer(null, TeamColor); enemyCopy = new ChessPlayer(null, opponentColor); gridCopy = opponentColor == TeamColor.White ? ChessGridInfo.CopyGrid(grid, enemyCopy, playerCopy) : ChessGridInfo.CopyGrid(grid, playerCopy, enemyCopy); } AllPossibleMoves.Clear(); for (int i = 0; i < ActivePieces.Count; i++) { ActivePieces[i].GeneratePossibleMoves(grid, gridCopy, playerCopy, enemyCopy, checkMovesValidity, checkSpecialMoves); AllPossibleMoves.AddRange(ActivePieces[i].AvailableMoves); } }
public static ChessGridInfo CopyGrid(ChessGridInfo grid, ChessPlayer whitePlayer, ChessPlayer blackPlayer) { ChessGridInfo newGrid = new ChessGridInfo(); Vector2Int square = Vector2Int.zero; for (int i = 0; i < GRID_SIZE; i++) { for (int j = 0; j < GRID_SIZE; j++) { square.Set(j, i); Piece pieceOnGrid = grid.GetPieceOnSquareIndex(square); if (pieceOnGrid != null) { Piece copy = ChessGameController.PieceFactory.CreatePiece(pieceOnGrid.GetType().ToString()); copy.SetData(pieceOnGrid.SquareIndex, pieceOnGrid.PreviousSquareIndex, pieceOnGrid.PieceType, pieceOnGrid.TeamColor, pieceOnGrid.MovedFirstTime, pieceOnGrid.Movement, null); newGrid.SetChessPieceOnGrid(copy, square); if (copy.TeamColor == TeamColor.White) { whitePlayer?.AddPiece(copy); } if (copy.TeamColor == TeamColor.Black) { blackPlayer?.AddPiece(copy); } } } } newGrid.SelectedPiece = grid.SelectedPiece; newGrid.PieceMovedInPreviousTurn = grid.PieceMovedInPreviousTurn; return(newGrid); }
public static Piece CreateChessPiece(Vector2Int squareIndex, PieceType pieceType, ChessGridInfo grid, ChessPlayer player) { Piece piece = PieceFactory.CreatePiece(pieceType.ToString()); grid.SetChessPieceOnGrid(piece, squareIndex); return(piece); }
public abstract void GeneratePossibleMoves(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer playerCopy, ChessPlayer enemyCopy, bool checkMovesValidity, bool checkSpecialMoves);
private void Awake() { TurnIsActive = false; SquareSelector = GetComponent <ChessSquareSelector>(); ChessGrid = new ChessGridInfo(); }
private void Castling(ChessGridInfo grid, ChessGridInfo gridCopy, ChessPlayer enemyCopy) { if (MovedFirstTime) { return; } enemyCopy.GenerateAllPossibleMoves(gridCopy, false, false); if (enemyCopy.IsFieldUnderAttack(SquareIndex)) { return; } int kingRow = SquareIndex.y; Piece leftRook = grid.GetPieceOnSquareIndex(new Vector2Int(0, kingRow)); Piece rightRook = grid.GetPieceOnSquareIndex(new Vector2Int(ChessGridInfo.GRID_SIZE - 1, kingRow)); if (leftRook != null && leftRook.PieceType == PieceType.Rook && leftRook.TeamColor == TeamColor && !leftRook.MovedFirstTime && leftRook.SquareIndex.y == SquareIndex.y) { bool isLeftCastlingPossible = true; Vector2Int square = Vector2Int.zero; for (int i = leftRook.SquareIndex.x + 1; i < SquareIndex.x; i++) { square.Set(i, kingRow); if (gridCopy.GetPieceOnSquareIndex(square) != null || (i > 1 && enemyCopy.IsFieldUnderAttack(square))) { isLeftCastlingPossible = false; break; } } if (isLeftCastlingPossible) { Move move = new Move(this, new Vector2Int(2, kingRow), null, false, true, leftRook, new Vector2Int(3, kingRow)); AvailableMoves.Add(move); } } if (rightRook != null && rightRook.PieceType == PieceType.Rook && rightRook.TeamColor == TeamColor && !rightRook.MovedFirstTime && rightRook.SquareIndex.y == SquareIndex.y) { bool isRightCastlingPossible = true; Vector2Int square = Vector2Int.zero; for (int i = SquareIndex.x + 1; i < rightRook.SquareIndex.x; i++) { square.Set(i, kingRow); if (gridCopy.GetPieceOnSquareIndex(square) != null || enemyCopy.IsFieldUnderAttack(square)) { isRightCastlingPossible = false; break; } } if (isRightCastlingPossible) { Move move = new Move(this, new Vector2Int(6, kingRow), null, false, true, rightRook, new Vector2Int(5, kingRow)); AvailableMoves.Add(move); } } }