Support limited distance sliders
authorFabian Fichter <ianfab@users.noreply.github.com>
Fri, 30 Apr 2021 22:36:54 +0000 (00:36 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Fri, 30 Apr 2021 22:51:36 +0000 (00:51 +0200)
src/bitboard.cpp
src/parser.cpp
src/piece.cpp
src/piece.h
src/psqt.cpp
src/variants.ini

index 139823f..010381d 100644 (file)
@@ -80,41 +80,46 @@ namespace {
 #endif
 
   // Rider directions
-  const std::set<Direction> RookDirectionsV { NORTH, SOUTH};
-  const std::set<Direction> RookDirectionsH { EAST, WEST };
-  const std::set<Direction> BishopDirections { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
-  const std::set<Direction> HorseDirections { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-                                              NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST };
-  const std::set<Direction> ElephantDirections { 2 * NORTH_EAST, 2 * SOUTH_EAST, 2 * SOUTH_WEST, 2 * NORTH_WEST };
-  const std::set<Direction> JanggiElephantDirections { NORTH + 2 * NORTH_EAST, EAST  + 2 * NORTH_EAST,
-                                                       EAST  + 2 * SOUTH_EAST, SOUTH + 2 * SOUTH_EAST,
-                                                       SOUTH + 2 * SOUTH_WEST, WEST  + 2 * SOUTH_WEST,
-                                                       WEST  + 2 * NORTH_WEST, NORTH + 2 * NORTH_WEST };
+  const std::map<Direction, int> RookDirectionsV { {NORTH, 0}, {SOUTH, 0}};
+  const std::map<Direction, int> RookDirectionsH { {EAST, 0}, {WEST, 0} };
+  const std::map<Direction, int> BishopDirections { {NORTH_EAST, 0}, {SOUTH_EAST, 0}, {SOUTH_WEST, 0}, {NORTH_WEST, 0} };
+  const std::map<Direction, int> HorseDirections { {2 * SOUTH + WEST, 0}, {2 * SOUTH + EAST, 0}, {SOUTH + 2 * WEST, 0}, {SOUTH + 2 * EAST, 0},
+                                                   {NORTH + 2 * WEST, 0}, {NORTH + 2 * EAST, 0}, {2 * NORTH + WEST, 0}, {2 * NORTH + EAST, 0} };
+  const std::map<Direction, int> ElephantDirections { {2 * NORTH_EAST, 0}, {2 * SOUTH_EAST, 0}, {2 * SOUTH_WEST, 0}, {2 * NORTH_WEST, 0} };
+  const std::map<Direction, int> JanggiElephantDirections { {NORTH + 2 * NORTH_EAST, 0}, {EAST  + 2 * NORTH_EAST, 0},
+                                                            {EAST  + 2 * SOUTH_EAST, 0}, {SOUTH + 2 * SOUTH_EAST, 0},
+                                                            {SOUTH + 2 * SOUTH_WEST, 0}, {WEST  + 2 * SOUTH_WEST, 0},
+                                                            {WEST  + 2 * NORTH_WEST, 0}, {NORTH + 2 * NORTH_WEST, 0} };
 
   enum MovementType { RIDER, HOPPER, LAME_LEAPER };
 
   template <MovementType MT>
 #ifdef PRECOMPUTED_MAGICS
-  void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions, Bitboard magicsInit[]);
+  void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, Bitboard magicsInit[]);
 #else
-  void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions);
+  void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions);
 #endif
 
   template <MovementType MT>
