cd Fairy-Stockfish/src
```
```bash
-emcc -O3 --bind ffishjs.cpp \
+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 \
-o ../tests/js/ffish.js
```
+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:
const ffish = require('ffish');
```
-Create a new variant board from its default starting position:
+Create a new variant board from its default starting position.
+The even `onRuntimeInitialized` ensures that the wasm file was properly loaded.
```javascript
-// create new board with starting position
-let board = new ffish.Board("chess");
+ffish['onRuntimeInitialized'] = () => {
+ let board = new ffish.Board("chess");
+}
```
Set a custom fen position:
board.setFen("rnb1kbnr/ppp1pppp/8/3q4/8/8/PPPP1PPP/RNBQKBNR w KQkq - 0 3");
```
-Initialize a board with a custom FEN:
+Alternatively, you can initialize a board with a custom FEN directly:
```javascript
-board = new ffish.Board("crazyhouse", "rnb1kb1r/ppp2ppp/4pn2/8/3P4/2N2Q2/PPP2PPP/R1B1KB1R/QPnp b KQkq - 0 6");
-// create a new board object for a given fen
-let board2 = new ffish.Board("crazyhouse", );
+let board2 = new ffish.Board("crazyhouse", "rnb1kb1r/ppp2ppp/4pn2/8/3P4/2N2Q2/PPP2PPP/R1B1KB1R/QPnp b KQkq - 0 6");
```
Add a new move:
let legalMovesSan = board.legalMovesSan().split(" ");
for (var i = 0; i < legalMovesSan.length; i++) {
- console.log(`${i}: ${legalMoves[i]}, ${legalMoves
+ console.log(`${i}: ${legalMoves[i]}, ${legalMoves})
+}
```
-For examples for every function see [test.js](./test.js).
+For examples for every function see [test.js](https://github.com/ianfab/Fairy-Stockfish/blob/master/tests/js/test.js).
+
+Unfortunately, it is impossible for Emscripten to call the destructors on C++ object.
+Therefore, you need to call `.delete()` to free the heap memory of an object.
+```javascript
+board.delete();
+```
## Instructions to run the tests
```bash
cd Fairy-Stockfish/src
```
```bash
-emcc -O3 --bind \
+emcc -O3 -DLARGEBOARDS --bind \
+-s TOTAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 \
+-s WASM_MEM_MAX=2147483648 -DLARGEBOARDS -DPRECOMPUTED_MAGICS \
-s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0 \
ffishjs.cpp \
benchmark.cpp \
const board = new ffish.Board();
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
chai.expect(board.is960()).to.equal(false);
+ board.delete();
});
});
const board = new ffish.Board("chess");
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
chai.expect(board.is960()).to.equal(false);
+ board.delete();
+ });
+});
+
+describe('Constructor: variant parameter 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");
+ chai.expect(board.is960()).to.equal(false);
+ board.delete();
});
});
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");
chai.expect(board.is960()).to.equal(false);
+ board.delete();
});
});
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");
chai.expect(board.is960()).to.equal(true);
+ board.delete();
});
});
'Q@g3 Q@h3 Q@a4 Q@b4 Q@c4 Q@d4 Q@f4 Q@g4 Q@h4 Q@a5 Q@b5 Q@d5 Q@f5 Q@g5 Q@h5 Q@a6 Q@b6 Q@d6 Q@e6 Q@f6 Q@g6' +
' Q@h6 Q@e7 Q@b8 Q@d8 Q@e8 Q@f8 e1d1 e1f1 e1e2';
chai.expect(board.legalMoves()).to.equal(expectedMoves);
+ board.delete();
});
});
' Q@d4 Q@f4+ Q@g4 Q@h4 Q@a5 Q@b5 Q@d5+ Q@f5+ Q@g5 Q@h5+ Q@a6 Q@b6 Q@d6 Q@e6+ Q@f6+ Q@g6+ Q@h6 Q@e7+ Q@b8' +
' Q@d8 Q@e8+ Q@f8+ Kd1 Kf1 Ke2';
chai.expect(board.legalMovesSan()).to.equal(expectedMoves);
+ board.delete();
});
});
it("it returns all legal moves in uci notation as a concatenated string", () => {
const board = new ffish.Board("crazyhouse", "r1b3nr/pppp1kpp/2n5/2b1p3/4P3/2N5/PPPP1PPP/R1B1K1NR/QPbq w KQ - 0 7");
chai.expect(board.numberLegalMoves()).to.equal(90);
+ board.delete();
});
});
board.push("e7e5");
board.push("g1f3");
chai.expect(board.fen()).to.equal("rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2");
+ board.delete();
});
});
board.pushSan("e5");
board.pushSan("Nf3");
chai.expect(board.fen()).to.equal("rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2");
+ board.delete();
});
});
board.push("f1b5");
board.pop();
board.pop();
-
chai.expect(board.fen()).to.equal("rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2");
+ board.delete();
});
});
board.pushSan("Nf3");
board.reset();
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
+ board.delete();
});
});
chai.expect(board.is960()).to.equal(false);
const board2 = new ffish.Board("chess", "rnknb1rq/pp2ppbp/3p2p1/2p5/4PP2/2N1N1P1/PPPP3P/R1K1BBRQ b KQkq - 1 5", true);
chai.expect(board2.is960()).to.equal(true);
+ board.delete();
});
});
it("it returns the current position in fen format", () => {
let board = new ffish.Board();
chai.expect(board.fen()).to.equal("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
+ board.delete();
});
});
let board = new ffish.Board();
board.setFen("r1bqkbnr/ppp2ppp/2np4/1B6/3NP3/8/PPP2PPP/RNBQK2R b KQkq - 0 5");
chai.expect(board.fen()).to.equal("r1bqkbnr/ppp2ppp/2np4/1B6/3NP3/8/PPP2PPP/RNBQK2R b KQkq - 0 5");
+ board.delete();
});
});
const board = new ffish.Board();
const san = board.sanMove("g1f3");
chai.expect(san).to.equal("Nf3");
+ board.delete();
});
});
chai.expect(board.turn()).to.equal(true);
board.push("e2e4");
chai.expect(board.turn()).to.equal(false);
+ board.delete();
});
});
chai.expect(board.halfmoveClock()).to.equal(2);
board.push("f3e5");
chai.expect(board.halfmoveClock()).to.equal(0);
+ board.delete();
});
});
board.push("g8f6");
board.push("f3e5");
chai.expect(board.gamePly()).to.equal(5);
+ board.delete();
});
});
board.setFen("r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4");
board.pushSan("Qxf7#");
chai.expect(board.isGameOver()).to.equal(true);
+ board.delete();
});
});