Drop7 Research
tree-search

TypeScript MCTS lab

rejectedevidence: task-record onlypublic information

A small, readable Monte Carlo tree search you can run in a terminal — the one place in the repository where the idea is easy to watch.

A small, readable Monte Carlo tree search you can run in a terminal — the one place in the repository where the idea is easy to watch.

rejectedevidence: task-record onlypublicreads only what a player can see

What it is

The C++ programs in this family are research instruments: thousands of lines, frozen gates, sanitizer builds. This one is a few hundred lines of TypeScript that plays complete games and prints a line of statistics. It exists so the idea can be read, modified and run without a compiler, and because the solver it drives is shared with the benchmark playground.

How it works, step by step

The search itself lives in src/core/typescript/mcts-solver.ts and is called by the lab in a loop until the game ends.

  1. The lab starts a game from a seed and hands the solver the public position: board, visible next disc, moves until the next rise, terminal flag. The solver is given its own fixed random stream, which is deliberately not the game's seed, so the search cannot sample the future the game will actually deal.
  2. Each simulation walks down the stored tree, choosing at every step the column with the best average result plus an exploration bonus for the least-visited ones. Tree nodes are keyed by the complete visible position, so a branch reached by two different routes is the same node, and a decision made after a sampled reveal is conditioned on the board that was actually observed — not on a future decided in advance.
  3. When the walk reaches a position the tree has not stored, the simulation is finished by a short greedy playout and the resulting board is scored by the heuristic evaluator. Dying is charged a large fixed penalty.
  4. Results are added back along the path. After the last simulation the lab plays the root column with the best average, the real game deals a real disc, and the loop repeats.

The stored tree has a hard entry limit; once it is full, further simulations fall back to the bounded playout evaluator rather than growing without bound.

Defaults, and what they mean

SettingLab defaultWhat it controls
--simulations2,000How many futures are sampled per move
--horizon20How many moves ahead a simulation may run
--rollout-depth2Greedy moves used to finish a new position
--exploration40,000Bonus for under-visited columns, in score units
--max-nodes100,000Hard cap on stored positions
--terminal-utility−1,000,000The penalty charged for dying
--games / --max-moves4 / 1,000Size of a run

The registered playground policy uses a much smaller budget — 400 simulations and a sixteen-move horizon — so that a scripted round finishes quickly. Those rounds are a demonstration and are never used as research evidence.

What happened, in plain English

Nothing was retained. The conclusion carried forward from this program is the one sentence in the index: ordinary Monte Carlo tree search did not establish a whole-game improvement over the reference. That statement is consistent with the three ledger-recorded C++ experiments in this family, which failed their frozen gates for reasons that were diagnosed in detail — but it is not itself evidence, and it should not be cited as though it were. If this program is ever run against fair depth 4 on a paired cohort with a registered protocol, the result will be the first real measurement this file has.

What this taught us, and what is still open

  • Provenance is part of a result. A rejection with no protocol and no data cannot be checked, reproduced, or rescored when the rules change — and the scoring rules did change here, from a 7,000-point rise bonus to 17,000.
  • The cheapest open experiment in this family is probably not a new idea but a registered run of code that already exists: this lab, and the PUCT lab next door, both complete and both without a retained outcome.

Source files

  • README.mdx
  • typescript.ts