// 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); }