Port evolution, Rare Candy, evolution stones and vitamins
Checks / web (push) Canceled after 0s

Pokémon that levelled up evolve after a won battle, following
EvolveAfterBattle's checks over the ROM's evolution bytes, with the
evolution screen that B can stop and move learning outside battle. The pack
uses Rare Candy, stones (with ABLE/NOT ABLE labels) and vitamins, and its
pocket tabs now sit in their own row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sébastien QUEROLandClaude Opus 5.5 committed 2026-09-30 16:21:59 +02:00
1 parent 1af2beacdc
commit 45275ba83b
19 files changed
+1032 -39

No files matched your search

+6 -1
View File
@@ -62,7 +62,12 @@ menu, pausing overworld ticks while choosing the Bicycle. Start opens
the party menu and pack change only the draft, which commits when the menu
closes, and an item that queues a script (the Bicycle) starts it afterwards.
The start menu, party menu and pocket cursors live in the world's memory,
not in saves, and are cleared after each battle. The bedroom PC edits
not in saves, and are cleared after each battle. `scripts/evolution.ts`
translates `EvolveAfterBattle`, `LearnLevelMoves` and `LearnMove` over a
draft. After a won battle the world runs it as an interlude on the battle's
script draft, before the script receives the battle result; the start menu
runs it inline for Rare Candy and stones. The `evolve` effect is a timed
picture sequence that B may stop. The bedroom PC edits
decorations on the script draft and reloads the room when the menu commits.
`scripts/intro.ts` runs a new game's introduction as a native generator on a
script draft; the session starts it only when nothing is saved, and the name,
+54 -1
View File
@@ -32,7 +32,8 @@ These paths refer to the pinned [PRET source](https://github.com/pret/pokecrysta
| Movement interpreter | `macros/scripts/movement.asm`, `engine/overworld/movement.asm`, `engine/overworld/map_objects.asm` | Turns, steps, slides, jumps (two tiles with the original arc), sleeps, facing locks, visibility and emotes. `follow` takes one tile toward the leader's previous square. All movement opcodes decode, including teleport, fishing, skyfall, shake and flicker poses; Controlled reference scenes check spin, teleport, skyfall, fishing and flicker direction, visibility and lift. |
| Specials | `data/events/special_pointers.asm`, `engine/rtc/timeset.asm`, `engine/overworld/decorations.asm` | Selected by routine address from the ROM table: `SetDayOfWeek`, initial DST flags, `RestartMapMusic` (no audio yet), room decoration toggles, `PokemonCenterPC` and `PlayersHousePC` (Bill's, the player's and Oak's PCs), the Town Map, `HealParty`, `HealMachineAnim` (presentation only), `CheckPokerus` and the `StubbedTrainerRankings_Healings` stub. |
| `game/scripts/pc.ts` | `engine/events/pokecenter_pc.asm`, `engine/pokemon/bills_pc_top.asm`, `engine/pokemon/bills_pc.asm`, `engine/events/prof_oaks_pc.asm`, `engine/events/std_collision.asm` | The Pokémon Center and house PCs: Bill's PC (deposit, withdraw, release, change and name boxes), item storage, the empty mail box and Oak's rating. Menu strings and texts come from the ROM; lists are native. Moving Pokémon, the stats screen and printing are not ported. |
| `game/scripts/start-menu.ts` | `engine/menus/start_menu.asm`, `engine/pokemon/mon_menu.asm`, `mon_submenu.asm`, `party_menu.asm`, `switchpartymons.asm`, `engine/items/pack.asm`, `engine/items/item_effects.asm` | The start menu, the party menu with the Pokémon submenu (STATS, SWITCH, MOVE, ITEM) and the pack (USE, GIVE, TOSS) with the field item effects listed below. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu, MAIL, SEL and the other field items give a notice. |
| `game/scripts/start-menu.ts` | `engine/menus/start_menu.asm`, `engine/pokemon/mon_menu.asm`, `mon_submenu.asm`, `party_menu.asm`, `switchpartymons.asm`, `engine/items/pack.asm`, `engine/items/item_effects.asm` | The start menu, the party menu with the Pokémon submenu (STATS, SWITCH, MOVE, ITEM) and the pack (USE, GIVE, TOSS) with the field item effects listed below, including Rare Candy, stones and vitamins. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu, MAIL, SEL and the other field items give a notice. |
| `game/scripts/evolution.ts` | `engine/pokemon/evolve.asm`, `engine/pokemon/learn.asm`, `engine/movie/evolution_animation.asm`, `engine/pokemon/party_menu.asm` | `EvolveAfterBattle`/`EvolvePokemon` over the raw evolution bytes, the evolution texts and a timed, B-stoppable picture sequence, `UpdateSpeciesNameIfNotNicknamed`, `CalcMonStats` and the HP rise, `LearnLevelMoves`, `LearnMove`/`ForgetMove` outside battle and `PlacePartyMonEvoStoneCompatibility`. |
| `game/rom/pokemon.ts` | `data/pokemon/base_stats`, `evos_attacks.asm`, `data/moves/moves.asm`, `data/items/attributes.asm`, `engine/gfx/load_pics.asm` | Species, move and item names, base data, evolution lists, learnsets, move PP, item pockets, growth-rate exp and front pictures (`FixPicBank`, `PadFrontpic`). Starter pictures match rebuilt bytes; all 251 evolution lists match the pinned source. |
| `game/party` | `engine/pokemon/move_mon.asm`, `engine/pokemon/caught_data.asm`, `engine/items/items.asm` | `GeneratePartyMonStats` for script gifts: DVs, `FillMoves`, PP, exp, `CalcMonStatC`, happiness and caught data. `PutItemInPocket`, key items and `TossItem`. `SendMonIntoBox`, `SendGetMonIntoFromBox` (deposit and withdraw), `RestorePPOfDepositedPokemon` and `CalcLevel` for the PC's boxes and item storage. TMs and HMs are refused. |
| Text interpreter | `macros/scripts/text.asm`, `constants/charmap.asm`, `home/text.asm` | Literal/far text, RAM names and string buffers from native state, numbers of dots, and sound or pause cues (consumed). `text_asm` and other RAM reads are refused. |
@@ -332,3 +333,55 @@ tossing, the Bicycle outdoors and indoors, unported effects and saving
while the menu is open. A Chromium/WebKit test opens the menu with Start,
switches Pokémon, changes pockets and tosses a Potion. These are not
emulator comparisons.
## Evolution
The battle's experience routine sets a party member's bit in
`wEvolvableFlags` when it levels up. `ExitBattle` runs `EvolveAfterBattle`
only when `wBattleResult & $0f` is a win; the world then presents it before
the script receives the battle result, on the same draft, so the evolution
commits with the battle. `CleanUpBattleRAM`'s cursor reset follows.
`EvolveAfterBattle` reads `EvosAttacksPointers` and walks each Pokémon's
entries with the original's pointer steps (`.dont_evolve_1/2/3`): trades are
skipped without Link, a forced evolution (a stone) skips every non-item
entry by two bytes, items need `wCurItem` and `wForceEvolution`, levels and
happiness (`HAPPINESS_TO_EVOLVE`, `TR_*` against `wTimeOfDay`) and Tyrogue's
`EVOLVE_STAT` check the copied Pokémon, and an Everstone blocks all but
items. The first match evolves; a stopped evolution goes on to the next
Pokémon. `UpdateSpeciesNameIfNotNicknamed` compares the nickname with the
old species' name (`wBaseDexNo`, which the animation restores).
`CalcMonStats` uses the stat experience; HP rises by the maximum HP's
increase. `LearnLevelMoves` then offers moves at exactly the current level,
and `SetSeenAndCaughtMon` records the species.
`EvolutionAnimation` is presented as a picture schedule in overworld ticks:
40 ticks on the old picture, then seven rounds of a B-checking wait (7 … 1
ticks) and that many flashes (two ticks each way). The waits and flashes
are approximations of the original frame timing; B is accepted only during
the waits and never when `wForceEvolution` is set. No music, cry, palette
or `AnimateFrontpic` is presented.
`LearnMove` outside battle: the first empty slot, otherwise `ForgetMove`
(yes/no, then a move list; `IsHMMove` refuses HM moves), `Text_1_2_and_Poof`
with its `text_asm` continuation, or "Stop learning" (NO asks again) and
"did not learn".
PACK items: `RareCandyEffect` (`CalcExpAtLevel` for the new level, the HP
rise that also revives a fainted Pokémon, `LevelUpHappinessMod` against the
caught landmark, `PARTYMENUTEXT_LEVEL_UP`, a `PrintTempMonStats` page,
`LearnLevelMoves` and an unforced `EvolvePokemon`), `EvoStoneEffect`
(`PARTYMENUACTION_EVO_STONE`'s ABLE/NOT ABLE labels copy ten bytes and step
three at a time, as the original does; bytes past the copy read as the end
here, where the original reads stale RAM) and `VitaminEffect`
(`StatExpItemPointerOffsets`, the high byte limit of 100, `StatStrings`,
`ItemStatRoseText` and `HAPPINESS_USEDITEM`).
Tests: `tests/start-menu.test.ts` covers the Rare Candy level-up, stat page,
HM refusal, forgetting and declining a move, the revived fainted Pokémon,
evolution with and without B, a stone (ABLE labels, no effect on another
species or with an Everstone, B ignored, a kept nickname) and a vitamin up
to its limit. `tests/battle-world.test.ts` wins a wild battle whose level-up
evolves Cyndaquil, and checks that a non-participant that could evolve does
not. A Chromium/WebKit test evolves through a Rare Candy. No emulator
comparison of these routines yet.
+14 -4
View File
@@ -169,7 +169,16 @@ The numbered sections below keep their full scope. Each one opens with a checkli
- PACK: the Items, Balls, Key and TM pockets (left and right change pockets; there are no TMs or HMs yet), and each item's submenu chosen by its permissions and field menu (`USE`, `GIVE`, `TOSS`, `SEL`, `QUIT`). TOSS asks how many and confirms. USE follows `UseItem`: Oak's warning without a field use, "You don't have a POKéMON!" for party items without one, and `_DoItemEffect` by the item's `ItemEffects` address: Potions and the other `HealingHPAmounts` items, status healers, Full Restore, Revive and Max Revive, the bitter Energypowder, Energy Root, Heal Powder and Revival Herb, Ethers, Elixers, the MysteryBerry and PP Up. The Bicycle closes the menu and runs `Script_GetOnBike` or `Script_GetOffBike` outdoors; elsewhere Oak objects, because `wFieldMoveSucceeded` shares `wItemEffectSucceeded`'s byte.
- PP Up keeps a quirk: `wUsePPUp` shares `wTempPP`'s byte, so `ComputeMaxPP` adds one step (a fifth of the base PP, at most 7) to the current PP as well as the maximum. Sketch and moves with three PP Ups are "maxed out".
- The menu runs on a script draft, like the PC. Changes commit when it closes; a save made while it is open keeps the state from before it. The start menu cursor, the party menu cursor and the last pocket stay in memory between openings and are cleared after a battle, as `CleanUpBattleRAM` does. The party cursor reaches the next battle's `ChangeHappiness`.
- Select keeps opening the Key Items shortcut, standing in for a registered item. Not ported: field moves from the menu, MAIL, SEL (registering items), moving a Pokémon's moves to another party member with left and right, item reordering with Select, evolution stones, Rare Candy, vitamins and the other field items (each gives a notice and changes nothing).
- Select keeps opening the Key Items shortcut, standing in for a registered item. Not ported: field moves from the menu, MAIL, SEL (registering items), moving a Pokémon's moves to another party member with left and right, item reordering with Select and the remaining field items such as Repel and Escape Rope (each gives a notice and changes nothing). Rare Candy, evolution stones and vitamins run since the evolution section below.
## Implemented: evolution
- `EvolveAfterBattle` runs after every won battle for the party members that levelled up (`wEvolvableFlags`, now recorded by the battle's experience routine), before the script resumes. Level, happiness (220 or more, by time of day) and Tyrogue's Attack/Defense evolutions follow the original checks, including the Everstone. The evolution data is walked byte by byte like the original, so a forced evolution skips a four-byte `EVOLVE_STAT` record the way the original does. Trades never evolve without Link mode.
- The evolution screen shows "What? … is evolving!", then the old picture flashing into the new one on the original schedule (80 frames, then seven rounds of flashes). B stops it only during the waits between flashes, and never for a stone. A stopped evolution prints "Huh? … stopped evolving!" and skips that Pokémon's other entries.
- After evolving: the species name replaces the nickname only if the nickname was the old species name, stats are recomputed with stat experience, HP rises by the maximum HP's increase, moves learned at exactly the current level are offered, and the Pokédex records the new species as seen and caught.
- Learning a move outside battle follows `LearnMove`: an empty slot, or "delete an older move?", the choice of a move (HM moves can't be forgotten), "1, 2 and… Poof!", or "Stop learning …?" and "did not learn".
- PACK: Rare Candy (`RareCandyEffect`: one level at the level's minimum experience; the HP gains the maximum HP's increase even for a fainted Pokémon; the caught-location happiness bonus; "grew to level", the stat box, new moves and a possible evolution), evolution stones (`EvoStoneEffect`: a forced `EvolvePokemon`; the party menu shows ABLE or NOT ABLE with the original's ten-byte, three-byte-step check; an Everstone or no matching evolution has no effect) and vitamins (`VitaminEffect`: ten more in the stat experience's high byte, up to 100, stats recomputed without changing the current HP, happiness).
- Not presented: the evolution music, cries and the palette changes. Trade evolutions need Link.
## Native battles: current state
@@ -235,7 +244,7 @@ their scripts and story progression are supported.
- [x] Native player, party, Pokémon, bag, money and quest models with versioned saves
- [x] Typed ROM decoders for species, moves, growth rates, items, encounters and trainers
- [x] Decoder for evolutions (the evolution itself is not ported yet)
- [x] Decoder for evolutions, and evolution after battles and from items (see section 3)
- [x] Mom, Elm's introduction, the starter, naming and the aide's Potion
- [x] Route 29, Cherrygrove City, the Poké Mart and the Pokémon Center
- [x] Route 30's trainers, Mr. Pokémon's house, the Mystery Egg and the Pokédex
@@ -253,7 +262,7 @@ Introduce native player, party, Pokémon, inventory, money and quest models. Rea
Expand script calls, choices, scene state, inventory commands and native special handlers. Translate routines reached through assembly calls into explicit native services; never fall back to emulator execution in the shipping game.
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle. Next: evolution, then MOVE PKMN W/O MAIL.
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle, and Pokémon evolve. Next: MOVE PKMN W/O MAIL, SEL and field moves from the menu, then the Pokégear.
Complete and validate the native battle engine: deterministic randomness, stats, move selection, accuracy/critical checks, damage, status, turn order, switching, fainting, experience, capture and rewards. Compare controlled seeds and states with the original, including integer rounding and overflow behavior.
@@ -263,7 +272,8 @@ Acceptance: finish the opening quest, including encounters and the rival battle,
- [x] Pokémon Center healing, standard Poké Marts and Reflect/Light Screen
- [ ] Remaining battle commands, move and item effects, AI layers and special battles
- [ ] Evolution, breeding, happiness, eggs and PC storage
- [x] Evolution by level, happiness, Tyrogue's stats and stones, with Rare Candy and vitamins (trade evolutions need Link)
- [ ] Breeding, eggs and the rest of PC storage
- [ ] Field moves, gyms, Rocket events, the phone and Pokégear, puzzles, minigames, daily events, roaming Pokémon and the postgame
- [ ] Johto beyond Route 30, the League, Kanto and the final battle
- [ ] Music and sound through Web Audio
+35 -2
View File
@@ -1,7 +1,6 @@
# Recovered Claude session
Latest continuation: see **Start menu, party menu and pack: 2026-09-30**
at the end of this file. Earlier sections are historical snapshots.
Latest continuation: see **Evolution: 2026-09-30** at the end of this file. Earlier sections are historical snapshots.
Recovered on 2026-09-23 from the local Claude Code transcript
`~/.claude/projects/-Users-kawa-Crystal/4ac88f30-29e6-4fd5-a4b2-b6a318dd83b3.jsonl`.
@@ -729,3 +728,37 @@ and reference builds, reference, vendor and release checks; `git diff
Next: evolution (`EvolveAfterBattle` after battles and from stones/Rare
Candy, with the level-up flags the battle must record), then vitamins,
MOVE PKMN W/O MAIL, SEL/registered items and field moves from the menu.
The start menu increment was committed and pushed as `1af2bea`.
## Evolution: 2026-09-30
Continued in the same session after `1af2bea`.
- `src/game/scripts/evolution.ts` (`PartyEvolution`): `EvolveAfterBattle`
walking the raw evolution bytes with the original's skip counts
(forced evolutions misread `EVOLVE_STAT` like the original), the texts,
a timed `evolve` effect (40 ticks, then seven wait/flash rounds; B only in
the waits and never for stones), nickname update only for unnicknamed
Pokémon, stats with stat experience, HP rise, `LearnLevelMoves`,
`LearnMove`/`ForgetMove` outside battle, and the Pokédex.
- The battle records `wEvolvableFlags` on level-up and returns them; after a
win the world runs the evolution as a script interlude before resuming
the battle's script (same draft, commits together).
- PACK: Rare Candy (level, exp, HP rise that revives, happiness, level-up
text, stat page, moves, evolution), evolution stones (ABLE/NOT ABLE party
labels with the original 10-byte/3-step check; Everstone and no-match
have no effect) and vitamins (stat experience high byte +10 up to 100).
- UI: the picture box shows the flashing evolution; the pack's pocket tabs
moved into their own compact row (`#mart-tabs`).
Checks: 360 unit tests with the local ROM (5 new start-menu evolution
tests, 2 new battle-world tests); 111 Chromium/WebKit browser tests passed,
19 skipped intentionally (a new Rare Candy evolution flow in both
browsers); native and reference builds, reference, vendor and release
checks; `git diff --check`. No emulator comparison of evolution or the
menus; no CI or physical-device run.
Next: MOVE PKMN W/O MAIL, SEL/registered items with Select, field moves
from the menu (Cut, Surf, Strength already have their ROM scripts), then
the Pokégear. Trade evolutions wait for Link.