Skip to content

Commit

Permalink
Merge remote-tracking branch 'fairy/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
ianfab committed Sep 15, 2023
2 parents 612f401 + 1b5a789 commit 962d0e0
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/bitboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace {
// Some magics need to be split in order to reduce memory consumption.
// Otherwise on a 12x10 board they can be >100 MB.
#ifdef LARGEBOARDS
Bitboard RookTableH[0x11800]; // To store horizontalrook attacks
Bitboard RookTableH[0x11800]; // To store horizontal rook attacks
Bitboard RookTableV[0x4800]; // To store vertical rook attacks
Bitboard BishopTable[0x33C00]; // To store bishop attacks
Bitboard CannonTableH[0x11800]; // To store horizontal cannon attacks
Expand Down Expand Up @@ -220,7 +220,7 @@ std::string Bitboards::pretty(Bitboard b) {

s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+---+---+---+---+\n";
}
s += " a b c d e f g h i j k\n";
s += " a b c d e f g h i j k l\n";

return s;
}
Expand Down
5 changes: 3 additions & 2 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ namespace {
target = value == "reversi" ? REVERSI
: value == "ataxx" ? ATAXX
: value == "quadwrangle" ? QUADWRANGLE
: value == "snort" ? SNORT
: NO_ENCLOSING;
return value == "reversi" || value == "ataxx" || value == "quadwrangle" || value == "none";
return value == "reversi" || value == "ataxx" || value == "quadwrangle" || value =="snort" || value == "none";
}

template <> bool set(const std::string& value, Bitboard& target) {
Expand Down Expand Up @@ -382,7 +383,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("blastOnCapture", v->blastOnCapture);
parse_attribute("blastImmuneTypes", v->blastImmuneTypes, v->pieceToChar);
parse_attribute("mutuallyImmuneTypes", v->mutuallyImmuneTypes, v->pieceToChar);
parse_attribute("petrifyOnCapture", v->petrifyOnCapture);
parse_attribute("petrifyOnCaptureTypes", v->petrifyOnCaptureTypes, v->pieceToChar);
parse_attribute("petrifyBlastPieces", v->petrifyBlastPieces);
parse_attribute("doubleStep", v->doubleStep);
parse_attribute("doubleStepRegionWhite", v->doubleStepRegion[WHITE]);
Expand Down
31 changes: 19 additions & 12 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,9 @@ bool Position::legal(Move m) const {
occupied &= ~square_bb(capture_square(kto));
if (capture(m) && blast_on_capture())
occupied &= ~((attacks_bb<KING>(kto) & ((pieces(WHITE) | pieces(BLACK)) ^ pieces(PAWN))) | kto);
// Petrifying a pseudo-royal piece is illegal
if (capture(m) && (var->petrifyOnCaptureTypes & type_of(moved_piece(m))) && (st->pseudoRoyals & from))
return false;
Bitboard pseudoRoyals = st->pseudoRoyals & pieces(sideToMove);
Bitboard pseudoRoyalsTheirs = st->pseudoRoyals & pieces(~sideToMove);
if (is_ok(from) && (pseudoRoyals & from))
Expand All @@ -1145,14 +1148,18 @@ bool Position::legal(Move m) const {
// Self-explosions are illegal
if (pseudoRoyals & ~occupied)
return false;
// Petrifiable pseudo-royals can't capture
Bitboard attackerCandidatesTheirs = occupied & ~square_bb(kto);
for (PieceSet ps = var->petrifyOnCaptureTypes & extinction_piece_types(); ps;)
attackerCandidatesTheirs &= ~pieces(~us, pop_lsb(ps));
// Check for legality unless we capture a pseudo-royal piece
if (!(pseudoRoyalsTheirs & ~occupied))
while (pseudoRoyals)
{
Square sr = pop_lsb(pseudoRoyals);
// Touching pseudo-royal pieces are immune
if ( !(blast_on_capture() && (pseudoRoyalsTheirs & attacks_bb<KING>(sr)))
&& (attackers_to(sr, occupied, ~us) & (occupied & ~square_bb(kto))))
&& (attackers_to(sr, occupied, ~us) & attackerCandidatesTheirs))
return false;
}
// Look for duple check
Expand All @@ -1169,18 +1176,14 @@ bool Position::legal(Move m) const {
Square sr = pop_lsb(pseudoRoyalCandidates);
// Touching pseudo-royal pieces are immune
if (!( !(blast_on_capture() && (pseudoRoyalsTheirs & attacks_bb<KING>(sr)))
&& (attackers_to(sr, occupied, ~us) & (occupied & ~square_bb(kto)))))
&& (attackers_to(sr, occupied, ~us) & attackerCandidatesTheirs)))
allCheck = false;
}
if (allCheck)
return false;
}
}

