Define piece types using Betza notation
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 11 Apr 2021 14:44:51 +0000 (16:44 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 11 Apr 2021 16:22:28 +0000 (18:22 +0200)
As preparation for configurable piece types,
simplify definition of piece types by using Betza notation.

No functional change.

src/piece.cpp
src/piece.h

index 48bd240..c750be3 100644 (file)
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <map>
 #include <string>
+#include <utility>
 
 #include "types.h"
 #include "piece.h"
 
 PieceMap pieceMap; // Global object
 
-void PieceInfo::merge(const PieceInfo* pi) {
-    stepsQuiet.insert(stepsQuiet.end(), pi->stepsQuiet.begin(), pi->stepsQuiet.end());
-    stepsCapture.insert(stepsCapture.end(), pi->stepsCapture.begin(), pi->stepsCapture.end());
-    sliderQuiet.insert(sliderQuiet.end(), pi->sliderQuiet.begin(), pi->sliderQuiet.end());
-    sliderCapture.insert(sliderCapture.end(), pi->sliderCapture.begin(), pi->sliderCapture.end());
-}
 
 namespace {
-  PieceInfo* pawn_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "pawn";
-      p->betza = "fmWfceF";
-      p->stepsQuiet = {NORTH};
-      p->stepsCapture = {NORTH_WEST, NORTH_EAST};
-      return p;
-  }
-  PieceInfo* knight_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "knight";
-      p->betza = "N";
-      p->stepsQuiet = {2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-                       NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST };
-      p->stepsCapture = {2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-                         NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST };
-      return p;
-  }
-  PieceInfo* bishop_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "bishop";
-      p->betza = "B";
-      p->sliderQuiet = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
-      p->sliderCapture = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
-      return p;
-  }
-  PieceInfo* rook_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "rook";
-      p->betza = "R";
-      p->sliderQuiet = {NORTH, EAST, SOUTH, WEST};
-      p->sliderCapture = {NORTH, EAST, SOUTH, WEST};
-      return p;
-  }
-  PieceInfo* queen_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "queen";
-      p->betza = "RB";
-      p->sliderQuiet = {NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
-      p->sliderCapture = {NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
-      return p;
-  }
-  PieceInfo* king_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "king";
-      p->betza = "K";
-      p->stepsQuiet = {SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      p->stepsCapture = {SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      return p;
-  }
-  PieceInfo* commoner_piece() {
-      PieceInfo* p = king_piece();
-      p->name = "commoner";
-      return p;
-  }
-  PieceInfo* fers_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "fers";
-      p->betza = "F";
-      p->stepsQuiet = {SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST};
-      p->stepsCapture = {SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST};
-      return p;
-  }
-  PieceInfo* wazir_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "wazir";
-      p->betza = "W";
-      p->stepsQuiet = {SOUTH, WEST, EAST, NORTH};
-      p->stepsCapture = {SOUTH, WEST, EAST, NORTH};
-      return p;
-  }
-  PieceInfo* alfil_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "alfil";
-      p->betza = "A";
-      p->stepsQuiet = {2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST};
-      p->stepsCapture = {2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST};
-      return p;
-  }
-  PieceInfo* fers_alfil_piece() {
-      PieceInfo* p = fers_piece();
-      p->name = "fersAlfil";
-      p->betza = "FA";
-      PieceInfo* p2 = alfil_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* silver_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "silver";
-      p->betza = "FfW";
-      p->stepsQuiet = {SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      p->stepsCapture = {SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      return p;
-  }
-  PieceInfo* aiwok_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "aiwok";
-      p->betza = "RNF";
-      PieceInfo* p2 = knight_piece();
-      PieceInfo* p3 = fers_piece();
-      p->merge(p2);
-      p->merge(p3);
-      delete p2;
-      delete p3;
-      return p;
-  }
-  PieceInfo* bers_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "bers";
-      p->betza = "RF";
-      PieceInfo* p2 = fers_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* archbishop_piece() {
-      PieceInfo* p = bishop_piece();
-      p->name = "archbishop";
-      p->betza = "BN";
-      PieceInfo* p2 = knight_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* chancellor_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "chancellor";
-      p->betza = "RN";
-      PieceInfo* p2 = knight_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* amazon_piece() {
-      PieceInfo* p = queen_piece();
-      p->name = "amazon";
-      p->betza = "RBN";
-      PieceInfo* p2 = knight_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* knibis_piece() {
-      PieceInfo* p = bishop_piece();
-      p->name = "knibis";
-      p->betza = "mNcB";
-      p->sliderQuiet.clear();
-      PieceInfo* p2 = knight_piece();
-      p2->stepsCapture.clear();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* biskni_piece() {
-      PieceInfo* p = bishop_piece();
-      p->name = "biskni";
-      p->betza = "mBcN";
-      p->sliderCapture.clear();
-      PieceInfo* p2 = knight_piece();
-      p2->stepsQuiet.clear();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* kniroo_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "kniroo";
-      p->betza = "mNcR";
-      p->sliderQuiet.clear();
-      PieceInfo* p2 = knight_piece();
-      p2->stepsCapture.clear();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* rookni_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "rookni";
-      p->betza = "mRcN";
-      p->sliderCapture.clear();
-      PieceInfo* p2 = knight_piece();
-      p2->stepsQuiet.clear();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* shogi_pawn_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "shogiPawn";
-      p->betza = "fW";
-      p->stepsQuiet = {NORTH};
-      p->stepsCapture = {NORTH};
-      return p;
-  }
-  PieceInfo* lance_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "lance";
-      p->betza = "fR";
-      p->sliderQuiet = {NORTH};
-      p->sliderCapture = {NORTH};
-      return p;
-  }
-  PieceInfo* shogi_knight_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "shogiKnight";
-      p->betza = "fN";
-      p->stepsQuiet = {2 * NORTH + WEST, 2 * NORTH + EAST};
-      p->stepsCapture = {2 * NORTH + WEST, 2 * NORTH + EAST};
-      return p;
-  }
-  PieceInfo* euroshogi_knight_piece() {
-      PieceInfo* p = shogi_knight_piece();
-      p->name = "euroshogiKnight";
-      p->betza = "fNsW";
-      p->stepsQuiet.push_back(WEST);
-      p->stepsQuiet.push_back(EAST);
-      p->stepsCapture.push_back(WEST);
-      p->stepsCapture.push_back(EAST);
-      return p;
-  }
-  PieceInfo* gold_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "gold";
-      p->betza = "WfF";
-      p->stepsQuiet = {SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      p->stepsCapture = {SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
-      return p;
-  }
-  PieceInfo* dragon_horse_piece() {
-      PieceInfo* p = bishop_piece();
-      p->name = "dragonHorse";
-      p->betza = "BW";
-      PieceInfo* p2 = wazir_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
-  PieceInfo* clobber_piece() {
-      PieceInfo* p = wazir_piece();
-      p->name = "clobber";
-      p->betza = "cW";
-      p->stepsQuiet.clear();
-      return p;
-  }
-  PieceInfo* breakthrough_piece() {
-      PieceInfo* p = pawn_piece();
-      p->name = "breakthrough";
-      p->betza = "fWfFcF";
-      p->stepsQuiet.push_back(NORTH_WEST);
-      p->stepsQuiet.push_back(NORTH_EAST);
-      return p;
-  }
-  PieceInfo* immobile_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "immobile";
-      return p;
-  }
-  PieceInfo* ataxx_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "ataxx";
-      p->betza = "mDNA";
-      p->stepsQuiet = {2 * NORTH_WEST, 2 * NORTH + WEST, 2 * NORTH, 2 * NORTH + EAST, 2 * NORTH_EAST,
-                       NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * WEST, 2 * EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-                       2 * SOUTH_WEST, 2 * SOUTH + WEST, 2 * SOUTH, 2 * SOUTH + EAST, 2 * SOUTH_EAST};
-      return p;
-  }
-  PieceInfo* quiet_queen_piece() {
-      PieceInfo* p = queen_piece();
-      p->name = "quietQueen";
-      p->betza = "mQ";
-      p->sliderCapture.clear();
-      return p;
-  }
-  PieceInfo* cannon_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "cannon";
-      p->betza = "mRcpR";
-      p->sliderQuiet = {NORTH, EAST, SOUTH, WEST};
-      p->hopperCapture = {NORTH, EAST, SOUTH, WEST};
-      return p;
-  }
-  PieceInfo* janggi_cannon_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "janggiCannon";
-      p->betza = "pR";
-      p->hopperQuiet = {NORTH, EAST, SOUTH, WEST};
-      p->hopperCapture = {NORTH, EAST, SOUTH, WEST};
-      return p;
-  }
-  PieceInfo* soldier_piece() {
-      PieceInfo* p = new PieceInfo();
-      p->name = "soldier";
-      p->betza = "fsW";
-      p->stepsQuiet = {NORTH, WEST, EAST};
-      p->stepsCapture = {NORTH, WEST, EAST};
-      return p;
-  }
-  PieceInfo* horse_piece() {
-      PieceInfo* p = knight_piece();
-      p->name = "horse";
-      p->betza = "nN";
-      p->lameLeaper = true;
-      return p;
-  }
-  PieceInfo* elephant_piece() {
-      PieceInfo* p = alfil_piece();
-      p->name = "elephant";
-      p->betza = "nA";
-      p->lameLeaper = true;
-      return p;
-  }
+  std::map<char, std::vector<std::pair<int, int>>> leaperAtoms = {
+      {'W', {std::make_pair(1, 0)}},
+      {'F', {std::make_pair(1, 1)}},
+      {'D', {std::make_pair(2, 0)}},
+      {'N', {std::make_pair(2, 1)}},
+      {'A', {std::make_pair(2, 2)}},
+      {'H', {std::make_pair(3, 0)}},
+      {'L', {std::make_pair(3, 1)}},
+      {'C', {std::make_pair(3, 1)}},
+      {'J', {std::make_pair(3, 2)}},
+      {'Z', {std::make_pair(3, 2)}},
+      {'G', {std::make_pair(3, 3)}},
+      {'K', {std::make_pair(1, 0), std::make_pair(1, 1)}},
+  };
+  std::map<char, std::vector<std::pair<int, int>>> riderAtoms = {
+      {'R', {std::make_pair(1, 0)}},
+      {'B', {std::make_pair(1, 1)}},
+      {'Q', {std::make_pair(1, 0), std::make_pair(1, 1)}},
+  };
+  const std::string verticals = "fbvh";
+  const std::string horizontals = "rlsh";
+  // from_betza creates a piece by parsing Betza notation
+  // https://en.wikipedia.org/wiki/Betza%27s_funny_notation
+  PieceInfo* from_betza(const std::string& betza, const std::string& name) {
+      PieceInfo* p = new PieceInfo();
+      p->name = name;
+      p->betza = betza;
+      std::vector<char> moveTypes = {};
+      bool hopper = false;
+      bool rider = false;
+      std::vector<std::string> prelimDirections = {};
+      for (std::string::size_type i = 0; i < betza.size(); i++)
+      {
+          char c = betza[i];
+          // Move or capture
+          if (c == 'm' || c == 'c')
+              moveTypes.push_back(c);
+          // Hopper
+          else if (c == 'p')
+              hopper = true;
+          // Lame leaper
+          else if (c == 'n')
+              p->lameLeaper = true;
+          // Directional modifiers
+          else if (verticals.find(c) != std::string::npos || horizontals.find(c) != std::string::npos)
+          {
+              if (i + 1 < betza.size())
+              {
+                  char c2 = betza[i+1];
+                  // Can modifiers be combined?
+                  if (   c2 == c
+                      || (verticals.find(c) != std::string::npos && horizontals.find(c2) != std::string::npos)
+                      || (horizontals.find(c) != std::string::npos && verticals.find(c2) != std::string::npos))
+                  {
+                      prelimDirections.push_back(std::string(1, c) + c2);
+                      i++;
+                      continue;
+                  }
+              }
+              prelimDirections.push_back(std::string(2, c));
+          }
+          // Move atom
+          else if (leaperAtoms.find(c) != leaperAtoms.end() || riderAtoms.find(c) != riderAtoms.end())
+          {
+              const auto& atoms = riderAtoms.find(c) != riderAtoms.end() ? riderAtoms.find(c)->second
+                                                                         : leaperAtoms.find(c)->second;
+              // 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]))
+                  {
+                      // TODO: not supported
+                  }
+                  i++;
+              }
+              // No type qualifier means m+c
+              if (moveTypes.size() == 0)
+              {
+                  moveTypes.push_back('m');
+                  moveTypes.push_back('c');
+              }
+              // Define moves
+              for (const auto& atom : atoms)
+              {
+                  std::vector<std::string> directions = {};
+                  // Split directions for orthogonal pieces
+                  // This is required e.g. to correctly interpret fsW for soldiers
+                  for (auto s : prelimDirections)
+                      if (atoms.size() == 1 && atom.second == 0 && s[0] != s[1])
+                      {
+                          directions.push_back(std::string(2, s[0]));
+                          directions.push_back(std::string(2, s[1]));
+                      }
+                      else
+                          directions.push_back(s);
+                  // Add moves
+                  for (char mt : moveTypes)
+                  {
+                      std::vector<Direction>& 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.push_back(Direction(atom.first * FILE_NB + atom.second));
+                      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.push_back(Direction(-atom.first * FILE_NB - atom.second));
+                      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.push_back(Direction(-atom.second * FILE_NB + atom.first));
+                      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.push_back(Direction(atom.second * FILE_NB - atom.first));
+                      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.push_back(Direction(atom.second * FILE_NB + atom.first));
+                      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.push_back(Direction(-atom.second * FILE_NB - atom.first));
+                      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.push_back(Direction(-atom.first * FILE_NB + atom.second));
+                      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.push_back(Direction(atom.first * FILE_NB - atom.second));
+                  }
+              }
+              // Reset state
+              moveTypes.clear();
+              prelimDirections.clear();
+              hopper = false;
+              rider = false;
+          }
+      }
+      return p;
+  }
+  // Special multi-leg betza description for Janggi elephant
   PieceInfo* janggi_elephant_piece() {
       PieceInfo* p = new PieceInfo();
       p->name = "janggiElephant";
@@ -359,69 +178,49 @@ namespace {
       p->lameLeaper = true;
       return p;
   }
-  PieceInfo* banner_piece() {
-      PieceInfo* p = rook_piece();
-      p->name = "banner";
-      p->betza = "RcpRnN";
-      PieceInfo* p2 = horse_piece();
-      p->merge(p2);
-      delete p2;
-      p->hopperCapture = {NORTH, EAST, SOUTH, WEST};
-      p->lameLeaper = true;
-      return p;
-  }
-  PieceInfo* centaur_piece() {
-      PieceInfo* p = commoner_piece();
-      p->name = "centaur";
-      p->betza = "KN";
-      PieceInfo* p2 = knight_piece();
-      p->merge(p2);
-      delete p2;
-      return p;
-  }
 }
 
 void PieceMap::init() {
-  add(PAWN, pawn_piece());
-  add(KNIGHT, knight_piece());
-  add(BISHOP, bishop_piece());
-  add(ROOK, rook_piece());
-  add(QUEEN, queen_piece());
-  add(FERS, fers_piece());
-  add(ALFIL, alfil_piece());
-  add(FERS_ALFIL, fers_alfil_piece());
-  add(SILVER, silver_piece());
-  add(AIWOK, aiwok_piece());
-  add(BERS, bers_piece());
-  add(ARCHBISHOP, archbishop_piece());
-  add(CHANCELLOR, chancellor_piece());
-  add(AMAZON, amazon_piece());
-  add(KNIBIS, knibis_piece());
-  add(BISKNI, biskni_piece());
-  add(KNIROO, kniroo_piece());
-  add(ROOKNI, rookni_piece());
-  add(SHOGI_PAWN, shogi_pawn_piece());
-  add(LANCE, lance_piece());
-  add(SHOGI_KNIGHT, shogi_knight_piece());
-  add(EUROSHOGI_KNIGHT, euroshogi_knight_piece());
-  add(GOLD, gold_piece());
-  add(DRAGON_HORSE, dragon_horse_piece());
-  add(CLOBBER_PIECE, clobber_piece());
-  add(BREAKTHROUGH_PIECE, breakthrough_piece());
-  add(IMMOBILE_PIECE, immobile_piece());
-  add(ATAXX_PIECE, ataxx_piece());
-  add(QUIET_QUEEN, quiet_queen_piece());
-  add(CANNON, cannon_piece());
-  add(JANGGI_CANNON, janggi_cannon_piece());
-  add(SOLDIER, soldier_piece());
-  add(HORSE, horse_piece());
-  add(ELEPHANT, elephant_piece());
+  add(PAWN, from_betza("fmWfceF", "pawn"));
+  add(KNIGHT, from_betza("N", "knight"));
+  add(BISHOP, from_betza("B", "bishop"));
+  add(ROOK, from_betza("R", "rook"));
+  add(QUEEN, from_betza("Q", "queen"));
+  add(FERS, from_betza("F", "fers"));
+  add(ALFIL, from_betza("A", "alfil"));
+  add(FERS_ALFIL, from_betza("FA", "fersAlfil"));
+  add(SILVER, from_betza("FfW", "silver"));
+  add(AIWOK, from_betza("RNF", "aiwok"));
+  add(BERS, from_betza("RF", "bers"));
+  add(ARCHBISHOP, from_betza("BN", "archbishop"));
+  add(CHANCELLOR, from_betza("RN", "chancellor"));
+  add(AMAZON, from_betza("QN", "amazon"));
+  add(KNIBIS, from_betza("mNcB", "knibis"));
+  add(BISKNI, from_betza("mBcN", "biskni"));
+  add(KNIROO, from_betza("mNcR", "kniroo"));
+  add(ROOKNI, from_betza("mRcN", "rookni"));
+  add(SHOGI_PAWN, from_betza("fW", "shogiPawn"));
+  add(LANCE, from_betza("fR", "lance"));
+  add(SHOGI_KNIGHT, from_betza("fN", "shogiKnight"));
+  add(EUROSHOGI_KNIGHT, from_betza("fNsW", "euroshogiKnight"));
+  add(GOLD, from_betza("WfF", "gold"));
+  add(DRAGON_HORSE, from_betza("BW", "dragonHorse"));
+  add(CLOBBER_PIECE, from_betza("cW", "clobber"));
+  add(BREAKTHROUGH_PIECE, from_betza("fWfFcF", "breakthrough"));
+  add(IMMOBILE_PIECE, from_betza("", "immobile"));
+  add(ATAXX_PIECE, from_betza("mDmNmA", "ataxx"));
+  add(QUIET_QUEEN, from_betza("mQ", "quietQueen"));
+  add(CANNON, from_betza("mRcpR", "cannon"));
+  add(JANGGI_CANNON, from_betza("pR", "janggiCannon"));
+  add(SOLDIER, from_betza("fsW", "soldier"));
+  add(HORSE, from_betza("nN", "horse"));
+  add(ELEPHANT, from_betza("nA", "elephant"));
   add(JANGGI_ELEPHANT, janggi_elephant_piece());
-  add(BANNER, banner_piece());
-  add(WAZIR, wazir_piece());
-  add(COMMONER, commoner_piece());
-  add(CENTAUR, centaur_piece());
-  add(KING, king_piece());
+  add(BANNER, from_betza("RcpRnN", "banner"));
+  add(WAZIR, from_betza("W", "wazir"));
+  add(COMMONER, from_betza("K", "commoner"));
+  add(CENTAUR, from_betza("KN", "centaur"));
+  add(KING, from_betza("K", "king"));
 }
 
 void PieceMap::add(PieceType pt, const PieceInfo* p) {
index 61670bc..66fa36f 100644 (file)
@@ -38,8 +38,6 @@ struct PieceInfo {
   std::vector<Direction> hopperQuiet = {};
   std::vector<Direction> hopperCapture = {};
   bool lameLeaper = false;
-
-  void merge(const PieceInfo* pi);
 };
 
 struct PieceMap : public std::map<PieceType, const PieceInfo*> {