// A toString type function for the parameter move. public static string MoveToString(int move) { string moveToPrint; var fromFile = Conversion.getFilesBrd(MoveOperations.FromSq(move)); var fromRank = Conversion.getRanksBrd(MoveOperations.FromSq(move)); var toFile = Conversion.getFilesBrd(MoveOperations.ToSq(move)); var toRank = Conversion.getRanksBrd(MoveOperations.ToSq(move)); var promoted = MoveOperations.Promoted(move); if (promoted != 0) { var pieceChar = 'q'; if (Data.IsPieceKnight(promoted)) { pieceChar = 'n'; } else if (Data.IsPieceRookQueen(promoted) && !Data.IsPieceBishopQueen(promoted)) { pieceChar = 'r'; } else if (!Data.IsPieceRookQueen(promoted) && Data.IsPieceBishopQueen(promoted)) { pieceChar = 'b'; } moveToPrint = string.Format("{0}{1}{2}{3}{4}", Convert.ToChar('a' + fromFile), Convert.ToChar('1' + fromRank), Convert.ToChar('a' + toFile), Convert.ToChar('1' + toRank), Convert.ToChar(pieceChar)); } else { moveToPrint = string.Format("{0}{1}{2}{3}", Convert.ToChar('a' + fromFile), Convert.ToChar('1' + fromRank), Convert.ToChar('a' + toFile), Convert.ToChar('1' + toRank)); } return(moveToPrint); }
public int AlphaBeta(int alpha, int beta, int depth, ref S_SearchInfo info, bool DoNull) { Debug.Assert(BoardOperations.CheckBoard(board)); if (depth == 0) { return(Quiescence(alpha, beta, ref info)); } if ((info.Nodes & 2047) == 0) { CheckUp(ref info); } info.Nodes++; // If position is a draw. if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0) { return(0); } if (board.Ply > Variables.MAX_DEPTH - 1) { return(Evaluate.Position(board)); } bool kingInCheck = Attack.IsSqAttacked(board.KingSq[board.Side], board.Side ^ 1, board); // If king is in check, search deeper to get out of check. if (kingInCheck) { depth++; // The two following lines are possibly ERROR. long timeInc = (info.StopTime - info.StartTime) * (1 / 2); info.StopTime += timeInc; } MoveList list = new MoveList(); MoveGen.GenerateAllMoves(board, list, false); int oldAlpha = alpha; int score = -infinite; int legal = 0; // Will increment when we find a legal move. int bestMove = Variables.NO_MOVE; int PvMove = PvTable.Probe(board); // Prioritize Principle Variation move if it's found. if (PvMove != Variables.NO_MOVE) { for (int i = 0; i < list.Count; ++i) { var move = list.Moves[i].Move; if (move == PvMove) { list.Moves[i].Score = 2000000; break; } } } for (int i = 0; i < list.Count; ++i) { PickNextMove(i, list); var move = list.Moves[i].Move; if (!MakeMove.Make_Move(board, move)) { continue; } legal++; score = -AlphaBeta(-beta, -alpha, depth - 1, ref info, true); MakeMove.TakeMove(board); // Take back the made move. if (info.Stopped) { return(0); // Back up to the root if times up. } // We have a new alpha or beta cutoff. if (score > alpha) { bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0; // beta cutoff? if (score >= beta) { if (legal == 1) { info.Fhf++; // We searched the best move first. } info.Fh++; // If beta cutoff, but no capture move. if (!isCaptureMove) { board.SearchKillers[1, board.Ply] = board.SearchKillers[0, board.Ply]; board.SearchKillers[0, board.Ply] = move; } return(beta); } // Alpha cutoff alpha = score; bestMove = move; if (!isCaptureMove) { int from = MoveOperations.FromSq(move); int to = MoveOperations.ToSq(move); board.SearchHistory[board[from], to] += depth; // Prioritizes move near the root of the tree. } } } // If we haven't had any legal moves. if (legal == 0) { // If in check with no legal moves checkmate. if (kingInCheck) { return(-mate + board.Ply); // Return the amount of moves it takes to mate. // Returning in this way, allows the method to "prefer" the fastest checkmate combination. } else { return(0); // Stalemate. } } if (alpha != oldAlpha) { PvTable.StoreMove(board, bestMove); } return(alpha); }
/// <summary> /// Translates a move to an integer /// </summary> /// <param name="board"></param> /// <param name="ptrChar"></param> /// <returns></returns> public static int ParseMove(Board board, char[] ptrChar) { if (ptrChar[1] > '8' || ptrChar[1] < '1') { return(Variables.NO_MOVE); } if (ptrChar[3] > '8' || ptrChar[3] < '1') { return(Variables.NO_MOVE); } if (ptrChar[0] > 'h' || ptrChar[0] < 'a') { return(Variables.NO_MOVE); } if (ptrChar[2] > 'h' || ptrChar[2] < 'a') { return(Variables.NO_MOVE); } // Use ASCII values as integers. int from = Conversion.FR2SQ(ptrChar[0] - 'a', ptrChar[1] - '1'); int to = Conversion.FR2SQ(ptrChar[2] - 'a', ptrChar[3] - '1'); Debug.Assert(Validators.SqOnBoard(from), String.Format("The from {0} sq is invalid", Io.SqToString(from))); Debug.Assert(Validators.SqOnBoard(to), String.Format("The to {0} sq is invalid", Io.SqToString(to))); MoveList moveList = new MoveList(); MoveGen.GenerateAllMoves(board, moveList, false); for (int i = 0; i < moveList.Count; ++i) { int move = moveList.Moves[i].Move; // If the move has been located in the move list, it means it's a valid move. if (MoveOperations.FromSq(move) == from && MoveOperations.ToSq(move) == to) { int promotedPce = MoveOperations.Promoted(move); if (promotedPce != (int)Piece.EMPTY) { if (Data.IsPieceRookQueen(promotedPce) && !Data.IsPieceBishopQueen(promotedPce) && ptrChar[4] == 'r') { return(move); } else if (!Data.IsPieceRookQueen(promotedPce) && Data.IsPieceBishopQueen(promotedPce) && ptrChar[4] == 'b') { return(move); } else if (Data.IsPieceKnight(promotedPce) && ptrChar[4] == 'k') { return(move); } else if (Data.IsPieceBishopQueen(promotedPce) && Data.IsPieceRookQueen(promotedPce) && ptrChar[4] == 'q') { return(move); } continue; } return(move); } } return(Variables.NO_MOVE); }