/// <summary> /// Examines the board's position to detect whethet '_side' is in check /// </summary> /// <param name="_side">The side in question</param> /// <returns>True if _side is in check, false otherwise</returns> internal bool IsInCheck(int _side) { //compute attackers int attackedPiece = Piece.BlackKing + _side; return(MovesGenerator.EnemyAttacksOn(this, Position.LSB(BitBoards[attackedPiece]), _side) != 0); }
private static void MakeMove(object _board) { Board board = _board as Board; //check if we only have one move var moves = MovesGenerator.GetMoves(board, false); if (moves.Count == 1) { Moved(moves[0]); } Move move; if (OpeningBook.IsInBook) { move = OpeningBook.GetRandomMove(); } else { BoardEvaluator.m_EvaluationCounter = 0; //Move move = AlphaBetaRoot(m_GameBoard, Depth); move = IterativeDeepeningAlphaBeta(board).BestMove; } Clock.Stop(); if (Moved != null) { Moved(move); } m_MoveThread.Abort(); }
private static IterativeDeepeningResult IterativeDeepeningAlphaBeta(Board _board) { IterativeDeepeningResult result = new IterativeDeepeningResult(); //Move bestMove = null; //Move currentMove = null; var moves = MovesGenerator.GetMoves(_board, true); //iterative deepening current depth int depth; Move lastMove = _board.LastMove[1 - _board.CurrentPlayer]; if (lastMove != null && m_Pondering.Keys.Any(x => x.EqualMove(lastMove))) { Move lastMoveOnPondering = m_Pondering.Keys.First(x => x.EqualMove(lastMove)); IterativeDeepeningResult ponderingResult = m_Pondering[lastMoveOnPondering]; foreach (Move move in ponderingResult.PV_Moves) { Move moveToReorder = moves.First(x => x.EqualMove(move)); moves.Remove(moveToReorder); moves.Insert(0, moveToReorder); } depth = ponderingResult.DepthReeched + 1; } else { depth = 1; } int alpha = -31000, beta = 32000; //iterative deepening for (; !Clock.TimesUp && depth <= Depth; depth++) { _board.NullMoveOk = true; m_NodesSearched = 0; AlphaBetaRootResult alphaBetaResult = AlphaBetaRoot(_board, depth, moves, false, alpha, beta); if (!Clock.TimesUp && alphaBetaResult.BestMove != null && alphaBetaResult.Finished == true) { //used in case of researching bool isSearchOk = true; /*if (alphaBetaResult.Score <= alpha || alphaBetaResult.Score >= beta) * { * alpha = -31000; * beta = 32000; * alphaBetaResult = AlphaBetaRoot(_board, depth, moves, false, alpha, beta); * if (Clock.TimesUp || alphaBetaResult.BestMove == null && alphaBetaResult.Finished == false) * isSearchOk = false; ; * } * else * { * alpha = alphaBetaResult.Score - 50; * beta = alphaBetaResult.Score + 50; * }*/ if (isSearchOk) { result.BestMove = alphaBetaResult.BestMove; result.PV_Moves = alphaBetaResult.PV_Moves; result.DepthReeched = depth; } //order moves by the PV moves. foreach (Move move in alphaBetaResult.PV_Moves) { moves.Remove(move); moves.Insert(0, move); } } Global.WriteToLog(depth.ToString() + ' ' + "100" + ' ' + (Clock.CurrentMoveTimeElapsed.TotalMilliseconds) + ' ' + m_NodesSearched + ' ' + (alphaBetaResult.BestMove != null)); } return(result); }
private static int AlphaBeta(Board _board, int _depth, int alpha, int beta) { m_NodesSearched++; /*TranspositionEntry _tableEntry; * if (_depth > 1 && m_TranspositionTable.TryLookupBoard(_board, out _tableEntry) && _tableEntry.Player == _board.CurrentPlayer) * { * if (_tableEntry.Depth >= _depth && _tableEntry.EvaluationType == EvaluationType.Exact) * return _tableEntry.Value; * }*/ if (_depth <= 0) { int score = QuiescenceSearch(_board, 0, alpha, beta); return(score); } if (_board.IsTerminal != TerminalType.NotTerminal) { if (_board.IsTerminal == TerminalType.Stalemate) { return(0); } } if (_depth > 4 && Clock.TimesUp) { return(TIMES_UP); } //try a null move first, maybe we will get a cutoff (fail-high) , or just a better lower bound if (_board.NullMoveOk) { Board nullMoveClone = Board.Clone(_board); nullMoveClone.ApplyNullMove(); int nullMoveSearchValue = -AlphaBeta(nullMoveClone, _depth - SHALLOWER_DEPTH_R - 1, -beta, -beta + 1); if (nullMoveSearchValue >= beta) { return(nullMoveSearchValue); } } _board.NullMoveOk = true; List <Move> movesBoards; if (_depth == 1) { movesBoards = MovesGenerator.GetMoves(_board, false); } else { movesBoards = MovesGenerator.GetMoves(_board, true); } //if terminal, evaluate if (movesBoards == null) { switch (_board.IsTerminal) { case TerminalType.BlackWon: if (_board.CurrentPlayer == Side.Black) { return(32000); } else { return(-32000); } case TerminalType.WhiteWon: if (_board.CurrentPlayer == Side.White) { return(32000); } else { return(-32000); } case TerminalType.Stalemate: return(0); } } foreach (Move move in movesBoards) { Board clone = Board.Clone(_board); clone.ApplyMove(move); int childAlphaBeta = -AlphaBeta(clone, _depth - 1, -beta, -alpha); if (childAlphaBeta > alpha) { alpha = childAlphaBeta; } if (childAlphaBeta == TIMES_UP) { return(TIMES_UP); } if (beta <= alpha) { break; } } //m_TranspositionTable.StoreBoard(_board, alpha, EvaluationType.Exact, _depth); return(alpha); }
private static void MakePondering(object _board) { Board board = _board as Board; m_Pondering = new Dictionary <Move, IterativeDeepeningResult>(); var moves = MovesGenerator.GetMoves(board, true); Dictionary <Move, List <Move> > responseMoves = new Dictionary <Move, List <Move> >(); bool finishedDepth = true; for (int depth = 1; finishedDepth && depth <= Depth; depth = depth + 1) { for (int i = 0; i < moves.Count; i++) { Move move = moves[i]; //order moves by the PV moves. if (depth > 1) { foreach (Move pvMove in m_Pondering[move].PV_Moves) { responseMoves[move].Remove(pvMove); responseMoves[move].Insert(0, pvMove); } } //now clone the game board (to avoid any changes) Board clone = Board.Clone(board); clone.ApplyMove(move); List <Move> response; if (responseMoves.ContainsKey(move)) { response = responseMoves[move]; } else { response = MovesGenerator.GetMoves(clone, true); if (response == null) { continue; } responseMoves.Add(move, response); } //launch alpha beta AlphaBetaRootResult alphaBetaResult = AlphaBetaRoot(clone, depth, response, true); if (alphaBetaResult.Finished == false) { finishedDepth = false; break; } IterativeDeepeningResult moveResult; if (m_Pondering.ContainsKey(move)) { moveResult = m_Pondering[move]; moveResult.BestMove = alphaBetaResult.BestMove; moveResult.PV_Moves = alphaBetaResult.PV_Moves; moveResult.DepthReeched++; } else { m_Pondering.Add(move, new IterativeDeepeningResult { BestMove = alphaBetaResult.BestMove, DepthReeched = 1, PV_Moves = alphaBetaResult.PV_Moves }); } } } m_PonderThread.Abort(); }
/// <summary> /// Parses one single move. /// </summary> /// <param name="_board">The current board , current opening book's game board</param> /// <param name="_pgnMove">the move's PGN notation</param> /// <param name="moves">A list of all availible moves</param> /// <returns>An opening move represents the parsed response.</returns> private static OpeningMove PGNMoveParser(Board _board, string _pgnMove, List <Move> moves) { bool isCapture = _pgnMove.Contains('x'); bool test = false; if (test) { moves = MovesGenerator.GetLegalMoves(_board); } OpeningMove move = new OpeningMove(); try { //first check if it is castle if (_pgnMove.StartsWith("O-O-O")) { move.Move = moves.First(x => x.MoveType == MoveTypes.CastleQueenSide); } else if (_pgnMove.StartsWith("O-O")) { move.Move = moves.First(x => x.MoveType == MoveTypes.CastleKingSide); } else { int piece = PGNletterToPieceParser(_pgnMove[0], _board.CurrentPlayer); var pieceMoves = moves.Where(x => x.MovingPiece == piece); if (pieceMoves.Count() == 1) { move.Move = pieceMoves.ElementAt(0); } else { if (piece == Piece.BlackPawn || piece == Piece.WhitePawn) { var sourceMoves = pieceMoves.Where(x => x.SourceFile == _pgnMove[0]); if (sourceMoves.Count() == 1) { move.Move = sourceMoves.ElementAt(0); } else { if (isCapture) { string dest = _pgnMove.Substring(_pgnMove.IndexOf('x') + 1, 2); move.Move = sourceMoves.First(x => x.DestinationSquareString == dest); } else { string dest = _pgnMove.Substring(0, 2); move.Move = sourceMoves.First(x => x.DestinationSquareString.StartsWith(dest)); } } } else { IEnumerable <Move> destMoves; if (isCapture) { string dest = _pgnMove.Substring(_pgnMove.IndexOf('x') + 1, 2); destMoves = pieceMoves.Where(x => x.DestinationSquareString == dest); } else { int indexDestRank = _pgnMove.LastIndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' }); string dest = _pgnMove.Substring(indexDestRank - 1, 2); destMoves = pieceMoves.Where(x => x.DestinationSquareString == dest); } switch (destMoves.Count()) { case 1: move.Move = destMoves.ElementAt(0); break; case 2: //either rank or file ambiguity if (_pgnMove[1] >= '1' && _pgnMove[1] <= '9') { //rank ambiguity move.Move = destMoves.First(x => x.SourceRank == _pgnMove[1]); } else { move.Move = destMoves.First(x => x.SourceFile == _pgnMove[1]); } break; case 3: move.Move = destMoves.First(x => x.SourceSquareString == _pgnMove.Substring(1, 2)); break; } } } //now get move type if (_pgnMove.Contains("!!")) { move.MoveType = OpeningMoveType.Excellent; } else if (_pgnMove.Contains("!?")) { move.MoveType = OpeningMoveType.Interesting; } else if (_pgnMove.Contains("?!")) { move.MoveType = OpeningMoveType.Dubious; } else if (_pgnMove.Contains("!")) { move.MoveType = OpeningMoveType.Good; } else if (_pgnMove.Contains("??")) { move.MoveType = OpeningMoveType.Blunder; } else if (_pgnMove.Contains("?")) { move.MoveType = OpeningMoveType.Bad; } } if (move.Move == null) { throw new System.Exception("not found"); } return(move); } catch (Exception ex) { throw ex; } }
/// <summary> /// Parses the book string in the standard PGN format, and inserts it into the starting position node /// </summary> /// <param name="book">A standard PGN formatted string</param> /// <param name="startingPoint">The starting node to add responses to</param> private static void AnalyzeBook(string book, OpeningMove startingPoint) { try { string[] tags = book.Replace("\r\n", " ").Split(new string[] { "[" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 6; i < tags.Length; i += 7) { string movesString = tags[i].Substring(tags[i].IndexOf(']') + 1); string[] movesArray = movesString.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); Board board = new Board(); board.StartingPosition(); //parentMove will slide, containing the parent to the move. OpeningMove parentMove = startingPoint; bool abortMatch = false; for (int j = 0; j < movesArray.Length && !abortMatch; j++) { if (j % 3 == 0) { continue; } if (parentMove.LegalMoves == null) { parentMove.LegalMoves = MovesGenerator.GetLegalMoves(board); } OpeningMove move = PGNMoveParser(board, movesArray[j], parentMove.LegalMoves); if (move.MoveType != OpeningMoveType.Excellent && move.MoveType != OpeningMoveType.Good) { abortMatch = true; break; } //to avoid duplicate entries problem, we make sure to use same instance of a move. OpeningMove storedSameMove = parentMove.Responses.FirstOrDefault(x => x.Move.EqualMove(move.Move)); if (storedSameMove == null) { move.Count = 1; parentMove.Responses.Add(move); } else { parentMove.Count++; move = storedSameMove; } parentMove = move; board.ApplyMove(move.Move); } } } catch (Exception ex) { throw ex; } }
public void WinBoardGame() { m_Clocks = new Clock[2]; m_Clocks[Side.White] = new Clock(); m_Clocks[Side.Black] = new Clock(); AIPlayer.Moved += new MoveEventHandler(m_EnginePlayer_Moved); //m_GameBoard.CurrentPlayer = (Side)(((int)currentPlayer + 1) & 0x1); //move = Players[currentPlayer].Move(); Global.WriteToLog("-----------------" + DateTime.Now.ToString() + "-----------------"); while (m_toContinue) { string input; if (m_GetResponseFromFile) { while (AIPlayer.IsThinking) { System.Threading.Thread.Sleep(2000); } input = m_FileResponse[0]; m_FileResponse.RemoveAt(0); //pause at level if (m_FileResponse.Count == 2) { int x = 1; if (x == 1) { x = 2; } } } else { while (AIPlayer.IsThinking) { System.Threading.Thread.Sleep(2000); } input = Console.ReadLine(); if (m_WriteToScript) { Global.WriteToScript(input); } } Global.WriteToLog("I:" + input); string arg = String.Empty; string commandType = String.Empty; int pos = input.IndexOf(' '); if (pos > 0) { commandType = input.Substring(0, pos); if (input.Length > pos + 1) { arg = input.Substring(pos + 1); } } else { commandType = input; } WinBoardCommands command = WinBoardCommands.Nopost; string response = String.Empty; if (m_editMode) { /*if (commandType.Length > 0) * { * if (commandType.Length > 1) * { * int Col = input[1] - 'a'; * int Row = int.Parse(input[2].ToString()) - 1; * int position = Row * 8 + Col; * switch (commandType[0]) * { * case 'P': * m_GameBoard.AddPiece(position, Piece.BlackPawn + m_GameBoard.CurrentPlayer); * break; * case 'R': * m_GameBoard.AddPiece(position, Piece.BlackRook + m_GameBoard.CurrentPlayer); * break; * case 'Q': * m_GameBoard.AddPiece(position, Piece.BlackQueen + m_GameBoard.CurrentPlayer); * break; * case 'K': * m_GameBoard.AddPiece(position, Piece.BlackKing + m_GameBoard.CurrentPlayer); * break; * case 'B': * m_GameBoard.AddPiece(position, Piece.BlackBishop + m_GameBoard.CurrentPlayer); * break; * case 'N': * m_GameBoard.AddPiece(position, Piece.BlackKnight + m_GameBoard.CurrentPlayer); * break; * } * } * else * { * switch (commandType[0]) * { * case '#': * int currentPlayer = m_GameBoard.CurrentPlayer; * m_GameBoard = new Board(); * m_GameBoard.ClearedBoard(); * m_GameBoard.CurrentPlayer = currentPlayer; * break; * case '.': * m_editMode = false; * break; * } * } * }*/ } else { try { command = (WinBoardCommands)Enum.Parse(typeof(WinBoardCommands), commandType, true); } catch (Exception ex) { switch (commandType) { case "?": command = WinBoardCommands.QMark; break; default: command = WinBoardCommands.Unknown; break; } } switch (command) { case WinBoardCommands.New: break; case WinBoardCommands.Protover: response = "feature time=0 colors=0 usermove=1 done=1"; break; case WinBoardCommands.Quit: m_toContinue = false; AIPlayer.Dispose(); break; case WinBoardCommands.Force: AIPlayer.ToForce = true; break; case WinBoardCommands.Level: string[] timeData; timeData = arg.Split(' '); if (timeData[1].Contains(':')) { string[] timeDataParts = timeData[1].Split(':'); int minutes = int.Parse(timeDataParts[0]), seconds = int.Parse(timeDataParts[1]); m_Clocks[Side.Black].Time = m_Clocks[Side.White].Time = TimeSpan.FromMinutes(minutes).Add(TimeSpan.FromSeconds(seconds)); } else { int minutes = int.Parse(timeData[1]); m_Clocks[Side.Black].Time = m_Clocks[Side.White].Time = TimeSpan.FromMinutes(minutes); } m_Clocks[Side.Black].Incremental = m_Clocks[Side.White].Incremental = TimeSpan.FromSeconds(int.Parse(timeData[2])); break; case WinBoardCommands.Sd: int depth; if (int.TryParse(arg, out depth)) { AIPlayer.Depth = depth; } else { //out error } break; case WinBoardCommands.QMark: AIPlayer.Move(m_GameBoard); break; case WinBoardCommands.Usermove: if (m_EngineSide == -1) { m_EngineSide = Side.Black; AIPlayer.Clock = m_Clocks[m_EngineSide]; } AIPlayer.StopPondering = true; var moves = MovesGenerator.GetMoves(m_GameBoard, false); int sourceCol = arg[0] - 'a'; int sourceRow = int.Parse(arg[1].ToString()) - 1; int destCol = arg[2] - 'a'; int destRow = int.Parse(arg[3].ToString()) - 1; int source = sourceRow * 8 + sourceCol; int dest = destRow * 8 + destCol; Move move = (from anyMove in moves where anyMove.SourceSquare == source && anyMove.DestinationSquare == dest select anyMove).ElementAtOrDefault(0); if (move == null) { response = "Illegal move: " + arg; } else { m_GameBoard.ApplyMove(move); OpeningBook.MoveApplied(move); m_Clocks[1 - m_GameBoard.CurrentPlayer].Stop(); m_Clocks[m_GameBoard.CurrentPlayer].Start(); AIPlayer.Move(m_GameBoard); } break; case WinBoardCommands.Go: if (m_EngineSide == -1) { m_EngineSide = Side.White; AIPlayer.Clock = m_Clocks[m_EngineSide]; } if (m_EngineSide != m_GameBoard.CurrentPlayer) { break; } AIPlayer.ToForce = false; m_EngineSide = m_GameBoard.CurrentPlayer; AIPlayer.Clock = m_Clocks[m_EngineSide]; m_Clocks[m_EngineSide].Start(); AIPlayer.Move(m_GameBoard); break; case WinBoardCommands.Accepted: break; case WinBoardCommands.Result: //announce defeat to winboard ? break; case WinBoardCommands.Edit: m_editMode = true; break; default: response = "Error (unknown command): " + commandType; break; } if (response != string.Empty) { Global.WriteToLog("O:" + response); Console.WriteLine(response); } } } }