~/kaustubh-lall

~/projects $ cat projects/ai-bomber.md

AI Bomber

research

Personal

High-performance Bomberman-style AI simulation environment and visualizer in C17.

Low-level, high-performance simulation and visualization environment for agent self-play experiments, written in C17 with raylib.

  • Headless simulator throughput: ~234,000 steps/sec, single core, no visualizer linked
  • 12 CTest suites covering determinism, replay, reward, danger, and hardening
  • 8 design docs; 59 C source and header files, 4,296 lines, ~146 KB across src/
  • CI matrix: GCC + Clang (-Werror) and MSVC, full suite on every push and PR

Overview

AI Bomber is a Bomberman-style simulation environment built to be trustworthy before anything gets trained on it. This case study covers the repository as of commit c50f423 (2026-07-06); development on the project continued past that commit. At the commit this case study covers, there is no neural network anywhere in the repository, and the README said so directly: "a local research sandbox, not a trained neural agent." What exists instead is a deterministic C17 environment with fixed-size state, per-instance agent RNG, arrival-time danger checking, a binary replay format, 12 CTest suites, CI on GCC, Clang, and MSVC with -Werror, and 8 design docs covering every subsystem.

The headline numbers are throughput and correctness, not a win rate. The headless simulator runs at roughly 234,000 steps per second and produces bit-identical episodes given the same seed and action sequence. Build and verify the environment first, that is the ordering principle: a fast, deterministic, well-tested simulator is what makes any later training result trustworthy, and skipping that step is why RL projects end up debugging their environment and their agent at the same time.

The problem

Reinforcement learning demos usually start from the model side: pick an algorithm, wire it to whatever environment is fastest to stand up, and start training. The environment itself rarely gets the same engineering attention as the model, which means bugs like shared static state between agent instances, or a "safe" check that ignores a bomb about to detonate by the time the agent arrives, silently corrupt every experiment run on top of them.

AI Bomber treats the environment as the deliverable. It asks a narrower question first: can this simulator reproduce the same result twice, run fast enough to be useful for training, and expose its internals cleanly enough for a Python or C++ policy to be dropped in without touching the core.

Approach and architecture

The project is a simulator-first C17 implementation of a four-agent Bomberman variant: movement, bomb placement, blast propagation, crate destruction, and powerups, with a raylib visualizer layered on top for debugging and a headless CLI for training-scale rollouts. Five modules split the work cleanly: core/ (a SplitMix64 PRNG with no global state, config bounds, a ring buffer for action history, binary replay save/load, and episode metrics), env/ (map generation, bomb and blast logic, the danger map, observation and reward builders, and the movement/placement/terminal rules), agents/ (a function-pointer interface with per-instance storage and four built-in policies: random, scripted, heuristic, greedy-crate), sim/ (episode runner, benchmark, and an agent-vs-agent evaluator), and viz/ (the raylib renderer, dashboard, and session manager).

The build separates concerns explicitly: -DAI_BOMBER_BUILD_VIZ=OFF compiles the environment, agents, and CLIs without linking raylib at all, so a training pipeline never pays for graphics dependencies it does not use. Correctness is enforced with CTest from the start rather than bolted on afterward, and CI runs the full matrix (GCC and Clang with -Werror on Linux, MSVC on Windows) on every push and pull request. The data flow is a straight loop: env_init and env_reset set up state from the config and seed, then each tick calls env_observe, hands the observation to whichever agent is attached, calls env_step with the returned action, updates metrics, and optionally records the tick to a replay buffer. The headless CLI, the benchmark CLI, and the visualizer are three different consumers of that same loop, not three different implementations of it.

Implementation notes

A few choices are deliberate, not incidental. Fixed-size state with no heap pointers (bounded arrays capped at a 31x31 tile grid, with limits on agent and bomb counts) means saving and loading a replay is a straightforward binary serialization of the struct, with no allocator-related nondeterminism to chase down.

Per-instance agent state was a real bug, not a hypothetical one. Commit c50f423 ("Harden simulator") replaced file-static implementation structs in the heuristic and greedy agents with per-instance storage. Before that fix, two heuristic agents running side by side shared the same static RNG state and interfered with each other. ARCHITECTURE.md now calls this out explicitly as a determinism rule, not just a style preference.

