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 27, 2023
2 parents 962d0e0 + b8274a7 commit f242c53
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 55 deletions.
18 changes: 14 additions & 4 deletions src/movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,23 @@ namespace {
}
if (T == EN_PASSANT)
b ^= pos.capture_square(to);
if (pos.variant()->arrowWalling)

if (pos.walling_rule() == ARROW)
b &= moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from);
if ((pos.variant()->staticWalling)||(pos.variant()->duckWalling))
b &= pos.variant()->wallingRegion[us];
if (pos.variant()->pastWalling)

//Any current or future wall variant must follow the walling region rule if set:
b &= pos.variant()->wallingRegion[us];

if (pos.walling_rule() == PAST)
b &= square_bb(from);
if (pos.walling_rule() == EDGE)
{
Bitboard wallsquares = pos.state()->wallSquares;

b &= (FileABB | file_bb(pos.max_file()) | Rank1BB | rank_bb(pos.max_rank())) |
( shift<NORTH >(wallsquares) | shift<SOUTH >(wallsquares)
| shift<EAST >(wallsquares) | shift<WEST >(wallsquares));
}
while (b)
*moveList++ = make_gating<T>(from, to, pt, pop_lsb(b));
return moveList;
Expand Down
27 changes: 19 additions & 8 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ namespace {
return value == "reversi" || value == "ataxx" || value == "quadwrangle" || value =="snort" || value == "none";
}

template <> bool set(const std::string& value, WallingRule& target) {
target = value == "arrow" ? ARROW
: value == "duck" ? DUCK
: value == "edge" ? EDGE
: value == "past" ? PAST
: value == "static" ? STATIC
: NO_WALLING;
return value == "arrow" || value == "duck" || value == "edge" || value =="past" || value == "static" || value == "none";
}

