Skip to content

Commit

Permalink
Add Cfour-anyside, Symphony, Teeko (#731)
Browse files Browse the repository at this point in the history
  • Loading branch information
RainRat authored Oct 24, 2023
1 parent 5d3af09 commit 3f40ada
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 17 deletions.
10 changes: 8 additions & 2 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ namespace {
: value == "ataxx" ? ATAXX
: value == "quadwrangle" ? QUADWRANGLE
: value == "snort" ? SNORT
: value == "anyside" ? ANYSIDE
: value == "top" ? TOP
: NO_ENCLOSING;
return value == "reversi" || value == "ataxx" || value == "quadwrangle" || value =="snort" || value == "none";
return value == "reversi" || value == "ataxx" || value == "quadwrangle" || value =="snort" || value =="anyside" || value =="top" || value == "none";
}

template <> bool set(const std::string& value, WallingRule& target) {
Expand Down Expand Up @@ -327,6 +329,10 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute<false>("castlingRookPiece", v->castlingRookPieces[WHITE], v->pieceToChar);
parse_attribute<false>("castlingRookPiece", v->castlingRookPieces[BLACK], v->pieceToChar);

bool dropOnTop = false;
parse_attribute<false>("dropOnTop", dropOnTop);
if (dropOnTop) v->enclosingDrop=TOP;

// Parse aliases
parse_attribute("pawnTypes", v->promotionPawnType[WHITE], v->pieceToChar);
parse_attribute("pawnTypes", v->promotionPawnType[BLACK], v->pieceToChar);
Expand Down Expand Up @@ -433,7 +439,6 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("capturesToHand", v->capturesToHand);
parse_attribute("firstRankPawnDrops", v->firstRankPawnDrops);
parse_attribute("promotionZonePawnDrops", v->promotionZonePawnDrops);
parse_attribute("dropOnTop", v->dropOnTop);
parse_attribute("enclosingDrop", v->enclosingDrop);
parse_attribute("enclosingDropStart", v->enclosingDropStart);
parse_attribute("whiteDropRegion", v->whiteDropRegion);
Expand Down Expand Up @@ -502,6 +507,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("connectHorizontal", v->connectHorizontal);
parse_attribute("connectVertical", v->connectVertical);
parse_attribute("connectDiagonal", v->connectDiagonal);
parse_attribute("connectNxN", v->connectNxN);
parse_attribute("materialCounting", v->materialCounting);
parse_attribute("countingRule", v->countingRule);
parse_attribute("castlingWins", v->castlingWins);
Expand Down
13 changes: 13 additions & 0 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2806,6 +2806,19 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
}
}
}

if (connect_nxn())
{
Bitboard connectors = pieces(~sideToMove);
for (int i = 1; i < connect_nxn() && connectors; i++)
connectors &= shift<SOUTH>(connectors) & shift<EAST>(connectors) & shift<SOUTH_EAST>(connectors);
if (connectors)
{
result = mated_in(ply);
return true;
}
}

