Support connect4
authorFabian Fichter <ianfab@users.noreply.github.com>
Mon, 10 Sep 2018 20:54:18 +0000 (22:54 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Mon, 10 Sep 2018 20:54:18 +0000 (22:54 +0200)
bench: 4832716

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

index b92da2e..ec90623 100644 (file)
@@ -175,6 +175,7 @@ void Bitboards::init() {
       { -8, -1, 1, 8 }, // horse
       { -8, -1, 1, 8 }, // clobber
       { 7, 9 }, // breakthrough
+      {}, // immobile
       { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
       { -9, -8, -7, -1, 1, 7, 8, 9 } // king
   };
@@ -202,6 +203,7 @@ void Bitboards::init() {
       { -8, -1, 1, 8 }, // horse
       {}, // clobber
       { 7, 8, 9 }, // breakthrough
+      {}, // immobile
       { -9, -8, -7, -1, 1, 7, 8, 9 }, // commoner
       { -9, -8, -7, -1, 1, 7, 8, 9 } // king
   };
@@ -229,6 +231,7 @@ void Bitboards::init() {
     { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
     {}, // clobber
     {}, // breakthrough
+    {}, // immobile
     {}, // commoner
     {} // king
   };
@@ -256,6 +259,7 @@ void Bitboards::init() {
     { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
     {}, // clobber
     {}, // breakthrough
+    {}, // immobile
     {}, // commoner
     {} // king
   };
@@ -283,6 +287,7 @@ void Bitboards::init() {
     7, // horse
     0, // clobber
     0, // breakthrough
+    0, // immobile
     0, // commoner
     0  // king
   };
@@ -310,6 +315,7 @@ void Bitboards::init() {
     7, // horse
     0, // clobber
     0, // breakthrough
+    0, // immobile
     0, // commoner
     0  // king
   };
index cc2852c..9f3819d 100644 (file)
@@ -199,6 +199,17 @@ constexpr Bitboard shift(Bitboard b) {
 }
 
 
+/// shift() moves a bitboard one step along direction D (mainly for pawns)
+
+constexpr Bitboard shift(Direction D, Bitboard b) {
+  return  D == NORTH      ?  b             << 8 : D == SOUTH      ?  b             >> 8
+        : D == EAST       ? (b & ~FileHBB) << 1 : D == WEST       ? (b & ~FileABB) >> 1
+        : D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == NORTH_WEST ? (b & ~FileABB) << 7
+        : D == SOUTH_EAST ? (b & ~FileHBB) >> 7 : D == SOUTH_WEST ? (b & ~FileABB) >> 9
+        : 0;
+}
+
+
 /// pawn_attacks_bb() returns the pawn attacks for the given color from the
 /// squares in the given bitboard.
 
index 4f80959..17dad19 100644 (file)
@@ -86,6 +86,9 @@ namespace {
   ExtMove* generate_drops(const Position& pos, ExtMove* moveList, PieceType pt, Bitboard b) {
     if (pos.count_in_hand(Us, pt))
     {
+        // Consider only drops on top of already placed pieces
+        if (pos.drop_on_top())
+            b &= shift<NORTH>(pos.pieces()) | Rank1BB;
         if (pt == PAWN)
         {
             b &= ~promotion_zone_bb(Us, pos.promotion_rank(), pos.max_rank());
index 8e5e9fd..680a1f1 100644 (file)
@@ -108,6 +108,7 @@ public:
   bool drop_loop() const;
   bool captures_to_hand() const;
   bool first_rank_drops() const;
+  bool drop_on_top() const;
   bool immobility_illegal() const;
   // winning conditions
   Value stalemate_value(int ply = 0) const;
@@ -120,6 +121,7 @@ public:
   Bitboard capture_the_flag(Color c) const;
   bool flag_move() const;
   CheckCount max_check_count() const;
+  int connect_n() const;
   CheckCount checks_given(Color c) const;
   bool is_variant_end() const;
   bool is_variant_end(Value& result, int ply = 0) const;
@@ -354,6 +356,11 @@ inline bool Position::first_rank_drops() const {
   return var->firstRankDrops;
 }
 
+inline bool Position::drop_on_top() const {
+  assert(var != nullptr);
+  return var->dropOnTop;
+}
+
 inline bool Position::immobility_illegal() const {
   assert(var != nullptr);
   return var->immobilityIllegal;
@@ -421,6 +428,11 @@ inline CheckCount Position::max_check_count() const {
   return var->maxCheckCount;
 }
 
+inline int Position::connect_n() const {
+  assert(var != nullptr);
+  return var->connectN;
+}
+
 inline CheckCount Position::checks_given(Color c) const {
   return st->checksGiven[c];
 }
@@ -477,6 +489,22 @@ inline bool Position::is_variant_end(Value& result, int ply) const {
       result = mated_in(ply);
       return true;
   }
+  // Connect-n
+  if (connect_n() > 0)
+  {
+      Bitboard b;
+      for (Direction d : {NORTH, NORTH_EAST, EAST, SOUTH_EAST})
+      {
+          b = pieces(~sideToMove);
+          for (int i = 1; i < connect_n() && b; i++)
+              b &= shift(d, b);
+          if (b)
+          {
+              result = mated_in(ply);
+              return true;
+          }
+      }
+  }
   return false;
 }
 
index ed6fbc9..33ab404 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, BreakthroughPieceValueMg, CommonerValueMg },
+    ClobberPieceValueMg, BreakthroughPieceValueMg, ImmobilePieceValueMg, CommonerValueMg },
   { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg,
     FersValueEg, AlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg, ChancellorValueEg,
     AmazonValueEg, KnibisValueMg, BiskniValueMg,
     ShogiPawnValueEg, LanceValueEg, ShogiKnightValueEg, EuroShogiKnightValueEg, GoldValueEg, HorseValueEg,
-    ClobberPieceValueEg, BreakthroughPieceValueEg, CommonerValueEg }
+    ClobberPieceValueEg, BreakthroughPieceValueEg, ImmobilePieceValueEg, CommonerValueEg }
 };
 
 namespace PSQT {
index bdda9af..ecf1e05 100644 (file)
@@ -213,6 +213,7 @@ enum Value : int {
   HorseValueMg             = 1500,  HorseValueEg             = 1500,
   ClobberPieceValueMg      = 300,   ClobberPieceValueEg      = 300,
   BreakthroughPieceValueMg = 300,   BreakthroughPieceValueEg = 300,
+  ImmobilePieceValueMg     = 100,   ImmobilePieceValueEg     = 100,
   CommonerValueMg          = 600,   CommonerValueEg          = 600,
 
   MidgameLimit  = 15258, EndgameLimit  = 3915
@@ -224,7 +225,7 @@ 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, BREAKTHROUGH_PIECE, COMMONER, KING,
+  CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, COMMONER, KING,
   ALL_PIECES = 0,
 
   PIECE_TYPE_NB = 1 << PIECE_TYPE_BITS
index 5903fb5..6fa1f9b 100644 (file)
@@ -395,6 +395,23 @@ void VariantMap::init() {
         v->blackFlag = Rank1BB;
         return v;
     } ();
+    const Variant* connect4 = [&]{
+        Variant* v = new Variant();
+        v->maxRank = RANK_6;
+        v->maxFile = FILE_G;
+        v->reset_pieces();
+        v->add_piece(IMMOBILE_PIECE, 'p');
+        v->startFen = "7/7/7/7/7/7[PPPPPPPPPPPPPPPPPPPPPppppppppppppppppppppp] w 0 1";
+        v->pieceDrops = true;
+        v->dropOnTop = true;
+        v->promotionPieceTypes = {};
+        v->doubleStep = false;
+        v->castling = false;
+        v->stalemateValue = -VALUE_MATE;
+        v->immobilityIllegal = false;
+        v->connectN = 4;
+        return v;
+    } ();
 
     // Add to UCI_Variant option
     add("chess", chess);
@@ -429,6 +446,7 @@ void VariantMap::init() {
     add("shatar", shatar);
     add("clobber", clobber);
     add("breakthrough", breakthrough);
+    add("connect4", connect4);
 }
 
 void VariantMap::add(std::string s, const Variant* v) {
index c976588..a52196a 100644 (file)
@@ -52,6 +52,7 @@ struct Variant {
   bool dropLoop = false;
   bool capturesToHand = false;
   bool firstRankDrops = false;
+  bool dropOnTop = false;
   bool immobilityIllegal = false;
   // game end
   Value stalemateValue = VALUE_DRAW;
@@ -65,6 +66,7 @@ struct Variant {
   Bitboard blackFlag = 0;
   bool flagMove = false;
   CheckCount maxCheckCount = CheckCount(0);
+  int connectN = 0;
 
   void add_piece(PieceType pt, char c) {
       pieceToChar[make_piece(WHITE, pt)] = toupper(c);