template <> bool set(const std::string& value, Bitboard& target) {
char file;
int rank;
Expand Down Expand Up @@ -181,6 +191,7 @@ template <bool Current, class T> bool VariantParser<DoCheck>::parse_attribute(co
: std::is_same<T, EnclosingRule>() ? "EnclosingRule"
: std::is_same<T, Bitboard>() ? "Bitboard"
: std::is_same<T, CastlingRights>() ? "CastlingRights"
: std::is_same<T, WallingRule>() ? "WallingRule"
: typeid(T).name();
std::cerr << key << " - Invalid value " << it->second << " for type " << typeName << std::endl;
}
Expand Down Expand Up @@ -434,14 +445,11 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("dropNoDoubledCount", v->dropNoDoubledCount);
parse_attribute("immobilityIllegal", v->immobilityIllegal);
parse_attribute("gating", v->gating);
parse_attribute("arrowWalling", v->arrowWalling);
parse_attribute("duckWalling", v->duckWalling);
parse_attribute("wallingRule", v->wallingRule);
parse_attribute("wallingRegionWhite", v->wallingRegion[WHITE]);
parse_attribute("wallingRegionBlack", v->wallingRegion[BLACK]);
parse_attribute("wallingRegion", v->wallingRegion[WHITE]);
parse_attribute("wallingRegion", v->wallingRegion[BLACK]);
parse_attribute("staticWalling", v->staticWalling);
parse_attribute("pastWalling", v->pastWalling);
parse_attribute("seirawanGating", v->seirawanGating);
parse_attribute("cambodianMoves", v->cambodianMoves);
parse_attribute("diagonalLines", v->diagonalLines);
Expand Down Expand Up @@ -488,6 +496,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("flagPieceCount", v->flagPieceCount);
parse_attribute("flagPieceBlockedWin", v->flagPieceBlockedWin);
parse_attribute("flagMove", v->flagMove);
parse_attribute("flagPieceSafe", v->flagPieceSafe);
parse_attribute("checkCounting", v->checkCounting);
parse_attribute("connectN", v->connectN);
parse_attribute("connectHorizontal", v->connectHorizontal);
Expand Down Expand Up @@ -553,8 +562,8 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
std::cerr << "Inconsistent settings: castlingQueensideFile > castlingKingsideFile." << std::endl;

// Check for limitations
if (v->pieceDrops && (v->arrowWalling || v->duckWalling || v->staticWalling || v->pastWalling))
std::cerr << "pieceDrops and arrowWalling/duckWalling are incompatible." << std::endl;
if (v->pieceDrops && v->wallingRule)
std::cerr << "pieceDrops and any walling are incompatible." << std::endl;

// Options incompatible with royal kings
if (v->pieceTypes & KING)
Expand All @@ -563,8 +572,8 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
std::cerr << "Can not use kings with blastOnCapture." << std::endl;
if (v->flipEnclosedPieces)
std::cerr << "Can not use kings with flipEnclosedPieces." << std::endl;
if (v->duckWalling)
std::cerr << "Can not use kings with duckWalling." << std::endl;
if (v->wallingRule==DUCK)
std::cerr << "Can not use kings with wallingRule = duck." << std::endl;
// We can not fully check support for custom king movements at this point,
// since custom pieces are only initialized on loading of the variant.
// We will assume this is valid, but it might cause problems later if it's not.
Expand All @@ -590,6 +599,8 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
if (v->mutuallyImmuneTypes)
std::cerr << "Can not use kings or pseudo-royal with mutuallyImmuneTypes." << std::endl;
}
if (v->flagPieceSafe && v->blastOnCapture)
std::cerr << "Can not use flagPieceSafe with blastOnCapture (flagPieceSafe uses simple assessment that does not see blast)." << std::endl;
}
return v;
}
Expand Down
40 changes: 27 additions & 13 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ bool Position::legal(Move m) const {
{
Square kto = to;
Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces());
if (var->duckWalling)
if (walling_rule() == DUCK)
occupied ^= st->wallSquares;
if (walling() || is_gating(m))
occupied |= gating_square(m);
Expand Down Expand Up @@ -1303,15 +1303,29 @@ bool Position::pseudo_legal(const Move m) const {
return checkers() ? MoveList< EVASIONS>(*this).contains(m)
: MoveList<NON_EVASIONS>(*this).contains(m);

// Illegal wall square placement
if (walling() && !((board_bb() & ~((pieces() ^ from) | to)) & gating_square(m)))
return false;
if (var->arrowWalling && !(moves_bb(us, type_of(pc), to, pieces() ^ from) & gating_square(m)))
return false;
if (var->pastWalling && (from != gating_square(m)))
return false;
if ((var->staticWalling || var->duckWalling) && !(var->wallingRegion[us] & gating_square(m)))
return false;
if (walling())
{
Bitboard wallsquares = st->wallSquares;

// Illegal wall square placement
if (!((board_bb() & ~((pieces() ^ from) | to)) & gating_square(m)))
return false;
if (!(var->wallingRegion[us] & gating_square(m)) || //putting a wall on disallowed square
wallsquares & gating_square(m)) //or square already with a wall
return false;
if (walling_rule() == ARROW && !(moves_bb(us, type_of(pc), to, pieces() ^ from) & gating_square(m)))
return false;
if (walling_rule() == PAST && (from != gating_square(m)))
return false;
if (walling_rule() == EDGE)
{
Bitboard validsquares = board_bb() &
((FileABB | file_bb(max_file()) | Rank1BB | rank_bb(max_rank())) |
( shift<NORTH >(wallsquares) | shift<SOUTH >(wallsquares)
| shift<EAST >(wallsquares) | shift<WEST >(wallsquares)));
if (!(validsquares & gating_square(m))) return false;
};
}

// Handle the case where a mandatory piece promotion/demotion is not taken
if ( mandatory_piece_promotion()
Expand Down Expand Up @@ -2034,7 +2048,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
if (walling())
{
// Reset wall squares for duck walling
if (var->duckWalling)
if (walling_rule() == DUCK)
{
Bitboard b = st->previous->wallSquares;
byTypeBB[ALL_PIECES] ^= b;
Expand Down Expand Up @@ -2476,7 +2490,7 @@ bool Position::see_ge(Move m, Value threshold) const {
stmAttackers &= ~blockers_for_king(stm);

// Ignore distant sliders
if (var->duckWalling)
if (walling_rule() == DUCK)
stmAttackers &= attacks_bb<KING>(to) | ~(pieces(BISHOP, ROOK) | pieces(QUEEN));

if (!stmAttackers)
Expand Down Expand Up @@ -2969,7 +2983,7 @@ bool Position::has_game_cycle(int ply) const {

int end = captures_to_hand() ? st->pliesFromNull : std::min(st->rule50, st->pliesFromNull);

if (end < 3 || var->nFoldValue != VALUE_DRAW || var->perpetualCheckIllegal || var->materialCounting || var->moveRepetitionIllegal || var->duckWalling)
if (end < 3 || var->nFoldValue != VALUE_DRAW || var->perpetualCheckIllegal || var->materialCounting || var->moveRepetitionIllegal || walling_rule() == DUCK)
return false;

Key originalKey = st->key;
Expand Down
41 changes: 39 additions & 2 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class Position {
bool immobility_illegal() const;
bool gating() const;
bool walling() const;
WallingRule walling_rule() const;
bool seirawan_gating() const;
bool cambodian_moves() const;
Bitboard diagonal_lines() const;
Expand Down Expand Up @@ -761,7 +762,12 @@ inline bool Position::gating() const {

inline bool Position::walling() const {
assert(var != nullptr);
return var->arrowWalling || var->duckWalling || var->staticWalling || var->pastWalling;
return var->wallingRule != NO_WALLING;
}

inline WallingRule Position::walling_rule() const {
assert(var != nullptr);
return var->wallingRule;
}

inline bool Position::seirawan_gating() const {
Expand Down Expand Up @@ -956,9 +962,40 @@ inline bool Position::flag_move() const {

inline bool Position::flag_reached(Color c) const {
assert(var != nullptr);
return (flag_region(c) & pieces(c, flag_piece(c)))
bool simpleResult =
(flag_region(c) & pieces(c, flag_piece(c)))
&& ( popcount(flag_region(c) & pieces(c, flag_piece(c))) >= var->flagPieceCount
|| (var->flagPieceBlockedWin && !(flag_region(c) & ~pieces())));

if (simpleResult&&var->flagPieceSafe)
{
Bitboard piecesInFlagZone = flag_region(c) & pieces(c, flag_piece(c));
int potentialPieces = (popcount(piecesInFlagZone));
/*
There isn't a variant that uses it, but in the hypothetical game where the rules say I need 3
pieces in the flag zone and they need to be safe: If I have 3 pieces there, but one is under
threat, I don't think I can declare victory. If I have 4 there, but one is under threat, I
think that's victory.
*/
while (piecesInFlagZone)
{
Square sr = pop_lsb(piecesInFlagZone);
Bitboard flagAttackers = attackers_to(sr, ~c);

if ((potentialPieces < var->flagPieceCount) || (potentialPieces >= var->flagPieceCount + 1)) break;
while (flagAttackers)
{
Square currentAttack = pop_lsb(flagAttackers);
if (legal(make_move(currentAttack, sr)))
{
potentialPieces--;
break;
}
}
}
return potentialPieces >= var->flagPieceCount;
}
return simpleResult;
}

inline bool Position::check_counting() const {
Expand Down
2 changes: 1 addition & 1 deletion src/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ namespace {
continue;

// Prune moves with negative SEE (~20 Elo)
if (!pos.variant()->duckWalling && !pos.see_ge(move, Value(-(30 - std::min(lmrDepth, 18) + 10 * !!pos.flag_region(pos.side_to_move())) * lmrDepth * lmrDepth)))
if (!(pos.walling_rule() == DUCK) && !pos.see_ge(move, Value(-(30 - std::min(lmrDepth, 18) + 10 * !!pos.flag_region(pos.side_to_move())) * lmrDepth * lmrDepth)))
continue;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ enum EnclosingRule {
NO_ENCLOSING, REVERSI, ATAXX, QUADWRANGLE, SNORT
};

enum WallingRule {
NO_WALLING, ARROW, DUCK, EDGE, PAST, STATIC
};

enum OptBool {
NO_VALUE, VALUE_FALSE, VALUE_TRUE
};
Expand Down
10 changes: 5 additions & 5 deletions src/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ namespace {
v->castlingKingPiece[WHITE] = v->castlingKingPiece[BLACK] = COMMONER;
v->extinctionValue = -VALUE_MATE;
v->extinctionPieceTypes = piece_set(COMMONER);
v->duckWalling = true;
v->wallingRule = DUCK;
v->stalemateValue = VALUE_MATE;
return v;
}
Expand All @@ -529,7 +529,7 @@ namespace {
v->add_piece(CUSTOM_PIECE_1, 'p', "mK"); //move as a King, but can't capture
v->startFen = "3p2/6/6/6/6/6/6/2P3 w - - 0 1";
v->stalemateValue = -VALUE_MATE;
v->staticWalling = true;
v->wallingRule = STATIC;
v->wallingRegion[WHITE] = v->wallingRegion[BLACK] = AllSquares ^ make_bitboard(SQ_C1, SQ_D8);
return v;
}
Expand All @@ -551,7 +551,7 @@ namespace {
v->add_piece(CUSTOM_PIECE_1, 'p', "mK"); //move as a King, but can't capture
v->startFen = "6p/7/7/7/7/7/P6 w - - 0 1";
v->stalemateValue = -VALUE_MATE;
v->pastWalling = true;
v->wallingRule = PAST;
return v;
}

Expand All @@ -562,7 +562,7 @@ namespace {
v->add_piece(CUSTOM_PIECE_1, 'n', "mN"); //move as a Knight, but can't capture
v->startFen = "8/8/8/4n3/3N4/8/8/8 w - - 0 1";
v->stalemateValue = -VALUE_MATE;
v->pastWalling = true;
v->wallingRule = PAST;
return v;
}

Expand Down Expand Up @@ -1668,7 +1668,7 @@ namespace {
v->add_piece(CUSTOM_PIECE_1, 'q', "mQ");
v->startFen = "3q2q3/10/10/q8q/10/10/Q8Q/10/10/3Q2Q3 w - - 0 1";
v->stalemateValue = -VALUE_MATE;
v->arrowWalling = true;
v->wallingRule = ARROW;
return v;
}
#endif
Expand Down
6 changes: 2 additions & 4 deletions src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ struct Variant {
int dropNoDoubledCount = 1;
bool immobilityIllegal = false;
bool gating = false;
bool arrowWalling = false;
bool duckWalling = false;
bool staticWalling = false;
bool pastWalling = false;
WallingRule wallingRule = NO_WALLING;
Bitboard wallingRegion[COLOR_NB] = {AllSquares, AllSquares};
bool seirawanGating = false;
bool cambodianMoves = false;
Expand Down Expand Up @@ -150,6 +147,7 @@ struct Variant {
int flagPieceCount = 1;
bool flagPieceBlockedWin = false;
bool flagMove = false;
bool flagPieceSafe = false;
bool checkCounting = false;
int connectN = 0;
bool connectHorizontal = true;
Expand Down
Loading

0 comments on commit f242c53

Please sign in to comment.