Let Betza parser understand extended atoms for larger leaps
authorH.G.Muller <hgm@hgm-xboard.(none)>
Sat, 3 Jan 2026 18:35:29 +0000 (19:35 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Sat, 3 Jan 2026 19:23:47 +0000 (20:23 +0100)
The Betza parser now understand an X suffix to an atom as a 3-square
extension in the long direction, and an Y suffix as a 2-square extension
in both the long and short direction. E.g. FX for a (4,1) leap, NY for
a (4,3) leap. This allows leaps of up to (6,3) = GX and (5,5) = GY.

src/piece.cpp

index c78075c..cd6660e 100644 (file)
@@ -62,6 +62,8 @@ namespace {
       bool lame = false;
       bool initial = false;
       int distance = 0;
+      int fExtension = 0;
+      int fsExtension = 0;
       std::vector<std::string> prelimDirections = {};
       for (std::string::size_type i = 0; i < betza.size(); i++)
       {
@@ -109,14 +111,22 @@ namespace {
               // Check for rider
               if (riderAtoms.find(c) != riderAtoms.end())
                   rider = true;
-              if (i + 1 < betza.size() && (isdigit(betza[i+1]) || betza[i+1] == c))
-              {
-                  rider = true;
-                  // limited distance riders
-                  if (isdigit(betza[i+1]))
-                      distance = betza[i+1] - '0';
-                  i++;
-              }
+              if (i + 1 < betza.size()) {
+                  if (betza[++i] == 'X')
+                      fExtension++;
+                  else if (betza[i] == 'Y')
+                      fsExtension++;
+                  else if (isdigit(betza[i]) || betza[i] == c)
+                  {
+                      rider = true;
+                      // limited distance riders
+                      if (isdigit(betza[i])) {
+                          int range = betza[i] - '0';
+                          if(range)
+                              distance = range;
+                      }
+                  } else i--;
+               }
               if (!rider && lame)
                   distance = -1;
               // No modality qualifier means m+c
@@ -128,6 +138,8 @@ namespace {
               // Define moves
               for (const auto& atom : atoms)
               {
+                  int y = atom.first + 3*fExtension + 2*fsExtension;
+                  int x = atom.second + 2*fsExtension;
                   std::vector<std::string> directions = {};
                   // Split directions for orthogonal pieces
                   // This is required e.g. to correctly interpret fsW for soldiers
@@ -148,21 +160,21 @@ namespace {
                       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"))
+                      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[step(y, x)] = 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"))
+                      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[step(-y, -x)] = distance;
-                       if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("br") || has_dir("bs") || has_dir("bh") || has_dir("rh") || has_dir("hr"))
+                      if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("br") || has_dir("bs") || has_dir("bh") || has_dir("rh") || has_dir("hr"))
                           v[step(-x, y)] = distance;
-                       if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("fl") || has_dir("fs") || has_dir("fh") || has_dir("lh") || has_dir("hr"))
+                      if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("fl") || has_dir("fs") || has_dir("fh") || has_dir("lh") || has_dir("hr"))
                           v[step(x, -y)] = 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"))
+                      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[step(x, y)] = 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"))
+                      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[step(-x, -y)] = 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"))
+                      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[step(-y, x)] = 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"))
+                      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[step(y, -x)] = distance;
                   }
               }
@@ -174,6 +186,8 @@ namespace {
               lame = false;
               initial = false;
               distance = 0;
+              fExtension = 0;
+              fsExtension = 0;
           }
       }
       return p;