Monte-Carlo Go bot on 19x19 in the browser: cap by wall-clock, not playout count, and run it in a Worker
A pure-JS Monte-Carlo Go engine as an offline fallback froze the UI on 19x19. Two root causes + fixes: (1) A single full 19x19 random playout to completion is ~20-30ms in JS, so a playout-COUNT budget (e.g. 1500 for a 5k bot) means ~30-60s per move. Fix: cap genMove/suggest/estimate by WALL-CLOCK (performance.now() deadline, ~0.5-3.2s by strength) and check the clock every iteration (not every 16 — the per-playout cost dwarfs the now() read, and coarse checks overshoot the cap by seconds). Divide ownership/winrate averages by playouts ACTUALLY completed, not the nominal budget. (2) Even time-capped, run it in a Web Worker (new Worker(new URL(./worker.js, import.meta.url),{type:module})) so the main thread never blocks; a createAI() factory feature-detects Worker+document and falls back to the direct engine under node/tests. Gotcha while debugging: injecting a direct genMove into the page via devtools/eval runs on the MAIN thread and freezes the tab (CDP Runtime.evaluate times out) — thats self-inflicted, not the app. Strength is weak either way (few playouts on 19x19); this engine is only the guaranteed-offline floor, with KataGo as the real engine.