docs: specify battle checkpoint extension

This commit is contained in:
MaxTomahawk
2026-08-07 16:41:13 +02:00
parent 2ce612d5b1
commit 5bffc89a2f
3 changed files with 150 additions and 13 deletions
+12 -9
View File
@@ -181,17 +181,20 @@ end
local ok, code, message = mod.checkpoints:restore(game, checkpoint)
```
Checkpoint format 1 supports settled overworld control only: the overworld must
be topmost, the player stationary on a tile, and no transition, menu, script,
queued script movement, or partial field animation may be active. Refusals carry
a stable `reason` and readable `message`. Capture excludes global options and
runtime objects. Restore validates format, game/playthrough identity, content,
and coordinates before mutation; preserves current options; suppresses normal
map-entry/save-load side effects; verifies a recapture; and rolls back in memory
if reconstruction fails. Callers that need crash recovery should durably capture
Checkpoint format 1 supports settled overworld control and proven battle
player-decision safe points. Battle checkpoints are limited to ordinary
single-player wild/trainer origins with no suspended script; link, Safari,
ghost, demo, scripted, animation, message, queue, and forced-action phases fail
closed. New checkpoints preserve gameplay RNG, while legacy overworld records
without RNG remain loadable. Capture excludes global options and runtime
objects. Restore validates format, game/playthrough identity, content,
coordinates, battle relationships, continuation, and RNG before mutation;
preserves current options; suppresses normal map-entry/save-load/intro side
effects; verifies a recapture; and rolls back runtime plus RNG in memory if
reconstruction fails. Callers that need crash recovery should durably capture
their own recovery checkpoint before restore.
See RFC 0003 and RFC 0004 for exact contracts and error codes.
See RFC 0003, RFC 0004, and RFC 0005 for exact contracts and error codes.
## Developer console
+5 -4
View File
@@ -104,10 +104,11 @@ runtime exception, not process termination.
## Runtime boundary and future kinds
Format 1 intentionally rejects battles, menus, transitions, animations, and
suspended/queued scripts. Future battle or explicit script-checkpoint kinds must
have separate inventories, validation, reconstruction, deterministic RNG, and
differential tests; they are not implied by this RFC.
This RFC's original Level A contract intentionally rejects battles, menus,
transitions, animations, and suspended/queued scripts. RFC 0005 subsequently
adds a separately inventoried `battle` kind with deterministic RNG and
differential reconstruction tests; it does not broaden script or arbitrary-frame
support implied here.
## Migration note for existing mods
@@ -0,0 +1,133 @@
# RFC 0005 — Persistent battle safe-point checkpoints
## Status
Proposed. Extends RFC 0004. Engine: `BattleCheckpoint.lua`, `Checkpoint.lua`,
`Game.lua`, `BattleState.lua`, and `OverworldController.lua`. Tests:
`battle_checkpoint_*.lua`, `checkpoints.lua`, and the existing no-mod suites.
## Motivation
RFC 0004 lets a tool capture and reconstruct settled overworld progress without
private engine access. A battle is a different runtime: its queue can hold Lua
functions and UI factories, its controller contains renderer objects and live
references, completion is currently an `onFinish` closure, and scripted battles
resume a suspended `ScriptRunner` coroutine. Copying the controller would create
a record that is neither data-only nor process-independent.
The engine can instead expose a narrow semantic safe point. This gives all mods
the strongest persistent battle checkpoint the current architecture can prove,
without claiming mid-animation or suspended-script support.
## API delta
No new facade is added. The existing additive `mod.checkpoints` API gains a
second format-1 runtime kind.
### Capability
`mod.checkpoints:inspect(game)` returns this only when an ordinary single-player
wild or trainer battle is settled at the player command menu:
```lua
{ canCapture = true, canRestore = true, kind = "battle" }
```
The action/message queue, waits, UI, animations, HP/status presentation, and
faint processing must be settled. The player must actually control the menu.
The underlying overworld must have no running/queued script or scripted move,
and the battle must carry an engine-owned semantic continuation descriptor.
Additional refusal codes are `battle_phase_busy`, `battle_origin_unsupported`,
`battle_variant_unsupported`, and `link_battle_unsupported`. Link, Safari,
ghost, old-man/demo, fishing, static-object, script-suspended, and mod-created
closure continuations remain rejected.
### Capture
A battle checkpoint remains detached and data-only:
```lua
{
format = 1,
kind = "battle",
identity = { engineVersion = "...", gameVersion = "red",
playthroughId = "..." },
save = { -- canonical dynamic progress, excluding global options },
runtime = {
overworld = { map = "ROUTE_1", x = 7, y = 8,
facing = "left", surfing = false },
battle = { -- normalized semantic model and continuation },
},
rng = { love = "..." },
}
```
The model carries player/enemy roster indices, dynamic enemy Pokémon, turn and
escape state, HP/PP/status/stages/volatiles, participants, level-up tracking,
trainer AI state, battle ruleset identity, side/field extension data, and
normalized pointer relationships such as multi-turn move slots and Mimic
restoration entries. Definitions, sprites, canvases, queues, callbacks, and
controller objects are reconstructed or excluded.
Callback-bearing battle extension tokens fail with `battle_extension_unsafe`;
invalid live reference relationships fail with `battle_state_invalid`. Nothing
is silently stripped.
New overworld checkpoints also carry the LÖVE gameplay RNG state. Legacy
format-1 overworld checkpoints without `rng` remain loadable and leave the
current stream untouched.
### Restore
Battle restore validates the detached save, map, content references, ruleset,
roster indices, move references, continuation identity, and RNG before live
mutation. The engine then:
1. reconstructs the saved overworld return point without entry side effects;
2. creates a fresh `BattleState` from current content registries;
3. applies the normalized battle model and rebuilds object-reference relations;
4. binds an engine-owned wild/trainer completion continuation;
5. installs the battle directly at the settled menu without replaying its intro;
6. restores the RNG after reconstruction has finished; and
7. recaptures and compares the complete checkpoint.
The pre-operation checkpoint is the transaction rollback. A failed post-install
RNG restore is covered: both battle runtime and RNG are reconstructed back to
their original values.
## Continuation decision
Ordinary random wild battles resume through `OverworldState:afterBattle`.
Ordinary trainer battles use a descriptor containing map id, stable NPC id,
trainer class/party, and optional header event; a win reapplies the same defeated
flag, event, reward, and `afterBattle` path. Reconstructed overworld input and
NPC freeze state are normalized instead of reviving the old closure.
`Commands.start_battle` is deliberately unsupported: its completion closure
mutates script context and resumes a coroutine whose program counter and Lua
stack cannot be serialized. Existing script rejection remains the correct safe
contract until a separate semantic ScriptRunner checkpoint RFC exists.
## Migration note
**Existing mods require no changes.** The facade and format number are unchanged;
the new kind and RNG field are additive. Overworld-only callers may continue to
filter `capability.kind`. No-mod behavior is unchanged when checkpoints are
unused.
## Verification
- settled/unsafe boundary and every variant refusal;
- data-only wild and trainer capture, including callback-bearing extension
rejection;
- process-independent controller and continuation reconstruction;
- exact differential recapture for wild and trainer states;
- HP, PP, status/stages/volatiles, AI layer, participants, enemy roster,
multi-turn move references, and Mimic restore pointers;
- exact damage, critical, accuracy, random AI, escape, next encounter, and next
raw RNG result after reload;
- corrupt content/continuation rejection before mutation;
- injected post-install failure with full runtime and RNG rollback;
- legacy overworld checkpoint compatibility;
- complete ROM-free engine and public mod-API suites.