multistockfish 0.6.1
multistockfish: ^0.6.1 copied to clipboard
Flutter plugin bundling Stockfish 19 and Fairy-Stockfish chess engines for Android and iOS, to run chess and chess variant analysis in mobile apps.
0.6.1 #
- Update package's description.
0.6.0 #
Breaking changes — Stockfish 19:
- Update to Stockfish 19 for both non-variant flavours.
StockfishFlavor.sf16is removed and replaced byStockfishFlavor.light: Stockfish 19 with a ~1MB embedded net, in place of Stockfish 16 with a 38MB one. It is the new default forStockfish.create(). Themultistockfish_sf16package is retired in favour ofmultistockfish_light.bigNetPathandsmallNetPathare replaced by a singlennuePath, andStockfish.latestBigNNUE/latestSmallNNUEbyStockfish.latestNNUE. Stockfish 19 evaluates with one network, soStockfishFlavor.latestNoNNUEnow needs one file instead of two.
Breaking changes — per-flavour engine handles:
An engine is now a handle you create and dispose, rather than a process-wide
singleton you start and quit. The handle is the flavour: at most one engine
per StockfishFlavor can be live at a time, and engines of different flavours
are independent and can run side by side — each with its own stdin, stdout,
state and diagnostics. Running an NNUE engine for analysis while
Fairy-Stockfish plays an opponent no longer means restarting one to get the
other.
- Add
Stockfish.create(), which starts an engine of one flavour and completes when it is ready for commands, anddispose(), which quits it and frees the flavour's slot.create()throws aStateErrorwhile another engine of the same flavour holds the slot. - An engine that ends — disposed, quit over
stdin, or crashed — releases its flavour's slot without waiting to be disposed, because the native library is provably free once itsmain()has returned. - A handle is single use.
stateends as the newStockfishState.disposed— afterdispose(), or after the engine exits cleanly on its own, as it does when sentquitoverstdin— or asStockfishState.errorif it died badly. Neither is recoverable on that handle.stdoutcloses when the engine ends, so it no longer persists across a restart — the replacement engine has its own. - Add an
onStdoutparameter tocreate().create()only completes once the engine is ready, so a listener attached tostdoutafterwards has already missed the banner and the UCI handshake;onStdoutis attached before the engine is spawned and receives every line for its whole life. dispose()gives up on an engine that will not exit within 5 seconds instead of waiting for it forever, and frees the slot regardless.create()now fails as soon as the engine exits during startup — a start the native library refused is reported in milliseconds with the exit code, rather than as a timeout five seconds later.Stockfish.instance,start()andquit()still work but are deprecated and will be removed in the next release. The singleton competes for the same per-flavour slots ascreate(), so the two APIs can be mixed during a migration without ending up with two engines of one flavour.
Migration:
// Before
final stockfish = Stockfish.instance;
await stockfish.start(flavor: StockfishFlavor.variant, variant: 'atomic');
stockfish.stdin = 'go movetime 1000';
await stockfish.quit();
// After
final stockfish = await Stockfish.create(
flavor: StockfishFlavor.variant,
variant: 'atomic',
);
stockfish.stdin = 'go movetime 1000';
await stockfish.dispose();
- Add Swift Package Manager support for iOS.
Engine lifecycle fixes (in the native packages, via the bumped constraints below):
- The engine no longer takes the process's
stdinandstdoutover. Each native library now reads and writes streams of its own, bound directly to its pipe, so anything the app writes tostdoutstill goes where it should while an engine is running — and two flavours can be resident at once, which per-flavour engine handles will build on. - Restarting after an engine failed to quit no longer corrupts memory. Nothing
previously stopped a second engine from running over the first one's
process-global state while it was still tearing its thread pool down; that is
now refused, and
startfails with an error saying so. - Sending a command can no longer freeze the app. The write to the engine was blocking, so once the engine stopped reading its input and the pipe filled, the calling isolate — usually the platform isolate — blocked forever. It now gives up and reports the failure instead.
- Starting the engine no longer leaks two file descriptors each time.
- A restarted engine no longer sees output or commands left over from its predecessor.
- The stdout reader no longer spins on a closed pipe.
Diagnosing an engine that will not start or will not quit:
- Add
Stockfish.diagnostics, reporting the native engine's lifecycle phase, the step within it, how long it has been there, and the last native error. Attach it to reports of an engine that would not start or would not quit. - Report where a start stalled: the
TimeoutExceptionthrown bystartnow names the phase and step the engine was in when it gave up. - Log a failed write to the engine at
SEVEREwith the reason and diagnostics, rather than discarding the result. quitno longer waits forever when the engine cannot be reached: if thequitcommand itself cannot be delivered, the engine is declared failed instead of leaving the returned future pending.- Log the meaning of a non-zero engine exit code and of an
initfailure. - A write that corrupts the command stream, or that breaks the channel to the
engine, now moves
statetoerroras well as logging. Later commands throw instead of piling onto a session the engine can no longer read correctly; a write that simply was not delivered leaves the engine usable.
Requires multistockfish_chess ^0.6.0, multistockfish_light ^0.1.0 and
multistockfish_variant ^0.4.0.
0.5.0 #
Breaking changes:
Stockfish.startnow sends the "uci" command to the engine and waits for it to respond with "uciok". When using the library, do not send "uci" yourself anymore, as that would reset UCI options.
Migration:
// Before
await Stockfish.instance.start(flavor: StockfishFlavor.variant, variant: 'atomic');
// stockfish is ready, enable uci protocol.
Stockfish.instance.stdin = 'uci';
// After
await Stockfish.instance.start(flavor: StockfishFlavor.variant, variant: 'atomic');
// "uci" command has already been sent to `stdin` internally, stockfish is ready and in uci mode.
0.4.0 #
- Update latest Stockfish to version 18.
Breaking changes:
Stockfishis now a singleton. UseStockfish.instance.- Configuration (
flavor,variant,bigNetPath,smallNetPath) moved from the constructor tostart(). - Removed
StockfishState.disposed. After callingquit(), the state returns toinitialand the engine can be restarted. start()throws aStateErrorif the engine is already running. Callquit()first.- The
stdoutstream now persists across restarts - listeners don't need to re-subscribe.
Migration:
// Before
final stockfish = Stockfish(flavor: StockfishFlavor.variant, variant: 'atomic');
// listen to stockfish state and wait for it to be ready
stockfish.stdin = 'uci';
// After
await Stockfish.instance.start(flavor: StockfishFlavor.variant, variant: 'atomic');
// stockfish is ready
Stockfish.instance.stdin = 'uci';
0.3.0 #
- Add Stockfish 16 (embedded NNUE).
- Default engine is now Stockfish 16.
0.2.1 #
- Fix wrong NNUE file for Stockfish 17.1
0.2.0 #
- Use last Stockfish as well on armv7 devices.
- Do not embed NNUE files in the app bundle.
0.1.0 #
Initial release