Skip to content

Commit

Permalink
Add CastlingRights as dedicated config type
Browse files Browse the repository at this point in the history
No functional change.
  • Loading branch information
ianfab committed Sep 10, 2023
1 parent 8e3fe58 commit 5f98659
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 32 deletions.
22 changes: 22 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,27 @@ namespace {
return !ss.fail();
}

template <> bool set(const std::string& value, CastlingRights& target) {
char c;
CastlingRights castlingRight;
std::stringstream ss(value);
target = NO_CASTLING;
bool valid = true;
while (ss >> c && c != '-')
{
castlingRight = c == 'K' ? WHITE_OO
: c == 'Q' ? WHITE_OOO
: c == 'k' ? BLACK_OO
: c == 'q' ? BLACK_OOO
: NO_CASTLING;
if (castlingRight)
target = CastlingRights(target | castlingRight);
else
valid = false;
}
return valid;
}

template <typename T> void set(PieceType pt, T& target) {
target.insert(pt);
}
Expand Down Expand Up @@ -158,6 +179,7 @@ template <bool Current, class T> bool VariantParser<DoCheck>::parse_attribute(co
: std::is_same<T, ChasingRule>() ? "ChasingRule"
: std::is_same<T, EnclosingRule>() ? "EnclosingRule"
: std::is_same<T, Bitboard>() ? "Bitboard"
: std::is_same<T, CastlingRights>() ? "CastlingRights"
: typeid(T).name();
std::cerr << key << " - Invalid value " << it->second << " for type " << typeName << std::endl;
}
Expand Down
36 changes: 16 additions & 20 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2738,32 +2738,28 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
}

// Castle chess
if (var->castlingWinConditions) {
if (type_of(st->move) == CASTLING)
if (var->castlingWins)
{
if (st->pliesFromNull > 0 && type_of(st->move) == CASTLING)
{
//check for victory first, because castling also removes castling rights.
CastlingRights justCastled = static_cast<CastlingRights>((sideToMove == BLACK ? WHITE_OOO : BLACK_OOO)
>> ((from_sq(st->move) < to_sq(st->move)) ? 1 : 0));
if (var->castlingWinConditions & justCastled)
// check for victory first, because castling also removes castling rights.
CastlingRights justCastled = ~sideToMove & ((from_sq(st->move) < to_sq(st->move)) ? KING_SIDE : QUEEN_SIDE);
if (var->castlingWins & justCastled)
{
result = mated_in(ply);
return true;
}
}
if ((var->castlingWinConditions & BLACK_CASTLING) && (!(var->castlingWinConditions & BLACK_CASTLING & st->castlingRights)))
{
//black permanently losing castling rights. either through moving a castling piece,
//or having their rook captured. Either way, black lost.
result = sideToMove == WHITE ? mate_in(ply) : mated_in(ply);
return true;
}
if ((var->castlingWinConditions & WHITE_CASTLING) && (!(var->castlingWinConditions & WHITE_CASTLING & st->castlingRights)))
{
//white permanently losing castling rights. either through moving a castling piece,
//or having their rook captured. Either way, white lost.
result = sideToMove == BLACK ? mate_in(ply) : mated_in(ply);
return true;
}
// We check the opponent side first, because a rook capturing a rook could remove both sides castling rights,
// which should likely be seen as losing, analogous to extinction rules.
for (Color c : { ~sideToMove, sideToMove })
if ((c & var->castlingWins) && !(c & var->castlingWins & st->castlingRights))
{
// player permanently losing castling rights. either through moving a castling piece,
// or having their rook captured.
result = c == sideToMove ? mated_in(ply) : mate_in(ply);
return true;
}
}

// nCheck
Expand Down
9 changes: 0 additions & 9 deletions src/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2041,15 +2041,6 @@ Variant* Variant::conclude() {
connect_directions.push_back(SOUTH_EAST);
}

for (char c : castlingWins) {
switch (c) {
case 'K': castlingWinConditions = static_cast<CastlingRights>(castlingWinConditions | WHITE_OO); break;
case 'Q': castlingWinConditions = static_cast<CastlingRights>(castlingWinConditions | WHITE_OOO); break;
case 'k': castlingWinConditions = static_cast<CastlingRights>(castlingWinConditions | BLACK_OO); break;
case 'q': castlingWinConditions = static_cast<CastlingRights>(castlingWinConditions | BLACK_OOO); break;
}
}

return this;
}

Expand Down
3 changes: 1 addition & 2 deletions src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ struct Variant {
bool connectDiagonal = true;
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
CountingRule countingRule = NO_COUNTING;
std::string castlingWins = "";
CastlingRights castlingWins = NO_CASTLING;

// Derived properties
bool fastAttacks = true;
Expand All @@ -173,7 +173,6 @@ struct Variant {
bool endgameEval = false;
bool shogiStylePromotions = false;
std::vector<Direction> connect_directions;
CastlingRights castlingWinConditions = NO_CASTLING;

void add_piece(PieceType pt, char c, std::string betza = "", char c2 = ' ') {
// Avoid ambiguous definition by removing existing piece with same letter
Expand Down
3 changes: 2 additions & 1 deletion src/variants.ini
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
# [int]: any natural number [0, 1, ...]
# [PieceType]: a piece type [letters defined for pieces, e.g., p]
# [PieceSet]: multiple piece types [letters defined for pieces, e.g., nbrq]
# [CastlingRights]: set of castling rights [letters for castling rights as in FEN, e.g., KQkq]
# [Bitboard]: list of squares [e.g., d4 e4 d5 e5]. * can be used as wildcard for files (e.g., *1 is the first rank)
# [Value]: game result for the side to move [win, loss, draw]
# [MaterialCounting]: material counting rules for adjudication [janggi, unweighted, whitedrawodds, blackdrawodds, none]
Expand Down Expand Up @@ -266,7 +267,7 @@
# connectDiagonal: connectN looks at Diagonal rows [bool] (default: true)
# materialCounting: enable material counting rules [MaterialCounting] (default: none)
# countingRule: enable counting rules [CountingRule] (default: none)
# castlingWins: Specified castling moves are win conditions. Losing these rights is losing. (ie. KQkq) [string] (default: "")
# castlingWins: Specified castling moves are win conditions. Losing these rights is losing. [CastlingRights] (default: -)

################################################
### Example for minishogi configuration that would be equivalent to the built-in variant:
Expand Down

0 comments on commit 5f98659

Please sign in to comment.