@@ -42,6 +42,64 @@ namespace {
4242 }
4343 };
4444
45+ struct GateScore {
46+ Square gate;
47+ int score;
48+ };
49+
50+ constexpr Direction RookDirections[] = {NORTH, SOUTH, EAST, WEST};
51+ constexpr Direction BishopDirections[] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
52+ constexpr int PotionKingBonus = 10000 ;
53+ constexpr int MaxFreezePotionGates = 8 ;
54+ constexpr int MaxJumpPotionGates = 6 ;
55+
56+ void add_jump_gate_scores (const Position& pos, Color us, PieceType pt,
57+ const Direction* dirs, int dirCount, int scores[SQUARE_NB]) {
58+ Bitboard sliders = pos.pieces (us, pt);
59+ const Bitboard board = pos.board_bb ();
60+ const Bitboard occ = pos.pieces ();
61+
62+ while (sliders)
63+ {
64+ Square s = pop_lsb (sliders);
65+ for (int i = 0 ; i < dirCount; ++i)
66+ {
67+ Direction d = dirs[i];
68+ Square cur = s;
69+ while (true )
70+ {
71+ cur += d;
72+ if (!is_ok (cur) || !(board & square_bb (cur)))
73+ break ;
74+ if (occ & square_bb (cur))
75+ {
76+ Square blocker = cur;
77+ cur += d;
78+ while (true )
79+ {
80+ if (!is_ok (cur) || !(board & square_bb (cur)))
81+ break ;
82+ if (occ & square_bb (cur))
83+ {
84+ Piece target = pos.piece_on (cur);
85+ if (color_of (target) == ~us)
86+ {
87+ int bonus = int (CapturePieceValue[MG][target]);
88+ if (type_of (target) == pos.king_type ())
89+ bonus += PotionKingBonus;
90+ scores[blocker] += bonus;
91+ }
92+ break ;
93+ }
94+ cur += d;
95+ }
96+ break ;
97+ }
98+ }
99+ }
100+ }
101+ }
102+
45103 template <MoveType T>
46104 ExtMove* make_move_and_gating (const Position& pos, ExtMove* moveList, Color us, Square from, Square to, PieceType pt = NO_PIECE_TYPE) {
47105
@@ -541,6 +599,9 @@ namespace {
541599 bool baseMovesSorted = false ;
542600 Move baseMoves[MAX_MOVES];
543601 int baseCount = 0 ;
602+ constexpr bool LimitPotionGates = Type == QUIETS;
603+ int jumpGateScores[SQUARE_NB];
604+ bool jumpScoresReady = false ;
544605
545606 for (int pt = 0 ; pt < Variant::POTION_TYPE_NB; ++pt)
546607 {
@@ -558,12 +619,10 @@ namespace {
558619 if (potion == Variant::POTION_JUMP)
559620 candidates &= allPieces;
560621
561- while (candidates)
562- {
563- Square gate = pop_lsb (candidates);
622+ auto generate_for_gate = [&](Square gate) {
564623
565624 if (potion == Variant::POTION_JUMP && !(allPieces & gate))
566- continue ;
625+ return ;
567626
568627 if (potion == Variant::POTION_FREEZE)
569628 {
@@ -595,7 +654,7 @@ namespace {
595654 }
596655
597656 cur = write;
598- continue ;
657+ return ;
599658 }
600659
601660 Bitboard jumpRemoved = square_bb (gate);
@@ -625,7 +684,7 @@ namespace {
625684
626685 cur = write;
627686 if (!allowNonKing)
628- continue ;
687+ return ;
629688
630689 if (!baseMovesSorted)
631690 {
@@ -691,6 +750,57 @@ namespace {
691750 }
692751
693752 cur = write;
753+ };
754+
755+ if constexpr (LimitPotionGates)
756+ {
757+ GateScore gateScores[SQUARE_NB];
758+ int gateCount = 0 ;
759+
760+ if (potion == Variant::POTION_JUMP && !jumpScoresReady)
761+ {
762+ std::fill_n (jumpGateScores, SQUARE_NB, 0 );
763+ add_jump_gate_scores (pos, Us, ROOK, RookDirections, 4 , jumpGateScores);
764+ add_jump_gate_scores (pos, Us, BISHOP, BishopDirections, 4 , jumpGateScores);
765+ add_jump_gate_scores (pos, Us, QUEEN, RookDirections, 4 , jumpGateScores);
766+ add_jump_gate_scores (pos, Us, QUEEN, BishopDirections, 4 , jumpGateScores);
767+ jumpScoresReady = true ;
768+ }
769+
770+ while (candidates)
771+ {
772+ Square gate = pop_lsb (candidates);
773+ int score = 0 ;
774+ if (potion == Variant::POTION_FREEZE)
775+ {
776+ Bitboard zone = pos.freeze_zone_from_square (gate);
777+ Bitboard enemies = zone & pos.pieces (~Us);
778+ while (enemies)
779+ score += int (CapturePieceValue[MG][pos.piece_on (pop_lsb (enemies))]);
780+ PieceType kingType = pos.king_type ();
781+ if (kingType != NO_PIECE_TYPE && (zone & pos.pieces (~Us, kingType)))
782+ score += PotionKingBonus;
783+ }
784+ else
785+ score = jumpGateScores[gate];
786+ gateScores[gateCount++] = {gate, score};
787+ }
788+
789+ int gateLimit = potion == Variant::POTION_FREEZE ? MaxFreezePotionGates : MaxJumpPotionGates;
790+ if (gateCount > gateLimit)
791+ {
792+ std::partial_sort (gateScores, gateScores + gateLimit, gateScores + gateCount,
793+ [](const GateScore& a, const GateScore& b) { return a.score > b.score ; });
794+ gateCount = gateLimit;
795+ }
796+
797+ for (int i = 0 ; i < gateCount; ++i)
798+ generate_for_gate (gateScores[i].gate );
799+ }
800+ else
801+ {
802+ while (candidates)
803+ generate_for_gate (pop_lsb (candidates));
694804 }
695805 }
696806
0 commit comments