// returns standing pat (static exchange evalutation) score of specified capturing move public static int StaticExchangeEvaluate(ChessMove move, int player) { // variables to track loss values int white_loss = 0, black_loss = 0, next_loss = 0; int wKing_loss = 0, bKing_loss = 0; // flags to check if either king is participating in attack bool wKingAttack = false, bKingAttack = false; // get current occupied BitBoard UInt64 occupied = AI.board.occupied_squares; // get target square of attack uint target = move.GetToSq(); // add piece on target square to color's material loss if (ChessBoard.GetPieceColor(move.GetCapture()) == ChessBoard.WHITE) { white_loss += Score.GetPieceValue(move.GetCapture()); } else if (ChessBoard.GetPieceColor(move.GetCapture()) == ChessBoard.BLACK) { black_loss += Score.GetPieceValue(move.GetCapture()); } // set next loss value equal to value of piece making initial capture next_loss = Score.GetPieceValue(move.GetPiece()); // remove piece making capture from occupied BitBoard occupied ^= ChessBoard.SQUARES[move.GetFromSq()]; // keep track of next player to move int playerToMove = AI.GetOtherPlayer(player); // loop until no more pieces are attacking the target square while (true) { // if either king is participating in an attack illegally, undo last capture, break loop if (wKingAttack && playerToMove == ChessBoard.WHITE) { black_loss -= wKing_loss; break; } else if (bKingAttack && playerToMove == ChessBoard.BLACK) { white_loss -= bKing_loss; break; } // reset attackers BitBoard UInt64 attackers = occupied; // check for attacking pieces of player to move if (playerToMove == ChessBoard.WHITE) { //--------------------// // WHITE PAWNS (NP) // //--------------------// // check for non-promoting white pawns if (ChessMove.GetRank(target) != 7) { // get all non-promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target] >> 16) & AI.board.white_pawn; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // WHITE KNIGHTS // //--------------------// // get all white knights attacking target square attackers = occupied & (MoveGen.GetKnightMoves(target, occupied)) & AI.board.white_knight; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_KNIGHT); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE BISHOPS // //--------------------// // get all white bishops attacking target square attackers = occupied & (MoveGen.GetBishopMoves(target, occupied, occupied)) & AI.board.white_bishop; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_BISHOP); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE ROOKS // //--------------------// // get all white rooks attacking target square attackers = occupied & (MoveGen.GetRookMoves(target, occupied, occupied)) & AI.board.white_rook; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_ROOK); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE PAWNS (P) // //--------------------// // check for promoting white pawns if (ChessMove.GetRank(target) == 7) { // get all promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target - 16]) & AI.board.white_pawn; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_QUEEN) - Score.GetPieceValue(ChessBoard.W_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // WHITE QUEENS // //--------------------// // get all white queens attacking target square attackers = occupied & (MoveGen.GetQueenMoves(target, occupied, occupied)) & AI.board.white_queen; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.W_QUEEN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // WHITE KING // //--------------------// // get white king attacking target square attackers = occupied & (MoveGen.GetKingMoves(target, occupied)) & AI.board.white_king; // if attacking piece exists, update black loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values black_loss += next_loss; wKing_loss = next_loss; // set white king attack flag wKingAttack = true; // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } else if (playerToMove == ChessBoard.BLACK) { //--------------------// // BLACK PAWNS (NP) // //--------------------// // check for non-promoting black pawns if (ChessMove.GetRank(target) != 0) { // get all non-promoting white pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target]) & AI.board.black_pawn; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // BLACK KNIGHTS // //--------------------// // get all black knights attacking target square attackers = occupied & (MoveGen.GetKnightMoves(target, occupied)) & AI.board.black_knight; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_KNIGHT); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK BISHOPS // //--------------------// // get all black bishops attacking target square attackers = occupied & (MoveGen.GetBishopMoves(target, occupied, occupied)) & AI.board.black_bishop; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_BISHOP); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK ROOKS // //--------------------// // get all black rooks attacking target square attackers = occupied & (MoveGen.GetRookMoves(target, occupied, occupied)) & AI.board.black_rook; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_ROOK); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK PAWNS (P) // //--------------------// // check for promoting black pawns if (ChessMove.GetRank(target) == 0) { // get all promoting black pawns attacking target square attackers = occupied & (ChessBoard.PAWN_CAPTURES[target]) & AI.board.black_pawn; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_QUEEN) - Score.GetPieceValue(ChessBoard.B_PAWN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } //--------------------// // BLACK QUEENS // //--------------------// // get all black queens attacking target square attackers = occupied & (MoveGen.GetQueenMoves(target, occupied, occupied)) & AI.board.black_queen; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; next_loss = Score.GetPieceValue(ChessBoard.B_QUEEN); // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } //--------------------// // BLACK KING // //--------------------// // get black king attacking target square attackers = occupied & (MoveGen.GetKingMoves(target, occupied)) & AI.board.black_king; // if attacking piece exists, update white loss, next loss, and occupied BitBoard; repeat loop if (attackers != ChessBoard.EMPTY_BOARD) { // update loss values white_loss += next_loss; bKing_loss = next_loss; // set white king attack flag bKingAttack = true; // update occupied BitBoard occupied ^= ChessBoard.GetFirstBit(attackers); // switch player to move playerToMove = AI.GetOtherPlayer(playerToMove); // restart loop continue; } } // no more attacking pieces - break loop break; } // return net standing pat score based on player color if (player == ChessBoard.WHITE) { return(black_loss - white_loss); } else if (player == ChessBoard.BLACK) { return(white_loss - black_loss); } // something went wrong... return(-1); }
// returns the position score for the specified color public static int GetPositionScore(int player) { // initialize variables int white_position = 0, black_position = 0, net_position = 0; uint white_king_sq = MoveGen.GetNextSquare(AI.board.white_king); uint black_king_sq = MoveGen.GetNextSquare(AI.board.black_king); // loop through game AI.board squares and calculate position/distance scores for each piece for (int i = 0; i < 64; i++) { if (AI.board.theBoard[i] == ChessBoard.EMPTY) { continue; // square is empty } if (ChessBoard.GetPieceColor(AI.board.theBoard[i]) == ChessBoard.WHITE) { switch (AI.board.theBoard[i]) { case ChessBoard.W_PAWN: white_position += PAWN_POSITION[i]; white_position += PAWN_OPPONENT_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; white_position += PAWN_OWN_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; break; case ChessBoard.W_ROOK: white_position += ROOK_POSITION[i]; white_position += ROOK_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; break; case ChessBoard.W_KNIGHT: white_position += KNIGHT_POSITION[i]; white_position += KNIGHT_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; break; case ChessBoard.W_BISHOP: white_position += BISHOP_POSITION[i]; white_position += BISHOP_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; break; case ChessBoard.W_QUEEN: white_position += QUEEN_POSITION[i]; white_position += QUEEN_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; break; case ChessBoard.W_KING: if (IsEndGame(GetMaterialScore(ChessBoard.WHITE), GetMaterialScore(ChessBoard.BLACK))) { white_position += KING_ENDGAME_POSITION[i]; } else { white_position += KING_POSITION[i]; } break; } } else if (ChessBoard.GetPieceColor(AI.board.theBoard[i]) == ChessBoard.BLACK) { switch (AI.board.theBoard[i]) { case ChessBoard.B_PAWN: black_position += PAWN_POSITION[MIRROR[i]]; black_position += PAWN_OPPONENT_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; black_position += PAWN_OWN_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(black_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(black_king_sq)))]; break; case ChessBoard.B_ROOK: black_position += ROOK_POSITION[MIRROR[i]]; black_position += ROOK_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; break; case ChessBoard.B_KNIGHT: black_position += KNIGHT_POSITION[MIRROR[i]]; black_position += KNIGHT_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; break; case ChessBoard.B_BISHOP: black_position += BISHOP_POSITION[MIRROR[i]]; black_position += BISHOP_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; break; case ChessBoard.B_QUEEN: black_position += QUEEN_POSITION[MIRROR[i]]; black_position += QUEEN_DISTANCE[Math.Min(Math.Abs((int)ChessMove.GetFile((uint)i) - (int)ChessMove.GetFile(white_king_sq)), Math.Abs((int)ChessMove.GetRank((uint)i) - (int)ChessMove.GetRank(white_king_sq)))]; break; case ChessBoard.B_KING: if (IsEndGame(GetMaterialScore(ChessBoard.WHITE), GetMaterialScore(ChessBoard.BLACK))) { black_position += KING_ENDGAME_POSITION[MIRROR[i]]; } else { black_position += KING_POSITION[MIRROR[i]]; } break; } } } // calculate net position score if (player == ChessBoard.WHITE) { net_position += white_position - black_position; } else if (player == ChessBoard.BLACK) { net_position += black_position - white_position; } // return position score return(net_position); }
// initializes non-constant scoring arrays public static void InitializeScoringArrays() { // initialize scoring arrays and set values to 0 W_PASSED_PAWN = new UInt64[64]; B_PASSED_PAWN = new UInt64[64]; W_ISOLATED_PAWN = new UInt64[64]; B_ISOLATED_PAWN = new UInt64[64]; W_BACKWARD_PAWN = new UInt64[64]; B_BACKWARD_PAWN = new UInt64[64]; W_KINGSAFETY_STRONG = new UInt64[64]; B_KINGSAFETY_STRONG = new UInt64[64]; W_KINGSAFETY_WEAK = new UInt64[64]; B_KINGSAFETY_WEAK = new UInt64[64]; for (int i = 0; i < 64; i++) { W_PASSED_PAWN[i] = 0; B_PASSED_PAWN[i] = 0; W_ISOLATED_PAWN[i] = 0; B_ISOLATED_PAWN[i] = 0; W_BACKWARD_PAWN[i] = 0; B_BACKWARD_PAWN[i] = 0; W_KINGSAFETY_STRONG[i] = 0; B_KINGSAFETY_STRONG[i] = 0; W_KINGSAFETY_WEAK[i] = 0; B_KINGSAFETY_WEAK[i] = 0; } // set values for pawn structure position arrays for (int i = 0; i < 64; i++) { // set values for passed pawn position arrays for (int rank = (int)ChessMove.GetRank((uint)i) + 1; rank < 8; rank++) { // white passed pawns if (ChessMove.GetFile((uint)i) > 0) { W_PASSED_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } W_PASSED_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; if (ChessMove.GetFile((uint)i) < 7) { W_PASSED_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } } // set values for isolated pawn position arrays for (int rank = 2; rank < 8; rank++) { // white isolated pawns if (ChessMove.GetFile((uint)i) > 0) { W_ISOLATED_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } if (ChessMove.GetFile((uint)i) < 7) { W_ISOLATED_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } } // set values for backward pawn position array for (int rank = 2; rank <= (int)ChessMove.GetRank((uint)i) + 1; rank++) { // white backward pawns if (ChessMove.GetFile((uint)i) > 0) { W_BACKWARD_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } if (ChessMove.GetFile((uint)i) < 7) { W_BACKWARD_PAWN[i] ^= ChessBoard.SQUARES[((rank - 1) * 8) + (int)ChessMove.GetFile((uint)i)]; } } } // set values for king safety position arrays for (int i = 0; i < 24; i++) { // white king safety strong/weak W_KINGSAFETY_STRONG[i] ^= ChessBoard.SQUARES[i + 8]; W_KINGSAFETY_WEAK[i] ^= ChessBoard.SQUARES[i + 16]; if (ChessMove.GetFile((uint)i) > 0) { W_KINGSAFETY_STRONG[i] ^= ChessBoard.SQUARES[i + 7]; W_KINGSAFETY_WEAK[i] ^= ChessBoard.SQUARES[i + 15]; } if (ChessMove.GetFile((uint)i) < 7) { W_KINGSAFETY_STRONG[i] ^= ChessBoard.SQUARES[i + 9]; W_KINGSAFETY_WEAK[i] ^= ChessBoard.SQUARES[i + 17]; } if (ChessMove.GetFile((uint)i) == 0) { W_KINGSAFETY_STRONG[i] ^= ChessBoard.SQUARES[i + 10]; W_KINGSAFETY_WEAK[i] ^= ChessBoard.SQUARES[i + 18]; } if (ChessMove.GetFile((uint)i) == 7) { W_KINGSAFETY_STRONG[i] ^= ChessBoard.SQUARES[i + 6]; W_KINGSAFETY_WEAK[i] ^= ChessBoard.SQUARES[i + 14]; } } // set values for black position arrays for (int i = 0; i < 64; i++) { for (int square = 0; square < 64; square++) { // black passed pawns (mirror of white passed pawns) if ((W_PASSED_PAWN[i] & ChessBoard.SQUARES[square]) != 0) { B_PASSED_PAWN[MIRROR[i]] |= ChessBoard.SQUARES[MIRROR[square]]; } // black isolated pawns (mirror of white isolated pawns) if ((W_ISOLATED_PAWN[i] & ChessBoard.SQUARES[square]) != 0) { B_ISOLATED_PAWN[MIRROR[i]] |= ChessBoard.SQUARES[MIRROR[square]]; } // black backward pawns (mirror of white backward pawns) if ((W_BACKWARD_PAWN[i] & ChessBoard.SQUARES[square]) != 0) { B_BACKWARD_PAWN[MIRROR[i]] |= ChessBoard.SQUARES[MIRROR[square]]; } // black king safety strong (mirror of white king safety strong) if ((W_KINGSAFETY_STRONG[i] & ChessBoard.SQUARES[square]) != 0) { B_KINGSAFETY_STRONG[MIRROR[i]] |= ChessBoard.SQUARES[MIRROR[square]]; } // black king safety weak (mirror of white king safety weak) if ((W_KINGSAFETY_WEAK[i] & ChessBoard.SQUARES[square]) != 0) { B_KINGSAFETY_WEAK[MIRROR[i]] |= ChessBoard.SQUARES[MIRROR[square]]; } } } }
//This function is called each time it is your turn //Return true to end your turn, return false to ask the server for updated information public override bool run() { // Print out the current board state Console.WriteLine("+---+---+---+---+---+---+---+---+"); for (int rank = 8; rank > 0; rank--) { Console.Write("|"); for (int file = 1; file <= 8; file++) { bool found = false; // Loops through all of the pieces for (int p = 0; !found && p < pieces.Length; p++) { // determines if that piece is at the current rank and file if (pieces[p].getRank() == rank && pieces[p].getFile() == file) { found = true; // Checks if the piece is black if (pieces[p].getOwner() == 1) { Console.Write("*"); } else { Console.Write(" "); } // prints the piece's type Console.Write((char)pieces[p].getType() + " "); } } if (!found) { Console.Write(" "); } Console.Write("|"); } Console.WriteLine("\n+---+---+---+---+---+---+---+---+"); } // Looks through information about the players for (int p = 0; p < players.Length; p++) { Console.Write(players[p].getPlayerName()); // if playerID is 0, you're white, if its 1, you're black if (players[p].getId() == myID) { Console.Write(" (ME)"); // update timeRemaining timeRemaining = players[p].getTime(); } Console.WriteLine(" time remaining: " + players[p].getTime()); } // if there has been a move, print the most recent move if (moves.Length > 0) { Console.Write("Last Move Was: "); Console.WriteLine(files[moves[0].getFromFile() - 1] + "" + moves[0].getFromRank() + "-" + files[moves[0].getToFile() - 1] + "" + moves[0].getToRank()); } ///////////////////////////////////// // <-- END OF STOCK AI.cs CODE --> // ///////////////////////////////////// // print current move number Console.WriteLine("\nMove " + turnNumber().ToString("D3") + "\n========\n"); // add to GameState List and update ChessBoard if (moves.Length <= 1) { board = new ChessBoard(ref pieces, myID); states.Add(new GameState(null, null)); } else { ChessMove lastMove = ChessMove.GetChessMove(moves[0].getFromFile(), moves[0].getToFile(), moves[0].getFromRank(), moves[0].getToRank(), moves[0].getPromoteType(), states[states.Count - 1].enPassant); board = new ChessBoard(ref pieces, myID); states.Add(new GameState(states[states.Count - 1], lastMove)); } // display current score information for player Console.Write("Score for "); if (myID == ChessBoard.WHITE) { Console.WriteLine("WHITE:\n"); } else if (myID == ChessBoard.BLACK) { Console.WriteLine("BLACK:\n"); } int material = Score.GetMaterialScore(myID); int position = Score.GetPositionScore(myID); // int mobility = Score.GetPositionScore(myID); int pawn_structure = Score.GetPawnStructureScore(myID); int king_safety = Score.GetKingSafetyScore(myID); Console.WriteLine("Net Material = " + material); Console.WriteLine("Net Position = " + position); //Console.WriteLine("Net Mobility = " + mobility); Console.WriteLine("Net Pawn Structure = " + pawn_structure); Console.WriteLine("Net King Safety = " + king_safety + "\n"); Console.WriteLine("Overall Score = " + (material + position + /*mobility +*/ pawn_structure + king_safety) + "\n"); // if playing as human, get move from console prompt while (HUMAN_PLAYER) { // get legal moves for this position List <ChessMove> legalMoves = MoveGen.GenerateMoves(myID, false); // prompt user for move Console.Write("Enter a move ([from] [to] <promotion type>): "); string[] humanMove = Console.ReadLine().Split(' '); // get origin square int humanFromFile = 0, humanFromRank = 0; for (int i = 0; i < 8; i++) { if (humanMove[0][0] == files[i]) { humanFromFile = i + 1; break; } } humanFromRank = (int)Char.GetNumericValue(humanMove[0][1]); // get destination square int humanToFile = 0, humanToRank = 0; for (int i = 0; i < 8; i++) { if (humanMove[1][0] == files[i]) { humanToFile = i + 1; break; } } humanToRank = (int)Char.GetNumericValue(humanMove[1][1]); // if promotion type is specified, get the promotion piece from move int humanPromote = 0; if (humanMove.Length > 2) { humanPromote = (int)humanMove[2][0]; } // check for legality of human move bool isLegal = false; for (int i = 0; i < legalMoves.Count; i++) { ChessMove m = legalMoves[i]; if ((ChessMove.GetFile(m.GetFromSq()) + 1) == (uint)humanFromFile && (ChessMove.GetRank(m.GetFromSq()) + 1) == (uint)humanFromRank && (ChessMove.GetFile(m.GetToSq()) + 1) == (uint)humanToFile && (ChessMove.GetRank(m.GetToSq()) + 1) == (uint)humanToRank) { isLegal = true; break; } } // if move is legal, make move if (isLegal) { // get Piece associated with move Piece humanPiece = pieces[FindPiece(humanFromFile, humanFromRank)]; // make move humanPiece.move(humanToFile, humanToRank, humanPromote); return(true); } else if (!isLegal) { Console.WriteLine("ILLEGAL MOVE. Please input a legal move.\n"); } } // reset TIME_EXPIRED and timer TIME_EXPIRED = false; timer.Reset(); // reset history table history = new HistoryTable(); // run ABMiniMax int moveScore = 0, n = 0, toFile = -1, toRank = -1; uint fromSq = 0, toSq = 0, thePiece = 0; depth = 0; List <ChessMove> completeBestMoves = new List <ChessMove>(0); Search.UpdateTimePerMove(moves.Length); timer.Start(); while (!TIME_EXPIRED) { depth += 1; nodes = 0; Search.MAX_DEPTH = depth; Search.NULLMOVE_ALLOWED = true; Search.FOLLOW_PV = true; Search.PV = new List <ChessMove>(0); int score = Search.PVABMiniMax(0, Search.SMALL_NUM, Search.LARGE_NUM); if (score != Score.TIME_EXPIRED_SCORE) { moveScore = score; completeBestMoves = new List <ChessMove>(Search.PV); } // select random move from bestMoves List if (completeBestMoves.Count > 0) { n = generator.Next(0, completeBestMoves.Count - 1); // get bestMove info fromSq = completeBestMoves[n].GetFromSq(); thePiece = completeBestMoves[n].GetPiece(); toSq = completeBestMoves[n].GetToSq(); toFile = (int)((toSq % 8) + 1); toRank = (int)((toSq / 8) + 1); // print bestMove info Console.WriteLine("Best Move: " + completeBestMoves[n].GetMoveString() + ", Score: " + moveScore + ", Depth: " + depth + " (t = " + (timer.ElapsedMilliseconds / 1000.0).ToString("F3") + "s, nodes = " + nodes + ")"); } // if checkmate is found, stop searching if (score == Score.CHECKMATE_WIN_SCORE) { break; } } timer.Stop(); // output number of best moves Console.WriteLine("completeBestMoves = " + completeBestMoves.Count); // make bestMove pieces[FindPiece(fromSq, thePiece)].move(toFile, toRank, completeBestMoves[n].GetPromoteType()); // update ChessBoard and GameState List completeBestMoves[n].DoMove(Search.MAKE); return(true); }