// Check for bikjang rule (Janggi) and double passing
if (st->pliesFromNull > 0 && ((st->bikjang && st->previous->bikjang) || (st->pass && st->previous->pass)))
{
Expand Down
52 changes: 42 additions & 10 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ class Position {
bool drop_loop() const;
bool captures_to_hand() const;
bool first_rank_pawn_drops() const;
bool drop_on_top() const;
bool can_drop(Color c, PieceType pt) const;
EnclosingRule enclosing_drop() const;
Bitboard drop_region(Color c) const;
Expand Down Expand Up @@ -210,6 +209,7 @@ class Position {
bool connect_vertical() const;
bool connect_diagonal() const;
const std::vector<Direction>& getConnectDirections() const;
int connect_nxn() const;

CheckCount checks_remaining(Color c) const;
MaterialCounting material_counting() const;
Expand Down Expand Up @@ -373,6 +373,7 @@ class Position {
void remove_from_hand(Piece pc);
void drop_piece(Piece pc_hand, Piece pc_drop, Square s);
void undrop_piece(Piece pc_hand, Square s);
Bitboard find_drop_region(Direction dir, Square s, Bitboard occupied) const;
};

extern std::ostream& operator<<(std::ostream& os, const Position& pos);
Expand Down Expand Up @@ -648,11 +649,6 @@ inline bool Position::first_rank_pawn_drops() const {
return var->firstRankPawnDrops;
}

inline bool Position::drop_on_top() const {
assert(var != nullptr);
return var->dropOnTop;
}

inline EnclosingRule Position::enclosing_drop() const {
assert(var != nullptr);
return var->enclosingDrop;
Expand All @@ -666,9 +662,6 @@ inline Bitboard Position::drop_region(Color c) const {
inline Bitboard Position::drop_region(Color c, PieceType pt) const {
Bitboard b = drop_region(c) & board_bb(c, pt);

// Connect4-style drops
if (drop_on_top())
b &= shift<NORTH>(pieces()) | Rank1BB;
// Pawns on back ranks
if (pt == PAWN)
{
Expand All @@ -686,14 +679,14 @@ inline Bitboard Position::drop_region(Color c, PieceType pt) const {
if (pt == ROOK && sittuyin_rook_drop())
b &= rank_bb(relative_rank(c, RANK_1, max_rank()));

// Filter out squares where the drop does not enclose at least one opponent's piece
if (enclosing_drop())
{
// Reversi start
if (var->enclosingDropStart & ~pieces())
b &= var->enclosingDropStart;
else
{
// Filter out squares where the drop does not enclose at least one opponent's piece
if (enclosing_drop() == REVERSI)
{
Bitboard theirs = pieces(~c);
Expand All @@ -715,6 +708,40 @@ inline Bitboard Position::drop_region(Color c, PieceType pt) const {
b &= ~(shift<NORTH >(theirs) | shift<SOUTH >(theirs)
| shift<EAST >(theirs) | shift<WEST >(theirs));
}
else if (enclosing_drop() == ANYSIDE)
{
Bitboard occupied = pieces();
b = 0ULL;
Bitboard candidates = (shift<WEST>(occupied) | file_bb(max_file())) & ~occupied;

for (Rank r = RANK_1; r <= max_rank(); ++r) {
if (!(occupied & make_square(FILE_A, r))) {
b |= lsb(candidates & rank_bb(r));
}
}
candidates = (shift<SOUTH>(occupied) | rank_bb(max_rank())) & ~occupied;
for (File f = FILE_A; f <= max_file(); ++f) {
if (!(occupied & make_square(f, RANK_1))) {
b |= lsb(candidates & file_bb(f));
}
}
candidates = (shift<NORTH>(occupied) | rank_bb(RANK_1)) & ~occupied;
for (File f = FILE_A; f <= max_file(); ++f) {
if (!(occupied & make_square(f, max_rank()))) {
b |= lsb(candidates & file_bb(f));
}
}
candidates = (shift<EAST>(occupied) | file_bb(FILE_A)) & ~occupied;
for (Rank r = RANK_1; r <= max_rank(); ++r) {
if (!(occupied & make_square(max_file(), r))) {
b |= lsb(candidates & rank_bb(r));
}
}
}
else if (enclosing_drop() == TOP)
{
b &= shift<NORTH>(pieces()) | Rank1BB;
}
else
{
assert(enclosing_drop() == ATAXX);
Expand Down Expand Up @@ -1026,6 +1053,11 @@ inline const std::vector<Direction>& Position::getConnectDirections() const {
return var->connect_directions;
}

inline int Position::connect_nxn() const {
assert(var != nullptr);
return var->connectNxN;
}

inline CheckCount Position::checks_remaining(Color c) const {
return st->checksRemaining[c];
}
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, SNORT
NO_ENCLOSING, REVERSI, ATAXX, QUADWRANGLE, SNORT, ANYSIDE, TOP
};

enum WallingRule {
Expand Down
2 changes: 1 addition & 1 deletion src/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ struct Variant {
bool capturesToHand = false;
bool firstRankPawnDrops = false;
bool promotionZonePawnDrops = false;
bool dropOnTop = false;
EnclosingRule enclosingDrop = NO_ENCLOSING;
Bitboard enclosingDropStart = 0;
Bitboard whiteDropRegion = AllSquares;
Expand Down Expand Up @@ -153,6 +152,7 @@ struct Variant {
bool connectHorizontal = true;
bool connectVertical = true;
bool connectDiagonal = true;
int connectNxN = 0;
MaterialCounting materialCounting = NO_MATERIAL_COUNTING;
CountingRule countingRule = NO_COUNTING;
CastlingRights castlingWins = NO_CASTLING;
Expand Down
42 changes: 39 additions & 3 deletions src/variants.ini
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,17 @@
# [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, snort, none]
# [EnclosingRule]: reversi, ataxx, etc. enclosing rules [reversi, ataxx, quadwrangle, snort, anyside, top, none]
# - in enclosingDrop:
# - reversi: must enclose opponent's pieces between yours by Queen move
# - ataxx: must be adjacent to own piece by King move
# - snort: most *not* be adjacent to opponent's piece by Wazir move
# - anyside: must be reached by inserting from an edge and sliding to opposite edge
# - top: must be reached by inserting from top and sliding to bottom (ie. Connect 4)
# - in flipEnclosedPieces:
# - reversi: flip opponent's pieces enclosed between yours by Queen move
# - quadwrangle: if a normal move *or* a drop with a friendly piece adjacent by King move, then flip opponent's pieces adjacent by King move
# - ataxx: flip opponent's pieces adjacent by King move
# [WallingRule]: wall-placing rule [arrow, duck, edge, past, static, none]
# - arrow: copies piece movement (ie. Game of the Amazons)
# - duck: mobile square (ie. Duck chess)
Expand Down Expand Up @@ -207,7 +217,7 @@
# capturesToHand: captured pieces go to opponent's hand [bool] (default: false)
# firstRankPawnDrops: allow pawn drops to first rank [bool] (default: false)
# promotionZonePawnDrops: allow pawn drops in promotion zone [bool] (default: false)
# dropOnTop: piece drops need to be on top of pieces on board (e.g., for connect4) [bool] (default: false)
# dropOnTop: DEPRECATED, use "enclosingDrop = top"
# enclosingDrop: require piece drop to enclose pieces [EnclosingRule] (default: none)
# enclosingDropStart: drop region for starting phase disregarding enclosingDrop (e.g., for reversi) [Bitboard]
# whiteDropRegion: restrict region for piece drops of all white pieces [Bitboard]
Expand Down Expand Up @@ -269,6 +279,7 @@
# connectVertical: connectN looks at Vertical rows [bool] (default: true)
# connectHorizontal: connectN looks at Horizontal rows [bool] (default: true)
# connectDiagonal: connectN looks at Diagonal rows [bool] (default: true)
# connectNxN: connect a tight NxN square for win [int] (default: 0)
# 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. [CastlingRights] (default: -)
Expand Down Expand Up @@ -490,7 +501,7 @@ maxFile = 7
immobile = p
startFen = 7/7/7/7/7/7[PPPPPPPPPPPPPPPPPPPPPppppppppppppppppppppp] w - - 0 1
pieceDrops = true
dropOnTop = true
enclosingDrop = top
doubleStep = false
castling = false
stalemateValue = draw
Expand Down Expand Up @@ -1801,6 +1812,15 @@ castling = false
doubleStep = false
promotionRegionWhite = *6

#https://www.zillions-of-games.com/cgi-bin/zilligames/submissions.cgi?do=show;id=655
[teeko:picaria]
maxRank = 5
maxFile = 5
connectN = 4
connectNxN = 2
customPiece1 = p:mK
startFen = 5/5/5/5/5[PPPPpppp] w - - 0 1

#https://www.chessvariants.com/small.dir/haynie.html
[haynie:chess]
maxRank = 6
Expand All @@ -1811,3 +1831,19 @@ promotionPieceTypes = rbq
castlingQueensideFile = c
castlingKingsideFile = e
promotionRegionWhite = *6

#https://www.zillions-of-games.com/cgi-bin/zilligames/submissions.cgi?do=show;id=1723
[symphony:tictactoe]
maxRank = 8
maxFile = 8
connectN = 5
customPiece1 = p:mfsW
nFoldRule = 3
startFen = 8/8/8/8/8/8/8/8[PPPPPPpppppp] w - - 0

#https://www.zillions-of-games.com/cgi-bin/zilligames/submissions.cgi?do=show;id=734
#am calling it cfour-anyside so it's less confusable with roll-ing-to-four
[cfour-anyside:cfour]
maxRank = 7
startFen = 7/7/7/7/7/7/7[PPPPPPPPPPPPPPPPPPPPPPPPPpppppppppppppppppppppppp] w - - 0 1
enclosingDrop = anyside

0 comments on commit 3f40ada

Please sign in to comment.