Files
gen1recomp/tests/drivers/game3_wild_exp_flow.lua
T
bryanthaboi 3620e787d2 FIELD GOAL
2026-09-27 16:58:27 -04:00

189 lines
7.8 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_wild_exp_flow"
return function(game)
io.stdout:setvbuf("line")
local fails = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then fails = fails + 1 end
return ok
end
local function finish()
print(string.format("[driver] game3_wild_exp_flow: %d failure(s)", fails))
love.event.quit(fails == 0 and 0 or 1)
U.wait(10)
end
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "BRENDAN", gender = 0 })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Party = require("src.core.game3.party")
local BattleBridge = require("src.core.game3.battle_bridge")
local Battle = require("src.core.game3.battle")
local Ui = require("src.core.game3.battle.ui")
local Message = require("src.ui.game3.message")
local StatGrowth = require("src.ui.game3.stat_growth")
local Anim = require("src.core.game3.battle.anim")
local Audio = require("src.core.game3.audio")
local Map = require("src.core.game3.map")
local Encounters = require("src.core.game3.encounters")
local Pokemon = require("src.core.game3.pokemon")
local Experience = require("src.core.game3.battle.experience")
local Constants = require("src.core.game3.constants")
local session = Runtime.getSession()
if not result(session ~= nil, "field session exists") then return finish() end
local C = Constants.of(Constants.versionOf(session))
print("[driver] version " .. tostring(C.game))
Encounters.onStep = function() return nil end
if C.game == "emerald" then
Map.load(nil, game, "EM_ROUTE101", { x = 7, y = 13, facing = "down" })
else
Map.load(nil, game, "FR_ROUTE1", { x = 10, y = 20, facing = "down" })
end
U.wait(40)
local MUDKIP = C.species.byName.SPECIES_MUDKIP
local learnLv, learnMove
for lv = 6, 40 do
local mv = Pokemon.movesLearnedAt(MUDKIP, lv)
if mv and #mv > 0 then learnLv, learnMove = lv, mv[1] break end
end
if not result(learnLv ~= nil, "Mudkip learnset has a move between LV6 and LV40 (" .. tostring(learnLv) .. ")") then
return finish()
end
session.party = {}
Party.giveMon(session, MUDKIP, learnLv - 1, "")
local mon = session.party[1]
local mv = function(n) return C.moves.byName["MOVE_" .. n] end
mon.moves = {}
for _, n in ipairs({ "TACKLE", "GROWL", "PROTECT", "WATER_GUN", "SCRATCH" }) do
if mv(n) ~= learnMove and #mon.moves < 4 then mon.moves[#mon.moves + 1] = mv(n) end
end
mon.pp = { 35, 40, 10, 10 }
mon.maxPp = { 35, 40, 10, 10 }
mon.exp = Experience.expForLevel(mon, learnLv) - 1
print(string.format("[driver] Mudkip LV%d exp %d, learns %s at LV%d", mon.level, mon.exp,
tostring(C:name("moves", learnMove, "MOVE_")), learnLv))
local VS_WILD = C.songs.byName.MUS_VS_WILD
local VICTORY_WILD = C.songs.byName.MUS_VICTORY_WILD
local outcome
local ok = BattleBridge.startWild(Runtime._mod, game,
{ species = C.species.byName.SPECIES_ZIGZAGOON, level = 5 }, { done = function(r) outcome = r end })
if not result(ok == true, "wild Zigzagoon battle started") then return finish() end
for _ = 1, 3000 do
if Battle.isActive() then break end
U.wait(1)
end
if not result(Battle.isActive(), "battle active") then return finish() end
local f = 0
local ev = {}
local function mark(name)
if not ev[name] then
ev[name] = f
print(string.format("[driver] f=%d %s song=%s", f, name, tostring(Audio._currentSong and Audio._currentSong.id)))
end
end
local songAt = {}
local waitF = 0
local statShot, expShot, learnShot = false, false, false
local gainedOpenFrames, gainedPrinted = 0, false
local endedWhileGained = false
local foeLowered = false
while (Battle.isActive() or outcome == nil) and f < 30000 do
f = f + 1
local song = Audio._currentSong and Audio._currentSong.id
local page = Message.isOpen() and Message.currentPage() or ""
local phase = Battle._phase
if song == VICTORY_WILD then mark("victory_song") end
if page:find("fainted") then
mark("fainted_open")
songAt.fainted = songAt.fainted or song
if Message.isWaiting() then mark("fainted_waiting") end
end
if page:find("EXP%. Points") then
mark("gained_open")
songAt.gained = songAt.gained or song
gainedOpenFrames = gainedOpenFrames + 1
if Message.isWaiting() then
gainedPrinted = true
mark("gained_printed")
if not expShot then
expShot = U.still(game, DIR .. "/01_gained_exp.png")
end
end
if phase == "ending" or phase == "fade_out" then endedWhileGained = true end
elseif ev.gained_open and not ev.gained_closed then
mark("gained_closed")
end
if page:find("grew to") then mark("grew_open") end
if page:find("trying to") or page:find("learn") then mark("learn_text") end
if phase == "ending" or phase == "fade_out" then mark("battle_ending") end
if StatGrowth.isOpen() then
mark("stat_box")
if not statShot then
U.wait(20)
statShot = U.still(game, DIR .. "/02_level_up_box.png")
end
U.wait(30)
U.tap(game, "a")
elseif Ui.choiceActive() then
mark("learn_prompt")
if not learnShot then
U.wait(10)
learnShot = U.still(game, DIR .. "/03_learn_prompt.png")
end
U.wait(20)
local lg = Ui.log()
local last = tostring(lg[#lg] or "")
U.tap(game, last:find("Stop") and "a" or "b")
elseif phase == "command" and Ui._mode == "menu" and not Anim.busy() then
local st = Battle.getState()
if st and st.enemy and st.enemy.mon and not foeLowered then
st.enemy.mon.hp = 1
foeLowered = true
end
U.wait(10) U.tap(game, "a") U.wait(10) U.tap(game, "a") U.wait(4)
elseif Message.isWaiting() and Ui.dialogPending() then
waitF = waitF + 1
if waitF >= 90 then
waitF = 0
U.tap(game, "a")
else
U.wait(1)
end
else
waitF = 0
U.wait(1)
end
end
result(outcome == "win", "battle outcome win (" .. tostring(outcome) .. ")")
result(ev.fainted_waiting ~= nil and ev.gained_open ~= nil and ev.gained_open - ev.fainted_waiting >= 90,
"fainted!\\p waits for a button press before getexp (" .. tostring(ev.fainted_waiting) .. " -> " .. tostring(ev.gained_open) .. ")")
result(songAt.fainted == VS_WILD, "MUS_VS_WILD still playing on the fainted message (" .. tostring(songAt.fainted) .. ")")
result(ev.victory_song ~= nil and ev.gained_open ~= nil and ev.victory_song <= ev.gained_open,
"MUS_VICTORY_WILD starts before the gained EXP text (" .. tostring(ev.victory_song) .. " <= " .. tostring(ev.gained_open) .. ")")
result(songAt.gained == VICTORY_WILD, "MUS_VICTORY_WILD playing under the gained EXP text")
result(gainedPrinted, "gained EXP text printed in full")
result(gainedOpenFrames >= 60, "gained EXP text on screen " .. gainedOpenFrames .. " frames")
result(not endedWhileGained, "battle did not start ending while the gained EXP text was up")
result(ev.grew_open ~= nil and ev.grew_open > (ev.gained_open or math.huge), "grew to LV text after the gained EXP text")
result(ev.stat_box ~= nil and ev.stat_box >= (ev.grew_open or math.huge), "level-up stat box shown after grew to LV")
result(ev.learn_prompt ~= nil and ev.learn_prompt > (ev.stat_box or math.huge), "move-learn prompt after the level-up box")
result(ev.battle_ending ~= nil and ev.battle_ending > (ev.learn_prompt or math.huge)
and ev.battle_ending > (ev.gained_closed or math.huge), "battle ends after the EXP / level / learn flow")
result(expShot and statShot and learnShot, "gained / level-up / learn prompt shots")
local m = session.party[1]
result(m and m.level == learnLv, "Mudkip reached LV" .. learnLv .. " (" .. tostring(m and m.level) .. ")")
return finish()
end