private void MakeCastlingMove(Move move) { var rookSrcIx = CastlingTables.GetCastlingRookSrcIx(move.DstIx); var rookDstIx = CastlingTables.GetCastlingRookDstIx(move.DstIx); MovePiece(move.SourceIx, move.DstIx, SideMoving, PieceType.King); MovePiece(rookSrcIx, rookDstIx, SideMoving, PieceType.Rook); }
public static Position MakeMove(Position shell, Move move, Position parent) { // copy data which doesn't depend on performing the move parent.CopyPieceBitboards(ref shell._pieceBitboards); parent.CopySquares(ref shell._squares); shell.ZobristHash = parent.ZobristHash; shell.Parent = parent; shell._inCheckWhite = null; shell._inCheckBlack = null; shell.SideToMove = parent.SideToMove.Other(); shell.EnPassant = 0; // this gets set for double moves shell.FiftyMoveCounter = CalculateFiftyMoveCounter(parent, move); shell.GamePly = parent.GamePly + 1; shell._historyPly = parent._historyPly + 1; switch (move.MoveType) { case MoveType.Normal | MoveType.Quiet: shell.MakeNormalQuietMove(move); break; case MoveType.Normal | MoveType.Capture: shell.MakeNormalCaptureMove(move); break; case MoveType.DoubleMove | MoveType.Quiet: shell.MakeDoublePawnMove(move); break; case MoveType.EnPassant | MoveType.Capture: shell.MakeEnPassantMove(move); break; case MoveType.Promotion | MoveType.Quiet: shell.MakePromotionQuietMove(move); break; case MoveType.Promotion | MoveType.Capture: shell.MakePromotionCaptureMove(move); break; case MoveType.Castling | MoveType.Quiet: shell.MakeCastlingMove(move); break; default: throw new Exception($"Invalid move type: {move.MoveType}"); } shell.CastlingRights = parent.CastlingRights & CastlingTables.GetCastlingUpdateMask(move); shell._occupiedWhite = shell.CalculateOccupied(Color.White); shell._occupiedBlack = shell.CalculateOccupied(Color.Black); shell._occupied = shell._occupiedWhite | shell._occupiedBlack; shell.ZobristHash ^= ZobristHashing.OtherHashDiff(parent, shell); shell.RepetitionNumber = CalculateRepetitionNumber(shell); return(shell); }
private void GenerateKingCastling(List <Move> moves, Position position) { var castlingDsts = position.CastlingRights & CastlingTables.GetCastlingRightsDstColorMask(position.SideToMove); while (Bits.TryPopLsb(ref castlingDsts, out var dstIx)) { if ((position.GetOccupied() & CastlingTables.GetCastlingEmptySquares(dstIx)) > 0) { continue; } if (position.InCheck(position.SideToMove)) { continue; } bool attacked = false; foreach (var potentiallyAttackedIx in Bits.Enumerate(CastlingTables.GetCastlingAttacks(dstIx))) { if (position.IsAttacked(potentiallyAttackedIx, position.SideToMove)) { attacked = true; break; } } if (attacked) { continue; } // if we still have castling rights, the inbetween squares aren't occupied, we aren't in check, and we aren't castling through or into check, then we should be good to go! int kingIx = Bits.GetLsb(position.GetPieceBitboard(position.SideToMove, PieceType.King)); moves.Add(new Move(MoveType.Castling | MoveType.Quiet, kingIx, dstIx)); } }