-  Bitboard sliding_attack(std::set<Direction> directions, Square sq, Bitboard occupied, Color c = WHITE) {
+  Bitboard sliding_attack(std::map<Direction, int> directions, Square sq, Bitboard occupied, Color c = WHITE) {
     assert(MT != LAME_LEAPER);
 
     Bitboard attack = 0;
 
-    for (Direction d : directions)
+    for (auto const& [d, limit] : directions)
     {
+        int count = 0;
         bool hurdle = false;
         for (Square s = sq + (c == WHITE ? d : -d);
              is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2;
              s += (c == WHITE ? d : -d))
         {
             if (MT != HOPPER || hurdle)
+            {
                 attack |= s;
+                if (limit && ++count >= limit)
+                    break;
+            }
 
             if (occupied & s)
             {
@@ -152,19 +157,19 @@ namespace {
     return b;
   }
 
-  Bitboard lame_leaper_path(std::set<Direction> directions, Square s) {
+  Bitboard lame_leaper_path(std::map<Direction, int> directions, Square s) {
     Bitboard b = 0;
-    for (Direction d : directions)
-        b |= lame_leaper_path(d, s);
+    for (const auto& i : directions)
+        b |= lame_leaper_path(i.first, s);
     return b;
   }
 
-  Bitboard lame_leaper_attack(std::set<Direction> directions, Square s, Bitboard occupied) {
+  Bitboard lame_leaper_attack(std::map<Direction, int> directions, Square s, Bitboard occupied) {
     Bitboard b = 0;
-    for (Direction d : directions)
+    for (const auto& i : directions)
     {
-        Square to = s + d;
-        if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(d, s) & occupied))
+        Square to = s + i.first;
+        if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(i.first, s) & occupied))
             b |= to;
     }
     return b;
@@ -213,65 +218,62 @@ void Bitboards::init_pieces() {
       AttackRiderTypes[pt] = NO_RIDER;
       MoveRiderTypes[pt] = NO_RIDER;
 
-      if (pi->lameLeaper)
+      for (auto const& [d, limit] : pi->stepsCapture)
       {
-          for (Direction d : pi->stepsCapture)
-          {
-              if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
-                  AttackRiderTypes[pt] |= RIDER_HORSE;
-              if (std::find(ElephantDirections.begin(), ElephantDirections.end(), d) != ElephantDirections.end())
-                  AttackRiderTypes[pt] |= RIDER_ELEPHANT;
-              if (std::find(JanggiElephantDirections.begin(), JanggiElephantDirections.end(), d) != JanggiElephantDirections.end())
-                  AttackRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
-          }
-          for (Direction d : pi->stepsQuiet)
-          {
-              if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
-                  MoveRiderTypes[pt] |= RIDER_HORSE;
-              if (std::find(ElephantDirections.begin(), ElephantDirections.end(), d) != ElephantDirections.end())
-                  MoveRiderTypes[pt] |= RIDER_ELEPHANT;
-              if (std::find(JanggiElephantDirections.begin(), JanggiElephantDirections.end(), d) != JanggiElephantDirections.end())
-                  MoveRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
-          }
+          if (limit && HorseDirections.find(d) != HorseDirections.end())
+              AttackRiderTypes[pt] |= RIDER_HORSE;
+          if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+              AttackRiderTypes[pt] |= RIDER_ELEPHANT;
+          if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+              AttackRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
+      }
+      for (auto const& [d, limit] : pi->stepsQuiet)
+      {
+          if (limit && HorseDirections.find(d) != HorseDirections.end())
+              MoveRiderTypes[pt] |= RIDER_HORSE;
+          if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+              MoveRiderTypes[pt] |= RIDER_ELEPHANT;
+          if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+              MoveRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
       }
-      for (Direction d : pi->sliderCapture)
+      for (auto const& [d, limit] : pi->sliderCapture)
       {
-          if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+          if (BishopDirections.find(d) != BishopDirections.end())
               AttackRiderTypes[pt] |= RIDER_BISHOP;
-          if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+          if (RookDirectionsH.find(d) != RookDirectionsH.end())
               AttackRiderTypes[pt] |= RIDER_ROOK_H;
-          if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+          if (RookDirectionsV.find(d) != RookDirectionsV.end())
               AttackRiderTypes[pt] |= RIDER_ROOK_V;
-          if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
+          if (HorseDirections.find(d) != HorseDirections.end())
               AttackRiderTypes[pt] |= RIDER_NIGHTRIDER;
       }
-      for (Direction d : pi->sliderQuiet)
+      for (auto const& [d, limit] : pi->sliderQuiet)
       {
-          if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+          if (BishopDirections.find(d) != BishopDirections.end())
               MoveRiderTypes[pt] |= RIDER_BISHOP;
-          if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+          if (RookDirectionsH.find(d) != RookDirectionsH.end())
               MoveRiderTypes[pt] |= RIDER_ROOK_H;
-          if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+          if (RookDirectionsV.find(d) != RookDirectionsV.end())
               MoveRiderTypes[pt] |= RIDER_ROOK_V;
-          if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
+          if (HorseDirections.find(d) != HorseDirections.end())
               MoveRiderTypes[pt] |= RIDER_NIGHTRIDER;
       }
-      for (Direction d : pi->hopperCapture)
+      for (auto const& [d, limit] : pi->hopperCapture)
       {
-          if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+          if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
               AttackRiderTypes[pt] |= RIDER_CANNON_H;
-          if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+          if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
               AttackRiderTypes[pt] |= RIDER_CANNON_V;
-          if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+          if (!limit && BishopDirections.find(d) != BishopDirections.end())
               AttackRiderTypes[pt] |= RIDER_CANNON_DIAG;
       }
-      for (Direction d : pi->hopperQuiet)
+      for (auto const& [d, limit] : pi->hopperQuiet)
       {
-          if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+          if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
               MoveRiderTypes[pt] |= RIDER_CANNON_H;
-          if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+          if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
               MoveRiderTypes[pt] |= RIDER_CANNON_V;
-          if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+          if (!limit && BishopDirections.find(d) != BishopDirections.end())
               MoveRiderTypes[pt] |= RIDER_CANNON_DIAG;
       }
 
@@ -284,16 +286,16 @@ void Bitboards::init_pieces() {
               PseudoMoves[c][pt][s] = 0;
               LeaperAttacks[c][pt][s] = 0;
               LeaperMoves[c][pt][s] = 0;
-              for (Direction d : pi->stepsCapture)
+              for (auto const& [d, limit] : pi->stepsCapture)
               {
                   PseudoAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
-                  if (!pi->lameLeaper)
+                  if (!limit)
                       LeaperAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
               }
-              for (Direction d : pi->stepsQuiet)
+              for (auto const& [d, limit] : pi->stepsQuiet)
               {
                   PseudoMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
-                  if (!pi->lameLeaper)
+                  if (!limit)
                       LeaperMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
               }
               PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->sliderCapture, s, 0, c);
@@ -370,9 +372,9 @@ namespace {
 
   template <MovementType MT>
 #ifdef PRECOMPUTED_MAGICS
-  void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions, Bitboard magicsInit[]) {
+  void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, Bitboard magicsInit[]) {
 #else
-  void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions) {
+  void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions) {
 #endif
 
     // Optimal PRNG seeds to pick the correct magics in the shortest time
index ed1762f..85a5fd9 100644 (file)
@@ -418,7 +418,8 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
             if (v->flipEnclosedPieces)
                 std::cerr << "Can not use kings with flipEnclosedPieces." << std::endl;
             const PieceInfo* pi = pieceMap.find(v->kingType)->second;
-            if (pi->lameLeaper || pi->hopperQuiet.size() || pi->hopperCapture.size())
+            if (pi->hopperQuiet.size() || pi->hopperCapture.size()
+                || std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](const std::pair<const Direction, int>& d) { return d.second; }))
                 std::cerr << pi->name << " is not supported as kingType." << std::endl;
         }
     }
index 6fc719b..e52e195 100644 (file)
@@ -57,6 +57,8 @@ namespace {
       std::vector<char> moveTypes = {};
       bool hopper = false;
       bool rider = false;
+      bool lame = false;
+      int distance = 0;
       std::vector<std::string> prelimDirections = {};
       for (std::string::size_type i = 0; i < betza.size(); i++)
       {
@@ -65,11 +67,15 @@ namespace {
           if (c == 'm' || c == 'c')
               moveTypes.push_back(c);
           // Hopper
-          else if (c == 'p')
+          else if (c == 'p' || c == 'g')
+          {
               hopper = true;
+              if (c == 'g')
+                  distance = 1;
+          }
           // Lame leaper
           else if (c == 'n')
-              p->lameLeaper = true;
+              lame = true;
           // Directional modifiers
           else if (verticals.find(c) != std::string::npos || horizontals.find(c) != std::string::npos)
           {
@@ -101,11 +107,11 @@ namespace {
                   rider = true;
                   // limited distance riders
                   if (isdigit(betza[i+1]))
-                  {
-                      // TODO: not supported
-                  }
+                      distance = betza[i+1] - '0';
                   i++;
               }
+              if (!rider && lame)
+                  distance = -1;
               // No type qualifier means m+c
               if (moveTypes.size() == 0)
               {
@@ -129,28 +135,28 @@ namespace {
                   // Add moves
                   for (char mt : moveTypes)
                   {
-                      std::set<Direction>& v = hopper ? (mt == 'c' ? p->hopperCapture : p->hopperQuiet)
-                                              : rider ? (mt == 'c' ? p->sliderCapture : p->sliderQuiet)
-                                                      : (mt == 'c' ? p->stepsCapture : p->stepsQuiet);
+                      auto& v = hopper ? (           mt == 'c' ? p->hopperCapture : p->hopperQuiet)
+                                          : rider ? (mt == 'c' ? p->sliderCapture : p->sliderQuiet)
+                                                  : (mt == 'c' ? p->stepsCapture : p->stepsQuiet);
                       auto has_dir = [&](std::string s) {
                         return std::find(directions.begin(), directions.end(), s) != directions.end();
                       };
                       if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("rf") || has_dir("rv") || has_dir("fh") || has_dir("rh") || has_dir("hr"))
-                          v.insert(Direction(atom.first * FILE_NB + atom.second));
+                          v[Direction(atom.first * FILE_NB + atom.second)] = distance;
                       if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("lb") || has_dir("lv") || has_dir("bh") || has_dir("lh") || has_dir("hr"))
-                          v.insert(Direction(-atom.first * FILE_NB - atom.second));
+                          v[Direction(-atom.first * FILE_NB - atom.second)] = distance;
                       if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("br") || has_dir("bs") || has_dir("bh") || has_dir("lh") || has_dir("hr"))
-                          v.insert(Direction(-atom.second * FILE_NB + atom.first));
+                          v[Direction(-atom.second * FILE_NB + atom.first)] = distance;
                       if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("fl") || has_dir("fs") || has_dir("fh") || has_dir("rh") || has_dir("hr"))
-                          v.insert(Direction(atom.second * FILE_NB - atom.first));
+                          v[Direction(atom.second * FILE_NB - atom.first)] = distance;
                       if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("fr") || has_dir("fs") || has_dir("fh") || has_dir("rh") || has_dir("hl"))
-                          v.insert(Direction(atom.second * FILE_NB + atom.first));
+                          v[Direction(atom.second * FILE_NB + atom.first)] = distance;
                       if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("bl") || has_dir("bs") || has_dir("bh") || has_dir("lh") || has_dir("hl"))
-                          v.insert(Direction(-atom.second * FILE_NB - atom.first));
+                          v[Direction(-atom.second * FILE_NB - atom.first)] = distance;
                       if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("rb") || has_dir("rv") || has_dir("bh") || has_dir("rh") || has_dir("hl"))
-                          v.insert(Direction(-atom.first * FILE_NB + atom.second));
+                          v[Direction(-atom.first * FILE_NB + atom.second)] = distance;
                       if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("lf") || has_dir("lv") || has_dir("fh") || has_dir("lh") || has_dir("hl"))
-                          v.insert(Direction(atom.first * FILE_NB - atom.second));
+                          v[Direction(atom.first * FILE_NB - atom.second)] = distance;
                   }
               }
               // Reset state
