From 3f1d1b08046f2e3dacb035e186ed3c43db58ba4e Mon Sep 17 00:00:00 2001 From: dayfine Date: Mon, 9 Nov 2026 18:40:11 -0800 Subject: [PATCH] Authored checkpoints: accept FRLG sections, notes, once_per_save and execution fields Arduino-Source #314 moves every FRLG story checkpoint to an authored plan. The common checkpoint now takes events or named sections, notes on the checkpoint/section/event and once_per_save on events; FRLG execution takes supplies, live_start and handoff beside menu. Schema and Python reader accept exactly those, and the 35 plans from #314 are fixtures for both. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss --- data/story/frlg-authored/frlg-00.01.plan.json | 31 ++ .../story/frlg-authored/frlg-00.01b.plan.json | 33 ++ data/story/frlg-authored/frlg-00.02.plan.json | 24 ++ data/story/frlg-authored/frlg-00.03.plan.json | 39 ++ data/story/frlg-authored/frlg-00.04.plan.json | 27 ++ .../story/frlg-authored/frlg-00.04b.plan.json | 68 ++++ data/story/frlg-authored/frlg-00.06.plan.json | 35 ++ data/story/frlg-authored/frlg-00.07.plan.json | 101 +++++ data/story/frlg-authored/frlg-00.08.plan.json | 78 ++++ data/story/frlg-authored/frlg-00.09.plan.json | 74 ++++ data/story/frlg-authored/frlg-00.10.plan.json | 51 +++ data/story/frlg-authored/frlg-00.11.plan.json | 128 +++++++ data/story/frlg-authored/frlg-00.12.plan.json | 43 +++ .../story/frlg-authored/frlg-00.12b.plan.json | 28 ++ .../story/frlg-authored/frlg-00.12c.plan.json | 34 ++ data/story/frlg-authored/frlg-00.13.plan.json | 189 ++++++++++ data/story/frlg-authored/frlg-00.14.plan.json | 96 +++++ .../story/frlg-authored/frlg-00.14b.plan.json | 96 +++++ .../story/frlg-authored/frlg-00.14c.plan.json | 71 ++++ data/story/frlg-authored/frlg-00.15.plan.json | 93 +++++ .../story/frlg-authored/frlg-00.15b.plan.json | 40 ++ data/story/frlg-authored/frlg-00.16.plan.json | 173 +++++++++ data/story/frlg-authored/frlg-00.17.plan.json | 146 +++++++ data/story/frlg-authored/frlg-00.18.plan.json | 112 ++++++ data/story/frlg-authored/frlg-00.19.plan.json | 47 +++ data/story/frlg-authored/frlg-00.20.plan.json | 75 ++++ data/story/frlg-authored/frlg-00.21.plan.json | 94 +++++ data/story/frlg-authored/frlg-00.22.plan.json | 160 ++++++++ data/story/frlg-authored/frlg-00.23.plan.json | 178 +++++++++ data/story/frlg-authored/frlg-00.24.plan.json | 115 ++++++ data/story/frlg-authored/frlg-00.25.plan.json | 72 ++++ data/story/frlg-authored/frlg-00.26.plan.json | 156 ++++++++ data/story/frlg-authored/frlg-00.27.plan.json | 202 ++++++++++ data/story/frlg-authored/frlg-00.28.plan.json | 355 ++++++++++++++++++ data/story/frlg-authored/frlg-00.29.plan.json | 70 ++++ schemas/README.md | 2 +- schemas/authored-checkpoint.schema.json | 19 +- schemas/story-checkpoint.schema.json | 23 +- src/pokesim/formats/json_schema.py | 2 + src/pokesim/formats/test_json_schema.py | 56 +++ src/pokesim/story/authored_checkpoint.py | 28 +- src/pokesim/story/checkpoint_wire.py | 45 ++- src/pokesim/story/test_authored_checkpoint.py | 2 +- 43 files changed, 3496 insertions(+), 15 deletions(-) create mode 100644 data/story/frlg-authored/frlg-00.01.plan.json create mode 100644 data/story/frlg-authored/frlg-00.01b.plan.json create mode 100644 data/story/frlg-authored/frlg-00.02.plan.json create mode 100644 data/story/frlg-authored/frlg-00.03.plan.json create mode 100644 data/story/frlg-authored/frlg-00.04.plan.json create mode 100644 data/story/frlg-authored/frlg-00.04b.plan.json create mode 100644 data/story/frlg-authored/frlg-00.06.plan.json create mode 100644 data/story/frlg-authored/frlg-00.07.plan.json create mode 100644 data/story/frlg-authored/frlg-00.08.plan.json create mode 100644 data/story/frlg-authored/frlg-00.09.plan.json create mode 100644 data/story/frlg-authored/frlg-00.10.plan.json create mode 100644 data/story/frlg-authored/frlg-00.11.plan.json create mode 100644 data/story/frlg-authored/frlg-00.12.plan.json create mode 100644 data/story/frlg-authored/frlg-00.12b.plan.json create mode 100644 data/story/frlg-authored/frlg-00.12c.plan.json create mode 100644 data/story/frlg-authored/frlg-00.13.plan.json create mode 100644 data/story/frlg-authored/frlg-00.14.plan.json create mode 100644 data/story/frlg-authored/frlg-00.14b.plan.json create mode 100644 data/story/frlg-authored/frlg-00.14c.plan.json create mode 100644 data/story/frlg-authored/frlg-00.15.plan.json create mode 100644 data/story/frlg-authored/frlg-00.15b.plan.json create mode 100644 data/story/frlg-authored/frlg-00.16.plan.json create mode 100644 data/story/frlg-authored/frlg-00.17.plan.json create mode 100644 data/story/frlg-authored/frlg-00.18.plan.json create mode 100644 data/story/frlg-authored/frlg-00.19.plan.json create mode 100644 data/story/frlg-authored/frlg-00.20.plan.json create mode 100644 data/story/frlg-authored/frlg-00.21.plan.json create mode 100644 data/story/frlg-authored/frlg-00.22.plan.json create mode 100644 data/story/frlg-authored/frlg-00.23.plan.json create mode 100644 data/story/frlg-authored/frlg-00.24.plan.json create mode 100644 data/story/frlg-authored/frlg-00.25.plan.json create mode 100644 data/story/frlg-authored/frlg-00.26.plan.json create mode 100644 data/story/frlg-authored/frlg-00.27.plan.json create mode 100644 data/story/frlg-authored/frlg-00.28.plan.json create mode 100644 data/story/frlg-authored/frlg-00.29.plan.json diff --git a/data/story/frlg-authored/frlg-00.01.plan.json b/data/story/frlg-authored/frlg-00.01.plan.json new file mode 100644 index 0000000..f265a76 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.01.plan.json @@ -0,0 +1,31 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.01", + "title": "new game to the bedroom", + "sections": [ + { + "id": "new_game", + "title": "Title screen to the bedroom", + "events": [ + { + "id": "intro", + "kind": "new_game", + "declared_after": {"certainty": "tile", "map": "PalletTown_PlayersHouse_2F", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "why": "Oak's speech, BOY, the player's name (default if none is set), rival GREEN", + "notes": [ + "new_game.c: the bedroom at (6, 6), facing the TV." + ] + }, + { + "id": "options", + "kind": "options", + "why": "fast text; no switch prompt between a trainer's Pokemon" + } + ] + } + ] + }, + "execution": {"handoff": "sid_helper", "menu": "before_pokemon"} +} diff --git a/data/story/frlg-authored/frlg-00.01b.plan.json b/data/story/frlg-authored/frlg-00.01b.plan.json new file mode 100644 index 0000000..bbf99b4 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.01b.plan.json @@ -0,0 +1,33 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.01b", + "title": "after SID Helper: close the Trainer Card, save in the bedroom", + "notes": [ + "SID Helper confirms the name, finishes the intro and reads the Trainer Card from the START menu, without moving the player or saving." + ], + "start": {"certainty": "tile", "map": "PalletTown_PlayersHouse_2F", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "sections": [ + { + "id": "bedroom", + "title": "Back from SID Helper in the bedroom", + "events": [ + { + "id": "close_trainer_card", + "kind": "game_action", + "variant": "close_trainer_card", + "declared_after": {"certainty": "tile", "map": "PalletTown_PlayersHouse_2F", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "why": "the Trainer Card SID Helper left open, or HOME" + }, + { + "id": "options", + "kind": "options", + "why": "fast text; no switch prompt between a trainer's Pokemon" + } + ] + } + ] + }, + "execution": {"live_start": true, "menu": "before_pokemon"} +} diff --git a/data/story/frlg-authored/frlg-00.02.plan.json b/data/story/frlg-authored/frlg-00.02.plan.json new file mode 100644 index 0000000..24d0869 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.02.plan.json @@ -0,0 +1,24 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.02", + "title": "bedroom to Pallet Town", + "start": {"certainty": "tile", "map": "PalletTown_PlayersHouse_2F", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "sections": [ + { + "id": "players_house", + "title": "Down the stairs and out", + "events": [ + { + "id": "front_door", + "kind": "route", + "target": {"certainty": "tile", "map": "PalletTown", "where": {"kind": "tiles", "tiles": [[6, 8]]}}, + "why": "down the stairs and out of the house" + } + ] + } + ] + }, + "execution": {"menu": "before_pokemon"} +} diff --git a/data/story/frlg-authored/frlg-00.03.plan.json b/data/story/frlg-authored/frlg-00.03.plan.json new file mode 100644 index 0000000..a357eec --- /dev/null +++ b/data/story/frlg-authored/frlg-00.03.plan.json @@ -0,0 +1,39 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.03", + "title": "Oak stops the player and walks them to the lab", + "start": {"certainty": "tile", "map": "PalletTown", "where": {"facing": "south", "kind": "tiles", "tiles": [[6, 8]]}}, + "sections": [ + { + "id": "pallet_north", + "title": "Pallet Town's north exit to Oak's lab", + "events": [ + { + "id": "below_oaks_trigger", + "kind": "route", + "target": {"certainty": "tile", "map": "PalletTown", "where": {"facing": "north", "kind": "tiles", "tiles": [[12, 2]]}}, + "why": "below the north exit, short of Oak's trigger at (12, 1)" + }, + { + "id": "oaks_trigger", + "kind": "step", + "direction": "north", + "why": "the trigger: \"Don't go out!\"" + }, + { + "id": "to_the_lab", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 4]]}}, + "why": "Oak walks the player into the lab; the scene ends at the table", + "notes": [ + "PlayerEnter walks the player up 8 tiles from the lab's door." + ] + } + ] + } + ] + }, + "execution": {"menu": "before_pokemon"} +} diff --git a/data/story/frlg-authored/frlg-00.04.plan.json b/data/story/frlg-authored/frlg-00.04.plan.json new file mode 100644 index 0000000..59ff443 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.04.plan.json @@ -0,0 +1,27 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.04", + "title": "to Squirtle's ball, south of the table", + "notes": [ + "Starter RNG starts from a save south of the table, facing the ball." + ], + "start": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 4]]}}, + "sections": [ + { + "id": "lab_table", + "title": "Oak's lab, below Squirtle's ball", + "events": [ + { + "id": "below_squirtle", + "kind": "route", + "target": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[9, 5]]}}, + "why": "under Squirtle's ball (9, 4)" + } + ] + } + ] + }, + "execution": {"handoff": "starter_rng", "menu": "before_pokemon"} +} diff --git a/data/story/frlg-authored/frlg-00.04b.plan.json b/data/story/frlg-authored/frlg-00.04b.plan.json new file mode 100644 index 0000000..84f39b5 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.04b.plan.json @@ -0,0 +1,68 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.04b", + "title": "Squirtle, then the rival's battle", + "start": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[9, 5]]}}, + "sections": [ + { + "id": "starter", + "title": "Squirtle from the table", + "events": [ + { + "id": "squirtle_ball", + "kind": "talk", + "why": "\"So, you want the WATER POKEMON SQUIRTLE?\"" + }, + { + "id": "choose_squirtle", + "kind": "answer", + "why": "take Squirtle" + }, + { + "id": "no_nickname", + "kind": "answer", + "yes": false, + "why": "\"give a nickname?\" NO" + }, + { + "id": "rival_takes_bulbasaur", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[9, 5]]}}, + "why": "the rival picks his ball; the player still faces the table (console B, 2026-11-01)" + } + ] + }, + { + "id": "rival_lab", + "title": "The rival's first battle", + "events": [ + { + "id": "above_rival_trigger", + "kind": "route", + "target": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "south", "kind": "tiles", "tiles": [[7, 7]]}}, + "why": "short of the rival's trigger row 8" + }, + { + "id": "rival_trigger", + "kind": "step", + "direction": "south", + "why": "\"Wait, let's check out our POKEMON!\"" + }, + { + "id": "rival_battle", + "kind": "battle", + "may_lose": true, + "declared_after": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "south", "kind": "tiles", "tiles": [[7, 8]]}}, + "why": "the tutorial battle; losing goes on too", + "notes": [ + "The rival leaves; PlayerWatchRivalExitAfterBattleRight ends facing down." + ] + } + ] + } + ] + }, + "execution": {"menu": "before_pokedex"} +} diff --git a/data/story/frlg-authored/frlg-00.06.plan.json b/data/story/frlg-authored/frlg-00.06.plan.json new file mode 100644 index 0000000..7eac3e3 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.06.plan.json @@ -0,0 +1,35 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.06", + "title": "Oak's Parcel to the Pokedex", + "start": {"certainty": "tile", "map": "ViridianCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "sections": [ + { + "id": "route1_to_oak", + "title": "Route 1 back to Oak", + "events": [ + { + "id": "below_oak", + "kind": "route", + "target": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 4]]}}, + "why": "back down Route 1 to Oak" + }, + { + "id": "give_parcel", + "kind": "talk", + "why": "Oak takes the parcel" + }, + { + "id": "pokedex_scene", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "south", "kind": "tiles", "tiles": [[6, 4]]}}, + "why": "the rival comes in, Pokedexes from the desk; the player ends facing south (console B, 2026-11-01)" + } + ] + } + ] + }, + "execution": {"menu": "full"} +} diff --git a/data/story/frlg-authored/frlg-00.07.plan.json b/data/story/frlg-authored/frlg-00.07.plan.json new file mode 100644 index 0000000..dd1d5f4 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.07.plan.json @@ -0,0 +1,101 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.07", + "title": "Viridian shopping, then into Viridian Forest", + "start": {"certainty": "tile", "map": "PalletTown_ProfessorOaksLab", "where": {"facing": "south", "kind": "tiles", "tiles": [[6, 4]]}}, + "sections": [ + { + "id": "viridian_mart", + "title": "Viridian Mart", + "events": [ + { + "id": "mart_clerk", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "why": "Route 1 again" + }, + { + "id": "potions_and_antidotes", + "kind": "shop", + "items": [{"item": "potion", "quantity": 5}, {"item": "antidote", "quantity": 3}, {"item": "parlyz_heal", "quantity": 1}], + "why": "5 Potions, 3 Antidotes, 1 Parlyz Heal", + "notes": [ + "2000 of the 3000 a new game starts with, plus the rival's prize." + ] + } + ] + }, + { + "id": "viridian_center", + "title": "Viridian's Pokemon Center", + "events": [ + { + "id": "viridian_nurse", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "heal before the forest" + }, + { + "id": "heal_viridian", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "old_man", + "title": "The old man's catching tutorial", + "events": [ + { + "id": "below_old_man_trigger", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[20, 9]]}}, + "why": "short of the tutorial trigger (20, 8)" + }, + { + "id": "old_man_trigger", + "kind": "step", + "direction": "north", + "why": "the old man's catching tutorial can't be walked around" + }, + { + "id": "old_man_tutorial", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "ViridianCity", "where": {"facing": "east", "kind": "tiles", "tiles": [[20, 8]]}}, + "why": "about 60 lines and his demo battle; TEACHY TV", + "notes": [ + "TutorialTriggerLeft turns the player right, to the old man." + ] + }, + { + "id": "past_old_man", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[20, 5]]}}, + "why": "north along column 20, clear of the old man", + "notes": [ + "After his demo the old man stands east of the player, beside (20, 8), where the map doesn't have him: \"east 2\" from there didn't move, and the walk north ended under Route 2's ledge in column 8 (console B, 2026-11-01). Go north first." + ] + } + ] + }, + { + "id": "route2", + "title": "Route 2 to Viridian Forest", + "events": [ + { + "id": "forest_entrance", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianForest", "where": {"facing": "north", "kind": "tiles", "tiles": [[29, 62]]}}, + "why": "Route 2 and the south gate, running from wild battles", + "notes": [ + "The gate's north warp lands on the forest's exit mat (29, 62), facing north. The save there keeps a forest failure from going back to Pallet." + ] + } + ] + } + ] + }, + "execution": {"menu": "full"} +} diff --git a/data/story/frlg-authored/frlg-00.08.plan.json b/data/story/frlg-authored/frlg-00.08.plan.json new file mode 100644 index 0000000..3f348ba --- /dev/null +++ b/data/story/frlg-authored/frlg-00.08.plan.json @@ -0,0 +1,78 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.08", + "title": "Viridian Forest to Pewter Center", + "notes": [ + "The supplies bought in 00.07." + ], + "start": {"certainty": "tile", "map": "ViridianForest", "where": {"facing": "north", "kind": "tiles", "tiles": [[29, 62]]}}, + "sections": [ + { + "id": "viridian_forest", + "title": "Viridian Forest, fighting wild battles", + "events": [ + { + "id": "forest_east", + "kind": "legs", + "legs": [{"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 4}, {"direction": "east", "tiles": 14}, {"direction": "north", "tiles": 15}], + "fight_wild": true, + "why": "up the east side to (44, 43)", + "notes": [ + "Wild battles are fought for EXP. Straight up the east side from the entrance, each leg ending on a wall (the Boy at (45, 58) stops the east one). Rick (47, 45) sees (42..46, 45), so the last leg meets his battle and is held on to its wall after it. The by-hand run's detour west to (13, 46) and back is dropped." + ] + }, + { + "id": "forest_north", + "kind": "route", + "target": {"certainty": "tile", "map": "ViridianForest", "where": {"kind": "tiles", "tiles": [[39, 25]]}}, + "fight_wild": true, + "why": "north part" + }, + { + "id": "forest_exit", + "kind": "legs", + "legs": [ + {"direction": "north", "tiles": 10}, {"direction": "west", "tiles": 12}, {"direction": "south", "tiles": 10}, {"direction": "west", "tiles": 6}, {"direction": "north", "tiles": 20}, {"direction": "south", "tiles": 1}, + {"direction": "west", "tiles": 10}, {"direction": "south", "tiles": 27}, {"direction": "west", "tiles": 8}, {"direction": "north", "tiles": 20}, {"direction": "east", "tiles": 1} + ], + "fight_wild": true, + "why": "walls all the way to the gate's column", + "notes": [ + "To the gate by legs that end on walls, which the walker holds again after a battle instead of estimating where it stopped: planned routes with open legs lost the player in the north of the forest (console B, 2026-11-01). The two 1-tile legs are single steps." + ] + }, + { + "id": "forest_gate", + "kind": "route", + "target": {"certainty": "tile", "map": "Route2_ViridianForest_NorthEntrance", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 10]]}}, + "fight_wild": true, + "why": "north onto the exit, arriving on the gate's mat" + } + ] + }, + { + "id": "pewter_center", + "title": "Route 2 north to Pewter's Pokemon Center", + "events": [ + { + "id": "pewter_nurse", + "kind": "route", + "target": {"certainty": "tile", "map": "PewterCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "Route 2 north to Pewter's Center", + "notes": [ + "Out of the forest, wild battles are run from; trainers are still fought." + ] + }, + { + "id": "heal_pewter", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"antidotes": 3, "parlyz_heals": 1, "potions": 5}} +} diff --git a/data/story/frlg-authored/frlg-00.09.plan.json b/data/story/frlg-authored/frlg-00.09.plan.json new file mode 100644 index 0000000..bbd9768 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.09.plan.json @@ -0,0 +1,74 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.09", + "title": "Pewter Gym: Camper Liam, then Brock", + "notes": [ + "The by-hand save: 2 Potions and 1 Antidote left after the forest." + ], + "start": {"certainty": "tile", "map": "PewterCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "camper_liam", + "title": "Pewter Gym: Camper Liam", + "events": [ + { + "id": "below_liam_line", + "kind": "route", + "target": {"certainty": "tile", "map": "PewterCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 9]]}}, + "why": "in by the door, up column 6 to below Liam's row", + "notes": [ + "Camper Liam (3, 8) always faces east (MOVEMENT_TYPE_FACE_RIGHT, sight 4) and sees (4..7, 8): walking north up column 6 from the door, the step onto (6, 8) starts his battle. He walks up to the player, who stays put and keeps facing north (FRLG doesn't turn the player to a trainer). That step is taken on its own, so no leg is cut." + ] + }, + { + "id": "liam_line", + "kind": "step", + "direction": "north", + "why": "onto (6, 8), in Liam's line" + }, + { + "id": "camper_liam", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "PewterCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 8]]}}, + "why": "Geodude and Sandshrew; EXP before Brock" + } + ] + }, + { + "id": "brock", + "title": "Pewter Gym: Brock", + "events": [ + { + "id": "ready_for_brock", + "kind": "ready", + "target": {"certainty": "tile", "map": "PewterCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "items for a status or low HP; the nurse only if they can't", + "notes": [ + "On to Brock unless red HP or a status is left that no item cures." + ] + }, + { + "id": "before_brock", + "kind": "route", + "target": {"certainty": "tile", "map": "PewterCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "why": "below Brock (6, 5); Liam, beaten, stands at (5, 8)" + }, + { + "id": "challenge_brock", + "kind": "talk", + "why": "Brock's speech" + }, + { + "id": "brock", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "PewterCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "why": "Geodude and Onix, with Bubble; Boulder Badge and TM39" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"antidotes": 1, "potions": 2}} +} diff --git a/data/story/frlg-authored/frlg-00.10.plan.json b/data/story/frlg-authored/frlg-00.10.plan.json new file mode 100644 index 0000000..05fd3c2 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.10.plan.json @@ -0,0 +1,51 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.10", + "title": "Pewter: the Running Shoes from Oak's aide", + "start": {"certainty": "tile", "map": "PewterCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[6, 6]]}}, + "sections": [ + { + "id": "pewter_aide", + "title": "Pewter City: Oak's aide and the Running Shoes", + "events": [ + { + "id": "before_aide_trigger", + "kind": "route", + "target": {"certainty": "tile", "map": "PewterCity", "where": {"facing": "east", "kind": "tiles", "tiles": [[45, 21]]}}, + "why": "out of the Gym, east along row 21, short of the top trigger", + "notes": [ + "Brock's win sets VAR_MAP_SCENE_PEWTER_CITY to 1 and shows the aide at (46, 20); his triggers are (46, 21..23) (PewterCity map.json). The Gym guide's triggers at (42..43, 21..23) need the scene at 0." + ] + }, + { + "id": "aide_trigger", + "kind": "step", + "direction": "east", + "why": "onto (46, 21), below the aide" + }, + { + "id": "shoes_from_aide", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "PewterCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[46, 21]]}}, + "why": "\"Oh, PLAYER!\" ... the Running Shoes; ends facing north", + "notes": [ + "RunningShoesAideTriggerTop: the aide talks from (46, 20), no YES/NO; the player only turns up. He walks off and is removed; FLAG_SYS_B_DASH is set (console B, 2026-11-02: about 20 B presses to the overworld)." + ] + }, + { + "id": "below_pewter_center", + "kind": "route", + "target": {"certainty": "tile", "map": "PewterCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[17, 26]]}}, + "why": "west along row 21 and down to below the Pokemon Center's door (17, 25)", + "notes": [ + "Where the by-hand walk stopped to start 00.11 (console B, 2026-11-02)." + ] + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.11.plan.json b/data/story/frlg-authored/frlg-00.11.plan.json new file mode 100644 index 0000000..e1a2022 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.11.plan.json @@ -0,0 +1,128 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.11", + "title": "Pewter Center, then Route 3's trainers", + "notes": [ + "Route 3's trainers (Route3 map.json): the way east meets three of them. Bug Catcher Colton (12, 6) faces east, sight 3: the only way north past the row 7 ledges is the gap at x 14..15, below his line. Youngster Ben (17, 4) faces south, sight 2, so the way east keeps to row 3 past him. Bug Catcher Greg (25, 4) faces south, sight 2, over the way east along row 5. Bug Catcher James (32, 6) faces east, sight 4, over the way down at x 35..36. The others are kept out of: Lass Janice (19, 9) sees west along row 9 to x 14, Lass Sally (30, 3) west along row 3 to x 25, and Youngster Calvin (29, 10) west along row 10. Each line is stepped into on its own, so no leg is cut; the trainer walks up to the player, who stays put facing the way they stepped." + ], + "start": {"certainty": "tile", "map": "PewterCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[17, 26]]}}, + "sections": [ + { + "id": "pewter_center", + "title": "Pewter's Pokemon Center", + "events": [ + { + "id": "pewter_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "PewterCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "in by the door below the player" + }, + { + "id": "heal_pewter", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "route3_colton", + "title": "Route 3 west: Bug Catcher Colton", + "events": [ + { + "id": "west_of_janice_line", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route3", "where": {"kind": "tiles", "tiles": [[13, 8]]}}, + "why": "out of Pewter by row 21, east into Route 3, short of Janice's line", + "notes": [ + "Up from row 9 west of Janice's line, which ends at x 14." + ] + }, + { + "id": "below_colton_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 1}], + "why": "to (14, 7), in the ledges' gap" + }, + { + "id": "colton_line", + "kind": "step", + "direction": "north", + "why": "onto (14, 6), in Colton's line" + }, + { + "id": "bug_catcher_colton", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route3", "where": {"facing": "north", "kind": "tiles", "tiles": [[14, 6]]}}, + "why": "his Bug Pokemon; Colton stops at (13, 6)" + } + ] + }, + { + "id": "route3_greg", + "title": "Route 3 middle: past Ben to Bug Catcher Greg", + "events": [ + { + "id": "past_ben", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 3}, {"direction": "east", "tiles": 4}, {"direction": "south", "tiles": 2}, {"direction": "east", "tiles": 6}], + "why": "up to row 3 above Ben, down at x 18 east of his line, to (24, 5)" + }, + { + "id": "greg_line", + "kind": "step", + "direction": "east", + "why": "onto (25, 5), below Greg" + }, + { + "id": "bug_catcher_greg", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route3", "where": {"facing": "east", "kind": "tiles", "tiles": [[25, 5]]}}, + "why": "his Bug Pokemon; Greg is already next to the player" + } + ] + }, + { + "id": "route3_james", + "title": "Route 3 east: Bug Catcher James and the save spot", + "events": [ + { + "id": "above_james_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 11}], + "why": "along row 5 to the wall at (36, 5)" + }, + { + "id": "james_line", + "kind": "step", + "direction": "south", + "why": "onto (36, 6), at the end of James's line" + }, + { + "id": "bug_catcher_james", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route3", "where": {"facing": "south", "kind": "tiles", "tiles": [[36, 6]]}}, + "why": "his Bug Pokemon; James stops at (35, 6)" + }, + { + "id": "save_spot", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 2}], + "why": "down to (36, 8), beside the wall east of it", + "notes": [ + "Saved here, the trainers behind, so a failure on the way to Route 4 doesn't fight them again." + ] + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.12.plan.json b/data/story/frlg-authored/frlg-00.12.plan.json new file mode 100644 index 0000000..48e1acb --- /dev/null +++ b/data/story/frlg-authored/frlg-00.12.plan.json @@ -0,0 +1,43 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.12", + "title": "Route 3 and 4 to the Magikarp salesman", + "notes": [ + "Route 3's north exit (x 68..75) joins Route 4 (offset 60) at x 8..15, up which column 12 leads to the Pokemon Center's door (12, 5). Lass Robin (40, 11) wanders up and down at x 40, looking north and south, sight 3. Rock above (y <= 8) and grass below (y >= 12) leave every way east across her column at y 9..11, so whether she sees the player depends on her facing. The walk watches for her after the leg along row 9, which crosses her sight on (40, 9) only; if she saw the player, her message goes to story_interrupts(), which fight her, and the route goes on from (40, 9) (run_route(); console B, 2026-11-02, she stopped the player there and spoke after the leg's short watch)." + ], + "start": {"certainty": "tile", "map": "Route3", "where": {"facing": "south", "kind": "tiles", "tiles": [[36, 8]]}}, + "sections": [ + { + "id": "route4_center", + "title": "Route 3 and 4 to the Magikarp salesman", + "events": [ + { + "id": "route4_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "east over Route 3, off the grass, north into Route 4 and its Pokemon Center" + }, + { + "id": "heal_route4", + "kind": "heal", + "why": "full HP" + }, + { + "id": "before_salesman", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "west", "kind": "tiles", "tiles": [[2, 3]]}}, + "why": "beside the Magikarp salesman, facing him", + "notes": [ + "Gift RNG starts from a save facing the salesman (1, 3)." + ] + } + ] + } + ] + }, + "execution": {"handoff": "gift_rng", "menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.12b.plan.json b/data/story/frlg-authored/frlg-00.12b.plan.json new file mode 100644 index 0000000..005365f --- /dev/null +++ b/data/story/frlg-authored/frlg-00.12b.plan.json @@ -0,0 +1,28 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.12b", + "title": "after Gift RNG: save with the Magikarp", + "notes": [ + "Gift RNG buys the Magikarp (500 of the money 00.12 brings) without moving the player and leaves its summary open, or HOME. This saves the shiny where 00.12 ended. A run started here with Gift RNG's handoff on loads the save beside the salesman and runs Gift RNG first." + ], + "start": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "west", "kind": "tiles", "tiles": [[2, 3]]}}, + "sections": [ + { + "id": "route4_center", + "title": "Back from Gift RNG beside the salesman", + "events": [ + { + "id": "leave_gift_summary", + "kind": "game_action", + "variant": "leave_gift_summary", + "declared_after": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "west", "kind": "tiles", "tiles": [[2, 3]]}}, + "why": "the Magikarp's summary Gift RNG left open, or HOME" + } + ] + } + ] + }, + "execution": {"live_start": true, "menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.12c.plan.json b/data/story/frlg-authored/frlg-00.12c.plan.json new file mode 100644 index 0000000..0c547fa --- /dev/null +++ b/data/story/frlg-authored/frlg-00.12c.plan.json @@ -0,0 +1,34 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.12c", + "title": "Route 4 Center: the Magikarp into BOX 1", + "notes": [ + "The Magikarp goes to BOX 1 at the Center's PC (11, 1), so Mt. Moon is fought with the starter alone (console B, 2026-11-02: done by hand and saved at (11, 2), facing the PC, where this row ends). The wandering boy (4..6, 3..5) is walked around. The Magikarp comes from Gift RNG: with Gift RNG off the party is the starter alone, and the deposit is skipped." + ], + "start": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "west", "kind": "tiles", "tiles": [[2, 3]]}}, + "sections": [ + { + "id": "route4_center_pc", + "title": "Route 4's Pokemon Center PC", + "events": [ + { + "id": "pc_front", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 2]]}}, + "why": "below the PC (11, 1), facing it" + }, + { + "id": "magikarp_to_box", + "kind": "game_action", + "variant": "pc deposit slot=2 box=1 if_present", + "why": "DEPOSIT the party's second slot into BOX 1, if it has one" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.13.plan.json b/data/story/frlg-authored/frlg-00.13.plan.json new file mode 100644 index 0000000..4f9d2e6 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.13.plan.json @@ -0,0 +1,189 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.13", + "title": "Mt. Moon: a Moon Stone, a Rocket, Miguel and the Helix Fossil", + "notes": [ + "Mt. Moon (pokefirered data/maps/MtMoon_1F, _B1F, _B2F). Every floor tile of the cave has wild encounters, which are run from, so its legs end on walls, ladders or someone standing still, which the walker holds again after a battle; the few open ones are short. The way through: up 1F's middle and west side, its north-west ladder, B1F's west ladder down to B2F's south-east, round B2F's south edge to its west, north past Miguel and the fossils, and the ladder up to B1F's east end, which leads out to Route 4 east of the mountain.", + "- 1F's trainers are walked around: Youngster Josh (13, 17) sees east along row 17 to x 17, so the way west into the west room is down column 18 and up column 11; Lass Miriam walks round (32..33, 4..5), sight 2, so the way east keeps to row 9 and columns 38 and 40; Hiker Marcos wanders (5..9, 8..12) and sees one tile, so the way north is column 11 and row 3.", + "- The Moon Stone ball (3, 2) on 1F (FLAG_HIDE_MT_MOON_1F_MOON_STONE) is a few tiles off the way to the ladder (5, 6).", + "- The Grunt at (37, 21) on B2F looks around (sight 3) over the only way east round B2F. His room is crossed on legs to walls, at one tile of his sight each, (37, 22) and (40, 21); if he looks the player's way, he walks up beside the leg, story_interrupts() fights him, and the leg is held on to its wall.", + "- The Grunt at (12, 20) faces south (sight 2) over (12, 21..22), across rows 21..22, the only way north to Miguel: stepped into from the west, he is next to the player and doesn't walk.", + "- Super Nerd Miguel (13, 11) battles on the step onto (14, 11) (MtMoon_B2F_EventScript_MiguelTrigger, VAR_MAP_SCENE_MT_MOON_B2F 0), then \"We'll each take one!\"", + "- The fossils: DOME (13, 7), HELIX (14, 7). After the HELIX, Miguel walks up to (13, 8) and takes the DOME, which opens the gap north. The save is on Route 4: the save card's places don't include Mt. Moon." + ], + "start": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 2]]}}, + "sections": [ + { + "id": "route4_center", + "title": "Route 4's Pokemon Center", + "events": [ + { + "id": "route4_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "the nurse, below the counter" + }, + { + "id": "heal_route4", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "mt_moon_1f", + "title": "Mt. Moon 1F and the Moon Stone", + "events": [ + { + "id": "mt_moon_entrance", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "MtMoon_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[18, 37]]}}, + "why": "out of the Center, west into Mt. Moon" + }, + { + "id": "mt_moon_1f", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "north", "tiles": 12}, {"direction": "east", "tiles": 8}, {"direction": "north", "tiles": 12}, {"direction": "east", "tiles": 3}, {"direction": "south", "tiles": 1}, {"direction": "east", "tiles": 9}, + {"direction": "north", "tiles": 1}, {"direction": "east", "tiles": 2}, {"direction": "north", "tiles": 4}, {"direction": "west", "tiles": 24}, {"direction": "east", "tiles": 2}, {"direction": "south", "tiles": 12}, + {"direction": "west", "tiles": 7}, {"direction": "north", "tiles": 18}, {"direction": "west", "tiles": 9}, {"direction": "east", "tiles": 1} + ], + "why": "up the middle, east of Miriam, west along row 9, down column 18 past Josh, up column 11 past Marcos, to (3, 3)" + }, + { + "id": "below_moon_stone", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "MtMoon_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[3, 3]]}}, + "why": "facing the Moon Stone (3, 2)" + }, + { + "id": "moon_stone_ball", + "kind": "talk", + "why": "A on the item ball" + }, + { + "id": "found_moon_stone", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "MtMoon_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[3, 3]]}}, + "why": "\" found a MOON STONE!\", then the pocket line; the ball is gone", + "notes": [ + "No reader for the text yet: the scene's end is the overworld." + ] + } + ] + }, + { + "id": "mt_moon_b2f_grunt", + "title": "Mt. Moon B2F: round the south edge to the Grunt", + "events": [ + { + "id": "b2f_ladder_foot", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "MtMoon_B2F", "where": {"facing": "east", "kind": "tiles", "tiles": [[26, 21]]}}, + "why": "1F's ladder (5, 6), down B1F's west side to its ladder (22, 18), onto B2F" + }, + { + "id": "b2f_south", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "north", "tiles": 4}, {"direction": "east", "tiles": 8}, {"direction": "west", "tiles": 2}, {"direction": "south", "tiles": 5}, {"direction": "east", "tiles": 8}, {"direction": "north", "tiles": 3}, + {"direction": "west", "tiles": 1}, {"direction": "north", "tiles": 5}, {"direction": "east", "tiles": 7}, {"direction": "south", "tiles": 14}, {"direction": "west", "tiles": 9}, {"direction": "south", "tiles": 10}, + {"direction": "west", "tiles": 29}, {"direction": "east", "tiles": 3}, {"direction": "north", "tiles": 17} + ], + "why": "through the Grunt's room at (37, 21), round the south edge, up column 11 to (11, 21)" + }, + { + "id": "grunt_line", + "kind": "step", + "direction": "east", + "why": "onto (12, 21), below the Grunt at (12, 20)" + }, + { + "id": "rocket_grunt", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "MtMoon_B2F", "where": {"facing": "east", "kind": "tiles", "tiles": [[12, 21]]}}, + "why": "Rattata and Zubat, Lv13" + } + ] + }, + { + "id": "mt_moon_b2f_miguel", + "title": "Mt. Moon B2F: Miguel and the Helix Fossil", + "events": [ + { + "id": "ready_for_miguel", + "kind": "ready", + "target": {"certainty": "tile", "map": "Route4_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "items for a status or low HP; the nurse, back through the cave, only if they can't" + }, + { + "id": "below_miguel_trigger", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 9}, {"direction": "east", "tiles": 1}], + "why": "to (14, 12), below Miguel's trigger (14, 11)", + "notes": [ + "Up column 13 to Miguel, who stops the leg on (13, 12), then east to the wall: the tile below his trigger." + ] + }, + { + "id": "miguel_trigger", + "kind": "step", + "direction": "north", + "why": "onto (14, 11), beside Miguel" + }, + { + "id": "super_nerd_miguel", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "MtMoon_B2F", "where": {"facing": "north", "kind": "tiles", "tiles": [[14, 11]]}}, + "why": "Grimer, Voltorb and Koffing, Lv12; \"We'll each take one!\"" + }, + { + "id": "below_helix_fossil", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 3}], + "why": "up column 14 to the HELIX FOSSIL (14, 7)" + }, + { + "id": "helix_fossil", + "kind": "game_action", + "variant": "fossil helix", + "why": "the HELIX FOSSIL; Miguel takes the DOME FOSSIL" + }, + { + "id": "helix_gap", + "kind": "step", + "direction": "north", + "why": "onto (14, 7), where the HELIX FOSSIL lay", + "notes": [ + "The maps keep the fossils, which the game removes after the choice: the step onto the HELIX's tile is taken on its own." + ] + } + ] + }, + { + "id": "mt_moon_exit", + "title": "B1F's east exit onto Route 4", + "events": [ + { + "id": "route4_east", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4", "where": {"facing": "south", "kind": "tiles", "tiles": [[32, 6]]}}, + "why": "west to B2F's ladder (5, 10), up to B1F, east to its exit onto Route 4" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.14.plan.json b/data/story/frlg-authored/frlg-00.14.plan.json new file mode 100644 index 0000000..a2d5804 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.14.plan.json @@ -0,0 +1,96 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.14", + "title": "Route 4: Mega Kick from its tutor, then east to Cerulean's Pokemon Center", + "notes": [ + "Route 4 east of Mt. Moon (Route4 map.json) joins Cerulean City at its east end (x 107; Route 4's row 3 is the city's row 13). Its upper road (rows 2..8) reaches the city only by water: the way on by land is down the ledge row 9 at x 90..96 to the lower road (rows 10..12), which joins the city's rows 20..22. Lass Crissy (75, 3) faces east, sight 4, over row 3 from x 76 to 79; the way east keeps out of her line and off the grass south of the road (75..87, 11..17).", + "On the way, the Mega Kick tutor (Black Belt (50, 3), facing west, Route4_EventScript_MegaKickTutor) stands in a pen (46..51, 2..4) north of the road, beside the Mega Punch tutor (47, 3); the pen opens south only on (48, 5) and (49, 5), the rest of row 5 ledges out of it. From Mt. Moon's exit the walk goes east and up into the pen to (50, 4), below the tutor, and Mega Kick takes Withdraw's slot. Cerulean can't be walked back to Route 4's upper road without Surf, so it is now or much later.", + "The open leg east across the city's edge ended a tile short on the console (2026-11-03: on (6, 20), not (7, 20)), and no hold to a wall in the city's west end finds the player from there: the next hold south met the fence on (6, 23) and the walk went on a column off. So the entry ends on (9, 20), and only legs to walls follow: north up column 9 (or 8, a tile short) to row 12, west to (8, 12), east to (30, 12) beside the policeman (31, 12), south to (30, 17), west to (25, 17), and down the ledge row 18 to (25, 19), a few tiles from the door (22, 19). The way keeps out of the boy's (16, 18..24) and the balding man's (8..10, 22..24) wander boxes." + ], + "start": {"certainty": "tile", "map": "Route4", "where": {"facing": "south", "kind": "tiles", "tiles": [[32, 6]]}}, + "sections": [ + { + "id": "mega_kick_tutor", + "title": "Route 4: the Mega Kick tutor", + "events": [ + { + "id": "mega_kick_tutor", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4", "where": {"facing": "north", "kind": "tiles", "tiles": [[50, 4]]}}, + "why": "east and up through (48, 5) into the tutors' pen, below the Mega Kick tutor (50, 3)" + }, + { + "id": "teach_mega_kick", + "kind": "game_action", + "variant": "teach tutor mega-kick slot=1 forget=withdraw", + "once_per_save": true, + "why": "the tutor's Mega Kick in place of Withdraw, unless the lead knows it" + } + ] + }, + { + "id": "route4_east", + "title": "Route 4's upper road and its ledge", + "events": [ + { + "id": "above_ledge", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4", "where": {"facing": "south", "kind": "tiles", "tiles": [[93, 8]]}}, + "why": "east along Route 4's upper road to above the ledge row 9" + }, + { + "id": "ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "Route4", "where": {"facing": "south", "kind": "tiles", "tiles": [[93, 10]]}}, + "why": "down the ledge (93, 9) to the lower road" + } + ] + }, + { + "id": "cerulean", + "title": "Cerulean City to its Pokemon Center", + "events": [ + { + "id": "cerulean_entry", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "east", "kind": "tiles", "tiles": [[9, 20]]}}, + "why": "east into Cerulean City, to (9, 20) below column 9" + }, + { + "id": "above_city_ledge", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 8}, {"direction": "west", "tiles": 1}, {"direction": "east", "tiles": 22}, {"direction": "south", "tiles": 5}, {"direction": "west", "tiles": 5}], + "why": "to walls: (9, 12), (8, 12), (30, 12), (30, 17), (25, 17)" + }, + { + "id": "city_ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[25, 19]]}}, + "why": "down the ledge (25, 18)" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "west along row 20 to the Pokemon Center's door (22, 19)" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.14b.plan.json b/data/story/frlg-authored/frlg-00.14b.plan.json new file mode 100644 index 0000000..fa88ff6 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.14b.plan.json @@ -0,0 +1,96 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.14b", + "title": "Cerulean: Potions, a GRIND to Lv23, then into the Gym, saved below Misty's platform", + "notes": [ + "Cerulean Gym (pokefirered CeruleanCity_Gym map.json and scripts.inc): a pool with walkways. Misty (8, 6) stands on a platform (7..9, 6) above row 7. Picnicker Diana (4, 7) faces east, sight 4, over (5..8, 7), so misty_front (8, 7) is in her line; Swimmer Luis (10, 12) in the water faces west, sight 1, over (9, 12), on column 9 north of the door. No gym trainer has to be fought for Misty, so neither is: from the door up column 9 to row 13 (a route there, so the planner's walk to a wall doesn't run on past it through (9, 12)), west to (4, 13), and to walls round the pool's west and north sides, (4, 10), (12, 10), (12, 7), then west to (9, 7), the tile below the platform's east end, out of Diana's line. 00.14c steps up onto (9, 6) and talks to Misty from beside her.", + "Misty beat a Lv20 Wartortle (console B, run m51), so first a GRIND to Lv23 on 00.15's patch. Gen 3 numbers (pokefirered: her mons have IV 0; Wartortle taken at IV 15, no EVs): Starmie Lv21 has 56 HP, Atk 36, SpA 47, SpD 40. Bite is Dark, special in Gen 3, no STAB, x2 on Psychic: at Lv23 (SpA 39) it does 23..28, three hits (two on top rolls); at Lv20, 20..24. Her Swift (physical, 60) does 9..11 to a Lv23 Wartortle (about 67 HP, Def 45) and Water Pulse (STAB, resisted) 8..10: 6 or more hits, though m51 saw about 20 a turn. Her Recover (28) and Super Potion undo a Bite, so the margin is in Bite's damage.", + "The Mart comes before the GRIND: its wild battles are fought only with 2 or more Potions, and 00.14's save has none (m51 met Misty with only the 5 this row bought). 5 Potions (row 3, 300 each), then up to 3 Super Potions (row 2, 700), last so they take the Items pocket's last row; the battle doesn't use them yet. The money box can't be read, so the floor stands for it, and a floor above the money fails the step (the quantity box wraps). Prizes (pokefirered: 4 x last level x the class's factor) from a new game's 3000, less Viridian's 2000 and the Magikarp's 500: Liam 220, Brock 1400, Route 3's bug catchers 360, the Mt. Moon grunt 416 and Miguel 288 (the first rival's 80 only if won), at least 3184 here. Floor and budget 3000: 5 Potions and 2 Super Potions, 2900. Misty's 2100 (4 x 21 x 25) then leaves 00.15 its floor of 1500. Then the nurse, and the save before Misty, so her battle is its own checkpoint, 00.14c, verified and retried from it. 00.15's GRIND then fights until the sim beats the Cerulean rival often enough." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "cerulean_mart", + "title": "Cerulean Mart", + "events": [ + { + "id": "mart_clerk", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "why": "out of the Center to the Mart's clerk" + }, + { + "id": "buy_potions", + "kind": "game_action", + "variant": "mart CeruleanCity_Mart budget=3000 floor=3000 potion=5 super-potion=3", + "once_per_save": true, + "why": "5 Potions for the GRIND's wild battles, then Super Potions as the money allows" + } + ] + }, + { + "id": "grind", + "title": "Route 4's grass: a GRIND to Lv23", + "events": [ + { + "id": "grind_patch", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4", "where": {"facing": "west", "kind": "tiles", "tiles": [[86, 16]]}}, + "why": "west out of the city along Route 4's lower road onto its grass's east edge" + }, + { + "id": "grind_to_lv23", + "kind": "game_action", + "variant": "grind slot=1 level=23 encounters=100 pace=west heal_every=0", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "wild battles until the lead is Lv23, where Bite takes Starmie in three" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "back to the Center: Misty's battle starts at full HP and PP" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "cerulean_gym", + "title": "Cerulean Gym to below Misty's platform", + "events": [ + { + "id": "gym_below_luis", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Gym", "where": {"kind": "tiles", "tiles": [[9, 13]]}}, + "why": "into the Gym, up column 9 to row 13, short of Luis's (9, 12)" + }, + { + "id": "gym_west_walkway", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 5}], + "why": "west to the wall (4, 13)" + }, + { + "id": "below_misty_platform", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 3}, {"direction": "east", "tiles": 8}, {"direction": "north", "tiles": 3}, {"direction": "west", "tiles": 3}], + "why": "walls (4, 10), (12, 10), (12, 7), then to (9, 7), out of Diana's line" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.14c.plan.json b/data/story/frlg-authored/frlg-00.14c.plan.json new file mode 100644 index 0000000..989e062 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.14c.plan.json @@ -0,0 +1,71 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.14c", + "title": "Cerulean Gym: Misty, then Water Pulse", + "notes": [ + "Misty (TRAINER_LEADER_MISTY: Staryu Lv18, Starmie Lv21), talked to from (9, 6), beside her on the platform. Her win text runs on to the CASCADE BADGE, TM03 (Water Pulse) and its explanation, all read with the battle's. Bite is chosen against her party (Starmie is Water/Psychic). Back to the nurse round the pool's west side, out of Luis's line; then Water Pulse in place of Tail Whip, last, at the Center, from the bag's TM CASE. Ends where 00.15 starts." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_Gym", "where": {"facing": "west", "kind": "tiles", "tiles": [[9, 7]]}}, + "sections": [ + { + "id": "misty", + "title": "Misty", + "events": [ + { + "id": "beside_misty", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Gym", "where": {"facing": "west", "kind": "tiles", "tiles": [[9, 6]]}}, + "why": "up onto (9, 6), facing Misty (8, 6)" + }, + { + "id": "challenge_misty", + "kind": "talk", + "why": "Misty's speech" + }, + { + "id": "misty", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "CeruleanCity_Gym", "where": {"facing": "west", "kind": "tiles", "tiles": [[9, 6]]}}, + "why": "Staryu and Starmie, with Bite; CASCADE BADGE and TM03" + } + ] + }, + { + "id": "cerulean_center", + "title": "Out of the Gym to the Center, then Water Pulse", + "events": [ + { + "id": "gym_way_out", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 1}, {"direction": "east", "tiles": 3}, {"direction": "south", "tiles": 3}, {"direction": "west", "tiles": 8}, {"direction": "south", "tiles": 3}, {"direction": "east", "tiles": 5}], + "why": "walls (12, 7), (12, 10), (4, 10), (4, 13), (9, 13), round Luis's (9, 12)" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "down column 9 out of the Gym, to the Center" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + }, + { + "id": "teach_water_pulse", + "kind": "game_action", + "variant": "teach tm03 water-pulse slot=1 forget=tail-whip", + "once_per_save": true, + "why": "TM03 Water Pulse in place of Tail Whip" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.15.plan.json b/data/story/frlg-authored/frlg-00.15.plan.json new file mode 100644 index 0000000..e5d4128 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.15.plan.json @@ -0,0 +1,93 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.15", + "title": "Cerulean: Water Pulse, Potions, a GRIND until the rival is winnable, then saved below his trigger", + "notes": [ + "Before the rival north of Cerulean (cerulean_rival()), from the Center: first TM03 Water Pulse over Tail Whip, if the lead doesn't know it yet, so the GRIND's sim plays it (a run without TM03 from Misty skips the step). Then 3 Potions at the Mart (CeruleanCity_Mart_Items: POTION is row 3, 300 each; Mt. Moon's trainers leave well over the floor) and 2 Awakenings (row 6, 250 each; pokefirered items.json) for the rival's Bulbasaur's Sleep Powder (console B, m56: asleep at 34/65 HP, it fainted two turns later with 15 Potions), 1400 of the floor's 1500. Then a GRIND on Route 4's grass east of Mt. Moon (75..86, 11..17; Spearow, Rattata, Ekans and Mankey around Lv10, about 80 EXP each), healing at the Center, until the battle sim beats the rival 00.15b fights 50% or more: the win chance his battle refuses below. Console B's Wartortle (Lv22, 65 HP, Water Pulse) is about 42% there and 62% at Lv23; Lv28 (about 88%, some 120 battles from Lv22) is the cap. Then the nurse, and the save on (23, 7), the tile below his trigger: his battle is its own checkpoint, 00.15b, verified and retried from this save." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "water_pulse", + "title": "Water Pulse in the Center", + "events": [ + { + "id": "teach_water_pulse", + "kind": "game_action", + "variant": "teach tm03 water-pulse slot=1 forget=tail-whip", + "once_per_save": true, + "why": "TM03 Water Pulse in place of Tail Whip, unless the lead knows it or there is no TM03" + } + ] + }, + { + "id": "cerulean_mart", + "title": "Cerulean Mart", + "events": [ + { + "id": "mart_clerk", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "why": "out of the Center to the Mart's clerk" + }, + { + "id": "buy_potions", + "kind": "game_action", + "variant": "mart CeruleanCity_Mart budget=1500 floor=1500 potion=3 awakening=2", + "once_per_save": true, + "why": "3 Potions: the GRIND fights wild battles only with 2 or more; 2 Awakenings for the rival's Sleep Powder" + } + ] + }, + { + "id": "grind", + "title": "Route 4's grass: a GRIND until the rival is winnable", + "events": [ + { + "id": "grind_patch", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route4", "where": {"facing": "west", "kind": "tiles", "tiles": [[86, 16]]}}, + "why": "west out of the city along Route 4's lower road onto its grass's east edge" + }, + { + "id": "grind_for_rival", + "kind": "game_action", + "variant": "grind slot=1 level=28 encounters=150 pace=west heal_every=0 beat=TRAINER_RIVAL_CERULEAN_BULBASAUR chance=50", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "wild battles until the sim beats the rival 50% or more, Lv28 at most; the nurse when hurt or low on PP" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "back to the Center: the rival's battle starts at full HP and PP" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "rival_trigger", + "title": "North to below the rival's trigger", + "events": [ + { + "id": "below_rival_trigger", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[23, 7]]}}, + "why": "out of the Center, north up to (23, 7), short of the trigger row 6" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.15b.plan.json b/data/story/frlg-authored/frlg-00.15b.plan.json new file mode 100644 index 0000000..e2fe43c --- /dev/null +++ b/data/story/frlg-authored/frlg-00.15b.plan.json @@ -0,0 +1,40 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.15b", + "title": "Cerulean: Water Pulse if not known, then the rival north of the city", + "notes": [ + "The rival north of Cerulean (CeruleanCity scripts.inc): the only way north to Nugget Bridge is columns 22..24, and a step onto row 6 there (CeruleanCity_EventScript_RivalTrigger*, VAR_MAP_SCENE_CERULEAN_CITY_RIVAL 0) brings him down to the player. From the middle, (23, 6), he stops at (23, 5); after the battle he walks round the player and off south, and the player, turning to watch him, ends facing south. His FAME CHECKER's text is read to the overworld with the battle's. For a player who took Squirtle he has Pidgeotto Lv17, Abra Lv16, Rattata Lv15 and Bulbasaur Lv18 (sParty_RivalCeruleanBulbasaur), whose Vine Whip and Sleep Powder are the danger. The row starts from 00.15's save below the trigger, and saves after him. First TM03 Water Pulse over Tail Whip (from the bag, where the player stands), if the lead doesn't know it yet: console B's save (2026-11-03) is past Misty's TEACH, which failed there. Where she taught it, the step reads the moves and does nothing." + ], + "start": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[23, 7]]}}, + "sections": [ + { + "id": "rival_cerulean", + "title": "The rival north of Cerulean", + "events": [ + { + "id": "teach_water_pulse", + "kind": "game_action", + "variant": "teach tm03 water-pulse slot=1 forget=tail-whip", + "once_per_save": true, + "why": "TM03 Water Pulse in place of Tail Whip, unless the lead knows it" + }, + { + "id": "rival_trigger", + "kind": "step", + "direction": "north", + "why": "onto (23, 6), the middle trigger: \"Yo! !\"" + }, + { + "id": "rival_cerulean", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[23, 6]]}}, + "why": "Pidgeotto, Abra, Rattata and Bulbasaur; then the FAME CHECKER" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.16.plan.json b/data/story/frlg-authored/frlg-00.16.plan.json new file mode 100644 index 0000000..aa4749e --- /dev/null +++ b/data/story/frlg-authored/frlg-00.16.plan.json @@ -0,0 +1,173 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.16", + "title": "Nugget Bridge: the nurse, five trainers and the Rocket", + "notes": [ + "Nugget Bridge (Route24 map.json) is x 10..12 from row 32 north to row 16, the city's columns 22..24 (offset 12). Its five trainers stand on it facing across, sight 2, so each line crosses the middle column 11 on the trainer's row: Bug Catcher Cale (12, 31), Lass Ali (10, 28), Youngster Timmy (12, 25), Lass Reli (10, 22) and Camper Ethan (12, 19). Each is fought on the step onto their row, beside them: they don't walk, and the player keeps facing north. Two tiles separate the rows, walked as one short leg; the step onto a row goes on a tile at a time until the trainer sees the player (into_line()), as the open leg onto the bridge ended a tile short twice on console B (2026-11-03), on (11, 33), and one step left the player out of Cale's sight. Then the Rocket (12, 15): the step onto (11, 15) (Route24_EventScript_RocketTriggerRight, VAR_MAP_SCENE_ROUTE24 0) gives the NUGGET, \"join Team Rocket\", and his battle; he only turns, and the player turns east to him. Camper Shane (5, 21) looks north from the west bank, off the way." + ], + "start": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[23, 6]]}}, + "sections": [ + { + "id": "cerulean_center", + "title": "Cerulean's Pokemon Center", + "events": [ + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "back to the Center after the rival, before Nugget Bridge" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + }, + { + "id": "nugget_bridge", + "title": "Nugget Bridge's five trainers", + "events": [ + { + "id": "below_cale_line", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 32]]}}, + "why": "out of the Center, north past the rival's row onto the bridge, below Cale's row" + }, + { + "id": "cale_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (11, 31), beside Cale" + }, + { + "id": "bug_catcher_cale", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 31]]}}, + "why": "his Bug Pokemon" + }, + { + "id": "below_ali_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 2}], + "why": "up to (11, 29)" + }, + { + "id": "ali_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (11, 28), beside Ali" + }, + { + "id": "lass_ali", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 28]]}}, + "why": "her Pokemon" + }, + { + "id": "below_timmy_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 2}], + "why": "up to (11, 26)" + }, + { + "id": "timmy_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (11, 25), beside Timmy" + }, + { + "id": "youngster_timmy", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 25]]}}, + "why": "his Pokemon" + }, + { + "id": "below_reli_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 2}], + "why": "up to (11, 23)" + }, + { + "id": "reli_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (11, 22), beside Reli" + }, + { + "id": "lass_reli", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 22]]}}, + "why": "her Pokemon" + }, + { + "id": "below_ethan_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 2}], + "why": "up to (11, 20)" + }, + { + "id": "ethan_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (11, 19), beside Ethan" + }, + { + "id": "camper_ethan", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 19]]}}, + "why": "his Pokemon" + } + ] + }, + { + "id": "rocket", + "title": "The Rocket at the bridge's north end", + "events": [ + { + "id": "ready_for_rocket", + "kind": "ready", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "items for a status or low HP; the nurse only if they can't", + "notes": [ + "A route, not legs: the nurse may have been needed." + ] + }, + { + "id": "below_rocket_trigger", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route24", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 16]]}}, + "why": "up the bridge to below the Rocket's trigger (11, 15)" + }, + { + "id": "rocket_trigger", + "kind": "step", + "direction": "north", + "why": "onto (11, 15), beside the Rocket" + }, + { + "id": "rocket_grunt", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route24", "where": {"facing": "east", "kind": "tiles", "tiles": [[11, 15]]}}, + "why": "the NUGGET, then Ekans and Zubat, Lv15" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.17.plan.json b/data/story/frlg-authored/frlg-00.17.plan.json new file mode 100644 index 0000000..d3e0745 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.17.plan.json @@ -0,0 +1,146 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.17", + "title": "Route 24 and 25 to Bill's Sea Cottage: Franklin, Kelsey, Nob and Haley", + "notes": [ + "Route 24 north of Nugget Bridge (Route24 map.json) joins Route 25 by its rows 7..9; the ledges on Route 25's row 6 (x 0..9) leave the way north at x 12..13. Route 25 (Route25 map.json, scripts.inc) to Bill's Sea Cottage door (51, 4): of its nine trainers, four can't be walked around.", + "- Hiker Franklin (11, 4) faces east, sight 4, over (12..15, 4), and Hiker Wayne (17, 7) east over (18..19, 7): the only ways east past x 15. Franklin is fought, from (15, 5) on the step onto (15, 4), the end of his line: he walks up to (14, 4).", + "- Youngster Joey (18, 2) faces south over (18, 3..4): the way keeps off column 18, south round Wayne to (19, 6) and up to (19, 4).", + "- Youngster Dan (22, 4) looks around, sight 2, over the only way east, (20..21, 4). On (20, 4), a one-tile leg, he may see the player and walk up to (21, 4); so the way goes north from there to row 2, east, and down column 23 past him to (23, 5), off every tile he may walk up to. Where his sight is crossed, the leg ends on a wall or is one tile; if he looks the player's way, story_interrupts() fight him.", + "- Picnicker Kelsey (22, 8) faces east over (23..24, 8), across the only way on: fought on the step onto (24, 8); she walks up to (23, 8).", + "- Hiker Nob (27, 9) faces north over (27, 6..8), Camper Flint (28, 4) south over (28, 5..7): every way east crosses one. Nob is fought on the step onto (27, 8), beside him; the way on keeps off Flint's column, by one-tile legs and legs to walls.", + "- Youngster Chad (36, 4) walks up and down column 36 (rows 2..7), so he may see any tile of it down to row 9. The way crosses his column on row 9, a leg to the water at (42, 9), where he can only walk up beside it.", + "- Lass Haley (42, 5) faces south over (42, 6..8), the only way east of x 42: fought on the step onto (42, 8); she walks up to (42, 7). The row saves inside the Sea Cottage, which the save card names ROUTE 25." + ], + "start": {"certainty": "tile", "map": "Route24", "where": {"facing": "east", "kind": "tiles", "tiles": [[11, 15]]}}, + "sections": [ + { + "id": "route24_franklin", + "title": "Off the bridge to Hiker Franklin", + "events": [ + { + "id": "below_franklin_line", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route25", "where": {"facing": "north", "kind": "tiles", "tiles": [[15, 5]]}}, + "why": "north off Nugget Bridge, east into Route 25, round its ledges to (15, 5), below the end of Franklin's line" + }, + { + "id": "franklin_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (15, 4), at the end of Franklin's line" + }, + { + "id": "hiker_franklin", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route25", "where": {"facing": "north", "kind": "tiles", "tiles": [[15, 4]]}}, + "why": "Machop and Geodude, Lv15; Franklin stops at (14, 4)" + } + ] + }, + { + "id": "route25_kelsey", + "title": "Round Dan to Picnicker Kelsey", + "events": [ + { + "id": "west_of_dan", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 2}, {"direction": "south", "tiles": 2}, {"direction": "east", "tiles": 2}, {"direction": "north", "tiles": 2}], + "why": "to (17, 4), short of Joey's (18, 4); round Wayne (17, 7) to (19, 6); up to (19, 4)" + }, + { + "id": "round_dan", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 2}, {"direction": "east", "tiles": 4}, {"direction": "west", "tiles": 1}, {"direction": "south", "tiles": 3}, {"direction": "east", "tiles": 1}, + {"direction": "south", "tiles": 2} + ], + "why": "onto (20, 4); up to (20, 2), east to (24, 2), down column 23 past Dan to (23, 5), to (24, 7) above Kelsey's line" + }, + { + "id": "kelsey_line", + "kind": "step", + "variant": "trainer_line", + "direction": "south", + "why": "onto (24, 8), at the end of Kelsey's line" + }, + { + "id": "picnicker_kelsey", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route25", "where": {"facing": "south", "kind": "tiles", "tiles": [[24, 8]]}}, + "why": "Nidoran M and Nidoran F, Lv15; Kelsey stops at (23, 8)" + } + ] + }, + { + "id": "route25_nob", + "title": "Hiker Nob", + "events": [ + { + "id": "west_of_nob_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 2}], + "why": "along row 8 to (26, 8)" + }, + { + "id": "nob_line", + "kind": "step", + "variant": "trainer_line", + "direction": "east", + "why": "onto (27, 8), above Nob" + }, + { + "id": "hiker_nob", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route25", "where": {"facing": "east", "kind": "tiles", "tiles": [[27, 8]]}}, + "why": "three Geodude and a Machop, Lv13" + } + ] + }, + { + "id": "route25_haley", + "title": "Past Chad to Lass Haley and the Sea Cottage", + "events": [ + { + "id": "below_haley_line", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "east", "tiles": 1}, {"direction": "south", "tiles": 1}, {"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 3}, {"direction": "east", "tiles": 5}, {"direction": "south", "tiles": 3}, + {"direction": "east", "tiles": 8} + ], + "why": "below Flint's column to (29, 9), up to (29, 6), east to (34, 6), down to (34, 9), east along row 9 past Chad's column to the water, (42, 9)" + }, + { + "id": "haley_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (42, 8), at the end of Haley's line" + }, + { + "id": "lass_haley", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route25", "where": {"facing": "north", "kind": "tiles", "tiles": [[42, 8]]}}, + "why": "Oddish, Pidgey and Oddish, Lv13; Haley stops at (42, 7)" + }, + { + "id": "sea_cottage", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 8]]}}, + "why": "east along row 8, up column 51 into the Sea Cottage (51, 4), a step in from its mat" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.18.plan.json b/data/story/frlg-authored/frlg-00.18.plan.json new file mode 100644 index 0000000..6f0cc4d --- /dev/null +++ b/data/story/frlg-authored/frlg-00.18.plan.json @@ -0,0 +1,112 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.18", + "title": "Bill's Sea Cottage: the Cell Separator and the S.S. Ticket", + "notes": [ + "Bill's Sea Cottage (Route25_SeaCottage scripts.inc). Bill is the Clefairy at (10, 6) (FLAG_HELPED_BILL_IN_SEA_COTTAGE unset): talked to from (10, 7), below him, he asks \"Help me out!\" (YES/NO; NO goes on the same), says to run the Cell Separation on the PC, and walks up into the right teleporter (10, 3); with the player facing north he walks straight up. The PC (4, 5) answers only from the south, (4, 6). Its scene: the teleporters run, Bill comes out of the left one (3, 3) and walks to (7, 6) (BillWalkToMiddleOfRoom); the player isn't moved. Talked to from (6, 6), Bill gives the S.S. TICKET, no YES/NO, and goes on about the S.S. ANNE (FLAG_GOT_SS_TICKET, which also hides Nugget Bridge's Rocket). Out by the mat (7, 9); the door puts the player on (51, 5), facing south. The maps keep Bill at (7, 5), but after his scene he stands on (7, 6), in the way from (6, 6) to the mat (console B, 2026-11-03), so the walk out goes around him to (7, 8) first." + ], + "start": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 8]]}}, + "sections": [ + { + "id": "clefairy", + "title": "Bill as a Clefairy", + "events": [ + { + "id": "below_bill_clefairy", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[10, 7]]}}, + "why": "below the Clefairy (10, 6), facing it" + }, + { + "id": "bill_clefairy", + "kind": "talk", + "why": "\"Hiya! I'm a POKEMON... ...No I'm not!\" ... \"Help me out!\"" + }, + { + "id": "help_bill", + "kind": "answer", + "why": "YES: \"run the Cell Separation on the PC\"" + }, + { + "id": "bill_into_teleporter", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[10, 7]]}}, + "why": "the Clefairy walks up into the right teleporter" + } + ] + }, + { + "id": "cell_separator", + "title": "The PC's Cell Separator", + "events": [ + { + "id": "pc_front", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[4, 6]]}}, + "why": "below the PC (4, 5), facing it" + }, + { + "id": "cell_separator", + "kind": "talk", + "why": "the PC: \" initiated the TELEPORTER's CELL SEPARATOR!\"" + }, + { + "id": "bill_comes_out", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "north", "kind": "tiles", "tiles": [[4, 6]]}}, + "why": "the teleporters run; Bill comes out of the left one and walks to (7, 6)" + } + ] + }, + { + "id": "ss_ticket", + "title": "Bill and the S.S. Ticket", + "events": [ + { + "id": "beside_bill", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 2}], + "why": "to (6, 6), west of Bill, facing him" + }, + { + "id": "thank_bill", + "kind": "talk", + "why": "\"Thanks, bud! ... take this\"" + }, + { + "id": "ss_ticket", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "Route25_SeaCottage", "where": {"facing": "east", "kind": "tiles", "tiles": [[6, 6]]}}, + "why": "the S.S. TICKET; \"... the S.S. ANNE ... go instead\"" + } + ] + }, + { + "id": "out", + "title": "Round Bill and out of the cottage", + "events": [ + { + "id": "around_bill", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 2}, {"direction": "east", "tiles": 1}], + "why": "to (7, 8), above the mat; Bill stands on (7, 6) after his scene" + }, + { + "id": "out_of_cottage", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route25", "where": {"facing": "south", "kind": "tiles", "tiles": [[51, 5]]}}, + "why": "down to the mat and out; the door puts the player below it" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.19.plan.json b/data/story/frlg-authored/frlg-00.19.plan.json new file mode 100644 index 0000000..0e74ab3 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.19.plan.json @@ -0,0 +1,47 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.19", + "title": "Route 25's south path back to Cerulean's Pokemon Center", + "notes": [ + "Back to Cerulean by Route 25's south path (Route25 map.json): from below the cottage down column 51 to row 12, west along row 12 and row 11 into Route 24 (x 14..23, row 11), and down its column 14..16 east of Nugget Bridge to Cerulean's north edge (x 26..28, offset 12). No trainer stands on it. Cerulean's row 1 there is a ledge (26..28, 1), hopped south from (27, 0); then on into the city to the Pokemon Center." + ], + "start": {"certainty": "tile", "map": "Route25", "where": {"facing": "south", "kind": "tiles", "tiles": [[51, 5]]}}, + "sections": [ + { + "id": "route25_south_path", + "title": "Route 25's south path to Cerulean's Pokemon Center", + "events": [ + { + "id": "above_cerulean_ledge", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[27, 0]]}}, + "why": "Route 25's south path west, Route 24 east of the bridge south, to above Cerulean's ledge (27, 1)" + }, + { + "id": "cerulean_ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[27, 2]]}}, + "why": "down the ledge (27, 1)" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "into the city to the Pokemon Center" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.20.plan.json b/data/story/frlg-authored/frlg-00.20.plan.json new file mode 100644 index 0000000..d8a251d --- /dev/null +++ b/data/story/frlg-authored/frlg-00.20.plan.json @@ -0,0 +1,75 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.20", + "title": "Route 24's grass: an Oddish for Cut, then the Center", + "notes": [ + "Stopgap for console B's save, which caught nothing on Route 1. A new playthrough should instead catch a Rattata on Route 1 or 22 early, as its Cut user and spare member, and drop this row (and its walk over Nugget Bridge and back).", + "An Oddish for HM01 Cut, and a second member behind the lead (docs/design/AutoStory-FRLG-FutureEvents.md, \"Console B run choices\"). Route 24's grass (Route24 map.json: x 3..5, rows 19..31, west of Nugget Bridge) is the nearest to the Center with Oddish: FireRed's sRoute24_FireRed (pokefirered wild_encounters.json) has it in 25% of battles, Lv12..14, as Route 25's grass; Routes 5 and 6 aren't on the story's maps yet. Up the bridge, whose trainers 00.16 beat, west along rows 10..15 to the cliff (3, 15) and down column 3 to the grass's first row, (3, 19); the step paces east to (4, 19) and back. Camper Shane (5, 21) faces north, sight 5, over (5, 16..20): column 5 is kept off. The leg west ends on the cliff, not open: on console B (m63) an open leg west to (4, 15) ended a tile short, and the walk down column 5 came into Shane's sight.", + "First 7 Poke Balls at the Mart (row 1, 200 each; the bag isn't read, so the step buys them whatever the bag holds). The floor, from 00.15's 1500 less its 1400: the rival's 288 (4 x 18 x 4), the Rocket's 480 (4 x 15 x 8), Franklin's 540 and Nob's 468 (hikers, 9) alone make 1876 (pokefirered gTrainerMoneyTable). An Oddish at full HP (catch rate 255) stays in a Poke Ball about 1 time in 3 (Gen 3: a = 85, four shakes of 0.76), so 7 balls catch it about 94% of the time; the step throws 7 at most, in 30 battles (none an Oddish: 0.02%). Nothing weakens it: the HP bar isn't read on the console yet.", + "The Oddish joins the party second. Battles keep the lead in (PokemonFRLG_AutoStoryBattleDecisions.h): the Oddish is sent only when the lead faints in a trainer's battle, which counts as lost. Back to the nurse, and the save in the Center." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "cerulean_mart", + "title": "Cerulean Mart: Poke Balls", + "events": [ + { + "id": "mart_clerk", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "why": "out of the Center to the Mart's clerk" + }, + { + "id": "buy_poke_balls", + "kind": "game_action", + "variant": "mart CeruleanCity_Mart budget=1400 floor=1500 poke-ball=7", + "once_per_save": true, + "why": "7 Poke Balls for the Oddish" + } + ] + }, + { + "id": "route24_grass", + "title": "Route 24's grass: an Oddish", + "events": [ + { + "id": "oddish_patch", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route24", "where": {"kind": "tiles", "tiles": [[3, 19]]}}, + "why": "north over Nugget Bridge, west to the cliff and down column 3 onto the grass's first row, out of Shane's column 5" + }, + { + "id": "catch_oddish", + "kind": "game_action", + "variant": "capture oddish catches=1 encounters=30 balls=7 pace=east", + "why": "wild battles until an Oddish, then Poke Balls; any other species is run from" + } + ] + }, + { + "id": "cerulean_center", + "title": "Back to Cerulean's Pokemon Center", + "events": [ + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "back over the bridge to the Center" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.21.plan.json b/data/story/frlg-authored/frlg-00.21.plan.json new file mode 100644 index 0000000..464619c --- /dev/null +++ b/data/story/frlg-authored/frlg-00.21.plan.json @@ -0,0 +1,94 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.21", + "title": "The Cerulean Rocket, Route 5, the Underground Path and Route 6 to Vermilion's Pokemon Center: Jeff", + "notes": [ + "Cerulean's only way south without Cut (CeruleanCity map.json, scripts.inc) is through the burgled house (30, 11), whose door the policeman leaves once the S.S. TICKET is had, out of the hole in its back wall into the yard (31, 8). The Rocket there (33, 6) stops the player on (33, 5) or (33, 7) (CeruleanCity_EventScript_GruntTrigger*): from (32, 7), the step east onto (33, 7) turns the player to him; Machop and Drowzee, Lv17, then TM28 Dig, and he is gone. Then east round the yard, down to the city's south edge by the path along its east side (39..40, 20..31), down Route 5's east side to the Underground Path's north house (31, 31), through its tunnel and out of the south house onto Route 6, below its door (19, 14). Route 6:", + "- Bug Catcher Keigo (3, 16) faces east, sight 5, over the middle path (4..8, 16); Bug Catcher Elijah (20, 25) faces west, sight 3, over the east path (17..19, 25). The way goes down column 15, through the grass to the wall (15, 33), out of both lines; the open leg west to it, a tile short, leaves the player on column 16, out of them too.", + "- Camper Ricky and Picnicker Nancy (12..13, 21) battle only when talked to.", + "- Picnicker Isabelle (13, 32) and Camper Jeff (13, 33) face west, sight 3, over (10..12, 32) and (10..12, 33); the only way south, (10..12, 34), is from Jeff's row. Up to (15, 31), west to the wall (7, 31), down to the wall (7, 33), east: Jeff is fought on the step onto (10, 33) and walks up to (11, 33). Isabelle's row is kept off. Then down into Vermilion City (offset 12) to its Pokemon Center." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "cerulean_rocket", + "title": "The Rocket behind the burgled house", + "events": [ + { + "id": "west_of_rocket", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "east", "kind": "tiles", "tiles": [[32, 7]]}}, + "why": "through the burgled house and out of the hole in its back wall, west of the Rocket (33, 6)" + }, + { + "id": "rocket_trigger", + "kind": "step", + "direction": "east", + "why": "onto (33, 7), below the Rocket" + }, + { + "id": "rocket_grunt", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[33, 7]]}}, + "why": "Machop and Drowzee, Lv17; TM28 Dig" + } + ] + }, + { + "id": "route6", + "title": "Route 5, the Underground Path and Route 6: Camper Jeff", + "events": [ + { + "id": "route6_column15", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route6", "where": {"kind": "tiles", "tiles": [[15, 14]]}}, + "why": "round the yard and down Cerulean's east side, Route 5 into the Underground Path, through it onto Route 6, west to column 15" + }, + { + "id": "round_keigo_and_elijah", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 19}, {"direction": "north", "tiles": 1}, {"direction": "north", "tiles": 1}, {"direction": "west", "tiles": 8}, {"direction": "south", "tiles": 2}, {"direction": "east", "tiles": 2}], + "why": "down column 15 to the wall (15, 33); up to (15, 31), west to the wall (7, 31), down to the wall (7, 33), east to (9, 33)" + }, + { + "id": "jeff_line", + "kind": "step", + "variant": "trainer_line", + "direction": "east", + "why": "onto (10, 33), in Jeff's line" + }, + { + "id": "camper_jeff", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route6", "where": {"facing": "east", "kind": "tiles", "tiles": [[10, 33]]}}, + "why": "Spearow and Raticate, Lv16; Jeff stops at (11, 33)" + } + ] + }, + { + "id": "vermilion_center", + "title": "Vermilion's Pokemon Center", + "events": [ + { + "id": "vermilion_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "down Route 6's south path into Vermilion City, to the Pokemon Center" + }, + { + "id": "heal_vermilion", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.22.plan.json b/data/story/frlg-authored/frlg-00.22.plan.json new file mode 100644 index 0000000..b932951 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.22.plan.json @@ -0,0 +1,160 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.22", + "title": "The S.S. Anne: the rival, HM01 Cut from the Captain, back to Vermilion's Pokemon Center", + "notes": [ + "The S.S. Anne (VermilionCity, SSAnne_* scripts.inc). The step onto (23, 33) (VermilionCity_EventScript_CheckTicket) has the sailor (24, 33) ask for a ticket; the S.S. TICKET (00.18) is shown and the player turns east to him. Then onto the pier (23, 34), along the gangway, through 1F, by legs off its cabins' doormats on row 10, which planned routes cross, and up its stairs (3, 8) to 2F. The step onto (30, 6), below the Captain's door (30, 2) (SSAnne_2F_Corridor_EventScript_RivalTriggerLeft), brings the rival out and down to (30, 5); the player keeps facing north, and after the battle he walks round the player and off. For a player who took Squirtle: Pidgeotto Lv19, Raticate Lv16, Kadabra Lv18, Ivysaur Lv20. The ship's trainers are in its cabins and on its deck, off the way. The Captain (5, 4) faces up; talked to from (5, 5) he is rubbed on the back and gives HM01 (VAR_MAP_SCENE_VERMILION_CITY 1). Back out through 1F's door (19, 1): on the gangway the ship sails (SSAnne_Exterior_ExitSSAnne), the player is put on (23, 34) and walked up to (23, 32) (VermilionCity_EventScript_ExitSSAnne). Cut is taught later, to the Oddish." + ], + "start": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "boarding", + "title": "The ticket check and S.S. Anne 1F", + "events": [ + { + "id": "above_ticket_check", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[23, 32]]}}, + "why": "out of the Center down to the harbor, above the ticket check (23, 33)" + }, + { + "id": "ticket_check", + "kind": "step", + "direction": "south", + "why": "onto (23, 33): \"Do you have a ticket?\"" + }, + { + "id": "show_ss_ticket", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "east", "kind": "tiles", "tiles": [[23, 33]]}}, + "why": "the S.S. TICKET; the player turns to the sailor" + }, + { + "id": "aboard", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "SSAnne_1F_Corridor", "where": {"facing": "south", "kind": "tiles", "tiles": [[19, 2]]}}, + "why": "onto the pier, along the gangway and in by 1F's door, a step below it" + }, + { + "id": "past_the_cabins", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 8}, {"direction": "north", "tiles": 1}, {"direction": "west", "tiles": 6}, {"direction": "north", "tiles": 1}], + "why": "to the wall (19, 10), up a step, west to the worker (12, 9), up a step to (13, 8): off the cabins' mats on row 10" + } + ] + }, + { + "id": "rival_ss_anne", + "title": "2F: the rival", + "events": [ + { + "id": "below_rival_trigger", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "SSAnne_2F_Corridor", "where": {"facing": "north", "kind": "tiles", "tiles": [[30, 7]]}}, + "why": "west along 1F, up the stairs (3, 8) and along 2F below the Captain's door" + }, + { + "id": "rival_trigger", + "kind": "step", + "direction": "north", + "why": "onto (30, 6): the rival comes out of the Captain's door" + }, + { + "id": "rival_ss_anne", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "SSAnne_2F_Corridor", "where": {"facing": "north", "kind": "tiles", "tiles": [[30, 6]]}}, + "why": "Pidgeotto, Raticate, Kadabra and Ivysaur" + } + ] + }, + { + "id": "captain", + "title": "The Captain and HM01", + "events": [ + { + "id": "behind_captain", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "SSAnne_CaptainsOffice", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 5]]}}, + "why": "into the Captain's office, behind the Captain (5, 4)" + }, + { + "id": "captain", + "kind": "talk", + "why": "\"Ooargh... I feel hideous... Urrp! Seasick...\"" + }, + { + "id": "hm01_cut", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "SSAnne_CaptainsOffice", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 5]]}}, + "why": "the player rubs his back; HM01, and what Cut does" + } + ] + }, + { + "id": "off_the_ship", + "title": "Back out and off the ship", + "events": [ + { + "id": "off_2f", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "SSAnne_1F_Corridor", "where": {"kind": "tiles", "tiles": [[13, 8]]}}, + "why": "back along 2F, down the stairs and east along 1F's row 8" + }, + { + "id": "round_the_sailor", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 4}, {"direction": "south", "tiles": 1}, {"direction": "east", "tiles": 2}], + "why": "to the sailor (18, 8), down a step, east to (19, 9): off the cabins' mats on row 10" + }, + { + "id": "below_ship_door", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "SSAnne_1F_Corridor", "where": {"facing": "north", "kind": "tiles", "tiles": [[19, 2]]}}, + "why": "up below the door to the gangway" + }, + { + "id": "off_the_ship", + "kind": "step", + "direction": "north", + "why": "out onto the gangway" + }, + { + "id": "ss_anne_sails", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[23, 32]]}}, + "why": "the ship sails; the player is walked off the pier to (23, 32)" + } + ] + }, + { + "id": "vermilion_center", + "title": "Vermilion's Pokemon Center", + "events": [ + { + "id": "vermilion_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "back to the Pokemon Center" + }, + { + "id": "heal_vermilion", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.23.plan.json b/data/story/frlg-authored/frlg-00.23.plan.json new file mode 100644 index 0000000..7ddd9c3 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.23.plan.json @@ -0,0 +1,178 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.23", + "title": "Vermilion Gym: Cut and Dig, the tree, Dwayne, Baily and Tucker, the trash cans", + "notes": [ + "Rows 00.23 to 00.25: HM01 Cut to the Oddish, the tree before Vermilion Gym, its three trainers and its trash cans, then Lt. Surge from a save in front of him.", + "The gym (VermilionCity_Gym map.json, scripts.inc), 11 x 20, entered on (5, 19): the cans on rows 10, 12 and 14 at x 1, 3, 5, 7, 9 (PokemonFRLG_AutoStoryTrashCans.h), the beams across rows 6 and 7 that the two switches turn off, Lt. Surge (5, 2) facing down above them. Its trainers, sight 3:", + "- Sailor Dwayne (8, 13) and Engineer Baily (2, 11) look around (MOVEMENT_TYPE_LOOK_AROUND): between them they see across rows 11 and 13 and down columns 2 and 8, so no way from the door to the cans keeps out of their sight. Each is fought from the second tile of his line, stepped onto from beside it, out of sight, and waited on there until he turns to the player (TRAINER_WAIT_VARIANT): Dwayne from (8, 15), stepped onto from (7, 15), Baily from (2, 13), from (3, 13). Each walks up a tile, Dwayne to (8, 14), Baily to (2, 12), and stays there while the player is in the gym.", + "- Gentleman Tucker (7, 8) faces west over (4..6, 8): fought on the step up from (5, 9) onto (5, 8); he walks up to (6, 8). The cans' stands, on rows 9, 11 and 13 above each, are clear of where the three stand after their battles. Leaving the gym puts them back where the map has them, beaten, and grows the tree back.", + "HM01 Cut, from the S.S. Anne (00.22), to the Oddish (00.20), second in the party: a wild Oddish of Lv12 to 14 knows 2 or 3 moves (Absorb, Sweet Scent, Poison Powder at 14), so it has room. TM28 Dig, from the Cerulean Rocket (00.21), to the lead in place of Withdraw: Ground, twice as strong on Lt. Surge's three, it takes the sim's chance against him for a Lv28 Wartortle with 14 Potions from 6% to 47%. Vermilion's tree (19, 24) (EventScript_CutTree) is the only way into the gym's yard, row 24 being walls but for it; the gym's door is (14, 25). In the gym, the trainers as above, then the trash cans until the door opens; out, the tree cut again from below, and back to the nurse." + ], + "start": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "teach", + "title": "Cut and Dig in the Center", + "events": [ + { + "id": "teach_cut", + "kind": "game_action", + "variant": "teach hm01 cut slot=2", + "once_per_save": true, + "why": "HM01 Cut to the Oddish, second in the party, unless it knows it" + }, + { + "id": "teach_dig", + "kind": "game_action", + "variant": "teach tm28 dig slot=1 forget=withdraw", + "once_per_save": true, + "why": "TM28 Dig in place of Withdraw, for Lt. Surge, unless the lead knows it or there is no TM28" + } + ] + }, + { + "id": "gym_tree", + "title": "The tree and the gym's door", + "events": [ + { + "id": "above_gym_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[19, 23]]}}, + "why": "out of the Center, south through the city to above the tree (19, 24)" + }, + { + "id": "cut_gym_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[19, 24]]}}, + "why": "the Oddish cuts the tree; a step onto its tile" + }, + { + "id": "gym_door", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 19]]}}, + "why": "down into the yard and in by the gym's door (14, 25)" + } + ] + }, + { + "id": "gym_trainers", + "title": "Dwayne, Baily and Tucker", + "events": [ + { + "id": "west_of_dwayne_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 4}, {"direction": "east", "tiles": 2}], + "why": "up column 5 to the can (5, 14), east to (7, 15): out of Dwayne's and Baily's sight" + }, + { + "id": "dwayne_sight", + "kind": "step", + "variant": "trainer_wait", + "direction": "east", + "why": "onto (8, 15), two below Dwayne (8, 13): he turns to the player and walks up to (8, 14)" + }, + { + "id": "sailor_dwayne", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[8, 15]]}}, + "why": "two Pikachu, Lv21" + }, + { + "id": "east_of_baily_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 1}], + "why": "west along row 15 to (4, 15), up to (4, 13), west to (3, 13): out of Baily's sight" + }, + { + "id": "baily_sight", + "kind": "step", + "variant": "trainer_wait", + "direction": "west", + "why": "onto (2, 13), two below Baily (2, 11): he turns to the player and walks up to (2, 12)" + }, + { + "id": "engineer_baily", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[2, 13]]}}, + "why": "Voltorb and Magnemite, Lv21" + }, + { + "id": "below_tucker_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 2}, {"direction": "north", "tiles": 4}, {"direction": "east", "tiles": 1}], + "why": "east to (4, 13), up column 4 past Baily's row to (4, 9), east to (5, 9): below Tucker's line, not on it" + }, + { + "id": "tucker_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (5, 8), in Tucker's line: he walks up to (6, 8)" + }, + { + "id": "gentleman_tucker", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "east", "kind": "tiles", "tiles": [[5, 8]]}}, + "why": "Pikachu, Lv23" + } + ] + }, + { + "id": "trash_cans", + "title": "The trash cans", + "events": [ + { + "id": "trash_cans", + "kind": "game_action", + "variant": "trash_cans", + "why": "the cans until both locks open; a wrong second can resets them" + } + ] + }, + { + "id": "vermilion_center", + "title": "Out, the tree, back to the Center", + "events": [ + { + "id": "below_gym_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[19, 25]]}}, + "why": "out of the gym, east to below the tree, grown back" + }, + { + "id": "cut_tree_out", + "kind": "game_action", + "variant": "cut_tree", + "direction": "north", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[19, 24]]}}, + "why": "the tree again; a step onto its tile" + }, + { + "id": "vermilion_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "north through the city to the Pokemon Center" + }, + { + "id": "heal_vermilion", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.24.plan.json b/data/story/frlg-authored/frlg-00.24.plan.json new file mode 100644 index 0000000..e7c920a --- /dev/null +++ b/data/story/frlg-authored/frlg-00.24.plan.json @@ -0,0 +1,115 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.24", + "title": "Route 6's grass until Lt. Surge is winnable, then through the open beams to him", + "notes": [ + "Wild battles on Route 6 until the sim beats Lt. Surge half the time: with Dig, 47% at Lv28 and 51% at Lv29, so a lead the gym's trainers have brought to Lv29 passes at once, and a Lv28 one after a level. The grass nearest the city is Route 6's south patch (13..16, 30..33); Picnicker Isabelle (13, 32) faces west over (10..12, 32), on the way north from the city, so the walk goes along Jeff's row 33 (he is beaten) to the wall (7, 33), up to row 31 and east along it onto the patch's west edge, (13, 31), above Isabelle, out of her line. Back to the nurse the same way. All that is skipped when the lead, read in the Center, passes already. Then the tree, the gym, whose trainers stand where the map has them, beaten, and whose beams stay off (FLAG_FOUND_BOTH_VERMILION_GYM_SWITCHES): up column 5 to below Lt. Surge, and saved there." + ], + "start": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "surge_check", + "title": "Whether Lt. Surge is winnable already", + "events": [ + { + "id": "surge_winnable", + "kind": "game_action", + "variant": "grind_check slot=1 level=32 encounters=150 pace=east heal_every=0 beat=TRAINER_LEADER_LT_SURGE chance=50", + "why": "the lead as it is: if the sim beats Lt. Surge 50% or more already, no trip to Route 6" + } + ] + }, + { + "id": "route6_grind", + "title": "Route 6's grass: a GRIND until he is", + "events": [ + { + "id": "route6_south_path", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route6", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 34]]}}, + "skip_if": ["surge_winnable"], + "why": "out of the Center, north out of the city onto Route 6's path, below Jeff's row" + }, + { + "id": "round_isabelle_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 1}, {"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 2}, {"direction": "east", "tiles": 5}, {"direction": "east", "tiles": 1}], + "skip_if": ["surge_winnable"], + "why": "onto Jeff's row (11, 33), west to the wall (7, 33), up to (7, 31), east along row 31 to (12, 31) and a step onto the grass, (13, 31): out of Isabelle's line" + }, + { + "id": "grind_for_surge", + "kind": "game_action", + "variant": "grind slot=1 level=32 encounters=150 pace=east heal_every=0 beat=TRAINER_LEADER_LT_SURGE chance=50", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "skip_if": ["surge_winnable"], + "why": "wild battles until the sim beats Lt. Surge 50% or more, Lv32 at most; the nurse when hurt or low on PP" + }, + { + "id": "west_on_row_31", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route6", "where": {"kind": "tiles", "tiles": [[7, 31]]}}, + "skip_if": ["surge_winnable"], + "why": "west along row 31, out of the grass, to the wall (7, 31)" + }, + { + "id": "down_to_jeff_row", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 2}, {"direction": "east", "tiles": 4}], + "skip_if": ["surge_winnable"], + "why": "down to the wall (7, 33), east along Jeff's row to (11, 33): out of Isabelle's line" + }, + { + "id": "vermilion_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "skip_if": ["surge_winnable"], + "why": "south into the city to the Pokemon Center" + }, + { + "id": "heal_vermilion", + "kind": "heal", + "skip_if": ["surge_winnable"], + "why": "full HP" + } + ] + }, + { + "id": "to_lt_surge", + "title": "The tree and the open beams to below Lt. Surge", + "events": [ + { + "id": "above_gym_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[19, 23]]}}, + "why": "out of the Center, south through the city to above the tree (19, 24)" + }, + { + "id": "cut_gym_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[19, 24]]}}, + "why": "the tree; a step onto its tile" + }, + { + "id": "below_lt_surge", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 3]]}}, + "why": "into the gym, up round the cans and through the beams, off, to below Surge (5, 2)" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.25.plan.json b/data/story/frlg-authored/frlg-00.25.plan.json new file mode 100644 index 0000000..179b116 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.25.plan.json @@ -0,0 +1,72 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.25", + "title": "Vermilion Gym: Lt. Surge, the THUNDERBADGE, then the Center", + "notes": [ + "Lt. Surge (5, 2), talked to from below, from the save in front of him: Voltorb Lv21, Pikachu Lv18 and Raichu Lv24, Shock Wave and Thunder Wave, a Super Potion and a Full Heal (sParty_LeaderLtSurge); then the THUNDERBADGE and TM34, read to the overworld with the battle's text. Out, the tree, and the nurse. Surge's win also puts Oak's aide on Vermilion City's (25, 7) (VermilionCity_Gym_EventScript_ShowOaksAide), where he stays until talked to; the story's maps don't have him. The way to the nurse along row 7 runs into him (console B, 2026-11-03: the leg west stopped beside him and the step into the Center's door went into a house), so it goes along row 10 to the water instead, clear of him, and up column 14 from there." + ], + "start": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 3]]}}, + "sections": [ + { + "id": "lt_surge", + "title": "Lt. Surge", + "events": [ + { + "id": "challenge_lt_surge", + "kind": "talk", + "why": "\"Hey, kid! What do you think you're doing here?\"" + }, + { + "id": "lt_surge", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "VermilionCity_Gym", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 3]]}}, + "why": "Voltorb, Pikachu and Raichu; THUNDERBADGE and TM34" + } + ] + }, + { + "id": "vermilion_center", + "title": "Out, the tree, round Oak's aide to the Center", + "events": [ + { + "id": "below_gym_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[19, 25]]}}, + "why": "down through the beams, out of the gym, east to below the tree, grown back" + }, + { + "id": "cut_tree_out", + "kind": "game_action", + "variant": "cut_tree", + "direction": "north", + "declared_after": {"certainty": "tile", "map": "VermilionCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[19, 24]]}}, + "why": "the tree; a step onto its tile" + }, + { + "id": "below_oaks_aide", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"kind": "tiles", "tiles": [[14, 10]]}}, + "why": "north through the city and west along row 10 to the water, (14, 10): off Oak's aide's row 7" + }, + { + "id": "vermilion_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "up to the Pokemon Center" + }, + { + "id": "heal_vermilion", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.26.plan.json b/data/story/frlg-authored/frlg-00.26.plan.json new file mode 100644 index 0000000..34d8de5 --- /dev/null +++ b/data/story/frlg-authored/frlg-00.26.plan.json @@ -0,0 +1,156 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.26", + "title": "The BIKE VOUCHER from the Fan Club, back north to Cerulean, the BICYCLE, Repels and Escape Ropes", + "notes": [ + "Rows from 00.26 on, after the THUNDERBADGE: the BICYCLE, and the way east and south to Celadon City.", + "The BIKE VOUCHER and the BICYCLE, from Vermilion's Center to Cerulean's (pokeguy 43:50 to 45:00).", + "- The Pokemon Fan Club (VermilionCity_PokemonFanClub map.json, scripts.inc), in by Vermilion's (12, 17): the chairman (5, 4) sits above a table (5..6, 5..6) with the worker (6, 4) east of him, so he is talked to from (4, 4), west of him. \"Did you come to hear about my POKEMON?\" YES: his story, then the BIKE VOUCHER (FLAG_GOT_BIKE_VOUCHER). Oak's aide stands on Vermilion's (25, 7) since Lt. Surge, where the story's maps don't have him: the way planned from the Center's door goes east along his row 7, so the walk goes down to the water (14, 10) first, as 00.25 came up from it. From the Fan Club, up to (22, 10) first, so that the way on to Route 6 goes up column 22, west of him, not round by column 27.", + "- Route 6 north, the trainers as 00.21 left them: Jeff (13, 33) beaten, Isabelle (13, 32) and Elijah (20, 25) not. As in 00.24, onto Jeff's row, west to the wall (7, 33) and up to row 31, above Isabelle's line; then east along row 31 to the wall (17, 31) and up column 16, west of Elijah's line (17..19, 25) and east of Keigo's (4..8, 16), to the ledge (16, 11). The first three legs are 00.24's, walked on console B; the two after end on walls, which the walker holds again after a wild battle in the grass.", + "- The Underground Path north, Route 5's sides, which have no trainer, and Cerulean's south edge, whose way into the city without the burgled house is the tree (26, 32) (pokeguy 44:42).", + "- The Bike Shop (CeruleanCity_BikeShop), in by (13, 28): the clerk (9, 3) is across the counter (8, 3), talked to from (7, 3). With the voucher he gives the BICYCLE (FLAG_GOT_BICYCLE) with no YES/NO; it isn't registered or ridden yet.", + "- The Mart: 5 Repels (row 9, 350 each) and 2 Escape Ropes (row 8, 550 each; pokefirered items.json), 2850 in all. Console B had about 9000 after Lt. Surge (2026-11-03); the floor of 6000 leaves 3000 or more after them.", + "- The nurse, and the save in Cerulean's Center." + ], + "start": {"certainty": "tile", "map": "VermilionCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "fan_club", + "title": "The Fan Club's BIKE VOUCHER", + "events": [ + { + "id": "below_center", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"kind": "tiles", "tiles": [[14, 10]]}}, + "why": "out of the Center, down to the water (14, 10): off Oak's aide's row 7" + }, + { + "id": "beside_chairman", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity_PokemonFanClub", "where": {"facing": "east", "kind": "tiles", "tiles": [[4, 4]]}}, + "why": "east along row 10, down to the Fan Club's door (12, 17), in, and up its west side beside the chairman (5, 4)" + }, + { + "id": "chairman", + "kind": "talk", + "why": "\"I chair the POKEMON Fan Club!\" ... \"Did you come to hear about my POKEMON?\"" + }, + { + "id": "hear_story", + "kind": "answer", + "why": "YES: his story" + }, + { + "id": "bike_voucher", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "VermilionCity_PokemonFanClub", "where": {"facing": "east", "kind": "tiles", "tiles": [[4, 4]]}}, + "why": "the story of his Rapidash; the BIKE VOUCHER" + } + ] + }, + { + "id": "route6_north", + "title": "North over Route 6", + "events": [ + { + "id": "west_of_oaks_aide", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "VermilionCity", "where": {"kind": "tiles", "tiles": [[22, 10]]}}, + "why": "out of the Fan Club, east along row 18 and up column 22 to (22, 10)" + }, + { + "id": "route6_south_path", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route6", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 34]]}}, + "why": "up column 22 west of Oak's aide (25, 7), out of the city onto Route 6's path, below Jeff's row" + }, + { + "id": "round_isabelle_and_elijah", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "north", "tiles": 1}, {"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 2}, {"direction": "east", "tiles": 9}, {"direction": "north", "tiles": 19}], + "why": "onto Jeff's row (11, 33), west to the wall (7, 33), up to (7, 31), east along row 31 to the wall (16, 31), up column 16 to the ledge (16, 12): out of Isabelle's and Elijah's lines" + } + ] + }, + { + "id": "bike_shop", + "title": "Cerulean's tree and the Bike Shop", + "events": [ + { + "id": "below_cerulean_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[26, 33]]}}, + "why": "the Underground Path north, up Route 5's side into Cerulean, below the tree (26, 32)" + }, + { + "id": "cut_cerulean_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "north", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "north", "kind": "tiles", "tiles": [[26, 32]]}}, + "why": "the tree; a step onto its tile" + }, + { + "id": "bike_clerk", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_BikeShop", "where": {"facing": "east", "kind": "tiles", "tiles": [[7, 3]]}}, + "why": "west into the Bike Shop (13, 28), across the counter from the clerk (9, 3)" + }, + { + "id": "talk_bike_clerk", + "kind": "talk", + "why": "\"Oh, that's... A BIKE VOUCHER!\"" + }, + { + "id": "bicycle", + "kind": "scene", + "declared_after": {"certainty": "tile", "map": "CeruleanCity_BikeShop", "where": {"facing": "east", "kind": "tiles", "tiles": [[7, 3]]}}, + "why": "the voucher exchanged for a BICYCLE" + } + ] + }, + { + "id": "cerulean_mart", + "title": "Repels and Escape Ropes, then the Center", + "events": [ + { + "id": "mart_clerk", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_Mart", "where": {"facing": "west", "kind": "tiles", "tiles": [[4, 3]]}}, + "why": "out of the Bike Shop to the Mart's clerk" + }, + { + "id": "buy_repels", + "kind": "game_action", + "variant": "mart CeruleanCity_Mart budget=2850 floor=6000 repel=5 escape-rope=2", + "once_per_save": true, + "why": "5 Repels and 2 Escape Ropes, 2850 at most" + }, + { + "id": "cerulean_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "out of the Mart to the Center" + }, + { + "id": "heal_cerulean", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.27.plan.json b/data/story/frlg-authored/frlg-00.27.plan.json new file mode 100644 index 0000000..e95427f --- /dev/null +++ b/data/story/frlg-authored/frlg-00.27.plan.json @@ -0,0 +1,202 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.27", + "title": "East over Route 9 to Route 10's Pokemon Center: the two trees, Alicia, Jeremy and Conner", + "notes": [ + "East out of Cerulean over Route 9 to Route 10's Pokemon Center (pokeguy 45:12 to 47:27), on foot: the Bicycle isn't registered yet.", + "- Cerulean (CeruleanCity map.json): the way east, column 39..40 up from row 33 to rows 18..19 and out of the city's east edge, is reached from the city only through the tree (26, 32), grown back since 00.26 (its flag is a FLAG_TEMP), or the burgled house. Cut from above. Route 9 joins the city's rows 18..19 by its rows 8..9 (offset -10); its tree (2, 8) (FLAG_TEMP_12) closes them, (2, 9) being rock: cut from (1, 8), west of it.", + "- Route 9 (Route9 map.json, scripts.inc), its ledges all facing south. Of its nine trainers, three can't be walked around, as in pokeguy's run, where Jeremy happened to look away:", + " - Picnicker Alicia (14, 10) faces west, sight 3, over (11..13, 10), the only tiles above the ledge row 11 the way west goes down by: fought on the step onto (11, 10); she walks up to (12, 10). Then down the ledge (11, 11).", + " - Hiker Jeremy (20, 17) looks north and west (FACE_UP_AND_LEFT), sight 4: north over (20, 13..16), every way east of column 19 below the rocks of row 12. Fought on (20, 13), waiting for him to look north (TRAINER_WAIT_VARIANT); he walks up to (20, 14).", + " - Bug Catcher Conner (49, 7) faces east, sight 3, over (50..52, 7): the way north from row 13 is column 52 alone (the ledges of row 11 face south), and row 7 is the way onto the ridge. Fought on the step onto (52, 7); he walks up to (51, 7).", + " - Hiker Brice wanders row 2 (50..56), looking west and east, sight 1, over (49..57, 2), and the way up from the ledges of row 4 is (50..51, 4) below him. The leg up column 51 ends on row 3 if he stands at (51, 2), else it goes on to (51, 1) past him, and he may see the player there; either way the legs to walls after it meet on (48, 1): west to the rock (48, 3) or (48, 1), up to (48, 1). Row 1 is clear of his sight; east along it to the rock (64, 1) and down column 64 past the hidden Rare Candy (63, 2), not picked up. A held leg down to (64, 3) would hop the ledge (64, 4) and go on, so the last tile is one step, then the hop.", + " - Picnicker Caitlin (60, 9) faces east over (61..64, 9): the way to Route 10 goes along row 8, above her line, by legs to (70, 8), a tile short of the edge. Camper Chris (26, 7), Bug Catcher Brent (26, 1), Camper Drew (36, 6) and Hiker Alan (61, 16) are off the way; TM40 (12, 17) is left.", + "- Route 10 (Route10 map.json) joins Route 9's rows 8..10 by its own; its north part, down to the Center's door (13, 20), has no trainer on the way and its grass is walked round. The trees west of the door (10, 20..26) stay. The walk there ends its open legs where a tile of error can't reach a blocker, and finds its place again on walls (console B, 2026-11-09, two runs \"no fade\" at the door): the step onto Route 10 is not always held up, so the player may stand a tile further east, and the leg along row 11 holds to the wall (17, 11) instead of ending on (16, 11) by count. The 12 tiles down column 16 may end a tile short or long: from rows 22..29 a tile west and up to the Center's wall (15, 20) all end on (15, 21). West along row 21 to the wall (9, 21) ends on (10, 21), three west of the door's column: the only count no wall after it checks.", + "- The nurse, and the save in Route 10's Center: the save card names ROUTE 10." + ], + "start": {"certainty": "tile", "map": "CeruleanCity_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "cerulean_trees", + "title": "Cerulean's tree and Route 9's", + "events": [ + { + "id": "above_cerulean_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[26, 31]]}}, + "why": "out of the Center, south through the city to above the tree (26, 32), grown back" + }, + { + "id": "cut_cerulean_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "CeruleanCity", "where": {"facing": "south", "kind": "tiles", "tiles": [[26, 32]]}}, + "why": "the tree; a step onto its tile" + }, + { + "id": "west_of_route9_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route9", "where": {"facing": "east", "kind": "tiles", "tiles": [[1, 8]]}}, + "why": "down to row 33, east and up column 39 or 40 to row 18, east out of the city onto Route 9, west of its tree (2, 8)" + }, + { + "id": "cut_route9_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "east", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "east", "kind": "tiles", "tiles": [[2, 8]]}}, + "why": "Route 9's tree; a step onto its tile" + } + ] + }, + { + "id": "route9_west", + "title": "Route 9 west: Alicia and Jeremy", + "events": [ + { + "id": "above_alicia_line", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route9", "where": {"facing": "south", "kind": "tiles", "tiles": [[11, 9]]}}, + "why": "east to (11, 9), above the west end of Alicia's line" + }, + { + "id": "alicia_line", + "kind": "step", + "variant": "trainer_line", + "direction": "south", + "why": "onto (11, 10), in Alicia's line: she walks up to (12, 10)" + }, + { + "id": "picnicker_alicia", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "east", "kind": "tiles", "tiles": [[11, 10]]}}, + "why": "Oddish, Bellsprout, Oddish and Bellsprout, Lv18" + }, + { + "id": "alicia_ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "south", "kind": "tiles", "tiles": [[11, 12]]}}, + "why": "down the ledge (11, 11)" + }, + { + "id": "west_of_jeremy_sight", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route9", "where": {"facing": "east", "kind": "tiles", "tiles": [[19, 13]]}}, + "why": "down to row 13 and east along it to (19, 13), west of Jeremy's north line" + }, + { + "id": "jeremy_sight", + "kind": "step", + "variant": "trainer_wait", + "direction": "east", + "why": "onto (20, 13), four above Jeremy (20, 17): when he looks north he walks up to (20, 14)" + }, + { + "id": "hiker_jeremy", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "south", "kind": "tiles", "tiles": [[20, 13]]}}, + "why": "Machop and Onix, Lv20" + } + ] + }, + { + "id": "route9_east", + "title": "Route 9 east: Conner, round Brice, above Caitlin", + "events": [ + { + "id": "below_conner_line", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route9", "where": {"facing": "north", "kind": "tiles", "tiles": [[52, 8]]}}, + "why": "east along row 13 and up column 52 to (52, 8), below the east end of Conner's line" + }, + { + "id": "conner_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "onto (52, 7), the end of Conner's line: he walks up to (51, 7)" + }, + { + "id": "bug_catcher_conner", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "west", "kind": "tiles", "tiles": [[52, 7]]}}, + "why": "Caterpie, Weedle and Venonat, Lv20" + }, + { + "id": "round_brice", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 1}, {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 3}, {"direction": "north", "tiles": 2}, {"direction": "east", "tiles": 16}, + {"direction": "south", "tiles": 1} + ], + "why": "up to the ledge (52, 4), up column 51 to Brice's row, west to the rock (48, 3) (or (48, 1)), up to (48, 1), east along row 1 to the rock (64, 1), down to (64, 2)" + }, + { + "id": "above_east_ledge", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "south", "kind": "tiles", "tiles": [[64, 3]]}}, + "why": "onto (64, 3), above the ledge (64, 4)" + }, + { + "id": "east_ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "Route9", "where": {"facing": "south", "kind": "tiles", "tiles": [[64, 5]]}}, + "why": "down the ledge (64, 4)" + }, + { + "id": "above_caitlin_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 3}, {"direction": "east", "tiles": 6}], + "why": "down column 64 to row 8, east along it to (70, 8): above Caitlin's line (61..64, 9)" + } + ] + }, + { + "id": "route10_center", + "title": "Route 10 to its Pokemon Center", + "events": [ + { + "id": "route10_ledge_end", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route10", "where": {"facing": "east", "kind": "tiles", "tiles": [[17, 11]]}}, + "why": "east onto Route 10, down to row 11 west of the grass and east along it to the wall (17, 11), above the fence post (17, 12)" + }, + { + "id": "below_center_door", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 1}, {"direction": "south", "tiles": 12}, {"direction": "west", "tiles": 1}, {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 5}, {"direction": "east", "tiles": 3}], + "why": "into the ledge's gap (16, 11), down column 16 to row 23, a tile west, up to the Center's wall (15, 21), west along row 21 to the wall (10, 21), east to (13, 21), below the door" + }, + { + "id": "route10_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route10_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "up onto the Center's door (13, 20), to the nurse" + }, + { + "id": "heal_route10", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.28.plan.json b/data/story/frlg-authored/frlg-00.28.plan.json new file mode 100644 index 0000000..1ff6a8a --- /dev/null +++ b/data/story/frlg-authored/frlg-00.28.plan.json @@ -0,0 +1,355 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.28", + "title": "Through Rock Tunnel: Ashton, Winston, Martha, Allen, Lenny, Sofia, Dudley, Cooper and Dana", + "notes": [ + "Rows from 00.28 on: through Rock Tunnel, without Flash, and down Route 10 to Lavender Town's Pokemon Center.", + "From Route 10's Pokemon Center through Rock Tunnel (pokefirered RockTunnel_1F, RockTunnel_B1F map.json and scripts.inc) to Route 10 south of it. The save is on Route 10 by the tunnel's south mouth: the save card's places don't include Rock Tunnel.", + "- Every floor tile of the tunnel has wild encounters, which are run from (the table has no step that uses a Repel), so the legs end on walls, ladders or someone standing still, which the walker holds again after a battle. An open leg (two tiles or more, not to a wall) is followed only by legs a tile of error in it can't send astray.", + "- Nine trainers stand where the way can't go round them. The others (1F Lucas, Oliver, Ariana, Leah; B1F Eric, Steve) are walked round.", + "- Unverified on the console: Rock Tunnel is dark without Flash, and the overworld, fade, dialog and battle detectors haven't been measured under its darkness (~/FRLGLab/notes/2026-11-09-0028-dark-measure.md). Every step from rock_tunnel_1f to route10_south depends on them." + ], + "start": {"certainty": "tile", "map": "Route10_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "sections": [ + { + "id": "route10_to_mouth", + "title": "Route 10: the tree and below the north mouth", + "notes": [ + "- The tunnel's north mouth (8, 19) is reached from the Center through the tree (10, 20), cut from below; Heidi (9, 27) sees rows 28..29 below the trees and is left. Two single steps west then put the player below the mouth on (8, 20)." + ], + "events": [ + { + "id": "below_route10_tree", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route10", "where": {"facing": "north", "kind": "tiles", "tiles": [[10, 21]]}}, + "why": "out of the Center (13, 20), west along row 21 to the wall (9, 21), below the tree (10, 20)" + }, + { + "id": "cut_route10_tree", + "kind": "game_action", + "variant": "cut_tree", + "direction": "north", + "declared_after": {"certainty": "tile", "map": "Route10", "where": {"facing": "north", "kind": "tiles", "tiles": [[10, 20]]}}, + "why": "the tree; a step onto its tile" + }, + { + "id": "west_of_tree", + "kind": "step", + "direction": "west", + "declared_after": {"certainty": "tile", "map": "Route10", "where": {"facing": "west", "kind": "tiles", "tiles": [[9, 20]]}}, + "why": "a step west along row 20" + }, + { + "id": "below_rock_tunnel", + "kind": "step", + "direction": "west", + "declared_after": {"certainty": "tile", "map": "Route10", "where": {"facing": "west", "kind": "tiles", "tiles": [[8, 20]]}}, + "why": "a step west, below the mouth (8, 19)" + } + ] + }, + { + "id": "1f_north", + "title": "1F north: Ashton, then east to the ladder (45, 2)", + "notes": [ + "- 1F Ashton (27, 10) looks west over (24..26, 10), the only way south from the mouth's room: stepped into from (24, 9)." + ], + "events": [ + { + "id": "rock_tunnel_1f", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[17, 2]]}}, + "why": "north into Rock Tunnel" + }, + { + "id": "above_ashton_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 6}, {"direction": "east", "tiles": 8}, {"direction": "south", "tiles": 1}, {"direction": "west", "tiles": 1}], + "why": "down column 17 to the wall (17, 8), east along row 8 to (25, 8), onto row 9 and west to the wall (24, 9)" + }, + { + "id": "ashton_line", + "kind": "step", + "variant": "trainer_line", + "direction": "south", + "why": "onto (24, 10), in Ashton's line: he walks up to (25, 10)" + }, + { + "id": "pokemaniac_ashton", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "east", "kind": "tiles", "tiles": [[24, 10]]}}, + "why": "Slowpoke, Slowpoke and Slowpoke" + }, + { + "id": "b1f_south_ladder", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[38, 28]]}}, + "why": "east along row 12 and up column 45 to the ladder (45, 2), down to B1F" + } + ] + }, + { + "id": "b1f_east", + "title": "B1F south and east: Winston, Martha and Allen, to the ladder (33, 3)", + "notes": [ + "- B1F Winston (29, 35) looks south over the south passage (29, 36..38): stepped into from (32, 37), after the leg down column 33 to the wall and a tile back.", + "- B1F Martha (15, 33) looks east over (16..17, 33), the corridor north: stepped into from (17, 34), the wall east of row 34.", + "- B1F Allen (36, 11) looks south over (36, 12..14), the way west to the ladder (33, 3): stepped into from (38, 12), below the wall." + ], + "events": [ + { + "id": "winston_line_end", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 5}, {"direction": "south", "tiles": 10}, {"direction": "north", "tiles": 1}, {"direction": "west", "tiles": 1}], + "why": "west to the wall (33, 28), down column 33 to the wall (33, 38), up to (33, 37) and west to (32, 37)" + }, + { + "id": "winston_line", + "kind": "step", + "variant": "trainer_line", + "direction": "west", + "why": "along row 37 onto (29, 37), the end of Winston's line: he walks down to (29, 36)" + }, + { + "id": "pokemaniac_winston", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[29, 37]]}}, + "why": "Slowpoke and Slowpoke" + }, + { + "id": "below_martha_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 16}, {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 2}, {"direction": "east", "tiles": 5}], + "why": "west along row 37 to (13, 37), up to the wall (13, 35), west to the corner (11, 35), east to (16, 35)", + "notes": [ + "The corner (11, 35), wall north and rock west, finds the player from any of (11..14, 35) after a battle; east to the wall (19, 35) did not (console B, 2026-11-09 13:35: found 5 tiles off)." + ] + }, + { + "id": "martha_line", + "kind": "step", + "variant": "trainer_line", + "direction": "north", + "why": "up column 16 onto (16, 33), beside Martha; from (17, 35), a tile short, up column 17 onto (17, 33), the end of her line" + }, + { + "id": "picnicker_martha", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "west", "kind": "tiles", "tiles": [[16, 33]]}}, + "why": "Oddish and Bulbasaur" + }, + { + "id": "below_allen_line", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "east", "tiles": 1}, {"direction": "north", "tiles": 5}, {"direction": "east", "tiles": 12}, {"direction": "north", "tiles": 9}, {"direction": "east", "tiles": 11}, {"direction": "north", "tiles": 2}, + {"direction": "west", "tiles": 2}, {"direction": "north", "tiles": 5} + ], + "why": "east to the wall (17, 33), up column 17 to the wall (17, 28), east to the wall (29, 28), up column 29 past Steve's line to the wall (29, 19), east to (40, 19), up to row 17, west to the wall (38, 17) and up to the wall (38, 12)" + }, + { + "id": "allen_line", + "kind": "step", + "variant": "trainer_line", + "direction": "west", + "why": "along row 12 onto (36, 12), below Allen" + }, + { + "id": "hiker_allen", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[36, 12]]}}, + "why": "Geodude, Geodude and Graveler" + }, + { + "id": "west_of_b1f_ladder", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 10}], + "why": "west along row 12 to the wall (32, 12), up column 32 to the wall (32, 2)" + }, + { + "id": "1f_west_ladder", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[4, 2]]}}, + "why": "onto the ladder (33, 3), up to 1F" + } + ] + }, + { + "id": "1f_west", + "title": "1F west: Lenny, round Lucas's line to the ladder (20, 13)", + "notes": [ + "- 1F Lenny (7, 5) looks south over (7, 6..9), the way east from the ladder (4, 2): stepped into from (6, 9), the end of column 6. The way on to the ladder (20, 13) keeps west of Lucas's line (16..19, 17): down column 11, up column 14 to row 16." + ], + "events": [ + { + "id": "above_lenny_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 2}, {"direction": "south", "tiles": 7}], + "why": "east to the wall (6, 2), down column 6 to the wall (6, 9)" + }, + { + "id": "lenny_line", + "kind": "step", + "variant": "trainer_line", + "direction": "east", + "why": "onto (7, 9), the end of Lenny's line: he walks down to (7, 8)" + }, + { + "id": "hiker_lenny", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 9]]}}, + "why": "Machop and Onix" + }, + { + "id": "west_of_lucas_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "east", "tiles": 4}, {"direction": "south", "tiles": 15}, {"direction": "east", "tiles": 7}, {"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 8}, {"direction": "east", "tiles": 6}], + "why": "east to the wall (11, 9), down column 11 to the wall (11, 24), east to the wall (18, 24), west to (14, 24), up column 14 to the wall (14, 16), east to the wall (20, 16)" + }, + { + "id": "b1f_middle_ladder", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[27, 12]]}}, + "why": "up column 20 onto the ladder (20, 13), down to B1F" + } + ] + }, + { + "id": "b1f_west", + "title": "B1F west: Sofia, Dudley and past Cooper to the ladder (2, 3)", + "notes": [ + "- B1F Sofia (11, 15) looks south over (11, 16..19), the way west: stepped into along row 16 from (12..14, 16).", + "- B1F Dudley (5, 11) looks south over (5, 12..15): stepped into from (8, 15) along row 15.", + "- B1F Cooper (2, 6) looks around (sight 2) by the ladder (2, 3): the leg up column 1 to the wall (1, 2) passes him on (1, 6); if he looks west, story_interrupts() fights him and the leg is held on to its wall, as Mt. Moon's Grunt in 00.13." + ], + "events": [ + { + "id": "east_of_sofia_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "south", "tiles": 3}, {"direction": "west", "tiles": 12}, {"direction": "south", "tiles": 1}, {"direction": "west", "tiles": 2}], + "why": "down to the wall (27, 15), west along row 15 to the wall (15, 15), down to row 16 and west to (13, 16)" + }, + { + "id": "sofia_line", + "kind": "step", + "variant": "trainer_line", + "direction": "west", + "why": "along row 16 onto (11, 16), below Sofia" + }, + { + "id": "picnicker_sofia", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[11, 16]]}}, + "why": "Pidgey, Pidgey and Pidgeotto" + }, + { + "id": "east_of_dudley_line", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 3}, {"direction": "north", "tiles": 1}], + "why": "west to the wall (8, 16), up to (8, 15)" + }, + { + "id": "dudley_line", + "kind": "step", + "variant": "trainer_line", + "direction": "west", + "why": "along row 15 onto (5, 15), the end of Dudley's line: he walks down to (5, 14)" + }, + { + "id": "hiker_dudley", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_B1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[5, 15]]}}, + "why": "Geodude, Geodude and Graveler" + }, + { + "id": "past_cooper", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 4}, {"direction": "north", "tiles": 13}, {"direction": "south", "tiles": 1}], + "why": "west to the wall (1, 15), up column 1 past Cooper (2, 6) to the wall (1, 2), back to (1, 3)" + }, + { + "id": "1f_east_ladder", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[45, 21]]}}, + "why": "east onto the ladder (2, 3), up to 1F" + } + ] + }, + { + "id": "1f_south", + "title": "1F south: Dana, to the south mouth", + "notes": [ + "- 1F Dana (26, 28) looks south over (26, 29..31), the only way west to the south mouth: stepped into along row 31 from (27..29, 31)." + ], + "events": [ + { + "id": "above_dana_line", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "west", "tiles": 6}, {"direction": "south", "tiles": 5}, {"direction": "east", "tiles": 6}, {"direction": "west", "tiles": 1}, {"direction": "south", "tiles": 4}, {"direction": "west", "tiles": 5}, + {"direction": "south", "tiles": 5}, {"direction": "west", "tiles": 2}, {"direction": "north", "tiles": 3}, {"direction": "west", "tiles": 6}, {"direction": "north", "tiles": 3}, {"direction": "west", "tiles": 3}, + {"direction": "south", "tiles": 2} + ], + "why": "west to the wall (39, 21), down column 39 to Ariana (39, 27), east to the wall (45, 26), down column 44 to the wall (44, 30), west to the wall (39, 30), down to the wall (39, 35), west to (37, 35), up to the wall (37, 32), west to the wall (31, 32), up to (31, 29), west to (28, 29) and down to the wall (28, 31)" + }, + { + "id": "dana_line", + "kind": "step", + "variant": "trainer_line", + "direction": "west", + "why": "along row 31 onto (26, 31), the end of Dana's line: she walks down to (26, 30)" + }, + { + "id": "picnicker_dana", + "kind": "battle", + "declared_after": {"certainty": "tile", "map": "RockTunnel_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[26, 31]]}}, + "why": "Meowth, Oddish and Pidgey" + }, + { + "id": "above_south_mouth", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "west", "tiles": 6}, {"direction": "south", "tiles": 1}, {"direction": "west", "tiles": 8}, {"direction": "south", "tiles": 5}, {"direction": "east", "tiles": 2}, {"direction": "north", "tiles": 1}, + {"direction": "east", "tiles": 5}, {"direction": "west", "tiles": 1} + ], + "why": "west along row 31 to (20, 31), onto row 32 and west to the wall (12, 32), down column 12 to the wall (12, 37), east to the wall (14, 37), up to (14, 36), east to the wall (19, 36), back to (18, 36)" + } + ] + }, + { + "id": "route10_south", + "title": "Out onto Route 10 south of the tunnel", + "events": [ + { + "id": "route10_south", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "Route10", "where": {"facing": "south", "kind": "tiles", "tiles": [[8, 58]]}}, + "why": "onto the mouth (18, 37), out onto Route 10" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/data/story/frlg-authored/frlg-00.29.plan.json b/data/story/frlg-authored/frlg-00.29.plan.json new file mode 100644 index 0000000..afebebf --- /dev/null +++ b/data/story/frlg-authored/frlg-00.29.plan.json @@ -0,0 +1,70 @@ +{ + "format": "pokesim-authored-checkpoint/1", + "game": "frlg", + "checkpoint": { + "id": "00.29", + "title": "Route 10 south to Lavender Town's Pokemon Center", + "notes": [ + "Route 10 south of Rock Tunnel (Route10 map.json) to Lavender Town's Pokemon Center. It has no grass. Carol (7, 60) and Clark (4, 62) look around, Trent (4, 68) looks west and Herman wanders row 70 (13..17), looking west and east (sight 2, to x 19): the way keeps to the east side, columns 17..21, and crosses row 70 on column 21. The ledges of row 62 leave a gap at (18, 62); row 66's leaves (21, 66). Row 74's ledge (11, 74) is hopped, and the hold south goes on over the connection into Lavender Town to the wall (11, 9). West of the Center's building, the wall (8, 9) sets the door's column." + ], + "start": {"certainty": "tile", "map": "Route10", "where": {"facing": "south", "kind": "tiles", "tiles": [[8, 58]]}}, + "sections": [ + { + "id": "route10_south", + "title": "Route 10's east side and its last ledge", + "events": [ + { + "id": "route10_east_side", + "kind": "legs", + "variant": "run", + "legs": [ + {"direction": "east", "tiles": 10}, {"direction": "north", "tiles": 2}, {"direction": "west", "tiles": 1}, {"direction": "east", "tiles": 1}, {"direction": "south", "tiles": 8}, {"direction": "east", "tiles": 3}, + {"direction": "south", "tiles": 9}, {"direction": "west", "tiles": 10} + ], + "why": "east along row 58 to (18, 58), up to the wall (18, 56), west to the wall (17, 56), back to (18, 56), down through the ledges' gap to (18, 64), east to the wall (21, 64), down column 21 to the wall (21, 73), west along row 73 to the wall (11, 73)" + }, + { + "id": "route10_ledge_hop", + "kind": "step", + "direction": "south", + "declared_after": {"certainty": "tile", "map": "Route10", "where": {"facing": "south", "kind": "tiles", "tiles": [[11, 75]]}}, + "why": "down the ledge (11, 74)" + } + ] + }, + { + "id": "lavender", + "title": "Lavender Town to its Pokemon Center", + "events": [ + { + "id": "lavender_north_wall", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "LavenderTown", "where": {"facing": "south", "kind": "tiles", "tiles": [[11, 8]]}}, + "why": "down column 11 over the connection into Lavender Town, to the wall (11, 9)" + }, + { + "id": "below_center_door", + "kind": "legs", + "variant": "run", + "legs": [{"direction": "west", "tiles": 6}, {"direction": "south", "tiles": 1}, {"direction": "east", "tiles": 2}, {"direction": "west", "tiles": 1}], + "why": "west along row 8 to (5, 8), onto row 9, east to the wall (7, 9), west to (6, 9)" + }, + { + "id": "lavender_nurse", + "kind": "route", + "variant": "run", + "target": {"certainty": "tile", "map": "LavenderTown_PokemonCenter_1F", "where": {"facing": "north", "kind": "tiles", "tiles": [[7, 4]]}}, + "why": "up column 6 onto the Center's door (6, 5), to the nurse" + }, + { + "id": "heal_lavender", + "kind": "heal", + "why": "full HP" + } + ] + } + ] + }, + "execution": {"menu": "full", "supplies": {"lead": "after_brock"}} +} diff --git a/schemas/README.md b/schemas/README.md index fe9df1d..be6f31b 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -72,4 +72,4 @@ The native capture schema names C++ widths in `$defs` (`int32`, `uint8`, `uint16`, `count64`) and references them at each field. Stats use `uint16`; PP/levels use `uint8`. These encode storage bounds, not valid gameplay ranges. -`authored-checkpoint.schema.json` defines the first executable native authoring pilot: common checkpoint data plus FRLG `execution.menu`. It is separate from the full native export snapshot. Replay bindings accept exactly one pinned `capture` or `plan` source. +`authored-checkpoint.schema.json` defines executable native authoring: common checkpoint data plus FRLG `execution` (`menu`, and optional `supplies`, `live_start`, `handoff`). A checkpoint has `events` or named `sections` of events; `notes` (checkpoint, section, event) and `once_per_save` (event) come from Arduino-Source #314. `data/story/frlg-authored/` holds that PR's FRLG plans byte for byte (not reformatted) as schema/reader fixtures. It is separate from the full native export snapshot. Replay bindings accept exactly one pinned `capture` or `plan` source. diff --git a/schemas/authored-checkpoint.schema.json b/schemas/authored-checkpoint.schema.json index 8b45444..7a54e3e 100644 --- a/schemas/authored-checkpoint.schema.json +++ b/schemas/authored-checkpoint.schema.json @@ -14,7 +14,21 @@ "$defs": { "frlg_execution": { "type": "object", - "properties": {"menu": {"enum": ["before_pokemon", "before_pokedex", "full"]}}, + "properties": { + "menu": {"enum": ["before_pokemon", "before_pokedex", "full"]}, + "supplies": { + "type": "object", + "properties": { + "potions": {"$ref": "#/$defs/int32"}, + "antidotes": {"$ref": "#/$defs/int32"}, + "parlyz_heals": {"$ref": "#/$defs/int32"}, + "lead": {"const": "after_brock"} + }, + "additionalProperties": false + }, + "live_start": {"type": "boolean"}, + "handoff": {"enum": ["none", "sid_helper", "starter_rng", "gift_rng"]} + }, "required": ["menu"], "additionalProperties": false }, @@ -27,7 +41,8 @@ {"properties": {"on_failure": {"const": "reload_and_retry"}, "saves_in": {"minLength": 1}}}, {"properties": {"on_failure": {"const": "stop"}, "saves_in": {"const": ""}}} ] - } + }, + "int32": {"type": "integer", "minimum": -2147483648, "maximum": 2147483647} }, "oneOf": [ {"properties": {"game": {"const": "frlg"}, "execution": {"$ref": "#/$defs/frlg_execution"}}}, diff --git a/schemas/story-checkpoint.schema.json b/schemas/story-checkpoint.schema.json index 0214bbb..c4deee3 100644 --- a/schemas/story-checkpoint.schema.json +++ b/schemas/story-checkpoint.schema.json @@ -6,12 +6,27 @@ "properties": { "id": {"type": "string", "minLength": 1}, "title": {"type": "string"}, + "notes": {"$ref": "#/$defs/notes"}, "start": {"$ref": "#/$defs/pose"}, - "events": {"type": "array", "items": {"$ref": "#/$defs/step"}} + "events": {"type": "array", "items": {"$ref": "#/$defs/step"}}, + "sections": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/section"}} }, - "required": ["id", "title", "events"], + "required": ["id", "title"], + "oneOf": [{"required": ["events"]}, {"required": ["sections"]}], "additionalProperties": false, "$defs": { + "notes": {"type": "array", "items": {"type": "string"}}, + "section": { + "type": "object", + "properties": { + "id": {"type": "string", "minLength": 1}, + "title": {"type": "string"}, + "notes": {"$ref": "#/$defs/notes"}, + "events": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/step"}} + }, + "required": ["id", "title", "events"], + "additionalProperties": false + }, "pose": { "type": "object", "properties": { @@ -105,7 +120,9 @@ } }, "variant": {"type": "string"}, - "skip_if": {"type": "array", "items": {"type": "string"}} + "skip_if": {"type": "array", "items": {"type": "string"}}, + "once_per_save": {"type": "boolean"}, + "notes": {"$ref": "#/$defs/notes"} }, "required": ["id", "kind"], "additionalProperties": false diff --git a/src/pokesim/formats/json_schema.py b/src/pokesim/formats/json_schema.py index 63bfc7b..e479294 100644 --- a/src/pokesim/formats/json_schema.py +++ b/src/pokesim/formats/json_schema.py @@ -44,6 +44,8 @@ def published(): for path in sorted(ROOT.glob('data/story/native/*.json')): yield 'native-checkpoint-export', path yield 'authored-checkpoint', ROOT / 'data/story/parcel-pilot/frlg-parcel-00.05.plan.json' + for path in sorted(ROOT.glob('data/story/frlg-authored/*.plan.json')): + yield 'authored-checkpoint', path yield 'story-replay-binding', ROOT / 'data/story/parcel-pilot/binding.json' yield 'story-replay-binding', ROOT / 'data/story/parcel-pilot/authored-binding.json' yield 'story-replay-cases', ROOT / 'data/story/parcel-pilot/cases.json' diff --git a/src/pokesim/formats/test_json_schema.py b/src/pokesim/formats/test_json_schema.py index e63c5a8..55fd2f5 100644 --- a/src/pokesim/formats/test_json_schema.py +++ b/src/pokesim/formats/test_json_schema.py @@ -11,8 +11,13 @@ from .json_schema import ROOT, SCHEMAS, published, validator from pokesim.maps.runtime_map_schema import validate as validate_map +from pokesim.story.authored_checkpoint import read_authored_checkpoint from pokesim.story.checkpoint_wire import read_checkpoint +# Copied byte for byte from dayfine/Arduino-Source #314 (frlg/story-json) at +# 3dcf3e8a231fce9935de5c60729272fa5347f52e, StoryData/frlg-00.*.plan.json. +FRLG_AUTHORED = ROOT / 'data/story/frlg-authored' + @unittest.skipUnless(jsonschema, 'install schemas/requirements.txt for schema tests') class JsonSchemaTests(unittest.TestCase): @@ -110,3 +115,54 @@ def test_semantic_validation_is_still_required(self): validator('story-checkpoint').validate(value) with self.assertRaisesRegex(ValueError, 'duplicate'): read_checkpoint(value) + + def test_frlg_authored_plans_pass_schema_and_reader(self): + check = validator('authored-checkpoint') + paths = sorted(FRLG_AUTHORED.glob('*.plan.json')) + self.assertEqual(len(paths), 35) + for path in paths + [ROOT / 'data/story/parcel-pilot/frlg-parcel-00.05.plan.json']: + with self.subTest(path=path.name): + value = json.loads(path.read_text()) + check.validate(value) + read_authored_checkpoint(value) + + def test_frlg_authored_fields_stay_strict(self): + source = json.loads((FRLG_AUTHORED / 'frlg-00.28.plan.json').read_text()) + check = validator('authored-checkpoint') + variants = [ + ('events and sections', lambda v: v['checkpoint'].update(events=[])), + ('neither events nor sections', lambda v: v['checkpoint'].pop('sections')), + ('no sections', lambda v: v['checkpoint'].update(sections=[])), + ('empty section', lambda v: v['checkpoint']['sections'][0].update(events=[])), + ('unknown section field', lambda v: v['checkpoint']['sections'][0].update(mystery=1)), + ('empty section id', lambda v: v['checkpoint']['sections'][0].update(id='')), + ('note not a string', lambda v: v['checkpoint'].update(notes=[1])), + ('once_per_save not boolean', lambda v: v['checkpoint']['sections'][0]['events'][0].update(once_per_save=1)), + ('unknown execution field', lambda v: v['execution'].update(mystery=1)), + ('unknown handoff', lambda v: v['execution'].update(handoff='trade')), + ('live_start not boolean', lambda v: v['execution'].update(live_start='yes')), + ('unknown lead', lambda v: v['execution'].update(supplies={'lead': 'new_game'})), + ('unknown supply', lambda v: v['execution'].update(supplies={'repels': 1})), + ('supply beyond int', lambda v: v['execution'].update(supplies={'potions': 2147483648})), + ('menu missing', lambda v: v['execution'].pop('menu')), + ] + check.validate(source) + read_authored_checkpoint(source) + for name, mutate in variants: + with self.subTest(name=name): + value = copy.deepcopy(source) + mutate(value) + self.assertFalse(check.is_valid(value)) + with self.assertRaises((ValueError, KeyError, TypeError)): + read_authored_checkpoint(value) + + def test_sections_still_need_unique_ids_in_code(self): + value = {'id': 'x', 'title': 'X', 'sections': [ + {'id': 's', 'title': 'S', 'events': [{'id': 'a', 'kind': 'talk'}]}, + {'id': 't', 'title': 'T', 'events': [{'id': 'a', 'kind': 'talk'}]}]} + validator('story-checkpoint').validate(value) + with self.assertRaisesRegex(ValueError, 'duplicate story event'): + read_checkpoint(value) + value['sections'][1].update(id='s', events=[{'id': 'b', 'kind': 'talk'}]) + with self.assertRaisesRegex(ValueError, 'duplicate story section'): + read_checkpoint(value) diff --git a/src/pokesim/story/authored_checkpoint.py b/src/pokesim/story/authored_checkpoint.py index 8003036..8d6314c 100644 --- a/src/pokesim/story/authored_checkpoint.py +++ b/src/pokesim/story/authored_checkpoint.py @@ -5,15 +5,37 @@ from .replay_handlers import exact +FRLG_HANDOFFS = ('none', 'sid_helper', 'starter_rng', 'gift_rng') + + +def read_frlg_execution(execution): + """FRLG's save menu, plus supplies, live start and handoff when not a new game's.""" + if not isinstance(execution, dict) or 'menu' not in execution or ( + set(execution) - {'menu', 'supplies', 'live_start', 'handoff'}): + raise ValueError('FRLG execution needs menu and allows supplies, live_start, handoff') + if execution['menu'] not in ('before_pokemon', 'before_pokedex', 'full'): + raise ValueError('unsupported authored checkpoint menu') + supplies = execution.get('supplies', {}) + if not isinstance(supplies, dict) or set(supplies) - {'potions', 'antidotes', 'parlyz_heals', 'lead'}: + raise ValueError('unsupported FRLG supplies') + for key in ('potions', 'antidotes', 'parlyz_heals'): + if key in supplies and (type(supplies[key]) is not int or not -2147483648 <= supplies[key] <= 2147483647): + raise ValueError('FRLG supply count outside native int: ' + key) + if supplies.get('lead', 'after_brock') != 'after_brock': + raise ValueError('unsupported FRLG lead') + if type(execution.get('live_start', False)) is not bool: + raise ValueError('FRLG live_start must be boolean') + if execution.get('handoff', 'none') not in FRLG_HANDOFFS: + raise ValueError('unsupported FRLG handoff') + + def read_authored_checkpoint(value): """Reject unsupported fields/game/menu before binding an authored checkpoint.""" exact(value, 'format game checkpoint execution') if value['format'] != 'pokesim-authored-checkpoint/1' or value['game'] not in ('frlg', 'bdsp'): raise ValueError('unsupported authored checkpoint format/game') if value['game'] == 'frlg': - execution = exact(value['execution'], 'menu') - if execution['menu'] not in ('before_pokemon', 'before_pokedex', 'full'): - raise ValueError('unsupported authored checkpoint menu') + read_frlg_execution(value['execution']) else: execution = exact(value['execution'], 'on_failure saves_in') if (execution['on_failure'] not in ('reload_and_retry', 'stop') diff --git a/src/pokesim/story/checkpoint_wire.py b/src/pokesim/story/checkpoint_wire.py index 534c57c..a9647f0 100644 --- a/src/pokesim/story/checkpoint_wire.py +++ b/src/pokesim/story/checkpoint_wire.py @@ -49,6 +49,13 @@ def array(value): return value +def read_notes(root, result): + """Copy non-empty `notes` paragraphs; no executor reads them.""" + notes = [text(v) for v in array(root.get('notes', []))] + if notes: + result['notes'] = notes + + def read_pose(value): root = fields(value, ('map', 'certainty', 'where')) result = dict(map=text(root['map']), certainty=choice(root['certainty'], CERTAINTIES)) @@ -72,7 +79,8 @@ def read_pose(value): def read_step(value): root = fields(value, ('id', 'kind', 'why', 'target', 'direction', 'legs', 'fight_wild', - 'yes', 'may_lose', 'battles', 'items', 'variant', 'skip_if', 'declared_after')) + 'yes', 'may_lose', 'battles', 'items', 'variant', 'skip_if', 'declared_after', + 'once_per_save', 'notes')) result = dict(id=text(root['id']), kind=choice(root['kind'], KINDS)) if not result['id']: raise ValueError('empty story step id') @@ -85,7 +93,7 @@ def read_step(value): direction = choice(root.get('direction', 'north'), DIRECTIONS) if direction != 'north': result['direction'] = direction - for key, default in (('fight_wild', False), ('yes', True), ('may_lose', False)): + for key, default in (('fight_wild', False), ('yes', True), ('may_lose', False), ('once_per_save', False)): flag = root.get(key, default) if type(flag) is not bool: raise ValueError('expected boolean: ' + key) @@ -110,18 +118,45 @@ def read_step(value): skip = [text(v) for v in array(root.get('skip_if', []))] if skip: result['skip_if'] = skip + read_notes(root, result) + return result + + +def read_section(value): + root = fields(value, ('id', 'title', 'notes', 'events')) + result = dict(id=text(root['id']), title=text(root['title'])) + if not result['id']: + raise ValueError('empty section id') + read_notes(root, result) + result['events'] = [read_step(value) for value in array(root['events'])] + if not result['events']: + raise ValueError('section has no events: ' + result['id']) return result def read_checkpoint(value): - root = fields(value, ('id', 'title', 'start', 'events')) + """Read `events`, or named `sections` of events (exactly one of the two).""" + root = fields(value, ('id', 'title', 'notes', 'start', 'events', 'sections')) result = dict(id=text(root['id']), title=text(root['title'])) if not result['id']: raise ValueError('empty checkpoint id') + read_notes(root, result) if 'start' in root: result['start'] = read_pose(root['start']) - result['events'] = [read_step(value) for value in array(root['events'])] - names = [step['id'] for step in result['events']] + if ('events' in root) == ('sections' in root): + raise ValueError('a checkpoint has events or sections, not both or neither') + if 'events' in root: + result['events'] = [read_step(value) for value in array(root['events'])] + steps = result['events'] + else: + result['sections'] = [read_section(value) for value in array(root['sections'])] + if not result['sections']: + raise ValueError('no sections') + ids = [section['id'] for section in result['sections']] + if len(ids) != len(set(ids)): + raise ValueError('duplicate story section ids') + steps = [step for section in result['sections'] for step in section['events']] + names = [step['id'] for step in steps] if len(names) != len(set(names)): raise ValueError('duplicate story event ids') return result diff --git a/src/pokesim/story/test_authored_checkpoint.py b/src/pokesim/story/test_authored_checkpoint.py index b6a0e5d..717bc2a 100644 --- a/src/pokesim/story/test_authored_checkpoint.py +++ b/src/pokesim/story/test_authored_checkpoint.py @@ -30,7 +30,7 @@ def test_rejects_snapshot_fields_and_unsupported_executor_configuration(self): mutations = [lambda p: p.update(native_fields={}), lambda p: p.update(game='bdsp'), lambda p: p['execution'].update(menu='guess'), - lambda p: p['execution'].update(supplies={}), + lambda p: p['execution'].update(supplies={'hp_fill': 1.0}), lambda p: p['checkpoint']['events'].append(p['checkpoint']['events'][0])] for mutate in mutations: plan = copy.deepcopy(original)