---
type: reference
title: "Pokemon TCG AI Battle — Action Coverage and Runtime Parity"
description: "Historical deterministic legal-action enumeration, bounded full-domain sampling, sidecar schema, and parity between offline prospective groups and the then-current runtime search."
tags: [pokemon-tcg, action-coverage, deterministic, prospective-v2, runtime-parity]
timestamp: "2026-08-15T17:45:00-03:00"
---

# Pokemon TCG AI Battle — Action Coverage and Runtime Parity

## Evidence Boundary

This page reflects the historical `rl/prospective_actions.py` sidecar builder,
the then-current PyTorch runtime planner, and commit `10c3750`, which fixed
prospective reward balancing and action coverage. The transcript later records
serial/parallel byte-for-byte equivalence as observed validation evidence, but
competition impact remains unmeasured. The separate sidecar was removed at
`a942373`; this page is retained for method and provenance, not as a current
runtime contract.

## Candidate Enumeration

The shared enumeration function resolves a complete legal action tuple, not
only a single option index. This matters for multi-select decisions because an
action can contain zero, one, or several selected option indices depending on
the engine's `minCount` and `maxCount`.

If the legal combination count is at most `max_branches`, every legal
combination is emitted. If the domain is larger, the sampler chooses evenly
spaced lexicographic ranks across the full legal domain, including both
endpoints. This removed the old prefix bias while preserving deterministic
bounded cost.

```text
legal combinations <= max_branches
    -> enumerate all combinations

legal combinations > max_branches
    -> sample ranks from the whole combination domain
    -> include first and last legal ranks
    -> keep output deterministic
```

The current default is `max_branches=64`. That is a compute budget, not a claim
that every huge action domain is fully enumerated. The invariant is full-domain
coverage by deterministic rank sampling when full enumeration is too large.

## Shared Offline/Runtime Function

The offline builder and runtime search both call the same
`enumerate_prospective_actions` implementation through:

| Consumer | Purpose |
|---|---|
| `scripts/bc/build_prospective_groups.py` | materialize prospective sidecar branch roots from real replay decisions |
| `rl/prospective_runtime.py` | construct live runtime branch roots before PyTorch reranking |

This is the main parity guarantee. Sidecars and live inference do not maintain
separate action-candidate logic.

## Multi-Select Relationship

The base Transformer path remains autoregressive:

\[
\pi(a_1\mid s),\quad
\pi(a_2\mid s,a_1),\quad
\pi(\mathrm{SUBMIT}\mid s,a_{<k}).
\]

The prospective planner instead ranks complete legal action tuples as branch
roots. When the planner succeeds, it returns the full tuple and commits memory
once. When it fails, the Transformer fallback recomputes options step by step.
Both paths must satisfy the same legality boundary supplied by the game engine
and encoder masks.

## Versioned Schema

Action coverage is versioned as `PROSPECTIVE_ACTION_CANDIDATE_VERSION =
"2.0.0"`. The sidecar manifest records this version next to the planner
version, input-adapter version, coordinate schema, source archive hashes, BC
dataset fingerprint, config, storage layout, and semantic fingerprint.

Branch actions are stored compactly in a flat `int16` array addressed by
`action_offset` and `action_count`. Group order is source archive, ZIP member,
real decision, then `trial_index`. Node order is parent-before-child within
each tree.

## Determinism And Resume

Parallel execution changes throughput only. The semantic fingerprint excludes
worker count because ordered process results preserve shard/group order. Resume
accepts legacy serial shards only when the existing completed groups form the
exact deterministic prefix expected by the current contract.

The source task recorded these observed checks after the parallelization work:

- real smoke sidecar completed with 4 groups, 22 branches and 44 nodes;
- serial and parallel outputs were byte-for-byte identical;
- the new parallel output matched the previous serial smoke sidecar;
- a legacy `.work` contract with `workers=1` was accepted without recalculating
  already completed shards.

These are validation facts for the builder, not evidence that the trained
planner improves ladder performance.

## Related Pages

- [[pokemon_tcg_prospective_v2]] — historical planner, sidecar and group-relative objective.
- [[pokemon_tcg_would_ko_prospective_search]] — would-KO versus prospective branch search.
- [[pokemon_tcg_temporal_learning]] — autoregressive multi-select and TBPTT.
- [[pokemon_tcg_training_overhaul_2026_07_29]] — trainer progress and checkpoint contract.