@@ -164,18 +170,8 @@ namespace {
   }
   // Special multi-leg betza description for Janggi elephant
   PieceInfo* janggi_elephant_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "janggiElephant";
-      p->betza = "mafsmafW";
-      p->stepsQuiet = {SOUTH + 2 * SOUTH_WEST, SOUTH + 2 * SOUTH_EAST,
-                       WEST  + 2 * SOUTH_WEST, EAST  + 2 * SOUTH_EAST,
-                       WEST  + 2 * NORTH_WEST, EAST  + 2 * NORTH_EAST,
-                       NORTH + 2 * NORTH_WEST, NORTH + 2 * NORTH_EAST};
-      p->stepsCapture = {SOUTH + 2 * SOUTH_WEST, SOUTH + 2 * SOUTH_EAST,
-                         WEST  + 2 * SOUTH_WEST, EAST  + 2 * SOUTH_EAST,
-                         WEST  + 2 * NORTH_WEST, EAST  + 2 * NORTH_EAST,
-                         NORTH + 2 * NORTH_WEST, NORTH + 2 * NORTH_EAST};
-      p->lameLeaper = true;
+      PieceInfo* p = from_betza("nZ", "");
+      p->betza = "mafsmafW"; // for compatiblity with XBoard/Winboard
       return p;
   }
 }
