/// <summary> /// Checks if the white knight move is valid /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <returns></returns> public static bool BlackKnight(ChessBoard board, ChessMove move) { //if not killing or empty space throw error if (!KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //if not in a style of knight movement throw error if (Math.Abs(move.To.X - move.From.X) == 2) { if (Math.Abs(move.To.Y - move.From.Y) != 1) return false; } else if (Math.Abs(move.To.X - move.From.X) == 1) { if (Math.Abs(move.To.Y - move.From.Y) != 2) return false; } else { return false; } //all good return true; }
/// <summary> /// Constructor that creates a decision tree off of a chess board. /// </summary> /// <param name="board">The chess board that the decision tree starts from.</param> public DecisionTree(ChessBoard board) { UvsChess.Framework.Profiler.AddToMainProfile((int)ProfilerMethodKey.DecisionTree_ctor_ChessBoard); Children = new List<DecisionTree>(); Board = board; BestChildMove = null; }
/// <summary> /// Takes a board and color, and returns a simplified state where friend pieces are represented /// by positive integers and always start on the same side of the board (0,0). Foe pieces are /// represented as negative values /// </summary> /// <param name="board">The board to convert</param> /// <param name="color">The color of the player (friend)</param> /// <returns>A simplified representation of the current board</returns> public static int[,] GetSimpleState(ChessBoard board, ChessColor color) { int[,] state = new int[Columns, Rows]; for (int col = 0; col < Columns; col++) { for (int row = 0; row < Rows; row++) { int stateRow = row; int stateCol = col; if (color == ChessColor.White) { stateRow = Rows - row - 1; stateCol = Columns - col - 1; } ChessPiece piece = board[col, row]; int multiplier = 1; if (color == ChessColor.White && piece < ChessPiece.Empty || color == ChessColor.Black && piece > ChessPiece.Empty) multiplier = -1; state[stateCol, stateRow] = multiplier * GamePieceToStatePiece[piece]; } } return state; }
public void GenerateMoves(ChessBoard board, ChessColor color) { Moves = new List<ChessMove>(); for (int y = 0; y < ChessBoard.NumberOfRows; y++) { for (int x = 0; x < ChessBoard.NumberOfColumns; x++) { if (color == ChessColor.White) // if player is white { if (board[x, y] > ChessPiece.Empty) { switch (board[x, y]) { case ChessPiece.WhiteBishop: BishopMoves(board, x, y, color); break; case ChessPiece.WhiteQueen: QueenMoves(board, x, y, color); break; case ChessPiece.WhiteKing: break; case ChessPiece.WhiteKnight: KnightMoves(board, x, y, color); break; case ChessPiece.WhitePawn: PawnMoves(board, x, y, color); break; case ChessPiece.WhiteRook: RookMoves(board, x, y, color); break; } } } else if ( color == ChessColor.Black) { switch (board[x, y]) { case ChessPiece.BlackBishop: BishopMoves(board, x, y, color); break; case ChessPiece.BlackQueen: QueenMoves(board, x, y, color); break; case ChessPiece.BlackKing: break; case ChessPiece.BlackKnight: KnightMoves(board, x, y, color); break; case ChessPiece.BlackPawn: PawnMoves(board, x, y, color); break; case ChessPiece.BlackRook: RookMoves(board, x, y, color); break; } } } } }
private DecisionTree(DecisionTree parent, ChessBoard board, ChessMove move) { UvsChess.Framework.Profiler.AddToMainProfile((int)ProfilerMethodKey.DecisionTree_ctor_DecisionTree_ChessBoard_ChessMove); Children = new List<DecisionTree>(); Parent = parent; Board = board; Move = move; BestChildMove = null; }
/// <summary> /// this will define BoardAfterMove, TheMove, and HValue based on move /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <param name="colorofEnemy"></param> public Hueristic(ChessBoard board, ChessMove move, ChessColor colorofEnemy) { BoardBeforeMove = board.Clone(); BoardAfterMove = board.Clone(); BoardAfterMove.MakeMove(move); TheMove = move; //HValue = CalculateHueristicBasic(board, colorofEnemy); HValue = CalculateHueristicAdvanced(colorofEnemy); }
/// <summary> /// Checks if the move the black king wants to make is valid /// </summary> /// <param name="board">board state before move</param> /// <param name="move">move the piece wants to make</param> /// <returns>true if valid move, false is invalid</returns> public static bool BlackKing(ChessBoard board, ChessMove move) { // ensure new move is onto an enemy piece or empty space if (!KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //validate the move is only one space away for a king if (Math.Abs(move.To.X - move.From.X) > 1 || Math.Abs(move.To.Y - move.From.Y) > 1) return false; //if all checks pass then return true; }
/// <summary> /// Checks if the move the white king wants to make is valid /// </summary> /// <param name="board">board state before move</param> /// <param name="move">move the piece wants to make</param> /// <returns>true if valid move, false is invalid</returns> public static bool WhiteKing(ChessBoard board, ChessMove move) { //TODO NOT DONE, still need to finish this //validate the move is still on the board as well as // ensure new move is onto an enemy piece or empty space if (!OnBoardAndKillOrEmpty(move.To.X, move.To.Y,board,ChessColor.White)) return false; //validate it doesn't put self into check //if all checks pass then return true; }
/// <summary> /// Checks if black bishop move is valid /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <returns></returns> public static bool BlackBishop(ChessBoard board, ChessMove move) { //if he tries to move diagonal throw an error if (Math.Abs(move.From.X - move.To.X) != Math.Abs(move.From.Y - move.To.Y)) { return false; } //if the path is not clear or they are not moving to kill then no good if (!PathClear(move.From.X, move.From.Y, move.To.X, move.To.Y, board) || !KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //all good return true; }
/// <summary> /// High Number = better board for your color /// </summary> /// <param name="board"></param> /// <param name="colorOfEnemyTeam"></param> /// <returns></returns> int CalculateBoardHP(ChessBoard board, ChessColor colorOfMyTeam) { int score = 0; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (colorOfMyTeam == ChessColor.Black && BoardAfterMove[x, y] < ChessPiece.Empty) //if black score += StudentAI.Piece.CalculatePieceValue(BoardAfterMove[x, y]); else if (colorOfMyTeam == ChessColor.White && BoardAfterMove[x, y] > ChessPiece.Empty) //if white score += StudentAI.Piece.CalculatePieceValue(BoardAfterMove[x, y]); } } return score; }
/// <summary> /// gets a list of available moves for a color /// </summary> public static List<ChessMove> getmovesofcolor(StudentAI ai, ChessColor color, ChessBoard board) { List<ChessMove> colormoves = new List<ChessMove>(); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { if (color == ChessColor.Black) { switch (board[x, y]) { case ChessPiece.BlackPawn: case ChessPiece.BlackKnight: case ChessPiece.BlackBishop: case ChessPiece.BlackQueen: case ChessPiece.BlackRook: case ChessPiece.BlackKing: colormoves.AddRange(getmovesofpiece(ai, color, board, new ChessLocation(x, y))); break; default: break; } } if (color == ChessColor.White) { switch (board[x, y]) { case ChessPiece.WhitePawn: case ChessPiece.WhiteKnight: case ChessPiece.WhiteBishop: case ChessPiece.WhiteQueen: case ChessPiece.WhiteRook: case ChessPiece.WhiteKing: colormoves.AddRange(getmovesofpiece(ai, color, board, new ChessLocation(x, y))); break; default: break; } } } } return colormoves; }
//checks if the move is still located on the board & is moved onto empty or kill spot private static bool OnBoardAndKillOrEmpty(int X, int Y,ChessBoard board,ChessColor color) { if (X > 8 || X < 0 || Y > 8 || Y < 0) return false; if(board[X,Y] == ChessPiece.Empty) { if(color==ChessColor.White) { switch (board[X,Y]) { case ChessPiece.BlackPawn: case ChessPiece.BlackKnight: case ChessPiece.BlackBishop: case ChessPiece.BlackQueen: case ChessPiece.BlackRook: case ChessPiece.BlackKing: return true; default: return false; } } else if(color==ChessColor.Black) { switch (board[X, Y]) { case ChessPiece.WhiteBishop: case ChessPiece.WhiteKing: case ChessPiece.WhiteKnight: case ChessPiece.WhitePawn: case ChessPiece.WhiteQueen: case ChessPiece.WhiteRook: return true; default: return false; } } } return true; }
private void KnightMoves(ChessBoard board, int x, int y, ChessColor color) { ChessColor killColor = ChessColor.White; if (color == ChessColor.White) { killColor = ChessColor.Black; } int x1 = x - 1; int y1 = y - 2; //up left direction if ((x1 >= 0 && y1 >= 0 )) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // up right direction x1 = x + 1; if ((x1 < ChessBoard.NumberOfColumns && y1 >= 0 ) ) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // right up direction y1 = y - 1; x1 = x + 2; if (x1 < ChessBoard.NumberOfColumns && y1 >= 0) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // right down direction y1 = y + 1; if (x1 < ChessBoard.NumberOfRows && y1 < ChessBoard.NumberOfColumns) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // down left direction x1 = x - 1; y1 = y + 2; if (x1 >= 0 && y1 < ChessBoard.NumberOfRows) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } //down right direction x1 = x + 1; if (x1 < ChessBoard.NumberOfRows && y1 < ChessBoard.NumberOfColumns ) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // left up direction x1 = x - 2; y1 = y - 1; if (x1 >= 0 && y1 >= 0 ) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } // left down direction y1 = y + 1; if (x1 >= 0 && y1 < ChessBoard.NumberOfColumns ) { if ((board[x1, y1] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x1, y1] < ChessPiece.Empty && killColor == ChessColor.Black) || board[x1, y1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x1, y1))); } } }
/// <summary> /// Checks if white rook move is valid /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <returns></returns> public static bool WhiteRook(ChessBoard board, ChessMove move) { //if he tries to move diagonal throw an error if(move.To.X!=move.From.X && move.To.Y!=move.From.Y) { return false; } //if the path is not clear or they are not moving to kill then no good if (!PathClear(move.From.X, move.From.Y, move.To.X, move.To.Y, board) || !KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.White)) return false; //all good return true; }
private static bool checkEmpty(int X, int Y, ChessBoard board) { if (board[X, Y] == ChessPiece.Empty) return true; return false; }
private static bool indanger(int x, int y, ChessBoard board, ChessColor color) { if (color == ChessColor.White) { if (board[x - 1, y - 1] == ChessPiece.BlackPawn || board[x + 1, y - 1] == ChessPiece.BlackPawn) return true; } if (color == ChessColor.Black) { } }
/// <summary> /// Uses mini-max algorithm to determine the next move that should be taken /// </summary> /// <param name="board">The board to evaluate</param> /// <param name="playerColor">The color of the player to determine moves for</param> /// <param name="boardEvaluator">The heuristic to use in evaluating the board</param> /// <returns>The best move based on the evaluation</returns> public ChessMove MiniMaxMove(ChessBoard board, ChessColor playerColor, Func<int[,], ChessMove, int> boardEvaluator) { this.boardEvaluator = boardEvaluator; ChessMove selectedMove = null; List<ChessMove> bestMoves = null; int depth = initialDepth; int[,] state = SimpleState.GetSimpleState(board, playerColor); List<ChessMove> allPossibleMoves = moveGenerator.GetAllMoves(state, true, boardEvaluator); while (!timesUp() && allPossibleMoves.Count > 0) { if (bestMoves != null) selectedMove = bestMoves[selectedMoveIndex % bestMoves.Count]; // Reverse Sort the moves so our best moves are at the beginning of the list to improve Alpha Beta Pruning allPossibleMoves.Sort((x, y) => y.ValueOfMove.CompareTo(x.ValueOfMove)); bestMoves = new List<ChessMove>(); bestMoves.Add(allPossibleMoves[0]); int i = 0; int alpha = int.MinValue; int beta = int.MaxValue; for (i = 0; i < allPossibleMoves.Count && !timesUp(); i++) { ChessMove move = allPossibleMoves[i]; move.ValueOfMove = MinValue(moveGenerator.GetStateAfterMove(state, move), move, depth - 1, alpha, beta); // Keep an ordered list of best moves -- this produces better results than simply sorting the final list since // It keeps the relative order the same as the original heuristic pass int pos = 0; while (pos < bestMoves.Count && bestMoves[pos].ValueOfMove >= move.ValueOfMove) pos++; bestMoves.Insert(pos, move); alpha = Math.Max(alpha, move.ValueOfMove); } #if DEBUG log(string.Format("(Depth: {5}) Processed {0} move(s) out of {1}. Move: {2} (index: {3}, value: {4})", i, allPossibleMoves.Count, SimpleState.GetGameMove(bestMoves[0], playerColor).ToString(), selectedMoveIndex, bestMoves[0].ValueOfMove, depth)); #endif depth++; } // In order to avoid moving back and forth endlessly, if we duplicate a recent move, then select the next best move instead of the best if (previousMoves.Contains(selectedMove)) selectedMoveIndex++; else selectedMoveIndex = 0; previousMoves.Enqueue(selectedMove.Clone()); while (previousMoves.Count > 10) previousMoves.Dequeue(); // We shouldn't hit this, but if we haven't made it through one full search path then default to whatever the current best move is from the current incomplete search attempt if (selectedMove == null && bestMoves != null && bestMoves.Count > 0) selectedMove = bestMoves[0]; // If we didn't find any moves, then return stalemate ChessMove gameMove = SimpleState.GetGameMove(selectedMove, playerColor) ?? new ChessMove(null, null) { Flag = ChessFlag.Stalemate }; log(string.Format("Chosen Move: {0} - Value: {1}", gameMove, gameMove.ValueOfMove)); log("Max Depth: " + (depth - 1)); return gameMove; }
/// <summary> /// Adds a child decision to the decision tree. /// </summary> /// <param name="board">The board the decision was made from</param> /// <param name="move">The move decided.</param> public void AddChild(ChessBoard board, ChessMove move) { UvsChess.Framework.Profiler.AddToMainProfile((int)ProfilerMethodKey.DecisionTree_AddChild_ChessBoard_ChessMove); this.Children.Add(new DecisionTree(this, board, move)); }
//check if move is enemy private static bool IsEnemy(int x, int y, ChessBoard board, ChessColor color) { if (color == ChessColor.White) { switch (board[x, y]) { case ChessPiece.BlackPawn: case ChessPiece.BlackKnight: case ChessPiece.BlackBishop: case ChessPiece.BlackQueen: case ChessPiece.BlackRook: case ChessPiece.BlackKing: return true; default: return false; } } if (color == ChessColor.Black) { switch (board[x, y]) { case ChessPiece.WhiteBishop: case ChessPiece.WhiteKing: case ChessPiece.WhiteKnight: case ChessPiece.WhitePawn: case ChessPiece.WhiteQueen: case ChessPiece.WhiteRook: return true; default: return false; } } throw new Exception("No Color defined"); }
public Hueristic getMinimax(StudentAI AI, ChessBoard board, ChessColor color, int depth, ChessColor maxColor, int alpha = -999999, int beta = 999999) { //TODO update to return heuristic instead of move and update get next move to return move of heuristic. if (depth > maxdepth) { return new Hueristic(board,new ChessMove(null, null),color); } List<ChessMove> allmoves = new List<ChessMove>(); allmoves.AddRange(PieceMoves.getmovesofcolor(AI, color, board)); List<Hueristic> HueristicMoves = new List<Hueristic>(); //DecisionTree descisions = new DecisionTree(board); //descisions. ChessColor oppositeColor = color == ChessColor.Black ? ChessColor.White : ChessColor.Black; //set check/checkmate flag and calculate hueristic on each move foreach (var move in allmoves) { var tempBoard = board.Clone(); tempBoard.MakeMove(move); if (StudentAI.IsKingInCheck(tempBoard, oppositeColor)) { move.Flag = ChessFlag.Check; //check for checkmate if (PieceMoves.getmovesofcolor(AI, oppositeColor, tempBoard).Count == 0) { move.Flag = ChessFlag.Checkmate; return new Hueristic(board,move,color); } } HueristicMoves.Add(new Hueristic(board, move, color)); if (color == maxColor && move.Flag == ChessFlag.Check) HueristicMoves[HueristicMoves.Count - 1].HValue += 2; if (color == maxColor && move.Flag == ChessFlag.Checkmate) { HueristicMoves[HueristicMoves.Count - 1].HValue = 10000; return HueristicMoves[HueristicMoves.Count -1]; } } HueristicMoves.Sort((x, y) => y.HValue.CompareTo(x.HValue)); if (AI.IsMyTurnOver() && HueristicMoves.Count > 0) return HueristicMoves[0]; //if (depth == maxdepth && HueristicMoves.Count>0) // return HueristicMoves[0]; List<Hueristic> updatedhueristic = new List<Hueristic>(); //minimax and alpha beta pruning bool defined = false; var temp = new List<Hueristic>(); do { //TODO, store previous move and if we ran out of time use that one since we don't know if optimal on the next one temp = new List<Hueristic>(); foreach (var hmove in HueristicMoves) { var tempBoard = board.Clone(); if (hmove.TheMove != null) { tempBoard.MakeMove(hmove.TheMove); if (depth != maxdepth) { var oppositemove = getMinimax(AI, tempBoard, oppositeColor, depth + 1, maxColor, alpha, beta); //get best move of the other color if (oppositemove.TheMove.To != null && oppositemove.TheMove.From != null) { hmove.HValue -= oppositemove.HValue; // update our moves score based on return of projected other move } } temp.Add(hmove); // add new scored hueristic to new list if (AI.IsMyTurnOver()) break; //a=max(a,hueristic) if (maxColor == color) { alpha = alpha > hmove.HValue ? alpha : hmove.HValue; if (beta <= alpha) break; } else { beta = beta < hmove.HValue ? beta : hmove.HValue; if (beta <= alpha) break; } } } if (!AI.IsMyTurnOver()) { if (depth == 0) { maxdepth += 1; defined = true; updatedhueristic = temp; } } } while (!AI.IsMyTurnOver() && depth == 0); if (!defined) updatedhueristic = temp; updatedhueristic.Sort((x, y) => y.HValue.CompareTo(x.HValue)); // sort the new list if (color == maxColor) { if (updatedhueristic.Count == 0) { var game_over = new ChessMove(null, null); game_over.Flag = ChessFlag.Stalemate; var game_overhueristic = new Hueristic(board, game_over, color); return game_overhueristic; } int tiecount = -1; foreach (var x in updatedhueristic) if (x.HValue == updatedhueristic[0].HValue) tiecount++; if (tiecount > 0) return updatedhueristic[rand.Next(0, tiecount)]; } if (updatedhueristic.Count == 0) return new Hueristic(board,new ChessMove(null, null),color); return updatedhueristic[0]; //return the best value from the new list }
/// <summary> /// Returns true if its just our king, their king, and we have a single rook or queen /// </summary> /// <param name="board">The board to evaluate</param> /// <param name="myColor">The player's color</param> /// <returns>True if we're in an end-game state otherwise false</returns> public bool IsEndgame(ChessBoard board, ChessColor myColor) { int numberOfPieces = 0; for (int column = 0; column < ChessBoard.NumberOfColumns; column++) { for (int row = 0; row < ChessBoard.NumberOfRows; row++) { ChessPiece piece = board[column, row]; if (piece != ChessPiece.Empty && piece != ChessPiece.WhiteQueen && piece != ChessPiece.WhiteRook && piece != ChessPiece.BlackQueen && piece != ChessPiece.BlackRook && piece != ChessPiece.WhiteKing && piece != ChessPiece.BlackKing) return false; if (piece != ChessPiece.Empty) numberOfPieces++; } } if (numberOfPieces == 3) return true; else return false; }
private void RookMoves(ChessBoard board, int x, int y, ChessColor color) { ChessColor killColor = ChessColor.White; if (color == ChessColor.White) { killColor = ChessColor.Black; } for (int i = y + 1; i < ChessBoard.NumberOfRows; i++) // direction down { if (board[x, i] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, i))); } else { if ((board[x, i] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x, i] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, i))); } break; } } for (int i = y - 1; i >= 0; i--) // direction up { if (board[x, i] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, i))); } else { if ((board[x, i] > ChessPiece.Empty && killColor == ChessColor.White) || (board[x, i] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, i))); } break; } } for (int j = x - 1; j > 0; j--) // direction left { if (board[j, y] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(j, y))); } else { if ((board[j, y] > ChessPiece.Empty && killColor == ChessColor.White) || (board[j, y] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(j, y))); } break; } } for (int j = x + 1; j < ChessBoard.NumberOfColumns; j++) // direction right { if (board[j, y] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(j,y))); } else { if ((board[j, y] > ChessPiece.Empty && killColor == ChessColor.White) || (board[j, y] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(j, y))); } break; } } }
private void BishopMoves(ChessBoard board, int x, int y, ChessColor color) { ChessColor killColor = ChessColor.White; if (color == ChessColor.White) { killColor = ChessColor.Black; } int i = x - 1; int j = y - 1; while (i > 0 && j > 0) // up left direction { if (board[i, j] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(i, j))); } else { if ((board[i, j] > ChessPiece.Empty && killColor == ChessColor.White) || (board[i, j] < ChessPiece.Empty && killColor == ChessColor.Black) ) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, j))); } break; } i--; j--; } while (i > 0 && j < ChessBoard.NumberOfColumns) // up right direction { if (board[i, j] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(i, j))); } else { if ((board[i, j] > ChessPiece.Empty && killColor == ChessColor.White) || (board[i, j] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, j))); } break; } i++; j--; } while (i < ChessBoard.NumberOfRows && j > 0) // down left direction { if (board[i, j] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(i, j))); } else { if ((board[i, j] > ChessPiece.Empty && killColor == ChessColor.White) || (board[i, j] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, j))); } break; } i--; j++; } while (i < ChessBoard.NumberOfRows && j < ChessBoard.NumberOfColumns) // down right direction { if (board[i, j] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(i, j))); } else { if ((board[i, j] > ChessPiece.Empty && killColor == ChessColor.White) || (board[i, j] < ChessPiece.Empty && killColor == ChessColor.Black)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, j))); } break; } i++; j++; } }
private void QueenMoves(ChessBoard board, int x, int y, ChessColor color) { RookMoves(board, x, y, color); BishopMoves(board, x, y, color); }
//checks if the move is still located on the board & is moved onto empty or kill spot private static bool KillOrEmpty(int x, int y,ChessBoard board,ChessColor color) { if(board[x,y] != ChessPiece.Empty) { if(color==ChessColor.White) { switch (board[x,y]) { case ChessPiece.BlackPawn: case ChessPiece.BlackKnight: case ChessPiece.BlackBishop: case ChessPiece.BlackQueen: case ChessPiece.BlackRook: case ChessPiece.BlackKing: return true; default: return false; } } if(color==ChessColor.Black) { switch (board[x, y]) { case ChessPiece.WhiteBishop: case ChessPiece.WhiteKing: case ChessPiece.WhiteKnight: case ChessPiece.WhitePawn: case ChessPiece.WhiteQueen: case ChessPiece.WhiteRook: return true; default: return false; } } } return true; }
//easy enough to just use inline check for this instead of calling a function /*private static bool CheckEmpty(int x, int y, ChessBoard board) { if (board[x, y] == ChessPiece.Empty) return true; return false; }*/ //this will not check last position for enemy or blank private static bool PathClear(int fromX, int fromY, int toX, int toY, ChessBoard board) { //if horizontal if(fromY==toY) { if (toX - fromX > 0) fromX++; else fromX--; while (fromX != toX) { if (board[fromX, fromY] != ChessPiece.Empty) return false; if (toX - fromX > 0) fromX++; else fromX--; } } //if vertical else if(fromX==toX) { if (toY - fromY > 0) fromY++; else fromY--; while (fromY != toY) { if (board[fromX, fromY] != ChessPiece.Empty) return false; if (toY - fromY > 0) fromY++; else fromY--; } } //if diagonal else if(Math.Abs(fromX-toX)==Math.Abs(fromY-toY)) { if (toY - fromY > 0) fromY++; else fromY--; if (toX - fromX > 0) fromX++; else fromX--; while (fromY != toY) { if (board[fromX, fromY] != ChessPiece.Empty) return false; if (toY - fromY > 0) fromY++; else fromY--; if (toX - fromX > 0) fromX++; else fromX--; } } else //if none of the above { return false; } return true; }
/// <summary> /// Checks if the move the white pawn wants to make is valid /// </summary> /// <param name="board">board state before move</param> /// <param name="move">move the piece wants to make</param> /// <returns>true if valid move, false is invalid</returns> public static bool BlackPawn(ChessBoard board, ChessMove move) { //if pawn tries to move backwords if (move.To.Y <= move.From.Y) //white pawns Y goes up or less than return false; //validate move is still on board & is empty or kill if (move.From.Y == 1 && move.To.Y == 3) //trying to move two places from start { //make sure they're moving to the same column if (move.To.X != move.From.X) return false; //if both spaces are not empty if (board[move.To.X, move.To.Y] != ChessPiece.Empty || board[move.To.X, move.To.Y - 1] != ChessPiece.Empty) return false; } //if just moving forward by one else if (move.To.Y - move.From.Y == 1) { //if going for kill diagnoally if (Math.Abs(move.From.X - move.To.X) == 1) { if (!IsEnemy(move.To.X, move.To.Y, board, ChessColor.Black)) return false; } //if just moving forward else if (move.From.X == move.To.X) { if (board[move.To.X, move.To.Y] != ChessPiece.Empty) return false; } //otherwise false if moving too far horizontally else { return false; } } else { return false; } //all checks pass return true; }
private void KingMoves(ChessBoard board, int x, int y, ChessColor color) { if (color == ChessColor.White) { //king moves up if (x > 0 && (board[x - 1, y] == ChessPiece.Empty || board[x - 1, y] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x - 1, y))); } // king moves up and left if (y > 0 && x > 0 && (board[x - 1, y - 1] == ChessPiece.Empty || board[x - 1, y - 1] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x - 1, y - 1))); } // king moves up and right if (y < ChessBoard.NumberOfColumns && x > 0 && (board[x - 1, y + 1] == ChessPiece.Empty || board[x - 1, y + 1] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x - 1, y + 1))); } //king right moves if (y < ChessBoard.NumberOfColumns && (board[x, y + 1] == ChessPiece.Empty || board[x, y + 1] == ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, y + 1))); } //king moves left if (y > 0 && (board[x, y - 1] < ChessPiece.Empty || board[x, y - 1] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, y - 1))); } //king moves down and left if (y > 0 && x < ChessBoard.NumberOfRows && board[x + 1, y - 1] < ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y - 1))); } //king moves down if (x < ChessBoard.NumberOfRows && (board[x + 1, y] == ChessPiece.Empty || board[x + 1, y] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y))); } //king moves down and right if (y < ChessBoard.NumberOfColumns && x < ChessBoard.NumberOfRows && (board[x + 1, y + 1] == ChessPiece.Empty || board[x + 1, y + 1] < ChessPiece.Empty)) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y + 1))); } } else { if (board[x + 1, y] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y))); } if (y > 0 && board[x + 1, y - 1] > ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y - 1))); } if (y < ChessBoard.NumberOfColumns && board[x + 1, y + 1] < ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y + 1))); } if (x == 2 && board[x + 1, y] == ChessPiece.Empty && board[x + 2, y] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x - 2, y))); } } }
/// <summary> /// gets move for a specfic piece /// </summary> public static List<ChessMove> getmovesofpiece(StudentAI ai,ChessColor color, ChessBoard board,ChessLocation location) { List<ChessMove> piecemoves = new List<ChessMove>(); ChessMove move = new ChessMove(location,location); switch (board[location]) { case ChessPiece.BlackPawn: ChessMove bdiag1 = new ChessMove(location,new ChessLocation((location.X)-1,(location.Y)+1)); ChessMove bdown = new ChessMove(location,new ChessLocation((location.X),(location.Y)+1)); ChessMove bdown2 = new ChessMove(location, new ChessLocation((location.X), (location.Y) + 2)); ChessMove bdiag2 = new ChessMove(location,new ChessLocation((location.X)+1,(location.Y)+1)); if (ai.IsValidMove(board, bdiag1, color)) piecemoves.Add(bdiag1); if (ai.IsValidMove(board, bdown, color)) piecemoves.Add(bdown); if (ai.IsValidMove(board, bdiag2, color)) piecemoves.Add(bdiag2); if (ai.IsValidMove(board, bdown2, color)) piecemoves.Add(bdown2); break; case ChessPiece.WhitePawn: ChessMove wdiag1 = new ChessMove(location,new ChessLocation((location.X)-1,(location.Y)-1)); ChessMove wup = new ChessMove(location,new ChessLocation((location.X),(location.Y)-1)); ChessMove wup2 = new ChessMove(location, new ChessLocation((location.X), (location.Y) - 2)); ChessMove wdiag2 = new ChessMove(location,new ChessLocation((location.X)+1,(location.Y)-1)); if (ai.IsValidMove(board, wdiag1, color)) piecemoves.Add(wdiag1); if (ai.IsValidMove(board, wup, color)) piecemoves.Add(wup); if (ai.IsValidMove(board, wdiag2, color)) piecemoves.Add(wdiag2); if (ai.IsValidMove(board, wup2, color)) piecemoves.Add(wup2); break; case ChessPiece.BlackKing: for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { move = new ChessMove(location, new ChessLocation(location.X + i, location.Y + j)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); } } break; case ChessPiece.WhiteKing: for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { move = new ChessMove(location, new ChessLocation(location.X + i, location.Y + j)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); } } break; case ChessPiece.BlackKnight: move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + 1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + -1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + 2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + -2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + 1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + -1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + 2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + -2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); break; case ChessPiece.WhiteKnight: move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + 1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + -1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + 2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + -2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + 1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + -1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + 2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + -2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); break; case ChessPiece.BlackBishop: case ChessPiece.WhiteBishop: bool flag = true; int x = 1; while(flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y + x)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; case ChessPiece.BlackRook: case ChessPiece.WhiteRook: flag = true; x = 1; while(flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y+x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y-x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; case ChessPiece.BlackQueen: case ChessPiece.WhiteQueen: flag = true; x = 1; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; default: return piecemoves; } return piecemoves; }
private void PawnMoves(ChessBoard board, int x, int y, ChessColor color) { if (color == ChessColor.White) { if (y - 1 > 0 && board[x , y - 1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x , y - 1))); } if (y - 1 > 0 && x - 1 > 0 && board[x - 1, y - 1] < ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x - 1, y - 1))); } if (y - 1 < ChessBoard.NumberOfColumns && x + 1 < ChessBoard.NumberOfRows && board[x + 1, y - 1] < ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y - 1))); } if (y == 6 && board[x, y - 1] == ChessPiece.Empty && board[x , y - 2] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, y - 2))); } } else { if (y + 1 < ChessBoard.NumberOfRows && board[x , y + 1] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, y + 1))); } if (y + 1 < ChessBoard.NumberOfRows && x + 1 < ChessBoard.NumberOfColumns && board[x + 1, y + 1] > ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y + 1))); } if (y < ChessBoard.NumberOfColumns && x + 1 < ChessBoard.NumberOfRows && board[x + 1, y + 1] < ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x + 1, y + 1))); } if (y == 2 && board[x , y + 1] == ChessPiece.Empty && board[x , y + 2] == ChessPiece.Empty) { Moves.Add(new ChessMove(new ChessLocation(x, y), new ChessLocation(x, y + 2))); } } }