/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; ++i) { m_iterator.Reset(board, location, m_directions[i]); while (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } else { if (m_iterator.CurrentPieceColor() != m_color) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } break; } } } } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { //Basic moves for (int i = 0; i < m_directions.Length; ++i) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) { if (m_iterator.CurrentPieceColor() != m_color) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } //Castling moves switch (m_color) { case PieceColor.White: if (board.State.WhiteCanCastleLong && board.IsPathClear(Square.E1, Square.A1) && !board.IsSquareAttacted(PieceColor.Black, Square.E1) && !board.IsSquareAttacted(PieceColor.Black, Square.D1)) { moves.Add(new Move(board, Square.E1, Square.C1, Square.A1, Square.D1)); } if (board.State.WhiteCanCastleShort && board.IsPathClear(Square.E1, Square.H1) && !board.IsSquareAttacted(PieceColor.Black, Square.E1) && !board.IsSquareAttacted(PieceColor.Black, Square.F1)) { moves.Add(new Move(board, Square.E1, Square.G1, Square.H1, Square.F1)); } break; case PieceColor.Black: if (board.State.BlackCanCastleLong && board.IsPathClear(Square.E8, Square.A8) && !board.IsSquareAttacted(PieceColor.White, Square.E8) && !board.IsSquareAttacted(PieceColor.White, Square.D8)) { moves.Add(new Move(board, Square.E8, Square.C8, Square.A8, Square.D8)); } if (board.State.BlackCanCastleShort && board.IsPathClear(Square.E8, Square.H8) && !board.IsSquareAttacted(PieceColor.White, Square.E8) && !board.IsSquareAttacted(PieceColor.White, Square.F8)) { moves.Add(new Move(board, Square.E8, Square.G8, Square.H8, Square.F8)); } break; } } }
/// <summary> /// Makes computer think. When the move to play as been decided the /// "MoveFound" event is raised. /// </summary> /// <param name="moveOrganizer">List of possible moves to select a move from.</param> /// <param name="maxSearchDepth">Maximum AlphaBeta depth to search. Must be equal to, or larger then one.</param> /// <param name="searchTime">Time before search is stoppen.</param> public void Think(MoveOrganizer moveOrganizer, int maxSearchDepth, int searchTime) { if (!m_workerThread.IsBusy) { m_abortingSearch = false; m_waitHandle.Reset(); m_workerThread.RunWorkerAsync(new ThreadParam(moveOrganizer, maxSearchDepth, searchTime)); } }
/// <summary> /// Instantiates a new instance of the "ThreadParam" class. /// </summary> /// <param name="board">Board associated with move organizer.</param> /// <param name="moveOrganizer">Collection of moves to evaluate and carry out search for.</param> /// <param name="useBook">May the engine use the opening book when selecting a move.</param> /// <param name="searchDepth">Depth to search.</param> /// <param name="aimSearchTime">Time to search. Actual search will typically be a little more.</param> /// <param name="maxSearchTime">Maximum time to search.</param> public ThreadParam(Board board, MoveOrganizer moveOrganizer, bool useBook, int searchDepth, TimeSpan aimSearchTime, TimeSpan maxSearchTime) { m_board = board; m_moveOrganizer = moveOrganizer; m_useBook = useBook; m_maxSearchDepth = searchDepth; m_aimSearchTime = aimSearchTime; m_maxSearchTime = maxSearchTime; }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { //Basic moves for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) if (m_iterator.CurrentPieceColor() != m_color) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } //Castling moves switch (m_color) { case PieceColor.White: if (board.State.WhiteCanCastleLong && board.IsPathClear(Square.E1, Square.A1) && !board.IsSquareAttacted(PieceColor.Black, Square.E1) && !board.IsSquareAttacted(PieceColor.Black, Square.D1)) { moves.Add(new CastlingMove(board, Square.E1, Square.C1)); } if (board.State.WhiteCanCastleShort && board.IsPathClear(Square.E1, Square.H1) && !board.IsSquareAttacted(PieceColor.Black, Square.E1) && !board.IsSquareAttacted(PieceColor.Black, Square.F1)) { moves.Add(new CastlingMove(board, Square.E1, Square.G1)); } break; case PieceColor.Black: if (board.State.BlackCanCastleLong && board.IsPathClear(Square.E8, Square.A8) && !board.IsSquareAttacted(PieceColor.White, Square.E8) && !board.IsSquareAttacted(PieceColor.White, Square.D8)) { moves.Add(new CastlingMove(board, Square.E8, Square.C8)); } if (board.State.BlackCanCastleShort && board.IsPathClear(Square.E8, Square.H8) && !board.IsSquareAttacted(PieceColor.White, Square.E8) && !board.IsSquareAttacted(PieceColor.White, Square.F8)) { moves.Add(new CastlingMove(board, Square.E8, Square.G8)); } break; } } }
/// <summary> /// Initializes a new instance of the Game class. /// </summary> /// <param name="board">A board holding the layout this game will be initialized with. If this parameter is null a standard layout will be created.</param> /// <param name="clockConfiguration">The type of clock to use for this game.</param> public Game(Board board, ClockConfiguration clockConfiguration) { m_board = (board == null) ? new Board() : new Board(board); m_possibleMoves = new MoveOrganizer(); m_undoMoveHistory = new Stack<Move>(); m_redoMoveHistory = new Stack<Move>(); SetClockConfiguration(clockConfiguration); HandleGameHasChanged(); }
/// <summary> /// Initializes a new instance of the Game class. /// </summary> /// <param name="board">A board holding the layout this game will be initialized with. If this parameter is null a standard layout will be created.</param> /// <param name="clockConfiguration">The type of clock to use for this game.</param> public Game(Board board, ClockConfiguration clockConfiguration) { m_board = (board == null) ? new Board() : new Board(board); m_possibleMoves = new MoveOrganizer(); m_undoMoveHistory = new Stack <Move>(); m_redoMoveHistory = new Stack <Move>(); SetClockConfiguration(clockConfiguration); HandleGameHasChanged(); }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < KNIGHT_MOVES; ++i) { m_iterator.Reset(board, location, m_directions[i]); m_iterator.Next(m_directions[i + 0]); m_iterator.Next(m_directions[i + 1]); if (m_iterator.Next(m_directions[i + 2])) { if (m_iterator.CurrentPieceColor() != m_color) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next(m_directions[(i + 0) % m_directions.Length]) && m_iterator.Next(m_directions[(i + 1) % m_directions.Length]) && m_iterator.Next(m_directions[(i + 2) % m_directions.Length])) { if (m_iterator.CurrentPieceColor() != m_color) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < KNIGHT_MOVES; ++i) { m_iterator.Reset(board, location, m_directions[i]); m_iterator.Next(m_directions[i + 0]); m_iterator.Next(m_directions[i + 1]); if (m_iterator.Next(m_directions[i + 2])) { if (m_iterator.CurrentPieceColor() != m_color) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next(m_directions[(i + 0) % m_directions.Length]) && m_iterator.Next(m_directions[(i + 1) % m_directions.Length]) && m_iterator.Next(m_directions[(i + 2) % m_directions.Length])) { if (m_iterator.CurrentPieceColor() != m_color) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } } }
/// <summary> /// Generates valid moves on piece level for all pieces on the board and adds them to moves. /// </summary> /// <remarks> /// Valid moves on piece level are moves that for the isolated piece is valid. Such a move might /// however on board level still be invalid if the move puts its own king in check. /// </remarks> /// <param name="moves">The MoveOrganizer where generated moves are added.</param> public void GeneratePseudoLegalMoves(MoveOrganizer moves) { switch (State.ColorToPlay) { case PieceColor.White: foreach (Square square in m_whiteLocationList) { IFlyweightPiece piece = m_pieceFactory.GetFlyweightPiece(this[square]); piece.GenerateMoves(this, square, moves); } break; case PieceColor.Black: foreach (Square square in m_blackLocationList) { IFlyweightPiece piece = m_pieceFactory.GetFlyweightPiece(this[square]); piece.GenerateMoves(this, square, moves); } break; } }
/// <summary> /// Makes computer think. When the move to play as been decided the /// "MoveFound" event is raised. /// </summary> /// <param name="board">The board to find a move for.</param> /// <param name="moveOrganizer">List of possible moves for the current position on board.</param> /// <param name="useBook">May the engine use the opening book when selecting a move.</param> /// <param name="maxSearchDepth">Maximum AlphaBeta depth to search. Must be equal to, or larger then one.</param> /// <param name="maxSearchTime">Time before search is stoppen.</param> /// <param name="clockTime">The remaining time of the clock.</param> public void Think(Board board, MoveOrganizer moveOrganizer, bool useBook, int maxSearchDepth, TimeSpan maxSearchTime, TimeSpan clockTime) { if (!m_thinking) { m_waitHandle.Reset(); m_thinking = true; TimeSpan calculatedAimTime = m_timeControl.CalculateAimedSearchTime(clockTime); TimeSpan calculatedMaxTime = m_timeControl.CalculateMaxSearchTime(clockTime); if (calculatedMaxTime > maxSearchTime) { calculatedMaxTime = maxSearchTime; } if (calculatedAimTime > calculatedMaxTime) { calculatedAimTime = calculatedMaxTime; } m_workerThread.RunWorkerAsync(new ThreadParam(board, moveOrganizer, useBook, maxSearchDepth, calculatedAimTime, calculatedMaxTime)); } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); while (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } else { if (m_iterator.CurrentPieceColor() != m_color) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } } } } }
/// <summary> /// Instantiates a new instance of the "ThreadParam" class. /// </summary> /// <param name="moveOrganizer">Collection of moves to evaluate and carry out search for.</param> /// <param name="searchDepth">Depth to search.</param> /// <param name="searchTime">Time to search. Actual search will typically be a little more.</param> public ThreadParam(MoveOrganizer moveOrganizer, int searchDepth, int searchTime) { m_moveOrganizer = moveOrganizer; m_maxSearchDepth = searchDepth; m_searchTime = searchTime; }
/// <summary> /// Instantiates an instance of the enumerator. /// </summary> /// <param name="organizer">The "MoveOrganizer" this enumerator iterates.</param> public MoveOrganizerEnumerator(MoveOrganizer organizer) { m_organizer = organizer; m_index = -1; }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { //Non hitting moves m_iterator.Reset(board, location, m_directions[0]); if (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None) { switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black non hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White non hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic non hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } //Two squares forward opening move if (Board.Rank(m_iterator.CurrentSquare()) == moveAgainRow) { m_iterator.Next(); if (m_iterator.CurrentPiece() == Piece.None) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } } //Hitting moves to the left and right for (int i = 1; i < m_directions.Length; ++i) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) { if (m_iterator.CurrentPieceColor() == m_opponentColor) { switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } } } } //EnPassant moves if (Math.Abs(board.State.EnPassantTarget - location) == 1) { switch (m_color) { case PieceColor.White: moves.Add(new Move(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) + 1), board.State.EnPassantTarget)); break; case PieceColor.Black: moves.Add(new Move(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) - 1), board.State.EnPassantTarget)); break; } } } }
/// <summary> /// Makes computer think. When the move to play as been decided the /// "MoveFound" event is raised. /// </summary> /// <param name="board">The board to find a move for.</param> /// <param name="moveOrganizer">List of possible moves for the current position on board.</param> /// <param name="useBook">May the engine use the opening book when selecting a move.</param> /// <param name="maxSearchDepth">Maximum AlphaBeta depth to search. Must be equal to, or larger then one.</param> /// <param name="maxSearchTime">Time before search is stoppen.</param> /// <param name="clockTime">The remaining time of the clock.</param> public void Think(Board board, MoveOrganizer moveOrganizer, bool useBook, int maxSearchDepth, TimeSpan maxSearchTime, TimeSpan clockTime) { if (!m_thinking) { m_waitHandle.Reset(); m_thinking = true; TimeSpan calculatedAimTime = m_timeControl.CalculateAimedSearchTime(clockTime); TimeSpan calculatedMaxTime = m_timeControl.CalculateMaxSearchTime(clockTime); if (calculatedMaxTime > maxSearchTime) calculatedMaxTime = maxSearchTime; if (calculatedAimTime > calculatedMaxTime) calculatedAimTime = calculatedMaxTime; m_workerThread.RunWorkerAsync(new ThreadParam(board, moveOrganizer, useBook, maxSearchDepth, calculatedAimTime, calculatedMaxTime)); } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None && (m_iterator.CurrentDirection() == Direction.Up || m_iterator.CurrentDirection() == Direction.Down)) { //Non hitting moves switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black non hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White non hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic non hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } if ((Board.Rank(m_iterator.CurrentSquare()) == 2 && m_iterator.CurrentDirection() == Direction.Up) || (Board.Rank(m_iterator.CurrentSquare()) == 5 && m_iterator.CurrentDirection() == Direction.Down)) { //Two squares forward opening move m_iterator.Next(); if (m_iterator.CurrentPiece() == Piece.None) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } else if (m_iterator.CurrentPiece() != Piece.None && m_iterator.CurrentPieceColor() != m_color && m_iterator.CurrentDirection() != Direction.Up && m_iterator.CurrentDirection() != Direction.Down) { //Hitting moves switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } } } } //EnPassant moves if (board.State.EnPassantTarget != Square.None && Math.Abs(board.State.EnPassantTarget - location) == 1 && Board.Rank(board.State.EnPassantTarget) == Board.Rank(location)) { switch (m_color) { case PieceColor.White: moves.Add(new EnPassantCaptureMove(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) + 1))); break; case PieceColor.Black: moves.Add(new EnPassantCaptureMove(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) - 1))); break; } } } }
public Move Query(Board board, MoveOrganizer moveOrganizer) { int totalQuaryVal = 0; m_queryMoves.Clear(); foreach (Move move in moveOrganizer) { if (move.Execute(board)) { int currentQueryVal = 0; if (board.State.NonHitAndPawnMovesPlayed < 100 && board.BoardHistoryFrequency() < 3 && m_positionTable.TryGetValue(board.BoardHash(false), out currentQueryVal)) { totalQuaryVal += currentQueryVal; m_queryMoves.Add(new QueryEntry(move, currentQueryVal)); } move.UnExecute(board); } } //select a move using probabilety based on the quary value int selectValueCurrent = 0; int selectValueTarget = (int)Math.Round(m_moveSelector.NextDouble() * totalQuaryVal); for (int i = 0; i < m_queryMoves.Count; ++i) { selectValueCurrent += m_queryMoves[i].QueryScore; if (selectValueCurrent >= selectValueTarget) { OutputWriter.Write("Book moves: " + m_queryMoves.Count + ", Selecting: " + Math.Round((float)m_queryMoves[i].QueryScore / (float)totalQuaryVal, 6)); return m_queryMoves[i].QueryMove; } } return null; }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done by a move when its carried out. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { //Non hitting moves m_iterator.Reset(board, location, m_directions[0]); if (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None) { switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black non hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White non hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic non hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } //Two squares forward opening move if (Board.Rank(m_iterator.CurrentSquare()) == moveAgainRow) { m_iterator.Next(); if (m_iterator.CurrentPiece() == Piece.None) moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } //Hitting moves to the left and right for (int i = 1; i < m_directions.Length; ++i) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) { if (m_iterator.CurrentPieceColor() == m_opponentColor) { switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White hitting promotion move moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new Move(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } } } } //EnPassant moves if (Math.Abs(board.State.EnPassantTarget - location) == 1) { switch (m_color) { case PieceColor.White: moves.Add(new Move(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) + 1), board.State.EnPassantTarget)); break; case PieceColor.Black: moves.Add(new Move(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) - 1), board.State.EnPassantTarget)); break; } } } }
/// <summary> /// Generate moves a FlyweightPiece can make. /// This method does not varifies if a move puts its own king in check. /// This is done in MoveOrganizer when adding a move. /// </summary> /// <param name="board">Board to generate moves for.</param> /// <param name="location">Location of the piece.</param> /// <param name="moves">Container class to which all generated moves are added.</param> public void GenerateMoves(Board board, Square location, MoveOrganizer moves) { if (m_color == board.State.ColorToPlay) { for (int i = 0; i < m_directions.Length; i++) { m_iterator.Reset(board, location, m_directions[i]); if (m_iterator.Next()) { if (m_iterator.CurrentPiece() == Piece.None && (m_iterator.CurrentDirection() == Direction.Up || m_iterator.CurrentDirection() == Direction.Down)) { //Non hitting moves switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black non hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White non hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic non hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } if ((Board.Rank(m_iterator.CurrentSquare()) == 2 && m_iterator.CurrentDirection() == Direction.Up) || (Board.Rank(m_iterator.CurrentSquare()) == 5 && m_iterator.CurrentDirection() == Direction.Down)) { //Two squares forward opening move m_iterator.Next(); if (m_iterator.CurrentPiece() == Piece.None) { moves.Add(new Move(board, location, m_iterator.CurrentSquare())); } } } else if (m_iterator.CurrentPiece() != Piece.None && m_iterator.CurrentPieceColor() != m_color && m_iterator.CurrentDirection() != Direction.Up && m_iterator.CurrentDirection() != Direction.Down) { //Hitting moves switch (Board.Rank(m_iterator.CurrentSquare())) { case 0: //Black hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.BlackRook)); break; case 7: //White hitting promotion move moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteBishop)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteKnight)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteQueen)); moves.Add(new PawnPromotionMove(board, location, m_iterator.CurrentSquare(), Piece.WhiteRook)); break; default: //Basic hitting move moves.Add(new Move(board, location, m_iterator.CurrentSquare())); break; } } } } //EnPassant moves if (board.State.EnPassantTarget != Square.None && Math.Abs(board.State.EnPassantTarget - location) == 1 && Board.Rank(board.State.EnPassantTarget) == Board.Rank(location)) { switch (m_color) { case PieceColor.White: moves.Add(new EnPassantCaptureMove(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) + 1))); break; case PieceColor.Black: moves.Add(new EnPassantCaptureMove(board, location, Board.Position(Board.File(board.State.EnPassantTarget), Board.Rank(location) - 1))); break; } } } }