Add Camelrider and Zebrarider pieces
authorH.G.Muller <hgm@hgm-xboard.(none)>
Fri, 9 Jan 2026 12:10:15 +0000 (13:10 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Fri, 9 Jan 2026 12:10:15 +0000 (13:10 +0100)
These new rides must always generate their own Magics. They only need
very small tables, as they never have more than 6 blocker squares
in their masks.

src/bitboard.cpp
src/types.h

index d1a9628..22c880a 100644 (file)
@@ -63,7 +63,7 @@ Magic CustomMagics[MAX_RIDE - CUSTOM_RIDES][SQUARE_NB];
 Magic* magics[MAX_RIDE] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV,
                    LameDabbabaMagics, HorseMagics, ElephantMagics, JanggiElephantMagics, CannonDiagMagics, NightriderMagics,
                    GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD,
-                   RookMagicsHT, RookMagicsHB, RookMagicsVL, RookMagicsVR };
+                   RookMagicsHT, RookMagicsHB, RookMagicsVL, RookMagicsVR, CamelriderMagics, ZebrariderMagics };
 
 int nrOfRides;
 int riderBaseType[MAX_RIDE];
@@ -85,6 +85,8 @@ namespace {
   Bitboard JanggiElephantTable[0x1C000];  // To store janggi elephant attacks
   Bitboard CannonDiagTable[0x33C00]; // To store diagonal cannon attacks
   Bitboard NightriderTable[0xD200]; // To store nightrider attacks
+  Bitboard CamelriderTable[0x8D0]; // To store nightrider attacks
+  Bitboard ZebrariderTable[0x3D0]; // To store nightrider attacks
   Bitboard GrasshopperTableH[0x11800];  // To store horizontal grasshopper attacks
   Bitboard GrasshopperTableV[0x4800];  // To store vertical grasshopper attacks
   Bitboard GrasshopperTableD[0x33C00]; // To store diagonal grasshopper attacks
@@ -100,6 +102,8 @@ namespace {
   Bitboard JanggiElephantTable[0x5C00];  // To store janggi elephant attacks
   Bitboard CannonDiagTable[0x1480]; // To store diagonal cannon attacks
   Bitboard NightriderTable[0x500]; // To store nightrider attacks
+  Bitboard CamelriderTable[0xD0]; // To store camelrider attacks
+  Bitboard ZebrariderTable[0x90]; // To store zebrarider attacks
   Bitboard GrasshopperTableH[0xA00];  // To store horizontal grasshopper attacks
   Bitboard GrasshopperTableV[0xA00];  // To store vertical grasshopper attacks
   Bitboard GrasshopperTableD[0x1480]; // To store diagonal grasshopper attacks
@@ -112,6 +116,8 @@ namespace {
   const std::map<DirectionCode, int> LameDabbabaDirections { {step(2, 0), 0}, {step(0, 2), 0}, {step(-2, 0), 0}, {step(0, -2), 0} };
   const std::map<DirectionCode, int> HorseDirections { {step(-2, 1), 0}, {step(-2, -1), 0}, {step(-1, 2), 0}, {step(-1, -2), 0},
                                                    {step(1, -2), 0}, {step(1, 2), 0}, {step(2, -1), 0}, {step(2, 1), 0} };
+  const std::map<DirectionCode, int> CamelDirections { {step(-3, 1), 0}, {step(-3, -1), 0}, {step(-1, 3), 0}, {step(-1, -3), 0},
+                                                   {step(1, -3), 0}, {step(1, 3), 0}, {step(3, -1), 0}, {step(3, 1), 0} };
   const std::map<DirectionCode, int> ElephantDirections { {step(2, 2), 0}, {step(-2, 2), 0}, {step(-2, -2), 0}, {step(2, -2), 0} };
   const std::map<DirectionCode, int> JanggiElephantDirections { {step(3, 2), 0}, {step(2, 3), 0},
                                                             {step(-2, 3), 0}, {step(-3, 2), 0},
@@ -159,10 +165,10 @@ namespace {
         }
 
         for (Square s = ss + d;
-             is_ok(s) && distance(s, s - d) <= 2;
+             is_ok(s) && distance(s, s - d) <= 3;
              s += d)
         {
-            if(mask && (!is_ok(s + d) || distance(s, s + d) > 2)) break; // forelast square is not blocker
+            if(mask && (!is_ok(s + d) || distance(s, s + d) > 3)) break; // forelast square is not blocker
 
             if (MT != HOPPER || hurdle)
             {
@@ -343,6 +349,10 @@ void Bitboards::init_pieces() {
                       riderTypes |= assign_magic(RIDER_ROOK_V, limit);
                   if (HorseDirections.find(d) != HorseDirections.end())
                       riderTypes |= RIDER_NIGHTRIDER;
+                  if (CamelDirections.find(d) != CamelDirections.end())
+                      riderTypes |= RIDER_CAMELRIDER;
+                  if (JannggiElephantDirections.find(d) != JannggiElephantDirections.end())
+                      riderTypes |= RIDER_ZEBRARIDER;
                   if (RookDirectionsHT.find(d) != RookDirectionsHT.end())
                       riderTypes |= RIDER_ROOK_HT;
                   if (RookDirectionsVR.find(d) != RookDirectionsVR.end())
@@ -427,6 +437,8 @@ void Bitboards::init() {
   init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections, JanggiElephantMagicInit);
   init_magics<HOPPER>(CannonDiagTable, CannonDiagMagics, BishopDirections, CannonDiagMagicInit);
   init_magics<RIDER>(NightriderTable, NightriderMagics, HorseDirections, NightriderMagicInit);
+  init_magics<RIDER>(CamelriderTable, CamelriderMagics, CamelDirections, NULL);
+  init_magics<RIDER>(ZebrariderTable, ZebrariderMagics, JanggiElephantDirections, NULL);
   init_magics<HOPPER>(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH, GrasshopperMagicHInit);
   init_magics<HOPPER>(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV, GrasshopperMagicVInit);
   init_magics<HOPPER>(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD, GrasshopperMagicDInit);
@@ -442,6 +454,8 @@ void Bitboards::init() {
   init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections);
   init_magics<HOPPER>(CannonDiagTable, CannonDiagMagics, BishopDirections);
   init_magics<RIDER>(NightriderTable, NightriderMagics, HorseDirections);
+  init_magics<RIDER>(CamelriderTable, CamelriderMagics, CamelDirections);
+  init_magics<RIDER>(ZebrariderTable, ZebrariderMagics, JanggiElephantDirections);
   init_magics<HOPPER>(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH);
   init_magics<HOPPER>(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV);
   init_magics<HOPPER>(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD);
index 620e99b..71d7cf5 100644 (file)
@@ -474,13 +474,15 @@ enum RiderType : int {
   RIDER_ROOK_HB = 1 << 15,
   RIDER_ROOK_VL = 1 << 16,
   RIDER_ROOK_VR = 1 << 17,
+  RIDER_CAMELRIDER = 1 << 18,
+  RIDER_ZEBRARIDER = 1 << 19,
   RIDER_GRIFFON = RIDER_ROOK_HT | RIDER_ROOK_HB | RIDER_ROOK_VL | RIDER_ROOK_VR,
   HOPPING_RIDERS =  RIDER_CANNON_H | RIDER_CANNON_V | RIDER_CANNON_DIAG
                   | RIDER_GRASSHOPPER_H | RIDER_GRASSHOPPER_V | RIDER_GRASSHOPPER_D,
   LAME_LEAPERS = RIDER_LAME_DABBABA | RIDER_HORSE | RIDER_ELEPHANT | RIDER_JANGGI_ELEPHANT,
   ASYMMETRICAL_RIDERS =  RIDER_HORSE | RIDER_JANGGI_ELEPHANT | GRIFFON
                        | RIDER_GRASSHOPPER_H | RIDER_GRASSHOPPER_V | RIDER_GRASSHOPPER_D,
-  NON_SLIDING_RIDERS = HOPPING_RIDERS | LAME_LEAPERS | RIDER_NIGHTRIDER,
+  NON_SLIDING_RIDERS = HOPPING_RIDERS | LAME_LEAPERS | RIDER_NIGHTRIDER | RIDER_CAMELRIDER | RIDER_ZEBRARIDER,
   CUSTOM_RIDES = 20,
   MAX_RIDE = 32
 };