static Cuckoo() { // initialize cuckoo tables CuckooKeys = new HashKey[8192]; CuckooMoves = new Move[8192]; Span <Piece> pieces = stackalloc Piece[] { Enums.Pieces.WhitePawn, Enums.Pieces.WhiteKnight, Enums.Pieces.WhiteBishop, Enums.Pieces.WhiteRook, Enums.Pieces.WhiteQueen, Enums.Pieces.WhiteKing, Enums.Pieces.BlackPawn, Enums.Pieces.BlackKnight, Enums.Pieces.BlackBishop, Enums.Pieces.BlackRook, Enums.Pieces.BlackQueen, Enums.Pieces.BlackKing }; var count = 0; foreach (var pc in pieces) { foreach (var sq1 in BitBoards.AllSquares) { for (var sq2 = sq1 + 1; sq2 <= Enums.Squares.h8; ++sq2) { if ((pc.Type().PseudoAttacks(sq1) & sq2).IsEmpty) { continue; } var move = Move.Create(sq1, sq2); HashKey key = pc.GetZobristPst(sq1) ^ pc.GetZobristPst(sq2) ^ Zobrist.GetZobristSide(); var i = CuckooHashOne(key); while (true) { (CuckooKeys[i], key) = (key, CuckooKeys[i].Key);
/// <summary> /// Updates the hash key depending on a move /// </summary> /// <param name="move">The move the hash key is depending on</param> private void UpdateKey(Move move) { // TODO : Merge with MakeMove to avoid duplicate ifs var pawnKey = State.PawnStructureKey; var key = State.Key ^ pawnKey; pawnKey ^= Zobrist.GetZobristSide(); if (_stateList[PositionIndex - 1].EnPassantSquare != ESquare.none) { key ^= _stateList[PositionIndex - 1].EnPassantSquare.File().GetZobristEnPessant(); } if (State.EnPassantSquare != ESquare.none) { key ^= State.EnPassantSquare.File().GetZobristEnPessant(); } if (move.IsNullMove()) { State.Key = key ^ pawnKey; State.PawnStructureKey = pawnKey; return; } var pawnPiece = move.GetMovingPieceType() == EPieceType.Pawn; var squareTo = move.GetToSquare(); if (move.IsPromotionMove()) { key ^= move.GetPromotedPiece().GetZobristPst(squareTo); } else { if (pawnPiece) { pawnKey ^= move.GetMovingPiece().GetZobristPst(squareTo); } else { key ^= move.GetMovingPiece().GetZobristPst(squareTo); } } if (pawnPiece) { pawnKey ^= move.GetMovingPiece().GetZobristPst(move.GetFromSquare()); if (move.IsEnPassantMove()) { pawnKey ^= move.GetCapturedPiece().GetZobristPst(squareTo + State.SideToMove.PawnPushDistance()); } else if (move.IsCaptureMove()) { pawnKey ^= move.GetCapturedPiece().GetZobristPst(squareTo); } } else { key ^= move.GetMovingPiece().GetZobristPst(move.GetFromSquare()); if (move.IsCaptureMove()) { key ^= move.GetCapturedPiece().GetZobristPst(squareTo); } else if (move.IsCastlelingMove()) { var piece = EPieceType.Rook.MakePiece(Position.State.SideToMove); key ^= piece.GetZobristPst(Position.GetRookCastleFrom(squareTo)); key ^= piece.GetZobristPst(squareTo.GetRookCastleTo()); } } // castling rights if (State.CastlelingRights != _stateList[PositionIndex - 1].CastlelingRights) { key ^= _stateList[PositionIndex - 1].CastlelingRights.GetZobristCastleling(); key ^= State.CastlelingRights.GetZobristCastleling(); } State.Key = key ^ pawnKey; State.PawnStructureKey = pawnKey; }
public KeyGeneratorFixture() { KeyGenerator = new Zobrist(); KeyGenerator.Init(); }
/// <summary> /// Updates the hash key depending on a move /// </summary> /// <param name="move">The move the hash key is depending on</param> private void UpdateKey(Move move) { // TODO : Merge with MakeMove to avoid duplicate ifs var pawnKey = State.PawnStructureKey; var key = State.Key ^ pawnKey; pawnKey ^= Zobrist.GetZobristSide(); if (_stateList[PositionIndex - 1].EnPassantSquare != ESquare.none) { key ^= Zobrist.GetZobristEnPessant(_stateList[PositionIndex - 1].EnPassantSquare.File().AsInt()); } if (State.EnPassantSquare != ESquare.none) { key ^= Zobrist.GetZobristEnPessant(State.EnPassantSquare.File().AsInt()); } if (move.IsNullMove()) { key ^= pawnKey; State.Key = key; State.PawnStructureKey = pawnKey; return; } var pawnPiece = move.GetMovingPieceType() == EPieceType.Pawn; if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetMovingPiece(), move.GetFromSquare()); } else { key ^= Zobrist.GetZobristPst(move.GetMovingPiece(), move.GetFromSquare()); } var squareTo = move.GetToSquare(); if (move.IsPromotionMove()) { key ^= Zobrist.GetZobristPst(move.GetPromotedPiece(), squareTo); } else { if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetMovingPiece(), squareTo); } else { key ^= Zobrist.GetZobristPst(move.GetMovingPiece(), squareTo); } } if (pawnPiece && move.IsEnPassantMove()) { pawnKey ^= Zobrist.GetZobristPst(move.GetCapturedPiece().Type() + (State.SideToMove << 3), squareTo + (State.SideToMove.Side == 0 ? 8 : -8)); } else if (move.IsCaptureMove()) { if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetCapturedPiece(), squareTo); } else { key ^= Zobrist.GetZobristPst(move.GetCapturedPiece(), squareTo); } } else if (move.IsCastlelingMove()) { var piece = (EPieces)(EPieceType.Rook + move.GetSideMask()); key ^= Zobrist.GetZobristPst(piece, Position.GetRookCastleFrom(squareTo)); key ^= Zobrist.GetZobristPst(piece, squareTo.GetRookCastleTo()); } // castleling // castling rights if (State.CastlelingRights != _stateList[PositionIndex - 1].CastlelingRights) { key ^= Zobrist.GetZobristCastleling(_stateList[PositionIndex - 1].CastlelingRights); key ^= Zobrist.GetZobristCastleling(State.CastlelingRights); } key ^= pawnKey; State.Key = key; State.PawnStructureKey = pawnKey; }
/// <summary> /// Apply a FEN string board setup to the board structure. /// </summary> /// <param name="fenString">The string to set</param> /// <param name="validate">If true, the fen string is validated, otherwise not</param> /// <returns> /// 0 = all ok. /// -1 = Error in piece file layout parsing /// -2 = Error in piece rank layout parsing /// -3 = Unknown piece detected /// -4 = Error while parsing moving side /// -5 = Error while parsing castleling /// -6 = Error while parsing en-passant square /// -9 = FEN length exceeding maximum /// </returns> public FenError SetFen(FenData fen, bool validate = false) { if (validate) { Fen.Fen.Validate(fen.Fen.ToString()); } // correctly clear all pieces and invoke possible notification(s) var bb = Occupied; while (bb) { var square = bb.Lsb(); Position.RemovePiece(square, Position.BoardLayout[square.AsInt()]); BitBoards.ResetLsb(ref bb); } var chunk = fen.Chunk(); if (chunk.IsEmpty) { return(new FenError()); } var f = 1; // file (column) var r = 8; // rank (row) Player player; foreach (var c in chunk) { if (char.IsDigit(c)) { f += c - '0'; if (f > 9) { return(new FenError(-1, fen.Index)); } } else if (c == '/') { if (f != 9) { return(new FenError(-2, fen.Index)); } r--; f = 1; } else { var pieceIndex = PieceExtensions.PieceChars.IndexOf(c); if (pieceIndex == -1) { return(new FenError(-3, fen.Index)); } player = char.IsLower(PieceExtensions.PieceChars[pieceIndex]); var square = new Square(r - 1, f - 1); AddPiece(square, player, (EPieceType)pieceIndex); f++; } } // player chunk = fen.Chunk(); if (chunk.IsEmpty || chunk.Length != 1) { return(new FenError(-3, fen.Index)); } player = (chunk[0] != 'w').ToInt(); // castleling chunk = fen.Chunk(); if (!SetupCastleling(chunk)) { return(new FenError(-5, fen.Index)); } // en-passant chunk = fen.Chunk(); if (chunk.Length == 1 || chunk[0] == '-' || !chunk[0].InBetween('a', 'h')) { State.EnPassantSquare = ESquare.none; } else { State.EnPassantSquare = chunk[1].InBetween('3', '6') ? ESquare.none : new Square(chunk[1] - '1', chunk[0] - 'a').Value; } // move number chunk = fen.Chunk(); var moveNum = 0; var halfMoveNum = 0; if (!chunk.IsEmpty) { chunk.ToIntegral(out halfMoveNum); // half move number chunk = fen.Chunk(); chunk.ToIntegral(out moveNum); if (moveNum > 0) { moveNum--; } } PositionIndex = PositionStart = moveNum; Position.State = _stateList[PositionIndex]; State.ReversibleHalfMoveCount = halfMoveNum; State.SideToMove = player; if (player.IsBlack()) { State.Key ^= Zobrist.GetZobristSide(); State.PawnStructureKey ^= Zobrist.GetZobristSide(); } State.Key ^= State.CastlelingRights.GetZobristCastleling(); if (State.EnPassantSquare != ESquare.none) { State.Key ^= State.EnPassantSquare.File().GetZobristEnPessant(); } Position.InCheck = Position.IsAttacked(Position.GetPieceSquare(EPieceType.King, player), ~player); return(0); }
internal static void EvaluateBoardScore(Board board) { if ((int)board.EnPassantPosition == 0 && !board.EndGamePhase) { int?nullable1 = Zobrist.SearchEval(board.ZobristHash); if (nullable1.HasValue) { int?nullable2 = nullable1; int num = 0; if ((nullable2.GetValueOrDefault() == num ? (!nullable2.HasValue ? 1 : 0) : 1) != 0) { board.Score = nullable1.Value; return; } } } board.Score = 0; bool insufficientMaterial = true; if (board.StaleMate || (int)board.FiftyMove >= 50 || (int)board.RepeatedMove >= 3) { return; } if (board.BlackMate) { board.Score = (int)short.MaxValue; } else if (board.WhiteMate) { board.Score = -32767; } else { if (board.BlackCheck) { board.Score += 70; if (board.EndGamePhase) { board.Score += 10; } } else if (board.WhiteCheck) { board.Score -= 70; if (board.EndGamePhase) { board.Score -= 10; } } if (board.BlackCastled) { board.Score -= 50; } if (board.WhiteCastled) { board.Score += 50; } if (board.WhoseMove == ChessPieceColor.White) { board.Score += 10; } else { board.Score -= 10; } byte bishopCount1 = 0; byte bishopCount2 = 0; byte knightCount1 = 0; byte knightCount2 = 0; byte num = 0; Evaluation.blackPawnCount = new short[8]; Evaluation.whitePawnCount = new short[8]; for (byte position = 0; (int)position < 64; ++position) { Square square = board.Squares[(int)position]; if (square.Piece != null) { if (square.Piece.PieceColor == ChessPieceColor.White) { board.Score += Evaluation.EvaluatePieceScore(square, position, board.EndGamePhase, ref knightCount2, ref bishopCount2, ref insufficientMaterial); if (square.Piece.PieceType == ChessPieceType.King && (int)position != 59 && (int)position != 60) { int pawnPos1 = (int)position - 8; board.Score += Evaluation.CheckPawnWall(board, pawnPos1, (int)position); int pawnPos2 = (int)position - 7; board.Score += Evaluation.CheckPawnWall(board, pawnPos2, (int)position); int pawnPos3 = (int)position - 9; board.Score += Evaluation.CheckPawnWall(board, pawnPos3, (int)position); } } else if (square.Piece.PieceColor == ChessPieceColor.Black) { board.Score -= Evaluation.EvaluatePieceScore(square, position, board.EndGamePhase, ref knightCount1, ref bishopCount1, ref insufficientMaterial); if (square.Piece.PieceType == ChessPieceType.King && (int)position != 3 && (int)position != 4) { int pawnPos1 = (int)position + 8; board.Score -= Evaluation.CheckPawnWall(board, pawnPos1, (int)position); int pawnPos2 = (int)position + 7; board.Score -= Evaluation.CheckPawnWall(board, pawnPos2, (int)position); int pawnPos3 = (int)position + 9; board.Score -= Evaluation.CheckPawnWall(board, pawnPos3, (int)position); } } if (square.Piece.PieceType == ChessPieceType.Knight) { ++num; if ((int)num > 1) { insufficientMaterial = false; } } if ((int)bishopCount1 + (int)bishopCount2 > 1) { insufficientMaterial = false; } else if ((int)bishopCount1 + (int)knightCount1 > 1) { insufficientMaterial = false; } else if ((int)bishopCount2 + (int)knightCount2 > 1) { insufficientMaterial = false; } } } if (insufficientMaterial) { board.Score = 0; board.StaleMate = true; board.InsufficientMaterial = true; } else { if (board.EndGamePhase) { if (board.BlackCheck) { board.Score += 10; } else if (board.WhiteCheck) { board.Score -= 10; } } else { if (!board.WhiteCanCastle && !board.WhiteCastled) { board.Score -= 50; } if (!board.BlackCanCastle && !board.BlackCastled) { board.Score += 50; } } if ((int)Evaluation.blackPawnCount[0] >= 1 && (int)Evaluation.blackPawnCount[1] == 0) { board.Score += 12; } if ((int)Evaluation.blackPawnCount[1] >= 1 && (int)Evaluation.blackPawnCount[0] == 0 && (int)Evaluation.blackPawnCount[2] == 0) { board.Score += 14; } if ((int)Evaluation.blackPawnCount[2] >= 1 && (int)Evaluation.blackPawnCount[1] == 0 && (int)Evaluation.blackPawnCount[3] == 0) { board.Score += 16; } if ((int)Evaluation.blackPawnCount[3] >= 1 && (int)Evaluation.blackPawnCount[2] == 0 && (int)Evaluation.blackPawnCount[4] == 0) { board.Score += 20; } if ((int)Evaluation.blackPawnCount[4] >= 1 && (int)Evaluation.blackPawnCount[3] == 0 && (int)Evaluation.blackPawnCount[5] == 0) { board.Score += 20; } if ((int)Evaluation.blackPawnCount[5] >= 1 && (int)Evaluation.blackPawnCount[4] == 0 && (int)Evaluation.blackPawnCount[6] == 0) { board.Score += 16; } if ((int)Evaluation.blackPawnCount[6] >= 1 && (int)Evaluation.blackPawnCount[5] == 0 && (int)Evaluation.blackPawnCount[7] == 0) { board.Score += 14; } if ((int)Evaluation.blackPawnCount[7] >= 1 && (int)Evaluation.blackPawnCount[6] == 0) { board.Score += 12; } if ((int)Evaluation.whitePawnCount[0] >= 1 && (int)Evaluation.whitePawnCount[1] == 0) { board.Score -= 12; } if ((int)Evaluation.whitePawnCount[1] >= 1 && (int)Evaluation.whitePawnCount[0] == 0 && (int)Evaluation.whitePawnCount[2] == 0) { board.Score -= 14; } if ((int)Evaluation.whitePawnCount[2] >= 1 && (int)Evaluation.whitePawnCount[1] == 0 && (int)Evaluation.whitePawnCount[3] == 0) { board.Score -= 16; } if ((int)Evaluation.whitePawnCount[3] >= 1 && (int)Evaluation.whitePawnCount[2] == 0 && (int)Evaluation.whitePawnCount[4] == 0) { board.Score -= 20; } if ((int)Evaluation.whitePawnCount[4] >= 1 && (int)Evaluation.whitePawnCount[3] == 0 && (int)Evaluation.whitePawnCount[5] == 0) { board.Score -= 20; } if ((int)Evaluation.whitePawnCount[5] >= 1 && (int)Evaluation.whitePawnCount[4] == 0 && (int)Evaluation.whitePawnCount[6] == 0) { board.Score -= 16; } if ((int)Evaluation.whitePawnCount[6] >= 1 && (int)Evaluation.whitePawnCount[5] == 0 && (int)Evaluation.whitePawnCount[7] == 0) { board.Score -= 14; } if ((int)Evaluation.whitePawnCount[7] >= 1 && (int)Evaluation.whitePawnCount[6] == 0) { board.Score -= 12; } if ((int)Evaluation.blackPawnCount[0] >= 1 && (int)Evaluation.whitePawnCount[0] == 0) { board.Score -= (int)Evaluation.blackPawnCount[0]; } if ((int)Evaluation.blackPawnCount[1] >= 1 && (int)Evaluation.whitePawnCount[1] == 0) { board.Score -= (int)Evaluation.blackPawnCount[1]; } if ((int)Evaluation.blackPawnCount[2] >= 1 && (int)Evaluation.whitePawnCount[2] == 0) { board.Score -= (int)Evaluation.blackPawnCount[2]; } if ((int)Evaluation.blackPawnCount[3] >= 1 && (int)Evaluation.whitePawnCount[3] == 0) { board.Score -= (int)Evaluation.blackPawnCount[3]; } if ((int)Evaluation.blackPawnCount[4] >= 1 && (int)Evaluation.whitePawnCount[4] == 0) { board.Score -= (int)Evaluation.blackPawnCount[4]; } if ((int)Evaluation.blackPawnCount[5] >= 1 && (int)Evaluation.whitePawnCount[5] == 0) { board.Score -= (int)Evaluation.blackPawnCount[5]; } if ((int)Evaluation.blackPawnCount[6] >= 1 && (int)Evaluation.whitePawnCount[6] == 0) { board.Score -= (int)Evaluation.blackPawnCount[6]; } if ((int)Evaluation.blackPawnCount[7] >= 1 && (int)Evaluation.whitePawnCount[7] == 0) { board.Score -= (int)Evaluation.blackPawnCount[7]; } if ((int)Evaluation.whitePawnCount[0] >= 1 && (int)Evaluation.blackPawnCount[1] == 0) { board.Score += (int)Evaluation.whitePawnCount[0]; } if ((int)Evaluation.whitePawnCount[1] >= 1 && (int)Evaluation.blackPawnCount[1] == 0) { board.Score += (int)Evaluation.whitePawnCount[1]; } if ((int)Evaluation.whitePawnCount[2] >= 1 && (int)Evaluation.blackPawnCount[2] == 0) { board.Score += (int)Evaluation.whitePawnCount[2]; } if ((int)Evaluation.whitePawnCount[3] >= 1 && (int)Evaluation.blackPawnCount[3] == 0) { board.Score += (int)Evaluation.whitePawnCount[3]; } if ((int)Evaluation.whitePawnCount[4] >= 1 && (int)Evaluation.blackPawnCount[4] == 0) { board.Score += (int)Evaluation.whitePawnCount[4]; } if ((int)Evaluation.whitePawnCount[5] >= 1 && (int)Evaluation.blackPawnCount[5] == 0) { board.Score += (int)Evaluation.whitePawnCount[5]; } if ((int)Evaluation.whitePawnCount[6] >= 1 && (int)Evaluation.blackPawnCount[6] == 0) { board.Score += (int)Evaluation.whitePawnCount[6]; } if ((int)Evaluation.whitePawnCount[7] >= 1 && (int)Evaluation.blackPawnCount[7] == 0) { board.Score += (int)Evaluation.whitePawnCount[7]; } if ((int)board.EnPassantPosition != 0 || board.EndGamePhase || board.Score == 0) { return; } Zobrist.AddEntryEval(board.ZobristHash, board.Score); } } }
/// <summary> /// Apply a FEN string board setup to the board structure. /// *EXCEPTION FREE FUNCTION* /// </summary> /// <param name="fenString">The string to set</param> /// <param name="validate">If true, the fen string is validated, otherwise not</param> /// <returns> /// 0 = all ok. /// -1 = Error in piece file layout parsing /// -2 = Error in piece rank layout parsing /// -3 = Unknown piece detected /// -4 = Error while parsing moving side /// -5 = Error while parsing castleling /// -6 = Error while parsing en-passant square /// -9 = FEN length exceeding maximum /// </returns> public FenError SetFen(string fenString, bool validate = false) { // TODO : Replace with stream at some point // basic validation, catches format errors if (validate) { Fen.Fen.Validate(fenString); } foreach (var square in Occupied) { Position.RemovePiece(square, Position.BoardLayout[square.AsInt()]); } //for (var i = 0; i <= PositionIndex; i++) // _stateList[i].Clear(); Position.Clear(); var fen = new FenData(fenString); Player player; var c = fen.GetAdvance; var f = 1; // file (column) var r = 8; // rank (row) // map pieces to data structure while (c != 0 && !(f == 9 && r == 1)) { if (char.IsDigit(c)) { f += c - '0'; if (f > 9) { return(new FenError(-1, fen.Index)); } c = fen.GetAdvance; continue; } if (c == '/') { if (f != 9) { return(new FenError(-2, fen.Index)); } r--; f = 1; c = fen.GetAdvance; continue; } var pieceIndex = PieceExtensions.PieceChars.IndexOf(c); if (pieceIndex == -1) { return(new FenError(-3, fen.Index)); } player = char.IsLower(PieceExtensions.PieceChars[pieceIndex]); var square = new Square(r - 1, f - 1); AddPiece(square, player, (EPieceType)pieceIndex); c = fen.GetAdvance; f++; } if (!Fen.Fen.IsDelimiter(c)) { return(new FenError(-4, fen.Index)); } c = fen.GetAdvance; player = c == 'w' ? 0 : 1; if (player == -1) { return(new FenError(-4, fen.Index)); } if (!Fen.Fen.IsDelimiter(fen.GetAdvance)) { return(new FenError(-5, fen.Index)); } if (!SetupCastleling(fen)) { return(new FenError(-5, fen.Index)); } if (!Fen.Fen.IsDelimiter(fen.GetAdvance)) { return(new FenError(-6, fen.Index)); } State.EnPassantSquare = fen.GetEpSquare(); // temporary.. the whole method should be using this, but this will do for now. var moveCounters = fen.Fen.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var first = moveCounters[moveCounters.Length - 2]; var second = moveCounters[moveCounters.Length - 1]; second.ToIntegral(out int number); if (number > 0) { number -= 1; } PositionIndex = PositionStart = number; first.ToIntegral(out number); State = Position.State = _stateList[PositionIndex]; State.ReversibleHalfMoveCount = number; State.SideToMove = player; if (player.IsBlack()) { var zobristSide = Zobrist.GetZobristSide(); State.Key ^= zobristSide; State.PawnStructureKey ^= zobristSide; } State.Key ^= Zobrist.GetZobristCastleling(State.CastlelingRights); if (State.EnPassantSquare != ESquare.none) { State.Key ^= Zobrist.GetZobristEnPessant(State.EnPassantSquare.File().AsInt()); } Position.InCheck = Position.IsAttacked(Position.GetPieceSquare(EPieceType.King, State.SideToMove), ~State.SideToMove); //State.GenerateMoves(true); return(0); }
public void HashSide() => Value ^= Zobrist.GetZobristSide();
public void Hash(int enPassantFile) => Value ^= Zobrist.GetZobristEnPessant(enPassantFile);
public void Hash(ECastleling castleling, ERank rank) => Value ^= Zobrist.GetZobristCastleling((int)rank);
public void Hash(Piece piece, Square square) => Value ^= Zobrist.GetZobristPst(piece, square);
public void Xor(ref Zobrist zobr1, ref Zobrist zobr2) { key = zobr1.key ^ zobr2.key; lock0 = zobr1.lock0 ^ zobr2.lock0; lock1 = zobr1.lock1 ^ zobr2.lock1; }
/// <summary> /// 执行异或操作 /// </summary> /// <param name="zobr"></param> public void Xor(ref Zobrist zobr) { key ^= zobr.key; lock0 ^= zobr.lock0; lock1 ^= zobr.lock1; }
public static void Init() { Zobrist.Init(); Bitboard.Init(); }
internal Board(string fen) : this() { byte num1 = 0; byte num2 = 0; this.WhiteCastled = true; this.BlackCastled = true; byte num3 = 0; this.WhoseMove = ChessPieceColor.White; if (fen.Contains("a3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)40; } else if (fen.Contains("b3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)41; } else if (fen.Contains("c3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)42; } else if (fen.Contains("d3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)43; } else if (fen.Contains("e3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)44; } else if (fen.Contains("f3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)45; } else if (fen.Contains("g3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)46; } else if (fen.Contains("h3")) { this.EnPassantColor = ChessPieceColor.White; this.EnPassantPosition = (byte)47; } if (fen.Contains("a6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)16; } else if (fen.Contains("b6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)17; } else if (fen.Contains("c6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)18; } else if (fen.Contains("d6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)19; } else if (fen.Contains("e6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)20; } else if (fen.Contains("f6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)21; } else if (fen.Contains("g6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)22; } else if (fen.Contains("h6")) { this.EnPassantColor = ChessPieceColor.Black; this.EnPassantPosition = (byte)23; } if (fen.Contains(" w ")) { this.WhoseMove = ChessPieceColor.White; } if (fen.Contains(" b ")) { this.WhoseMove = ChessPieceColor.Black; } foreach (char ch in fen) { if ((int)num1 < 64 && (int)num2 == 0) { if ((int)ch == 49 && (int)num1 < 63) { ++num1; } else if ((int)ch == 50 && (int)num1 < 62) { num1 += (byte)2; } else if ((int)ch == 51 && (int)num1 < 61) { num1 += (byte)3; } else if ((int)ch == 52 && (int)num1 < 60) { num1 += (byte)4; } else if ((int)ch == 53 && (int)num1 < 59) { num1 += (byte)5; } else if ((int)ch == 54 && (int)num1 < 58) { num1 += (byte)6; } else if ((int)ch == 55 && (int)num1 < 57) { num1 += (byte)7; } else if ((int)ch == 56 && (int)num1 < 56) { num1 += (byte)8; } else if ((int)ch == 80) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Pawn, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 78) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Knight, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 66) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Bishop, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 82) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Rook, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 81) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Queen, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 75) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.King, ChessPieceColor.White); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 112) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Pawn, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 110) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Knight, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 98) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Bishop, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 114) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Rook, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 113) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.Queen, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch == 107) { this.Squares[(int)num1].Piece = new Piece(ChessPieceType.King, ChessPieceColor.Black); this.Squares[(int)num1].Piece.Moved = true; ++num1; } else if ((int)ch != 47 && (int)ch == 32) { ++num2; } } else if ((int)ch == 75) { if (this.Squares[60].Piece != null && this.Squares[60].Piece.PieceType == ChessPieceType.King) { this.Squares[60].Piece.Moved = false; } if (this.Squares[63].Piece != null && this.Squares[63].Piece.PieceType == ChessPieceType.Rook) { this.Squares[63].Piece.Moved = false; } this.WhiteCastled = false; } else if ((int)ch == 81) { if (this.Squares[60].Piece != null && this.Squares[60].Piece.PieceType == ChessPieceType.King) { this.Squares[60].Piece.Moved = false; } if (this.Squares[56].Piece != null && this.Squares[56].Piece.PieceType == ChessPieceType.Rook) { this.Squares[56].Piece.Moved = false; } this.WhiteCastled = false; } else if ((int)ch == 107) { if (this.Squares[4].Piece != null && this.Squares[4].Piece.PieceType == ChessPieceType.King) { this.Squares[4].Piece.Moved = false; } if (this.Squares[7].Piece != null && this.Squares[7].Piece.PieceType == ChessPieceType.Rook) { this.Squares[7].Piece.Moved = false; } this.BlackCastled = false; } else if ((int)ch == 113) { if (this.Squares[4].Piece != null && this.Squares[4].Piece.PieceType == ChessPieceType.King) { this.Squares[4].Piece.Moved = false; } if (this.Squares[0].Piece != null && this.Squares[0].Piece.PieceType == ChessPieceType.Rook) { this.Squares[0].Piece.Moved = false; } this.BlackCastled = false; } else if ((int)ch == 32) { ++num3; } else if ((int)ch == 49 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 1); } else if ((int)ch == 50 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 2); } else if ((int)ch == 51 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 3); } else if ((int)ch == 52 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 4); } else if ((int)ch == 53 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 5); } else if ((int)ch == 54 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 6); } else if ((int)ch == 55 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 7); } else if ((int)ch == 56 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 8); } else if ((int)ch == 57 && (int)num3 == 4) { this.FiftyMove = (byte)((int)this.FiftyMove * 10 + 9); } else if ((int)ch == 48 && (int)num3 == 4) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 0); } else if ((int)ch == 49 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 1); } else if ((int)ch == 50 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 2); } else if ((int)ch == 51 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 3); } else if ((int)ch == 52 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 4); } else if ((int)ch == 53 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 5); } else if ((int)ch == 54 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 6); } else if ((int)ch == 55 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 7); } else if ((int)ch == 56 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 8); } else if ((int)ch == 57 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 9); } else if ((int)ch == 48 && (int)num3 == 5) { this.MoveCount = (int)(byte)(this.MoveCount * 10 + 0); } } Zobrist.InitiateZobristTable(); this.ZobristHash = Zobrist.CalculateZobristHash(this); }
internal static ulong UpdateZobristHash(ulong hash, MoveContent move, ChessPieceColor whosMove, bool pawnPromote) { hash = Zobrist.GetHashResult((int)move.MovingPiecePrimary.SrcPosition, move.MovingPiecePrimary.PieceType, move.MovingPiecePrimary.PieceColor, hash); if (move.MovingPieceSecondary.PieceType != ChessPieceType.None) { hash = Zobrist.GetHashResult((int)move.MovingPieceSecondary.SrcPosition, move.MovingPieceSecondary.PieceType, move.MovingPieceSecondary.PieceColor, hash); hash = Zobrist.GetHashResult((int)move.MovingPieceSecondary.DstPosition, move.MovingPieceSecondary.PieceType, move.MovingPieceSecondary.PieceColor, hash); if (move.MovingPieceSecondary.PieceColor == ChessPieceColor.White) { hash ^= Zobrist.ZobristTable[770]; } else { hash ^= Zobrist.ZobristTable[771]; } } if (move.TakenPiece.PieceType != ChessPieceType.None) { hash = Zobrist.GetHashResult((int)move.TakenPiece.Position, move.TakenPiece.PieceType, move.TakenPiece.PieceColor, hash); } hash = !pawnPromote?Zobrist.GetHashResult((int)move.MovingPiecePrimary.DstPosition, move.MovingPiecePrimary.PieceType, move.MovingPiecePrimary.PieceColor, hash) : Zobrist.GetHashResult((int)move.MovingPiecePrimary.DstPosition, ChessPieceType.Queen, move.MovingPiecePrimary.PieceColor, hash); if (whosMove == ChessPieceColor.White) { hash ^= Zobrist.ZobristTable[769]; hash ^= Zobrist.ZobristTable[768]; } else { hash ^= Zobrist.ZobristTable[768]; hash ^= Zobrist.ZobristTable[769]; } return(hash); }