Prepare for virtual piece drops
authorFabian Fichter <ianfab@users.noreply.github.com>
Fri, 2 Apr 2021 19:37:51 +0000 (21:37 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Fri, 2 Apr 2021 19:37:51 +0000 (21:37 +0200)
Make code more robust for negative piece count.

No functional change.

src/evaluate.cpp
src/movegen.cpp
src/partner.cpp
src/partner.h
src/position.cpp
src/position.h
src/search.cpp
src/timeman.cpp

index 77ade99..d3fce55 100644 (file)
@@ -628,7 +628,7 @@ namespace {
 
     Score score = SCORE_ZERO;
 
-    if (pos.count_in_hand(Us, pt))
+    if (pos.count_in_hand(Us, pt) > 0)
     {
         Bitboard b = pos.drop_region(Us, pt) & ~pos.pieces() & (~attackedBy2[Them] | attackedBy[Us][ALL_PIECES]);
         if ((b & kingRing[Them]) && pt != SHOGI_PAWN)
@@ -695,7 +695,7 @@ namespace {
     b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
 
     std::function <Bitboard (Color, PieceType)> get_attacks = [this](Color c, PieceType pt) {
-        return attackedBy[c][pt] | (pos.piece_drops() && pos.count_in_hand(c, pt) ? pos.drop_region(c, pt) & ~pos.pieces() : Bitboard(0));
+        return attackedBy[c][pt] | (pos.piece_drops() && pos.count_in_hand(c, pt) > 0 ? pos.drop_region(c, pt) & ~pos.pieces() : Bitboard(0));
     };
     for (PieceType pt : pos.piece_types())
     {
@@ -724,7 +724,7 @@ namespace {
                 unsafeChecks |= knightChecks;
             break;
         case PAWN:
-            if (pos.piece_drops() && pos.count_in_hand(Them, pt))
+            if (pos.piece_drops() && pos.count_in_hand(Them, pt) > 0)
             {
                 pawnChecks = attacks_bb(Us, pt, ksq, pos.pieces()) & ~pos.pieces() & pos.board_bb();
                 if (pawnChecks & safe)
@@ -759,7 +759,7 @@ namespace {
     if (pos.two_boards() && pos.piece_drops())
     {
         for (PieceType pt : pos.piece_types())
-            if (!pos.count_in_hand(Them, pt) && (attacks_bb(Us, pt, ksq, pos.pieces()) & safe & pos.drop_region(Them, pt) & ~pos.pieces()))
+            if (pos.count_in_hand(Them, pt) <= 0 && (attacks_bb(Us, pt, ksq, pos.pieces()) & safe & pos.drop_region(Them, pt) & ~pos.pieces()))
             {
                 kingDanger += VirtualCheck * 500 / (500 + PieceValue[MG][pt]);
                 // Presumably a mate threat
index f88222a..5a473cf 100644 (file)
@@ -30,7 +30,7 @@ namespace {
     if (pos.arrow_gating())
     {
         for (PieceType pt_gating : pos.piece_types())
-            if (pos.count_in_hand(us, pt_gating))
+            if (pos.count_in_hand(us, pt_gating) > 0)
             {
                 Bitboard b = pos.drop_region(us, pt_gating) & moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from) & ~(pos.pieces() ^ from);
                 while (b)
@@ -44,11 +44,11 @@ namespace {
     // Gating moves
     if (pos.seirawan_gating() && (pos.gates(us) & from))
         for (PieceType pt_gating : pos.piece_types())
-            if (pos.count_in_hand(us, pt_gating) && (pos.drop_region(us, pt_gating) & from))
+            if (pos.count_in_hand(us, pt_gating) > 0 && (pos.drop_region(us, pt_gating) & from))
                 *moveList++ = make_gating<T>(from, to, pt_gating, from);
     if (pos.seirawan_gating() && T == CASTLING && (pos.gates(us) & to))
         for (PieceType pt_gating : pos.piece_types())
-            if (pos.count_in_hand(us, pt_gating) && (pos.drop_region(us, pt_gating) & to))
+            if (pos.count_in_hand(us, pt_gating) > 0 && (pos.drop_region(us, pt_gating) & to))
                 *moveList++ = make_gating<T>(from, to, pt_gating, to);
 
     return moveList;
@@ -72,7 +72,7 @@ namespace {
 
   template<Color Us, bool Checks>
   ExtMove* generate_drops(const Position& pos, ExtMove* moveList, PieceType pt, Bitboard b) {
-    if (pos.count_in_hand(Us, pt))
+    if (pos.count_in_hand(Us, pt) > 0)
     {
         // Restrict to valid target
         b &= pos.drop_region(Us, pt);
@@ -373,7 +373,7 @@ namespace {
         if (pt != PAWN && pt != KING)
             moveList = generate_moves<Checks>(pos, moveList, pt, piecesToMove, target);
     // generate drops
-    if (pos.piece_drops() && Type != CAPTURES && pos.count_in_hand(Us, ALL_PIECES))
+    if (pos.piece_drops() && Type != CAPTURES && pos.count_in_hand(Us, ALL_PIECES) > 0)
         for (PieceType pt : pos.piece_types())
             moveList = generate_drops<Us, Checks>(pos, moveList, pt, target & ~pos.pieces(~Us));
 
index 306b6e2..c53d069 100644 (file)
@@ -140,12 +140,12 @@ void PartnerHandler::parse_ptell(std::istringstream& is, const Position& pos) {
     else if (token == "time")
     {
         int value;
-        time = (is >> value) ? value : 0;
+        time = (is >> value) ? value * 10 : 0;
     }
     else if (token == "otim")
     {
         int value;
-        opptime = (is >> value) ? value : 0;
+        opptime = (is >> value) ? value * 10 : 0;
     }
 }
 
index 01b68e6..8a78882 100644 (file)
@@ -22,6 +22,7 @@
 #include <atomic>
 #include <sstream>
 
+#include "misc.h"
 #include "position.h"
 
 /// PartnerHandler manages the communication with the partner
@@ -42,7 +43,7 @@ struct PartnerHandler {
 
     std::atomic<bool> isFairy;
     std::atomic<bool> fast, sitRequested, partnerDead, weDead, weWin;
-    std::atomic<int> time, opptime;
+    std::atomic<TimePoint> time, opptime;
     Move moveRequested;
 };
 
index 9eef9ed..3157db0 100644 (file)
@@ -362,7 +362,7 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
                   st->gatesBB[c] |= st->castlingKingSquare[c];
               // Do not set castling rights for gates unless there are no pieces in hand,
               // which means that the file is referring to a chess960 castling right.
-              else if (!seirawan_gating() || count_in_hand(c, ALL_PIECES) || captures_to_hand())
+              else if (!seirawan_gating() || count_in_hand(c, ALL_PIECES) > 0 || captures_to_hand())
                   continue;
           }
 
@@ -373,7 +373,7 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
       // Set castling rights for 960 gating variants
       if (gating() && castling_enabled())
           for (Color c : {WHITE, BLACK})
-              if ((gates(c) & pieces(castling_king_piece())) && !castling_rights(c) && (!seirawan_gating() || count_in_hand(c, ALL_PIECES) || captures_to_hand()))
+              if ((gates(c) & pieces(castling_king_piece())) && !castling_rights(c) && (!seirawan_gating() || count_in_hand(c, ALL_PIECES) > 0 || captures_to_hand()))
               {
                   Bitboard castling_rooks = gates(c) & pieces(castling_rook_piece());
                   while (castling_rooks)
@@ -671,13 +671,13 @@ const string Position::fen(bool sfen, bool showPromoted, int countStarted, std::
       ss << (sideToMove == WHITE ? " b " : " w ");
       for (Color c : {WHITE, BLACK})
           for (PieceType pt = KING; pt >= PAWN; --pt)
-              if (pieceCountInHand[c][pt])
+              if (pieceCountInHand[c][pt] > 0)
               {
                   if (pieceCountInHand[c][pt] > 1)
                       ss << pieceCountInHand[c][pt];
                   ss << piece_to_char()[make_piece(c, pt)];
               }
-      if (!count_in_hand(ALL_PIECES))
+      if (count_in_hand(ALL_PIECES) == 0)
           ss << '-';
       ss << " " << gamePly + 1;
       return ss.str();
@@ -692,7 +692,10 @@ const string Position::fen(bool sfen, bool showPromoted, int countStarted, std::
       else
           for (Color c : {WHITE, BLACK})
               for (PieceType pt = KING; pt >= PAWN; --pt)
+              {
+                  assert(pieceCountInHand[c][pt] >= 0);
                   ss << std::string(pieceCountInHand[c][pt], piece_to_char()[make_piece(c, pt)]);
+              }
       ss << ']';
   }
 
@@ -708,7 +711,7 @@ const string Position::fen(bool sfen, bool showPromoted, int countStarted, std::
   if (can_castle(WHITE_OOO))
       ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q');
 
-  if (gating() && gates(WHITE) && (!seirawan_gating() || count_in_hand(WHITE, ALL_PIECES) || captures_to_hand()))
+  if (gating() && gates(WHITE) && (!seirawan_gating() || count_in_hand(WHITE, ALL_PIECES) > 0 || captures_to_hand()))
       for (File f = FILE_A; f <= max_file(); ++f)
           if (gates(WHITE) & file_bb(f))
               ss << char('A' + f);
@@ -723,7 +726,7 @@ const string Position::fen(bool sfen, bool showPromoted, int countStarted, std::
   if (can_castle(BLACK_OOO))
       ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q');
 
-  if (gating() && gates(BLACK) && (!seirawan_gating() || count_in_hand(BLACK, ALL_PIECES) || captures_to_hand()))
+  if (gating() && gates(BLACK) && (!seirawan_gating() || count_in_hand(BLACK, ALL_PIECES) > 0 || captures_to_hand()))
       for (File f = FILE_A; f <= max_file(); ++f)
           if (gates(BLACK) & file_bb(f))
               ss << char('a' + f);
@@ -927,7 +930,7 @@ bool Position::legal(Move m) const {
       return false;
 
   // Illegal non-drop moves
-  if (must_drop() && type_of(m) != DROP && count_in_hand(us, var->mustDropType))
+  if (must_drop() && type_of(m) != DROP && count_in_hand(us, var->mustDropType) > 0)
   {
       if (checkers())
       {
@@ -1115,7 +1118,7 @@ bool Position::pseudo_legal(const Move m) const {
       return   piece_drops()
             && pc != NO_PIECE
             && color_of(pc) == us
-            && count_in_hand(us, in_hand_piece_type(m))
+            && count_in_hand(us, in_hand_piece_type(m)) > 0
             && (drop_region(us, type_of(pc)) & ~pieces() & to)
             && (   type_of(pc) == in_hand_piece_type(m)
                 || (drop_promoted() && type_of(pc) == promoted_piece_type(in_hand_piece_type(m))));
@@ -1689,7 +1692,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
           st->gatesBB[us] ^= to_sq(m);
       if (gates(them) & to)
           st->gatesBB[them] ^= to;
-      if (seirawan_gating() && !count_in_hand(us, ALL_PIECES) && !captures_to_hand())
+      if (seirawan_gating() && count_in_hand(us, ALL_PIECES) == 0 && !captures_to_hand())
           st->gatesBB[us] = 0;
   }
 
index d47e61f..bc80fc8 100644 (file)
@@ -1291,7 +1291,7 @@ inline void Position::remove_from_hand(Piece pc) {
 }
 
 inline void Position::drop_piece(Piece pc_hand, Piece pc_drop, Square s) {
-  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
+  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)] > 0 || var->twoBoards);
   put_piece(pc_drop, s, pc_drop != pc_hand, pc_drop != pc_hand ? pc_hand : NO_PIECE);
   remove_from_hand(pc_hand);
 }
@@ -1300,7 +1300,7 @@ inline void Position::undrop_piece(Piece pc_hand, Square s) {
   remove_piece(s);
   board[s] = NO_PIECE;
   add_to_hand(pc_hand);
-  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
+  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)] > 0 || var->twoBoards);
 }
 
 #endif // #ifndef POSITION_H_INCLUDED
index 3f63836..fbe2ad4 100644 (file)
@@ -261,7 +261,7 @@ void MainThread::search() {
   // Sit in bughouse variants if partner requested it or we are dead
   if (rootPos.two_boards() && !Threads.abort && Options["Protocol"] == "xboard")
   {
-      while (!Threads.stop && (Partner.sitRequested || Partner.weDead) && Time.elapsed() < Limits.time[us] - 1000)
+      while (!Threads.stop && (Partner.sitRequested || (Partner.weDead && !Partner.partnerDead)) && Time.elapsed() < Limits.time[us] - 1000)
       {}
   }
 
@@ -587,12 +587,12 @@ void Thread::search() {
                   Partner.ptell("x");
                   Partner.weDead = false;
               }
-              else if (!Partner.weWin && bestValue >= VALUE_MATE_IN_MAX_PLY && Limits.time[~us] < Partner.time * 10)
+              else if (!Partner.weWin && bestValue >= VALUE_MATE_IN_MAX_PLY && Limits.time[~us] < Partner.time)
               {
                   Partner.ptell("sit");
                   Partner.weWin = true;
               }
-              else if (Partner.weWin && (bestValue < VALUE_MATE_IN_MAX_PLY || Limits.time[~us] > Partner.time * 10))
+              else if (Partner.weWin && (bestValue < VALUE_MATE_IN_MAX_PLY || Limits.time[~us] > Partner.time))
               {
                   Partner.ptell("x");
                   Partner.weWin = false;
@@ -1965,7 +1965,7 @@ void MainThread::check_time() {
 
   if (   rootPos.two_boards()
       && Time.elapsed() < Limits.time[rootPos.side_to_move()] - 1000
-      && (Partner.sitRequested || Partner.weDead))
+      && (Partner.sitRequested || (Partner.weDead && !Partner.partnerDead)))
       return;
 
   if (   (Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit))
index 8939ea7..aa90d78 100644 (file)
@@ -71,10 +71,10 @@ void TimeManagement::init(const Position& pos, Search::LimitsType& limits, Color
   if (pos.two_boards())
   {
       if (Partner.partnerDead && Partner.opptime)
-          timeLeft -= Partner.opptime * 10;
+          timeLeft -= Partner.opptime;
       else
       {
-          timeLeft = std::min(timeLeft, 5000 + std::min(std::abs(limits.time[us] - Partner.opptime * 10), TimePoint(Partner.opptime * 10)));
+          timeLeft = std::min(timeLeft, 5000 + std::min(std::abs(limits.time[us] - Partner.opptime), TimePoint(Partner.opptime)));
           if (Partner.fast || Partner.partnerDead)
               timeLeft /= 4;
       }