public void MakeNullMove() { NullMoves++; if (ColorToMove == Color.White) { MovesCount++; } _enPassants.Push(EnPassant); _hashes.Push(Hash); if (EnPassant != 0) { var enPassantRank = BitOperations.BitScan(EnPassant) % 8; Hash = ZobristHashing.ToggleEnPassant(Hash, enPassantRank); EnPassant = 0; } ColorToMove = ColorOperations.Invert(ColorToMove); Hash = ZobristHashing.ChangeSide(Hash); }
public void MakeMove(Move move) { var pieceType = PieceTable[move.From]; var enemyColor = ColorOperations.Invert(ColorToMove); if (ColorToMove == Color.White) { MovesCount++; } _castlings.Push(Castling); _hashes.Push(Hash); _pawnHashes.Push(PawnHash); _enPassants.Push(EnPassant); _irreversibleMovesCounts.Push(IrreversibleMovesCount); if (pieceType == Piece.Pawn || move.IsCapture() || move.IsCastling()) { IrreversibleMovesCount = 0; } else { IrreversibleMovesCount++; } if (EnPassant != 0) { var enPassantRank = BitOperations.BitScan(EnPassant) % 8; Hash = ZobristHashing.ToggleEnPassant(Hash, enPassantRank); EnPassant = 0; } if (move.IsSinglePush()) { MovePiece(ColorToMove, pieceType, move.From, move.To); Hash = ZobristHashing.MovePiece(Hash, ColorToMove, pieceType, move.From, move.To); if (pieceType == Piece.Pawn) { PawnHash = ZobristHashing.MovePiece(PawnHash, ColorToMove, pieceType, move.From, move.To); } } else if (move.IsDoublePush()) { MovePiece(ColorToMove, pieceType, move.From, move.To); Hash = ZobristHashing.MovePiece(Hash, ColorToMove, pieceType, move.From, move.To); PawnHash = ZobristHashing.MovePiece(PawnHash, ColorToMove, pieceType, move.From, move.To); var enPassantField = ColorToMove == Color.White ? 1ul << move.To - 8 : 1ul << move.To + 8; var enPassantFieldIndex = BitOperations.BitScan(enPassantField); EnPassant |= enPassantField; Hash = ZobristHashing.ToggleEnPassant(Hash, enPassantFieldIndex % 8); } else if (move.IsEnPassant()) { var enemyPieceField = ColorToMove == Color.White ? (byte)(move.To - 8) : (byte)(move.To + 8); var killedPiece = PieceTable[enemyPieceField]; RemovePiece(enemyColor, killedPiece, enemyPieceField); Hash = ZobristHashing.AddOrRemovePiece(Hash, enemyColor, killedPiece, enemyPieceField); PawnHash = ZobristHashing.AddOrRemovePiece(PawnHash, enemyColor, killedPiece, enemyPieceField); MovePiece(ColorToMove, pieceType, move.From, move.To); Hash = ZobristHashing.MovePiece(Hash, ColorToMove, pieceType, move.From, move.To); PawnHash = ZobristHashing.MovePiece(PawnHash, ColorToMove, pieceType, move.From, move.To); _killedPieces.Push(killedPiece); } else if (move.IsCapture()) { var killedPiece = PieceTable[move.To]; RemovePiece(enemyColor, killedPiece, move.To); Hash = ZobristHashing.AddOrRemovePiece(Hash, enemyColor, killedPiece, move.To); if (killedPiece == Piece.Pawn) { PawnHash = ZobristHashing.AddOrRemovePiece(PawnHash, enemyColor, killedPiece, move.To); } else if (killedPiece == Piece.Rook) { switch (move.To) { case 0: { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteShort); Castling &= ~Castling.WhiteShort; break; } case 7: { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteLong); Castling &= ~Castling.WhiteLong; break; } case 56: { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackShort); Castling &= ~Castling.BlackShort; break; } case 63: { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackLong); Castling &= ~Castling.BlackLong; break; } } } if (move.IsPromotion()) { var promotionPiece = GetPromotionPiece(move.Flags); RemovePiece(ColorToMove, pieceType, move.From); Hash = ZobristHashing.AddOrRemovePiece(Hash, ColorToMove, pieceType, move.From); PawnHash = ZobristHashing.AddOrRemovePiece(PawnHash, ColorToMove, pieceType, move.From); AddPiece(ColorToMove, promotionPiece, move.To); Hash = ZobristHashing.AddOrRemovePiece(Hash, ColorToMove, promotionPiece, move.To); _promotedPieces.Push(promotionPiece); } else { MovePiece(ColorToMove, pieceType, move.From, move.To); Hash = ZobristHashing.MovePiece(Hash, ColorToMove, pieceType, move.From, move.To); if (pieceType == Piece.Pawn) { PawnHash = ZobristHashing.MovePiece(PawnHash, ColorToMove, pieceType, move.From, move.To); } } _killedPieces.Push(killedPiece); } else if (move.IsCastling()) { // Short castling if (move.IsKingCastling()) { if (ColorToMove == Color.White) { MovePiece(Color.White, Piece.King, 3, 1); MovePiece(Color.White, Piece.Rook, 0, 2); Hash = ZobristHashing.MovePiece(Hash, Color.White, Piece.King, 3, 1); Hash = ZobristHashing.MovePiece(Hash, Color.White, Piece.Rook, 0, 2); } else { MovePiece(Color.Black, Piece.King, 59, 57); MovePiece(Color.Black, Piece.Rook, 56, 58); Hash = ZobristHashing.MovePiece(Hash, Color.Black, Piece.King, 59, 57); Hash = ZobristHashing.MovePiece(Hash, Color.Black, Piece.Rook, 56, 58); } } // Long castling else { if (ColorToMove == Color.White) { MovePiece(Color.White, Piece.King, 3, 5); MovePiece(Color.White, Piece.Rook, 7, 4); Hash = ZobristHashing.MovePiece(Hash, Color.White, Piece.King, 3, 5); Hash = ZobristHashing.MovePiece(Hash, Color.White, Piece.Rook, 7, 4); } else { MovePiece(Color.Black, Piece.King, 59, 61); MovePiece(Color.Black, Piece.Rook, 63, 60); Hash = ZobristHashing.MovePiece(Hash, Color.Black, Piece.King, 59, 61); Hash = ZobristHashing.MovePiece(Hash, Color.Black, Piece.Rook, 63, 60); } } if (ColorToMove == Color.White) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteShort); Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteLong); Castling &= ~Castling.WhiteCastling; } else { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackShort); Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackLong); Castling &= ~Castling.BlackCastling; } CastlingDone[ColorToMove] = true; } else if (move.IsPromotion()) { var promotionPiece = GetPromotionPiece(move.Flags); RemovePiece(ColorToMove, pieceType, move.From); Hash = ZobristHashing.AddOrRemovePiece(Hash, ColorToMove, pieceType, move.From); PawnHash = ZobristHashing.AddOrRemovePiece(PawnHash, ColorToMove, pieceType, move.From); AddPiece(ColorToMove, promotionPiece, move.To); Hash = ZobristHashing.AddOrRemovePiece(Hash, ColorToMove, promotionPiece, move.To); _promotedPieces.Push(promotionPiece); } if (pieceType == Piece.King && !move.IsCastling()) { if (ColorToMove == Color.White) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteShort); Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteLong); Castling &= ~Castling.WhiteCastling; } else { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackShort); Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackLong); Castling &= ~Castling.BlackCastling; } } else if (pieceType == Piece.Rook && Castling != 0) { if (move.From == 0) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteShort); Castling &= ~Castling.WhiteShort; } else if (move.From == 7) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.WhiteLong); Castling &= ~Castling.WhiteLong; } else if (move.From == 56) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackShort); Castling &= ~Castling.BlackShort; } else if (move.From == 63) { Hash = ZobristHashing.RemoveCastlingFlag(Hash, Castling, Castling.BlackLong); Castling &= ~Castling.BlackLong; } } ColorToMove = enemyColor; Hash = ZobristHashing.ChangeSide(Hash); }