Consistently use wrappers around variant properties (#898)
authorFabian Fichter <ianfab@users.noreply.github.com>
Fri, 15 Aug 2025 20:35:17 +0000 (22:35 +0200)
committerGitHub <noreply@github.com>
Fri, 15 Aug 2025 20:35:17 +0000 (22:35 +0200)
* Consistently use wrappers around variant properties instead of a mix of direct and indirect access
* Rename drop region fields to follow the color postfix naming convention
* Disambiguate the promotionPawnType(s) fields

12 files changed:
src/apiutil.h
src/evaluate.cpp
src/movegen.cpp
src/nnue/features/half_ka_v2_variants.cpp
src/parser.cpp
src/position.cpp
src/position.h
src/psqt.cpp
src/variant.cpp
src/variant.h
src/variants.ini
test.py

index f3003a9..74bdc6d 100644 (file)
@@ -389,7 +389,7 @@ inline bool has_insufficient_material(Color c, const Position& pos) {
 
     // Mating pieces
     for (PieceType pt : { ROOK, QUEEN, ARCHBISHOP, CHANCELLOR, SILVER, GOLD, COMMONER, CENTAUR, AMAZON, BERS })
-        if ((pos.pieces(c, pt) & ~restricted) || (pos.count(c, pos.promotion_pawn_type(c)) && (pos.promotion_piece_types(c) & pt)))
+        if ((pos.pieces(c, pt) & ~restricted) || (pos.count(c, pos.main_promotion_pawn_type(c)) && (pos.promotion_piece_types(c) & pt)))
             return false;
 
     // Color-bound pieces
index 5e49874..ce30aa0 100644 (file)
@@ -1074,7 +1074,7 @@ namespace {
     }
 
     // Passed custom pawns
-    for (PieceSet ps = pos.variant()->promotionPawnTypes[Us] & ~piece_set(PAWN); ps;)
+    for (PieceSet ps = (pos.promotion_pawn_types(Us) & ~piece_set(PAWN)); ps;)
     {
         PieceType pt = pop_lsb(ps);
         Bitboard b2 = pos.pieces(Us, pt);
@@ -1388,8 +1388,8 @@ namespace {
 
     // Compute the initiative bonus for the attacking side
     complexity =       9 * pe->passed_count()
-                    + 12 * pos.count(WHITE, pos.promotion_pawn_type(WHITE)) * bool(pos.promotion_pawn_type(WHITE))
-                    + 12 * pos.count(BLACK, pos.promotion_pawn_type(BLACK)) * bool(pos.promotion_pawn_type(BLACK))
+                    + 12 * pos.count(WHITE, pos.main_promotion_pawn_type(WHITE)) * bool(pos.main_promotion_pawn_type(WHITE))
+                    + 12 * pos.count(BLACK, pos.main_promotion_pawn_type(BLACK)) * bool(pos.main_promotion_pawn_type(BLACK))
                     + 15 * pos.count<SOLDIER>()
                     +  9 * outflanking
                     + 21 * pawnsOnBothFlanks
index f5a16eb..a7b6a9f 100644 (file)
@@ -30,7 +30,7 @@ namespace {
 
     // Wall placing moves
     //if it's "wall or move", and they chose non-null move, skip even generating wall move
-    if (pos.walling() && !(pos.variant()->wallOrMove && (from!=to)))
+    if (pos.walling() && !(pos.wall_or_move() && (from!=to)))
     {
         Bitboard b = pos.board_bb() & ~((pos.pieces() ^ from) | to);
         if (T == CASTLING)
@@ -47,7 +47,7 @@ namespace {
             b &= moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from);
 
         //Any current or future wall variant must follow the walling region rule if set:
-        b &= pos.variant()->wallingRegion[us];
+        b &= pos.walling_region(us);
 
         if (pos.walling_rule() == PAST)
             b &= square_bb(from);
@@ -275,7 +275,7 @@ namespace {
             Bitboard b = pawns & pawn_attacks_bb(Them, epSquare);
 
             // En passant square is already disabled for non-fairy variants if there is no attacker
-            assert(b || !pos.variant()->fastAttacks);
+            assert(b || !pos.fast_attacks());
 
             while (b)
                 moveList = make_move_and_gating<EN_PASSANT>(pos, moveList, Us, pop_lsb(b), epSquare);
@@ -306,8 +306,8 @@ namespace {
         PieceType promPt = pos.promoted_piece_type(Pt);
         Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(Us, promPt)) ? b1 : Bitboard(0);
         Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0);
-        Bitboard pawnPromotions = pos.variant()->promotionPawnTypes[Us] & Pt ? b & (Type == EVASIONS ? target : ~pos.pieces(Us)) & promotion_zone : Bitboard(0);
-        Bitboard epSquares = pos.variant()->enPassantTypes[Us] & Pt ? attacks & ~quiets & pos.ep_squares() & ~pos.pieces() : Bitboard(0);
+        Bitboard pawnPromotions = (pos.promotion_pawn_types(Us) & Pt) ? (b & (Type == EVASIONS ? target : ~pos.pieces(Us)) & promotion_zone) : Bitboard(0);
+        Bitboard epSquares = (pos.en_passant_types(Us) & Pt) ? (attacks & ~quiets & pos.ep_squares() & ~pos.pieces()) : Bitboard(0);
 
         // target squares considering pawn promotions
         if (pawnPromotions && pos.mandatory_pawn_promotion())
@@ -446,7 +446,7 @@ namespace {
             *moveList++ = make<SPECIAL>(lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
 
         //if "wall or move", generate walling action with null move
-        if (pos.variant()->wallOrMove)
+        if (pos.wall_or_move())
         {
             moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
         }
index 1e0fd6e..bf4360a 100644 (file)
@@ -38,12 +38,12 @@ namespace Stockfish::Eval::NNUE::Features {
 
   // Index of a feature for a given king position and another piece on some square
   inline IndexType HalfKAv2Variants::make_index(Color perspective, Square s, Piece pc, Square ksq, const Position& pos) {
-    return IndexType(orient(perspective, s, pos) + pos.variant()->pieceSquareIndex[perspective][pc] + pos.variant()->kingSquareIndex[ksq]);
+    return IndexType(orient(perspective, s, pos) + pos.nnue_piece_square_index(perspective, pc) + pos.nnue_king_square_index(ksq));
   }
 
   // Index of a feature for a given king position and another piece on some square
   inline IndexType HalfKAv2Variants::make_index(Color perspective, int handCount, Piece pc, Square ksq, const Position& pos) {
-    return IndexType(handCount + pos.variant()->pieceHandIndex[perspective][pc] + pos.variant()->kingSquareIndex[ksq]);
+    return IndexType(handCount + pos.nnue_piece_hand_index(perspective, pc) + pos.nnue_king_square_index(ksq));
   }
 
   // Get a list of indices for active features
index 3ebf1b1..9f2f848 100644 (file)
@@ -345,14 +345,16 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
     parse_attribute<false>("blackFlag", v->flagRegion[BLACK]);
     parse_attribute<false>("castlingRookPiece", v->castlingRookPieces[WHITE], v->pieceToChar);
     parse_attribute<false>("castlingRookPiece", v->castlingRookPieces[BLACK], v->pieceToChar);
+    parse_attribute<false>("whiteDropRegion", v->dropRegion[WHITE]);
+    parse_attribute<false>("blackDropRegion", v->dropRegion[BLACK]);
 
     bool dropOnTop = false;
     parse_attribute<false>("dropOnTop", dropOnTop);
     if (dropOnTop) v->enclosingDrop=TOP;
 
     // Parse aliases
-    parse_attribute("pawnTypes", v->promotionPawnType[WHITE], v->pieceToChar);
-    parse_attribute("pawnTypes", v->promotionPawnType[BLACK], v->pieceToChar);
+    parse_attribute("pawnTypes", v->mainPromotionPawnType[WHITE], v->pieceToChar);
+    parse_attribute("pawnTypes", v->mainPromotionPawnType[BLACK], v->pieceToChar);
     parse_attribute("pawnTypes", v->promotionPawnTypes[WHITE], v->pieceToChar);
     parse_attribute("pawnTypes", v->promotionPawnTypes[BLACK], v->pieceToChar);
     parse_attribute("pawnTypes", v->enPassantTypes[WHITE], v->pieceToChar);
@@ -370,12 +372,12 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
     parse_attribute("promotionRegionWhite", v->promotionRegion[WHITE]);
     parse_attribute("promotionRegionBlack", v->promotionRegion[BLACK]);
     // Take the first promotionPawnTypes as the main promotionPawnType
-    parse_attribute("promotionPawnTypes", v->promotionPawnType[WHITE], v->pieceToChar);
-    parse_attribute("promotionPawnTypes", v->promotionPawnType[BLACK], v->pieceToChar);
+    parse_attribute("promotionPawnTypes", v->mainPromotionPawnType[WHITE], v->pieceToChar);
+    parse_attribute("promotionPawnTypes", v->mainPromotionPawnType[BLACK], v->pieceToChar);
     parse_attribute("promotionPawnTypes", v->promotionPawnTypes[WHITE], v->pieceToChar);
     parse_attribute("promotionPawnTypes", v->promotionPawnTypes[BLACK], v->pieceToChar);
-    parse_attribute("promotionPawnTypesWhite", v->promotionPawnType[WHITE], v->pieceToChar);
-    parse_attribute("promotionPawnTypesBlack", v->promotionPawnType[BLACK], v->pieceToChar);
+    parse_attribute("promotionPawnTypesWhite", v->mainPromotionPawnType[WHITE], v->pieceToChar);
+    parse_attribute("promotionPawnTypesBlack", v->mainPromotionPawnType[BLACK], v->pieceToChar);
     parse_attribute("promotionPawnTypesWhite", v->promotionPawnTypes[WHITE], v->pieceToChar);
     parse_attribute("promotionPawnTypesBlack", v->promotionPawnTypes[BLACK], v->pieceToChar);
     parse_attribute("promotionPieceTypes", v->promotionPieceTypes[WHITE], v->pieceToChar);
@@ -458,8 +460,8 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
     parse_attribute("promotionZonePawnDrops", v->promotionZonePawnDrops);
     parse_attribute("enclosingDrop", v->enclosingDrop);
     parse_attribute("enclosingDropStart", v->enclosingDropStart);
-    parse_attribute("whiteDropRegion", v->whiteDropRegion);
-    parse_attribute("blackDropRegion", v->blackDropRegion);
+    parse_attribute("dropRegionWhite", v->dropRegion[WHITE]);
+    parse_attribute("dropRegionBlack", v->dropRegion[BLACK]);
     parse_attribute("sittuyinRookDrop", v->sittuyinRookDrop);
     parse_attribute("dropOppositeColoredBishop", v->dropOppositeColoredBishop);
     parse_attribute("dropPromoted", v->dropPromoted);
index eec715d..c55ab3f 100644 (file)
@@ -76,7 +76,7 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
               os << " *";
           else
               os << "  ";
-          if (!pos.variant()->freeDrops && (pos.piece_drops() || pos.seirawan_gating()))
+          if (!pos.free_drops() && (pos.piece_drops() || pos.seirawan_gating()))
           {
               os << " [";
               for (PieceType pt = KING; pt >= PAWN; --pt)
@@ -746,7 +746,7 @@ string Position::fen(bool sfen, bool showPromoted, int countStarted, std::string
   }
 
   // pieces in hand
-  if (!variant()->freeDrops && (piece_drops() || seirawan_gating()))
+  if (!free_drops() && (piece_drops() || seirawan_gating()))
   {
       ss << '[';
       if (holdings != "-")
@@ -1637,7 +1637,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
       {
           Piece pieceToHand = !capturedPromoted || drop_loop() ? ~captured
                              : unpromotedCaptured ? ~unpromotedCaptured
-                                                  : make_piece(~color_of(captured), promotion_pawn_type(color_of(captured)));
+                                                  : make_piece(~color_of(captured), main_promotion_pawn_type(color_of(captured)));
           add_to_hand(pieceToHand);
           k ^=  Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)] - 1]
               ^ Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)]];
@@ -2187,7 +2187,7 @@ void Position::undo_move(Move m) {
       assert((promotion_zone(us) & to) || sittuyin_promotion());
       assert(type_of(pc) == promotion_type(m));
       assert(type_of(pc) >= KNIGHT && type_of(pc) < KING);
-      assert(type_of(st->promotionPawn) == promotion_pawn_type(us) || !captures_to_hand());
+      assert(type_of(st->promotionPawn) == main_promotion_pawn_type(us) || !captures_to_hand());
 
       remove_piece(to);
       pc = st->promotionPawn;
@@ -2236,7 +2236,7 @@ void Position::undo_move(Move m) {
           put_piece(st->capturedPiece, capsq, st->capturedpromoted, st->unpromotedCapturedPiece); // Restore the captured piece
           if (captures_to_hand())
               remove_from_hand(!drop_loop() && st->capturedpromoted ? (st->unpromotedCapturedPiece ? ~st->unpromotedCapturedPiece
-                                                                                                   : make_piece(~color_of(st->capturedPiece), promotion_pawn_type(us)))
+                                                                                                   : make_piece(~color_of(st->capturedPiece), main_promotion_pawn_type(us)))
                                                                     : ~st->capturedPiece);
       }
   }
@@ -2361,7 +2361,7 @@ Key Position::key_after(Move m) const {
       k ^= Zobrist::psq[captured][to];
       if (captures_to_hand())
       {
-          Piece removeFromHand = !drop_loop() && is_promoted(to) ? make_piece(~color_of(captured), promotion_pawn_type(color_of(captured))) : ~captured;
+          Piece removeFromHand = !drop_loop() && is_promoted(to) ? make_piece(~color_of(captured), main_promotion_pawn_type(color_of(captured))) : ~captured;
           k ^= Zobrist::inHand[removeFromHand][pieceCountInHand[color_of(removeFromHand)][type_of(removeFromHand)] + 1]
               ^ Zobrist::inHand[removeFromHand][pieceCountInHand[color_of(removeFromHand)][type_of(removeFromHand)]];
       }
@@ -2818,7 +2818,7 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
   {
       Bitboard b;
 
-      for (Direction d : var->connect_directions)
+      for (Direction d : var->connectDirections)
       {
           b = connectPieces;
           for (int i = 1; i < connect_n() && b; i++)
@@ -2838,7 +2838,7 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
 
       while (true) {
           Bitboard newBitboard = 0;
-          for (Direction d : var->connect_directions) {
+          for (Direction d : var->connectDirections) {
               newBitboard |= shift(d, current | newBitboard) & connectPieces; // the "| newBitboard" here probably saves a few loops
           }
 
@@ -2872,7 +2872,7 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
   // Collinear-n
   if (collinear_n() > 0) {
       Bitboard allPieces = connectPieces;
-      for (Direction d : var->connect_directions) {
+      for (Direction d : var->connectDirections) {
           Bitboard b = allPieces;
           while (b) {
               Square s = pop_lsb(b);
index 242a4c9..45517d2 100644 (file)
@@ -130,7 +130,7 @@ public:
   const std::string& piece_to_char_synonyms() const;
   Bitboard promotion_zone(Color c) const;
   Square promotion_square(Color c, Square s) const;
-  PieceType promotion_pawn_type(Color c) const;
+  PieceType main_promotion_pawn_type(Color c) const;
   PieceSet promotion_piece_types(Color c) const;
   bool sittuyin_promotion() const;
   int promotion_limit(PieceType pt) const;
@@ -158,6 +158,12 @@ public:
   Square nnue_king_square(Color c) const;
   bool nnue_use_pockets() const;
   bool nnue_applicable() const;
+  int nnue_piece_square_index(Color perspective, Piece pc) const;
+  int nnue_piece_hand_index(Color perspective, Piece pc) const;
+  int nnue_king_square_index(Square ksq) const;
+  bool free_drops() const;
+  bool fast_attacks() const;
+  bool fast_attacks2() const;
   bool checking_permitted() const;
   bool drop_checks() const;
   bool must_capture() const;
@@ -175,10 +181,14 @@ public:
   bool drop_opposite_colored_bishop() const;
   bool drop_promoted() const;
   PieceType drop_no_doubled() const;
+  PieceSet promotion_pawn_types(Color c) const;
+  PieceSet en_passant_types(Color c) const;
   bool immobility_illegal() const;
   bool gating() const;
   bool walling() const;
   WallingRule walling_rule() const;
+  bool wall_or_move() const;
+  Bitboard walling_region(Color c) const;
   bool seirawan_gating() const;
   bool cambodian_moves() const;
   Bitboard diagonal_lines() const;
@@ -448,9 +458,9 @@ inline Square Position::promotion_square(Color c, Square s) const {
   return !b ? SQ_NONE : c == WHITE ? lsb(b) : msb(b);
 }
 
-inline PieceType Position::promotion_pawn_type(Color c) const {
+inline PieceType Position::main_promotion_pawn_type(Color c) const {
   assert(var != nullptr);
-  return var->promotionPawnType[c];
+  return var->mainPromotionPawnType[c];
 }
 
 inline PieceSet Position::promotion_piece_types(Color c) const {
@@ -587,11 +597,41 @@ inline bool Position::nnue_applicable() const {
   return (!count_in_hand(ALL_PIECES) || nnue_use_pockets() || !must_drop()) && !virtualPieces;
 }
 
+inline int Position::nnue_piece_square_index(Color perspective, Piece pc) const {
+  assert(var != nullptr);
+  return var->pieceSquareIndex[perspective][pc];
+}
+
+inline int Position::nnue_piece_hand_index(Color perspective, Piece pc) const {
+  assert(var != nullptr);
+  return var->pieceHandIndex[perspective][pc];
+}
+
+inline int Position::nnue_king_square_index(Square ksq) const {
+  assert(var != nullptr);
+  return var->kingSquareIndex[ksq];
+}
+
 inline bool Position::checking_permitted() const {
   assert(var != nullptr);
   return var->checking;
 }
 
+inline bool Position::free_drops() const {
+  assert(var != nullptr);
+  return var->freeDrops;
+}
+
+inline bool Position::fast_attacks() const {
+  assert(var != nullptr);
+  return var->fastAttacks;
+}
+
+inline bool Position::fast_attacks2() const {
+  assert(var != nullptr);
+  return var->fastAttacks2;
+}
+
 inline bool Position::drop_checks() const {
   assert(var != nullptr);
   return var->dropChecks;
@@ -660,7 +700,7 @@ inline EnclosingRule Position::enclosing_drop() const {
 
 inline Bitboard Position::drop_region(Color c) const {
   assert(var != nullptr);
-  return c == WHITE ? var->whiteDropRegion : var->blackDropRegion;
+  return var->dropRegion[c];
 }
 
 inline Bitboard Position::drop_region(Color c, PieceType pt) const {
@@ -781,6 +821,16 @@ inline PieceType Position::drop_no_doubled() const {
   return var->dropNoDoubled;
 }
 
+inline PieceSet Position::promotion_pawn_types(Color c) const {
+  assert(var != nullptr);
+  return var->promotionPawnTypes[c];
+}
+
+inline PieceSet Position::en_passant_types(Color c) const {
+  assert(var != nullptr);
+  return var->enPassantTypes[c];
+}
+
 inline bool Position::immobility_illegal() const {
   assert(var != nullptr);
   return var->immobilityIllegal;
@@ -801,6 +851,16 @@ inline WallingRule Position::walling_rule() const {
   return var->wallingRule;
 }
 
+inline bool Position::wall_or_move() const {
+  assert(var != nullptr);
+  return var->wallOrMove;
+}
+
+inline Bitboard Position::walling_region(Color c) const {
+  assert(var != nullptr);
+  return var->wallingRegion[c];
+}
+
 inline bool Position::seirawan_gating() const {
   assert(var != nullptr);
   return var->seirawanGating;
@@ -1059,7 +1119,7 @@ inline bool Position::connect_diagonal() const {
 
 inline const std::vector<Direction>& Position::getConnectDirections() const {
     assert(var != nullptr);
-    return var->connect_directions;
+    return var->connectDirections;
 }
 
 inline int Position::connect_nxn() const {
@@ -1436,7 +1496,7 @@ inline const std::string Position::piece_to_partner() const {
   if (!st->capturedPiece) return std::string();
   Color color = color_of(st->capturedPiece);
   Piece piece = st->capturedpromoted ?
-      (st->unpromotedCapturedPiece ? st->unpromotedCapturedPiece : make_piece(color, promotion_pawn_type(color))) :
+      (st->unpromotedCapturedPiece ? st->unpromotedCapturedPiece : make_piece(color, main_promotion_pawn_type(color))) :
       st->capturedPiece;
   return std::string(1, piece_to_char()[piece]);
 }
index 01237dd..d1a84d6 100644 (file)
@@ -218,7 +218,7 @@ void init(const Variant* v) {
       Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
 
       // Consider promotion types in pawn score
-      if (pt == v->promotionPawnType[WHITE])
+      if (pt == v->mainPromotionPawnType[WHITE])
       {
           score -= make_score(0, (QueenValueEg - maxPromotion) / 100);
           if (v->blastOnCapture)
index c3ed05d..c8aa137 100644 (file)
@@ -86,7 +86,7 @@ namespace {
         Variant* v = chess_variant_base()->init();
         v->remove_piece(PAWN);
         v->add_piece(CUSTOM_PIECE_1, 'p', "mfFcfeWimfnA");
-        v->promotionPawnType[WHITE] = v->promotionPawnType[BLACK] = CUSTOM_PIECE_1;
+        v->mainPromotionPawnType[WHITE] = v->mainPromotionPawnType[BLACK] = CUSTOM_PIECE_1;
         v->promotionPawnTypes[WHITE] = v->promotionPawnTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->enPassantTypes[WHITE] = v->enPassantTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->nMoveRuleTypes[WHITE] = v->nMoveRuleTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
@@ -98,7 +98,7 @@ namespace {
         Variant* v = chess_variant_base()->init();
         v->remove_piece(PAWN);
         v->add_piece(CUSTOM_PIECE_1, 'p', "fsmWfceFifmnD");
-        v->promotionPawnType[WHITE] = v->promotionPawnType[BLACK] = CUSTOM_PIECE_1;
+        v->mainPromotionPawnType[WHITE] = v->mainPromotionPawnType[BLACK] = CUSTOM_PIECE_1;
         v->promotionPawnTypes[WHITE] = v->promotionPawnTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->enPassantTypes[WHITE] = v->enPassantTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->nMoveRuleTypes[WHITE] = v->nMoveRuleTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
@@ -112,7 +112,7 @@ namespace {
         v->add_piece(CUSTOM_PIECE_1, 'p', "fbmWfceFifmnD");
         v->mobilityRegion[WHITE][CUSTOM_PIECE_1] = (Rank2BB | Rank3BB | Rank4BB | Rank5BB | Rank6BB | Rank7BB | Rank8BB);
         v->mobilityRegion[BLACK][CUSTOM_PIECE_1] = (Rank7BB | Rank6BB | Rank5BB | Rank4BB | Rank3BB | Rank2BB | Rank1BB);
-        v->promotionPawnType[WHITE] = v->promotionPawnType[BLACK] = CUSTOM_PIECE_1;
+        v->mainPromotionPawnType[WHITE] = v->mainPromotionPawnType[BLACK] = CUSTOM_PIECE_1;
         v->promotionPawnTypes[WHITE] = v->promotionPawnTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->enPassantTypes[WHITE] = v->enPassantTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->nMoveRuleTypes[WHITE] = v->nMoveRuleTypes[BLACK] = NO_PIECE_SET; // backwards pawn moves are reversible
@@ -126,7 +126,7 @@ namespace {
         v->add_piece(CUSTOM_PIECE_1, 'p', "mflFcflW");
         v->promotionRegion[WHITE] = make_bitboard(SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_A7, SQ_A6, SQ_A5);
         v->promotionRegion[BLACK] = make_bitboard(SQ_E1, SQ_F1, SQ_G1, SQ_H1, SQ_H2, SQ_H3, SQ_H4);
-        v->promotionPawnType[WHITE] = v->promotionPawnType[BLACK] = CUSTOM_PIECE_1;
+        v->mainPromotionPawnType[WHITE] = v->mainPromotionPawnType[BLACK] = CUSTOM_PIECE_1;
         v->promotionPawnTypes[WHITE] = v->promotionPawnTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->nMoveRuleTypes[WHITE] = v->nMoveRuleTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->startFen = "knbrp3/bqpp4/npp5/rp1p3P/p3P1PR/5PPN/4PPQB/3PRBNK w - - 0 1";
@@ -689,8 +689,8 @@ namespace {
         v->mustDrop = true;
         v->pieceDrops = true;
         v->capturesToHand = false;
-        v->whiteDropRegion = Rank1BB;
-        v->blackDropRegion = Rank8BB;
+        v->dropRegion[WHITE] = Rank1BB;
+        v->dropRegion[BLACK] = Rank8BB;
         v->dropOppositeColoredBishop = true;
         v->castlingDroppedPiece = true;
         v->nnueAlias = "nn-";
@@ -708,8 +708,8 @@ namespace {
         v->mustDrop = true;
         v->pieceDrops = true;
         v->capturesToHand = false;
-        v->whiteDropRegion = Rank1BB | Rank2BB | Rank3BB;
-        v->blackDropRegion = Rank8BB | Rank7BB | Rank6BB;
+        v->dropRegion[WHITE] = Rank1BB | Rank2BB | Rank3BB;
+        v->dropRegion[BLACK] = Rank8BB | Rank7BB | Rank6BB;
         v->sittuyinRookDrop = true;
         v->sittuyinPromotion = true;
         v->promotionRegion[WHITE] = make_bitboard(SQ_A8, SQ_B7, SQ_C6, SQ_D5, SQ_E5, SQ_F6, SQ_G7, SQ_H8);
@@ -760,8 +760,8 @@ namespace {
         v->startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[Dd] w KQkq - 0 1";
         v->pieceDrops = true;
         v->capturesToHand = false;
-        v->whiteDropRegion = Rank1BB;
-        v->blackDropRegion = Rank8BB;
+        v->dropRegion[WHITE] = Rank1BB;
+        v->dropRegion[BLACK] = Rank8BB;
         v->promotionPieceTypes[WHITE] = piece_set(ARCHBISHOP) | QUEEN | ROOK | BISHOP | KNIGHT;
         v->promotionPieceTypes[BLACK] = piece_set(ARCHBISHOP) | QUEEN | ROOK | BISHOP | KNIGHT;
         return v;
@@ -1068,7 +1068,7 @@ namespace {
         v->add_piece(CUSTOM_PIECE_2, 'l', "FAsmW");
         v->add_piece(CUSTOM_PIECE_3, 'c', "WD");
         v->startFen = "lgkcckwl/hhhhhhhh/8/8/8/8/PPPPPPPP/RNBQKBNR w KQ - 0 1";
-        v->promotionPawnType[BLACK] = CUSTOM_PIECE_1;
+        v->mainPromotionPawnType[BLACK] = CUSTOM_PIECE_1;
         v->promotionPawnTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->nMoveRuleTypes[BLACK] = piece_set(CUSTOM_PIECE_1);
         v->promotionPieceTypes[BLACK] = piece_set(COMMONER) | DRAGON | ARCHBISHOP | CUSTOM_PIECE_2 | CUSTOM_PIECE_3;
@@ -1628,7 +1628,7 @@ namespace {
         v->add_piece(CUSTOM_PIECE_2, 'n', "NN"); // nightrider
         v->add_piece(CUSTOM_PIECE_3, 'e', "NNQ"); // elephant
         v->startFen = "qwfrbbnk/pssppssp/1pp2pp1/8/8/8/8/1PP2PP1/PSSPPSSP/KNBBRFWQ w - - 0 1";
-        v->promotionPawnType[WHITE] = v->promotionPawnType[BLACK] = PAWN;
+        v->mainPromotionPawnType[WHITE] = v->mainPromotionPawnType[BLACK] = PAWN;
         v->promotionPawnTypes[WHITE] = v->promotionPawnTypes[BLACK] = piece_set(PAWN) | piece_set(CUSTOM_PIECE_1);
         v->promotionPieceTypes[WHITE] = piece_set(QUEEN) | CHANCELLOR | ARCHBISHOP | ROOK | BISHOP;
         v->promotionPieceTypes[BLACK] = piece_set(QUEEN) | CHANCELLOR | ARCHBISHOP | ROOK | BISHOP;
@@ -1748,8 +1748,8 @@ namespace {
         v->twoBoards = true;
         v->pieceDrops = true;
         v->dropChecks = false;
-        v->whiteDropRegion = v->mobilityRegion[WHITE][ELEPHANT];
-        v->blackDropRegion = v->mobilityRegion[BLACK][ELEPHANT];
+        v->dropRegion[WHITE] = v->mobilityRegion[WHITE][ELEPHANT];
+        v->dropRegion[BLACK] = v->mobilityRegion[BLACK][ELEPHANT];
         v->mobilityRegion[WHITE][FERS] = make_bitboard(SQ_D1, SQ_F1, SQ_E2, SQ_D3, SQ_F3);
         v->mobilityRegion[BLACK][FERS] = make_bitboard(SQ_D8, SQ_F8, SQ_E9, SQ_D10, SQ_F10);
         v->mobilityRegion[WHITE][ELEPHANT] = make_bitboard(SQ_C1, SQ_G1, SQ_A3, SQ_E3, SQ_I3, SQ_C5, SQ_G5);
@@ -2091,19 +2091,19 @@ Variant* Variant::conclude() {
             break;
         }
 
-    connect_directions.clear();
+    connectDirections.clear();
     if (connectHorizontal)
     {
-        connect_directions.push_back(EAST);
+        connectDirections.push_back(EAST);
     }
     if (connectVertical)
     {
-        connect_directions.push_back(NORTH);
+        connectDirections.push_back(NORTH);
     }
     if (connectDiagonal)
     {
-        connect_directions.push_back(NORTH_EAST);
-        connect_directions.push_back(SOUTH_EAST);
+        connectDirections.push_back(NORTH_EAST);
+        connectDirections.push_back(SOUTH_EAST);
     }
 
     // If not a connect variant, set connectPieceTypesTrimmed to no pieces.
index 98fe314..c13305d 100644 (file)
@@ -52,7 +52,7 @@ struct Variant {
   std::string startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
   Bitboard mobilityRegion[COLOR_NB][PIECE_TYPE_NB] = {};
   Bitboard promotionRegion[COLOR_NB] = {Rank8BB, Rank1BB};
-  PieceType promotionPawnType[COLOR_NB] = {PAWN, PAWN};
+  PieceType mainPromotionPawnType[COLOR_NB] = {PAWN, PAWN};
   PieceSet promotionPawnTypes[COLOR_NB] = {piece_set(PAWN), piece_set(PAWN)};
   PieceSet promotionPieceTypes[COLOR_NB] = {piece_set(QUEEN) | ROOK | BISHOP | KNIGHT,
                                             piece_set(QUEEN) | ROOK | BISHOP | KNIGHT};
@@ -97,8 +97,7 @@ struct Variant {
   bool promotionZonePawnDrops = false;
   EnclosingRule enclosingDrop = NO_ENCLOSING;
   Bitboard enclosingDropStart = 0;
-  Bitboard whiteDropRegion = AllSquares;
-  Bitboard blackDropRegion = AllSquares;
+  Bitboard dropRegion[COLOR_NB] = {AllSquares, AllSquares};
   bool sittuyinRookDrop = false;
   bool dropOppositeColoredBishop = false;
   bool dropPromoted = false;
@@ -177,7 +176,7 @@ struct Variant {
   int nnueMaxPieces;
   EndgameEval endgameEval = EG_EVAL_CHESS;
   bool shogiStylePromotions = false;
-  std::vector<Direction> connect_directions;
+  std::vector<Direction> connectDirections;
   PieceSet connectPieceTypesTrimmed = ~NO_PIECE_SET;
   void add_piece(PieceType pt, char c, std::string betza = "", char c2 = ' ') {
       // Avoid ambiguous definition by removing existing piece with same letter
index 5f17447..24dc66d 100644 (file)
 # capturesToHand: captured pieces go to opponent's hand [bool] (default: false)
 # firstRankPawnDrops: allow pawn drops to first rank [bool] (default: false)
 # promotionZonePawnDrops: allow pawn drops in promotion zone  [bool] (default: false)
-# dropOnTop: DEPRECATED, use "enclosingDrop = top"
 # enclosingDrop: require piece drop to enclose pieces [EnclosingRule] (default: none)
 # enclosingDropStart: drop region for starting phase disregarding enclosingDrop (e.g., for reversi) [Bitboard]
-# whiteDropRegion: restrict region for piece drops of all white pieces [Bitboard]
-# blackDropRegion: restrict region for piece drops of all black pieces [Bitboard]
+# dropRegionWhite: restrict region for piece drops of all white pieces [Bitboard]
+# dropRegionBlack: restrict region for piece drops of all black pieces [Bitboard]
 # sittuyinRookDrop: restrict region of rook drops to first rank [bool] (default: false)
 # dropOppositeColoredBishop: dropped bishops have to be on opposite-colored squares [bool] (default: false)
 # dropPromoted: pieces may be dropped in promoted state [bool] (default: false)
@@ -372,8 +371,8 @@ startFen = rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR[] w - - 0
 pieceDrops = true
 capturesToHand = true
 dropChecks = false
-whiteDropRegion = *1 *2 *3 *4 *5
-blackDropRegion = *6 *7 *8 *9 *10
+dropRegionWhite = *1 *2 *3 *4 *5
+dropRegionBlack = *6 *7 *8 *9 *10
 mobilityRegionWhiteFers = d1 f1 e2 d3 f3
 mobilityRegionBlackFers = d8 f8 e9 d10 f10
 mobilityRegionWhiteElephant = c1 g1 a3 e3 i3 c5 g5
@@ -551,8 +550,8 @@ promotedPieceType = p:c n:g b:a r:m f:q
 mandatoryPawnPromotion = false
 firstRankPawnDrops = true
 promotionZonePawnDrops = true
-whiteDropRegion = *1 *2 *3 *4 *5
-blackDropRegion = *4 *5 *6 *7 *8
+dropRegionWhite = *1 *2 *3 *4 *5
+dropRegionBlack = *4 *5 *6 *7 *8
 immobilityIllegal = true
 
 #https://www.chess.com/variants/caught-in-a-snag
@@ -639,7 +638,7 @@ perpetualCheckIllegal = true
 startFen = rneakenr/8/1c4c1/1ss2ss1/8/8/PPPPPPPP/RNBQKBNR[ss] w KQ - 0 1
 flyingGeneral = true
 capturesToHand = false
-blackDropRegion = *5
+dropRegionBlack = *5
 flagPiece = k
 flagRegionWhite = *8
 flagRegionBlack = *1
@@ -666,8 +665,8 @@ startFen = RNBKQBNR/pppppppp/8/8/8/8/PPPPPPPP/rnbkqbnr w - - 0 1
 [screen:placement]
 dropNoDoubled = p
 startFen = 8/8/8/8/8/8/8/8[KQRRBBNNPPPPPPPPkqrrbbnnpppppppp] w - - 0 1
-whiteDropRegion = *1 *2 *3 *4
-blackDropRegion = *8 *7 *6 *5
+dropRegionWhite = *1 *2 *3 *4
+dropRegionBlack = *8 *7 *6 *5
 
 # Crossing chess
 # https://vchess.club/#/variants/Crossing
@@ -791,8 +790,8 @@ stalemateValue = loss
 perpetualCheckIllegal = true
 startFen = rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/LH1CK1HL[LHMMDJ] w kq - 0 1
 pieceDrops = true
-whiteDropRegion = *1 *2 *3 *4
-blackDropRegion = *5 *6 *7 *8
+dropRegionWhite = *1 *2 *3 *4
+dropRegionBlack = *5 *6 *7 *8
 immobilityIllegal = true
 flagPiece = k
 flagRegionWhite = *8
@@ -1118,8 +1117,8 @@ stalemateValue = loss
 perpetualCheckIllegal = true
 startFen = lh1ck1hl/pppppppp/8/8/8/8/PPPPPPPP/LH1CK1HL[LHMMDJlhmmdj] w - - 0 1
 capturesToHand = false
-whiteDropRegion = *1 *2 *3 *4
-blackDropRegion = *5 *6 *7 *8
+dropRegionWhite = *1 *2 *3 *4
+dropRegionBlack = *5 *6 *7 *8
 immobilityIllegal = true
 flagPiece = k
 flagRegionWhite = *8
@@ -1219,8 +1218,8 @@ chancellor = c
 startFen = rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[CAca] w - - 0 1
 promotionPieceTypes = qcarbn
 pieceDrops = true
-whiteDropRegion = *1
-blackDropRegion = *8
+dropRegionWhite = *1
+dropRegionBlack = *8
 castling = false
 doubleStep = false
 stalemateValue = loss
@@ -1290,8 +1289,8 @@ customPiece4 = y:mRcD
 customPiece5 = o:WcF
 startFen = 3tot3/1p5p1/3XRX3/1d5d1/9/1p1t1t1p1/4d4/9/9/4C4[XXXXYYYYtttttttttd] w - - 0 1
 pieceDrops = true
-whiteDropRegion = *1 *2 *3 d4 e4 f4 d5 e5 f5 d6 e6 f6 *7 d8 e8 f8 d9 e9 f9 d10 e10 f10
-blackDropRegion = a4 b4 c4 g4 h4 i4 a5 b5 c5 g5 h5 i5 a6 b6 c6 g6 h6 i6 a8 b8 c8 g8 h8 i8 a9 b9 c9 g9 h9 i9 a10 b10 c10 g10 h10 i10
+dropRegionWhite = *1 *2 *3 d4 e4 f4 d5 e5 f5 d6 e6 f6 *7 d8 e8 f8 d9 e9 f9 d10 e10 f10
+dropRegionBlack = a4 b4 c4 g4 h4 i4 a5 b5 c5 g5 h5 i5 a6 b6 c6 g6 h6 i6 a8 b8 c8 g8 h8 i8 a9 b9 c9 g9 h9 i9 a10 b10 c10 g10 h10 i10
 castling = false
 mobilityRegionWhiteCustomPiece3 = *1 *2 *3 *4 a5 c5 d5 e5 f5 g5 i5 *6 *7 *8 a9 c9 d9 e9 f9 g9 i9 *10
 # mobilityRegionBlackCustomPiece3 = b5 b9 h5 h9 
@@ -1823,8 +1822,8 @@ castling = true
 castlingRookPieces = r
 startFen = rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[MMmm] w KQkq - 0 1
 pieceDrops = true
-whiteDropRegion = *1
-blackDropRegion = *8
+dropRegionWhite = *1
+dropRegionBlack = *8
 
 #https://www.chessvariants.com/small.dir/petty.html
 [petty:chess]
@@ -1947,7 +1946,7 @@ nFoldRule = 4
 perpetualCheckIllegal = true
 startFen = rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/4K3[JDFCLHM] w kq - 0 1
 capturesToHand = false
-whiteDropRegion = *1 *2 *3 *4
+dropRegionWhite = *1 *2 *3 *4
 immobilityIllegal = true
 flagPiece = k
 flagRegionWhite = *8
diff --git a/test.py b/test.py
index bef588e..72d61b9 100644 (file)
--- a/test.py
+++ b/test.py
@@ -46,8 +46,8 @@ promotedPieceType = p:c n:g b:a r:m f:q
 mandatoryPawnPromotion = false
 firstRankPawnDrops = true
 promotionZonePawnDrops = true
-whiteDropRegion = *1 *2 *3 *4 *5
-blackDropRegion = *4 *5 *6 *7 *8
+dropRegionWhite = *1 *2 *3 *4 *5
+dropRegionBlack = *4 *5 *6 *7 *8
 immobilityIllegal = true
 
 # Asymmetric variant with one army using pieces that move like knights but attack like other pieces (kniroo and knibis)