Ludus Boom — self-play league agents
PPO agents for Boom, the real-time lane-battler of the Ludus competition platform (a deterministic pure-JAX engine: int32 fixed-point state, bit-identical replays, ~5M env-steps/s on one RTX 3090).
Files
| file | what |
|---|---|
champion.msgpack |
current league champion (serialized Flax params) |
gen_0..4.msgpack |
the founding lineage — each promoted only by beating the previous champion in seat-swapped mirrored pairs with a Wilson 95% lower bound > 0.5 |
standings.json |
full lineage with per-generation gate results and anchor win-rates |
league.jsonl |
append-only league event log (training, gates, promotions) |
Architecture
ActorCritic from baselines/ppo_selfplay.py in the repo: two conv layers
(24, 48, stride 2) over the 32×18 board observation + a dense branch for the
vector observation, merged into a 256-unit trunk with a 2305-way masked action
head (noop + card-slot × tile) and a value head.
Training protocol
Generational self-play league with CI-gated promotion. Each generation trains PPO (deck-randomized both seats — mixed decks fixed an earlier deck-specialist failure) and must beat the reigning champion with statistical significance to be promoted. Later generations add an elixir-overflow penalty (passivity bleeds reward) and opponent-pool training (half the updates vs frozen sampled past generations).
Founding lineage (win-rate vs previous champion; anchors vs scripted rule_v0):
| gen | vs champion | vs rule_v0 |
|---|---|---|
| 0 | founder | 43.0% |
| 1 | 85.2% (CI ≥ 80.3) | 47.7% |
| 2 | 71.9% (CI ≥ 66.1) | 64.8% |
| 3 | 64.1% (CI ≥ 58.0) | 69.5% |
| 4 | promoted | ~78% |
Usage
from flax.serialization import from_bytes
from baselines.ppo_selfplay import ActorCritic # github.com/SuuTTT/ludus
import jax, jax.numpy as jnp
from boom.engine import H, W, OBS_C, OBS_VEC
net = ActorCritic()
tmpl = net.init(jax.random.PRNGKey(0),
jnp.zeros((1, H, W, OBS_C), jnp.float32),
jnp.zeros((1, OBS_VEC), jnp.float32))
params = from_bytes(tmpl, open("champion.msgpack", "rb").read())
Or upload any of these files straight to a running Ludus platform's
/submit page and fight them in the browser.
Boom is an original game: mechanics-inspired by the lane-battler genre with original names and art; numeric stats are unprotectable facts.