Files
gen1recomp/tests/parity_F.lua
T
2026-07-19 16:18:18 -04:00

93 lines
4.2 KiB
Lua

-- Parity test, Workstream F.
-- Self-contained: run via `luajit tests/parity_F.lua`; also dofile'd by
-- tests/run_tests.lua's aggregator.
--
-- Covers: Oak no longer hands over 5 POKé BALLs the instant a starter is
-- picked (scripts/OaksLab.asm has no such grant); the balls are handed
-- over later, at TEXT_OAKSLAB_OAK1's .give_poke_balls beat, gated on
-- EVENT_BEAT_ROUTE22_RIVAL_1ST_BATTLE and the one-shot
-- EVENT_GOT_POKEBALLS_FROM_OAK flag (data/scripts/oaks_lab.lua).
package.path = "./?.lua;./?/init.lua;" .. package.path
if not _G.love then _G.love = require("tests.love_stub") end
local Data = require("src.core.Data")
if not (Data.maps and Data.maps.PALLET_TOWN) then Data:load() end
local S = require("tests.harness").suite("parity F")
local check, eq = S.check, S.eq
local Game = require("src.core.Game")
local Input = require("src.core.Input")
local StateStack = require("src.core.StateStack")
local SaveData = require("src.core.SaveData")
local ScriptRunner = require("src.script.ScriptRunner")
local Flags = require("src.script.Flags")
local mapScripts = require("data.scripts.init")
Game.data = Data
Game.input = Input; Input:init()
Game.stack = StateStack; StateStack:init()
Game.save = SaveData.newGame()
require("src.render.Font").load(Data)
-- pumps a script coroutine to completion, mashing A through any
-- show_text/ask boxes along the way (mirrors tests/run_tests.lua's
-- runScript helper for the parcel/pokedex chain)
local function runScript(script)
local r = ScriptRunner.new(Game, nil)
r:run(script, {})
local guard = 0
while r:isRunning() and guard < 2000 do
guard = guard + 1
Input.pressed = { a = true }
StateStack:update(1 / 60)
r:update()
end
Input.pressed = {}
return not r:isRunning()
end
-- === 1) picking a starter no longer grants POKé BALLs ===
-- (like the parcel-chain runScript below, this runner has no live
-- overworld; the starterBall() script's give_pokemon/set_flag rows run
-- fine, but its later rival-counterpick NPC choreography needs
-- ctx.overworld and errors out headless -- the ScriptRunner logs and
-- kills the coroutine, so isRunning() still goes false, which is all we
-- need to check the pre-crash flag/inventory state below)
Flags.set(Game.save, "EVENT_FOLLOWED_OAK_INTO_LAB")
check(runScript(mapScripts.talkScript("OAKS_LAB", "TEXT_OAKSLAB_BULBASAUR_POKE_BALL")),
"starter pick script completes")
check(Flags.get(Game.save, "EVENT_GOT_STARTER"), "starter flag set")
eq(Game.save.inventory.POKE_BALL, nil, "no POKe BALLs yet right after picking a starter")
-- === 2) the parcel/pokedex beat still doesn't grant POKé BALLs ===
check(runScript(mapScripts.talkScript("VIRIDIAN_MART", "TEXT_VIRIDIANMART_CLERK")),
"mart clerk script completes")
eq(Game.save.inventory.OAKS_PARCEL, 1, "clerk hands over Oak's Parcel")
check(runScript(mapScripts.talkScript("OAKS_LAB", "TEXT_OAKSLAB_OAK1")),
"Oak delivery script completes")
eq(Game.save.inventory.OAKS_PARCEL, nil, "parcel delivered")
check(Flags.get(Game.save, "EVENT_OAK_GOT_PARCEL"), "delivery flag set")
check(Flags.get(Game.save, "EVENT_GOT_POKEDEX"), "Pokedex flag set")
eq(Game.save.inventory.POKE_BALL, nil, "still no POKe BALLs at the pokedex beat")
-- talking to Oak again before beating the Route 22 rival should fall
-- into the RaiseYourYoungPokemon branch, not give balls
check(runScript(mapScripts.talkScript("OAKS_LAB", "TEXT_OAKSLAB_OAK1")),
"Oak talk (pre-Route22-win) script completes")
eq(Game.save.inventory.POKE_BALL, nil, "still no POKe BALLs before the Route 22 rival is beaten")
-- === 3) beating the Route 22 rival unlocks the real grant ===
Flags.set(Game.save, "EVENT_BEAT_ROUTE22_RIVAL_1ST_BATTLE")
check(runScript(mapScripts.talkScript("OAKS_LAB", "TEXT_OAKSLAB_OAK1")),
"Oak give-balls script completes")
eq(Game.save.inventory.POKE_BALL, 5, "Oak gives 5 POKe Balls after the Route 22 win")
check(Flags.get(Game.save, "EVENT_GOT_POKEBALLS_FROM_OAK"), "one-shot flag set")
-- === 4) talking to Oak again does not re-grant (one-shot gate) ===
check(runScript(mapScripts.talkScript("OAKS_LAB", "TEXT_OAKSLAB_OAK1")),
"Oak talk (post-grant) script completes")
eq(Game.save.inventory.POKE_BALL, 5, "POKe Ball count unchanged on a second talk")
S.finish()