parse_attribute("connectDiagonal", v->connectDiagonal);
parse_attribute("materialCounting", v->materialCounting);
parse_attribute("countingRule", v->countingRule);
-
+ parse_attribute("castlingWins", v->castlingWins);
+
// Report invalid options
if (DoCheck)
{
return true;
}
}
+
+ // Castle chess
+ if (var->castlingWinConditions) {
+ if (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)
+ {
+ 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;
+ }
+ }
+
// nCheck
if (check_counting() && checks_remaining(~sideToMove) == 0)
{
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;
}
bool connectDiagonal = true;
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
CountingRule countingRule = NO_COUNTING;
+ std::string castlingWins = "";
// Derived properties
bool fastAttacks = true;
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
# 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: "")
################################################
### Example for minishogi configuration that would be equivalent to the built-in variant:
pieceDrops = true
castlingRank = 2
+#https://www.chessvariants.com/winning.dir/castle.html
+[castle:chess]
+castlingWins = q
+
[opposite-castling:chess]
oppositeCastling = true