Drop7 Policy Protocol (D7P)
docs/d7p-protocol.mdDrop7 Policy Protocol (D7P)
D7P is the standard interface between a Drop7 policy and a benchmark harness — the analogue of UCI for chess engines. It exists so that any strategy, in any language, can be benched against the same scripted rounds and reported the same way.
D7P has two equivalent layers:
- a TypeScript interface used by the in-repository registry
(
src/bench/policies.ts), and - a text wire protocol for standalone processes
(
src/bench/d7p-server.ts).
Both layers express the same idea: a policy is a deterministic function of the public state.
The public state
A policy receives exactly four things, matching the information boundary in methodology.md:
- the 49 visible board cells;
- the visible next disc;
- the number of moves until the next row rise; and
- whether the game is over (equivalently, whether any column is legal).
A policy must not receive or infer the round id, generator seed, future discs,
hidden gray-disc values, score, level, absolute move number, or any history it
cannot reconstruct from the public state. In the TypeScript registry, strict
policies are handed a sanitized state whose score, level, and move counter are
fixed constants; policies that deliberately read level or move number are
flagged publicInformation: false and badged "extended state" on the
leaderboard.
TypeScript layer
interface BenchPolicy {
id: string; // stable kebab-case id
name: string;
family: string; // approaches/<family> grouping
description: string;
publicInformation: boolean; // strict public-state only?
slow?: boolean; // excluded from the default bench suite
chooseColumn(state: GameState): number | null;
}
chooseColumn returns a 0-indexed column. Returning null or an illegal
column is recorded as an illegal decision and the harness plays the first
legal column as a fallback. Policies must be deterministic: same public state,
same column. Solver seeds, when needed, are derived from the policy id and are
never game seeds.
Wire protocol
The wire protocol is line-oriented UTF-8 over stdin/stdout. The harness sends commands; the policy answers. All tokens are space-separated.
Handshake
-> d7p
<- id name Greedy 1-ply
<- id family heuristic-search
<- id public-information true
<- d7pok
Readiness
-> isready
<- readyok
Setting the position
-> position startpos next 3 rise 5
-> position board 00000000000000000000000000000000000000008888888 next 3 rise 5
boardis the 49-character serialization from the engine (serializeBoard): row-major from the top,0empty,1-7numbered,8solid gray,9cracked gray.startposis the standard opening (empty board, one covered bottom row).nextis the visible next disc,1-7.riseis the moves remaining before the next row rise,1-5.
Asking for a move
-> go
<- bestmove 4
bestmove carries the 0-indexed column, or none when no column is legal.
The policy may emit info ... lines at any time; harnesses must ignore lines
they do not understand. quit ends the session.
Reference server
Any registry policy can be driven over the wire protocol:
node --experimental-strip-types src/bench/d7p-server.ts --policy expectimax-d2
Scripted rounds
Benchmark randomness is predetermined by the drop7-scripted-round-v1 format
(src/bench/rounds.ts):
discs[m]— the visible disc at movem, indexed by absolute move number;latentRows[r][c]— the hidden value of the covered disc in columncof covered-row generationr(generation 0 is the opening bottom row).
The engine's latent-board mode (PlayMoveOptions.latent in
src/core/typescript/engine.ts) carries each hidden value with its physical
disc through gravity and rises, and a reveal can only produce that
predetermined value. The standard suite is Gauntlet 01–08
(src/bench/rounds/), generated from the dedicated 0x5eed**** domain, which
overlaps no historical or reserved research seed range.
Scripted rounds are a public playground: they consume no research seed lease and produce no tier evidence. Research-tier claims follow benchmarks.md.
Running the benchmark
npm run bench # default policies x all rounds
npm run bench -- --all # include slow reference policies
Results are written to web/data/leaderboard.json with one replay file per
game in web/data/replays/, and render in the web console at /leaderboard.