index 2ce4a7e..8f8479c 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <string>
 #include <map>
-#include <set>
 
 #include "types.h"
 #include "variant.h"
 struct PieceInfo {
   std::string name = "";
   std::string betza = "";
-  std::set<Direction> stepsQuiet = {};
-  std::set<Direction> stepsCapture = {};
-  std::set<Direction> sliderQuiet = {};
-  std::set<Direction> sliderCapture = {};
-  std::set<Direction> hopperQuiet = {};
-  std::set<Direction> hopperCapture = {};
-  bool lameLeaper = false;
+  std::map<Direction, int> stepsQuiet = {};
+  std::map<Direction, int> stepsCapture = {};
+  std::map<Direction, int> sliderQuiet = {};
+  std::map<Direction, int> sliderCapture = {};
+  std::map<Direction, int> hopperQuiet = {};
+  std::map<Direction, int> hopperCapture = {};
 };
 
 struct PieceMap : public std::map<PieceType, const PieceInfo*> {
index f8ba11d..026883f 100644 (file)
@@ -161,8 +161,8 @@ Value piece_value(Phase phase, PieceType pt)
             + (phase == MG ? 100 :  80) * pi->hopperCapture.size()
             + (phase == MG ?  80 :  60) * pi->hopperQuiet.size()
             // Rook sliding directions are more valuable, especially in endgame
-            + (phase == MG ?  10 :  30) * std::count_if(pi->sliderCapture.begin(), pi->sliderCapture.end(), [](Direction d) { return std::abs(d) == NORTH || std::abs(d) == 1; })
-            + (phase == MG ?  30 :  45) * std::count_if(pi->sliderQuiet.begin(), pi->sliderQuiet.end(), [](Direction d) { return std::abs(d) == NORTH || std::abs(d) == 1; });
+            + (phase == MG ?  10 :  30) * std::count_if(pi->sliderCapture.begin(), pi->sliderCapture.end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; })
+            + (phase == MG ?  30 :  45) * std::count_if(pi->sliderQuiet.begin(), pi->sliderQuiet.end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; });
     return Value(v0 * exp(double(v0) / 10000));
 }
 
