Port field moves from the menu, SEL with Select, and moving Pokémon in Bill's PC
Checks / web (push) Canceled after 0s

Field moves chosen in the party menu run their original checks and the
ROM's from-menu scripts (Cut, Surf, Strength, Flash, Whirlpool, Waterfall,
Sweet Scent), and Softboiled and Milk Drink share HP. SEL registers a key
item that Select then uses, replacing the Key Items shortcut, and Bill's
PC moves Pokémon between the party and every box.

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 17:22:56 +02:00
1 parent 45275ba83b
commit 3456aa4e11
25 files changed
+1129 -186

No files matched your search

+109
View File
@@ -226,6 +226,115 @@ describe.skipIf(!existsSync(romPath))("the Pokémon Center PC", () => {
expect(world.save()).toEqual(saved);
});
it("moves Pokémon between the party and boxes without mail", () => {
const world = fixture();
const data = world.assets.pokemon;
const [cyndaquil, pidgey] = world.state.party;
pidgey.hp = 1;
pidgey.pp = [1, 0, 0, 0];
const boxed = toBoxMon(
generatePartyMon(data, {
species: 19, // RATTATA
level: 6,
item: 0,
otId: world.playerId,
ot: "CHRIS",
dvs: 0x1234,
caughtData: 0,
}),
);
world.state.storage.boxes[0] = [boxed];
open(world);
pick(world, "BILL's PC");
expect(pick(world, "MOVE POKéMON W/O MAIL")).toEqual([
"Each time you move a POKéMON, data will be saved. OK?",
]);
world.choose(1);
until(world);
// The party, then the fourteen boxes, with the current box highlighted.
const boxes = world.dialogue?.choice;
expect(boxes?.kind === "menu" && [boxes.items.length, boxes.selected]).toEqual([15, 1]);
expect(menuItems(world)[0]).toBe("PARTY POKéMON");
// PIDGEY from the party to the end of BOX1: its PP are restored.
pick(world, "PARTY POKéMON");
pick(world, /^PIDGEY/);
expect(menuItems(world)).toEqual(["MOVE", "STATS", "CANCEL"]);
pick(world, "MOVE");
pick(world, "BOX1");
expect(menuItems(world)).toEqual(["RATTATA", "▶"]);
pick(world, "▶");
// RATTATA from BOX1 to the front of the party, with full HP.
pick(world, "BOX1");
pick(world, /^RATTATA/);
pick(world, "MOVE");
pick(world, "PARTY POKéMON");
pick(world, /^CYNDAQUIL/);
expect(world.liveState.party.map((mon) => mon.species)).toEqual([19, 155]);
// Within the party: RATTATA to the end.
pick(world, "PARTY POKéMON");
pick(world, /^RATTATA/);
pick(world, "MOVE");
pick(world, "PARTY POKéMON");
pick(world, "▶");
close(world);
expect(world.state.party.map((mon) => mon.species)).toEqual([155, 19]);
const rattata = world.state.party[1];
expect(rattata.hp).toBe(rattata.stats[0]);
expect(rattata.stats).toEqual(calcStats(data, 19, 0x1234, 6, rattata.statExp));
expect(world.state.storage.boxes[0].map((mon) => mon.species)).toEqual([16]);
expect(world.state.storage.boxes[0][0].pp[0]).toBe(data.move(pidgey.moves[0]).pp);
expect(cyndaquil.species).toBe(155);
});
it("keeps the last Pokémon and refuses a full destination when moving", () => {
const world = fixture();
const data = world.assets.pokemon;
world.state.party = [world.state.party[0]];
const full = Array.from({ length: 20 }, () =>
toBoxMon(
generatePartyMon(data, {
species: 16,
level: 3,
item: 0,
otId: world.playerId,
ot: "CHRIS",
dvs: 0,
caughtData: 0,
}),
),
);
world.state.storage.boxes[1] = full;
world.state.storage.boxes[2] = [structuredClone(full[0])];
world.state.storage.boxes[2][0].nickname = "SPARE";
open(world);
pick(world, "BILL's PC");
pick(world, "MOVE POKéMON W/O MAIL");
world.choose(1);
until(world);
pick(world, "PARTY POKéMON");
expect(pick(world, /^CYNDAQUIL/)).toEqual(["What's up?"]);
expect(pick(world, "MOVE")).toContain("It's your last POKéMON!");
// BOX3 into the full BOX2: no room, and the position is chosen again.
pick(world, "BOX3");
pick(world, /^SPARE/);
pick(world, "MOVE");
pick(world, "BOX2");
expect(pick(world, "▶")).toContain("There's no room!");
// B leaves the destination list for the list of boxes to move from.
world.advanceDialogue();
until(world);
// Within the full BOX2 a Pokémon can still move.
pick(world, "BOX2");
pick(world, /^PIDGEY/);
pick(world, "MOVE");
pick(world, "BOX2");
expect(pick(world, "▶")).toContain("Saving… Leave ON!");
close(world);
expect(world.state.storage.boxes[1]).toHaveLength(20);
expect(world.state.storage.boxes[2].map((mon) => mon.nickname)).toEqual(["SPARE"]);
expect(world.state.party).toHaveLength(1);
});
it("opens the stats screen from Bill's PC for party and boxed Pokémon", () => {
const world = fixture();
const data = world.assets.pokemon;