Commit graph

271 commits

Author SHA1 Message Date
acamilo
862e343e1c docs: v0.6.2 status
Some checks failed
ci / node 22 (test + typecheck) (push) Has been cancelled
ci / rust stable (cargo test --workspace --release) (push) Has been cancelled
ci / infra/tests/lint.sh (push) Has been cancelled
ci / playwright apps/stage (allowed to fail) (push) Has been cancelled
2026-09-23 23:48:20 +00:00
acamilo
d0ce10e3c9 Merge fix/loop-row61: a trainer's challenge is the cartridge's until its battle is over 2026-09-23 23:48:20 +00:00
acamilo
9b117dc4b2 docs: 12.25 and the row 61 audit on top of row 59, the bubble, game.scene in macros mode 2026-09-23 23:47:36 +00:00
acamilo
cff15804fb state, tests: the challenge covers the "!" bubble too, the doc block back above its impl, and the ROM test asserts no pad inside a challenge 2026-09-23 23:47:36 +00:00
acamilo
d6597b3e98 docs: the row 61 audit, a trainer's challenge text walled the forest's corridor 2026-09-23 23:28:17 +00:00
acamilo
0117a85354 docs: macros.md 12.24, a trainer's challenge is the cartridge's until its battle is over 2026-09-23 23:28:12 +00:00
acamilo
c78ca352f6 tests: the ROM proof from the forest's south gate checkpoint 2026-09-23 23:28:05 +00:00
acamilo
0e366cd4e4 state: a trainer's challenge is the cartridge's until its battle is over, in the macros' own scene 2026-09-23 23:27:54 +00:00
acamilo
16bc65b5a8 survey: FLY_PROBE_CATCH_FRAME reads the first free frame from a given one, FLY_PROBE_WHOLE prints a big map whole 2026-09-23 23:27:54 +00:00
acamilo
510727ccc0 docs: v0.6.1 status
Some checks are pending
ci / node 22 (test + typecheck) (push) Waiting to run
ci / rust stable (cargo test --workspace --release) (push) Waiting to run
ci / infra/tests/lint.sh (push) Waiting to run
ci / playwright apps/stage (allowed to fail) (push) Waiting to run
2026-09-23 23:08:10 +00:00
acamilo
f32352bd5e Merge fix/loop-row59: the map graph as the cartridge's headers and warps draw it, pieces and all 2026-09-23 23:08:09 +00:00
acamilo
9ccc0592b1 docs: macros.md 12.24 and the row 59 audit 2026-09-23 22:33:47 +00:00
acamilo
437dfa84a9 tests: from the live Route 4 checkpoint, the fly goes into Mt. Moon and Route 4's west doors are not a ring 2026-09-23 22:33:47 +00:00
acamilo
d181f952a7 tests: from the badge, the road to Mt. Moon is not a ring at the Pewter end, and Route 4's doors and sides are the cartridge's 2026-09-23 22:23:27 +00:00
acamilo
5147ab1a87 geography: a header connection no step on foot crosses is named and is not a way out; Pallet's shore, the sea routes, the League fence 2026-09-23 22:23:01 +00:00
acamilo
97a97a501d geography: a split map is pieces with their own doors and neighbours; Route 4 and Mt. Moon's lower floors, the hop matched on where an exit lands 2026-09-23 22:23:01 +00:00
acamilo
4108fec5ce macros: a push-back is a refusal once the overworld has stayed the fly's for half a second, not on the first frame of it 2026-09-23 22:23:01 +00:00
acamilo
d85ee5026f geography: Route 3/4, 14/15 and 24/25 as the headers connect them, and Mt. Moon's doors on Route 4 2026-09-23 22:23:01 +00:00
acamilo
288e958d19 survey: FLY_PROBE_SAVE_RANK writes the first safe overworld frame at a rung as a checkpoint 2026-09-23 22:23:01 +00:00
acamilo
4d82f7db74 Merge refactor/legacy-frame: FND-01, one LegacyFrame for the service and every harness, FLY_TRACE and the sugar journal 2026-09-23 21:43:45 +00:00
acamilo
2f7b7cebd0 docs: v0.6.0 status
Some checks are pending
ci / node 22 (test + typecheck) (push) Waiting to run
ci / rust stable (cargo test --workspace --release) (push) Waiting to run
ci / infra/tests/lint.sh (push) Waiting to run
ci / playwright apps/stage (allowed to fail) (push) Waiting to run
2026-09-23 21:23:57 +00:00
acamilo
ff49b56e2c docs: the explore row stays "new place" 2026-09-23 21:23:40 +00:00
acamilo
b484a077d4 stage: the explore row reads "new place" again (the operator, 2026-09-23) 2026-09-23 21:23:05 +00:00
acamilo
9301e395e8 docs: the trap hunt and the bench run the service's frame since FND-01, and hunts across the change do not compare 2026-09-23 20:15:20 +00:00
acamilo
9e2f90749f flysim: FLY_TRACE's boundary half read back with fly-session-types, the journal held to the service test, rustfmt on the new files 2026-09-23 20:15:20 +00:00
acamilo
60f09b79a3 flysim: every harness runs the legacy frame: the trap hunt, the benches, the ROM tests' and the probe's stub drivers
trap_hunt, palette_bench and room_escape ran the frame through NeuralAgent::tick, which installs
a frame and its rewards after the next ticks: one frame behind the stream, with the ratchet
observed without the objective signal and a rollback that never re-observed the scene. They now
restore the way the stream restores and run LegacyFrame::transition and ::boundary, looking in
through FrameObserver; FLY_TRACE works in each of them. The stub-readout drivers of
rom_macros_mode, rom_catch and scene_probe run LegacyFrame::execute and ::stub_advance, which are
the same calls they made, in the same order.
2026-09-23 20:15:20 +00:00
acamilo
ad1c0e3693 flysim: a frame-stamped sugar journal in the hot directory
Every admitted sugar and operator reward pulse is appended to sugar-journal.jsonl with the frame
counter it was applied at, which is the step of the next transition in FLY_TRACE, so a shadow run
can replay the audience's input. Append-only, not checkpointed, never read back into the fly.
2026-09-23 20:14:01 +00:00
acamilo
94cc91369a flysim: the legacy frame is one type, flysim::frame::LegacyFrame, and the sim loop runs it
prepare, execute, advance, evaluate, commit, then the boundary's ratchet capture and rollback,
in the order the stream runs them. The frame owns the remainder, the frame counter, the frame on
screen, the mask and the blocked-direction window; the sim loop keeps the feed, the event log,
the milestone archive between commit and boundary, and the checkpoints. Two moves between
disjoint state change no byte: the visual frame is installed at commit, and the stimulations
follow the scene's observation. The FLY_TRACE of a run from the rung-10 checkpoint is
byte-identical to the one the inline hooks wrote.
2026-09-23 20:14:00 +00:00
acamilo
ff74c07622 flysim: FLY_TRACE, a per-frame trace of the legacy loop in the step trace's field names
One JSON line per transition: ticks and the exact remainder, digests of the rates, of the
transition's spikes, of the frame and of work RAM, the decision and the mask, macro and reward
events in order, the rank, and the boundary's slot saves, rollback and captures in the shape of
TraceBehaviour.boundaryActions and TraceOperational.captures. Off unless FLY_TRACE names a file.
Recorded inline in step_frame first, so the frame's extraction can be held to it.
2026-09-23 20:14:00 +00:00
acamilo
bc117ad470 flybrain-gb: say what a move with power does not promise 2026-09-23 19:23:48 +00:00
acamilo
fa021918b4 Merge fix/loop-row60: a move the cartridge would refuse is not dealt beside one that works 2026-09-23 19:23:43 +00:00
acamilo
4591e7907a docs: macros.md 12.23, macros-wram.md section 13, the row 60 audit 2026-09-23 17:59:29 +00:00
acamilo
07f88c443a tests: the ROM proof from the Route 1 checkpoint 2026-09-23 17:23:05 +00:00
acamilo
b33af9e772 scene_probe: the route survey prints the battle bytes a MOVE n button's effect rests on 2026-09-23 17:23:05 +00:00
acamilo
a02d5f7995 trap_hunt: payouts by kind, battle lengths and wins, and MOVE n on a move without effect 2026-09-23 17:23:05 +00:00
acamilo
f3e3e9cf98 palette: a move the cartridge answers with nothing is not dealt beside one it does not
Row 60: TAIL WHIP against a Pidgey at DEFENSE -6 was MOVE 2 183 times. The
rule is PP's: a refused move leaves the pad while another move is usable, and
with none usable the moves stay as PP deals them, so an open list never
comes down to BACK alone.
2026-09-23 17:23:05 +00:00
acamilo
438b2d8540 state: the move table, and whether the battle engine will answer a move with nothing
move_data reads a row of Moves from the cartridge image ($0E:$4000, each row
checked against its own id); move_without_effect answers the refusals the
effect routines make on bytes already in WRAM: a stat stage at its limit or a
stat at 1/999, Mist or a substitute against a stat-lowering move, a status
move against a statused, Poison-type or (Electric) Ground-type target.
MacroState::move_without_effect defaults to false.
2026-09-23 17:23:05 +00:00
acamilo
c8ecf06db5 symbols: the stat stages and the enemy's status, type and stats, resolved from wram.asm
resolve_wram.py now follows the decomp's const and _RS counters and a struct
macro's field labels, so battle_struct fields resolve and 77 of 81 pinned
addresses are re-derived with no disagreement.
2026-09-23 17:23:05 +00:00
acamilo
37adeb9417 docs: a map script's text can pay talk when it names the thing in front, and where it can 2026-09-23 17:22:11 +00:00
acamilo
5d527f0910 Merge feat/engage-reward: the fly is paid for talking to people indoors and picking up items, not for leaving buildings (adapter v7) 2026-09-23 17:20:02 +00:00
acamilo
56b02ff758 rewards: a frame on which no item bit moved reads nothing more 2026-09-23 14:34:10 +00:00
acamilo
8d1d5c44f5 docs: the engagement rewards, and the v6 migration in deploy examples
rewards-learning.md carries the v7 table, the definition of indoors, the four
conditions a conversation pays under, the item and hidden-item reads, the seed,
boundary's indoor rule with the warp-transition frame it was measured on, the
feed-kind choice and the ticker word, and the honesty note on paying for a
conversation. flysim.md records the v6 -> v7 migration; macros-wram.md the six
new reads; the architecture tour and integration.md point at the live catalog.
The deploy comments, example.env and the runbook name FLY_ACCEPT_ADAPTERS=
pokered-unique8-v6 for the v0.6.0 deploy.
2026-09-23 14:34:10 +00:00
acamilo
3cf706c96a rewards: read the conversation's argument once the cartridge has written it, and a ROM test
The first cartridge run found what the synthetic trace could not. In the
Viridian Forest north gate the font bit rose on one frame and DisplayTextID's
argument reached wSpriteIndex twenty frames later: DisplayTextIDInit loads the
font's tiles into VRAM first. Until then the byte still names the previous
text's subject, which may be the person in front of the fly from a conversation
that did not pay. So the watch now remembers the byte from the last ready
frame and reads it once, when it changes or after 45 samples, and only while
the bottom dialogue box is drawn (the start menu draws its own elsewhere); a
box that closes first is read on the closing sample if the dialogue box was up.

