Run Structure
In short
A run is 9 innings at one ballpark, at one difficulty. Each inning (a
RunNode) has a pitcher and a score goal. Innings 3, 6 and 9 are boss innings. Reach the goal to clear the inning; run out of outs first and the run ends. Everything is rebuilt from the run seed, so a checkpoint only stores your choices and totals.
How it works
RunStateis created with a batter, park, difficulty and seed. The batter’s starting upgrades are added andCoinsstarts atRunConfig.startingCoins.RunMapGenerator.Generatebuilds the innings fromnew SeededRandom(seed)(the only thing that uses the raw seed). For each inningi(0-based):- Boss inning if
(i + 1) % bossEvery == 0, or it is the last inning and the park has afinalBossId. - Last inning with a park boss: that pitcher (the park’s
finalBossId). It is never drawn earlier. - Other boss innings: a random boss not used yet in this run whose
minRound <= i, never one that is any park’s own final boss (park bosses only ever pitch at their park). If none fit, the rules relax step by step (ignoreminRound, then allow repeats, then any boss, then any pitcher). - Normal innings: a random non-boss pitcher with
minRound <= i. isFinalBossis set on a boss inning that is also the last one.targetScorecomes fromRunState.InningGoal.
- Boss inning if
- Each inning,
RunManager.PlayCurrentRoundcopies the run’s stats, adds the park’s and the pitcher’sbatterModifiers, and sets outs toOutsPerInning + ExtraOuts. See Upgrades and Synergies for stats. - The inning ends when the score reaches
targetScore(cleared) or outs hit 0 (run over). A cleared inning pays coins, movesCurrentIndexon and opens the shop; clearing the last one beats the map. - Cutscenes (Cutscenes): inning 1 opens with the match intro (once per run); a cleared boss inning that is not the last plays BOSS DOWN! before the shop; the run’s end plays MAP BEATEN! or GAME OVER before the results.
Inning goal (RunState.InningGoal):
goal = inningGoal x inningGoalGrowth^inning x (boss ? bossGoalMultiplier : 1)
x mapGoalGrowth^(map's place in the unlock order) x difficulty goal multiplier
rounded to the nearest 25, never below 25
Seeds. Each system derives its own stream with SeededRandom.Derive, so nothing you do changes the pitches:
innings use the raw seed, pitches use stream 1 (RoundSeed = Derive(Derive(seed, 1), inning index)), shop visits use
stream 2. Normal runs get Random.Range(1, int.MaxValue); the daily uses the date. See Seeds and Determinism.
Checkpoint and resume. RunManager.Checkpoint writes run.json (RunSaveData) every time the between-innings
screen opens and every time the shop opens (after a boss inning that is before BOSS DOWN! starts, so quitting
mid-cutscene resumes in the shop). CONTINUE on the title screen rebuilds the run from the seed, then
restores inning, coins, score, home runs, longest hit, cleared inning scores and owned upgrades. A checkpoint taken in
the shop reopens the shop with the same offers. Quitting mid-inning resumes before that inning, which plays the same
pitches again.
Numbers
| What | Value | Where to tune |
|---|---|---|
| Innings per run | 9 | RunConfig.inningsPerRun |
| Boss every | 3 innings | RunConfig.bossEvery |
| Outs per inning | 3 | RunConfig.outsPerInning |
| First goal | 500 | RunConfig.inningGoal |
| Growth per inning | x1.25 | RunConfig.inningGoalGrowth |
| Boss inning | x1.25 | RunConfig.bossGoalMultiplier |
| Per map along the unlock order | x1.15 | RunConfig.mapGoalGrowth |
| Goal rounding | nearest 25, minimum 25 | RunState.InningGoal |
| Checkpoint version | 2 (older saves are dropped) | RunSaveData.CurrentVersion |
Goals on the first map (Sandlot Field), Normal, worked out from the formula (the editor test checks 500, 625 and 975):
| Inning | 1 | 2 | 3 (boss) | 4 | 5 | 6 (boss) | 7 | 8 | 9 (boss) |
|---|---|---|---|---|---|---|---|---|---|
| Goal | 500 | 625 | 975 | 975 | 1225 | 1900 | 1900 | 2375 | 3725 |
With the default pitchers (Pitchers and Bosses): inning 1 is always Coach Pete (the only non-boss with
minRound 0); inning 3 is always The Ace and inning 6 always Knuckle Sandwich (the only two bosses that are not a
park’s own). Inning 9 is always the park’s own final boss:
| Park | Inning 9 boss (finalBossId) |
|---|---|
| Sandlot Field | Backyard Benny (benny) |
| Farmyard | Farmer Fitz (farmer) |
| Windy City Yard | The Gale (gale) |
| Midnight Yard | The Phantom (phantom) |
| Moon Stadium | The Alien (alien) |
In the code
| File | What it does |
|---|---|
Assets/_Project/Scripts/Run/RunState.cs | Run state, InningGoal, RoundSeed, TurnSeed, CreateShopRng, PriceOf, AddUpgrade, RecalculateStats |
Assets/_Project/Scripts/Run/RunMapGenerator.cs | Generate: pitchers, bosses and goals per inning |
Assets/_Project/Scripts/Run/RunNode.cs | One inning: pitcher, isBoss, isFinalBoss, targetScore, cleared, score |
Assets/_Project/Scripts/Run/RunManager.cs | OutsPerInning, InningContext, Checkpoint, ContinueRun, CanResume |
Assets/_Project/Scripts/Progression/RunSaveData.cs | The checkpoint fields |
Assets/_Project/Scripts/UI/RunMapView.cs | The between-innings line score (BOSS / FINAL BOSS cells, GOAL per inning) and briefing |
Assets/_Project/Editor/RunStructureTest.cs | Checks 9 innings, bosses at 3/6/9, goals, unlock order, coins and outs |
Gotchas
- A checkpoint is dropped (and deleted) if its version is not 2, its batter or park no longer exists, its difficulty is
out of range, its inning is past the end, or it is a daily from another UTC day (
CanResume). - The batting cage uses
targetScore = int.MaxValue, so its round never clears. See Batting Cage. - Every run map now sets
finalBossId. A park without one would fall back to a random boss in inning 9. DefaultContent’s comment on The Phantom says “Elsewhere he can turn up as a late boss (inning 6 on)“. The code wins:RunMapGeneratorkeeps every park’s own boss out of the random pool, so he only pitches at Midnight Yard.- The level perks are fixed at run start (
RunState.LevelBonus); XP only arrives when the run ends. - Dev menu tools (
DevJumpToInning,DevOpenShop,DevEndRun) mark skipped innings as cleared at exactly their goals. See Dev Menu and Shortcuts.
Related
- Core Loop: where innings sit in the whole game
- Difficulty: the goal multiplier and outs change
- Map Select and Unlocks: the unlock order that sets each map’s goal growth
- Count and Outs: how outs are made
- Run Config: every
RunConfigfield - Cutscenes: the intro and the outros around innings
- Save System: how
run.jsonis written safely