Support Manchu chess
authorFabian Fichter <ianfab@users.noreply.github.com>
Fri, 15 Nov 2019 15:31:44 +0000 (16:31 +0100)
committerFabian Fichter <ianfab@users.noreply.github.com>
Fri, 15 Nov 2019 15:31:44 +0000 (16:31 +0100)
https://en.wikipedia.org/wiki/Manchu_chess

bench: 4700464

Readme.md
src/movegen.cpp
src/piece.cpp
src/position.cpp
src/psqt.cpp
src/types.h
src/variant.cpp
src/variants.ini

index a989b78..a52651b 100644 (file)
--- a/Readme.md
+++ b/Readme.md
@@ -14,7 +14,7 @@ The goal of the project is to create an engine supporting a large variety of che
 The games currently supported besides chess are listed below. Fairy-Stockfish can also play user-defined variants loaded via a variant configuration file, see the file `src/variants.ini`.
 
 ### Regional and historical games
-- [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi), [Minixiangqi](http://mlwi.magix.net/bg/minixiangqi.htm)
+- [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi), [Manchu](https://en.wikipedia.org/wiki/Manchu_chess), [Minixiangqi](http://mlwi.magix.net/bg/minixiangqi.htm)
 - [Shogi](https://en.wikipedia.org/wiki/Shogi)
 - [Makruk](https://en.wikipedia.org/wiki/Makruk), [Ouk Chatrang](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [Kar Ouk](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [ASEAN](http://hgm.nubati.net/rules/ASEAN.html), Ai-Wok
 - [Sittuyin](https://en.wikipedia.org/wiki/Sittuyin)
index b418016..6232eac 100644 (file)
@@ -453,7 +453,7 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
   Bitboard sliders = pos.checkers();
 
   // Consider all evasion moves for special pieces
-  if (sliders & (pos.pieces(CANNON) | pos.pieces(HORSE, ELEPHANT)))
+  if (sliders & (pos.pieces(CANNON, BANNER) | pos.pieces(HORSE, ELEPHANT)))
   {
       Bitboard target = pos.board_bb() & ~pos.pieces(us);
       Bitboard b = pos.attacks_from<KING>(us, ksq) & target;
index 60f6f83..f193266 100644 (file)
@@ -288,6 +288,16 @@ namespace {
       p->lameLeaper = true;
       return p;
   }
+  PieceInfo* banner_piece() {
+      PieceInfo* p = rook_piece();
+      p->name = "banner";
+      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";
@@ -330,6 +340,7 @@ void PieceMap::init() {
   add(SOLDIER, soldier_piece());
   add(HORSE, horse_piece());
   add(ELEPHANT, elephant_piece());
+  add(BANNER, banner_piece());
   add(WAZIR, wazir_piece());
   add(COMMONER, commoner_piece());
   add(CENTAUR, centaur_piece());
index 0279eff..4c22bac 100644 (file)
@@ -752,13 +752,13 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c) const {
       if (board_bb(c, pt) & s)
       {
           // Consider asymmetrical move of horse
-          if (pt == HORSE)
+          if (pt == HORSE || pt == BANNER)
           {
-              Bitboard horses = PseudoAttacks[~c][KNIGHT][s] & pieces(c, HORSE);
+              Bitboard horses = PseudoAttacks[~c][pt][s] & pieces(c, pt);
               while (horses)
               {
                   Square s2 = pop_lsb(&horses);
-                  if (attacks_bb(c, HORSE, s2, occupied) & s)
+                  if (attacks_bb(c, pt, s2, occupied) & s)
                       b |= s2;
               }
           }
@@ -999,7 +999,7 @@ bool Position::pseudo_legal(const Move m) const {
   // Evasions generator already takes care to avoid some kind of illegal moves
   // and legal() relies on this. We therefore have to take care that the same
   // kind of moves are filtered out here.
-  if (checkers() & ~(pieces(CANNON) | pieces(HORSE, ELEPHANT)))
+  if (checkers() & ~(pieces(CANNON, BANNER) | pieces(HORSE, ELEPHANT)))
   {
       if (type_of(pc) != KING)
       {
@@ -1040,18 +1040,19 @@ bool Position::gives_check(Move m) const {
   // Is there a direct check?
   if (type_of(m) != PROMOTION && type_of(m) != PIECE_PROMOTION && type_of(m) != PIECE_DEMOTION)
   {
-      if (type_of(moved_piece(m)) == CANNON || type_of(moved_piece(m)) == HORSE)
+      PieceType pt = type_of(moved_piece(m));
+      if (pt == CANNON || pt == BANNER || pt == HORSE)
       {
-          if (attacks_bb(sideToMove, type_of(moved_piece(m)), to, (pieces() ^ from) | to) & square<KING>(~sideToMove))
+          if (attacks_bb(sideToMove, pt, to, (pieces() ^ from) | to) & square<KING>(~sideToMove))
               return true;
       }
-      else if (st->checkSquares[type_of(moved_piece(m))] & to)
+      else if (st->checkSquares[pt] & to)
           return true;
   }
 
   // Is there a discovered check?
   if (   type_of(m) != DROP
-      && ((st->blockersForKing[~sideToMove] & from) || pieces(sideToMove, CANNON, HORSE))
+      && ((st->blockersForKing[~sideToMove] & from) || (pieces(sideToMove, CANNON, BANNER) | pieces(HORSE, ELEPHANT)))
       && attackers_to(square<KING>(~sideToMove), (pieces() ^ from) | to, sideToMove))
       return true;
 
index 985c618..82d306f 100644 (file)
@@ -30,13 +30,15 @@ Value PieceValue[PHASE_NB][PIECE_NB] = {
     ArchbishopValueMg, ChancellorValueMg, AmazonValueMg, KnibisValueMg, BiskniValueMg, KnirooValueMg, RookniValueMg,
     ShogiPawnValueMg, LanceValueMg, ShogiKnightValueMg, EuroShogiKnightValueMg, GoldValueMg, DragonHorseValueMg,
     ClobberPieceValueMg, BreakthroughPieceValueMg, ImmobilePieceValueMg,
-    CannonPieceValueMg, SoldierValueMg, HorseValueMg, ElephantValueMg, WazirValueMg, CommonerValueMg, CentaurValueMg },
+    CannonPieceValueMg, SoldierValueMg, HorseValueMg, ElephantValueMg, BannerValueMg,
+    WazirValueMg, CommonerValueMg, CentaurValueMg },
   { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg,
     FersValueEg, AlfilValueEg, FersAlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg,
     ArchbishopValueMg, ChancellorValueEg, AmazonValueEg, KnibisValueMg, BiskniValueMg, KnirooValueEg, RookniValueEg,
     ShogiPawnValueEg, LanceValueEg, ShogiKnightValueEg, EuroShogiKnightValueEg, GoldValueEg, DragonHorseValueEg,
     ClobberPieceValueEg, BreakthroughPieceValueEg, ImmobilePieceValueEg,
-    CannonPieceValueEg, SoldierValueEg, HorseValueEg, ElephantValueEg, WazirValueEg, CommonerValueEg, CentaurValueEg }
+    CannonPieceValueEg, SoldierValueEg, HorseValueEg, ElephantValueEg, BannerValueEg,
+    WazirValueEg, CommonerValueEg, CentaurValueEg }
 };
 
 namespace PSQT {
index 4858ccc..839d4e3 100644 (file)
@@ -341,6 +341,7 @@ enum Value : int {
   SoldierValueMg           = 200,   SoldierValueEg           = 300,
   HorseValueMg             = 500,   HorseValueEg             = 800,
   ElephantValueMg          = 350,   ElephantValueEg          = 350,
+  BannerValueMg            = 3500,  BannerValueEg            = 3500,
   WazirValueMg             = 400,   WazirValueEg             = 400,
   CommonerValueMg          = 700,   CommonerValueEg          = 900,
   CentaurValueMg           = 1500,  CentaurValueEg           = 1500,
@@ -355,7 +356,8 @@ enum PieceType {
   FERS, MET = FERS, ALFIL, FERS_ALFIL, SILVER, KHON = SILVER, AIWOK, BERS, DRAGON = BERS,
   ARCHBISHOP, CHANCELLOR, AMAZON, KNIBIS, BISKNI, KNIROO, ROOKNI,
   SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, DRAGON_HORSE,
-  CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, CANNON, SOLDIER, HORSE, ELEPHANT, WAZIR, COMMONER, CENTAUR, KING,
+  CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, CANNON, SOLDIER, HORSE, ELEPHANT, BANNER,
+  WAZIR, COMMONER, CENTAUR, KING,
   ALL_PIECES = 0,
 
   PIECE_TYPE_NB = 1 << PIECE_TYPE_BITS
index 9d91e55..81e0aeb 100644 (file)
@@ -739,6 +739,13 @@ namespace {
         v->xiangqiSoldier = true;
         return v;
     }
+    Variant* manchu_variant() {
+        Variant* v = xiangqi_variant();
+        v->pieceToCharTable = "PN.R.AB..K.C....M.....pn.r.ab..k.c..........";
+        v->add_piece(BANNER, 'm');
+        v->startFen = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/9/9/M1BAKAB2 w - - 0 1";
+        return v;
+    }
 #endif
 
 } // namespace
@@ -813,6 +820,7 @@ void VariantMap::init() {
     add("shako", shako_variant());
     add("clobber10", clobber10_variant());
     add("xiangqi", xiangqi_variant());
+    add("manchu", manchu_variant());
 #endif
 }
 
index b8b8375..49c0440 100644 (file)
 # soldier
 # horse
 # elephant
+# banner (=rook+cannon+horse)
 # wazir
 # commoner (non-royal king)
-# centaur (=knight + commoner)
+# centaur (=knight+commoner)
 # king
 
 ### Option types