Make code more robust for negative piece count.
No functional change.
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)
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())
{
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)
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
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)
// 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;
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);
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));
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;
}
}
#include <atomic>
#include <sstream>
+#include "misc.h"
#include "position.h"
/// PartnerHandler manages the communication with the partner
std::atomic<bool> isFairy;
std::atomic<bool> fast, sitRequested, partnerDead, weDead, weWin;
- std::atomic<int> time, opptime;
+ std::atomic<TimePoint> time, opptime;
Move moveRequested;
};
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;
}
// 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)
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();
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 << ']';
}
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);
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);
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())
{
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))));
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;
}
}
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);
}
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
// 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)
{}
}
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;
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))
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;
}