tests/rom_engage.rs, gated on FLY_ROM and FLY_ENGAGE_CHECKPOINT: from the rung-10
Pewter checkpoint, with the checkpoint's own v6 ledger restored (the migration,
on real game state), a scripted walker goes down Route 2 into the forest's north
gate, talks to the old man three times (one payout, 0.10) and picks up the
Antidote ball at (25, 11) (one payout, 0.15, "FOUND ITEM #11"); pressing A at
the empty tile pays nothing, and after rolling the emulator back to before the
pickup, taking it again pays nothing. No boundary payout lands while an indoor
header is loaded.

It also measured the warp transition: for about thirty frames of
PlayMapChangeSound wCurMap already names the destination while the tileset and
warp table are still the map being left, so the exit the fly stands on is
classified by the map it belongs to -- a town door still pays its on-exit half,
keyed under the building's id as before, and a building's door does not. A unit
test pins both directions.
2026-09-23 14:34:10 +00:00
acamilo
2d288b0146 stage: the explore row reads "new find"
Since pokered-unique8-v7 the explore feed kind carries four adapter rules --
new ground, an exit, a conversation indoors, an item picked up -- and "new
place" was true of the first two only. The per-game copy now names what all
four are; the feed protocol and the kind set are unchanged.
2026-09-23 14:34:10 +00:00
acamilo
52811bf512 session types: the legacy composition names pokered-unique8-v7
The example composition's adapter and FLYSIM01 string move to v7 with the live
adapter, and the fixtures are regenerated by update_fixtures; valid.json and
invalid.json's hand-written cases follow, with the one deliberately mismatched
string moving from v5 to v6 so it is still the previous adapter.
2026-09-23 14:34:10 +00:00
acamilo
2e7eed0a78 rewards: talk and item, boundary indoors pays nothing, adapter v7 with a v6 migration
The operator's decision of 2026-09-23: pay the fly for engaging with what is
inside a building, and stop paying it for walking back out of one. Chosen over
a pad rule and over weighting the choice, and like v0.5.0's catch reward it is
a catalog change, not a loop-review fix.

