Open Kanto: the S.S. Aqua, the Kanto gyms, the Magnet Train, Mt. Silver and Red (Closes #33)
All 146 Kanto maps, Route 22, Route 28 and Silver Cave are open. The Magnet Train, Snorlax and the Poké Flute channel, the Diploma, the Trainer House, Bill's grandpa, Oak's Pokédex rating in Pallet and Goldenrod's postgame move tutor are ported; big objects cover 2x2 tiles. The Magnet Train and the Diploma are compared with the cartridge frame by frame. The playthrough continues from the Hall of Fame through the S.S. Aqua, the eight Kanto badges, Oak opening Mt. Silver and Red's defeat and credits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f05fd8ebee
commit
d3be732118
22 files changed
+1877
-31
No files matched your search
@@ -238,6 +238,98 @@ const HM07 = 0xf9,
|
||||
EVENT_BEAT_ELITE_4_KAREN = 0x5bb,
|
||||
EVENT_BEAT_CHAMPION_LANCE = 0x5bc,
|
||||
EVENT_BEAT_ELITE_FOUR = 0x44;
|
||||
const FAST_SHIP_1F = "15:3",
|
||||
FAST_SHIP_CABINS_NNW = "15:4",
|
||||
FAST_SHIP_CABINS_SE = "15:6",
|
||||
FAST_SHIP_B1F = "15:7",
|
||||
OLIVINE_PORT = "15:1",
|
||||
OLIVINE_PORT_PASSAGE = "15:8",
|
||||
VERMILION_PORT_PASSAGE = "15:9",
|
||||
VERMILION = "12:3",
|
||||
VERMILION_CENTER = "12:5",
|
||||
VERMILION_GYM = "12:11",
|
||||
ROUTE_6 = "12:1",
|
||||
ROUTE_6_SAFFRON_GATE = "12:12",
|
||||
SAFFRON = "25:2",
|
||||
ROUTE_5 = "25:1",
|
||||
ROUTE_5_SAFFRON_GATE = "25:14",
|
||||
SAFFRON_GYM = "25:4",
|
||||
SAFFRON_MART = "25:5",
|
||||
SAFFRON_CENTER = "25:6",
|
||||
CERULEAN = "7:17",
|
||||
CERULEAN_CENTER = "7:4",
|
||||
CERULEAN_GYM = "7:6",
|
||||
POWER_PLANT = "7:10",
|
||||
ROUTE_9 = "7:13",
|
||||
ROUTE_10_NORTH = "7:14",
|
||||
ROUTE_24 = "7:15",
|
||||
ROUTE_25 = "7:16",
|
||||
ROCK_TUNNEL = ["3:87", "3:88"],
|
||||
ROUTE_10_SOUTH = "18:3",
|
||||
LAVENDER = "18:4",
|
||||
LAVENDER_CENTER = "18:5",
|
||||
LAVENDER_RADIO_TOWER = "18:12",
|
||||
ROUTE_8 = "18:1",
|
||||
ROUTE_8_SAFFRON_GATE = "18:13",
|
||||
DIGLETTS_CAVE = "3:84",
|
||||
ROUTE_2 = "23:1",
|
||||
VIRIDIAN = "23:3",
|
||||
ROUTE_22 = "23:2",
|
||||
VIRIDIAN_GYM = "23:4",
|
||||
VIRIDIAN_CENTER = "23:9",
|
||||
PEWTER = "14:2",
|
||||
PEWTER_GYM = "14:4",
|
||||
PEWTER_CENTER = "14:6",
|
||||
ROUTE_1 = "13:1",
|
||||
PALLET = "13:2",
|
||||
OAKS_LAB = "13:6",
|
||||
CINNABAR_CENTER = "6:1",
|
||||
ROUTE_19_FUCHSIA_GATE = "6:3",
|
||||
SEAFOAM_GYM = "6:4",
|
||||
ROUTE_19 = "6:5",
|
||||
ROUTE_20 = "6:6",
|
||||
ROUTE_21 = "6:7",
|
||||
CINNABAR = "6:8",
|
||||
FUCHSIA_GYM = "17:8",
|
||||
ROUTE_18 = "17:4",
|
||||
FUCHSIA = "17:5",
|
||||
FUCHSIA_CENTER = "17:10",
|
||||
ROUTE_7 = "21:1",
|
||||
ROUTE_17 = "21:3",
|
||||
CELADON = "21:4",
|
||||
CELADON_CENTER = "21:17",
|
||||
CELADON_GYM = "21:21",
|
||||
ROUTE_7_SAFFRON_GATE = "21:25",
|
||||
ROUTE_17_ROUTE_18_GATE = "21:26",
|
||||
ROUTE_28 = "19:1",
|
||||
SILVER_CAVE_OUTSIDE = "19:2",
|
||||
SILVER_CAVE_CENTER = "19:3",
|
||||
SILVER_CAVE = ["3:74", "3:75"],
|
||||
SILVER_CAVE_ROOM_3 = "3:76";
|
||||
const S_S_TICKET = 0x44,
|
||||
MACHINE_PART = 0x80,
|
||||
ENGINE_EXPN_CARD = 3,
|
||||
ENGINE_BOULDERBADGE = 0x23,
|
||||
ENGINE_CASCADEBADGE = 0x24,
|
||||
ENGINE_THUNDERBADGE = 0x25,
|
||||
ENGINE_RAINBOWBADGE = 0x26,
|
||||
ENGINE_SOULBADGE = 0x27,
|
||||
ENGINE_MARSHBADGE = 0x28,
|
||||
ENGINE_VOLCANOBADGE = 0x29,
|
||||
ENGINE_EARTHBADGE = 0x2a,
|
||||
EARTHQUAKE = 89,
|
||||
EVENT_GOT_SS_TICKET_FROM_ELM = 0x24,
|
||||
EVENT_FAST_SHIP_FIRST_TIME = 0x30,
|
||||
EVENT_RETURNED_MACHINE_PART = 0xc9,
|
||||
EVENT_MET_MANAGER_AT_POWER_PLANT = 0xca,
|
||||
EVENT_RESTORED_POWER_TO_KANTO = 0xcd,
|
||||
EVENT_FOUND_MACHINE_PART_IN_CERULEAN_GYM = 0xfb,
|
||||
EVENT_TALKED_TO_OAK_IN_KANTO = 0xe1,
|
||||
EVENT_BLUE_IN_CINNABAR = 0x775,
|
||||
EVENT_BEAT_BLUE = 0x4cc,
|
||||
EVENT_OPENED_MT_SILVER = 0x74f,
|
||||
EVENT_FOUGHT_SNORLAX = 0x750,
|
||||
EVENT_RED_IN_MT_SILVER = 0x762;
|
||||
|
||||
/** The acceptance run for PLAN section 2: a new game played from the
|
||||
* introduction to the catching tutorial through the world's own inputs,
|
||||
@@ -1653,5 +1745,385 @@ describe.skipIf(!existsSync(romPath))(
|
||||
reload();
|
||||
writeTestSave("hall-of-fame-new-bark");
|
||||
}, 300_000);
|
||||
|
||||
/** A Kanto gym leader in front of the player's way in: the battle
|
||||
* and the badge. */
|
||||
const beatLeader = (id: number, badge: number) => {
|
||||
talkTo(id);
|
||||
play();
|
||||
expect(p.world.state.flags.has(badge), p.log.slice(-3).join(" ")).toBe(true);
|
||||
};
|
||||
|
||||
it("takes the S.S. Ticket from Elm and sails the S.S. Aqua to Vermilion", () => {
|
||||
traceFailures();
|
||||
p.world.move("down");
|
||||
play();
|
||||
enter(ELMS_LAB, "up");
|
||||
play();
|
||||
talkTo(2); // Elm
|
||||
play();
|
||||
expect(p.world.state.events.has(EVENT_GOT_SS_TICKET_FROM_ELM)).toBe(true);
|
||||
expect(p.world.state.bag.keyItems).toContain(S_S_TICKET);
|
||||
stairs(NEW_BARK);
|
||||
cross("left", ROUTE_29);
|
||||
cross("left", CHERRYGROVE);
|
||||
cross("up", ROUTE_30);
|
||||
cross("up", ROUTE_31);
|
||||
stairs(ROUTE_31_GATE);
|
||||
stairs(VIOLET);
|
||||
cross("left", ROUTE_36);
|
||||
cross("up", ROUTE_37);
|
||||
cross("up", ECRUTEAK);
|
||||
stairs(ROUTE_38_GATE);
|
||||
stairs(ROUTE_38);
|
||||
cross("left", ROUTE_39);
|
||||
cross("down", OLIVINE);
|
||||
travel(OLIVINE_PORT, [OLIVINE_PORT_PASSAGE]);
|
||||
// OlivinePortWalkUpToShipScript stops the player on the way to the
|
||||
// gangway: YES, the ticket, and on board.
|
||||
try {
|
||||
walk(7, 16);
|
||||
} catch {
|
||||
// The script takes over the walk.
|
||||
}
|
||||
play();
|
||||
expect(p.world.mapId).toBe(FAST_SHIP_1F);
|
||||
// FastShipB1FSailorBlocksLeft: a sailor steps in front of the
|
||||
// corridor west until the lazy sailor in the north cabins goes back
|
||||
// to work.
|
||||
stairs(FAST_SHIP_B1F);
|
||||
walk(30, 8);
|
||||
p.world.move("up");
|
||||
play();
|
||||
if (p.world.save().direction !== "up") p.world.move("up");
|
||||
p.world.interact();
|
||||
play();
|
||||
walk(31, 13); // back up the east ladder
|
||||
play();
|
||||
expect(route(FAST_SHIP_CABINS_NNW, [FAST_SHIP_1F], 3, { x: 4, y: 27 })).toBe(true);
|
||||
talkTo(6); // the lazy sailor
|
||||
play();
|
||||
// Down to B1F and along it to the captain's cabin, where the lost
|
||||
// girl is found and the ship comes in.
|
||||
expect(route(FAST_SHIP_CABINS_SE, [FAST_SHIP_B1F, FAST_SHIP_1F], 6, { x: 1, y: 26 })).toBe(true);
|
||||
talkTo(5);
|
||||
play();
|
||||
// Off the ship: the sailor at the gangway lets the player out.
|
||||
expect(route(FAST_SHIP_1F, [FAST_SHIP_B1F], 4, { x: 25, y: 3 })).toBe(true);
|
||||
talkTo(2);
|
||||
play();
|
||||
travel(VERMILION, [VERMILION_PORT_PASSAGE]);
|
||||
expect(p.world.state.events.has(EVENT_FAST_SHIP_FIRST_TIME)).toBe(true);
|
||||
reload();
|
||||
writeTestSave("vermilion-city");
|
||||
}, 300_000);
|
||||
|
||||
it("wins the THUNDERBADGE from Lt. Surge", () => {
|
||||
traceFailures();
|
||||
heal(VERMILION_CENTER, VERMILION);
|
||||
// A tree hides the gym's yard; Bellsprout cuts it.
|
||||
p.cut(13, 18);
|
||||
enter(VERMILION_GYM, "up");
|
||||
beatLeader(p.world.map.objects[0].id, ENGINE_THUNDERBADGE);
|
||||
reload();
|
||||
}, 240_000);
|
||||
|
||||
it("wins the MARSHBADGE from Sabrina", () => {
|
||||
traceFailures();
|
||||
exit(VERMILION);
|
||||
p.cut(13, 18); // the tree has grown back
|
||||
cross("up", ROUTE_6);
|
||||
stairs(ROUTE_6_SAFFRON_GATE);
|
||||
stairs(SAFFRON);
|
||||
heal(SAFFRON_CENTER, SAFFRON);
|
||||
writeTestSave("saffron-city");
|
||||
enter(SAFFRON_GYM, "up");
|
||||
// Sabrina at (9, 8), past the gym's warp panels.
|
||||
expect(route(SAFFRON_GYM, [SAFFRON_GYM], 12, { x: 9, y: 9 })).toBe(true);
|
||||
beatLeader(p.world.map.objects[0].id, ENGINE_MARSHBADGE);
|
||||
reload();
|
||||
}, 240_000);
|
||||
|
||||
it("meets the Power Plant's manager, finds the Machine Part and wins the CASCADEBADGE", () => {
|
||||
traceFailures();
|
||||
expect(route(SAFFRON, [SAFFRON_GYM], 12)).toBe(true);
|
||||
stairs(ROUTE_5_SAFFRON_GATE);
|
||||
stairs(ROUTE_5);
|
||||
cross("up", CERULEAN);
|
||||
heal(CERULEAN_CENTER, CERULEAN);
|
||||
cross("right", ROUTE_9);
|
||||
p.cut(5, 8);
|
||||
// Route 10's fence lets no one down from its Pokémon Center: the
|
||||
// river from Route 9's east end leads down to the Power Plant.
|
||||
sail(56, 17);
|
||||
p.world.move("down");
|
||||
play();
|
||||
sail(3, 11);
|
||||
stairs(POWER_PLANT);
|
||||
talkTo(7); // the manager
|
||||
play();
|
||||
expect(p.world.state.events.has(EVENT_MET_MANAGER_AT_POWER_PLANT)).toBe(true);
|
||||
stairs(ROUTE_10_NORTH);
|
||||
// Back up the river, ashore at its top and west to Cerulean; the
|
||||
// tree has grown back.
|
||||
sail(16, 0);
|
||||
p.world.move("up");
|
||||
play();
|
||||
sail(50, 4);
|
||||
p.cut(5, 8);
|
||||
cross("left", CERULEAN);
|
||||
// The thief Rocket's scene on the way in, and the grunt on Route 24
|
||||
// tells where he hid the part.
|
||||
enter(CERULEAN_GYM, "up");
|
||||
play();
|
||||
exit(CERULEAN);
|
||||
cross("up", ROUTE_24);
|
||||
talkTo(2);
|
||||
play();
|
||||
cross("down", CERULEAN);
|
||||
enter(CERULEAN_GYM, "up");
|
||||
p.inspect(3, 8);
|
||||
expect(p.world.state.events.has(EVENT_FOUND_MACHINE_PART_IN_CERULEAN_GYM)).toBe(true);
|
||||
expect(p.world.state.bag.keyItems).toContain(MACHINE_PART);
|
||||
exit(CERULEAN);
|
||||
cross("up", ROUTE_24);
|
||||
cross("up", ROUTE_25);
|
||||
// Route25MistyDate: the date breaks up as the player walks by.
|
||||
walk(41, 6);
|
||||
p.world.move("right");
|
||||
play();
|
||||
expect(p.log.join(" ")).toContain("MISTY");
|
||||
cross("down", ROUTE_24);
|
||||
cross("down", CERULEAN);
|
||||
heal(CERULEAN_CENTER, CERULEAN);
|
||||
enter(CERULEAN_GYM, "up");
|
||||
beatLeader(3, ENGINE_CASCADEBADGE); // Misty, on the pool's island
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("restores the power, crosses Rock Tunnel and takes the EXPN card in Lavender", () => {
|
||||
traceFailures();
|
||||
exit(CERULEAN);
|
||||
cross("right", ROUTE_9);
|
||||
p.cut(5, 8);
|
||||
sail(56, 17);
|
||||
p.world.move("down");
|
||||
play();
|
||||
sail(3, 11);
|
||||
stairs(POWER_PLANT);
|
||||
talkTo(7);
|
||||
play();
|
||||
expect(p.world.state.events.has(EVENT_RETURNED_MACHINE_PART)).toBe(true);
|
||||
expect(p.world.state.events.has(EVENT_RESTORED_POWER_TO_KANTO)).toBe(true);
|
||||
stairs(ROUTE_10_NORTH);
|
||||
sail(16, 0);
|
||||
p.world.move("up");
|
||||
play();
|
||||
sail(50, 4);
|
||||
// Rock Tunnel's door on Route 9 is reached from below: Route 10's
|
||||
// Pokémon Center grounds lead north into Route 9's corner by it.
|
||||
cross("down", ROUTE_10_NORTH);
|
||||
walk(8, 0);
|
||||
p.world.move("up");
|
||||
play();
|
||||
walk(48, 16);
|
||||
p.world.move("up");
|
||||
play();
|
||||
travel(ROUTE_10_SOUTH, ROCK_TUNNEL);
|
||||
cross("down", LAVENDER);
|
||||
heal(LAVENDER_CENTER, LAVENDER);
|
||||
enter(LAVENDER_RADIO_TOWER, "up");
|
||||
talkTo(5); // the director, by the stairs
|
||||
play();
|
||||
expect(p.world.state.flags.has(ENGINE_EXPN_CARD)).toBe(true);
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("wakes Vermilion's Snorlax with the Poké Flute channel", () => {
|
||||
traceFailures();
|
||||
exit(LAVENDER);
|
||||
cross("left", ROUTE_8);
|
||||
stairs(ROUTE_8_SAFFRON_GATE);
|
||||
stairs(SAFFRON);
|
||||
stairs(ROUTE_6_SAFFRON_GATE);
|
||||
stairs(ROUTE_6);
|
||||
cross("down", VERMILION);
|
||||
// SnorlaxAwake: the radio left on the Poké Flute channel, beside it.
|
||||
walk(34, 10);
|
||||
p.tuneRadio("20.0");
|
||||
if (p.world.save().direction !== "up") p.world.move("up");
|
||||
p.world.interact();
|
||||
play();
|
||||
expect(p.world.state.events.has(EVENT_FOUGHT_SNORLAX)).toBe(true);
|
||||
reload();
|
||||
}, 240_000);
|
||||
|
||||
it("goes through Diglett's Cave and wins the BOULDERBADGE from Brock", () => {
|
||||
traceFailures();
|
||||
heal(VERMILION_CENTER, VERMILION);
|
||||
travel(ROUTE_2, [DIGLETTS_CAVE]);
|
||||
p.cut(5, 8);
|
||||
cross("up", PEWTER);
|
||||
heal(PEWTER_CENTER, PEWTER);
|
||||
enter(PEWTER_GYM, "up");
|
||||
beatLeader(p.world.map.objects[0].id, ENGINE_BOULDERBADGE);
|
||||
reload();
|
||||
}, 240_000);
|
||||
|
||||
it("surfs from Pallet Town to Cinnabar and wins the VOLCANOBADGE at Seafoam", () => {
|
||||
traceFailures();
|
||||
exit(PEWTER);
|
||||
cross("down", ROUTE_2);
|
||||
p.cut(5, 8);
|
||||
cross("down", VIRIDIAN);
|
||||
heal(VIRIDIAN_CENTER, VIRIDIAN);
|
||||
cross("down", ROUTE_1);
|
||||
cross("down", PALLET);
|
||||
cross("down", ROUTE_21, { water: true });
|
||||
cross("down", CINNABAR, { water: true });
|
||||
heal(CINNABAR_CENTER, CINNABAR);
|
||||
cross("right", ROUTE_20, { water: true });
|
||||
travel(SEAFOAM_GYM, [], { water: true });
|
||||
beatLeader(2, ENGINE_VOLCANOBADGE); // Blaine
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("hears Blue out on Cinnabar and wins the SOULBADGE from Janine", () => {
|
||||
traceFailures();
|
||||
stairs(ROUTE_20);
|
||||
cross("left", CINNABAR, { water: true });
|
||||
talkTo(2); // Blue
|
||||
play();
|
||||
expect(p.log.join(" ")).toContain("Who are you?");
|
||||
expect(p.world.state.events.has(EVENT_BLUE_IN_CINNABAR)).toBe(true);
|
||||
cross("right", ROUTE_20, { water: true });
|
||||
cross("right", ROUTE_19, { water: true });
|
||||
travel(FUCHSIA, [ROUTE_19_FUCHSIA_GATE], { water: true });
|
||||
heal(FUCHSIA_CENTER, FUCHSIA);
|
||||
enter(FUCHSIA_GYM, "up");
|
||||
beatLeader(2, ENGINE_SOULBADGE);
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("rides up Cycling Road and wins the RAINBOWBADGE from Erika", () => {
|
||||
traceFailures();
|
||||
exit(FUCHSIA);
|
||||
cross("left", ROUTE_18);
|
||||
// Cycling Road: on the Bicycle through the gate and up Route 17,
|
||||
// which continues north into Route 16 between x 4 and 9.
|
||||
p.world.useBicycle();
|
||||
play();
|
||||
stairs(ROUTE_17_ROUTE_18_GATE);
|
||||
stairs(ROUTE_17);
|
||||
p.rideUp(6, 0);
|
||||
// Through the Route 16 gate to its east side, then Celadon.
|
||||
walk(9, 7);
|
||||
p.world.move("right");
|
||||
play();
|
||||
walk(9, 5);
|
||||
p.world.move("right");
|
||||
play();
|
||||
cross("right", CELADON);
|
||||
if (p.world.state.playerState === 1) {
|
||||
p.world.useBicycle();
|
||||
play();
|
||||
}
|
||||
heal(CELADON_CENTER, CELADON);
|
||||
writeTestSave("celadon-city");
|
||||
p.cut(28, 35); // the tree by the gym's yard
|
||||
enter(CELADON_GYM, "up");
|
||||
beatLeader(2, ENGINE_RAINBOWBADGE);
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("restocks in Saffron and wins the EARTHBADGE from Blue", () => {
|
||||
traceFailures();
|
||||
exit(CELADON);
|
||||
p.cut(28, 35); // grown back
|
||||
heal(CELADON_CENTER, CELADON);
|
||||
cross("right", ROUTE_7);
|
||||
stairs(ROUTE_7_SAFFRON_GATE);
|
||||
stairs(SAFFRON);
|
||||
// Saffron's mart sells Max Potions.
|
||||
enter(SAFFRON_MART, "up");
|
||||
buy(2, C.MAX_POTION, Math.min(99, Math.floor((p.world.state.money - 3000) / 2500)));
|
||||
exit(SAFFRON);
|
||||
stairs(ROUTE_6_SAFFRON_GATE);
|
||||
stairs(ROUTE_6);
|
||||
cross("down", VERMILION);
|
||||
travel(ROUTE_2, [DIGLETTS_CAVE]);
|
||||
p.cut(5, 8);
|
||||
cross("down", VIRIDIAN);
|
||||
heal(VIRIDIAN_CENTER, VIRIDIAN);
|
||||
enter(VIRIDIAN_GYM, "up");
|
||||
beatLeader(2, ENGINE_EARTHBADGE);
|
||||
expect(p.world.state.events.has(EVENT_BEAT_BLUE)).toBe(true);
|
||||
reload();
|
||||
}, 300_000);
|
||||
|
||||
it("has Oak open Mt. Silver for sixteen badges", () => {
|
||||
traceFailures();
|
||||
exit(VIRIDIAN);
|
||||
heal(VIRIDIAN_CENTER, VIRIDIAN);
|
||||
cross("down", ROUTE_1);
|
||||
cross("down", PALLET);
|
||||
enter(OAKS_LAB, "up");
|
||||
talkTo(2); // Oak
|
||||
play();
|
||||
expect(p.world.state.events.has(EVENT_TALKED_TO_OAK_IN_KANTO)).toBe(true);
|
||||
expect(p.world.state.events.has(EVENT_OPENED_MT_SILVER)).toBe(true);
|
||||
expect(p.log.join(" ")).toContain("POKéMON seen");
|
||||
reload();
|
||||
}, 240_000);
|
||||
|
||||
it("reaches Mt. Silver by Route 28 and trains outside Silver Cave", () => {
|
||||
traceFailures();
|
||||
exit(PALLET);
|
||||
cross("up", ROUTE_1);
|
||||
cross("up", VIRIDIAN);
|
||||
cross("left", ROUTE_22);
|
||||
stairs(VICTORY_ROAD_GATE);
|
||||
stairs(ROUTE_28);
|
||||
cross("left", SILVER_CAVE_OUTSIDE);
|
||||
heal(SILVER_CAVE_CENTER, SILVER_CAVE_OUTSIDE);
|
||||
writeTestSave("mt-silver");
|
||||
// Red's team is in the 70s and 80s: the lead trains in steps.
|
||||
travel(SILVER_CAVE_ROOM_3, SILVER_CAVE);
|
||||
travel(SILVER_CAVE_OUTSIDE, SILVER_CAVE);
|
||||
const rest = () => heal(SILVER_CAVE_CENTER, SILVER_CAVE_OUTSIDE);
|
||||
for (const level of [84, 88, 91, 93, 95]) train(level, rest);
|
||||
expect(lead().level).toBeGreaterThanOrEqual(95);
|
||||
reload();
|
||||
}, 900_000);
|
||||
|
||||
it("takes TM26 from Victory Road, beats Red and sees the credits", () => {
|
||||
traceFailures();
|
||||
cross("right", ROUTE_28);
|
||||
stairs(VICTORY_ROAD_GATE);
|
||||
stairs(VICTORY_ROAD);
|
||||
expect(route(VICTORY_ROAD, [VICTORY_ROAD], 8, { x: 4, y: 28 })).toBe(true);
|
||||
talkTo(3); // TM26's ball
|
||||
play();
|
||||
p.teach(tmhmItem(26), 0, 2); // Earthquake for Smokescreen
|
||||
expect(lead().moves[2]).toBe(EARTHQUAKE);
|
||||
travel(VICTORY_ROAD_GATE, [VICTORY_ROAD]);
|
||||
stairs(ROUTE_28);
|
||||
cross("left", SILVER_CAVE_OUTSIDE);
|
||||
heal(SILVER_CAVE_CENTER, SILVER_CAVE_OUTSIDE);
|
||||
travel(SILVER_CAVE_ROOM_3, SILVER_CAVE);
|
||||
talkTo(2); // Red
|
||||
play();
|
||||
const log = p.log.join(" ");
|
||||
expect(log).toContain("RED\nwas defeated!");
|
||||
// RedCredits, then SPAWN_MT_SILVER outside the cave, with Red gone
|
||||
// for good and the party healed.
|
||||
expect(p.world.state.events.has(EVENT_RED_IN_MT_SILVER)).toBe(true);
|
||||
expect(p.world.mapId).toBe(SILVER_CAVE_OUTSIDE);
|
||||
expect({ x: p.world.x, y: p.world.y }).toEqual({ x: 23, y: 20 });
|
||||
expect(p.world.state.party.every((mon) => mon.hp === mon.stats[0])).toBe(true);
|
||||
expect(p.world.busy).toBe(false);
|
||||
reload();
|
||||
writeTestSave("red-beaten");
|
||||
}, 300_000);
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user