Support breakthrough
authorianfab <ianfab@users.noreply.github.com>
Fri, 17 Aug 2018 18:31:23 +0000 (20:31 +0200)
committerianfab <ianfab@users.noreply.github.com>
Fri, 17 Aug 2018 18:58:00 +0000 (20:58 +0200)
https://en.wikipedia.org/wiki/Breakthrough_(board_game)

bench: 5016237

src/bitboard.cpp
src/evaluate.cpp
src/position.h
src/psqt.cpp
src/types.h
src/variant.cpp
src/variant.h

index 8794578..b92da2e 100644 (file)
@@ -174,6 +174,7 @@ void Bitboards::init() {
       { -8, -1, 1, 7, 8, 9 }, // gold
       { -8, -1, 1, 8 }, // horse
       { -8, -1, 1, 8 }, // clobber
+      { 7, 9 }, // breakthrough
       { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
       { -9, -8, -7, -1, 1, 7, 8, 9 } // king
   };
@@ -200,6 +201,7 @@ void Bitboards::init() {
       { -8, -1, 1, 7, 8, 9 }, // gold
       { -8, -1, 1, 8 }, // horse
       {}, // clobber
+      { 7, 8, 9 }, // breakthrough
       { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
       { -9, -8, -7, -1, 1, 7, 8, 9 } // king
   };
@@ -226,6 +228,7 @@ void Bitboards::init() {
     {}, // gold
     { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
     {}, // clobber
+    {}, // breakthrough
     {}, // commoner
     {} // king
   };
@@ -252,6 +255,7 @@ void Bitboards::init() {
     {}, // gold
     { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
     {}, // clobber
+    {}, // breakthrough
     {}, // commoner
     {} // king
   };
@@ -278,6 +282,7 @@ void Bitboards::init() {
     0, // gold
     7, // horse
     0, // clobber
+    0, // breakthrough
     0, // commoner
     0  // king
   };
@@ -304,6 +309,7 @@ void Bitboards::init() {
     0, // gold
     7, // horse
     0, // clobber
+    0, // breakthrough
     0, // commoner
     0  // king
   };
index b9ffc8d..52c12d8 100644 (file)
@@ -808,14 +808,20 @@ namespace {
     // Capture the flag
     if (pos.capture_the_flag(Us))
     {
-        Bitboard target_squares = pos.capture_the_flag(Us);
-        while (target_squares)
+        bool can_block = pos.capture_the_flag_piece() == KING;
+        Bitboard ctfPieces = pos.pieces(Us, pos.capture_the_flag_piece());
+        while (ctfPieces)
         {
-            Square s = pop_lsb(&target_squares);
-            int dist =  distance(pos.square<KING>(Us), s)
-                      + popcount(pos.attackers_to(s) & pos.pieces(Them))
-                      + !!(pos.pieces(Us) & s);
-            score += make_score(3000, 3000) / (1 + dist * (pos.checking_permitted() ? dist : 1));
+            Square s1 = pop_lsb(&ctfPieces);
+            Bitboard target_squares = pos.capture_the_flag(Us);
+            while (target_squares)
+            {
+                Square s2 = pop_lsb(&target_squares);
+                int dist =  distance(s1, s2)
+                          + (can_block ? popcount(pos.attackers_to(s2) & pos.pieces(Them)) : 0)
+                          + !!(pos.pieces(Us) & s2);
+                score += make_score(3000, 3000) / (1 + dist * (can_block && pos.checking_permitted() ? dist : 1));
+            }
         }
     }
 
index 7656a31..8e5e9fd 100644 (file)
@@ -116,6 +116,7 @@ public:
   Value extinction_value(int ply = 0) const;
   bool bare_king_move() const;
   const std::set<PieceType>& extinction_piece_types() const;
+  PieceType capture_the_flag_piece() const;
   Bitboard capture_the_flag(Color c) const;
   bool flag_move() const;
   CheckCount max_check_count() const;
@@ -400,6 +401,11 @@ inline const std::set<PieceType>& Position::extinction_piece_types() const {
   return var->extinctionPieceTypes;
 }
 
+inline PieceType Position::capture_the_flag_piece() const {
+  assert(var != nullptr);
+  return var->flagPiece;
+}
+
 inline Bitboard Position::capture_the_flag(Color c) const {
   assert(var != nullptr);
   return c == WHITE ? var->whiteFlag : var->blackFlag;
@@ -451,12 +457,16 @@ inline bool Position::is_variant_end(Value& result, int ply) const {
           }
   }
   // capture the flag
-  if (count<KING>(~sideToMove) && !flag_move() && (capture_the_flag(~sideToMove) & square<KING>(~sideToMove)))
+  if (   capture_the_flag_piece()
+      && !flag_move()
+      && (capture_the_flag(~sideToMove) & pieces(~sideToMove, capture_the_flag_piece())))
   {
       result = mated_in(ply);
       return true;
   }
-  if (count<KING>( sideToMove) &&  flag_move() && (capture_the_flag( sideToMove) & square<KING>( sideToMove)))
+  if (   capture_the_flag_piece()
+      && flag_move()
+      && (capture_the_flag(sideToMove) & pieces(sideToMove, capture_the_flag_piece())))
   {
       result = mate_in(ply);
       return true;
index ae390a7..ed6fbc9 100644 (file)
@@ -27,12 +27,12 @@ Value PieceValue[PHASE_NB][PIECE_NB] = {
     FersValueMg, AlfilValueMg, SilverValueMg, AiwokValueMg, BersValueMg, ChancellorValueMg,
     AmazonValueMg, KnibisValueMg, BiskniValueMg,
     ShogiPawnValueMg, LanceValueMg, ShogiKnightValueMg, EuroShogiKnightValueMg, GoldValueMg, HorseValueMg,
-    ClobberPieceValueMg, CommonerValueMg },
+    ClobberPieceValueMg, BreakthroughPieceValueMg, CommonerValueMg },
   { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg,
     FersValueEg, AlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg, ChancellorValueEg,
     AmazonValueEg, KnibisValueMg, BiskniValueMg,
     ShogiPawnValueEg, LanceValueEg, ShogiKnightValueEg, EuroShogiKnightValueEg, GoldValueEg, HorseValueEg,
-    ClobberPieceValueEg, CommonerValueEg }
+    ClobberPieceValueEg, BreakthroughPieceValueEg, CommonerValueEg }
 };
 
 namespace PSQT {
index 66874ac..bdda9af 100644 (file)
@@ -191,28 +191,29 @@ enum Value : int {
   VALUE_MATE_IN_MAX_PLY  =  VALUE_MATE - 2 * MAX_PLY,
   VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
 
-  PawnValueMg            = 171,   PawnValueEg            = 240,
-  KnightValueMg          = 764,   KnightValueEg          = 848,
-  BishopValueMg          = 826,   BishopValueEg          = 891,
-  RookValueMg            = 1282,  RookValueEg            = 1373,
-  QueenValueMg           = 2500,  QueenValueEg           = 2670,
-  FersValueMg            = 400,   FersValueEg            = 400,
-  AlfilValueMg           = 300,   AlfilValueEg           = 300,
-  SilverValueMg          = 600,   SilverValueEg          = 600,
-  AiwokValueMg           = 2500,  AiwokValueEg           = 2500,
-  BersValueMg            = 2000,  BersValueEg            = 2000,
-  ChancellorValueMg      = 2500,  ChancellorValueEg      = 2500,
-  AmazonValueMg          = 3000,  AmazonValueEg          = 3000,
-  KnibisValueMg          = 800,   KnibisValueEg          = 800,
-  BiskniValueMg          = 800,   BiskniValueEg          = 800,
-  ShogiPawnValueMg       = 100,   ShogiPawnValueEg       = 100,
-  LanceValueMg           = 300,   LanceValueEg           = 300,
-  ShogiKnightValueMg     = 300,   ShogiKnightValueEg     = 300,
-  EuroShogiKnightValueMg = 400,   EuroShogiKnightValueEg = 400,
-  GoldValueMg            = 600,   GoldValueEg            = 600,
-  HorseValueMg           = 1500,  HorseValueEg           = 1500,
-  ClobberPieceValueMg    = 300,   ClobberPieceValueEg    = 300,
-  CommonerValueMg        = 600,   CommonerValueEg        = 600,
+  PawnValueMg              = 171,   PawnValueEg              = 240,
+  KnightValueMg            = 764,   KnightValueEg            = 848,
+  BishopValueMg            = 826,   BishopValueEg            = 891,
+  RookValueMg              = 1282,  RookValueEg              = 1373,
+  QueenValueMg             = 2500,  QueenValueEg             = 2670,
+  FersValueMg              = 400,   FersValueEg              = 400,
+  AlfilValueMg             = 300,   AlfilValueEg             = 300,
+  SilverValueMg            = 600,   SilverValueEg            = 600,
+  AiwokValueMg             = 2500,  AiwokValueEg             = 2500,
+  BersValueMg              = 2000,  BersValueEg              = 2000,
+  ChancellorValueMg        = 2500,  ChancellorValueEg        = 2500,
+  AmazonValueMg            = 3000,  AmazonValueEg            = 3000,
+  KnibisValueMg            = 800,   KnibisValueEg            = 800,
+  BiskniValueMg            = 800,   BiskniValueEg            = 800,
+  ShogiPawnValueMg         = 100,   ShogiPawnValueEg         = 100,
+  LanceValueMg             = 300,   LanceValueEg             = 300,
+  ShogiKnightValueMg       = 300,   ShogiKnightValueEg       = 300,
+  EuroShogiKnightValueMg   = 400,   EuroShogiKnightValueEg   = 400,
+  GoldValueMg              = 600,   GoldValueEg              = 600,
+  HorseValueMg             = 1500,  HorseValueEg             = 1500,
+  ClobberPieceValueMg      = 300,   ClobberPieceValueEg      = 300,
+  BreakthroughPieceValueMg = 300,   BreakthroughPieceValueEg = 300,
+  CommonerValueMg          = 600,   CommonerValueEg          = 600,
 
   MidgameLimit  = 15258, EndgameLimit  = 3915
 };
@@ -222,7 +223,8 @@ const int PIECE_TYPE_BITS = 5; // PIECE_TYPE_NB = pow(2, PIECE_TYPE_BITS)
 enum PieceType {
   NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK,
   QUEEN, FERS, MET = FERS, ALFIL, SILVER, KHON = SILVER, AIWOK, BERS, DRAGON = BERS, CHANCELLOR,
-  AMAZON, KNIBIS, BISKNI, SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, HORSE, CLOBBER_PIECE, COMMONER, KING,
+  AMAZON, KNIBIS, BISKNI, SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, HORSE,
+  CLOBBER_PIECE, BREAKTHROUGH_PIECE, COMMONER, KING,
   ALL_PIECES = 0,
 
   PIECE_TYPE_NB = 1 << PIECE_TYPE_BITS
index f2e7e11..216b73f 100644 (file)
@@ -109,6 +109,7 @@ void VariantMap::init() {
     } ();
     const Variant* kingofthehill = [&]{
         Variant* v = new Variant();
+        v->flagPiece = KING;
         v->whiteFlag = make_bitboard(SQ_D4, SQ_E4, SQ_D5, SQ_E5);
         v->blackFlag = make_bitboard(SQ_D4, SQ_E4, SQ_D5, SQ_E5);
         v->flagMove = false;
@@ -117,6 +118,7 @@ void VariantMap::init() {
     const Variant* racingkings = [&]{
         Variant* v = new Variant();
         v->startFen = "8/8/8/8/8/8/krbnNBRK/qrbnNBRQ w - - 0 1";
+        v->flagPiece = KING;
         v->whiteFlag = Rank8BB;
         v->blackFlag = Rank8BB;
         v->flagMove = true;
@@ -368,6 +370,20 @@ void VariantMap::init() {
         v->immobilityIllegal = false;
         return v;
     } ();
+    const Variant* breakthrough = [&]{
+        Variant* v = new Variant();
+        v->reset_pieces();
+        v->add_piece(BREAKTHROUGH_PIECE, 'p');
+        v->startFen = "pppppppp/pppppppp/8/8/8/8/PPPPPPPP/PPPPPPPP w 0 1";
+        v->promotionPieceTypes = {};
+        v->firstRankDoubleSteps = false;
+        v->castling = false;
+        v->stalemateValue = -VALUE_MATE;
+        v->flagPiece = BREAKTHROUGH_PIECE;
+        v->whiteFlag = Rank8BB;
+        v->blackFlag = Rank1BB;
+        return v;
+    } ();
 
     // Add to UCI_Variant option
     add("chess", chess);
@@ -400,6 +416,7 @@ void VariantMap::init() {
     add("chigorin", chigorin);
     add("shatar", shatar);
     add("clobber", clobber);
+    add("breakthrough", breakthrough);
 }
 
 void VariantMap::add(std::string s, const Variant* v) {
index 6126673..c976588 100644 (file)
@@ -60,6 +60,7 @@ struct Variant {
   Value extinctionValue = VALUE_NONE;
   bool bareKingMove = false;
   std::set<PieceType> extinctionPieceTypes = {};
+  PieceType flagPiece = NO_PIECE_TYPE;
   Bitboard whiteFlag = 0;
   Bitboard blackFlag = 0;
   bool flagMove = false;