private static void generate_castle( int Side, bool Checks, Position pos, MoveStack[] ms, ref int mpos, int us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side)) == 0)) { return; } // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. var kfrom = pos.king_square(us); var rfrom = pos.castle_rook_square(us, Side); var kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); var enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); int K = pos.chess960 ? kto > kfrom ? -1 : 1 : Side == CastlingSideC.KING_SIDE ? -1 : 1; for (Square s = kto; s != kfrom; s += (Square)K) { if ((pos.attackers_to(s) & enemies) != 0) { return; } } // 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 (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) { return; } var m = Utils.make(kfrom, rfrom, MoveTypeC.CASTLING); if (Checks) { var ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); var givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) { return; } } ms[mpos++].move = m; }
private static void generate_castle(CastlingSide Side, bool OnlyChecks, Position pos, MoveStack[] ms, ref int mpos, Color us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side))==0) ) return; // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); Square rfrom = pos.castle_rook_square(us, Side); Square kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); Bitboard enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); for (Square s = Math.Min(kfrom, kto), e = Math.Max(kfrom, kto); s <= e; s++) if (s != kfrom // We are not in check && ((pos.attackers_to(s) & enemies) != 0)) return; // 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 (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) return; Move m = Utils.make_castle(kfrom, rfrom); if (OnlyChecks) { CheckInfo ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); bool givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) return; } ms[mpos++].move = m; }
// book_key() returns the PolyGlot hash key of the given position private static UInt64 book_key(Position pos) { UInt64 key = 0; Bitboard b = pos.occupied_squares; while (b != 0) { // Piece offset is at 64 * polyPiece where polyPiece is defined as: // BP = 0, WP = 1, BN = 2, WN = 3, ... BK = 10, WK = 11 Square s = Utils.pop_1st_bit(ref b); Piece p = pos.piece_on(s); int polyPiece = 2 * (Utils.type_of(p) - 1) + (Utils.color_of(p) == ColorC.WHITE ? 1 : 0); key ^= PolyGlotRandoms[ZobPieceOffset + (64 * polyPiece + s)]; } b = (ulong)pos.can_castle_CR(CastleRightC.ALL_CASTLES); while (b != 0) key ^= PolyGlotRandoms[ZobCastleOffset + Utils.pop_1st_bit(ref b)]; if (pos.st.epSquare != SquareC.SQ_NONE) key ^= PolyGlotRandoms[ZobEnPassantOffset + Utils.file_of(pos.st.epSquare)]; if (pos.sideToMove == ColorC.WHITE) key ^= PolyGlotRandoms[ZobTurnOffset + 0]; return key; }
/// flip() flips position with the white and black sides reversed. This /// is only useful for debugging especially for finding evaluation symmetry bugs. internal void flip() { // Make a copy of current position before to start changing Position pos = new Position(this); clear(); sideToMove = pos.sideToMove ^ 1; thisThread = pos.this_thread(); nodes = pos.nodes; chess960 = pos.chess960; startPosPly = pos.startpos_ply_counter(); for (Square s = SquareC.SQ_A1; s <= SquareC.SQ_H8; s++) if (!pos.is_empty(s)) put_piece((pos.piece_on(s) ^ 8), Utils.flip_S(s)); if (pos.can_castle_CR(CastleRightC.WHITE_OO) != 0) set_castle_right(ColorC.BLACK, Utils.flip_S(pos.castle_rook_square(ColorC.WHITE, CastlingSideC.KING_SIDE))); if (pos.can_castle_CR(CastleRightC.WHITE_OOO) != 0) set_castle_right(ColorC.BLACK, Utils.flip_S(pos.castle_rook_square(ColorC.WHITE, CastlingSideC.QUEEN_SIDE))); if (pos.can_castle_CR(CastleRightC.BLACK_OO) != 0) set_castle_right(ColorC.WHITE, Utils.flip_S(pos.castle_rook_square(ColorC.BLACK, CastlingSideC.KING_SIDE))); if (pos.can_castle_CR(CastleRightC.BLACK_OOO) != 0) set_castle_right(ColorC.WHITE, Utils.flip_S(pos.castle_rook_square(ColorC.BLACK, CastlingSideC.QUEEN_SIDE))); if (pos.st.epSquare != SquareC.SQ_NONE) st.epSquare = Utils.flip_S(pos.st.epSquare); // Checkers st.checkersBB = attackers_to(king_square(sideToMove)) & pieces_C(Utils.flip_C(sideToMove)); // Hash keys st.key = compute_key(); st.pawnKey = compute_pawn_key(); st.materialKey = compute_material_key(); // Incremental scores st.psqScore = compute_psq_score(); // Material st.npMaterialWHITE = compute_non_pawn_material(ColorC.WHITE); st.npMaterialBLACK = compute_non_pawn_material(ColorC.BLACK); Debug.Assert(pos_is_ok()); }