if (pos.count_in_hand(Us, pt))
{
if (pt == PAWN)
- b &= ~(promotion_zone_bb(Us, pos.promotion_rank()) | rank_bb(relative_rank(Us, RANK_1)));
+ {
+ b &= ~promotion_zone_bb(Us, pos.promotion_rank());
+ if (!pos.first_rank_drops())
+ b &= ~rank_bb(relative_rank(Us, RANK_1, pos.max_rank()));
+ }
if (Checks)
b &= pos.check_squares(pt);
while (b)
stoppers = theirPawns & passed_pawn_mask(Us, s);
lever = theirPawns & PseudoAttacks[Us][PAWN][s];
leverPush = theirPawns & PseudoAttacks[Us][PAWN][s + Up];
- doubled = ourPawns & (s - Up);
+ doubled = relative_rank(Us, s, pos.max_rank()) > RANK_1 ? ourPawns & (s - Up) : 0;
neighbours = ourPawns & adjacent_files_bb(f);
phalanx = neighbours & rank_bb(s);
- supported = neighbours & rank_bb(s - Up);
+ supported = relative_rank(Us, s, pos.max_rank()) > RANK_1 ? neighbours & rank_bb(s - Up) : 0;
// A pawn is backward when it is behind all pawns of the same color
// on the adjacent files and cannot be safely advanced.
for (int opposed = 0; opposed <= 1; ++opposed)
for (int phalanx = 0; phalanx <= 1; ++phalanx)
for (int support = 0; support <= 2; ++support)
- for (Rank r = RANK_2; r < RANK_8; ++r)
+ for (Rank r = RANK_1; r < RANK_8; ++r)
{
int v = 17 * support;
v += (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed;
++sq;
}
// Set flag for promoted pieces
- else if (piece_drops() && !drop_loop() && token == '~')
+ else if (captures_to_hand() && !drop_loop() && token == '~')
promotedPieces |= SquareBB[sq - 1];
// Stop before pieces in hand
else if (token == '[')
ss << piece_to_char()[piece_on(make_square(f, r))];
// Set promoted pieces
- if (piece_drops() && is_promoted(make_square(f, r)))
+ if (captures_to_hand() && is_promoted(make_square(f, r)))
ss << "~";
}
}
else
{
st->nonPawnMaterial[them] -= PieceValue[MG][captured];
- if (piece_drops() && !is_promoted(to))
+ if (captures_to_hand() && !is_promoted(to))
st->nonPawnMaterial[us] += PieceValue[MG][captured];
}
// Update board and piece lists
remove_piece(captured, capsq);
- if (piece_drops())
+ if (captures_to_hand())
{
st->capturedpromoted = is_promoted(to);
Piece pieceToHand = is_promoted(to) ? make_piece(~color_of(captured), PAWN) : ~captured;
remove_piece(pc, to);
put_piece(promotion, to);
- if (piece_drops() && !drop_loop())
+ if (captures_to_hand() && !drop_loop())
promotedPieces = promotedPieces | to;
// Update hash keys
// Set capture piece
st->capturedPiece = captured;
- if (piece_drops() && !captured)
+ if (captures_to_hand() && !captured)
st->capturedpromoted = false;
// Update the key with the final value
remove_piece(pc, to);
pc = make_piece(us, PAWN);
put_piece(pc, to);
- if (piece_drops() && !drop_loop())
+ if (captures_to_hand() && !drop_loop())
promotedPieces -= to;
}
undrop_piece(pc, to); // Remove the dropped piece
else
move_piece(pc, to, from); // Put the piece back at the source square
- if (piece_drops() && !drop_loop() && is_promoted(to))
+ if (captures_to_hand() && !drop_loop() && is_promoted(to))
promotedPieces = (promotedPieces - to) | from;
if (st->capturedPiece)
}
put_piece(st->capturedPiece, capsq); // Restore the captured piece
- if (piece_drops())
+ if (captures_to_hand())
{
remove_from_hand(~color_of(st->capturedPiece),
!drop_loop() && st->capturedpromoted ? PAWN : type_of(st->capturedPiece));
if (captured)
{
k ^= Zobrist::psq[captured][to];
- if (piece_drops())
+ if (captures_to_hand())
{
Piece removeFromHand = !drop_loop() && is_promoted(to) ? make_piece(~color_of(captured), PAWN) : ~captured;
k ^= Zobrist::inHand[removeFromHand][pieceCountInHand[color_of(removeFromHand)][type_of(removeFromHand)] + 1]
if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
return true;
- int end = piece_drops() ? st->pliesFromNull : std::min(st->rule50, st->pliesFromNull);
+ int end = captures_to_hand() ? st->pliesFromNull : std::min(st->rule50, st->pliesFromNull);
if (end < 4)
return false;
bool must_capture() const;
bool piece_drops() const;
bool drop_loop() const;
+ bool captures_to_hand() const;
+ bool first_rank_drops() const;
// winning conditions
Value stalemate_value(int ply = 0) const;
Value checkmate_value(int ply = 0) const;
return var->dropLoop;
}
+inline bool Position::captures_to_hand() const {
+ assert(var != nullptr);
+ return var->capturesToHand;
+}
+
+inline bool Position::first_rank_drops() const {
+ assert(var != nullptr);
+ return var->firstRankDrops;
+}
+
inline Value Position::stalemate_value(int ply) const {
assert(var != nullptr);
Value v = var->stalemateValue;
Variant* v = new Variant();
v->startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[] w KQkq - 0 1";
v->pieceDrops = true;
+ v->capturesToHand = true;
return v;
} ();
const Variant* loop = [&]{
Variant* v = new Variant();
v->startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[] w KQkq - 0 1";
v->pieceDrops = true;
+ v->capturesToHand = true;
v->dropLoop = true;
return v;
} ();
+ const Variant* chessgi = [&]{
+ Variant* v = new Variant();
+ v->startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[] w KQkq - 0 1";
+ v->pieceDrops = true;
+ v->dropLoop = true;
+ v->capturesToHand = true;
+ v->firstRankDrops = true;
+ return v;
+ } ();
+ const Variant* pocketknight = [&]{
+ Variant* v = new Variant();
+ v->startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[Nn] w KQkq - 0 1";
+ v->pieceDrops = true;
+ v->capturesToHand = false;
+ return v;
+ } ();
const Variant* euroshogi = [&]{
Variant* v = new Variant();
v->reset_pieces();
v->add_piece(KING, 'k');
v->startFen = "1nbgkgn1/1r4b1/pppppppp/8/8/PPPPPPPP/1B4R1/1NGKGBN1[-] w 0 1";
v->pieceDrops = true;
+ v->capturesToHand = true;
v->promotionRank = RANK_6;
v->promotionPieceTypes = {};
v->doubleStep = false;
v->add_piece(KING, 'k');
v->startFen = "rbsgk/4p/5/P4/KGSBR[-] w 0 1";
v->pieceDrops = true;
+ v->capturesToHand = true;
v->promotionRank = RANK_5;
v->promotionPieceTypes = {};
v->doubleStep = false;
add("5check", fivecheck);
add("crazyhouse", crazyhouse);
add("loop", loop);
+ add("chessgi", chessgi);
+ add("pocketknight", pocketknight);
add("euroshogi", euroshogi);
add("minishogi", minishogi);
add("losalamos", losalamos);
bool mustCapture = false;
bool pieceDrops = false;
bool dropLoop = false;
+ bool capturesToHand = false;
+ bool firstRankDrops = false;
// game end
Value stalemateValue = VALUE_DRAW;
Value checkmateValue = -VALUE_MATE;