TypeScript engine
- Role
- reference rulebook
- Board
- 49-cell array, copied per step
- Latent mode
- yes
- Parity
- exact on 256 seeds, 6,852 moves
These are the various implementations of a Drop7 game that are used in the research.
An *engine* is the code that plays the game. The TypeScript engine is generally used for scripting and low-throughput scenarios, while the Rust engineenables high-performance computing and massive parallelism.
The solver that runs in a visitor's browser: the reference search with a faster move generator, an allocation-free leaf and a packed transposition table, kept value-identical to the reference.
A second Rust crate for the Classic ruleset, written for the mobile game-collection API; nothing consumes it yet.
Not a game engine: the work that made PyTorch run on the workstation's GPU and measured training throughput; a batched GPU simulator is a proposal only.
Here is a full table that combines all the records about the various engine measurements, so they can easily be compared side by side.
| Quantity | TypeScript | Browser | C++ | C++ fast | Scenario | Rust | Rust Classic | Source |
|---|---|---|---|---|---|---|---|---|
| Board bytes | 49 cells; bytes not recordedengine.ts | not recorded | 49finding-13-fast-engine | 49 + scanfast-engine.hpp | 49 + 49 latentscenario.hpp | 28RS-…e89ea128 | not recorded | |
| Rules parity partner and scale | C++: 256 seeds / 6,852 moves; Rust: 256 gamesreproducibility, RS-…e89ea128 | TypeScript: test-gated, counts not retainedfast-search.test.ts | TypeScript: 256 seeds / 6,852 moves; scenario: 218,470 moves; C++ fast: 438,020 moves; Rust: 512 center + 256 search-policy gamesreproducibility, finding-02-scenario-benchmark, finding-13-fast-engine, RS-…e89ea128 | C++: 438,020 moves; whole-game 704 comparisonsfinding-13-fast-engine, finding-15-depth5-exact-estimator | C++: 218,470 movesfinding-02-scenario-benchmark | C++, C++ fast, TypeScript: 36,427 moves / 40,286 wavesRS-…e89ea128 | TypeScript Classic: one shared transition; 4 cargo testsclassic-engine.test.ts | |
| Leaf parity | not applicable | bit-identical vs evaluateHeuristic, all profilesfast-search.test.ts | not applicable | 225,183 states bit-exactfinding-13-fast-engine | not applicable | 150,854 statesRS-…e89ea128 | not applicable | web/lib/play/fast-search.test.tsdocs/exploratory/finding-13-fast-engine.mdRS-20260824T075451Z-e89ea128 |
| Search parity | not applicable | depth 2/3/4 exact incl. evictionfast-search.test.ts | not applicable | 306 moves, 9 configsfinding-13-fast-engine | 428 solver comparisons vs naivefinding-02-scenario-benchmark | 105 d4s7 + 10 d5s7 rootsRS-…e89ea128 | not applicable | web/lib/play/fast-search.test.tsdocs/exploratory/finding-13-fast-engine.mddocs/exploratory/finding-02-scenario-benchmark.mdRS-20260824T075451Z-e89ea128 |
| Single-core moves/s | 649,471 | not recorded | 6,799,180 | 6,511,760 | not recorded | 12,838,933 | not recorded | |
| Leaf ns/eval | not recorded | not recorded | 970.3 at load 14.6finding-13-fast-engine | 278.8 at load 14.6; 187.5finding-13-fast-engine, RS-…e89ea128 | not applicable | 155.6RS-…e89ea128 | not applicable | |
| d4s7 ms/decision | not recorded | not recorded | 3,247.8; 2,903.9 at load 26.9RS-…e89ea128, finding-13-fast-engine | 1,071.5; 910.9RS-…e89ea128, finding-13-fast-engine | not applicable | 907.6 with 64k table; 1,633.4 no tableRS-…e89ea128 | not applicable | |
| d5s7 ms/decision | not recorded | not recorded | 23,992.6; 30,340.2RS-…e89ea128, finding-13-fast-engine | 7,817.3; 9,379.2RS-…e89ea128, finding-13-fast-engine | not applicable | 7,787.9 / 7,047.1 / 6,748.4 at 256k / 1M / 4M; 63,325.4 no tableRS-…e89ea128 | not applicable | |
| Speedup vs its own reference | not applicable | not recorded | 1.00 (the reference)finding-13-fast-engine | 3.08x d4s5 decision; 2.88x to 3.23x games and probes; memo 1.581x / 1.634x indicative; M6 5.56x play dutyfinding-13-fast-engine, RS-…bd1697c8, RS-…8f3e9b4f | table 7.6x nodes / 4.9x wallfinding-02-scenario-benchmark | 1.97x vs C++ fast engine, 19.8x vs TypeScript; frontier 1.2612x d4s7, 1.1352x d5s7 on arm64 12 CPUsRS-…e89ea128, RS-…1b3ed9a5 | not recorded | |
| Table memory | 40,000 entries; bytes not recordedsolver.ts | not recorded | ~15.4 MB / ~51 MB at 60k / 200k, estimatedfinding-13-fast-engine | 4,648,576 B at 60k; 16,194,304 B at 200kfinding-13-fast-engine, RS-…e89ea128 | not recorded | 3,145,728 B at 64k; searcher 2,496 BRS-…e89ea128 | not applicable | |
| 16-thread moves/s | not recorded | not applicable | not recorded | 82,364,000 | not recorded | 129,483,860 | not applicable | |
| Latent / hidden-board mode | yes (LatentBoardOptions)engine.ts | nofast-search.ts | noengine.hpp | nofast-engine.hpp | yes (LatentRevealSource)scenario.hpp | noRS-…e89ea128 | yes (explicit inputs)lib.rs | |
| Idle-host measurement | none | none | none | none | none | none | none | no record |
The record behind the latency columns notes: “Timing measured on a shared workstation (load average 1.1-1.7); ratios between back-to-back arms are the trustworthy quantity, absolute nanoseconds are not.” (RS-20260824T075451Z-e89ea128).
Nothing in this table qualifies as a clean performance baseline under the benchmark rules. A clean measurement would need exclusive resources, three repeats and a scaling preflight.
Engineering evidence, CHECK tier: no score, strength or ranking claim is made anywhere. finding-13 section 0 headline table, all ratios measured back-to-back or interleaved in one process on a machine shared at load 14-57 — ratios are the trustworthy quantity; absolute times are inflated roughly 3x at load 50 relative to load 15, and an earlier SEQUENTIAL (non-interleaved) measurement of the same stack reported an illusory 5.51x that vanished under interleaving (recorded as the load-drift lesson). Behind every bar: identical selected columns (306 gated search moves plus 438,020 gated engine moves), identical logical work at all nine (depth, strata) configurations, identical completed depth, bit-identical leaf values over 225,183 states, and whole-game identity on the 64-game cohort (704 field comparisons, finding-15 section 1). The leaf-memo bars are a separate record (RS-20260822T074305Z-bd1697c8, metrics.timingIndicative): one-entry memo, interleaved plain/memo under load ~31, 12 roots x 3 reps (d4s5) and 6 roots x 2 reps (d4s7), flagged indicative by the record itself; the memo is deliberately NOT shipped (finding-13 section 8.4 — a cache-semantics change needing its own declaration). Not a clean performance baseline under docs/benchmarks.md; nothing here may enter research/benchmarks/profiles-v1.json.
Spec: web/content/figures/engine-speedup.json · 2 source records · kind bar
Two implementations mean two chances to be wrong. If the fast engine dropped a chain wave one move earlier, or awarded the rise bonus in a different order, every score from the C++ experiments would mean something slightly different from every score from the TypeScript ones, and nobody would notice by comparing means. So the engines are compared move by move instead.
Pick a seed. The seed fixes the sequence of discs the game will deal, in both engines, through the same arithmetic. Play a complete game in each engine, choosing columns from a shared random stream rather than from a policy, so both engines make exactly the same moves and any difference in the result is a difference in the rules. After every move each engine writes one record: the points that move scored, the running score, the level, the moves left before the next rise, whether the game ended, whether the board was cleared, whether the level advanced, every chain wave, and the full 49-cell board as a string. Compare the two streams line by line, byte for byte. Any difference at all is a failure.
The same method sits behind every “bit-identical” claim on this site: the fast engine's leaf, search and trajectory gates, the scenario engine's parity run, and the Rust engine's three gate binaries all replay the C++ engine and stop at the first differing byte. The method has a limit the fidelity audit states plainly: two engines can agree exactly on the wrong rules, and the 70,000-point board-clear branches have zero cross-engine coverage in the parity sweep (docs/exploratory/audit-01-engine-fidelity.md).
The approach directories that build, speed up or check an engine rather than play the game. Each keeps its own page with its records and gates.
Play the same games in the readable TypeScript engine and the fast C++ engine, then require their records to match exactly.
A packed Drop7 engine that avoids unused leaf calculations and offers bounded private or shared search caches.
One instrumented game loop and one results writer, shared by every experiment in this family so their numbers are directly comparable and every game's score is checked against the rules.
A semantics-preserving reimplementation of the Drop7 move engine and the fair-D4 leaf, proven bit-identical to the frozen reference and measured at about 3× end to end.
Reuses board features across equivalent chance samples and recomputes only the next-disc term, preserving exact values with less work.
Ports the native factored chance node (N disc strata x M reveal samples) into the fast memo engine, trace-equivalent to the C0 search at a fraction of the cost.
An infrastructure package that made PyTorch work on this machine's integrated AMD GPU, checked that it computes correct answers, and measured how much faster it is than the CPU.
Fix every future disc and hidden number in advance so a position has one exactly computable best line.
Replays many games and labels every visited position with its remaining lifetime, producing training data for the rest of the family.
The C++ program trains the original n-tuple evaluator, searches with it, benchmarks the fast engine, and runs the shared self-tests.
Keep the deep, mature boards a future-reading planner reaches, throw away everything privileged about them, and hand them to other experiments as practice positions.
A shared trainer fits board models from four kinds of teacher on separate seed lanes, making the teachers directly comparable.
web/lib/play/fast-search.tsapproaches/lifetime-objective/fast-engine/README.mdx)approaches/lifetime-objective/scenario/README.mdx)approaches/fair-expectimax/rust-engine/README.mdx)approaches/lifetime-objective/gpu/README.mdx)The tests and gate binaries that must pass before an engine's output counts, grouped by the file or command that runs them.
src/core/typescript/engine.test.ts
src/core/typescript/engine-latent.test.ts
src/core/typescript/classic-engine.test.ts
web/lib/play/fast-search.test.ts
make test-native; make parity
build/fast-engine (finding-13 section 10)
build/scenario
approaches/fair-expectimax/rust-engine (target/release)
src/core/rust/classic-engine (cargo test)