Indoors. engage::indoor is two of the cartridge's own tables: not outside by
CheckIfInOutsideMap (tileset OVERWORLD or PLATEAU; WarpFound2 labels the other
branch .indoorMaps) and not a place BikeRidingTilesets lets the bike be ridden
(OVERWORLD, FOREST, UNDERGROUND, SHIP_PORT, CAVERN). That is every house, mart,
center, gym, gate, lab, museum, ship, tower, mansion and hideout, and not
Viridian Forest, a cave, the Underground Path or the dock.

`talk`, +0.10, 100 ms, the catalog's tenth kind. Paid when the text box closes
on a conversation that (1) opened on the sample after one where the fly had the
joypad (state::controllable) and was standing still (wWalkCounter zero, the only
state the overworld reads A in) on the same tile; (2) is with the thing in
front: DisplayTextID copies its argument into wSpriteIndex, a sprite slot up to
wNumSprites whose sprite stands on the tile the player faces (or one further
across a counter, on a tileset with counter tiles), or a text id matching the
sign on that tile; an item ball is not a person; (3) opened indoors; (4) closed
on the same map. Keyed talk:<map>:sprite:<slot> / talk:<map>:sign:<id> in the
lifetime `seen` ledger, which is checkpointed and survives a rollback -- not the
macros' session `talked` ledger.

