Skip to content

Commit

Permalink
Merge branch 'ianfab:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mtaktikos authored Jan 26, 2023
2 parents c2fbc93 + 88d692e commit a4e4bdf
Show file tree
Hide file tree
Showing 28 changed files with 536 additions and 81 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The games currently supported besides chess are listed below. Fairy-Stockfish ca
- [Chess960](https://en.wikipedia.org/wiki/Chess960), [Placement/Pre-Chess](https://www.chessvariants.com/link/placement-chess)
- [Crazyhouse](https://en.wikipedia.org/wiki/Crazyhouse), [Loop](https://en.wikipedia.org/wiki/Crazyhouse#Variations), [Chessgi](https://en.wikipedia.org/wiki/Crazyhouse#Variations), [Pocket Knight](http://www.chessvariants.com/other.dir/pocket.html), Capablanca-Crazyhouse
- [Bughouse](https://en.wikipedia.org/wiki/Bughouse_chess), [Koedem](http://schachclub-oetigheim.de/wp-content/uploads/2016/04/Koedem-rules.pdf)
- [Seirawan](https://en.wikipedia.org/wiki/Seirawan_chess), Seirawan-Crazyhouse
- [Seirawan](https://en.wikipedia.org/wiki/Seirawan_chess), Seirawan-Crazyhouse, [Dragon Chess](https://www.edami.com/dragonchess/)
- [Amazon](https://www.chessvariants.com/diffmove.dir/amazone.html), [Chigorin](https://www.chessvariants.com/diffsetup.dir/chigorin.html), [Almost chess](https://en.wikipedia.org/wiki/Almost_Chess)
- [Hoppel-Poppel](http://www.chessvariants.com/diffmove.dir/hoppel-poppel.html), New Zealand
- [Antichess](https://lichess.org/variant/antichess), [Giveaway](http://www.chessvariants.com/diffobjective.dir/giveaway.old.html), [Suicide](https://www.freechess.org/Help/HelpFiles/suicide_chess.html), [Losers](https://www.chessclub.com/help/Wild17), [Codrus](http://www.binnewirtz.com/Schlagschach1.htm)
Expand All @@ -56,7 +56,7 @@ The games currently supported besides chess are listed below. Fairy-Stockfish ca
- [Atomic](https://en.wikipedia.org/wiki/Atomic_chess)
- [Horde](https://en.wikipedia.org/wiki/Dunsany%27s_Chess#Horde_Chess), [Maharajah and the Sepoys](https://en.wikipedia.org/wiki/Maharajah_and_the_Sepoys)
- [Knightmate](https://www.chessvariants.com/diffobjective.dir/knightmate.html), [Nightrider](https://en.wikipedia.org/wiki/Nightrider_(chess)), [Grasshopper](https://en.wikipedia.org/wiki/Grasshopper_chess)
- [Dragon Chess](https://www.edami.com/dragonchess/)
- [Duck chess](https://duckchess.com/), [Omicron](http://www.eglebbk.dds.nl/program/chess-omicron.html), [Gustav III](https://www.chessvariants.com/play/gustav-iiis-chess)

### Shogi variants
- [Minishogi](https://en.wikipedia.org/wiki/Minishogi), [EuroShogi](https://en.wikipedia.org/wiki/EuroShogi), [Judkins shogi](https://en.wikipedia.org/wiki/Judkins_shogi)
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
else:
args = ["-std=c++17", "-flto", "-Wno-date-time"]

args.extend(["-DLARGEBOARDS", "-DPRECOMPUTED_MAGICS", "-DNNUE_EMBEDDING_OFF"])
args.extend(["-DLARGEBOARDS", "-DALLVARS", "-DPRECOMPUTED_MAGICS", "-DNNUE_EMBEDDING_OFF"])

if "64bit" in platform.architecture():
args.append("-DIS_64BIT")
Expand All @@ -39,7 +39,7 @@
sources=sources,
extra_compile_args=args)

setup(name="pyffish", version="0.0.75",
setup(name="pyffish", version="0.0.77",
description="Fairy-Stockfish Python wrapper",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ ifeq ($(nnue),no)
CXXFLAGS += -DNNUE_EMBEDDING_OFF
endif

# Enable all variants, even heavyweight ones like amazons
# Enable all variants, even heavyweight ones like duck and amazons
ifneq ($(all),no)
CXXFLAGS += -DALLVARS
endif
Expand Down
6 changes: 6 additions & 0 deletions src/Makefile_js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ CXX=emcc
CXXFLAGS += --bind -DNNUE_EMBEDDING_OFF -DNO_THREADS -std=c++17 -Wall

largeboards = yes
all = yes
optimize = yes
debug = no

Expand All @@ -48,6 +49,11 @@ ifneq ($(largeboards),no)
CXXFLAGS += -DLARGEBOARDS -DPRECOMPUTED_MAGICS -s TOTAL_MEMORY=32MB -s ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=1GB
endif

# Enable all variants, even heavyweight ones like duck and amazons
ifneq ($(all),no)
CXXFLAGS += -DALLVARS
endif

### Compile as ES6/ES2015 module
ifeq ($(es6),yes)
CXXFLAGS += -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0
Expand Down
14 changes: 10 additions & 4 deletions src/apiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ inline const std::string move_to_san(Position& pos, Move m, Notation n) {
san += std::string("/") + (char)toupper(pos.piece_to_char()[make_piece(us, gating_type(m))]);
}

// Wall square
if (pos.wall_gating())
san += "," + square(pos, gating_square(m), n);

// Check and checkmate
if (pos.gives_check(m) && !is_shogi(n) && n != NOTATION_XIANGQI_WXF)
{
Expand Down Expand Up @@ -551,7 +555,9 @@ inline Validation fill_char_board(CharBoard& board, const std::string& fenBoard,
{
if (c == ' ' || c == '[')
break;
if (isdigit(c))
if (c == '*')
++fileIdx;
else if (isdigit(c))
{
fileIdx += c - '0';
// if we have multiple digits attached we can add multiples of 9 to compute the resulting number (e.g. -> 21 = 2 + 2 * 9 + 1)
Expand Down Expand Up @@ -885,13 +891,13 @@ inline Validation check_digit_field(const std::string& field) {
}

inline std::string get_valid_special_chars(const Variant* v) {
std::string validSpecialCharactersFirstField = "/";
std::string validSpecialCharactersFirstField = "/*";
// Whether or not '-', '+', '~', '[', ']' are valid depends on the variant being played.
if (v->shogiStylePromotions)
validSpecialCharactersFirstField += '+';
if (!v->promotionPieceTypes.empty())
validSpecialCharactersFirstField += '~';
if (!v->freeDrops && (v->pieceDrops || v->seirawanGating || v->arrowGating))
if (!v->freeDrops && (v->pieceDrops || v->seirawanGating))
validSpecialCharactersFirstField += "[-]";
return validSpecialCharactersFirstField;
}
Expand Down Expand Up @@ -935,7 +941,7 @@ inline FenValidation validate_fen(const std::string& fen, const Variant* v, bool

// check for pocket
std::string pocket = "";
if (v->pieceDrops || v->seirawanGating || v->arrowGating)
if (v->pieceDrops || v->seirawanGating)
{
if (check_pocket_info(fenParts[0], nbRanks, v, pocket) == NOK)
return FEN_INVALID_POCKET_INFO;
Expand Down
10 changes: 10 additions & 0 deletions src/ffishjs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ class Board {
return this->pos.fen();
}

std::string fen(bool showPromoted) const {
return this->pos.fen(false, showPromoted);
}

std::string fen(bool showPromoted, int countStarted) const {
return this->pos.fen(false, showPromoted, countStarted);
}
Expand Down Expand Up @@ -332,6 +336,10 @@ class Board {
return pos.bikjang();
}

bool is_capture(std::string uciMove) const {
return pos.capture(UCI::to_move(pos, uciMove));
}

std::string move_stack() const {
std::string moves;
for(auto it = std::begin(moveStack); it != std::end(moveStack); ++it) {
Expand Down Expand Up @@ -680,6 +688,7 @@ EMSCRIPTEN_BINDINGS(ffish_js) {
.function("reset", &Board::reset)
.function("is960", &Board::is_960)
.function("fen", select_overload<std::string()const>(&Board::fen))
.function("fen", select_overload<std::string(bool)const>(&Board::fen))
.function("fen", select_overload<std::string(bool, int)const>(&Board::fen))
.function("setFen", &Board::set_fen)
.function("sanMove", select_overload<std::string(std::string)>(&Board::san_move))
Expand All @@ -699,6 +708,7 @@ EMSCRIPTEN_BINDINGS(ffish_js) {
.function("result", select_overload<std::string(bool) const>(&Board::result))
.function("isCheck", &Board::is_check)
.function("isBikjang", &Board::is_bikjang)
.function("isCapture", &Board::is_capture)
.function("moveStack", &Board::move_stack)
.function("pushMoves", &Board::push_moves)
.function("pushSanMoves", select_overload<void(std::string)>(&Board::push_san_moves))
Expand Down
55 changes: 34 additions & 21 deletions src/movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,34 @@ namespace Stockfish {
namespace {

template<MoveType T>
ExtMove* make_move_and_gating(const Position& pos, ExtMove* moveList, Color us, Square from, Square to) {
ExtMove* make_move_and_gating(const Position& pos, ExtMove* moveList, Color us, Square from, Square to, PieceType pt = NO_PIECE_TYPE) {

// Arrow gating moves
if (pos.arrow_gating())
// Wall placing moves
if (pos.wall_gating())
{
for (PieceType pt_gating : pos.piece_types())
if (pos.can_drop(us, pt_gating))
{
Bitboard b = pos.drop_region(us, pt_gating) & moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from) & ~(pos.pieces() ^ from);
while (b)
*moveList++ = make_gating<T>(from, to, pt_gating, pop_lsb(b));
}
Bitboard b = pos.board_bb() & ~((pos.pieces() ^ from) | to);
if (T == CASTLING)
{
Square kto = make_square(to > from ? pos.castling_kingside_file() : pos.castling_queenside_file(), pos.castling_rank(us));
Direction step = kto > from ? EAST : WEST;
Square rto = kto - step;
b ^= square_bb(to) ^ kto ^ rto;
}
if (T == EN_PASSANT)
b ^= to - pawn_push(us);
if (pos.variant()->arrowGating)
b &= moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from);
if (pos.variant()->staticGating)
b &= pos.variant()->staticGatingRegion;
if (pos.variant()->pastGating)
b &= square_bb(from);

while (b)
*moveList++ = make_gating<T>(from, to, pt, pop_lsb(b));
return moveList;
}

*moveList++ = make<T>(from, to);
*moveList++ = make<T>(from, to, pt);

// Gating moves
if (pos.seirawan_gating() && (pos.gates(us) & from))
Expand All @@ -63,10 +75,10 @@ namespace {
{
for (PieceType pt : pos.promotion_piece_types())
if (!pos.promotion_limit(pt) || pos.promotion_limit(pt) > pos.count(c, pt))
*moveList++ = make<PROMOTION>(to - D, to, pt);
moveList = make_move_and_gating<PROMOTION>(pos, moveList, pos.side_to_move(), to - D, to, pt);
PieceType pt = pos.promoted_piece_type(PAWN);
if (pt && !(pos.piece_promotion_on_capture() && pos.empty(to)))
*moveList++ = make<PIECE_PROMOTION>(to - D, to);
moveList = make_move_and_gating<PIECE_PROMOTION>(pos, moveList, pos.side_to_move(), to - D, to);
}

return moveList;
Expand Down Expand Up @@ -114,9 +126,9 @@ namespace {
Bitboard TRank3BB = forward_ranks_bb(Us, relative_rank(Us, pos.double_step_rank_min(), pos.max_rank()))
& ~shift<Up>(forward_ranks_bb(Us, relative_rank(Us, pos.double_step_rank_max(), pos.max_rank())));

const Bitboard emptySquares = Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces() & pos.board_bb();
const Bitboard enemies = Type == EVASIONS ? (pos.checkers() & pos.non_sliding_riders() ? pos.pieces(Them) : pos.checkers())
: Type == CAPTURES ? target : pos.pieces(Them);
const Bitboard emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces()) & pos.board_bb(Us, PAWN);
const Bitboard enemies = (Type == EVASIONS ? (pos.checkers() & pos.non_sliding_riders() ? pos.pieces(Them) : pos.checkers())
: Type == CAPTURES ? target : pos.pieces(Them)) & pos.board_bb(Us, PAWN);

Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & (pos.mandatory_pawn_promotion() ? ~TRank7BB : AllSquares);
Expand Down Expand Up @@ -147,13 +159,13 @@ namespace {
while (b1)
{
Square to = pop_lsb(b1);
*moveList++ = make_move(to - Up, to);
moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - Up, to);
}

while (b2)
{
Square to = pop_lsb(b2);
*moveList++ = make_move(to - Up - Up, to);
moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - Up - Up, to);
}
}

Expand Down Expand Up @@ -216,13 +228,13 @@ namespace {
while (b1)
{
Square to = pop_lsb(b1);
*moveList++ = make_move(to - UpRight, to);
moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - UpRight, to);
}

while (b2)
{
Square to = pop_lsb(b2);
*moveList++ = make_move(to - UpLeft, to);
moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - UpLeft, to);
}

if (pos.ep_square() != SQ_NONE)
Expand All @@ -238,7 +250,7 @@ namespace {
assert(b1);

while (b1)
*moveList++ = make<EN_PASSANT>(pop_lsb(b1), pos.ep_square());
moveList = make_move_and_gating<EN_PASSANT>(pos, moveList, Us, pop_lsb(b1), pos.ep_square());
}
}

Expand Down Expand Up @@ -335,6 +347,7 @@ namespace {
target = pos.checkers();
}

// Remove inaccesible squares (outside board + wall squares)
target &= pos.board_bb();

moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
Expand Down
14 changes: 8 additions & 6 deletions src/movepick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ namespace {
/// ordering is at the current node.

/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const LowPlyHistory* lp,
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const GateHistory* dh, const LowPlyHistory* lp,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, const Move* killers, int pl)
: pos(p), mainHistory(mh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch),
: pos(p), mainHistory(mh), gateHistory(dh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch),
ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d), ply(pl) {

assert(d > 0);
Expand All @@ -75,9 +75,9 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist
}

/// MovePicker constructor for quiescence search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const GateHistory* dh,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs)
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {
: pos(p), mainHistory(mh), gateHistory(dh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {

assert(d <= 0);

Expand All @@ -89,8 +89,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist

/// MovePicker constructor for ProbCut: we generate captures with SEE greater
/// than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph)
: pos(p), captureHistory(cph), ttMove(ttm), threshold(th) {
MovePicker::MovePicker(const Position& p, Move ttm, Value th, const GateHistory* dh, const CapturePieceToHistory* cph)
: pos(p), gateHistory(dh), captureHistory(cph), ttMove(ttm), threshold(th) {

assert(!pos.checkers());

Expand All @@ -110,10 +110,12 @@ void MovePicker::score() {
for (auto& m : *this)
if constexpr (Type == CAPTURES)
m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6
+ (*gateHistory)[pos.side_to_move()][gating_square(m)]
+ (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];

else if constexpr (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
+ (*gateHistory)[pos.side_to_move()][gating_square(m)]
+ 2 * (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ (*continuationHistory[1])[history_slot(pos.moved_piece(m))][to_sq(m)]
+ (*continuationHistory[3])[history_slot(pos.moved_piece(m))][to_sq(m)]
Expand Down
7 changes: 6 additions & 1 deletion src/movepick.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ enum StatsType { NoCaptures, Captures };
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB + 1) * int(1 << SQUARE_BITS)> ButterflyHistory;

typedef Stats<int16_t, 13365, COLOR_NB, SQUARE_NB> GateHistory;

/// At higher depths LowPlyHistory records successful quiet moves near the root
/// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
/// search and filled during iterative deepening.
Expand Down Expand Up @@ -124,12 +126,14 @@ class MovePicker {
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
MovePicker(const Position&, Move, Value, const GateHistory*, const CapturePieceToHistory*);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const GateHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Square);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const GateHistory*,
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Expand All @@ -146,6 +150,7 @@ class MovePicker {

const Position& pos;
const ButterflyHistory* mainHistory;
const GateHistory* gateHistory;
const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
Expand Down
2 changes: 1 addition & 1 deletion src/nnue/features/half_ka_v2_variants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace Stockfish::Eval::NNUE::Features {
ValueListInserter<IndexType> active
) {
Square oriented_ksq = orient(perspective, pos.nnue_king_square(perspective), pos);
Bitboard bb = pos.pieces();
Bitboard bb = pos.pieces(WHITE) | pos.pieces(BLACK);
while (bb)
{
Square s = pop_lsb(bb);
Expand Down
10 changes: 9 additions & 1 deletion src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("mandatoryPiecePromotion", v->mandatoryPiecePromotion);
parse_attribute("pieceDemotion", v->pieceDemotion);
parse_attribute("blastOnCapture", v->blastOnCapture);
parse_attribute("petrifyOnCapture", v->petrifyOnCapture);
parse_attribute("doubleStep", v->doubleStep);
parse_attribute("doubleStepRank", v->doubleStepRank);
parse_attribute("doubleStepRankMin", v->doubleStepRankMin);
Expand Down Expand Up @@ -328,6 +329,10 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("immobilityIllegal", v->immobilityIllegal);
parse_attribute("gating", v->gating);
parse_attribute("arrowGating", v->arrowGating);
parse_attribute("duckGating", v->duckGating);
parse_attribute("staticGating", v->staticGating);
parse_attribute("pastGating", v->pastGating);
parse_attribute("staticGatingRegion", v->staticGatingRegion);
parse_attribute("seirawanGating", v->seirawanGating);
parse_attribute("cambodianMoves", v->cambodianMoves);
parse_attribute("diagonalLines", v->diagonalLines);
Expand Down Expand Up @@ -434,14 +439,17 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
std::cerr << "Inconsistent settings: castlingQueensideFile > castlingKingsideFile." << std::endl;

// Check for limitations

if (v->pieceDrops && (v->arrowGating || v->duckGating || v->staticGating || v->pastGating))
std::cerr << "pieceDrops and arrowGating/duckGating are incompatible." << std::endl;
// Options incompatible with royal kings
if (v->pieceTypes.find(KING) != v->pieceTypes.end())
{
if (v->blastOnCapture)
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->duckGating)
std::cerr << "Can not use kings with duckGating." << 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 Down
Loading

0 comments on commit a4e4bdf

Please sign in to comment.