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);
}
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) {
.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))
.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))
return Py_BuildValue("O", Stockfish::is_check(pos) ? Py_True : Py_False);
}
+// INPUT variant, fen, move list, move
+extern "C" PyObject* pyffish_isCapture(PyObject* self, PyObject *args) {
+ Position pos;
+ PyObject *moveList;
+ const char *variant, *fen, *move;
+ int chess960 = false;
+ if (!PyArg_ParseTuple(args, "ssO!s|p", &variant, &fen, &PyList_Type, &moveList, &move, &chess960)) {
+ return NULL;
+ }
+
+ StateListPtr states(new std::deque<StateInfo>(1));
+ buildPosition(pos, states, variant, fen, moveList, chess960);
+ std::string moveStr = move;
+
+ return Py_BuildValue("O", pos.capture(UCI::to_move(pos, moveStr)) ? Py_True : Py_False);
+}
+
// INPUT variant, fen, move list
// should only be called when the move list is empty
extern "C" PyObject* pyffish_gameResult(PyObject* self, PyObject *args) {
{"legal_moves", (PyCFunction)pyffish_legalMoves, METH_VARARGS, "Get legal moves from given FEN and movelist."},
{"get_fen", (PyCFunction)pyffish_getFEN, METH_VARARGS, "Get resulting FEN from given FEN and movelist."},
{"gives_check", (PyCFunction)pyffish_givesCheck, METH_VARARGS, "Get check status from given FEN and movelist."},
+ {"is_capture", (PyCFunction)pyffish_isCapture, METH_VARARGS, "Get whether given move is a capture from given FEN and movelist."},
{"game_result", (PyCFunction)pyffish_gameResult, METH_VARARGS, "Get result from given FEN, considering variant end, checkmate, and stalemate."},
{"is_immediate_game_end", (PyCFunction)pyffish_isImmediateGameEnd, METH_VARARGS, "Get result from given FEN if variant rules ends the game."},
{"is_optional_game_end", (PyCFunction)pyffish_isOptionalGameEnd, METH_VARARGS, "Get result from given FEN it rules enable game end by player."},
result = sf.gives_check("janggi", "4ka3/4a4/9/4R4/2B6/9/9/5K3/4p4/3r5 b - - 0 113", ["e2f2"])
self.assertTrue(result)
+ def test_is_capture(self):
+ result = sf.is_capture("chess", CHESS, [], "e2e4")
+ self.assertFalse(result)
+
+ result = sf.is_capture("chess", CHESS, ["e2e4", "e7e5", "g1f3", "b8c6", "f1c4", "f8c5"], "e1g1")
+ self.assertFalse(result)
+
+ result = sf.is_capture("chess", CHESS, ["e2e4", "g8f6", "e4e5", "d7d5"], "e5f6")
+ self.assertTrue(result)
+
+ # en passant
+ result = sf.is_capture("chess", CHESS, ["e2e4", "g8f6", "e4e5", "d7d5"], "e5d6")
+ self.assertTrue(result)
+
+ # 960 castling
+ result = sf.is_capture("chess", "bqrbkrnn/pppppppp/8/8/8/8/PPPPPPPP/BQRBKRNN w CFcf - 0 1", ["g1f3", "h8g6"], "e1f1", True)
+ self.assertFalse(result)
+
+ # Sittuyin in-place promotion
+ result = sf.is_capture("sittuyin", "8/2k5/8/4P3/4P1N1/5K2/8/8[] w - - 0 1", [], "e5e5f")
+ self.assertFalse(result)
+
def test_game_result(self):
result = sf.game_result("chess", CHESS, ["f2f3", "e7e5", "g2g4", "d8h4"])
self.assertEqual(result, -sf.VALUE_MATE)
--- /dev/null
+export declare function Module(opts?: ModuleOptions): Promise<FairyStockfish>;
+export default Module;
+
+export interface ModuleOptions {
+ arguments?: string[];
+ buffer?: ArrayBuffer | SharedArrayBuffer;
+ wasmMemory?: WebAssembly.Memory;
+ locateFile?: (file: string, prefix: string) => string;
+ logReadFiles?: boolean;
+ printWithColors?: boolean;
+ onAbort?: (status: string | number) => void;
+ onRuntimeInitialized?: (loadedModule: FairyStockfish) => void;
+ noExitRuntime?: boolean;
+ noInitialRun?: boolean;
+ preInit?: () => void | (() => void)[];
+ preRun?: () => void | (() => void)[];
+ print?: (text: string) => void;
+ printErr?: (text: string) => void;
+ mainScriptUrlOrBlob?: string;
+}
+
+export interface FairyStockfish {
+ Board: Board;
+ Game: Game;
+ Notation: typeof Notation;
+ Termination: typeof Termination;
+ info(): string;
+ setOption<T>(name: string, value: T): void;
+ setOptionInt(name: string, value: number): void;
+ setOptionBool(name: string, value: boolean): void;
+ readGamePGN(pgn: string): Game;
+ variants(): string;
+ loadVariantConfig(variantInitContent: string): void;
+ capturesToHand(uciVariant: string): boolean;
+ startingFen(uciVariant: string): string;
+ validateFen(fen: string, uciVariant?: string, chess960?: boolean): number;
+}
+
+export interface Board {
+ new(uciVariant?: string, fen?: string, is960?: boolean): Board;
+ delete(): void;
+ legalMoves(): string;
+ legalMovesSan(): string;
+ numberLegalMoves(): number;
+ push(uciMove: string): boolean;
+ pushSan(sanMove: string, notation?: Notation): boolean;
+ pop(): void;
+ reset(): void;
+ is960(): boolean;
+ fen(showPromoted?: boolean, countStarted?: number): string;
+ setFen(fen: string): void;
+ sanMove(uciMove: string, notation?: Notation): string;
+ variationSan(uciMoves: string, notation?: Notation, moveNumbers?: boolean): string;
+ turn(): boolean;
+ fullmoveNumber(): number;
+ halfmoveClock(): number;
+ gamePly(): number;
+ hasInsufficientMaterial(turn: boolean): boolean;
+ isInsufficientMaterial(): boolean;
+ isGameOver(claimDraw?: boolean): boolean;
+ result(claimDraw?: boolean): string;
+ isCheck(): boolean;
+ isBikjang(): boolean;
+ isCapture(uciMove: string): boolean;
+ moveStack(): string;
+ pushMoves(uciMoves: string): void;
+ pushSanMoves(sanMoves: string, notation?: Notation): void;
+ pocket(color: boolean): string;
+ toString(): string;
+ toVerboseString(): string;
+ variant(): string;
+}
+
+export interface Game {
+ delete(): void;
+ headerKeys(): string;
+ headers(item: string): string;
+ mainlineMoves(): string;
+}
+
+export declare enum Notation {
+ DEFAULT,
+ SAN,
+ LAN,
+ SHOGI_HOSKING,
+ SHOGI_HODGES,
+ SHOGI_HODGES_NUMBER,
+ JANGGI,
+ XIANGQI_WXF,
+ THAI_SAN,
+ THAI_LAN,
+}
+
+export declare enum Termination {
+ ONGOING,
+ CHECKMATE,
+ STALEMATE,
+ INSUFFICIENT_MATERIAL,
+ N_MOVE_RULE,
+ N_FOLD_REPETITION,
+ VARIANT_END,
+}
{
"name": "ffish",
- "version": "0.7.2",
+ "version": "0.7.3",
"description": "A high performance WebAssembly chess variant library based on Fairy-Stockfish",
"main": "ffish.js",
+ "types": "ffish.d.ts",
"scripts": {
"test": "mocha --timeout 80000",
"dev": "node index"
});
});
+describe('board.fen(showPromoted)', function () {
+ it("it returns the current position in fen format. showPromoted makes promoted pieces always followed by the symbol ~ regardless of variant.", () => {
+ let board = new ffish.Board("makruk", "8/6ks/3M~2r1/2K1M3/8/3R4/8/8 w - 128 18 50");
+ chai.expect(board.fen(true)).to.equal("8/6ks/3M~2r1/2K1M3/8/3R4/8/8 w - 128 18 50");
+ chai.expect(board.fen(false)).to.equal("8/6ks/3M2r1/2K1M3/8/3R4/8/8 w - 128 18 50");
+ });
+});
+
describe('board.fen(showPromoted, countStarted)', function () {
it("it returns the current position in fen format. showPromoted makes promoted pieces always followed by the symbol ~ regardless of variant. countStarted overwrites the start of makruk's board honor counting.", () => {
let board = new ffish.Board("makruk", "8/6ks/3M~2r1/2K1M3/8/3R4/8/8 w - 128 18 50");
});
});
+describe('board.isCapture(move)', function() {
+ it("it checks if a move is a capture", () => {
+ let board = new ffish.Board();
+ chai.expect(board.isCapture("e2e4")).to.equal(false);
+ board.pushMoves("e2e4 e7e5 g1f3 b8c6 f1c4 f8c5");
+ chai.expect(board.isCapture("e1g1")).to.equal(false);
+ board.reset();
+ board.pushMoves("e2e4 g8f6 e4e5 d7d5");
+ chai.expect(board.isCapture("e5f6")).to.equal(true);
+ chai.expect(board.isCapture("e5d6")).to.equal(true);
+ board.delete();
+
+ board = new ffish.Board("chess", "bqrbkrnn/pppppppp/8/8/8/8/PPPPPPPP/BQRBKRNN w CFcf - 0 1", true);
+ board.pushMoves("g1f3 h8g6");
+ chai.expect(board.isCapture("e1f1")).to.equal(false);
+ board.delete();
+
+ board = new ffish.Board("sittuyin", "8/2k5/8/4P3/4P1N1/5K2/8/8[] w - - 0 1");
+ chai.expect(board.isCapture("e5e5f")).to.equal(false);
+ board.delete();
+ });
+});
+
describe('board.moveStack()', function () {
it("it returns the move stack in UCI notation", () => {
let board = new ffish.Board();