Skip to content

Releases: shielune/YaneuraOu

YaneuraOu 9.60.0

Choose a tag to compare

@github-actions github-actions released this 01 Aug 00:42

YaneuraOu shogi engine — WebAssembly packages and native Windows binaries.

What's new in this release: the engine base moves to YaneuraOu V9.60 (upstream), native Windows
binaries are published alongside the WASM packages for the first time
, and
the set is trimmed to the variants that are actually useful for play and
analysis — NNUE (KP256 / HalfKP128 / HalfKP256 / HalfKP768), the SFNN NAGISA_V3
network, and the DfPn mate solver. That means fourteen WASM packages across
browser, Node.js and Cloudflare Workers (where the eval fits), plus six Windows
tarballs covering every 64-bit CPU target. The Material / Mobility / HumanLike
variants are no longer published; their sources remain in the repository. The
loader API is unchanged from 8.50.0 apart from the new progressBin option
described below.

  • USI_Hash now defaults to 16 MB on WASM builds (native stays at 1024 MB).
    The transposition table is sized from this default while the Threads option
    is registered — before any setoption can reach the engine — and 1024 MB
    exceeds MAXIMUM_MEMORY for every WASM package, so the engine called
    exit(EXIT_FAILURE) during startup. Builds published between the V9.60 merge
    and this fix could not start at all
    ; the builds themselves succeeded, so CI
    stayed green. If you want a larger table — in particular for the DfPn mate-*
    packages, which search deeper the more hash they get — raise it explicitly with
    setoption name USI_Hash value 256.

  • New: HalfKP_128x2_32_32 (pthread-halfkp128, node-halfkp128). Half the
    first layer of the standard HalfKP256 network, so the eval is ~31 MB instead of
    ~62 MB. There is no cfworkers variant — loading the eval overruns the 128 MB
    Workers heap.

  • New: the NAGISA_V3 network is supported (pthread-halfka1024, node-halfka1024).
    This is an SFNN HalfKA_hm2 1024x2-15-64 net with 9 layer stacks. Unlike every
    other supported network it keeps its layer-stack selection coefficients in a
    separate progress.bin rather than inside nn.bin, so both files must be
    supplied: the loaders take a new progressBin option alongside evalBin, and
    the engine reads the coefficients through the LS_PROGRESS_COEFF USI option
    (defaulting to progress.bin under EvalDir).

  • LS_BUCKET_MODE selects the layer-stack bucket rule, defaulting to
    progress8kpabs to match NAGISA_V3's own default — progress alone picks
    buckets 0–7 and the 9th layer stack is never used. Set it to progress8ek to
    route mutual-entering-king positions to that 9th stack instead. The two rules
    differ only in entering-king positions, and both produce identical node counts
    and moves on native and WASM.

    This distinction matters because both rules pass the eval file's hash check.
    Picking the wrong one loads without any error or warning and quietly selects
    different weights, so a mismatch is only visible by comparing search output.

  • FV_SCALE now defaults to 28 on SFNN builds (16 elsewhere). Together with
    the two options above this matches the eval_options.txt that NAGISA_V3 ships
    next to its weights, so the network runs correctly out of the box. There is no
    halfka1024-cfworkers variant: the 75 MB eval does not fit the 128 MB Workers heap.

  • Heap ceiling raised to 4 GB on every pthread and Node package (the wasm32
    maximum), up from 1–2 GB. MAXIMUM_MEMORY is an address-space reservation, not
    an upfront allocation, so this costs nothing until the memory is actually used.

  • USI_Hash's ceiling is now derived from the heap rather than hard-coded to
    2048 MB on every WASM build. It is half the heap ceiling: 2048 MB on the
    pthread/Node packages, 64 MB on the cfworkers ones. Previously a cfworkers
    build would happily accept USI_Hash 2048 and then die allocating it; now the
    option range only offers values the build can actually satisfy. Native builds
    are unaffected.

  • Fixed: NNUE evaluation was silently wrong on plain-NEON builds — the
    published macOS (APPLEM1) and Android (arm64-v8a) binaries. The
    sparse-input layer loaded its weights in the scrambled layout whenever
    USE_NEON >= 8, but only reads that layout back when USE_NEON_DOTPROD is
    set; without dotprod it falls back to the dense kernel, so the load and the
    compute disagreed. The plain-NEON kernels also treated the uint8 input as
    signed, wrapping any value of 128 or above negative. Neither failed loudly:
    the engine started, searched, and returned plausible-looking scores.
    On aarch64 at depth 16 the NEON build reported 12,017,078 nodes / cp 87 where
    scalar and WASM both give 743,902 / cp 94. All four networks now agree node
    for node across scalar, NEON and WASM. WASM builds were never affected.

  • WebAssembly support restored on the V9.6x engine model: the NNUE weights stay
    in the dense layout (upstream's scrambled/sparse layout is AVX-only), and the
    explicit affine layers stay dense under WASM too.

  • Edge variants build with pthreads fully off rather than
    pthread-capable-but-single-threaded.

  • Fork engine options carried over: FullTimeMode (stop shrinking the think time
    on stable positions), hidden USI options settable only via setoption, and a
    tolerant NNUE header-version check. See docs/fork_engine_options.md.

  • Node variants remain pinned to emscripten 3.1.43 — the only toolchain
    verified to drive a pthread-backed YaneuraOu cleanly under Node (newer
    emscriptens stall, see docs/wasm_client_usage.md for the matrix). The rest
    build on 5.0.5.


Each .tar.gz contains the package's package.json (version bumped to this release), README.md, SPEC.md, the TypeScript loader (dist/index.js, dist/index.d.ts), and the engine bundle (dist/yaneuraou.js, dist/yaneuraou.wasm, .wasm.br). Node variants additionally ship dist/yaneuraou.worker.js (the emscripten 3.1.43 classic pthread worker) and dist/worker_shim.{js,d.ts} (the worker_threads-side glue the loader uses to bridge .worker.js into a fake web-worker scope).

Packages

Browser / Cloudflare Workers

Package Engine Eval data Threading Initial / Max memory
@ultemica/yaneuraou-wasm-kp256-cfworkers NNUE KP256 external (~873 KB) single-thread 64 MB / 128 MB
@ultemica/yaneuraou-wasm-mate-cfworkers Mate (DfPn) none single-thread 64 MB / 128 MB
@ultemica/yaneuraou-wasm-pthread-kp256 NNUE KP256 external (~873 KB) pthread 128 MB / 4 GB
@ultemica/yaneuraou-wasm-mate-pthread Mate (DfPn) none pthread 128 MB / 4 GB
@ultemica/yaneuraou-wasm-pthread-halfkp128 NNUE HalfKP_128x2_32_32 external (~31 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-pthread-halfkp256 NNUE HalfKP_256x2_32_32 external (~62 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-pthread-halfkp768 NNUE HalfKP_768x2_16_64 external (~184 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-pthread-halfka1024 SFNN HalfKA_hm2 1024x2-15-64 external (~75 MB + progress.bin) pthread 256 MB / 4 GB

The pthread-* packages run in the browser and need SharedArrayBuffer, so the page must be served cross-origin isolated (Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp). Where you cannot set those headers, use a *-cfworkers package.

Cloudflare Workers cannot host pthread builds — use the cfworkers variant there. HalfKP cfworkers variant does not exist (eval exceeds Workers memory budget).

Node.js variants

Six packages built with EM_ENVIRONMENT=node, EM_PTHREAD=1, and EM_EXPORTED_RUNTIME_METHODS=['FS','ccall','callMain']. Pinned to emscripten 3.1.43 — the only toolchain currently verified to drive a multi-threaded YaneuraOu correctly under Node (3.1.44–3.1.73 stall on ESM workers, 3.1.74+ stall on INCOMING_MODULE_JS_API; both unresolved). See docs/wasm_client_usage.md for the full compatibility matrix.

Package Engine Eval data Threading Initial / Max memory
@ultemica/yaneuraou-wasm-node-kp256 NNUE KP256 external (~873 KB) pthread 128 MB / 4 GB
@ultemica/yaneuraou-wasm-node-mate Mate (DfPn) none pthread 128 MB / 4 GB
@ultemica/yaneuraou-wasm-node-halfkp128 NNUE HalfKP_128x2_32_32 external (~31 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-node-halfkp256 NNUE HalfKP_256x2_32_32 external (~62 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-node-halfkp768 NNUE HalfKP_768x2_16_64 external (~184 MB) pthread 256 MB / 4 GB
@ultemica/yaneuraou-wasm-node-halfka1024 SFNN HalfKA_hm2 1024x2-15-64 external (~75 MB + progress.bin) pthread 256 MB / 4 GB

Quickstart (Node 18+):

import fs from "node:fs/promises";
import { createRequire } from "node:module";
import { createEngine } from "@ultemica/yaneuraou-wasm-node-kp256";
import YaneuraOuFactory from "@ultemica/yaneuraou-wasm-node-kp256/engine";

const require = createRequire(import.meta.url);
const wasmPath   = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/wasm");
const enginePath = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/engine");
const wasmBinary = await fs.readFile(wasmPath);
const evalBin    = await fs.readFile("./eval/nn.bin"); // suishopetite for KP256

const engine = await createEngine({
  factory: YaneuraOuFactory,
  enginePath,
  wasmBinary,
  evalBin,
  threads: 4,
  usiHash: 64,
});

const result = await engine.eval({
  sfen: "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1",
  byoyomi: 2_000,
});
console.log(result.bestmove, result.score); // -> "7g7f", { kind: "cp", value: ... }
engine.dispose();

Requires Node.js 18 or later. Browsers cannot load these binaries (built with EM_ENVIRONMENT=node, not web,worker); use the pthread-* packages there. Cloudflare Workers / V8 Isolate environments can't host pthread builds at all; ...

Read more

v8.50.0

Choose a tag to compare

@tkgstrator tkgstrator released this 01 Aug 00:07

YaneuraOu shogi engine — WebAssembly builds.

What's new in this release: Node.js-targeted packages (@ultemica/yaneuraou-wasm-node-*) join the
browser and Cloudflare Workers builds, so the engine can be driven from a plain
Node process with no browser involved.

  • kp256 / mate / halfkp256 / halfkp768, all multi-threaded via
    node:worker_threads.
  • Built with emscripten 3.1.43 — the only toolchain currently verified to
    drive a pthread-backed YaneuraOu cleanly under Node (newer emscriptens stall,
    see docs/wasm_client_usage.md for the matrix).
  • Drop-in createEngine() loader: zero boilerplate on the consumer side. The
    package wraps the node:worker_threads plumbing, Worker polyfill,
    web-globals shim, and noInitialRun + callMain bootstrap internally.
  • Verified on Node 26 with KP256 + suishopetite — depth 24 in ~3.4 s at
    threads=1 (~0.84 M nps), ~6.8 s at threads=4 (~3.32 M nps, roughly linear).

Note (added later): this release originally shipped twenty packages,
including Material / Mobility engines and HumanLike (-hlsl) variants of each
engine. Those assets have since been removed to keep the published set to the
ten variants that are useful for play and analysis; their sources remain in the
repository. The engine binaries for the remaining ten are unchanged from the
original 8.50.0 publish.


Each archive contains the package's package.json (version bumped to this release), README.md, SPEC.md, the TypeScript loader (dist/index.js, dist/index.d.ts), and the engine bundle (dist/yaneuraou.js, dist/yaneuraou.wasm, .wasm.br). Node variants additionally ship dist/yaneuraou.worker.js (the emscripten 3.1.43 classic pthread worker) and dist/worker_shim.{js,d.ts} (the worker_threads-side glue the loader uses to bridge .worker.js into a fake web-worker scope).

Packages

Browser / Cloudflare Workers

Package Engine Eval data Threading Initial / Max memory Target
@ultemica/yaneuraou-wasm-kp256-cfworkers NNUE KP256 (Suishopetite) external (~873 KB) single-thread 64 MB / 128 MB Cloudflare Workers, edge runtimes
@ultemica/yaneuraou-wasm-mate-cfworkers Mate (DfPn) none single-thread 64 MB / 128 MB Cloudflare Workers, edge runtimes
@ultemica/yaneuraou-wasm-pthread-kp256 NNUE KP256 (Suishopetite) external (~873 KB) pthread 128 MB / 1 GB Browser (COOP/COEP required)
@ultemica/yaneuraou-wasm-mate-pthread Mate (DfPn) none pthread 128 MB / 1 GB Browser (COOP/COEP required)
@ultemica/yaneuraou-wasm-pthread-halfkp256 NNUE HalfKP_256x2_32_32 (Suisho5) external (~62 MB) pthread 256 MB / 2 GB Browser (COOP/COEP required)
@ultemica/yaneuraou-wasm-pthread-halfkp768 NNUE HalfKP_768x2_16_64 (AobaNNUE) external (~184 MB) pthread 256 MB / 2 GB Browser (COOP/COEP required)

Cloudflare Workers cannot host pthread builds — use the cfworkers variant there. HalfKP cfworkers variant does not exist (eval exceeds Workers memory budget).

Node.js variants

Four packages built with EM_ENVIRONMENT=node, EM_PTHREAD=1, and EM_EXPORTED_RUNTIME_METHODS=['FS','ccall','callMain']. Pinned to emscripten 3.1.43 — the only toolchain currently verified to drive a multi-threaded YaneuraOu correctly under Node (3.1.44–3.1.73 stall on ESM workers, 3.1.74+ stall on INCOMING_MODULE_JS_API; both unresolved). See docs/wasm_client_usage.md for the full compatibility matrix.

Package Engine Eval data Threading Initial / Max memory
@ultemica/yaneuraou-wasm-node-kp256 NNUE KP256 (Suishopetite) external (~873 KB) pthread 128 MB / 1 GB
@ultemica/yaneuraou-wasm-node-mate Mate (DfPn) none pthread 128 MB / 1 GB
@ultemica/yaneuraou-wasm-node-halfkp256 NNUE HalfKP_256x2_32_32 (Suisho5) external (~62 MB) pthread 256 MB / 2 GB
@ultemica/yaneuraou-wasm-node-halfkp768 NNUE HalfKP_768x2_16_64 (AobaNNUE) external (~184 MB) pthread 256 MB / 2 GB

Quickstart (Node 18+):

import fs from "node:fs/promises";
import { createRequire } from "node:module";
import { createEngine } from "@ultemica/yaneuraou-wasm-node-kp256";
import YaneuraOuFactory from "@ultemica/yaneuraou-wasm-node-kp256/engine";

const require = createRequire(import.meta.url);
const wasmPath   = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/wasm");
const enginePath = require.resolve("@ultemica/yaneuraou-wasm-node-kp256/engine");
const wasmBinary = await fs.readFile(wasmPath);
const evalBin    = await fs.readFile("./eval/nn.bin"); // suishopetite for KP256

const engine = await createEngine({
  factory: YaneuraOuFactory,
  enginePath,
  wasmBinary,
  evalBin,
  threads: 4,
  usiHash: 64,
});

const result = await engine.eval({
  sfen: "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1",
  byoyomi: 2_000,
});
console.log(result.bestmove, result.score); // -> "7g7f", { kind: "cp", value: ... }
engine.dispose();

Requires Node.js 18 or later. Browsers cannot load these binaries (built with EM_ENVIRONMENT=node, not web,worker); use the pthread-* packages there. Cloudflare Workers / V8 Isolate environments can't host pthread builds at all; use the *-cfworkers packages there.

Performance — how close to native?

WASM is not the slow option. Measured on one machine with the same eval and the
same search parameters, WASM reaches about 92% of a native SIMD build.

Build nps vs native NEON
native clang-14 (NEON) 764k 102%
native gcc (NEON) 748k 100%
wasm32 pthread 691k 92%
wasm32 (no SIMD) 585k 78%
native clang-14 (scalar) 320k 43%
native gcc (scalar) 203k 27%

Threads=1 / go nodes 1000000 / KP256 + suishopetite / median of 3 runs.
Absolute numbers are machine-dependent — only the ratios carry over.

  • WASM SIMD is doing real work. Turning it off drops 691k to 585k (-15%).
    WASM still beats both native scalar builds by more than 2x.
  • Threads scale. On Node, 1 to 4 threads goes 686k to 2,916k (4.25x) —
    superlinear thanks to the shared transposition table.
  • Browser and Node are within noise. 99% at 1 thread, 92% at 4 threads;
    SharedArrayBuffer synchronisation costs the browser a little.

Search results are bit-identical across every WASM variant (32/64-bit,
SIMD on/off, browser/Node/edge) down to the node count, so switching runtimes
does not change what the engine plays.

Full conditions and raw data: docs/reports/2026-07-28_wasm_v96x_performance.md.

Required: NNUE eval file (NNUE builds only)

WASM bundle には評価関数を内蔵していないので、別途 nn.bin を取得して FS.writeFile で MEMFS に書いて EvalDir USI option で読み込ませる。

Eval Engine Size URL
suisho5 nn.bin HalfKP_256x2_32_32 ~62 MB https://github.com/mizar/YaneuraOu/releases/download/resource/suisho5_20211123.halfkp.nnue.cpp.gz
AobaNNUE nn.bin HalfKP_768x2_16_64 ~184 MB https://github.com/yssaya/AobaNNUE/releases
suishopetite nn.bin KP256 ~873 KB https://github.com/mizar/YaneuraOu/releases/download/resource/suishopetite_20211123.k_p.nnue.cpp.gz

suisho5 / suishopetite は embedded C++ array 形式の .cpp.gzscript/eval_bin_to_cpp_literal.py の逆変換で .bin に戻す。AobaNNUE は素の nn.bin がそのまま配布されている。

KP256 / HalfKP_256x2_32_32 / HalfKP_768x2_16_64 の eval はそれぞれ互換性なし。Mate engine は eval 不要。HalfKP eval (62 MB) は cfworkers の 128 MB heap で OOM になるため pthread variant でのみ使える。

Optional: opening book

BookDir / BookFile USI option で読み込ませる。

Book 局面数 Size URL
100T-shock ~40,000 4.7 MB https://github.com/yaneurao/YaneuraOu/releases/download/BOOK-100T-Shock/100T-shock-book.zip
700T-shock ~400,000 32 MB https://github.com/yaneurao/YaneuraOu/releases/download/BOOK-700T-Shock/700T-shock-book.zip
新ペタショック 233万 ~2,330,000 76 MB (.7z) https://github.com/yaneurao/YaneuraOu/releases/download/new_petabook233/new_petabook_20250505c.7z

700T-shock (32 MB) は cfworkers の 128 MB heap だと OOM。cfworkers で book を使う場合は 100T-shock まで。petabook は pthread variant でも heap 圧迫するので注意。