public void SubmitNullMove() { states.Push(new BoardState { lastMove = null, positionKey = positionKey, enPassentSquare = EnPassentSquare, castelingRights = CastelingRights, materialKey = materialKey, WhitePawnBitboard = WhitePawnBitboard, BlackPawnBitboard = BlackPawnBitboard, WhitePiecesBitboard = WhitePiecesBitboard, BlackPiecesBitboard = BlackPiecesBitboard }); //No EnPassent in NullMovePruning EnPassentSquare = -1; Ply++; Us = Them; Them = Piece.OtherColor(Us); ZobristKey.ColorChanged(ref positionKey); }
//We assume the submitted move is legal public void SubmitMove(Move move) { states.Push(new BoardState //Save the current state to the history { lastMove = move, positionKey = positionKey, materialKey = materialKey, enPassentSquare = EnPassentSquare, castelingRights = CastelingRights, WhitePawnBitboard = WhitePawnBitboard, BlackPawnBitboard = BlackPawnBitboard, WhitePiecesBitboard = WhitePiecesBitboard, BlackPiecesBitboard = BlackPiecesBitboard }); Ply++; board[move.Start] = Piece.NONE; pieceList[move.MovedPiece].Remove(move.Start); if (move.Promotion != Piece.NONE) { var promotedPiece = (Piece.COLOR_MASK & move.MovedPiece) | move.Promotion; board[move.Target] = promotedPiece; pieceList[promotedPiece].Add(move.Target); //Update material key MaterialKey.RemovePiece(move.MovedPiece, ref materialKey); MaterialKey.AddPiece(promotedPiece, ref materialKey); //Update Zobrist key ZobristKey.PieceMoved(move.MovedPiece, move.Start, -1, ref positionKey); ZobristKey.PieceMoved(promotedPiece, move.Target, -1, ref positionKey); //Update piece and pawn Bitboards if (Us == Piece.WHITE) { WhitePawnBitboard &= ~(1ul << move.Start); WhitePiecesBitboard |= 1ul << move.Target; } else // Us == Piece.BLACK { BlackPawnBitboard &= ~(1ul << move.Start); BlackPiecesBitboard |= 1ul << move.Target; } } else { board[move.Target] = move.MovedPiece; pieceList[move.MovedPiece].Add(move.Target); //material key need not be updated, piece just moved //Update Zobrist key ZobristKey.PieceMoved(move.MovedPiece, move.Start, move.Target, ref positionKey); //Update Pawn and pieces Bitboards if (move.MovedPiece == (Piece.WHITE | Piece.PAWN)) { WhitePawnBitboard &= ~(1ul << move.Start); WhitePawnBitboard |= 1ul << move.Target; } else if (move.MovedPiece == (Piece.BLACK | Piece.PAWN)) { BlackPawnBitboard &= ~(1ul << move.Start); BlackPawnBitboard |= 1ul << move.Target; } else if (Us == Piece.WHITE) { WhitePiecesBitboard &= ~(1ul << move.Start); WhitePiecesBitboard |= 1ul << move.Target; } else { BlackPiecesBitboard &= ~(1ul << move.Start); BlackPiecesBitboard |= 1ul << move.Target; } } if (move.CapturedPiece != Piece.NONE) { pieceList[move.CapturedPiece].Remove(move.Target); //Update material key MaterialKey.RemovePiece(move.CapturedPiece, ref materialKey); //Update Zobrist Key ZobristKey.PieceMoved(move.CapturedPiece, move.Target, -1, ref positionKey); //Update pawn bitboards if (move.CapturedPiece == (Piece.BLACK | Piece.PAWN)) { BlackPawnBitboard &= ~(1ul << move.Target); } else if (move.CapturedPiece == (Piece.WHITE | Piece.PAWN)) { WhitePawnBitboard &= ~(1ul << move.Target); } else if (Us == Piece.WHITE) { BlackPiecesBitboard &= ~(1ul << move.Target); } else { WhitePiecesBitboard &= ~(1ul << move.Target); } } //EnPassent related stuff if (move.IsDoublePawnMove) { //set the enPassent square to the square behind the target EnPassentSquare = Us == Piece.WHITE ? move.Target - 8 : move.Target + 8; } else { //reset the enPassent square EnPassentSquare = -1; } if (move.IsEnPassent) { //Remove the pawn on the advanced square var captureSquare = Us == Piece.WHITE ? move.Target - 8 : move.Target + 8; //rank of start + file of target pieceList[Piece.PAWN | Them].Remove(captureSquare); board[captureSquare] = Piece.NONE; //Update material key MaterialKey.RemovePiece(Piece.PAWN | Them, ref materialKey); //Update Zobrist key ZobristKey.PieceMoved(Piece.PAWN | Them, captureSquare, -1, ref positionKey); //Update pawn bitboards if (Us == Piece.WHITE) { BlackPawnBitboard &= ~(1ul << captureSquare); } else //Us == BLACK { WhitePawnBitboard &= ~(1ul << captureSquare); } } //Casteling related stuff if (move.MovedPiece == (Piece.WHITE | Piece.KING)) { //Revoke whites casteling rights after a king move CastelingRights &= BLACK_KINGSIDE_CASTLE | BLACK_QUEENSIDE_CASTLE; } else if (move.MovedPiece == (Piece.BLACK | Piece.KING)) { //Revoke blacks casteling rights after a king move CastelingRights &= WHITE_KINGSIDE_CASTLE | WHITE_QUEENSIDE_CASTLE; } else { //Revoke whites casteling rights if the correpsonding rook moved or was captured if (move.Start == 0 || move.Target == 0) //A1 { CastelingRights &= ~WHITE_QUEENSIDE_CASTLE; } if (move.Start == 7 || move.Target == 7) //H1 { CastelingRights &= ~WHITE_KINGSIDE_CASTLE; } //Revoke blacks casteling rights if the correpsonding rook moved or was captured if (move.Start == 7 * 8 || move.Target == 7 * 8) //A8 { CastelingRights &= ~BLACK_QUEENSIDE_CASTLE; } if (move.Start == 7 * 8 + 7 || move.Target == 7 * 8 + 7) //H8 { CastelingRights &= ~BLACK_KINGSIDE_CASTLE; } } if (move.IsCasteling) { //We need not revoke casteling rights after castle, this has already happend //We only need to move the rook int rookStart, rookEnd; switch (move.Target) { case 2: //C1 rookStart = 0; //A1 rookEnd = 3; //D1 break; case 6: //G1 rookStart = 7; //H1 rookEnd = 5; //F1 break; case 7 * 8 + 2: //C8 rookStart = 7 * 8; //A8 rookEnd = 7 * 8 + 3; //D8 break; case 7 * 8 + 6: //G8 rookStart = 7 * 8 + 7; //H8 rookEnd = 7 * 8 + 5; //F8 break; default: throw new Exception("Illegal casteling move: " + move.ToAlgebraicNotation()); } var pieceType = Piece.ROOK | Us; board[rookStart] = Piece.NONE; board[rookEnd] = pieceType; pieceList[pieceType].Remove(rookStart); pieceList[pieceType].Add(rookEnd); ZobristKey.PieceMoved(pieceType, rookStart, rookEnd, ref positionKey); if (Us == Piece.WHITE) { WhitePiecesBitboard &= ~(1ul << rookStart); WhitePiecesBitboard |= 1ul << rookEnd; } else { BlackPiecesBitboard &= ~(1ul << rookStart); BlackPiecesBitboard |= 1ul << rookEnd; } } Us = Them; Them = Piece.OtherColor(Us); ZobristKey.ColorChanged(ref positionKey); }