Use a general mobility bonus formula for fairy pieces
authorianfab <ianfab@users.noreply.github.com>
Sat, 7 Jul 2018 14:19:28 +0000 (16:19 +0200)
committerianfab <ianfab@users.noreply.github.com>
Sat, 7 Jul 2018 14:19:28 +0000 (16:19 +0200)
No functional change for standard chess.

src/evaluate.cpp
src/position.h
src/variant.cpp
src/variant.h

index da23236..5abb88a 100644 (file)
@@ -159,7 +159,7 @@ namespace {
   constexpr int PassedDanger[RANK_NB] = { 0, 0, 0, 3, 6, 12, 21 };
 
   // KingProtector[PieceType-2] contains a penalty according to distance from king
-  constexpr Score KingProtector[] = { S(3, 5), S(4, 3), S(3, 0), S(1, -1) };
+  constexpr Score KingProtector[PIECE_TYPE_NB - 2] = { S(3, 5), S(4, 3), S(3, 0), S(1, -1) };
 
   // Assorted bonuses and penalties
   constexpr Score BishopPawns        = S(  3,  5);
@@ -196,7 +196,7 @@ namespace {
 
   private:
     template<Color Us> void initialize();
-    template<Color Us, PieceType Pt> Score pieces();
+    template<Color Us> Score pieces(PieceType Pt);
     template<Color Us> Score king() const;
     template<Color Us> Score threats() const;
     template<Color Us> Score passed() const;
@@ -291,14 +291,14 @@ namespace {
 
 
   // Evaluation::pieces() scores pieces of a given color and type
-  template<Tracing T> template<Color Us, PieceType Pt>
-  Score Evaluation<T>::pieces() {
+  template<Tracing T> template<Color Us>
+  Score Evaluation<T>::pieces(PieceType Pt) {
 
     constexpr Color     Them = (Us == WHITE ? BLACK : WHITE);
     constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
     constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
                                                    : Rank5BB | Rank4BB | Rank3BB);
-    const Square* pl = pos.squares<Pt>(Us);
+    const Square* pl = pos.squares(Us, Pt);
 
     Bitboard b, bb;
     Square s;
@@ -330,7 +330,10 @@ namespace {
 
         int mob = popcount(b & mobilityArea[Us]);
 
-        mobility[Us] += MobilityBonus[Pt - 2][mob];
+        if (Pt <= QUEEN)
+            mobility[Us] += MobilityBonus[Pt - 2][mob];
+        else
+            mobility[Us] += make_score(300, 300) * (mob - 2) / (10 + mob);
 
         // Penalty if the piece is far from the king
         score -= KingProtector[Pt - 2] * distance(s, pos.square<KING>(Us));
@@ -909,10 +912,9 @@ namespace {
     initialize<BLACK>();
 
     // Pieces should be evaluated first (populate attack tables)
-    score +=  pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>()
-            + pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
-            + pieces<WHITE, ROOK  >() - pieces<BLACK, ROOK  >()
-            + pieces<WHITE, QUEEN >() - pieces<BLACK, QUEEN >();
+    for (PieceType pt : pos.piece_types())
+        if (pt != PAWN && pt != KING)
+            score += pieces<WHITE>(pt) - pieces<BLACK>(pt);
 
     score += mobility[WHITE] - mobility[BLACK];
 
index 5738427..1079764 100644 (file)
@@ -89,9 +89,10 @@ public:
   const Variant* variant() const;
   Rank max_rank() const;
   File max_file() const;
+  const std::set<PieceType>& piece_types() const;
   const std::string piece_to_char() const;
   Rank promotion_rank() const;
-  const std::vector<PieceType>& promotion_piece_types() const;
+  const std::set<PieceType, std::greater<PieceType> >& promotion_piece_types() const;
   bool double_step_enabled() const;
   bool castling_enabled() const;
   bool checking_permitted() const;
@@ -252,6 +253,11 @@ inline File Position::max_file() const {
   return var->maxFile;
 }
 
+inline const std::set<PieceType>& Position::piece_types() const {
+  assert(var != nullptr);
+  return var->pieceTypes;
+}
+
 inline const std::string Position::piece_to_char() const {
   assert(var != nullptr);
   return var->pieceToChar;
@@ -262,7 +268,7 @@ inline Rank Position::promotion_rank() const {
   return var->promotionRank;
 }
 
-inline const std::vector<PieceType>& Position::promotion_piece_types() const {
+inline const std::set<PieceType, std::greater<PieceType> >& Position::promotion_piece_types() const {
   assert(var != nullptr);
   return var->promotionPieceTypes;
 }
index 1b1c86f..df0820e 100644 (file)
@@ -27,19 +27,17 @@ using std::string;
 VariantMap variants; // Global object
 
 void VariantMap::init() {
+    // Define variant rules
     const Variant* chess = [&]{
         Variant* v = new Variant();
         return v;
     } ();
     const Variant* makruk = [&]{
         Variant* v = new Variant();
-        v->reset_pieces();
-        v->set_piece(PAWN, 'p');
-        v->set_piece(KNIGHT, 'n');
-        v->set_piece(KHON, 's');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(MET, 'm');
-        v->set_piece(KING, 'k');
+        v->remove_piece(BISHOP);
+        v->remove_piece(QUEEN);
+        v->add_piece(KHON, 's');
+        v->add_piece(MET, 'm');
         v->startFen = "rnsmksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKMSNR w - - 0 1";
         v->promotionRank = RANK_6;
         v->promotionPieceTypes = {MET};
@@ -49,13 +47,10 @@ void VariantMap::init() {
     } ();
     const Variant* asean = [&]{
         Variant* v = new Variant();
-        v->reset_pieces();
-        v->set_piece(PAWN, 'p');
-        v->set_piece(KNIGHT, 'n');
-        v->set_piece(KHON, 'b');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(MET, 'q');
-        v->set_piece(KING, 'k');
+        v->remove_piece(BISHOP);
+        v->remove_piece(QUEEN);
+        v->add_piece(KHON, 'b');
+        v->add_piece(MET, 'q');
         v->startFen = "rnbqkbnr/8/pppppppp/8/8/PPPPPPPP/8/RNBQKBNR w - - 0 1";
         v->promotionPieceTypes = {ROOK, KNIGHT, KHON, MET};
         v->doubleStep = false;
@@ -64,13 +59,10 @@ void VariantMap::init() {
     } ();
     const Variant* aiwok = [&]{
         Variant* v = new Variant();
-        v->reset_pieces();
-        v->set_piece(PAWN, 'p');
-        v->set_piece(KNIGHT, 'n');
-        v->set_piece(KHON, 's');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(AIWOK, 'a');
-        v->set_piece(KING, 'k');
+        v->remove_piece(BISHOP);
+        v->remove_piece(QUEEN);
+        v->add_piece(KHON, 's');
+        v->add_piece(AIWOK, 'a');
         v->startFen = "rnsaksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKASNR w - - 0 1";
         v->promotionRank = RANK_6;
         v->promotionPieceTypes = {AIWOK};
@@ -80,13 +72,10 @@ void VariantMap::init() {
     } ();
     const Variant* shatranj = [&]{
         Variant* v = new Variant();
-        v->reset_pieces();
-        v->set_piece(PAWN, 'p');
-        v->set_piece(KNIGHT, 'n');
-        v->set_piece(ALFIL, 'b');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(FERS, 'q');
-        v->set_piece(KING, 'k');
+        v->remove_piece(BISHOP);
+        v->remove_piece(QUEEN);
+        v->add_piece(ALFIL, 'b');
+        v->add_piece(FERS, 'q');
         v->startFen = "rnbkqbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBKQBNR w - - 0 1";
         v->promotionPieceTypes = {FERS};
         v->doubleStep = false;
@@ -98,18 +87,18 @@ void VariantMap::init() {
     } ();
     const Variant* amazon = [&]{
         Variant* v = new Variant();
-        v->set_piece(QUEEN, ' ');
-        v->set_piece(AMAZON, 'a');
+        v->remove_piece(QUEEN);
+        v->add_piece(AMAZON, 'a');
         v->startFen = "rnbakbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBAKBNR w KQkq - 0 1";
         v->promotionPieceTypes = {AMAZON, ROOK, BISHOP, KNIGHT};
         return v;
     } ();
     const Variant* hoppelpoppel = [&]{
         Variant* v = new Variant();
-        v->set_piece(KNIGHT, ' ');
-        v->set_piece(BISHOP, ' ');
-        v->set_piece(KNIBIS, 'n');
-        v->set_piece(BISKNI, 'b');
+        v->remove_piece(KNIGHT);
+        v->remove_piece(BISHOP);
+        v->add_piece(KNIBIS, 'n');
+        v->add_piece(BISKNI, 'b');
         v->promotionPieceTypes = {QUEEN, ROOK, BISKNI, KNIBIS};
         return v;
     } ();
@@ -167,12 +156,12 @@ void VariantMap::init() {
     const Variant* euroshogi = [&]{
         Variant* v = new Variant();
         v->reset_pieces();
-        v->set_piece(SHOGI_PAWN, 'p');
-        v->set_piece(EUROSHOGI_KNIGHT, 'n');
-        v->set_piece(GOLD, 'g');
-        v->set_piece(BISHOP, 'b');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(KING, 'k');
+        v->add_piece(SHOGI_PAWN, 'p');
+        v->add_piece(EUROSHOGI_KNIGHT, 'n');
+        v->add_piece(GOLD, 'g');
+        v->add_piece(BISHOP, 'b');
+        v->add_piece(ROOK, 'r');
+        v->add_piece(KING, 'k');
         v->startFen = "1nbgkgn1/1r4b1/pppppppp/8/8/PPPPPPPP/1B4R1/1NGKGBN1[-] w 0 1";
         v->pieceDrops = true;
         v->promotionRank = RANK_6;
@@ -187,12 +176,12 @@ void VariantMap::init() {
         v->maxRank = RANK_5;
         v->maxFile = FILE_E;
         v->reset_pieces();
-        v->set_piece(SHOGI_PAWN, 'p');
-        v->set_piece(SILVER, 's');
-        v->set_piece(GOLD, 'g');
-        v->set_piece(BISHOP, 'b');
-        v->set_piece(ROOK, 'r');
-        v->set_piece(KING, 'k');
+        v->add_piece(SHOGI_PAWN, 'p');
+        v->add_piece(SILVER, 's');
+        v->add_piece(GOLD, 'g');
+        v->add_piece(BISHOP, 'b');
+        v->add_piece(ROOK, 'r');
+        v->add_piece(KING, 'k');
         v->startFen = "rbsgk/4p/5/P4/KGSBR[-] w 0 1";
         v->pieceDrops = true;
         v->promotionRank = RANK_5;
@@ -206,7 +195,7 @@ void VariantMap::init() {
         Variant* v = new Variant();
         v->maxRank = RANK_6;
         v->maxFile = FILE_F;
-        v->set_piece(BISHOP, ' ');
+        v->remove_piece(BISHOP);
         v->startFen = "rnqknr/pppppp/6/6/PPPPPP/RNQKNR w - - 0 1";
         v->promotionRank = RANK_6;
         v->promotionPieceTypes = {QUEEN, ROOK, KNIGHT};
@@ -214,28 +203,41 @@ void VariantMap::init() {
         v->castling = false;
         return v;
     } ();
-    insert(std::pair<std::string, const Variant*>(std::string("chess"), chess));
-    insert(std::pair<std::string, const Variant*>(std::string("makruk"), makruk));
-    insert(std::pair<std::string, const Variant*>(std::string("asean"), asean));
-    insert(std::pair<std::string, const Variant*>(std::string("ai-wok"), aiwok));
-    insert(std::pair<std::string, const Variant*>(std::string("shatranj"), shatranj));
-    insert(std::pair<std::string, const Variant*>(std::string("amazon"), amazon));
-    insert(std::pair<std::string, const Variant*>(std::string("hoppelpoppel"), hoppelpoppel));
-    insert(std::pair<std::string, const Variant*>(std::string("kingofthehill"), kingofthehill));
-    insert(std::pair<std::string, const Variant*>(std::string("racingkings"), racingkings));
-    insert(std::pair<std::string, const Variant*>(std::string("losers"), losers));
-    insert(std::pair<std::string, const Variant*>(std::string("3check"), threecheck));
-    insert(std::pair<std::string, const Variant*>(std::string("5check"), fivecheck));
-    insert(std::pair<std::string, const Variant*>(std::string("crazyhouse"), crazyhouse));
-    insert(std::pair<std::string, const Variant*>(std::string("loop"), loop));
-    insert(std::pair<std::string, const Variant*>(std::string("euroshogi"), euroshogi));
-    insert(std::pair<std::string, const Variant*>(std::string("minishogi"), minishogi));
-    insert(std::pair<std::string, const Variant*>(std::string("losalamos"), losalamos));
+
+    // Add to UCI_Variant option
+    add("chess", chess);
+    add("standard", chess);
+    add("makruk", makruk);
+    add("asean", asean);
+    add("ai-wok", aiwok);
+    add("shatranj", shatranj);
+    add("amazon", amazon);
+    add("hoppelpoppel", hoppelpoppel);
+    add("kingofthehill", kingofthehill);
+    add("racingkings", racingkings);
+    add("losers", losers);
+    add("3check", threecheck);
+    add("5check", fivecheck);
+    add("crazyhouse", crazyhouse);
+    add("loop", loop);
+    add("euroshogi", euroshogi);
+    add("minishogi", minishogi);
+    add("losalamos", losalamos);
+}
+
+void VariantMap::add(std::string s, const Variant* v) {
+  insert(std::pair<std::string, const Variant*>(s, v));
 }
 
 void VariantMap::clear_all() {
+  std::set<const Variant*> deleted_vars;
   for (auto const& element : *this) {
-      delete element.second;
+      // Delete duplicated variants (synonyms) only once
+      if (deleted_vars.find(element.second) == deleted_vars.end())
+      {
+          delete element.second;
+          deleted_vars.insert(element.second);
+      }
   }
   clear();
 }
index 9b313a2..82f695d 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef VARIANT_H_INCLUDED
 #define VARIANT_H_INCLUDED
 
+#include <set>
 #include <map>
 #include <vector>
 #include <string>
 struct Variant {
   Rank maxRank = RANK_8;
   File maxFile = FILE_H;
+  std::set<PieceType> pieceTypes = { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING };
   std::string pieceToChar =  " PNBRQ" + std::string(KING - QUEEN - 1, ' ') + "K" + std::string(PIECE_TYPE_NB - KING - 1, ' ')
                            + " pnbrq" + std::string(KING - QUEEN - 1, ' ') + "k" + std::string(PIECE_TYPE_NB - KING - 1, ' ');
   std::string startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
   Rank promotionRank = RANK_8;
-  std::vector<PieceType> promotionPieceTypes = {QUEEN, ROOK, BISHOP, KNIGHT};
+  std::set<PieceType, std::greater<PieceType> > promotionPieceTypes = { QUEEN, ROOK, BISHOP, KNIGHT };
   bool doubleStep = true;
   bool castling = true;
   bool checking = true;
@@ -55,18 +57,27 @@ struct Variant {
   bool flagMove = false;
   CheckCount maxCheckCount = CheckCount(0);
 
-  void set_piece(PieceType pt, char c) {
+  void add_piece(PieceType pt, char c) {
       pieceToChar[make_piece(WHITE, pt)] = toupper(c);
       pieceToChar[make_piece(BLACK, pt)] = tolower(c);
+      pieceTypes.insert(pt);
+  }
+
+  void remove_piece(PieceType pt) {
+      pieceToChar[make_piece(WHITE, pt)] = ' ';
+      pieceToChar[make_piece(BLACK, pt)] = ' ';
+      pieceTypes.erase(pt);
   }
 
   void reset_pieces() {
       pieceToChar = std::string(PIECE_NB, ' ');
+      pieceTypes.clear();
   }
 };
 
 struct VariantMap : public std::map<std::string, const Variant*> {
   void init();
+  void add(std::string s, const Variant* v);
   void clear_all();
   std::vector<std::string> get_keys();
 };