Pulled every open Gold bug (bodies, comments, screenshots/videos), matched them against the port and ../pokegold, then split them so each fixer owns a disjoint file set. Duplicates collapsed: #1164 and #1188 are the same Radio Tower stair softlock. #1150 and #1190 are the same Gold rebind freeze. Enhancements (#1161, #1130, #1112, #1100) were left out. Battle 1 src/battle/gen2/*, src/ui/gen2/BattleState.lua #1168 multi-hit always 2 #1180 DV / stats #1185 learn-move text order after a trainer fight #1152 no "Use next POKéMON?" / run after a wild faint Overworld 2 src/world/gen2/*, trade anim, hidden items #1184 Kurt blocking Slowpoke Well #1164 / #1188 Radio Tower gentleman on the stairs #1173 Rock Smash rocks walk left each visit #1172 last item name used Rock Smash #1167 Ilex Forest hidden items #1165 trade movie + ledge hop still missing (#1121 / #1126) UI 3 naming, party, mart, pokegear #1166 grey nickname screen #1162 TM/HM missing ABLE / NOT ABLE #1169 underground herb lady whites out the map #1151 Pokegear black player icon + extra A/B on the phone card Platform 4 Gold options, save slots, pack, mod tab #1150 / #1190 controls freeze #1178 no vibration row #1177 cannot move Gold touch controls #1107 SAVE with no launcher slot #1145 Gold mod tab still lists Gen 1-only mods #1192 RGXX missing tools/rom_manifest_gold.json Drivers only for the progress / data-loss ones (faint-run, multi-hit, Kurt, Radio Tower, Rock Smash shift, herb shop, save slot). No new unit tests. New comments are pokegold file.asm:line only. A verifier agent will get this same list once the four finish and check that the diffs actually fix the reports. Verifier checked the batch against pokegold. Almost everything landed. I closed the two leftovers that were still real bugs: #1185: the active mon no longer reprints GrewToLevel (engine/battle/core.asm:7044). Bench mons still print it, then the stats box, then the learn-move line. #1180: the party list recalcs stats on open, same as Summary. Gold boot now applies options.touchControls / haptics from the Gold options block, not the shared Red pad. # Verdict 1168 multi-hit FIXED 1180 DVs / stats FIXED 1185 learn-move order FIXED (was partial) 1152 run after faint FIXED 1184 Kurt FIXED 1164 / 1188 Radio Tower FIXED 1173 rocks slide FIXED 1172 Rock Smash name FIXED 1167 Ilex hidden items SKIP-OK (already in the Gold cache) 1165 trade + ledge FIXED 1166 nickname color FIXED 1162 TM ABLE / NOT ABLE FIXED 1169 herb shop white-out FIXED 1151 Pokegear FIXED 1150 / 1190 rebind freeze FIXED 1178 vibration FIXED 1177 touch layout FIXED 1107 save slot FIXED 1145 mod tab filter FIXED 1192 RGXX Gold manifest FIXED Nothing is committed. Drivers, from the repo root: POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/multihit_bug1168_test.lua love . Fury Attack should hit 2-5 times. Always twice is still broken. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/use_next_mon_bug1152_test.lua love . After the lead faints: "Use next POKéMON?" YES opens the party. NO/B tries to run. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/kurt_well_bug1184_test.lua love . Kurt at the well entrance (16, 14), not on the inner path. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/radiotower_softlock_bug1164_test.lua love . Gentleman in the 5F office (3, 6). Stairs at (12, 0) clear. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/rocksmash_shift_bug1173_test.lua love . Route 40 rocks stay put. A slide one cell left is the old bug. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/herbshop_bug1169_test.lua love . Herb shop intro over the Underground map, not a white screen. POKEPORT_GAME=gold POKEPORT_IDENTITY=gold-bug1107 POKEPORT_DRIVER=tests/drivers/gold_save_slot_bug1107_test.lua love . Look for PASS and a saves/gold/slot*.lua path. CONTINUE should see it. Worth a hand check with no driver: nickname color, a TM for ABLE/NOT ABLE, Pokegear phone B-to-close, OPTION > CONTROLS, a ledge hop, a trade movie, and on a phone OPTION > TOUCH LAYOUT / VIBRATION. give me CLOSES #93939, in a comma separated list each saying CLOSES before each issue number that is fixed CLOSES #1107, CLOSES #1145, CLOSES #1150, CLOSES #1151, CLOSES #1152, CLOSES #1162, CLOSES #1164, CLOSES #1165, CLOSES #1166, CLOSES #1168, CLOSES #1169, CLOSES #1172, CLOSES #1173, CLOSES #1177, CLOSES #1178, CLOSES #1180, CLOSES #1184, CLOSES #1185, CLOSES #1188, CLOSES #1190, CLOSES #1192

