[](https://travis-ci.org/ianfab/Fairy-Stockfish)
[](https://ci.appveyor.com/project/ianfab/Fairy-Stockfish/branch/master)
[](https://badge.fury.io/py/pyffish)
+[](https://www.npmjs.com/package/ffish)
Fairy-Stockfish is a chess variant engine derived from [Stockfish](https://github.com/official-stockfish/Stockfish/) designed for the support of fairy chess variants and easy extensibility with more games. It can play various regional, historical, and modern chess variants as well as [games with user-defined rules](https://github.com/ianfab/Fairy-Stockfish/wiki/Variant-configuration). For [compatibility with graphical user interfaces](https://github.com/ianfab/Fairy-Stockfish/wiki/Usage) it supports the UCI, UCCI, USI, and CECP/XBoard protocols.
#include <emscripten/bind.h>
#include <vector>
#include <string>
+#include <sstream>
#include "misc.h"
#include "types.h"
using namespace emscripten;
-void initializeStockfish(std::string& uciVariant) {
+void initialize_stockfish(std::string& uciVariant) {
pieceMap.init();
variants.init();
UCI::init(Options);
Position pos;
Thread* thread;
std::vector<Move> moveStack;
- static bool sfInitialized;
bool is960;
public:
+ static bool sfInitialized;
+
Board():
Board("chess", "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" , false) {
}
- Board(std::string uciVariant) {
- init(uciVariant, "", is960);
+ Board(std::string uciVariant):
+ Board(uciVariant, "", false) {
}
Board(std::string uciVariant, std::string fen):
- Board(uciVariant, fen , false) {
+ Board(uciVariant, fen, false) {
}
Board(std::string uciVariant, std::string fen, bool is960) {
std::string moves = "";
bool first = true;
for (const ExtMove& move : MoveList<LEGAL>(this->pos)) {
- if (first) {
- moves = UCI::move(this->pos, move);
- first = false;
- }
- else
- moves += " " + UCI::move(this->pos, move);
+ if (first) {
+ moves = UCI::move(this->pos, move);
+ first = false;
+ }
+ else
+ moves += " " + UCI::move(this->pos, move);
}
return moves;
}
std::string movesSan = "";
bool first = true;
for (const ExtMove& move : MoveList<LEGAL>(this->pos)) {
- if (first) {
- movesSan = move_to_san(this->pos, move, NOTATION_SAN);
- first = false;
- }
- else
- movesSan += " " + move_to_san(this->pos, move, NOTATION_SAN);
+ if (first) {
+ movesSan = move_to_san(this->pos, move, NOTATION_SAN);
+ first = false;
+ }
+ else
+ movesSan += " " + move_to_san(this->pos, move, NOTATION_SAN);
}
return movesSan;
}
- int number_legal_moves() {
+ int number_legal_moves() const {
return MoveList<LEGAL>(pos).size();
}
// TODO: This is a naive implementation which compares all legal SAN moves with the requested string.
// If the SAN move wasn't found the position remains unchanged. Alternatively, implement a direct conversion.
- void push_san(std::string sanMove) {
- Move foundMove = MOVE_NONE;
- for (const ExtMove& move : MoveList<LEGAL>(pos)) {
- if (sanMove == move_to_san(this->pos, move, NOTATION_SAN)) {
- foundMove = move;
- break;
- }
- }
- if (foundMove != MOVE_NONE)
- do_move(foundMove);
- }
-
+ void push_san(std::string sanMove) {
+ Move foundMove = MOVE_NONE;
+ for (const ExtMove& move : MoveList<LEGAL>(pos)) {
+ if (sanMove == move_to_san(this->pos, move, NOTATION_SAN)) {
+ foundMove = move;
+ break;
+ }
+ }
+ if (foundMove != MOVE_NONE)
+ do_move(foundMove);
+ }
void pop() {
pos.undo_move(this->moveStack.back());
states->pop_back();
}
- void reset() {
- set_fen(v->startFen);
- }
+ void reset() {
+ set_fen(v->startFen);
+ }
- bool is_960() {
- return is960;
- }
+ bool is_960() const {
+ return is960;
+ }
- std::string fen() const {
- return this->pos.fen();
- }
+ std::string fen() const {
+ return this->pos.fen();
+ }
void set_fen(std::string fen) {
resetStates();
return move_to_san(this->pos, UCI::to_move(this->pos, uciMove), NOTATION_SAN);
}
+ std::string san_move(std::string uciMove, Notation notation) {
+ return move_to_san(this->pos, UCI::to_move(this->pos, uciMove), Notation(notation));
+ }
+ std::string variation_san(std::string uciMoves) {
+ return variation_san(uciMoves, NOTATION_SAN, true);
+ }
+
+ std::string variation_san(std::string uciMoves, Notation notation) {
+ return variation_san(uciMoves, notation, true);
+ }
+
+ std::string variation_san(std::string uciMoves, Notation notation, bool moveNumbers) {
+ std::stringstream ss(uciMoves);
+ StateListPtr tempStates;
+ std::vector<Move> moves;
+ std::string variationSan = "";
+ std::string uciMove;
+ bool first = true;
+
+ while (std::getline(ss, uciMove, ' ')) {
+ moves.emplace_back(UCI::to_move(this->pos, uciMove));
+ if (first) {
+ first = false;
+ if (moveNumbers) {
+ variationSan = std::to_string(fullmove_number());
+ if (pos.side_to_move() == WHITE)
+ variationSan += ". ";
+ else
+ variationSan += "...";
+ }
+ variationSan += move_to_san(this->pos, moves.back(), Notation(notation));
+ }
+ else {
+ if (moveNumbers && pos.side_to_move() == WHITE)
+ variationSan += " " + std::to_string(fullmove_number()) + ".";
+ variationSan += " " + move_to_san(this->pos, moves.back(), Notation(notation));
+ }
+ states->emplace_back();
+ pos.do_move(moves.back(), states->back());
+ }
+
+ // recover initial state
+ for(auto rIt = std::rbegin(moves); rIt != std::rend(moves); ++rIt) {
+ pos.undo_move(*rIt);
+ }
+
+ return variationSan;
+ }
+
// returns true for WHITE and false for BLACK
- bool turn() {
+ bool turn() const {
return !pos.side_to_move();
}
- int halfmove_clock() {
+ int fullmove_number() const {
+ return pos.game_ply() / 2 + 1;
+ }
+
+ int halfmove_clock() const {
return pos.rule50_count();
}
- int game_ply() {
+ int game_ply() const {
return pos.game_ply();
}
- bool is_game_over() {
- for (const ExtMove& move : MoveList<LEGAL>(pos)) {
- return false;
- }
+ bool is_game_over() const {
+ for (const ExtMove& move: MoveList<LEGAL>(pos))
+ return false;
return true;
}
+ bool is_check() const {
+ return pos.checkers();
+ }
+
+ bool is_bikjang() const {
+ return pos.bikjang();
+ }
+
// TODO: return board in ascii notation
// static std::string get_string_from_instance(const Board& board) {
// }
}
void init(std::string& uciVariant, std::string fen, bool is960) {
- if (!Board::sfInitialized) {
- initializeStockfish(uciVariant);
- Board::sfInitialized = true;
- }
+ if (!Board::sfInitialized) {
+ initialize_stockfish(uciVariant);
+ Board::sfInitialized = true;
+ }
this->v = variants.find(uciVariant)->second;
this->resetStates();
if (fen == "")
- fen = v->startFen;
+ fen = v->startFen;
this->pos.set(this->v, fen, is960, &this->states->back(), this->thread);
this->is960 = is960;
}
// returns the version of the Fairy-Stockfish binary
std::string info() {
- return engine_info();
+ return engine_info();
}
bool Board::sfInitialized = false;
+template <typename T>
+void set_option(std::string name, T value) {
+ Options[name] = value;
+ Board::sfInitialized = false;
+}
+
// binding code
EMSCRIPTEN_BINDINGS(ffish_js) {
- function("info", &info);
class_<Board>("Board")
.constructor<>()
.constructor<std::string>()
.function("is960", &Board::is_960)
.function("fen", &Board::fen)
.function("setFen", &Board::set_fen)
- .function("sanMove", &Board::san_move)
+ .function("sanMove", select_overload<std::string(std::string)>(&Board::san_move))
+ .function("sanMove", select_overload<std::string(std::string, Notation)>(&Board::san_move))
+ .function("variationSan", select_overload<std::string(std::string)>(&Board::variation_san))
+ .function("variationSan", select_overload<std::string(std::string, Notation)>(&Board::variation_san))
+ .function("variationSan", select_overload<std::string(std::string, Notation, bool)>(&Board::variation_san))
.function("turn", &Board::turn)
+ .function("fullmoveNumber", &Board::fullmove_number)
.function("halfmoveClock", &Board::halfmove_clock)
.function("gamePly", &Board::game_ply)
- .function("isGameOver", &Board::is_game_over);
- // TODO: enable to string conversion method
- // .class_function("getStringFromInstance", &Board::get_string_from_instance);
+ .function("isGameOver", &Board::is_game_over)
+ .function("isCheck", &Board::is_check)
+ .function("isBikjang", &Board::is_bikjang);
+ // usage: e.g. ffish.Notation.DEFAULT
+ enum_<Notation>("Notation")
+ .value("DEFAULT", NOTATION_DEFAULT)
+ .value("SAN", NOTATION_SAN)
+ .value("LAN", NOTATION_LAN)
+ .value("SHOGI_HOSKING", NOTATION_SHOGI_HOSKING)
+ .value("SHOGI_HODGES", NOTATION_SHOGI_HODGES)
+ .value("SHOGI_HODGES_NUMBER", NOTATION_SHOGI_HODGES_NUMBER)
+ .value("JANGGI", NOTATION_JANGGI)
+ .value("XIANGQI_WXF", NOTATION_XIANGQI_WXF);
+ function("info", &info);
+ function("setOption", &set_option<std::string>);
+ function("setOptionInt", &set_option<int>);
+ function("setOptionBool", &set_option<bool>);
+ // TODO: enable to string conversion method
+ // .class_function("getStringFromInstance", &Board::get_string_from_instance);
}
-# ffish.js
+<h2 align="center">ffish.js</h2>
-A high performance WebAssembly chess variant library based on _Fairy-Stockfish_.
+<p align="center">
+<a href="https://img.shields.io/badge/-ffish.js-green"><img src="https://img.shields.io/badge/-ffish.js-green" alt="Package"></a>
+<a href="https://npmcharts.com/compare/ffish?minimal=true"><img src="https://img.shields.io/npm/dm/ffish.svg?sanitize=true" alt="Downloads"></a>
+<a href="https://www.npmjs.com/package/ffish"><img src="https://img.shields.io/npm/v/ffish.svg?sanitize=true" alt="Version"></a>
+</p>
-It is built using emscripten/Embind from C++ source code.
+<p align="center">
+<a href="https://img.shields.io/badge/-ffish--es6.js-green"><img src="https://img.shields.io/badge/-ffish--es6.js-green" alt="Package-ES6"></a>
+<a href="https://npmcharts.com/compare/ffish-es6?minimal=true"><img src="https://img.shields.io/npm/dm/ffish-es6.svg?sanitize=true" alt="Downloads-ES6"></a>
+<a href="https://www.npmjs.com/package/ffish-es6"><img src="https://img.shields.io/npm/v/ffish-es6.svg?sanitize=true" alt="Version-ES6"></a>
+</p>
-* https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html
+
+The package **ffish.js** is a high performance WebAssembly chess variant library based on [_Fairy-Stockfish_](https://github.com/ianfab/Fairy-Stockfish).
+
+It is available as a [standard module](https://www.npmjs.com/package/ffish) and as an [ES6 module](https://www.npmjs.com/package/ffish-es6).
## Install instructions
+### Standard module
+
```bash
npm install ffish
```
-## Build instuctions
-
-```bash
-cd Fairy-Stockfish/src
-```
+### ES6 module
```bash
-emcc -O3 --bind -s TOTAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 \
- -s WASM_MEM_MAX=2147483648 -DLARGEBOARDS -DPRECOMPUTED_MAGICS \
-ffishjs.cpp \
-benchmark.cpp \
-bitbase.cpp \
-bitboard.cpp \
-endgame.cpp \
-evaluate.cpp \
-material.cpp \
-misc.cpp \
-movegen.cpp \
-movepick.cpp \
-parser.cpp \
-partner.cpp \
-pawns.cpp \
-piece.cpp \
-position.cpp \
-psqt.cpp \
-search.cpp \
-thread.cpp \
-timeman.cpp \
-tt.cpp \
-uci.cpp \
-syzygy/tbprobe.cpp \
-ucioption.cpp \
-variant.cpp \
-xboard.cpp \
--o ../tests/js/ffish.js
+npm install ffish-es6
```
-If you want to disable variants with a board greater than 8x8,
- you can remove the flags `-s TOTAL_MEMORY=67108864 -s
- ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=2147483648
- -DLARGEBOARDS` ``-DPRECOMPUTED_MAGICS`.
-
-The pre-compiled wasm binary is built with `-DLARGEBOARDS`.
-
## Examples
Load the API in JavaScript:
+### Standard module
+
```javascript
const ffish = require('ffish');
```
+### ES6 module
+
+```javascript
+import Module from 'ffish';
+let ffish = null;
+
+new Module().then(loadedModule => {
+ ffish = loadedModule;
+ console.log(`initialized ${ffish} ${loadedModule}`);
+ }
+});
+```
+
+### Board object
+
Create a new variant board from its default starting position.
The even `onRuntimeInitialized` ensures that the wasm file was properly loaded.
board.delete();
```
-## Instructions to run the tests
-```bash
-npm install
-npm test
-```
-## Instructions to run the example server
+## Build instuctions
+
+It is built using emscripten/Embind from C++ source code.
+
+* https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html
+
+
+If you want to disable variants with a board greater than 8x8,
+ you can remove the flags `-s TOTAL_MEMORY=67108864 -s
+ ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=2147483648
+ -DLARGEBOARDS -DPRECOMPUTED_MAGICS`.
+
+The pre-compiled wasm binary is built with `-DLARGEBOARDS`.
+
+### Compile as standard module
+
```bash
-npm install
+cd Fairy-Stockfish/src
```
```bash
-node index.js
+emcc -O3 --bind -s TOTAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 \
+ -s WASM_MEM_MAX=2147483648 -DLARGEBOARDS -DPRECOMPUTED_MAGICS \
+ffishjs.cpp \
+benchmark.cpp \
+bitbase.cpp \
+bitboard.cpp \
+endgame.cpp \
+evaluate.cpp \
+material.cpp \
+misc.cpp \
+movegen.cpp \
+movepick.cpp \
+parser.cpp \
+partner.cpp \
+pawns.cpp \
+piece.cpp \
+position.cpp \
+psqt.cpp \
+search.cpp \
+thread.cpp \
+timeman.cpp \
+tt.cpp \
+uci.cpp \
+syzygy/tbprobe.cpp \
+ucioption.cpp \
+variant.cpp \
+xboard.cpp \
+-o ../tests/js/ffish.js
```
-## Compile as ES6/ES2015 module
+### Compile as ES6/ES2015 module
Some environments such as [vue-js](https://vuejs.org/) may require the library to be exported
as a ES6/ES2015 module.
-o ../tests/js/ffish.js
```
-Later the module can be imported as follows:
+Reference: [emscripten/#10114](https://github.com/emscripten-core/emscripten/issues/10114)
-```javascript
-import Module from './ffish.js';
-let ffish = null;
-
-new Module().then(loadedModule => {
- ffish = loadedModule;
- console.log(`initialized ${ffish} ${loadedModule}`);
- }
-});
+## Instructions to run the tests
+```bash
+npm install
+npm test
+```
+## Instructions to run the example server
+```bash
+npm install
+```
+```bash
+node index.js
```
-References: [emscripten/#10114](https://github.com/emscripten-core/emscripten/issues/10114)
{
"name": "ffish",
- "version": "0.1.5",
+ "version": "0.2.0",
"description": "A high performance WebAssembly chess variant library based on Fairy-Stockfish",
"main": "ffish.js",
"scripts": {
"url": "https://github.com/QueensGambit"
}
],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/ianfab/Fairy-Stockfish.git"
+ },
"keywords": ["wasm", "library", "chess-variants", "fairy-stockfish"],
"license": "GPL-3.0",
"homepage": "https://github.com/ianfab/Fairy-Stockfish/tree/master/tests/js#readme",
});
});
-describe('Constructor: no parameter ', function () {
+describe('Board()', function () {
it("it creates a chess board from the default position", () => {
const board = new ffish.Board();
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
});
});
-describe('Constructor: variant parameter ', function () {
+describe('Board(uciVariant) ', function () {
it("it creates a board object from a given UCI-variant", () => {
const board = new ffish.Board("chess");
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
});
});
-describe('Constructor: variant parameter with large board', function () {
+describe('Board(uciVariant) with large board', function () {
it("it creates a large-board object from a given UCI-variant", () => {
const board = new ffish.Board("xiangqi");
chai.expect(board.fen()).to.equal("rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1");
});
});
-describe('Constructor: variant parameter + fen ', function () {
+describe('Board(uciVariant, fen) ', function () {
it("it creates a board object for a given UCI-variant with a given FEN", () => {
const board = new ffish.Board("crazyhouse", "rnbqkb1r/pp3ppp/5p2/2pp4/8/5N2/PPPP1PPP/RNBQKB1R/Np w KQkq - 0 5");
chai.expect(board.fen()).to.equal("rnbqkb1r/pp3ppp/5p2/2pp4/8/5N2/PPPP1PPP/RNBQKB1R[Np] w KQkq - 0 5");
});
});
-describe('Constructor: variant parameter + fen + is960', function () {
+describe('Board(uciVariant, fen, is960)', function () {
it("it creates a board object for a given UCI-variant with a given FEN and is960 identifier", () => {
const board = new ffish.Board("chess", "rnknb1rq/pp2ppbp/3p2p1/2p5/4PP2/2N1N1P1/PPPP3P/R1K1BBRQ b KQkq - 1 5", true);
chai.expect(board.fen()).to.equal("rnknb1rq/pp2ppbp/3p2p1/2p5/4PP2/2N1N1P1/PPPP3P/R1K1BBRQ b GAga - 1 5");
});
});
-describe('board.push()', function () {
+describe('board.push(uciMove)', function () {
it("it pushes a move in uci notation to the board", () => {
let board = new ffish.Board();
board.push("e2e4");
});
});
-describe('board.setFen()', function () {
+describe('board.setFen(fen)', function () {
it("it sets a custom position via fen", () => {
let board = new ffish.Board();
board.setFen("r1bqkbnr/ppp2ppp/2np4/1B6/3NP3/8/PPP2PPP/RNBQK2R b KQkq - 0 5");
});
});
+describe('board.sanMove(ffish.Notation)', function () {
+ it("it converts an uci move into san using a given notation", () => {
+ const board = new ffish.Board();
+ chai.expect(board.sanMove("g1f3", ffish.Notation.DEFAULT)).to.equal("Nf3");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.SAN)).to.equal("Nf3");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.LAN)).to.equal("Ng1-f3");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.SHOGI_HOSKING)).to.equal("N36");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.SHOGI_HODGES)).to.equal("N-3f");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.SHOGI_HODGES_NUMBER)).to.equal("N-36");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.JANGGI)).to.equal("N87-66");
+ chai.expect(board.sanMove("g1f3", ffish.Notation.XIANGQI_WXF)).to.equal("N2+3");
+ board.delete();
+ });
+});
+
+describe('board.variationSan(uciMoves)', function () {
+ it("it converts a list of uci moves into san notation. The board will not changed by this method.", () => {
+ let board = new ffish.Board();
+ board.push("e2e4")
+ const sanMoves = board.variationSan("e7e5 g1f3 b8c6 f1c4");
+ chai.expect(sanMoves).to.equal("1...e5 2. Nf3 Nc6 3. Bc4");
+ board.delete();
+ });
+});
+
+describe('board.variationSan(uciMoves, notation)', function () {
+ it("it converts a list of uci moves into san notation given a notation format", () => {
+ let board = new ffish.Board();
+ board.push("e2e4")
+ const sanMoves = board.variationSan("e7e5 g1f3 b8c6 f1c4", ffish.Notation.LAN);
+ chai.expect(sanMoves).to.equal("1...e7-e5 2. Ng1-f3 Nb8-c6 3. Bf1-c4");
+ board.delete();
+ });
+});
+
+describe('board.variationSan(uciMoves, notation, moveNumbers)', function () {
+ it("it converts a list of uci moves into san notation given a notation format and optionally disabling move numbers", () => {
+ let board = new ffish.Board();
+ board.push("e2e4")
+ const sanMoves = board.variationSan("e7e5 g1f3 b8c6 f1c4", ffish.Notation.SAN, false);
+ chai.expect(sanMoves).to.equal("e5 Nf3 Nc6 Bc4");
+ board.delete();
+ });
+});
+
describe('board.turn()', function () {
it("it returns the side to move", () => {
let board = new ffish.Board();
});
});
+describe('board.fullmoveNumber()', function () {
+ it("it returns the move number starting with 1 and is increment after each move of the 2nd player", () => {
+ let board = new ffish.Board();
+ chai.expect(board.fullmoveNumber()).to.equal(1);
+ board.push("e2e4");
+ chai.expect(board.fullmoveNumber()).to.equal(1);
+ board.push("e7e5");
+ board.push("g1f3");
+ board.push("g8f6");
+ board.push("f3e5");
+ chai.expect(board.fullmoveNumber()).to.equal(3);
+ board.delete();
+ });
+});
+
describe('board.halfmoveClock()', function () {
it("it returns the halfmoveClock / 50-move-rule-counter", () => {
let board = new ffish.Board();
});
});
+describe('board.isCheck()', function () {
+ it("it checks if a player is in check", () => {
+ let board = new ffish.Board();
+ chai.expect(board.isCheck()).to.equal(false);
+ board.setFen("rnbqkb1r/pppp1Bpp/5n2/4p3/4P3/8/PPPP1PPP/RNBQK1NR b KQkq - 0 3");
+ chai.expect(board.isCheck()).to.equal(true);
+ board.setFen("r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4");
+ board.pushSan("Qxf7#");
+ chai.expect(board.isCheck()).to.equal(true);
+ board.delete();
+ });
+});
+
+describe('board.isBikjang()', function () {
+ it("it checks if a player is in bikjang (only relevant for janggi)", () => {
+ let board = new ffish.Board("janggi");
+ chai.expect(board.isBikjang()).to.equal(false);
+ board.setFen("rnba1abnr/4k4/1c5c1/p1p3p1p/9/9/P1P3P1P/1C5C1/4K4/RNBA1ABNR w - - 0 1");
+ chai.expect(board.isBikjang()).to.equal(true);
+ board.delete();
+ });
+});
+
describe('ffish.info()', function () {
it("it returns the version of the Fairy-Stockfish binary", () => {
chai.expect(ffish.info()).to.be.a('string');
});
});
+
+describe('ffish.setOption(name, value)', function () {
+ it("it sets a string uci option value pair", () => {
+ ffish.setOption("VariantPath", "variants.ini");
+ chai.expect(true).to.equal(true);
+ });
+});
+
+describe('ffish.setOptionInt(name, value)', function () {
+ it("it sets a int uci option value pair", () => {
+ ffish.setOptionInt("Threads", 4);
+ chai.expect(true).to.equal(true);
+ });
+});
+
+describe('ffish.setOptionBool(name, value)', function () {
+ it("it sets a boolean uci option value pair", () => {
+ ffish.setOptionBool("Ponder", true);
+ chai.expect(true).to.equal(true);
+ });
+});