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).
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).
1from flax.serialization import from_bytes
2from baselines.ppo_selfplay import ActorCritic # github.com/SuuTTT/ludus
3import jax, jax.numpy as jnp
4from boom.engine import H, W, OBS_C, OBS_VEC
5
6net = ActorCritic()
7tmpl = net.init(jax.random.PRNGKey(0),
8 jnp.zeros((1, H, W, OBS_C), jnp.float32),
9 jnp.zeros((1, OBS_VEC), jnp.float32))
10params = from_bytes(tmpl, open("champion.msgpack", "rb").read())
Boom is an original game: mechanics-inspired by the lane-battler genre with
original names and art; numeric stats are unprotectable facts.