`item`, +0.15, 120 ms, the eleventh. An item ball is a toggleable sprite of this
map (wToggleableObjectList) whose wMapSpriteExtraData is (item id, 0), the shape
LoadMapHeader writes for an ITEM object_event and nothing else; PickUpItem sets
its global bit in wToggleableObjectFlags after GiveItem succeeds. A hidden item
is a bit of wObtainedHiddenItemsFlags, set by FoundHiddenItemText after GiveItem
and by nothing else. Either pays when its bit rises between two playable
samples, once per item (item:<global> / hidden:<index>) for the ledger's life.

`boundary` still writes every key indoors, so exit_visited answers what it did
and the macros see no change, but emits nothing on an indoor map. Outdoor,
forest and cave exits pay as before.

v6 -> v7. STATE_VERSION stays 4 and no field is added: the new ledgers are keys
in `seen`. A v6 state restores with no talk: keys, and the first playable sample
that finds `items:seeded` absent writes one key per item the game already shows
as taken, pays for none, and marks the seed -- so a rollback that un-takes a v6
pickup cannot pay for it. The two item balls a script reveals (the Rocket
Hideout's Silph Scope and Lift Key, toggles $87 and $88, the only ITEM entries
toggleable_objects.asm starts OFF) are left out of the seed. MIGRATES_FROM is
["pokered-unique8-v6"]; v5 is no longer migrated.

Feed kinds: both publish on `explore`, the family of new ground and a door found,
at the same quiet scale; not `area` (maps, notable), `story` or `wildwin`. No
feed-protocol change.

The compatibility string differs from main's in exactly one segment:
pokered-unique8-v6 -> pokered-unique8-v7.

Tests: catalog values and order; indoor over all 24 tilesets; a talk pays once
per (map, object), not while the box is open, not re-talked, not outdoors/in the
forest/in a cave, not for text opened with the joypad taken, simulated, scripted,
mid-step, about someone not in front, or the start menu; not across a warp or a
rollback; counter reach only with counter tiles; item balls, people, trainers,
hidden items, the seed and the script-shown balls; boundary indoors records and
pays nothing; a v6 state and a v6 FLYSIM01 envelope migrate with the new ledgers
empty and the items seeded. rom.rs's bedroom walk now proves the stairs are
recorded and unpaid on the cartridge.
2026-09-23 14:34:10 +00:00
acamilo
ed0080ab2c symbols: the six WRAM names the engagement rewards read
wSpriteIndex, wWalkCounter, wMapSpriteExtraData, wToggleableObjectFlags,
wToggleableObjectList and wObtainedHiddenItemsFlags, resolved by
tools/resolve_wram.py from ram/wram.asm at the pinned commit and bracketed by
addresses symbols.rs already carries. Two of the brackets needed the tool to
count NUM_STATS and NUM_CITY_MAPS, which the decomp defines as const_value over
an enumeration; both are now counted up to the line that defines them.
2026-09-23 14:34:10 +00:00
acamilo
7784a9d172 docs: v0.5.5 status
Some checks are pending
ci / node 22 (test + typecheck) (push) Waiting to run
ci / rust stable (cargo test --workspace --release) (push) Waiting to run
ci / infra/tests/lint.sh (push) Waiting to run
ci / playwright apps/stage (allowed to fail) (push) Waiting to run
2026-09-23 13:43:21 +00:00
acamilo
6fd6d840dc Merge fix/loop-row58: the gym's people are there when the screen does not draw them, and the game's own moves write no ledger 2026-09-23 13:43:18 +00:00
acamilo
0f510c93aa infra(05-deploy): refuse a bad FLY_FEED_VIA before the release is flipped, not half way through 2026-09-23 13:13:59 +00:00