/// <summary> /// Does the current position match the specified variation? /// </summary> /// <param name="strVariation"> the iteration and the variation. Ex: "5 Rb4b5 Pf4f5 Pe5f6" </param> /// <param name="iPly"> number positive or 0 of halfmove. Do not confuse with iDepth </param> /// <param name="moveThis"> the current move at the beginning of the research </param> /// <param name="intSearchDepth">Search depth.</param> /// <param name="intMaxSearchDepth">Max search depth.</param> /// <returns> true if the variation is recognized otherwise false </returns> /// <remarks> /// Must be called after moveThis.DoMove() in AlphaBeta /// </remarks> private static bool DebugMatchLine( string strVariation, int iPly, Move moveThis, int intSearchDepth, int intMaxSearchDepth) { const int iSAN_LENGTH = 5; // Length of Abbreviation of the piece + From square + To square if (m_iDbgLevel == iPly) { // Is the level of depth of the variation reached? if (m_strDbgLine.Length == 0) { // Interpret dynamically the variation // In PlayerDebug version, strVariation contains unambiguous descriptive moves int indPos = 0; // Evaluate the number of iteration and parse the variation while (char.IsNumber(strVariation[indPos])) { indPos++; } m_iDbgIteration = Convert.ToInt32(strVariation.Substring(0, indPos)); m_strDbgLine = strVariation.Substring(indPos); // Parse the variation m_strDbgLine = m_strDbgLine.Replace(" ", string.Empty); // removing all whitespaces m_strDbgLine = m_strDbgLine.Replace("x", string.Empty); // removing all "x" } if (intSearchDepth == m_iDbgIteration) { // Number of iteration of AlphaBeta at the top level int indPiece = iPly * iSAN_LENGTH; // Index where begins the notation of the move int iLenVar = m_strDbgLine.Length; string strMoveDescr = moveThis.Piece.Abbreviation + moveThis.From.Name + moveThis.To.Name; if ((indPiece <= iLenVar - iSAN_LENGTH) && (strMoveDescr == m_strDbgLine.Substring(indPiece, iSAN_LENGTH))) { if (++m_iDbgLevel == iLenVar / iSAN_LENGTH) { // Number of moves in the variation m_iDbgLevel = intMaxSearchDepth + 1; // Do not recall PlayerDebug utility BoardDebug.DebugDisplay(); // Display the current position in the "Output Window" Debug.WriteLine("\nPosition after: " + strVariation); return true; // The current position matches the wished variation } } } } return false; }
public void RecordPossibleKillerMoveTest() { int Ply = 10; KillerMoves.Clear(); Piece piece = new Piece(Piece.PieceNames.Bishop, null, 0, 0, Piece.PieceIdentifierCodes.BlackKingsBishop); Move move1 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 20); KillerMoves.RecordPossibleKillerMove(Ply, move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsNull(KillerMoves.RetrieveB(Ply)); Move move2 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 10); KillerMoves.RecordPossibleKillerMove(Ply, move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move2); Move move3 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(4), Board.GetSquare(5), null, 0, 15); KillerMoves.RecordPossibleKillerMove(Ply, move3); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move3); Move move4 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(6), Board.GetSquare(7), null, 0, 30); KillerMoves.RecordPossibleKillerMove(Ply, move4); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move4); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move1); // Start again KillerMoves.Clear(); Move move5 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(16), Board.GetSquare(17), null, 0, 200); KillerMoves.RecordPossibleKillerMove(Ply, move5); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move5); Assert.IsNull(KillerMoves.RetrieveB(Ply)); Move move6 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(18), Board.GetSquare(19), null, 0, 300); KillerMoves.RecordPossibleKillerMove(Ply, move6); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move6); Assert.IsTrue(KillerMoves.RetrieveB(Ply) == move5); }
/// <summary> /// Move the piece to a new square. /// </summary> /// <param name="moveName"> /// The move name. /// </param> /// <param name="square"> /// The square. /// </param> /// <returns> /// Move made. /// </returns> public Move Move(Move.MoveNames moveName, Square square) { Square squarepieceCaptured = square; if (moveName == Model.Move.MoveNames.EnPassent) { // Override when en passent squarepieceCaptured = Board.GetSquare(square.Ordinal - this.Player.PawnForwardOffset); } Board.HashCodeA ^= this.HashCodeA; // Un-XOR current piece position Board.HashCodeB ^= this.HashCodeB; // Un-XOR current piece position if (this.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= this.HashCodeA; Board.PawnHashCodeB ^= this.HashCodeB; } Move move = new Move( Game.TurnNo, this.LastMoveTurnNo, moveName, this, this.Square, square, squarepieceCaptured.Piece, squarepieceCaptured.Piece == null ? -1 : squarepieceCaptured.Piece.Player.Pieces.IndexOf(squarepieceCaptured.Piece), 0); if (square.Piece != null) { if (squarepieceCaptured.Piece != null) { Board.HashCodeA ^= squarepieceCaptured.Piece.HashCodeA; // un-XOR the piece taken Board.HashCodeB ^= squarepieceCaptured.Piece.HashCodeB; // un-XOR the piece taken if (squarepieceCaptured.Piece.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= squarepieceCaptured.Piece.HashCodeA; Board.PawnHashCodeB ^= squarepieceCaptured.Piece.HashCodeB; } //TODO: aCapturinf Pice Here. -> SIL squarepieceCaptured.Piece.Capture(); } } Game.TurnNo++; this.Square.Piece = null; square.Piece = this; this.Square = square; this.LastMoveTurnNo = Game.TurnNo; this.NoOfMoves++; Piece pieceRook; switch (moveName) { case Model.Move.MoveNames.CastleKingSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(7, 0) : Board.GetPiece(7, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square.Piece = null; pieceRook.LastMoveTurnNo = Game.TurnNo; pieceRook.NoOfMoves++; Board.GetSquare(5, square.Rank).Piece = pieceRook; pieceRook.Square = Board.GetSquare(5, square.Rank); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; this.Player.HasCastled = true; break; case Model.Move.MoveNames.CastleQueenSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(0, 0) : Board.GetPiece(0, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square.Piece = null; pieceRook.LastMoveTurnNo = Game.TurnNo; pieceRook.NoOfMoves++; Board.GetSquare(3, square.Rank).Piece = pieceRook; pieceRook.Square = Board.GetSquare(3, square.Rank); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; this.Player.HasCastled = true; break; case Model.Move.MoveNames.PawnPromotionQueen: { this.Promote(PieceNames.Queen); break; } case Model.Move.MoveNames.PawnPromotionRook: { this.Promote(PieceNames.Rook); break; } case Model.Move.MoveNames.PawnPromotionBishop: { this.Promote(PieceNames.Bishop); break; } case Model.Move.MoveNames.PawnPromotionKnight: { this.Promote(PieceNames.Knight); break; } case Model.Move.MoveNames.EnPassent: { Board.HashCodeA ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeA; Board.HashCodeB ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeB; Board.PawnHashCodeA ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeA; Board.PawnHashCodeB ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeB; Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).Capture(); // Take enemy pawn that is now behind us break; } } Board.HashCodeA ^= this.HashCodeA; // XOR piece into new piece position Board.HashCodeB ^= this.HashCodeB; // XOR piece into new piece position if (this.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= this.HashCodeA; Board.PawnHashCodeB ^= this.HashCodeB; } move.IsInCheck = move.Piece.Player.IsInCheck; move.IsEnemyInCheck = move.Piece.Player.OpposingPlayer.IsInCheck; move.HashCodeA = Board.HashCodeA; move.HashCodeB = Board.HashCodeB; Game.MoveHistory.Add(move); if (move.Piece.Player.CanClaimThreeMoveRepetitionDraw) { Board.HashCodeA ^= 31; Board.HashCodeB ^= 29; move.HashCodeA = Board.HashCodeA; move.HashCodeB = Board.HashCodeB; move.IsThreeMoveRepetition = true; } return move; }
/// <summary> /// Move the piece to a new square, after testing that the move is valid. /// </summary> /// <param name="moveName"> /// The move name. /// </param> /// <param name="square"> /// The square. /// </param> /// <returns> /// Move made, or null if move is not valid. /// </returns> public Move TestAndMakeMove(Move.MoveNames moveName, Square square) { return null; }
/// <summary> /// Undo the specified move. /// </summary> /// <param name="move"> /// Move to undo. /// </param> public static void Undo(Move move) { Board.HashCodeA ^= move.To.Piece.HashCodeA; // un_XOR the piece from where it was previously moved to Board.HashCodeB ^= move.To.Piece.HashCodeB; // un_XOR the piece from where it was previously moved to if (move.Piece.Name == Piece.PieceNames.Pawn) { Board.PawnHashCodeA ^= move.To.Piece.HashCodeA; Board.PawnHashCodeB ^= move.To.Piece.HashCodeB; } move.Piece.Square = move.From; // Set piece board location move.From.Piece = move.Piece; // Set piece on board move.Piece.LastMoveTurnNo = move.LastMoveTurnNo; move.Piece.NoOfMoves--; if (move.Name != MoveNames.EnPassent) { move.To.Piece = move.PieceCaptured; // Return piece taken } else { move.To.Piece = null; // Blank square where this pawn was Board.GetSquare(move.To.Ordinal - move.Piece.Player.PawnForwardOffset).Piece = move.PieceCaptured; // Return En Passent pawn taken } if (move.PieceCaptured != null) { move.PieceCaptured.Uncapture(move.PieceCapturedOrdinal); Board.HashCodeA ^= move.PieceCaptured.HashCodeA; // XOR back into play the piece that was taken Board.HashCodeB ^= move.PieceCaptured.HashCodeB; // XOR back into play the piece that was taken if (move.PieceCaptured.Name == Piece.PieceNames.Pawn) { Board.PawnHashCodeA ^= move.PieceCaptured.HashCodeA; Board.PawnHashCodeB ^= move.PieceCaptured.HashCodeB; } } Piece pieceRook; switch (move.Name) { case MoveNames.CastleKingSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(5, 0) : Board.GetPiece(5, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square = Board.GetSquare(7, move.Piece.Square.Rank); pieceRook.LastMoveTurnNo = move.LastMoveTurnNo; pieceRook.NoOfMoves--; Board.GetSquare(7, move.Piece.Square.Rank).Piece = pieceRook; Board.GetSquare(5, move.Piece.Square.Rank).Piece = null; move.Piece.Player.HasCastled = false; Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; break; case MoveNames.CastleQueenSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(3, 0) : Board.GetPiece(3, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square = Board.GetSquare(0, move.Piece.Square.Rank); pieceRook.LastMoveTurnNo = move.LastMoveTurnNo; pieceRook.NoOfMoves--; Board.GetSquare(0, move.Piece.Square.Rank).Piece = pieceRook; Board.GetSquare(3, move.Piece.Square.Rank).Piece = null; move.Piece.Player.HasCastled = false; Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; break; case MoveNames.PawnPromotionQueen: case MoveNames.PawnPromotionRook: case MoveNames.PawnPromotionBishop: case MoveNames.PawnPromotionKnight: move.Piece.Demote(); break; } Board.HashCodeA ^= move.From.Piece.HashCodeA; // XOR the piece back into the square it moved back to Board.HashCodeB ^= move.From.Piece.HashCodeB; // XOR the piece back into the square it moved back to if (move.From.Piece.Name == Piece.PieceNames.Pawn) { Board.PawnHashCodeA ^= move.From.Piece.HashCodeA; Board.PawnHashCodeB ^= move.From.Piece.HashCodeB; } if (move.IsThreeMoveRepetition) { Board.HashCodeA ^= 31; Board.HashCodeB ^= 29; } Game.TurnNo--; Game.MoveHistory.RemoveLast(); }
/// <summary> /// Move the piece to a new square. /// </summary> /// <param name="moveName"> /// The move name. /// </param> /// <param name="square"> /// The square. /// </param> /// <returns> /// Move made. /// </returns> public Move Move(Move.MoveNames moveName, Square square) { Square squarepieceCaptured = square; if (moveName == Model.Move.MoveNames.EnPassent) { // Override when en passent squarepieceCaptured = Board.GetSquare(square.Ordinal - this.Player.PawnForwardOffset); } Board.HashCodeA ^= this.HashCodeA; // Un-XOR current piece position Board.HashCodeB ^= this.HashCodeB; // Un-XOR current piece position if (this.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= this.HashCodeA; Board.PawnHashCodeB ^= this.HashCodeB; } Move move = new Move( Game.TurnNo, this.LastMoveTurnNo, moveName, this, this.Square, square, squarepieceCaptured.Piece, squarepieceCaptured.Piece == null ? -1 : squarepieceCaptured.Piece.Player.Pieces.IndexOf(squarepieceCaptured.Piece), 0); if (square.Piece != null) { if (squarepieceCaptured.Piece != null) { Board.HashCodeA ^= squarepieceCaptured.Piece.HashCodeA; // un-XOR the piece taken Board.HashCodeB ^= squarepieceCaptured.Piece.HashCodeB; // un-XOR the piece taken if (squarepieceCaptured.Piece.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= squarepieceCaptured.Piece.HashCodeA; Board.PawnHashCodeB ^= squarepieceCaptured.Piece.HashCodeB; } squarepieceCaptured.Piece.Capture(); } } Game.TurnNo++; this.Square.Piece = null; square.Piece = this; this.Square = square; this.LastMoveTurnNo = Game.TurnNo; this.NoOfMoves++; Piece pieceRook; switch (moveName) { case Model.Move.MoveNames.CastleKingSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(7, 0) : Board.GetPiece(7, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square.Piece = null; pieceRook.LastMoveTurnNo = Game.TurnNo; pieceRook.NoOfMoves++; Board.GetSquare(5, square.Rank).Piece = pieceRook; pieceRook.Square = Board.GetSquare(5, square.Rank); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; this.Player.HasCastled = true; break; case Model.Move.MoveNames.CastleQueenSide: pieceRook = move.Piece.Player.Colour == Player.PlayerColourNames.White ? Board.GetPiece(0, 0) : Board.GetPiece(0, 7); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; pieceRook.Square.Piece = null; pieceRook.LastMoveTurnNo = Game.TurnNo; pieceRook.NoOfMoves++; Board.GetSquare(3, square.Rank).Piece = pieceRook; pieceRook.Square = Board.GetSquare(3, square.Rank); Board.HashCodeA ^= pieceRook.HashCodeA; Board.HashCodeB ^= pieceRook.HashCodeB; this.Player.HasCastled = true; break; case Model.Move.MoveNames.PawnPromotionQueen: this.Promote(PieceNames.Queen); break; case Model.Move.MoveNames.PawnPromotionRook: this.Promote(PieceNames.Rook); break; case Model.Move.MoveNames.PawnPromotionBishop: this.Promote(PieceNames.Bishop); break; case Model.Move.MoveNames.PawnPromotionKnight: this.Promote(PieceNames.Knight); break; case Model.Move.MoveNames.EnPassent: Board.HashCodeA ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeA; Board.HashCodeB ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeB; Board.PawnHashCodeA ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeA; Board.PawnHashCodeB ^= Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).HashCodeB; Board.GetPiece(this.Square.Ordinal - this.Player.PawnForwardOffset).Capture(); // Take enemy pawn that is now behind us break; } Board.HashCodeA ^= this.HashCodeA; // XOR piece into new piece position Board.HashCodeB ^= this.HashCodeB; // XOR piece into new piece position if (this.Name == PieceNames.Pawn) { Board.PawnHashCodeA ^= this.HashCodeA; Board.PawnHashCodeB ^= this.HashCodeB; } move.IsInCheck = move.Piece.Player.IsInCheck; move.IsEnemyInCheck = move.Piece.Player.OpposingPlayer.IsInCheck; move.HashCodeA = Board.HashCodeA; move.HashCodeB = Board.HashCodeB; Game.MoveHistory.Add(move); if (move.Piece.Player.CanClaimThreeMoveRepetitionDraw) { Board.HashCodeA ^= 31; Board.HashCodeB ^= 29; move.HashCodeA = Board.HashCodeA; move.HashCodeB = Board.HashCodeB; move.IsThreeMoveRepetition = true; } return move; }
/// <summary> /// Send move. /// </summary> /// <param name="move"> /// The move. /// </param> public static void SendMove(Move move) { if (Active) { SendOutputMessage("move " + move.From.Name + move.To.Name); } }
/// <summary> /// Add a move node to the save game XML document. /// </summary> /// <param name="xmldoc"> Xml document representing the save game file. </param> /// <param name="xmlnodeGame"> Parent game xmlnode. </param> /// <param name="move"> Move to append to the save game Xml document. </param> private static void AddSaveGameNode(XmlDocument xmldoc, XmlElement xmlnodeGame, Move move) { XmlElement xmlnodeMove = xmldoc.CreateElement("Move"); xmlnodeGame.AppendChild(xmlnodeMove); xmlnodeMove.SetAttribute("MoveNo", move.MoveNo.ToString(CultureInfo.InvariantCulture)); xmlnodeMove.SetAttribute("Name", move.Name.ToString()); xmlnodeMove.SetAttribute("From", move.From.Name); xmlnodeMove.SetAttribute("To", move.To.Name); xmlnodeMove.SetAttribute("SecondsElapsed", Convert.ToInt32(move.TimeStamp.TotalSeconds).ToString(CultureInfo.InvariantCulture)); }
/// <summary> /// Make the specified move. For internal use only. /// </summary> /// <param name="moveName"> The move name. </param> /// <param name="piece"> The piece to move. </param> /// <param name="square"> The square to move to. </param> private static void MakeAMoveInternal(Move.MoveNames moveName, Piece piece, Square square) { MoveRedoList.Clear(); Move move = piece.Move(moveName, square); move.EnemyStatus = move.Piece.Player.OpposingPlayer.Status; PlayerToPlay.Clock.Stop(); MoveHistory.Last.TimeStamp = PlayerToPlay.Clock.TimeElapsed; if (PlayerToPlay.Intellegence == Player.PlayerIntellegenceNames.Computer) { WinBoard.SendMove(move); if (!PlayerToPlay.OpposingPlayer.CanMove) { if (PlayerToPlay.OpposingPlayer.IsInCheckMate) { WinBoard.SendCheckMate (); } else if (!PlayerToPlay.OpposingPlayer.IsInCheck) { WinBoard.SendCheckStaleMate (); } } else if (PlayerToPlay.OpposingPlayer.CanClaimThreeMoveRepetitionDraw == true) { WinBoard.SendDrawByRepetition (); } else if (PlayerToPlay.OpposingPlayer.CanClaimFiftyMoveDraw == true) { WinBoard.SendDrawByFiftyMoveRule (); } else if (PlayerToPlay.OpposingPlayer.CanClaimInsufficientMaterialDraw == true) { WinBoard.SendDrawByInsufficientMaterial (); } } BroadcastMovedName (move); CheckGameStatus (); PlayerToPlay = PlayerToPlay.OpposingPlayer; PlayerToPlay.Clock.Start(); }
/// <summary> /// Remove a move from this list. /// </summary> /// <param name="move"> /// The move to remove. /// </param> public void Remove(Move move) { this.moves.Remove(move); }
/// <summary> /// Insert a move into this list at the specified index position. /// </summary> /// <param name="intIndex"> /// The index position. /// </param> /// <param name="move"> /// The move to insert. /// </param> public void Insert(int intIndex, Move move) { this.moves.Insert(intIndex, move); }
/// <summary> /// Add a new move to this list. /// </summary> /// <param name="move"> /// The move. /// </param> public void Add(Move move) { this.moves.Add(move); }
/// <summary> /// The add. /// </summary> /// <param name="turnNo"> /// The turn no. /// </param> /// <param name="lastMoveTurnNo"> /// The last move turn no. /// </param> /// <param name="moveName"> /// The move name. /// </param> /// <param name="piece"> /// The piece moving. /// </param> /// <param name="from"> /// The square the peice is moving from. /// </param> /// <param name="to"> /// The square the peice is moving to. /// </param> /// <param name="pieceCaptured"> /// The piece being captured. /// </param> /// <param name="pieceCapturedOrdinal"> /// Ordinal position of the piece being captured. /// </param> /// <param name="score"> /// The positional score. /// </param> public void Add(int turnNo, int lastMoveTurnNo, Move.MoveNames moveName, Piece piece, Square from, Square to, Piece pieceCaptured, int pieceCapturedOrdinal, int score) { this.moves.Add(new Move(turnNo, lastMoveTurnNo, moveName, piece, from, to, pieceCaptured, pieceCapturedOrdinal, score)); }
/// <summary> /// Record a hash new hash entry in the hash table. /// </summary> /// <param name="hashCodeA"> /// Hash Code for Board position A /// </param> /// <param name="hashCodeB"> /// Hash Code for Board position B /// </param> /// <param name="from"> /// From square ordinal. /// </param> /// <param name="to"> /// To square ordinal. /// </param> /// <param name="moveName"> /// The move name. /// </param> /// <param name="colour"> /// The player colour. /// </param> private static unsafe void RecordHash(ulong hashCodeA, ulong hashCodeB, byte from, byte to, Move.MoveNames moveName, Player.PlayerColourNames colour) { if (colour == Player.PlayerColourNames.Black) { hashCodeA |= 0x1; hashCodeB |= 0x1; } else { hashCodeA &= 0xFFFFFFFFFFFFFFFE; hashCodeB &= 0xFFFFFFFFFFFFFFFE; } fixed (HashEntry* phashBase = &HashTableEntries[0]) { HashEntry* phashEntry = phashBase; phashEntry += (uint)(hashCodeA % HashTableSize); phashEntry->HashCodeA = hashCodeA; phashEntry->HashCodeB = hashCodeB; phashEntry->From = from; phashEntry->To = to; phashEntry->MoveName = moveName; } }
/// <summary> /// Break on the variation at the given iteration /// </summary> /// <param name="iPly"> /// the positive or null ply of halfmove. Don't confuse with iDepth /// </param> /// <param name="moveThis"> /// the current move /// </param> /// <returns> /// true if the position is reached otherwise false /// </returns> private static bool DebugMatchVariation(int iPly, Move moveThis, int intSearchDepth, int intMaxSearchDepth) { // Syntax of the string strVariation: <iteration> Move1 Move2 ... #if !SKIP_MATCH_LINE // Add or remove the exclamation mark before SKIP_MATCH_LINE return PlayerDebug.DebugMatchLine("5 Bb3a4 Bc8d7 Ba4xc6 Bd7xc6 Rf1e1 Bf8e7 Bc1d2", iPly, moveThis, intSearchDepth, intMaxSearchDepth); // The variation/line you want to debug! #else return false; // Do not break on the variation #endif // SKIP_MATCH_LINE }
/// <summary> /// Replace the move at ths specified index position with the supplied move. /// </summary> /// <param name="intIndex"> /// The index position to replace. /// </param> /// <param name="moveNew"> /// The new move. /// </param> public void Replace(int intIndex, Move moveNew) { this.moves[intIndex] = moveNew; }
public void SameKillerMoveWithHigherScoreReplacesSlotEntry() { const int Ply = 10; KillerMoves.Clear(); Piece piece = new Piece(Piece.PieceNames.Bishop, null, 0, 0, Piece.PieceIdentifierCodes.BlackKingsBishop); Move move1 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 20); // Add a move KillerMoves.RecordPossibleKillerMove(Ply, move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move1); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 20); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Add same move AGAIN, but with higher score. Move should be replaced, using higher score. Move move2 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 30); KillerMoves.RecordPossibleKillerMove(Ply, move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply) == move2); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Add same move AGAIN, but with LOWER score. No killer moves should be changed Move move3 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(0), Board.GetSquare(1), null, 0, 10); KillerMoves.RecordPossibleKillerMove(Ply, move3); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move2)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsNull(KillerMoves.RetrieveB(Ply)); // Now add a different move, and check it goes in slot B Move move4 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 5); KillerMoves.RecordPossibleKillerMove(Ply, move4); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move3)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 30); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveB(Ply), move4)); Assert.IsTrue(KillerMoves.RetrieveB(Ply).Score == 5); // Now improve score of the move that is in slot B. // Slot B's score should be updated. Slot A should stay the same. // Slot's A & B should be SWAPPED. Move move5 = new Move(0, 0, Move.MoveNames.Standard, piece, Board.GetSquare(2), Board.GetSquare(3), null, 0, 100); KillerMoves.RecordPossibleKillerMove(Ply, move5); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveA(Ply), move5)); Assert.IsTrue(KillerMoves.RetrieveA(Ply).Score == 100); Assert.IsTrue(Move.MovesMatch(KillerMoves.RetrieveB(Ply), move3)); Assert.IsTrue(KillerMoves.RetrieveB(Ply).Score == 30); }
/// <summary> /// The add move to history. /// </summary> /// <param name="move"> /// The move. /// </param> private void AddMoveToHistory(Move move) { string[] lvi = { move.MoveNo.ToString(), move.TimeStamp.Hours.ToString().PadLeft(2, '0') + ":" + move.TimeStamp.Minutes.ToString().PadLeft(2, '0') + ":" + move.TimeStamp.Seconds.ToString().PadLeft(2, '0'), move.Description + (move.PieceCaptured != null ? (" (" + move.PieceCaptured.Name.ToString() + ")") : string.Empty) }; this.lvwMoveHistory.Items.Add(new ListViewItem(lvi)); switch (move.Piece.Player.Colour) { case Player.PlayerColourNames.White: this.lvwMoveHistory.Items[this.lvwMoveHistory.Items.Count - 1].BackColor = Color.White; this.lvwMoveHistory.Items[this.lvwMoveHistory.Items.Count - 1].ForeColor = Color.Blue; break; case Player.PlayerColourNames.Black: this.lvwMoveHistory.Items[this.lvwMoveHistory.Items.Count - 1].BackColor = Color.White; this.lvwMoveHistory.Items[this.lvwMoveHistory.Items.Count - 1].ForeColor = Color.Black; break; } this.lvwMoveHistory.Items[this.lvwMoveHistory.Items.Count - 1].EnsureVisible(); }
/// <summary> /// Make a move. /// </summary> /// <param name="moveName"> The move name. </param> /// <param name="piece"> The piece to move. </param> /// <param name="square"> The square to move to. </param> public static void MakeAMove(Move.MoveNames moveName, Piece piece, Square square) { SuspendPondering(); MakeAMoveInternal(moveName, piece, square); SaveBackup(); SendBoardPositionChangeEvent(); // CheckIfAutoNextMove(); }
/// <summary> /// Determines whether a proposed move is valid. /// </summary> /// <param name="moveProposed"> /// The move proposed. /// </param> /// <returns> /// True if valid. /// </returns> public static bool IsValid(Move moveProposed) { if (moveProposed.Piece != Board.GetPiece(moveProposed.From.Ordinal)) { return false; } Moves movesPossible = new Moves(); moveProposed.Piece.GenerateLazyMoves(movesPossible, Moves.MoveListNames.All); foreach (Move move in movesPossible) { if (moveProposed.Name == move.Name && moveProposed.To.Ordinal == move.To.Ordinal) { return true; } } return false; }
private static void BroadcastMovedName(Move move) { if (OnPlayerMoved != null) { OnPlayerMoved (move); } }
/// <summary> /// Determine where two moves are identical moves. /// </summary> /// <param name="moveA"> /// Move A. /// </param> /// <param name="moveB"> /// Move B. /// </param> /// <returns> /// True if moves match. /// </returns> public static bool MovesMatch(Move moveA, Move moveB) { return moveA != null && moveB != null && moveA.Piece == moveB.Piece && moveA.From == moveB.From && moveA.To == moveB.To && moveA.Name == moveB.Name && ( (moveA.PieceCaptured == null && moveB.PieceCaptured == null) || (moveA.PieceCaptured != null && moveB.PieceCaptured != null && moveA.PieceCaptured == moveB.PieceCaptured)); }
/// <summary> /// Send analyze status. /// </summary> /// <param name="thinkingTime"> /// The thinking time. /// </param> /// <param name="nodes"> /// The nodes. /// </param> /// <param name="ply"> /// The ply. /// </param> /// <param name="movesRemaining"> /// The moves remaining. /// </param> /// <param name="totalMoves"> /// The total moves. /// </param> /// <param name="moveCurrent"> /// The move current. /// </param> private static void SendAnalyzeStatus( TimeSpan thinkingTime, int nodes, int ply, int movesRemaining, int totalMoves, Move moveCurrent) { /* stat01: time nodes ply mvleft mvtot mvname Where: time Elapsed search time in centiseconds (ie: 567 = 5.67 seconds). nodes Nodes searched so far. ply Search depth so far. mvleft Number of moves left to consider at this depth. mvtot Total number of moves to consider. mvname Move currently being considered (SAN or coordinate notation). Optional; added in protocol version 2. Examples: stat01: 1234 30000 7 5 30 stat01: 1234 30000 7 5 30 Nf3 Meaning: After 12.34 seconds, I've searched 7 ply/30000 nodes, there are a total of 30 legal moves, and I have 5 more moves to search before going to depth 8. In the second example, of the 30 legal moves, the one I am currently searching is Nf3. */ if (Active && Game.IsInAnalyseMode) { int intTimeIncentiseconds = Convert.ToInt32(thinkingTime.TotalMilliseconds / 100); SendOutputMessage( "stat01:" + " " + intTimeIncentiseconds.ToString() + " " + nodes.ToString() + " " + ply.ToString() + " " + movesRemaining.ToString() + " " + totalMoves.ToString() + " " + moveCurrent.From.Name + moveCurrent.To.Name); } }