Arrival-time danger checking replaces the naive "is this tile safe right now" question with the one an agent moving toward a bomb actually needs answered: danger_is_action_safe_at_arrival checks whether the blast reaches a tile after the agent would arrive there, using a per-tile time-to-blast field computed from every active bomb. Reward is a struct of eight-plus named components (survival, crate destruction, powerup pickup, enemy damage and elimination, win and death, escape from danger, trap opportunity, and penalty terms) rather than one scalar, which is slower to read but far faster to debug when an agent's behavior does not match expectations.

What is deliberately not here: FUTURE_MODELS.md lays out five planned model-integration paths (behavior cloning, DQN, PPO, a genetic algorithm over network weights, and evolution strategies) through the same C ABI, none of them implemented at this stage. The README states plainly that the project is "a local research sandbox, not a trained neural agent," a scope boundary stated up front rather than a gap discovered later.

Results

Verified against a local checkout at commit c50f423 ("Harden simulator"), where the documentation, test suite, and CI configuration all match exactly. Headless simulator throughput: about 234,000 steps per second, single core, no visualizer linked, quoted directly from a later commit message reporting a passing test run at that throughput.

The test suite has 12 CTest suites in tests/, covering rules, determinism, replay round-trips, reward accounting, agent behavior, danger-map correctness, and the c50f423 hardening fixes specifically. An earlier assessment cited 14 test files. This write-up reports the verified count of 12 instead. Documentation totals 8 design docs in docs/, and the source is 59 C source and header files, 4,296 lines and 146 KB, across src/. CI runs two jobs on every push and pull request: GCC and Clang on Ubuntu with -Werror, and MSVC on Windows, both running the full CTest suite.

Tradeoffs and lessons

Fixed-size, bounded state buys determinism and cheap serialization, but it caps the board at 31x31 tiles and a fixed agent and bomb count. Scaling up means touching the constants and re-verifying every test that assumes them. Writing the core in C17 instead of Python buys raw throughput and a clean C ABI, at the cost of the conveniences the Python ML ecosystem takes for granted. Making the visualizer optional at build time keeps the headless path fast and CI simple, but the compiled visualizer was not exercised in this write-up, no display was available, so nothing about bomber_viz beyond its documented behavior was directly checked. Shipping the environment without a trained model is the whole point of this project, but it also means there is no end-to-end result yet showing a learned policy beating the rule-based baselines. That is future work, explicitly deferred, not a missing feature.

The clearest lesson is about sequencing: the project spent its early commits entirely on the environment (state representation, rules, danger computation, replay, CI, docs) before writing anything resembling a trained agent, and the payoff shows up directly in the hardening commit. The per-instance-state bug would have been invisible, or worse, silently biased, if it had first surfaced three weeks into a training run instead of being caught by a test written against the simulator itself. "Safe" is a time-dependent property in a bomb-based game, and building danger_is_action_safe_at_arrival as its own named, tested function made that distinction explicit and checkable, rather than leaving it as an approximation inlined into the heuristic agent.

Architecture

BomberConfig + seed (u64)env_init / env_resetenv/ · BomberEnvbomber_map · bomber_bombs · bomber_blastbomber_danger · bomber_observationbomber_reward · bomber_rulesfixed-size state, no heap pointersagents/random · scriptedheuristic · greedyper-instance stateact()observe()tests/12 CTest suitesdeterminism, replay,reward, danger, hardenedenv_step + metrics_updatesim/runner · benchmark · evaluatorbomber_headlessCLI, --export metrics.jsonbomber_benchmarkCLI, ~234k steps/secbomber_vizraylib, 3 view modesArena · Graphs · Comparison views, replay.bin runs through the same env_step loop

architecture · ai-bomber

Results

AI Bomber results at commit c50f423: throughput, test coverage, documentation, source size, and CI configuration
MetricValueDetail
Throughput~234,000 steps/secsingle core, no visualizer linked
Test suites12 CTest suitestest_agents, test_blast, test_bomber_env, test_bombs, test_danger, test_determinism, test_hardened, test_map, test_observation, test_replay, test_reward, test_rng
Design docs8 docsARCHITECTURE, ENV_API, OBSERVATION, REWARD, DANGER_MAP, VISUALIZER, ADDING_AGENTS, FUTURE_MODELS
Source size59 files · 4,296 linessrc/*.c + src/*.h, ~145 KB total
CI2 jobs / push + PRGCC + Clang -Werror (Ubuntu), MSVC (Windows), full CTest suite each

results · ai-bomber · verified against commit c50f423 (2026-07-06)

notes

  • Research-sandbox stage: no trained neural agent exists yet, only four rule-based agents (random, scripted, heuristic, greedy-crate). Five model-integration paths are documented in FUTURE_MODELS.md but not implemented.
← All projects