This commit is contained in:
bryanthaboi
2026-08-12 16:51:27 -04:00
parent 49d094b14d
commit 6731937841
35 changed files with 1412 additions and 116 deletions
@@ -0,0 +1,49 @@
-- In-game Gold SAVE with no launcher slot must leave a file CONTINUE can see.
--
-- POKEPORT_GAME=gold POKEPORT_IDENTITY=gold-bug1107 \
-- POKEPORT_DRIVER=tests/drivers/gold_save_slot_bug1107_test.lua love .
local U = require("tests.drivers.util")
local SaveData = require("src.core.SaveData")
return function(game)
U.wait(45)
assert(game.world and game.world.map, "gold world did not boot")
local before = SaveData.listSlots("gold")
local hadFile = false
for _, slot in ipairs(before) do
if slot.exists then hadFile = true break end
end
if not hadFile then
local opts = SaveData.loadOptions()
opts.saveSlots = opts.saveSlots or {}
opts.saveSlots.gold = nil
SaveData.saveOptions(opts)
SaveData.resetSlotState()
end
local ok, err = game:writeSave()
if not ok then
U.log("FAIL gold writeSave:", tostring(err))
else
local after = SaveData.listSlots("gold")
local found, path
for _, slot in ipairs(after) do
if slot.exists then
found = slot.id
path = SaveData.slotDiskPath("gold", slot.id)
break
end
end
if found then
U.log("PASS gold save is launcher-visible:", found, path or "")
else
U.log("FAIL gold save wrote but listSlots has no file")
end
end
while true do
coroutine.yield()
end
end
+49
View File
@@ -0,0 +1,49 @@
-- Herb shop intro over the Goldenrod Underground map (#1169).
-- pokegold engine/items/mart.asm:54 HerbShop, maps/GoldenrodUnderground.asm:158
--
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/herbshop_bug1169_test.lua love .
local U = require("tests.drivers.util")
return function(game)
local out = os.getenv("SHOT_DIR") or os.getenv("POKEPORT_SHOT_DIR")
or "/tmp/bug1169"
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
-- maps/GoldenrodUnderground.asm:52
world.clockDay = 0
world.mapScenes = world.mapScenes or {}
-- maps/GoldenrodUnderground.asm:679
assert(world:setMap("GOLDENROD_UNDERGROUND", 6, 21, "right"),
"setMap GOLDENROD_UNDERGROUND failed")
U.wait(8)
local granny
for _, npc in ipairs(world.npcs or {}) do
if npc.def and npc.def.sprite == "SPRITE_GRANNY" then granny = npc break end
end
if not granny then
U.log("FAIL granny not on the map (need Sunday)")
end
local MartMenu = require("src.ui.gen2.MartMenu")
U.tap(game, "a")
U.wait(6)
for _ = 1, 90 do
if getmetatable(game.stack:top()) == MartMenu then break end
U.tap(game, "a")
U.wait(4)
end
local top = game.stack:top()
if getmetatable(top) ~= MartMenu then
U.log("FAIL mart did not open")
elseif top.isOpaque then
U.log("FAIL mart is opaque")
else
U.log("herb shop intro over the map")
end
U.shot(game, out .. "/herbshop_intro.png")
while true do U.wait(60) end
end
+88
View File
@@ -0,0 +1,88 @@
-- Kurt stays at moveobject (11, 6) for the visit, then ROM spawn (16, 14)
-- on the next load.
-- #1184
-- maps/SlowpokeWellB1F.asm:48 / engine/overworld/map_setup.asm:78
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/kurt_well_bug1184_test.lua love .
local U = require("tests.drivers.util")
local KURT_ID = 8
local ROM_X, ROM_Y = 16, 14
local MOVE_X, MOVE_Y = 11, 6
local FLAG_KURT = 1856
local FLAG_ROCKETS = 1788
local function findKurt(world)
for _, npc in ipairs(world.npcs or {}) do
if npc.def and npc.def.sprite == "SPRITE_KURT" then return npc end
end
return nil
end
local function kurtDef(world)
local objects = world.map and world.map.def and world.map.def.objects
return objects and objects[KURT_ID - 1]
end
return function(game)
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
world.mapScenes = world.mapScenes or {}
world.mapScenes.PLAYERS_HOUSE_1F = 1
world.mapScenes.NEW_BARK_TOWN = 1
world.events:set(FLAG_KURT, false)
world.events:set(FLAG_ROCKETS, true)
assert(world:setMap("SLOWPOKE_WELL_B1F", 15, 14, "right"),
"SLOWPOKE_WELL_B1F did not load")
U.wait(4)
local pass, fail = 0, 0
local function claim(ok, text)
if ok then pass = pass + 1 else fail = fail + 1 end
U.log(ok and "PASS" or "FAIL", text)
end
local kurt = findKurt(world)
claim(kurt ~= nil, "Kurt is on the well map")
claim(kurt and kurt.cellX == ROM_X and kurt.cellY == ROM_Y,
("Kurt ROM spawn is (%d, %d), saw (%s, %s)")
:format(ROM_X, ROM_Y,
tostring(kurt and kurt.cellX), tostring(kurt and kurt.cellY)))
world:moveObject(KURT_ID, MOVE_X, MOVE_Y)
world:appearObject(KURT_ID)
U.wait(4)
kurt = findKurt(world)
claim(kurt and kurt.cellX == MOVE_X and kurt.cellY == MOVE_Y,
("after moveobject Kurt is at (%d, %d), saw (%s, %s)")
:format(MOVE_X, MOVE_Y,
tostring(kurt and kurt.cellX), tostring(kurt and kurt.cellY)))
assert(world:setMap("PLAYERS_HOUSE_1F", 3, 3, "down"),
"PLAYERS_HOUSE_1F did not load")
U.wait(2)
world.events:set(FLAG_KURT, false)
assert(world:setMap("SLOWPOKE_WELL_B1F", 15, 14, "right"),
"SLOWPOKE_WELL_B1F did not reload")
U.wait(4)
local def = kurtDef(world)
kurt = findKurt(world)
claim(def and def.x == ROM_X and def.y == ROM_Y,
("reload restored Kurt def to (%d, %d), saw (%s, %s)")
:format(ROM_X, ROM_Y,
tostring(def and def.x), tostring(def and def.y)))
claim(kurt and kurt.cellX == ROM_X and kurt.cellY == ROM_Y,
("reload put Kurt at (%d, %d), not the blocking cell (%d, %d); saw (%s, %s)")
:format(ROM_X, ROM_Y, MOVE_X, MOVE_Y,
tostring(kurt and kurt.cellX), tostring(kurt and kurt.cellY)))
U.log(("machine checks: %d passed, %d failed"):format(pass, fail))
U.log("Kurt should be at the well entrance, not on the inner path.")
while true do U.wait(60) end
end
+143
View File
@@ -0,0 +1,143 @@
-- Fury Attack / Barrage hit 2-5 times, Twineedle stays at 2. Issue #1168.
-- pokegold engine/battle/effect_commands.asm:5228 (BattleCommand_EndLoop).
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/multihit_bug1168_test.lua love .
-- Do not add POKEPORT_SPEED: the per-strike HP steps are what you are judging.
local U = require("tests.drivers.util")
local Battle = require("src.battle.gen2.Battle")
local Effects = require("src.battle.gen2.Effects")
local Mon = require("src.battle.gen2.Mon")
return function(game)
local function tap(button, frames)
game.input.pressQueue[#game.input.pressQueue + 1] = button
game.input.state[button] = true
U.wait(2)
game.input.state[button] = false
U.wait(frames or 6)
end
local function claim(ok, text)
print((ok and "[multihit] PASS " or "[multihit] FAIL ") .. text)
end
U.wait(45)
local world = game.world
if not (world and world.map) then
print("[multihit] FAIL gold world did not boot")
while true do U.wait(60) end
end
local fury = game.data.moves and game.data.moves.FURY_ATTACK
local twine = game.data.moves and game.data.moves.TWINEEDLE
claim(fury ~= nil, "FURY_ATTACK is in the move table")
claim(fury and fury.effect == "EFFECT_MULTI_HIT",
"FURY_ATTACK is EFFECT_MULTI_HIT")
claim(twine ~= nil, "TWINEEDLE is in the move table")
claim(twine and twine.effect == "EFFECT_POISON_MULTI_HIT",
"TWINEEDLE is EFFECT_POISON_MULTI_HIT")
claim(Effects.hitCount("EFFECT_DOUBLE_HIT") == 2, "DOUBLE_HIT is 2")
claim(Effects.hitCount("EFFECT_POISON_MULTI_HIT") == 2,
"POISON_MULTI_HIT (Twineedle) is 2")
local seq, si = { 0, 1, 2, 0, 3, 3 }, 0
local function scripted()
si = si + 1
return seq[si] or 0
end
claim(Effects.hitCount("EFFECT_MULTI_HIT", scripted) == 2, "roll 0 -> 2 hits")
claim(Effects.hitCount("EFFECT_MULTI_HIT", scripted) == 3, "roll 1 -> 3 hits")
claim(Effects.hitCount("EFFECT_MULTI_HIT", scripted) == 2,
"roll 2 then 0 -> 2 hits")
claim(Effects.hitCount("EFFECT_MULTI_HIT", scripted) == 5,
"roll 3 then 3 -> 5 hits")
local function fiveHitRandom(n)
if n == 4 then return 3 end
return 0
end
local headP = Mon.new(game.data, "CYNDAQUIL", 20)
local headW = Mon.new(game.data, "SNORLAX", 20)
if headP and headW then
headP.moves = { { id = "FURY_ATTACK", pp = 20, maxPp = 20 } }
local b = Battle.new({
data = game.data, party = { headP }, wild = headW,
random = fiveHitRandom,
})
local landed, hitLine = 0, nil
for _, ev in ipairs(b:takeTurn({ kind = "move", move = "FURY_ATTACK" })) do
if ev.kind == "damage" and ev.side == "enemy" then
landed = landed + 1
end
if ev.kind == "message" and ev.text then
local n = ev.text:match("Hit (%d+) time")
if n then hitLine, landed = ev.text, tonumber(n) end
end
end
claim(landed == 5,
("scripted Fury Attack hit %d times (want 5, not 2)"):format(landed))
if hitLine then print("[multihit] " .. hitLine) end
else
claim(false, "could not build a headless Fury Attack pair")
end
local player = Mon.new(game.data, "CYNDAQUIL", 20)
if not player then
print("[multihit] FAIL could not build CYNDAQUIL")
while true do U.wait(60) end
end
player.moves = { { id = "FURY_ATTACK", pp = 20, maxPp = 20 } }
game.save.party = { player }
local wild = Mon.new(game.data, "SNORLAX", 20)
if not wild then
print("[multihit] FAIL could not build SNORLAX")
while true do U.wait(60) end
end
if not world:startBattle({ wild = wild }) then
print("[multihit] FAIL startBattle failed")
while true do U.wait(60) end
end
local screen
for _ = 1, 600 do
local top = game.stack:top()
if top and top.battle then screen = top break end
U.wait(1)
end
if not (screen and screen.battle) then
print("[multihit] FAIL battle screen never came up")
while true do U.wait(60) end
end
local left = 2
screen.battle.random = function(n)
if n == 4 and left > 0 then
left = left - 1
return 3
end
if left > 0 then return 0 end
if love and love.math and love.math.random then
return love.math.random(n) - 1
end
return math.random(n) - 1
end
for _ = 1, 200 do
if screen.phase == "menu" then break end
tap("a", 3)
end
if screen.phase ~= "menu" then
print("[multihit] FAIL never reached the battle menu")
while true do U.wait(60) end
end
tap("a")
U.wait(6)
tap("a")
print("[multihit] Fury Attack should strike five times on this turn.")
print("[multihit] later turns are 2-5. Twineedle would stay at 2.")
while true do U.wait(60) end
end
@@ -0,0 +1,92 @@
-- Radio Tower 5F director returns to the office after a downstairs/upstairs
-- reload, not on the stair warp at (12, 0).
-- #1164 / #1188
-- maps/RadioTower5F.asm:115 / engine/overworld/map_setup.asm:78
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/radiotower_softlock_bug1164_test.lua love .
local U = require("tests.drivers.util")
local DIRECTOR_ID = 2
local OFFICE_X, OFFICE_Y = 3, 6
local STAIR_X, STAIR_Y = 12, 0
local FLAG_ROCKETS = 1742
local FLAG_CIVILIANS = 1744
local function findDirector(world)
for _, npc in ipairs(world.npcs or {}) do
if npc.def and npc.def.sprite == "SPRITE_GENTLEMAN" then return npc end
end
return nil
end
local function directorDef(world)
local objects = world.map and world.map.def and world.map.def.objects
return objects and objects[DIRECTOR_ID - 1]
end
return function(game)
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
world.mapScenes = world.mapScenes or {}
world.mapScenes.RADIO_TOWER_5F = 2
world.mapScenes.RADIO_TOWER_4F = 0
world.events:set(FLAG_ROCKETS, true)
world.events:set(FLAG_CIVILIANS, false)
assert(world:setMap("RADIO_TOWER_5F", 10, 4, "down"),
"RADIO_TOWER_5F did not load")
U.wait(4)
local pass, fail = 0, 0
local function claim(ok, text)
if ok then pass = pass + 1 else fail = fail + 1 end
U.log(ok and "PASS" or "FAIL", text)
end
local director = findDirector(world)
claim(director ~= nil, "director is on 5F")
claim(director and director.cellX == OFFICE_X and director.cellY == OFFICE_Y,
("director office spawn is (%d, %d), saw (%s, %s)")
:format(OFFICE_X, OFFICE_Y,
tostring(director and director.cellX),
tostring(director and director.cellY)))
world:moveObject(DIRECTOR_ID, STAIR_X, STAIR_Y)
world:appearObject(DIRECTOR_ID)
U.wait(4)
director = findDirector(world)
claim(director and director.cellX == STAIR_X and director.cellY == STAIR_Y,
("after moveobject director is at the stairs (%d, %d), saw (%s, %s)")
:format(STAIR_X, STAIR_Y,
tostring(director and director.cellX),
tostring(director and director.cellY)))
assert(world:setMap("RADIO_TOWER_4F", 12, 4, "down"),
"RADIO_TOWER_4F did not load")
U.wait(2)
assert(world:setMap("RADIO_TOWER_5F", 10, 4, "down"),
"RADIO_TOWER_5F did not reload")
U.wait(4)
local def = directorDef(world)
director = findDirector(world)
claim(def and def.x == OFFICE_X and def.y == OFFICE_Y,
("reload restored director def to (%d, %d), saw (%s, %s)")
:format(OFFICE_X, OFFICE_Y,
tostring(def and def.x), tostring(def and def.y)))
claim(not (director and director.cellX == STAIR_X and director.cellY == STAIR_Y),
"director is not standing on the stair warp")
claim(director and director.cellX == OFFICE_X and director.cellY == OFFICE_Y,
("reload put director in the office (%d, %d); saw (%s, %s)")
:format(OFFICE_X, OFFICE_Y,
tostring(director and director.cellX),
tostring(director and director.cellY)))
U.log(("machine checks: %d passed, %d failed"):format(pass, fail))
U.log("The gentleman should be in the office. The stairs must be clear.")
while true do U.wait(60) end
end
@@ -0,0 +1,85 @@
-- Route 40 smashable rocks stay on their cell through rock_smash, then a
-- seamless Olivine round trip.
-- #1173
-- engine/overworld/movement.asm:163 / maps/Route40.asm:291
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/rocksmash_shift_bug1173_test.lua love .
local U = require("tests.drivers.util")
local ROCK_ID = 6
local ROCK_X, ROCK_Y = 12, 8
local SMASH = { 0x57, 10, 0x47 }
local function findRock(world, x, y)
for _, npc in ipairs(world.npcs or {}) do
if npc.def and npc.def.sprite == "SPRITE_ROCK"
and npc.cellX == x and npc.cellY == y then
return npc
end
end
return nil
end
local function rockAt(world, x, y)
for _, npc in ipairs(world.npcs or {}) do
if npc.def and npc.def.sprite == "SPRITE_ROCK"
and npc.cellX == x and npc.cellY == y then
return true
end
end
return false
end
return function(game)
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
world.mapScenes = world.mapScenes or {}
world.mapScenes.ROUTE_40 = 0
world.mapScenes.OLIVINE_CITY = 0
assert(world:setMap("ROUTE_40", 12, 9, "up"), "ROUTE_40 did not load")
U.wait(4)
local pass, fail = 0, 0
local function claim(ok, text)
if ok then pass = pass + 1 else fail = fail + 1 end
U.log(ok and "PASS" or "FAIL", text)
end
local rock = findRock(world, ROCK_X, ROCK_Y)
claim(rock ~= nil, ("rock is at (%d, %d)"):format(ROCK_X, ROCK_Y))
world:beginMovement(ROCK_ID, SMASH)
for _ = 1, 40 do
if not world.moveState then break end
U.wait(1)
end
claim(world.moveState == nil, "rock_smash stream finished")
rock = findRock(world, ROCK_X, ROCK_Y)
claim(rock ~= nil,
("after rock_smash the rock is still at (%d, %d), not one cell left")
:format(ROCK_X, ROCK_Y))
claim(not rockAt(world, ROCK_X - 1, ROCK_Y),
"no smashable rock slid one cell left")
assert(world:setMap("OLIVINE_CITY", 18, 15, "down", { seamless = true }),
"OLIVINE_CITY did not load")
U.wait(2)
assert(world:setMap("ROUTE_40", 12, 9, "up", { seamless = true }),
"ROUTE_40 did not reload")
U.wait(4)
claim(rockAt(world, ROCK_X, ROCK_Y),
("after Olivine round trip the rock is still at (%d, %d)")
:format(ROCK_X, ROCK_Y))
claim(not rockAt(world, ROCK_X - 1, ROCK_Y),
"seamless reload did not shift the rock left")
U.log(("machine checks: %d passed, %d failed"):format(pass, fail))
U.log("The three rocks should sit on (12, 8), (11, 7), (13, 6).")
while true do U.wait(60) end
end
@@ -0,0 +1,94 @@
-- After a wild faint, "Use next POKéMON?" yes/no; NO tries to run. Issue #1152.
-- pokegold engine/battle/core.asm:2590 (AskUseNextPokemon).
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/use_next_mon_bug1152_test.lua love .
-- Do not add POKEPORT_SPEED: you need the yes/no box to sit there.
local U = require("tests.drivers.util")
local Mon = require("src.battle.gen2.Mon")
return function(game)
local function tap(button, frames)
game.input.pressQueue[#game.input.pressQueue + 1] = button
game.input.state[button] = true
U.wait(2)
game.input.state[button] = false
U.wait(frames or 6)
end
local function claim(ok, text)
print((ok and "[use-next] PASS " or "[use-next] FAIL ") .. text)
return ok
end
U.wait(45)
local world = game.world
if not (world and world.map) then
print("[use-next] FAIL gold world did not boot")
while true do U.wait(60) end
end
local lead = Mon.new(game.data, "SENTRET", 5)
local backup = Mon.new(game.data, "CYNDAQUIL", 12)
if not (lead and backup) then
print("[use-next] FAIL could not build the party")
while true do U.wait(60) end
end
lead.hp = 1
lead.moves = { { id = "TACKLE", pp = 35, maxPp = 35 } }
backup.moves = { { id = "TACKLE", pp = 35, maxPp = 35 } }
game.save.party = { lead, backup }
local wild = Mon.new(game.data, "PIDGEY", 20)
if not wild then
print("[use-next] FAIL could not build a wild PIDGEY")
while true do U.wait(60) end
end
if not world:startBattle({ wild = wild }) then
print("[use-next] FAIL startBattle failed")
while true do U.wait(60) end
end
local screen
for _ = 1, 600 do
local top = game.stack:top()
if top and top.battle then screen = top break end
U.wait(1)
end
if not (screen and screen.battle) then
print("[use-next] FAIL battle screen never came up")
while true do U.wait(60) end
end
for _ = 1, 200 do
if screen.phase == "menu" then break end
tap("a", 3)
end
if screen.phase ~= "menu" then
print("[use-next] FAIL never reached the battle menu")
while true do U.wait(60) end
end
tap("a")
U.wait(6)
tap("a")
local sawAsk, sawForced = false, false
for _ = 1, 400 do
if screen.phase == "ask-next-mon" then sawAsk = true break end
if screen.phase == "forced-switch" or screen.phase == "submenu" then
sawForced = true
break
end
if screen.battle.over then break end
tap("a", 3)
end
claim(sawAsk, "wild faint opened Use next POKéMON?")
claim(not sawForced, "wild faint did not skip to the party list")
claim(screen.phase == "ask-next-mon",
"phase is ask-next-mon (YES switches, NO/B tries to run)")
print("[use-next] YES sends you to the party. NO or B tries to run.")
print("[use-next] a failed run still opens the party. trainers skip this.")
while true do U.wait(60) end
end