Rewrite definition of piece types
authorFabian Fichter <ianfab@users.noreply.github.com>
Tue, 2 Apr 2019 19:00:14 +0000 (21:00 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Tue, 9 Apr 2019 20:53:29 +0000 (22:53 +0200)
No functional change.

src/Makefile
src/bitboard.cpp
src/main.cpp
src/piece.cpp [new file with mode: 0644]
src/piece.h [new file with mode: 0644]

index c73379f..942049e 100644 (file)
@@ -37,7 +37,7 @@ PGOBENCH = ./$(EXE) bench
 
 ### Object files
 OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
-       material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \
+       material.o misc.o movegen.o movepick.o pawns.o piece.o position.o psqt.o \
        search.o thread.o timeman.o tt.o uci.o ucioption.o variant.o syzygy/tbprobe.o
 
 ### Establish the operating system name
index e812cb8..ec2edc0 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "bitboard.h"
 #include "misc.h"
+#include "piece.h"
 
 uint8_t PopCnt16[1 << 16];
 uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
@@ -307,19 +308,19 @@ namespace {
 #endif
 
 #ifdef PRECOMPUTED_MAGICS
-  void init_magics(Bitboard table[], Magic magics[], Direction directions[], Bitboard magicsInit[]);
+  void init_magics(Bitboard table[], Magic magics[], std::vector<Direction> directions, Bitboard magicsInit[]);
 #else
-  void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
+  void init_magics(Bitboard table[], Magic magics[], std::vector<Direction> directions);
 #endif
 
-  Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied, int maxDist = FILE_MAX, Color c = WHITE) {
+  Bitboard sliding_attack(std::vector<Direction> directions, Square sq, Bitboard occupied, Color c = WHITE) {
 
     Bitboard attack = 0;
 
-    for (int i = 0; directions[i]; ++i)
-        for (Square s = sq + (c == WHITE ? directions[i] : -directions[i]);
-             is_ok(s) && distance(s, s - (c == WHITE ? directions[i] : -directions[i])) == 1 && distance(s, sq) <= maxDist;
-             s += (c == WHITE ? directions[i] : -directions[i]))
+    for (Direction d : directions)
+        for (Square s = sq + (c == WHITE ? d : -d);
+             is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) == 1;
+             s += (c == WHITE ? d : -d))
         {
             attack |= s;
 
@@ -374,8 +375,8 @@ void Bitboards::init() {
           }
 
   // Piece moves
-  Direction RookDirections[5] = { NORTH,  EAST,  SOUTH,  WEST };
-  Direction BishopDirections[5] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
+  std::vector<Direction> RookDirections = { NORTH,  EAST,  SOUTH,  WEST };
+  std::vector<Direction> BishopDirections = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
 
 #ifdef PRECOMPUTED_MAGICS
   init_magics(RookTable, RookMagics, RookDirections, RookMagicInit);
@@ -385,206 +386,16 @@ void Bitboards::init() {
   init_magics(BishopTable, BishopMagics, BishopDirections);
 #endif
 
-  int stepsCapture[][13] = {
-      {}, // NO_PIECE_TYPE
-      { NORTH_WEST, NORTH_EAST }, // pawn
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
-      {}, // bishop
-      {}, // rook
-      {}, // queen
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
-      { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
-      {}, // knibis
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // biskni
-      { NORTH }, // shogi pawn
-      {}, // lance
-      {  2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
-      { WEST, EAST,  2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
-      { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
-      { SOUTH, WEST, EAST, NORTH }, // horse
-      { SOUTH, WEST, EAST, NORTH }, // clobber
-      { NORTH_WEST, NORTH_EAST }, // breakthrough
-      {}, // immobile
-      { SOUTH, WEST, EAST, NORTH }, // wazir
-      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
-      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
-  };
-  int stepsQuiet[][13] = {
-      {}, // NO_PIECE_TYPE
-      { NORTH }, // pawn
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
-      {}, // bishop
-      {}, // rook
-      {}, // queen
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
-      { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
-      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
-      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
-        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knibis
-      {}, // biskni
-      { NORTH }, // shogi pawn
-      {}, // lance
-      {  2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
-      { WEST, EAST,  2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
-      { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
-      { SOUTH, WEST, EAST, NORTH }, // horse
-      {}, // clobber
-      { NORTH_WEST, NORTH, NORTH_EAST }, // breakthrough
-      {}, // immobile
-      { SOUTH, WEST, EAST, NORTH }, // wazir
-      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
-      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
-  };
-  Direction sliderCapture[][9] = {
-    {}, // NO_PIECE_TYPE
-    {}, // pawn
-    {}, // knight
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
-    { NORTH,  EAST,  SOUTH,  WEST }, // rook
-    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
-    {}, // fers/met
-    {}, // alfil
-    {}, // silver/khon
-    { NORTH,  EAST,  SOUTH,  WEST }, // aiwok
-    { NORTH,  EAST,  SOUTH,  WEST }, // bers/dragon
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
-    { NORTH,  EAST,  SOUTH,  WEST }, // chancellor
-    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // knibis
-    {}, // biskni
-    {}, // shogi pawn
-    { NORTH }, // lance
-    {}, // shogi knight
-    {}, // euroshogi knight
-    {}, // gold
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
-    {}, // clobber
-    {}, // breakthrough
-    {}, // immobile
-    {}, // wazir
-    {}, // commoner
-    {} // king
-  };
-  Direction sliderQuiet[][9] = {
-    {}, // NO_PIECE_TYPE
-    {}, // pawn
-    {}, // knight
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
-    { NORTH,  EAST,  SOUTH,  WEST }, // rook
-    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
-    {}, // fers/met
-    {}, // alfil
-    {}, // silver/khon
-    { NORTH,  EAST,  SOUTH,  WEST }, // aiwok
-    { NORTH,  EAST,  SOUTH,  WEST }, // bers/dragon
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
-    { NORTH,  EAST,  SOUTH,  WEST }, // chancellor
-    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
-    {}, // knibis
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // biskni
-    {}, // shogi pawn
-    { NORTH }, // lance
-    {}, // shogi knight
-    {}, // euroshogi knight
-    {}, // gold
-    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
-    {}, // clobber
-    {}, // breakthrough
-    {}, // immobile
-    {}, // wazir
-    {}, // commoner
-    {} // king
-  };
-  int sliderDistCapture[] = {
-    0, // NO_PIECE_TYPE
-    0, // pawn
-    0, // knight
-    FILE_MAX, // bishop
-    FILE_MAX, // rook
-    FILE_MAX, // queen
-    0, // fers/met
-    0, // alfil
-    0, // silver/khon
-    FILE_MAX, // aiwok
-    FILE_MAX, // bers/dragon
-    FILE_MAX, // archbishop
-    FILE_MAX, // chancellor
-    FILE_MAX, // amazon
-    FILE_MAX, // knibis
-    0, // biskni
-    0, // shogi pawn
-    FILE_MAX, // lance
-    0, // shogi knight
-    0, // euroshogi knight
-    0, // gold
-    FILE_MAX, // horse
-    0, // clobber
-    0, // breakthrough
-    0, // immobile
-    0, // wazir
-    0, // commoner
-    0  // king
-  };
-  int sliderDistQuiet[] = {
-    0, // NO_PIECE_TYPE
-    0, // pawn
-    0, // knight
-    FILE_MAX, // bishop
-    FILE_MAX, // rook
-    FILE_MAX, // queen
-    0, // fers/met
-    0, // alfil
-    0, // silver/khon
-    FILE_MAX, // aiwok
-    FILE_MAX, // bers/dragon
-    FILE_MAX, // archbishop
-    FILE_MAX, // chancellor
-    FILE_MAX, // amazon
-    0, // knibis
-    FILE_MAX, // biskni
-    0, // shogi pawn
-    FILE_MAX, // lance
-    0, // shogi knight
-    0, // euroshogi knight
-    0, // gold
-    FILE_MAX, // horse
-    0, // clobber
-    0, // breakthrough
-    0, // immobile
-    0, // wazir
-    0, // commoner
-    0  // king
-  };
-
   for (Color c = WHITE; c <= BLACK; ++c)
       for (PieceType pt = PAWN; pt <= KING; ++pt)
+      {
+          const PieceInfo* pi = pieceMap.find(pt)->second;
+
           for (Square s = SQ_A1; s <= SQ_MAX; ++s)
           {
-              for (int i = 0; stepsCapture[pt][i]; ++i)
+              for (Direction d : pi->stepsCapture)
               {
-                  Square to = s + Direction(c == WHITE ? stepsCapture[pt][i] : -stepsCapture[pt][i]);
+                  Square to = s + Direction(c == WHITE ? d : -d);
 
                   if (is_ok(to) && distance(s, to) < 4)
                   {
@@ -592,9 +403,9 @@ void Bitboards::init() {
                       LeaperAttacks[c][pt][s] |= to;
                   }
               }
-              for (int i = 0; stepsQuiet[pt][i]; ++i)
+              for (Direction d : pi->stepsQuiet)
               {
-                  Square to = s + Direction(c == WHITE ? stepsQuiet[pt][i] : -stepsQuiet[pt][i]);
+                  Square to = s + Direction(c == WHITE ? d : -d);
 
                   if (is_ok(to) && distance(s, to) < 4)
                   {
@@ -602,9 +413,10 @@ void Bitboards::init() {
                       LeaperMoves[c][pt][s] |= to;
                   }
               }
-              PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt], c);
-              PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt], c);
+              PseudoAttacks[c][pt][s] |= sliding_attack(pi->sliderCapture, s, 0, c);
+              PseudoMoves[c][pt][s] |= sliding_attack(pi->sliderQuiet, s, 0, c);
           }
+      }
 
   for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
   {
@@ -624,9 +436,9 @@ namespace {
   // called "fancy" approach.
 
 #ifdef PRECOMPUTED_MAGICS
-  void init_magics(Bitboard table[], Magic magics[], Direction directions[], Bitboard magicsInit[]) {
+  void init_magics(Bitboard table[], Magic magics[], std::vector<Direction> directions, Bitboard magicsInit[]) {
 #else
-  void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
+  void init_magics(Bitboard table[], Magic magics[], std::vector<Direction> directions) {
 #endif
 
     // Optimal PRNG seeds to pick the correct magics in the shortest time
index 68099dd..f5f7ff7 100644 (file)
@@ -26,6 +26,7 @@
 #include "thread.h"
 #include "tt.h"
 #include "uci.h"
+#include "piece.h"
 #include "variant.h"
 #include "syzygy/tbprobe.h"
 
@@ -37,6 +38,7 @@ int main(int argc, char* argv[]) {
 
   std::cout << engine_info() << std::endl;
 
+  pieceMap.init();
   variants.init();
   UCI::init(Options);
   PSQT::init(variants.find("chess")->second);
@@ -51,5 +53,6 @@ int main(int argc, char* argv[]) {
 
   Threads.set(0);
   variants.clear_all();
+  pieceMap.clear_all();
   return 0;
 }
diff --git a/src/piece.cpp b/src/piece.cpp
new file mode 100644 (file)
index 0000000..b510bb0
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+  Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish
+  Copyright (C) 2018-2019 Fabian Fichter
+
+  Fairy-Stockfish is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Fairy-Stockfish is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string>
+
+#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->stepsQuiet = {NORTH};
+      p->stepsCapture = {NORTH_WEST, NORTH_EAST};
+      return p;
+  }
+  PieceInfo* knight_piece() {
+      PieceInfo* p = new PieceInfo();
+      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->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->sliderQuiet = {NORTH, EAST, SOUTH, WEST};
+      p->sliderCapture = {NORTH, EAST, SOUTH, WEST};
+      return p;
+  }
+  PieceInfo* queen_piece() {
+      PieceInfo* p = new PieceInfo();
+      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->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* fers_piece() {
+      PieceInfo* p = new PieceInfo();
+      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->stepsQuiet = {SOUTH, WEST, EAST, NORTH};
+      p->stepsCapture = {SOUTH, WEST, EAST, NORTH};
+      return p;
+  }
+  PieceInfo* alfil_piece() {
+      PieceInfo* p = new PieceInfo();
+      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* silver_piece() {
+      PieceInfo* p = new PieceInfo();
+      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();
+      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();
+      PieceInfo* p2 = fers_piece();
+      p->merge(p2);
+      delete p2;
+      return p;
+  }
+  PieceInfo* archbishop_piece() {
+      PieceInfo* p = bishop_piece();
+      PieceInfo* p2 = knight_piece();
+      p->merge(p2);
+      delete p2;
+      return p;
+  }
+  PieceInfo* chancellor_piece() {
+      PieceInfo* p = rook_piece();
+      PieceInfo* p2 = knight_piece();
+      p->merge(p2);
+      delete p2;
+      return p;
+  }
+  PieceInfo* amazon_piece() {
+      PieceInfo* p = queen_piece();
+      PieceInfo* p2 = knight_piece();
+      p->merge(p2);
+      delete p2;
+      return p;
+  }
+  PieceInfo* knibis_piece() {
+      PieceInfo* p = bishop_piece();
+      PieceInfo* p2 = knight_piece();
+      p->merge(p2);
+      delete p2;
+      p->stepsCapture = {};
+      p->sliderQuiet = {};
+      return p;
+  }
+  PieceInfo* biskni_piece() {
+      PieceInfo* p = bishop_piece();
+      PieceInfo* p2 = knight_piece();
+      p->merge(p2);
+      delete p2;
+      p->stepsQuiet = {};
+      p->sliderCapture = {};
+      return p;
+  }
+  PieceInfo* shogi_pawn_piece() {
+      PieceInfo* p = new PieceInfo();
+      p->stepsQuiet = {NORTH};
+      p->stepsCapture = {NORTH};
+      return p;
+  }
+  PieceInfo* lance_piece() {
+      PieceInfo* p = new PieceInfo();
+      p->sliderQuiet = {NORTH};
+      p->sliderCapture = {NORTH};
+      return p;
+  }
+  PieceInfo* shogi_knight_piece() {
+      PieceInfo* p = new PieceInfo();
+      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->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->stepsQuiet = {SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
+      p->stepsCapture = {SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST};
+      return p;
+  }
+  PieceInfo* horse_piece() {
+      PieceInfo* p = bishop_piece();
+      PieceInfo* p2 = wazir_piece();
+      p->merge(p2);
+      delete p2;
+      return p;
+  }
+  PieceInfo* clobber_piece() {
+      PieceInfo* p = wazir_piece();
+      p->stepsQuiet = {};
+      return p;
+  }
+  PieceInfo* breakthrough_piece() {
+      PieceInfo* p = pawn_piece();
+      p->stepsQuiet.push_back(NORTH_WEST);
+      p->stepsQuiet.push_back(NORTH_EAST);
+      return p;
+  }
+  PieceInfo* immobile_piece() {
+      PieceInfo* p = new PieceInfo();
+      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(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(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(HORSE, horse_piece());
+  add(CLOBBER_PIECE, clobber_piece());
+  add(BREAKTHROUGH_PIECE, breakthrough_piece());
+  add(IMMOBILE_PIECE, immobile_piece());
+  add(WAZIR, wazir_piece());
+  add(COMMONER, king_piece());
+  add(KING, king_piece());
+}
+
+void PieceMap::add(PieceType pt, const PieceInfo* p) {
+  insert(std::pair<PieceType, const PieceInfo*>(pt, p));
+}
+
+void PieceMap::clear_all() {
+  for (auto const& element : *this)
+      delete element.second;
+  clear();
+}
diff --git a/src/piece.h b/src/piece.h
new file mode 100644 (file)
index 0000000..a6404e5
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+  Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish
+  Copyright (C) 2018-2019 Fabian Fichter
+
+  Fairy-Stockfish is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Fairy-Stockfish is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PIECE_H_INCLUDED
+#define PIECE_H_INCLUDED
+
+#include <map>
+#include <vector>
+
+#include "types.h"
+
+
+/// PieceInfo struct stores information about the piece movements.
+
+struct PieceInfo {
+  std::vector<Direction> stepsQuiet = {};
+  std::vector<Direction> stepsCapture = {};
+  std::vector<Direction> sliderQuiet = {};
+  std::vector<Direction> sliderCapture = {};
+
+  void merge(const PieceInfo* pi);
+};
+
+struct PieceMap : public std::map<PieceType, const PieceInfo*> {
+  void init();
+  void add(PieceType pt, const PieceInfo* v);
+  void clear_all();
+};
+
+extern PieceMap pieceMap;
+
+#endif // #ifndef PIECE_H_INCLUDED