internal static ExtMoveArrayWrapper generate_castling( CastlingRight Cr, bool Checks, bool Chess960, Position pos, ExtMoveArrayWrapper moveList, ColorT us, CheckInfo ci) { var KingSide = (Cr == CastlingRight.WHITE_OO || Cr == CastlingRight.BLACK_OO); if (pos.castling_impeded(Cr) || !pos.can_castle(Cr)) { return moveList; } // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. var kfrom = pos.square(PieceType.KING, us); var rfrom = pos.castling_rook_square(Cr); var kto = Square.relative_square(us, KingSide ? Square.SQ_G1 : Square.SQ_C1); var enemies = pos.pieces_Ct(Color.opposite(us)); Debug.Assert(pos.checkers() == 0); var K = Chess960 ? kto > kfrom ? Square.DELTA_W : Square.DELTA_E : KingSide ? Square.DELTA_W : Square.DELTA_E; for (var s = kto; s != kfrom; s += K) { if ((pos.attackers_to(s) & enemies) != 0) { return moveList; } } // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (Chess960 && ((Utils.attacks_bb_PtSBb(PieceType.ROOK, kto, Bitboard.XorWithSquare(pos.pieces(), rfrom)) & pos.pieces_CtPtPt(Color.opposite(us), PieceType.ROOK, PieceType.QUEEN)))!= 0) { return moveList; } var m = Move.make(MoveType.CASTLING, kfrom, rfrom); if (Checks && !pos.gives_check(m, ci)) { return moveList; } moveList.Add(m); return moveList; }
internal SquareT castling_rook_square(CastlingRight cr) { return castlingRookSquare[(int) cr]; }
internal bool castling_impeded(CastlingRight cr) { return (byTypeBB[PieceType.ALL_PIECES] & castlingPath[(int) cr]) != 0; }
internal bool can_castle(CastlingRight cr) { return (st.castlingRights & (int) cr) != 0; }