no LoseLife (ADR-0005). SettleDeath / SettleCompletion defer to the Attempt's terminal outcome, so both are atomic and idempotent. SettleCompletion branches on HasCleared itself - a Replay cannot bank or move campaign position backwards (ADR-0003). Campaign value object holds authored level order; ReachableLevels is derived, replacing the stored UnlockedLevels. Coins.IsAtLeast driven out by cross-scope affordability. 29 tests. CONTEXT.md: Campaign, Settle.
104 lines
4.8 KiB
Markdown
104 lines
4.8 KiB
Markdown
# Mr. Brick Adventures
|
|
|
|
A 2D platformer. This context covers **player state and progression** — what the player has, what they have done,
|
|
and at what point each of those becomes permanent. Gameplay behaviour (movement, combat, hazards) lives in the
|
|
composable components and is deliberately outside this context.
|
|
|
|
## Language
|
|
|
|
### Scopes
|
|
|
|
Three lifetimes. Every fact in this context belongs to exactly one.
|
|
|
|
**Attempt**:
|
|
One try at a level, from entering it to either completing it or losing a life. Holds a ledger of everything that
|
|
happened during the try — coins found, coins spent, skills bought. Discarded whole if the player dies.
|
|
_Avoid_: Session, run, life
|
|
|
|
**Playthrough**:
|
|
One game from New Game until game over, identified by a `PlaythroughId`. Holds lives, banked coins, owned skills
|
|
and their levels, campaign position, and which levels it has cleared. Several exist at once and the player picks
|
|
between them.
|
|
_Avoid_: Save, save slot, progress, game, run
|
|
|
|
**Profile**:
|
|
Everything shared across all Playthroughs, one per installation. Achievements, best time per Level, and lifetime
|
|
statistics. Never reset by starting a new Playthrough.
|
|
_Avoid_: Global state, meta, persistent data, account
|
|
|
|
### Operations
|
|
|
|
**Settle**:
|
|
Resolving an ended Attempt against the Playthrough — Commit it on a First Clear, Discard it otherwise. Settling is
|
|
the only way an Attempt affects a Playthrough, and it decides First Clear versus Replay itself rather than being
|
|
told which one happened.
|
|
_Avoid_: Apply, resolve, finalise
|
|
|
|
**Commit**:
|
|
Applying an Attempt's ledger to the Playthrough. Only a First Clear commits — nothing else, ever.
|
|
_Avoid_: Save, persist, flush, sync
|
|
|
|
**First Clear**:
|
|
Completing a Level this Playthrough has not cleared before. The only event that commits an Attempt and advances
|
|
campaign position.
|
|
_Avoid_: Level complete, finish (both ambiguous — they also describe a Replay)
|
|
|
|
**Replay**:
|
|
Completing a Level this Playthrough has already cleared. Records Best Time, achievements and statistics to the
|
|
Profile; commits nothing and never advances campaign position.
|
|
_Avoid_: Practice, retry, second run
|
|
|
|
**Bank**:
|
|
The coins a Playthrough holds, as opposed to coins found in the current Attempt. Coins are banked by committing,
|
|
never on pickup.
|
|
_Avoid_: Total coins, saved coins
|
|
|
|
**Discard**:
|
|
Throwing away an Attempt's ledger — on death, or at the end of a Replay. Purchases made during the Attempt are
|
|
undone by discarding, not refunded; under the ledger they never happened.
|
|
_Avoid_: Reset, rollback, revert
|
|
|
|
### Things
|
|
|
|
**Level**:
|
|
One playable stage, identified by a stable `LevelId` — never by position in a list. Knows its scene and display
|
|
name. Ids must survive inserting and reordering levels, because Playthroughs and Best Times both reference them.
|
|
_Avoid_: Stage, scene, level index
|
|
|
|
**Campaign**:
|
|
The authored ordering of Levels that defines progression — which Level is first, and what follows a given one. One
|
|
Campaign is shared by every Playthrough: it is authored data, not per-Playthrough state, and it carries no scene
|
|
or presentation detail.
|
|
_Avoid_: Level list, level order, world, chapter
|
|
|
|
**Cleared Levels**:
|
|
The Levels a Playthrough has completed at least once. Gates both campaign progression and level select; whether a
|
|
Level is reachable is computed from this, never stored alongside it.
|
|
_Avoid_: Unlocked levels, completed levels, available levels
|
|
|
|
**Skill**:
|
|
An ability the player can own and upgrade. `SkillData` is the authored asset describing one (name, icon, upgrade
|
|
table) and is immutable at runtime; the level the player has reached in it belongs to the Playthrough.
|
|
_Avoid_: Ability, power-up, upgrade (for the skill itself)
|
|
|
|
**Movement Ability**:
|
|
A composable behaviour attached to the player controller (jump, wall-jump, gravity). Unrelated to Skill —
|
|
authored per movement preset, not owned, not upgraded, not persisted.
|
|
_Avoid_: Skill, movement skill
|
|
|
|
**Best Time**:
|
|
The fastest recorded completion of a Level, from a First Clear or a Replay alike. Belongs to the Profile, so it
|
|
survives New Game and is shared by every Playthrough. Stored alongside, but distinct from, the ghost replay
|
|
frames that produced it.
|
|
_Avoid_: Personal best, high score, record
|
|
|
|
## Rules
|
|
|
|
- Reads may cross scopes freely — affordability spans Attempt and Playthrough. Writes must not.
|
|
- Derived facts are computed, never stored. Level reachability is derived from Cleared Levels; total coins from
|
|
Attempt plus Bank. Storing either alongside its source creates the second source of truth this context exists
|
|
to prevent.
|
|
- Achievements are mirrored to Steam, which is per-account and cannot be un-earned. That is why they are Profile
|
|
and not Playthrough: a per-Playthrough achievement list would contradict Steam permanently.
|
|
- Nothing in this context may reference Godot. Its correctness must be checkable without a scene tree.
|