Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/apiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,14 @@ inline bool has_insufficient_material(Color c, const Position& pos) {
// Other win rules
if ( pos.captures_to_hand()
|| pos.count_in_hand(c, ALL_PIECES)
|| (pos.extinction_value() != VALUE_NONE && !pos.extinction_pseudo_royal())
|| (pos.extinction_value() != VALUE_NONE && (pos.extinction_piece_types() & ~pos.pseudo_royal_types()))
|| (pos.flag_region(c) && pos.count(c, pos.flag_piece(c))))
return false;

// Restricted pieces
Bitboard restricted = pos.pieces(~c, KING);
// Atomic kings can not help checkmating
if (pos.extinction_pseudo_royal() && pos.blast_on_capture() && (pos.extinction_piece_types() & COMMONER))
if (pos.pseudo_royal_types() & COMMONER)
restricted |= pos.pieces(c, COMMONER);
for (PieceSet ps = pos.piece_types(); ps;)
{
Expand Down Expand Up @@ -414,7 +414,7 @@ inline bool has_insufficient_material(Color c, const Position& pos) {

inline Bitboard checked(const Position& pos) {
return (pos.checkers() ? square_bb(pos.square<KING>(pos.side_to_move())) : Bitboard(0))
| (pos.extinction_pseudo_royal() ? pos.checked_pseudo_royals(pos.side_to_move()) : Bitboard(0));
| (pos.pseudo_royal_types() ? pos.checked_pseudo_royals(pos.side_to_move()) : Bitboard(0));
}

namespace FEN {
Expand Down
17 changes: 14 additions & 3 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,16 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute<false>("whiteDropRegion", v->dropRegion[WHITE]);
parse_attribute<false>("blackDropRegion", v->dropRegion[BLACK]);

bool deprecatedPseudoRoyal = false;
parse_attribute<false>("extinctionPseudoRoyal", deprecatedPseudoRoyal);
if (deprecatedPseudoRoyal)
{
parse_attribute("extinctionPieceTypes", v->pseudoRoyalTypes, v->pieceToChar);
// pseudo royal count is one more than extinction count
if (parse_attribute("extinctionPieceCount", v->pseudoRoyalCount))
v->pseudoRoyalCount++;
}

bool dropOnTop = false;
parse_attribute<false>("dropOnTop", dropOnTop);
if (dropOnTop) v->enclosingDrop=TOP;
Expand Down Expand Up @@ -511,10 +521,11 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("shogiPawnDropMateIllegal", v->shogiPawnDropMateIllegal);
parse_attribute("shatarMateRule", v->shatarMateRule);
parse_attribute("bikjangRule", v->bikjangRule);
parse_attribute("pseudoRoyalTypes", v->pseudoRoyalTypes, v->pieceToChar);
parse_attribute("pseudoRoyalCount", v->pseudoRoyalCount);
parse_attribute("dupleCheck", v->dupleCheck);
parse_attribute("extinctionValue", v->extinctionValue);
parse_attribute("extinctionClaim", v->extinctionClaim);
parse_attribute("extinctionPseudoRoyal", v->extinctionPseudoRoyal);
parse_attribute("dupleCheck", v->dupleCheck);
// extinction piece types
parse_attribute("extinctionPieceTypes", v->extinctionPieceTypes, v->pieceToChar);
parse_attribute("extinctionPieceCount", v->extinctionPieceCount);
Expand Down Expand Up @@ -635,7 +646,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
// 1. In blast variants, moving a (pseudo-)royal blastImmuneType into another piece is legal.
// 2. In blast variants, capturing a piece next to a (pseudo-)royal blastImmuneType is legal.
// 3. Moving a (pseudo-)royal mutuallyImmuneType into a square threatened by the same type is legal.
if ((v->extinctionPseudoRoyal) || (v->pieceTypes & KING))
if (v->pseudoRoyalTypes || (v->pieceTypes & KING))
{
if (v->blastImmuneTypes)
std::cerr << "Can not use kings or pseudo-royal with blastImmuneTypes." << std::endl;
Expand Down
22 changes: 11 additions & 11 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,17 +591,17 @@ void Position::set_check_info(StateInfo* si) const {
si->bikjang = var->bikjangRule && ksq != SQ_NONE ? bool(attacks_bb(sideToMove, ROOK, ksq, pieces()) & pieces(sideToMove, KING)) : false;
si->chased = var->chasingRule ? chased() : Bitboard(0);
si->legalCapture = NO_VALUE;
if (var->extinctionPseudoRoyal)
if (var->pseudoRoyalTypes)
{
si->pseudoRoyalCandidates = 0;
si->pseudoRoyals = 0;
for (PieceSet ps = extinction_piece_types(); ps;)
for (PieceSet ps = pseudo_royal_types(); ps;)
{
PieceType pt = pop_lsb(ps);
si->pseudoRoyalCandidates |= pieces(pt);
if (count(sideToMove, pt) <= var->extinctionPieceCount + 1)
if (count(sideToMove, pt) <= var->pseudoRoyalCount)
si->pseudoRoyals |= pieces(sideToMove, pt);
if (count(~sideToMove, pt) <= var->extinctionPieceCount + 1)
if (count(~sideToMove, pt) <= var->pseudoRoyalCount)
si->pseudoRoyals |= pieces(~sideToMove, pt);
}
}
Expand Down Expand Up @@ -1005,7 +1005,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
/// Position::checked_pseudo_royals computes a bitboard of
/// all pseudo-royal pieces of a particular color that are in check
Bitboard Position::checked_pseudo_royals(Color c) const {
assert(extinction_pseudo_royal());
assert(pseudo_royal_types());
Bitboard checked = 0;
Bitboard pseudoRoyals = st->pseudoRoyals & pieces(c);
Bitboard pseudoRoyalsTheirs = st->pseudoRoyals & pieces(~c);
Expand Down Expand Up @@ -1113,7 +1113,7 @@ bool Position::legal(Move m) const {
}

// Check for attacks to pseudo-royal pieces
if (var->extinctionPseudoRoyal)
if (var->pseudoRoyalTypes)
{
Square kto = to;
Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces());
Expand Down Expand Up @@ -1149,9 +1149,9 @@ bool Position::legal(Move m) const {
Bitboard pseudoRoyalsTheirs = st->pseudoRoyals & pieces(~sideToMove);
if (is_ok(from) && (pseudoRoyals & from))
pseudoRoyals ^= square_bb(from) ^ kto;
if (type_of(m) == PROMOTION && (extinction_piece_types() & promotion_type(m)))
if (type_of(m) == PROMOTION && (pseudo_royal_types() & promotion_type(m)))
{
if (count(sideToMove, promotion_type(m)) > extinction_piece_count())
if (count(sideToMove, promotion_type(m)) >= var->pseudoRoyalCount)
// increase in count leads to loss of pseudo-royalty
pseudoRoyals &= ~pieces(sideToMove, promotion_type(m));
else
Expand All @@ -1163,7 +1163,7 @@ bool Position::legal(Move m) const {
return false;
// Petrifiable pseudo-royals can't capture
Bitboard attackerCandidatesTheirs = occupied & ~square_bb(kto);
for (PieceSet ps = var->petrifyOnCaptureTypes & extinction_piece_types(); ps;)
for (PieceSet ps = var->petrifyOnCaptureTypes & pseudo_royal_types(); ps;)
attackerCandidatesTheirs &= ~pieces(~us, pop_lsb(ps));
// Check for legality unless we capture a pseudo-royal piece
if (!(pseudoRoyalsTheirs & ~occupied))
Expand All @@ -1181,7 +1181,7 @@ bool Position::legal(Move m) const {
Bitboard pseudoRoyalCandidates = st->pseudoRoyalCandidates & pieces(sideToMove);
if (is_ok(from) && (pseudoRoyalCandidates & from))
pseudoRoyalCandidates ^= square_bb(from) ^ kto;
if (type_of(m) == PROMOTION && (extinction_piece_types() & promotion_type(m)))
if (type_of(m) == PROMOTION && (pseudo_royal_types() & promotion_type(m)))
pseudoRoyalCandidates |= kto;
bool allCheck = bool(pseudoRoyalCandidates);
while (allCheck && pseudoRoyalCandidates)
Expand Down Expand Up @@ -2724,7 +2724,7 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {

// Extinction
// Extinction does not apply for pseudo-royal pieces, because they can not be captured
if (extinction_value() != VALUE_NONE && (!var->extinctionPseudoRoyal || blast_on_capture()))
if (extinction_value() != VALUE_NONE)
{
for (Color c : { ~sideToMove, sideToMove })
for (PieceSet ps = extinction_piece_types(); ps;)
Expand Down
8 changes: 4 additions & 4 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class Position {
bool extinction_single_piece() const;
int extinction_piece_count() const;
int extinction_opponent_piece_count() const;
bool extinction_pseudo_royal() const;
PieceSet pseudo_royal_types() const;
PieceType flag_piece(Color c) const;
Bitboard flag_region(Color c) const;
bool flag_move() const;
Expand Down Expand Up @@ -919,7 +919,7 @@ inline Value Position::stalemate_value(int ply) const {
return c == 0 ? VALUE_DRAW : convert_mate_value(c < 0 ? var->stalemateValue : -var->stalemateValue, ply);
}
// Check for checkmate of pseudo-royal pieces
if (var->extinctionPseudoRoyal)
if (var->pseudoRoyalTypes)
{
Bitboard pseudoRoyals = st->pseudoRoyals & pieces(sideToMove);
Bitboard pseudoRoyalsTheirs = st->pseudoRoyals & pieces(~sideToMove);
Expand Down Expand Up @@ -1031,9 +1031,9 @@ inline int Position::extinction_opponent_piece_count() const {
return var->extinctionOpponentPieceCount;
}

inline bool Position::extinction_pseudo_royal() const {
inline PieceSet Position::pseudo_royal_types() const {
assert(var != nullptr);
return var->extinctionPseudoRoyal;
return var->pseudoRoyalTypes;
}

inline PieceType Position::flag_piece(Color c) const {
Expand Down
2 changes: 1 addition & 1 deletion src/psqt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ void init(const Variant* v) {
: pt == KING ? KingBonus[std::clamp(Rank(r - pawnRank + 1), RANK_1, RANK_8)][std::min(f, FILE_D)] * (1 + v->capturesToHand)
: pt <= QUEEN ? Bonus[pc][std::min(r, RANK_8)][std::min(f, FILE_D)] * (1 + v->blastOnCapture)
: pt == HORSE ? Bonus[KNIGHT][std::min(r, RANK_8)][std::min(f, FILE_D)]
: pt == COMMONER && v->extinctionValue == -VALUE_MATE && (v->extinctionPieceTypes & COMMONER) ? KingBonus[std::clamp(Rank(r - pawnRank + 1), RANK_1, RANK_8)][std::min(f, FILE_D)]
: pt == COMMONER && ((v->pseudoRoyalTypes & COMMONER) || (v->extinctionValue == -VALUE_MATE && (v->extinctionPieceTypes & COMMONER))) ? KingBonus[std::clamp(Rank(r - pawnRank + 1), RANK_1, RANK_8)][std::min(f, FILE_D)]
: isSlider ? make_score(5, 5) * (2 * f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile - 1)
: isPawn ? make_score(5, 5) * (2 * f - v->maxFile)
: make_score(10, 10) * (1 + isSlowLeaper) * (f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile / 2));
Expand Down
30 changes: 16 additions & 14 deletions src/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,7 @@ namespace {
v->remove_piece(KING);
v->add_piece(COMMONER, 'k');
v->castlingKingPiece[WHITE] = v->castlingKingPiece[BLACK] = COMMONER;
v->extinctionValue = -VALUE_MATE;
v->extinctionPieceTypes = piece_set(COMMONER);
v->extinctionPseudoRoyal = true;
v->pseudoRoyalTypes = piece_set(COMMONER);
v->petrifyOnCaptureTypes = piece_set(COMMONER) | QUEEN | ROOK | BISHOP | KNIGHT;
return v;
}
Expand All @@ -509,7 +507,7 @@ namespace {
// https://en.wikipedia.org/wiki/Atomic_chess
Variant* atomic_variant() {
Variant* v = nocheckatomic_variant()->init();
v->extinctionPseudoRoyal = true;
v->pseudoRoyalTypes = piece_set(COMMONER);
v->endgameEval = EG_EVAL_ATOMIC;
return v;
}
Expand Down Expand Up @@ -1076,8 +1074,9 @@ namespace {
v->promotionLimit[COMMONER] = 2;
v->enPassantRegion[WHITE] = 0;
v->enPassantRegion[BLACK] = 0;
v->extinctionPieceCount = 0;
v->extinctionPseudoRoyal = true;
v->extinctionValue = VALUE_NONE;
v->pseudoRoyalTypes = piece_set(COMMONER);
v->pseudoRoyalCount = 1;
v->dupleCheck = true;
return v;
}
Expand All @@ -1104,10 +1103,8 @@ namespace {
// https://www.chessvariants.com/winning.dir/coregal.html
Variant* coregal_variant() {
Variant* v = chess_variant_base()->init();
v->extinctionValue = -VALUE_MATE;
v->extinctionPieceTypes = piece_set(QUEEN);
v->extinctionPseudoRoyal = true;
v->extinctionPieceCount = 64; // no matter how many queens, all are royal
v->pseudoRoyalTypes = piece_set(QUEEN);
v->pseudoRoyalCount = 64; // no matter how many queens, all are royal
return v;
}
// Clobber
Expand Down Expand Up @@ -1265,10 +1262,8 @@ namespace {
v->pieceDrops = false;
v->promotedPieceType[CUSTOM_PIECE_1] = COMMONER;
v->castlingKingPiece[WHITE] = v->castlingKingPiece[BLACK] = COMMONER;
v->extinctionValue = -VALUE_MATE;
v->extinctionPieceTypes = piece_set(COMMONER);
v->extinctionPseudoRoyal = true;
v->extinctionPieceCount = 0;
v->pseudoRoyalTypes = piece_set(COMMONER);
v->pseudoRoyalCount = 1;
return v;
}
// Yari shogi
Expand Down Expand Up @@ -1963,6 +1958,11 @@ Variant* Variant::conclude() {
doubleStepRegion[WHITE] = doubleStepRegion[BLACK] = 0;
if (!doubleStepRegion[WHITE] && !doubleStepRegion[BLACK])
doubleStep = false;
if (extinctionValue == VALUE_NONE || !(extinctionPieceTypes & pieceTypes))
{
extinctionValue = VALUE_NONE;
extinctionPieceTypes = NO_PIECE_SET;
}

// Determine optimizations
bool restrictedMobility = false;
Expand All @@ -1985,6 +1985,7 @@ Variant* Variant::conclude() {

// Initialize calculated NNUE properties
nnueKing = pieceTypes & KING ? KING
: pseudoRoyalCount == 1 && popcount(pseudoRoyalTypes) == 1 ? lsb(pseudoRoyalTypes)
: extinctionPieceCount == 0 && (extinctionPieceTypes & COMMONER) ? COMMONER
: NO_PIECE_TYPE;
// The nnueKing has to present exactly once and must not change in count
Expand Down Expand Up @@ -2068,6 +2069,7 @@ Variant* Variant::conclude() {
||
( endgameEval == EG_EVAL_CHESS
&& extinctionValue == VALUE_NONE
&& !pseudoRoyalTypes
&& checkmateValue == -VALUE_MATE
&& stalemateValue == VALUE_DRAW
&& !materialCounting
Expand Down
3 changes: 2 additions & 1 deletion src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ struct Variant {
bool bikjangRule = false;
Value extinctionValue = VALUE_NONE;
bool extinctionClaim = false;
bool extinctionPseudoRoyal = false;
PieceSet pseudoRoyalTypes = NO_PIECE_SET;
int pseudoRoyalCount = 1;
bool dupleCheck = false;
PieceSet extinctionPieceTypes = NO_PIECE_SET;
int extinctionPieceCount = 0;
Expand Down
Loading
Loading