Support mobility region config for custom pieces
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 8 May 2021 12:26:06 +0000 (14:26 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 8 May 2021 12:26:06 +0000 (14:26 +0200)
src/apiutil.h
src/parser.cpp
src/piece.h
src/psqt.cpp
src/types.h
src/variant.h

index 267e42e..7fe7c54 100644 (file)
@@ -306,7 +306,7 @@ inline bool has_insufficient_material(Color c, const Position& pos) {
     for (PieceType pt : pos.piece_types())
         if (pt == KING || !(pos.board_bb(c, pt) & pos.board_bb(~c, KING)))
             restricted |= pos.pieces(c, pt);
-        else if (pt >= CUSTOM_PIECES && pt <= CUSTOM_PIECES_END && pos.count(c, pt) > 0)
+        else if (is_custom(pt) && pos.count(c, pt) > 0)
             // to be conservative, assume any custom piece has mating potential
             return false;
 
index 5f8de07..e25bf91 100644 (file)
@@ -160,51 +160,38 @@ Variant* VariantParser<DoCheck>::parse() {
 template <bool DoCheck>
 Variant* VariantParser<DoCheck>::parse(Variant* v) {
     // piece types
-    for (const auto& pieceInfo : pieceMap)
+    for (PieceType pt = PAWN; pt <= KING; ++pt)
     {
         // piece char
-        const auto& keyValue = config.find(pieceInfo.second->name);
+        std::string name = piece_name(pt);
+
+        const auto& keyValue = config.find(name);
         if (keyValue != config.end() && !keyValue->second.empty())
         {
             if (isalpha(keyValue->second.at(0)))
-                v->add_piece(pieceInfo.first, keyValue->second.at(0));
+                v->add_piece(pt, keyValue->second.at(0));
             else
             {
                 if (DoCheck && keyValue->second.at(0) != '-')
-                    std::cerr << pieceInfo.second->name << " - Invalid letter: " << keyValue->second.at(0) << std::endl;
-                v->remove_piece(pieceInfo.first);
+                    std::cerr << name << " - Invalid letter: " << keyValue->second.at(0) << std::endl;
+                v->remove_piece(pt);
+            }
+            // betza
+            if (is_custom(pt))
+            {
+                if (keyValue->second.size() > 1)
+                    v->customPiece[pt - CUSTOM_PIECES] = keyValue->second.substr(2);
+                else if (DoCheck)
+                    std::cerr << name << " - Missing Betza move notation" << std::endl;
             }
         }
         // mobility region
-        std::string capitalizedPiece = pieceInfo.second->name;
+        std::string capitalizedPiece = name;
         capitalizedPiece[0] = toupper(capitalizedPiece[0]);
         for (Color c : {WHITE, BLACK})
         {
             std::string color = c == WHITE ? "White" : "Black";
-            parse_attribute("mobilityRegion" + color + capitalizedPiece, v->mobilityRegion[c][pieceInfo.first]);
-        }
-    }
-    // custom piece types
-    for (PieceType pt = CUSTOM_PIECES; pt <= CUSTOM_PIECES_END; ++pt)
-    {
-        std::string customPieceName = "customPiece" + std::to_string(pt - CUSTOM_PIECES + 1);
-        const auto& itCustomPt = config.find(customPieceName);
-        if (itCustomPt != config.end() && !itCustomPt->second.empty())
-        {
-            // piece char
-            if (isalpha(itCustomPt->second.at(0)))
-                v->add_piece(pt, itCustomPt->second.at(0));
-            else
-            {
-                if (DoCheck && itCustomPt->second.at(0) != '-')
-                    std::cerr << customPieceName << " - Invalid letter: " << itCustomPt->second.at(0) << std::endl;
-                v->remove_piece(pt);
-            }
-            // betza
-            if (itCustomPt->second.size() > 1)
-                v->customPiece[pt - CUSTOM_PIECES] = itCustomPt->second.substr(2);
-            else if (DoCheck)
-                std::cerr << customPieceName << " - Missing Betza move notation" << std::endl;
+            parse_attribute("mobilityRegion" + color + capitalizedPiece, v->mobilityRegion[c][pt]);
         }
     }
     // piece values
@@ -375,6 +362,14 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
     // Check consistency
     if (DoCheck)
     {
+        // pieces
+        for (PieceType pt : v->pieceTypes)
+        {
+            for (Color c : {WHITE, BLACK})
+                if (std::count(v->pieceToChar.begin(), v->pieceToChar.end(), v->pieceToChar[make_piece(c, pt)]) != 1)
+                    std::cerr << piece_name(pt) << " - Ambiguous piece character: " << v->pieceToChar[make_piece(c, pt)] << std::endl;
+        }
+
         // startFen
         if (FEN::validate_fen(v->startFen, v, v->chess960) != FEN::FEN_OK)
             std::cerr << "startFen - Invalid starting position: " << v->startFen << std::endl;
@@ -418,11 +413,17 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
                 std::cerr << "Can not use kings with blastOnCapture." << std::endl;
             if (v->flipEnclosedPieces)
                 std::cerr << "Can not use kings with flipEnclosedPieces." << std::endl;
-            const PieceInfo* pi = pieceMap.find(v->kingType)->second;
-            if (   pi->hopper[MODALITY_QUIET].size()
-                || pi->hopper[MODALITY_CAPTURE].size()
-                || std::any_of(pi->steps[MODALITY_CAPTURE].begin(), pi->steps[MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return d.second; }))
-                std::cerr << pi->name << " is not supported as kingType." << std::endl;
+            // We can not fully check custom king movements at this point
+            if (!is_custom(v->kingType))
+            {
+                const PieceInfo* pi = pieceMap.find(v->kingType)->second;
+                if (   pi->hopper[MODALITY_QUIET].size()
+                    || pi->hopper[MODALITY_CAPTURE].size()
+                    || std::any_of(pi->steps[MODALITY_CAPTURE].begin(),
+                                pi->steps[MODALITY_CAPTURE].end(),
+                                [](const std::pair<const Direction, int>& d) { return d.second; }))
+                    std::cerr << piece_name(v->kingType) << " is not supported as kingType." << std::endl;
+            }
         }
     }
     return v;
index 0a9e9a1..ac73e6e 100644 (file)
@@ -46,4 +46,9 @@ struct PieceMap : public std::map<PieceType, const PieceInfo*> {
 
 extern PieceMap pieceMap;
 
+inline std::string piece_name(PieceType pt) {
+  return is_custom(pt) ? "customPiece" + std::to_string(pt - CUSTOM_PIECES + 1)
+                       : pieceMap.find(pt)->second->name;
+}
+
 #endif // #ifndef PIECE_H_INCLUDED
index 273560b..64b8161 100644 (file)
@@ -182,7 +182,7 @@ void init(const Variant* v) {
   PieceType strongestPiece = NO_PIECE_TYPE;
   for (PieceType pt : v->pieceTypes)
   {
-      if (pt >= CUSTOM_PIECES && pt <= CUSTOM_PIECES_END)
+      if (is_custom(pt))
       {
           PieceValue[MG][pt] = piece_value(MG, pt);
           PieceValue[EG][pt] = piece_value(EG, pt);
index a2ea3b9..a343f74 100644 (file)
@@ -791,6 +791,10 @@ constexpr PieceType in_hand_piece_type(Move m) {
   return PieceType((m >> (2 * SQUARE_BITS + MOVE_TYPE_BITS + PIECE_TYPE_BITS)) & (PIECE_TYPE_NB - 1));
 }
 
+inline bool is_custom(PieceType pt) {
+  return pt >= CUSTOM_PIECES && pt <= CUSTOM_PIECES_END;
+}
+
 inline bool is_ok(Move m) {
   return from_sq(m) != to_sq(m) || type_of(m) == PROMOTION || type_of(m) == SPECIAL; // Catch MOVE_NULL and MOVE_NONE
 }
index 61cbdf7..9faeec9 100644 (file)
@@ -146,7 +146,7 @@ struct Variant {
       pieceToCharSynonyms[make_piece(BLACK, pt)] = tolower(c2);
       pieceTypes.insert(pt);
       // Add betza notation for custom piece
-      if (pt >= CUSTOM_PIECES && pt <= CUSTOM_PIECES_END)
+      if (is_custom(pt))
           customPiece[pt - CUSTOM_PIECES] = betza;
   }