public void UndoMove(int move) { var fromIndex = MoveUtil.GetFromIndex(move); var toIndex = MoveUtil.GetToIndex(move); var toMask = 1L << toIndex; var fromToMask = (1L << fromIndex) ^ toMask; var sourcePieceIndex = MoveUtil.GetSourcePieceIndex(move); var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move); PopHistoryValues(); // undo move Pieces[ColorToMoveInverse][All] ^= fromToMask; Pieces[ColorToMoveInverse][sourcePieceIndex] ^= fromToMask; PieceIndexes[fromIndex] = sourcePieceIndex; PsqtScore += EvalConstants.Psqt[sourcePieceIndex][ColorToMoveInverse][fromIndex] - EvalConstants.Psqt[sourcePieceIndex][ColorToMoveInverse][toIndex]; switch (sourcePieceIndex) { case Empty: // not necessary but provides a table-index break; case Pawn: PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][fromIndex]; if (MoveUtil.IsPromotion(move)) { Phase += EvalConstants.Phase[MoveUtil.GetMoveType(move)]; MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][MoveUtil.GetMoveType(move)] - MaterialUtil.Values[ColorToMoveInverse][Pawn]; Pieces[ColorToMoveInverse][Pawn] ^= toMask; Pieces[ColorToMoveInverse][MoveUtil.GetMoveType(move)] ^= toMask; PsqtScore += EvalConstants.Psqt[Pawn][ColorToMoveInverse][toIndex] - EvalConstants.Psqt[MoveUtil.GetMoveType(move)][ColorToMoveInverse][toIndex]; } else { PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex]; } break; case King: if (MoveUtil.IsCastlingMove(move)) { CastlingUtil.UncastleRookUpdatePsqt(this, toIndex); } KingIndex[ColorToMoveInverse] = fromIndex; break; } // undo hit switch (attackedPieceIndex) { case Empty: break; case Pawn: if (MoveUtil.IsEpMove(move)) { PieceIndexes[toIndex] = Empty; toIndex += ColorFactor8[ColorToMove]; toMask = Util.PowerLookup[toIndex]; } PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][toIndex]; goto default; // fall-through default: PsqtScore += EvalConstants.Psqt[attackedPieceIndex][ColorToMove][toIndex]; Phase -= EvalConstants.Phase[attackedPieceIndex]; MaterialKey += MaterialUtil.Values[ColorToMove][attackedPieceIndex]; Pieces[ColorToMove][All] |= toMask; Pieces[ColorToMove][attackedPieceIndex] |= toMask; break; } PieceIndexes[toIndex] = attackedPieceIndex; AllPieces = Pieces[ColorToMove][All] | Pieces[ColorToMoveInverse][All]; EmptySpaces = ~AllPieces; ChangeSideToMove(); SetCheckingPinnedAndDiscoPieces(); if (EngineConstants.Assert) { ChessBoardTestUtil.TestValues(this); } }
public bool IsValidMove(int move) { // check piece at from square var fromIndex = MoveUtil.GetFromIndex(move); var fromSquare = Util.PowerLookup[fromIndex]; if ((Pieces[ColorToMove][MoveUtil.GetSourcePieceIndex(move)] & fromSquare) == 0) { return(false); } // check piece at to square var toIndex = MoveUtil.GetToIndex(move); var toSquare = Util.PowerLookup[toIndex]; var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move); if (attackedPieceIndex == 0) { if (PieceIndexes[toIndex] != Empty) { return(false); } } else { if ((Pieces[ColorToMoveInverse][attackedPieceIndex] & toSquare) == 0 && !MoveUtil.IsEpMove(move)) { return(false); } } // check if move is possible switch (MoveUtil.GetSourcePieceIndex(move)) { case Pawn: if (MoveUtil.IsEpMove(move)) { return(toIndex == EpIndex && IsLegalEpMove(fromIndex)); } else { if (ColorToMove == White) { if (fromIndex > toIndex) { return(false); } // 2-move if (toIndex - fromIndex == 16 && (AllPieces & Util.PowerLookup[fromIndex + 8]) != 0) { return(false); } } else { if (fromIndex < toIndex) { return(false); } // 2-move if (fromIndex - toIndex == 16 && (AllPieces & Util.PowerLookup[fromIndex - 8]) != 0) { return(false); } } } break; case Knight: break; case Bishop: // fall-through case Rook: // fall-through case Queen: if ((InBetween[fromIndex][toIndex] & AllPieces) != 0) { return(false); } break; case King: if (!MoveUtil.IsCastlingMove(move)) { return(IsLegalKingMove(move)); } var castlingIndexes = CastlingUtil.GetCastlingIndexes(this); while (castlingIndexes != 0) { if (toIndex == BitOperations.TrailingZeroCount(castlingIndexes)) { return(CastlingUtil.IsValidCastlingMove(this, fromIndex, toIndex)); } castlingIndexes &= castlingIndexes - 1; } return(false); } if ((fromSquare & PinnedPieces) != 0) { if ((PinnedMovement[fromIndex][KingIndex[ColorToMove]] & toSquare) == 0) { return(false); } } if (CheckingPieces == 0) { return(true); } if (attackedPieceIndex == 0) { return(IsLegalNonKingMove(move)); } if (BitOperations.PopCount((ulong)CheckingPieces) == 2) { return(false); } return((toSquare & CheckingPieces) != 0); }
public void DoMove(int move) { MoveCount++; var fromIndex = MoveUtil.GetFromIndex(move); var toIndex = MoveUtil.GetToIndex(move); var toMask = 1L << toIndex; var fromToMask = (1L << fromIndex) ^ toMask; var sourcePieceIndex = MoveUtil.GetSourcePieceIndex(move); var attackedPieceIndex = MoveUtil.GetAttackedPieceIndex(move); if (EngineConstants.Assert) { Assert.IsTrue(move != 0); Assert.IsTrue(attackedPieceIndex != King); Assert.IsTrue(attackedPieceIndex == 0 || (Util.PowerLookup[toIndex] & Pieces[ColorToMove][All]) == 0); Assert.IsTrue(IsValidMove(move)); } PushHistoryValues(); ZobristKey ^= Zobrist.Piece[ColorToMove][sourcePieceIndex][fromIndex] ^ Zobrist.Piece[ColorToMove][sourcePieceIndex][toIndex] ^ Zobrist.SideToMove; if (EpIndex != 0) { ZobristKey ^= Zobrist.EpIndex[EpIndex]; EpIndex = 0; } Pieces[ColorToMove][All] ^= fromToMask; Pieces[ColorToMove][sourcePieceIndex] ^= fromToMask; PieceIndexes[fromIndex] = Empty; PieceIndexes[toIndex] = sourcePieceIndex; PsqtScore += EvalConstants.Psqt[sourcePieceIndex][ColorToMove][toIndex] - EvalConstants.Psqt[sourcePieceIndex][ColorToMove][fromIndex]; switch (sourcePieceIndex) { case Pawn: PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][fromIndex]; if (MoveUtil.IsPromotion(move)) { Phase -= EvalConstants.Phase[MoveUtil.GetMoveType(move)]; MaterialKey += MaterialUtil.Values[ColorToMove][MoveUtil.GetMoveType(move)] - MaterialUtil.Values[ColorToMove][Pawn]; Pieces[ColorToMove][Pawn] ^= toMask; Pieces[ColorToMove][MoveUtil.GetMoveType(move)] |= toMask; PieceIndexes[toIndex] = MoveUtil.GetMoveType(move); ZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][toIndex] ^ Zobrist.Piece[ColorToMove][MoveUtil.GetMoveType(move)][toIndex]; PsqtScore += EvalConstants.Psqt[MoveUtil.GetMoveType(move)][ColorToMove][toIndex] - EvalConstants.Psqt[Pawn][ColorToMove][toIndex]; } else { PawnZobristKey ^= Zobrist.Piece[ColorToMove][Pawn][toIndex]; // 2-move if (InBetween[fromIndex][toIndex] != 0) { if ((StaticMoves.PawnAttacks[ColorToMove][ BitOperations.TrailingZeroCount(InBetween[fromIndex][toIndex])] & Pieces[ColorToMoveInverse][Pawn]) != 0) { EpIndex = BitOperations.TrailingZeroCount(InBetween[fromIndex][toIndex]); ZobristKey ^= Zobrist.EpIndex[EpIndex]; } } } break; case Rook: if (CastlingRights != 0) { ZobristKey ^= Zobrist.Castling[CastlingRights]; CastlingRights = CastlingUtil.GetRookMovedOrAttackedCastlingRights(CastlingRights, fromIndex); ZobristKey ^= Zobrist.Castling[CastlingRights]; } break; case King: KingIndex[ColorToMove] = toIndex; if (CastlingRights != 0) { if (MoveUtil.IsCastlingMove(move)) { CastlingUtil.CastleRookUpdateKeyAndPsqt(this, toIndex); } ZobristKey ^= Zobrist.Castling[CastlingRights]; CastlingRights = CastlingUtil.GetKingMovedCastlingRights(CastlingRights, fromIndex); ZobristKey ^= Zobrist.Castling[CastlingRights]; } break; } // piece hit? switch (attackedPieceIndex) { case Empty: break; case Pawn: if (MoveUtil.IsEpMove(move)) { toIndex += ColorFactor8[ColorToMoveInverse]; toMask = Util.PowerLookup[toIndex]; PieceIndexes[toIndex] = Empty; } PawnZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex]; PsqtScore -= EvalConstants.Psqt[Pawn][ColorToMoveInverse][toIndex]; Pieces[ColorToMoveInverse][All] ^= toMask; Pieces[ColorToMoveInverse][Pawn] ^= toMask; ZobristKey ^= Zobrist.Piece[ColorToMoveInverse][Pawn][toIndex]; MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][Pawn]; break; case Rook: if (CastlingRights != 0) { ZobristKey ^= Zobrist.Castling[CastlingRights]; CastlingRights = CastlingUtil.GetRookMovedOrAttackedCastlingRights(CastlingRights, toIndex); ZobristKey ^= Zobrist.Castling[CastlingRights]; } goto default; // fall-through default: Phase += EvalConstants.Phase[attackedPieceIndex]; PsqtScore -= EvalConstants.Psqt[attackedPieceIndex][ColorToMoveInverse][toIndex]; Pieces[ColorToMoveInverse][All] ^= toMask; Pieces[ColorToMoveInverse][attackedPieceIndex] ^= toMask; ZobristKey ^= Zobrist.Piece[ColorToMoveInverse][attackedPieceIndex][toIndex]; MaterialKey -= MaterialUtil.Values[ColorToMoveInverse][attackedPieceIndex]; break; } AllPieces = Pieces[ColorToMove][All] | Pieces[ColorToMoveInverse][All]; EmptySpaces = ~AllPieces; ChangeSideToMove(); SetCheckingPinnedAndDiscoPieces(); if (EngineConstants.Assert) { ChessBoardTestUtil.TestValues(this); } }