@@ -212,8 +212,8 @@ void init(const Variant* v) {
       
       const PieceInfo* pi = pieceMap.find(pt)->second;
       bool isSlider = pi->sliderQuiet.size() || pi->sliderCapture.size() || pi->hopperQuiet.size() || pi->hopperCapture.size();
-      bool isPawn = !isSlider && pi->stepsQuiet.size() && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return d < SOUTH / 2; });
-      bool isSlowLeaper = !isSlider && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return dist(d) > 1; });
+      bool isPawn = !isSlider && pi->stepsQuiet.size() && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](const std::pair<const Direction, int>& d) { return d.first < SOUTH / 2; });
+      bool isSlowLeaper = !isSlider && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1; });
 
       // Scale slider piece values with board size
       if (isSlider)
@@ -246,8 +246,7 @@ void init(const Variant* v) {
       // Increase leapers' value in makpong
       else if (v->makpongRule)
       {
-          if (std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](Direction d) { return dist(d) > 1; })
-                  && !pi->lameLeaper)
+          if (std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1 && !d.second; }))
               score = make_score(mg_value(score) * 4200 / (3500 + mg_value(score)),
                                  eg_value(score) * 4700 / (3500 + mg_value(score)));
       }
index fe04d55..9ec87e3 100644 (file)
@@ -95,9 +95,9 @@
 # In Fairy-Stockfish only a subset of Betza notation can be used. The supported features are:
 # - all base moves/atoms (W, F, etc.)
 # - all directional modifiers (f, b, etc.)
-# - unlimited distance sliders/riders for W/R, F/B, and N directions
+# - limited and unlimited distance sliders/riders for W/R, F/B, and N directions
 # - hoppers for W/R and F/B directions, i.e., pR and pB
-# - lame leapers (n) for N and A directions, i.e., nN and nA
+# - lame leapers (n) for N, A, and Z directions, i.e., nN, nA, and nZ
 
 ### Piece values
 # The predefined and precalculated piece values can be overriden