This repository contains a command line play-by-play simulator that aims to produce logs that feel indistinguishable from a real Major League Baseball broadcast. The engine models pitch-by-pitch sequences, strategic bullpen usage, and situational events (mound visits, defensive alignments, challenges, weather, etc.) to generate rich narration while respecting modern MLB rules.
- Python 3.9 or newer
Install the Python dependencies (only the standard library is required) and run the simulator directly:
python baseball.pyUse the available CLI flags to tailor the output:
--commentary {narrative,statcast,gameday}– choose output style:narrative(default) – descriptive, broadcast-style play-by-playstatcast– data-driven output with exit velocity, launch angle, and pitch metricsgameday– structured JSON output matching MLB StatsAPI format
--terse– switch to compact play-by-play phrasing (data feed style)--bracketed-ui– render base runner state using legacy bracketed indicators instead of prose
The project ships with a growing collection of regression tests that encode previously observed realism issues. Run everything with:
python -m unittest discover -p "test_*.py"Or run a specific test file:
python -m unittest test_realism.py -vThe tests cover items such as bullpen variability, pitch vocabulary diversity, realistic catcher groundout frequencies, and snapshot comparisons against curated example games.
The examples/ directory tracks ten seeded, deterministic game logs in multiple formats. These files are used both for documentation and for regression testing to ensure that engine changes produce intentional differences.
-
example_games.pydefines theExampleGamehelper along with the catalog of seeds. -
test_examples_snapshot.pyrenders each game with a fixed seed and asserts that the generated output matches the stored text files. -
After making behavior changes, refresh the tracked examples:
python update_examples.py # Regenerates examples/game_*.txt python update_statcast_examples.py # Regenerates examples/statcast_game_*.txt
The scripts will re-render every example using the latest simulator behavior so the new output can be reviewed and committed alongside your code changes.
Note: Gameday JSON examples are tested via test_gameday_regression.py using curated single-event examples rather than full game snapshots.
The file pbp_example_1.txt is a manually-written example of the target announcing style for the narrative commentary mode. It is not a direct output from the simulator. It serves as a stylistic reference for the tone, pacing, and descriptive detail that the simulation aims to emulate. This file should not be updated or regenerated, as it is a fixed benchmark for the desired "old-timey radio broadcast" feel.
baseball.py– core simulation engine and CLI entry pointteams.py– fictional rosters, player attributes, and ambient context (umpires, weather, venues)gameday.py– type definitions for gameday JSON output formatexample_games.py– deterministic example definitions used for snapshot testing and documentationexamples/– checked-in play-by-play logs generated from fixed seeds (narrative, statcast, and gameday formats)test_*.py– test suites that enforce realism constraints and snapshot parityCLAUDE.md– guidance for Claude Code AI assistant when working with this codebase
Feel free to modify the team definitions or extend the rules engine. When adding new realism features, remember to regenerate the example logs and expand the regression tests where appropriate so we continue guarding against past issues resurfacing.
This repository uses two distinct snapshot files for different purposes, which should not be confused:
examples/gameday_snapshot.json: The canonical snapshot of the core simulator structure for structural tests (test_gameday_snapshot.py). This file is auto-generated and should not be manually tweaked. Usepython update_gameday_snapshot.pyto regenerate it.test_fixture_pbp_example_3.json: A manually constructed/tweaked JSON fixture used specifically for testing NarrativeRenderer similarity against the target text (pbp_example_3.txt). It is intentionally modified to hit specific RNG outputs and should NOT be synced withexamples/gameday_snapshot.json.
If you modify test_fixture_pbp_example_3.json, you must also update the generated test output test_fixture_pbp_example_3.txt.