// Petrifying the king is illegal
if (var->petrifyOnCapture && capture(m) && type_of(moved_piece(m)) == KING)
return false;

// mutuallyImmuneTypes (diplomacy in Atomar)-- In no-check Atomic, kings can be beside each other, but in Atomar, this prevents them from actually taking.
// Generalized to allow a custom set of pieces that can't capture a piece of the same type.
if (capture(m) &&
Expand Down Expand Up @@ -1405,7 +1408,7 @@ bool Position::gives_check(Move m) const {

// Is there a direct check?
if (type_of(m) != PROMOTION && type_of(m) != PIECE_PROMOTION && type_of(m) != PIECE_DEMOTION && type_of(m) != CASTLING
&& !(var->petrifyOnCapture && capture(m) && type_of(moved_piece(m)) != PAWN))
&& !((var->petrifyOnCaptureTypes & type_of(moved_piece(m))) && capture(m)))
{
PieceType pt = type_of(moved_piece(m));
if (pt == JANGGI_CANNON)
Expand Down Expand Up @@ -1433,7 +1436,7 @@ bool Position::gives_check(Move m) const {
return true;

// Petrified piece can't give check
if (var->petrifyOnCapture && capture(m) && type_of(moved_piece(m)) != PAWN)
if ((var->petrifyOnCaptureTypes & type_of(moved_piece(m))) && capture(m))
return false;

// Is there a check by special diagonal moves?
Expand Down Expand Up @@ -1946,7 +1949,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {


// Remove the blast pieces
if (captured && (blast_on_capture() || var->petrifyOnCapture))
if (captured && (blast_on_capture() || var->petrifyOnCaptureTypes))
{
std::memset(st->unpromotedBycatch, 0, sizeof(st->unpromotedBycatch));
st->demotedBycatch = st->promotedBycatch = 0;
Expand All @@ -1956,7 +1959,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
blastImmune |= pieces(pt);
};
Bitboard blast = blast_on_capture() ? ((attacks_bb<KING>(to) & ((pieces(WHITE) | pieces(BLACK)) ^ pieces(PAWN))) | to)
& (pieces() ^ blastImmune) : type_of(pc) != PAWN ? square_bb(to) : Bitboard(0);
& (pieces() ^ blastImmune) : var->petrifyOnCaptureTypes & type_of(pc) ? square_bb(to) : Bitboard(0);
while (blast)
{
Square bsq = pop_lsb(blast);
Expand Down Expand Up @@ -2018,7 +2021,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
}

// Make a wall square where the piece was
if (bsq == to ? var->petrifyOnCapture : var->petrifyBlastPieces)
if (bsq == to ? bool(var->petrifyOnCaptureTypes & type_of(bpc)) : var->petrifyBlastPieces)
{
st->wallSquares |= bsq;
byTypeBB[ALL_PIECES] |= bsq;
Expand Down Expand Up @@ -2116,7 +2119,7 @@ void Position::undo_move(Move m) {
byTypeBB[ALL_PIECES] ^= st->wallSquares ^ st->previous->wallSquares;

// Add the blast pieces
if (st->capturedPiece && (blast_on_capture() || var->petrifyOnCapture))
if (st->capturedPiece && (blast_on_capture() || var->petrifyOnCaptureTypes))
{
Bitboard blast = attacks_bb<KING>(to) | to;
while (blast)
Expand Down Expand Up @@ -2435,6 +2438,10 @@ bool Position::see_ge(Move m, Value threshold) const {
if (swap <= 0)
return true;

// Petrification ends SEE
if (var->petrifyOnCaptureTypes & type_of(moved_piece(m)) && capture(m))
return false;

Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces()) ^ to;
Color stm = color_of(moved_piece(m));
Bitboard attackers = attackers_to(to, occupied);
Expand Down
6 changes: 6 additions & 0 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,12 @@ inline Bitboard Position::drop_region(Color c, PieceType pt) const {
b ^= s;
}
}
else if (enclosing_drop() == SNORT)
{
Bitboard theirs = pieces(~c);
b &= ~(shift<NORTH >(theirs) | shift<SOUTH >(theirs)
| shift<EAST >(theirs) | shift<WEST >(theirs));
}
else
{
assert(enclosing_drop() == ATAXX);
Expand Down
2 changes: 1 addition & 1 deletion src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ enum ChasingRule {
};

enum EnclosingRule {
NO_ENCLOSING, REVERSI, ATAXX, QUADWRANGLE
NO_ENCLOSING, REVERSI, ATAXX, QUADWRANGLE, SNORT
};

enum OptBool {
Expand Down
17 changes: 17 additions & 0 deletions src/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,20 @@ namespace {
v->extinctionPieceTypes = piece_set(ALL_PIECES);
return v;
}
// Petrified
// Sideways pawns + petrification on capture
// https://www.chess.com/variants/petrified
Variant* petrified_variant() {
Variant* v = pawnsideways_variant()->init();
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->petrifyOnCaptureTypes = piece_set(COMMONER) | QUEEN | ROOK | BISHOP | KNIGHT;
return v;
}
// Atomic chess without checks (ICC rules)
// https://www.chessclub.com/help/atomic
Variant* nocheckatomic_variant() {
Expand Down Expand Up @@ -493,6 +507,7 @@ namespace {

#ifdef ALLVARS
// Duck chess
// https://duckchess.com/
Variant* duck_variant() {
Variant* v = chess_variant_base()->init();
v->remove_piece(KING);
Expand Down Expand Up @@ -1805,6 +1820,7 @@ void VariantMap::init() {
add("kinglet", kinglet_variant());
add("threekings", threekings_variant());
add("horde", horde_variant());
add("petrified", petrified_variant());
add("nocheckatomic", nocheckatomic_variant());
add("atomic", atomic_variant());
add("atomar", atomar_variant());
Expand Down Expand Up @@ -2013,6 +2029,7 @@ Variant* Variant::conclude() {
&& !makpongRule
&& !connectN
&& !blastOnCapture
&& !petrifyOnCaptureTypes
&& !capturesToHand
&& !twoBoards
&& !restrictedMobility
Expand Down
2 changes: 1 addition & 1 deletion src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct Variant {
bool blastOnCapture = false;
PieceSet blastImmuneTypes = NO_PIECE_SET;
PieceSet mutuallyImmuneTypes = NO_PIECE_SET;
bool petrifyOnCapture = false;
PieceSet petrifyOnCaptureTypes = NO_PIECE_SET;
bool petrifyBlastPieces = false;
bool doubleStep = true;
Bitboard doubleStepRegion[COLOR_NB] = {Rank2BB, Rank7BB};
Expand Down
48 changes: 45 additions & 3 deletions src/variants.ini
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
# [MaterialCounting]: material counting rules for adjudication [janggi, unweighted, whitedrawodds, blackdrawodds, none]
# [CountingRule]: makruk, cambodian, or ASEAN counting rules [makruk, cambodian, asean, none]
# [ChasingRule]: xiangqi chasing rules [axf, none]
# [EnclosingRule]: reversi or ataxx enclosing rules [reversi, ataxx, quadwrangle, none]
# [EnclosingRule]: reversi or ataxx enclosing rules [reversi, ataxx, quadwrangle, snort, none]

### Additional options relevant for usage in Winboard/XBoard
# A few options only have the purpose of improving compatibility with Winboard/Xboard.
Expand Down Expand Up @@ -169,7 +169,7 @@
# blastOnCapture: captures explode all adjacent non-pawn pieces (e.g., atomic chess) [bool] (default: false)
# blastImmuneTypes: pieces completely immune to explosions (even at ground zero) [PieceSet] (default: none)
# mutuallyImmuneTypes: pieces that can't capture another piece of same types (e.g., kings (commoners) in atomar) [PieceSet] (default: none)
# petrifyOnCapture: non-pawn pieces are turned into wall squares when capturing [bool] (default: false)
# petrifyOnCaptureTypes: defined pieces are turned into wall squares when capturing [PieceSet] (default: -)
# petrifyBlastPieces: if petrify and blast combined, should pieces destroyed in the blast be petrified? [bool] (default: false)
# doubleStep: enable pawn double step [bool] (default: true)
# doubleStepRegionWhite: region where pawn double steps are allowed for white [Bitboard] (default: *2)
Expand Down Expand Up @@ -1656,7 +1656,7 @@ startFen = lnsgkgsnl/1rci1uab1/p1p1p1p1p/9/9/9/P1P1P1P1P/1BAU1ICR1/LNSGKGSNL[-]
pawn = -
customPiece1 = p:fmWfceFifmnD
pawnTypes = p
petrifyOnCapture = true
petrifyOnCaptureTypes = pnbrq
enPassantRegion = -

#https://en.wikipedia.org/wiki/Nim
Expand Down Expand Up @@ -1704,6 +1704,18 @@ flipEnclosedPieces = ataxx
pieceDrops = false
passOnStalemate = false

#https://www.ludii.games/details.php?keyword=Snort
#also known as Cats & Dogs
[snort:ataxx]
immobile = p
startFen = 8/8/8/8/8/8/8/8
enclosingDrop = snort
flipEnclosedPieces = none
maxRank = 8
maxFile = 8
passOnStalemate = false
stalematePieceCount = false

#https://www.chess.com/variants/blackletter-chess
[blackletter:chess]
pieceToCharTable = PNBRQ.......E...M...HKpnbrq.......e...m...hk
Expand All @@ -1727,3 +1739,33 @@ castlingWins = q

[opposite-castling:chess]
oppositeCastling = true

# A Kyoto Shogi variant with a left/right theme.
[gethenian]
maxRank = 7
maxFile = 7
king = -
customPiece1 = k:K
customPiece2 = q:mW
customPiece3 = b:lfrbB
customPiece4 = i:rflbB
customPiece5 = r:lrR
customPiece6 = n:hlN
customPiece7 = t:hrN
customPiece8 = m:WfF
customPiece9 = s:FfW
startFen = 2ikb2/2mnm2/7/7/7/2MNM2/2B+KI2[] w - - 0 1
promotionPieceTypes = -
promotedPieceType = k:q b:r i:r n:t m:s
promotionRegionWhite = *1 *2 *3 *4 *5 *6 *7
promotionRegionBlack = *7 *6 *5 *4 *3 *2 *1
mandatoryPiecePromotion = true
pieceDemotion = true
pieceDrops = true
capturesToHand = true
dropPromoted = true
immobilityIllegal = false
extinctionValue = loss
extinctionPieceTypes = kq
extinctionPseudoRoyal = true
stalemateValue = loss

0 comments on commit 962d0e0

Please sign in to comment.