mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
457 lines
19 KiB
Lua
457 lines
19 KiB
Lua
-- Comprehensive test suite for Game 3 Pokédex tracking, catch mechanics, and UI.
|
|
|
|
require("tests.game3_cache").requireData("game3_pokedex_and_catch_test")
|
|
local GameVersion = require("src.core.GameVersion")
|
|
GameVersion.set("firered")
|
|
|
|
local Dex = require("src.core.game3.dex")
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local Catching = require("src.core.game3.battle.catching")
|
|
local BattleItems = require("src.core.game3.battle.items")
|
|
local Bag = require("src.core.game3.bag")
|
|
local Battle = require("src.core.game3.battle")
|
|
local Pokedex = require("src.ui.game3.pokedex")
|
|
|
|
Pokemon.install(nil)
|
|
|
|
print("[test] 1. Pokédex data structure & seen/caught tracking")
|
|
local dex = Dex.new()
|
|
assert(Dex.isSeen(dex, 1) == false, "Bulbasaur not seen initially")
|
|
assert(Dex.isCaught(dex, 1) == false, "Bulbasaur not caught initially")
|
|
assert(Dex.countSeen(dex, "kanto") == 0, "0 seen in Kanto")
|
|
assert(Dex.countCaught(dex, "kanto") == 0, "0 caught in Kanto")
|
|
|
|
-- Register encounter
|
|
local wasSeen = Dex.registerEncounter(dex, 1)
|
|
assert(wasSeen == false, "First encounter was not previously seen")
|
|
assert(Dex.isSeen(dex, 1) == true, "Bulbasaur is now seen")
|
|
assert(Dex.isCaught(dex, 1) == false, "Bulbasaur is not yet caught")
|
|
assert(Dex.countSeen(dex, "kanto") == 1, "1 seen in Kanto")
|
|
assert(Dex.countCaught(dex, "kanto") == 0, "0 caught in Kanto")
|
|
|
|
-- Second encounter returns wasSeen == true
|
|
assert(Dex.registerEncounter(dex, 1) == true, "Second encounter knows it was seen")
|
|
|
|
-- Register capture
|
|
local wasCaught = Dex.registerCapture(dex, 1)
|
|
assert(wasCaught == false, "First capture was not previously caught")
|
|
assert(Dex.isCaught(dex, 1) == true, "Bulbasaur is now caught")
|
|
assert(Dex.countSeen(dex, "kanto") == 1, "1 seen in Kanto")
|
|
assert(Dex.countCaught(dex, "kanto") == 1, "1 caught in Kanto")
|
|
|
|
-- String resolution
|
|
Dex.setSeen(dex, "CHARMANDER")
|
|
Dex.setCaught(dex, "CHARMANDER")
|
|
assert(Dex.isSeen(dex, 4) == true, "Charmander numeric is seen")
|
|
assert(Dex.isCaught(dex, 4) == true, "Charmander numeric is caught")
|
|
assert(Dex.isSeen(dex, "CHARMANDER") == true, "Charmander string is seen")
|
|
assert(Dex.isCaught(dex, "CHARMANDER") == true, "Charmander string is caught")
|
|
assert(Dex.countSeen(dex, "kanto") == 2, "2 seen in Kanto")
|
|
assert(Dex.countCaught(dex, "kanto") == 2, "2 caught in Kanto")
|
|
|
|
-- National dex tracking (e.g. Torchic = 255)
|
|
Dex.setSeen(dex, 255)
|
|
Dex.setCaught(dex, 255)
|
|
assert(Dex.countSeen(dex, "kanto") == 2, "Kanto seen count ignores Torchic (255)")
|
|
assert(Dex.countCaught(dex, "kanto") == 2, "Kanto caught count ignores Torchic (255)")
|
|
assert(Dex.countSeen(dex, "national") == 3, "National seen count includes Torchic")
|
|
assert(Dex.countCaught(dex, "national") == 3, "National caught count includes Torchic")
|
|
print("[ok] Pokédex seen/caught tracking and Kanto/National counts passed")
|
|
|
|
print("[test] 2. Catch rate calculations & ball multipliers")
|
|
local foePikachu = {
|
|
species = 25,
|
|
type1 = 13, -- ELECTRIC
|
|
mon = { species = 25, level = 5, hp = 10, maxHp = 20, status = nil }
|
|
}
|
|
|
|
-- Master Ball (item 1) -> guaranteed 255 odds
|
|
local masterOdds = Catching.catchOdds(1, foePikachu, {}, { dex = dex })
|
|
assert(masterOdds == 255, "Master ball catch odds is 255")
|
|
|
|
-- Ultra Ball (item 2) vs Poké Ball (item 4)
|
|
local pokeOdds = Catching.catchOdds(4, foePikachu, {}, { dex = dex })
|
|
local ultraOdds = Catching.catchOdds(2, foePikachu, {}, { dex = dex })
|
|
assert(ultraOdds > pokeOdds, "Ultra ball has higher odds than Poké ball")
|
|
assert(math.abs(ultraOdds - pokeOdds * 2) <= 1, "Ultra ball bonus is ~2x Poké ball")
|
|
|
|
-- Status bonuses: Sleep doubles base odds
|
|
foePikachu.status = "SLP"
|
|
local sleepOdds = Catching.catchOdds(4, foePikachu, {}, { dex = dex })
|
|
assert(sleepOdds == pokeOdds * 2 or sleepOdds == 255, "Sleep status doubles catch odds")
|
|
|
|
-- Net Ball (item 6) on Water type
|
|
local foeSquirtle = {
|
|
species = 7,
|
|
type1 = 11, -- WATER
|
|
mon = { species = 7, level = 5, hp = 10, maxHp = 20 }
|
|
}
|
|
local netMultWater = Catching.ballMultiplier(6, foeSquirtle, {}, { dex = dex })
|
|
assert(netMultWater == 30, "Net ball gets 3x multiplier on Water type")
|
|
|
|
-- Repeat Ball (item 9) on previously caught vs uncaught species
|
|
local repeatMultCaught = Catching.ballMultiplier(9, { species = 1, mon = { level = 5 } }, {}, { dex = dex })
|
|
assert(repeatMultCaught == 30, "Repeat ball gets 3x multiplier on caught species (Bulbasaur)")
|
|
local repeatMultUncaught = Catching.ballMultiplier(9, { species = 150, mon = { level = 70 } }, {}, { dex = dex })
|
|
assert(repeatMultUncaught == 10, "Repeat ball gets 1x on uncaught species (Mewtwo)")
|
|
|
|
-- Timer Ball (item 10) scaling with turns
|
|
local timerMultT1 = Catching.ballMultiplier(10, foePikachu, { turn = 1 }, { dex = dex })
|
|
local timerMultT15 = Catching.ballMultiplier(10, foePikachu, { turn = 15 }, { dex = dex })
|
|
local timerMultT40 = Catching.ballMultiplier(10, foePikachu, { turn = 40 }, { dex = dex })
|
|
assert(timerMultT1 == 11, "Timer ball at turn 1 is 1.1x")
|
|
assert(timerMultT15 == 25, "Timer ball at turn 15 is 2.5x")
|
|
assert(timerMultT40 == 40, "Timer ball caps at 4.0x")
|
|
print("[ok] Catch rate calculations and ball multipliers passed")
|
|
|
|
print("[test] 3. Deterministic Catch simulation & Storage (Party vs PC)")
|
|
-- Deterministic RNG mock
|
|
local mockRngPass = function(lo, hi) return lo end -- always passes threshold
|
|
local mockRngFail = function(lo, hi) return hi end -- always fails threshold
|
|
|
|
local foeCaterpie = {
|
|
species = 10,
|
|
mon = { species = 10, level = 3, hp = 2, maxHp = 15, moves = { 33 } }
|
|
}
|
|
local session = {
|
|
name = "RED",
|
|
id = 54321,
|
|
party = { { species = 1, level = 10, hp = 30, maxHp = 30 } },
|
|
dex = Dex.new(),
|
|
}
|
|
|
|
-- Catch Caterpie with Master Ball
|
|
local caught, shakes = Catching.tryCatch(1, foeCaterpie, {}, session, mockRngPass)
|
|
assert(caught == true, "Master ball catches Caterpie")
|
|
assert(shakes == 4, "Master ball gives 4 shakes")
|
|
|
|
-- Store Caterpie into party (< 6)
|
|
local res = Catching.storeCaught(session, foeCaterpie, 1)
|
|
assert(res.success == true, "storeCaught succeeded")
|
|
assert(res.location == "party", "Caterpie stored in party")
|
|
assert(res.firstTimeCaught == true, "First time Caterpie was caught")
|
|
assert(#session.party == 2, "Party count is now 2")
|
|
assert(session.party[2].species == 10, "Party slot 2 is Caterpie")
|
|
assert(session.party[2].pokeball == 1, "Stored with Master Ball ID")
|
|
assert(session.party[2].ot == "RED", "OT set to RED")
|
|
assert(Dex.isCaught(session.dex, 10) == true, "Caterpie marked caught in Dex")
|
|
|
|
-- Fill party to 6 Pokémon
|
|
while #session.party < 6 do
|
|
session.party[#session.party + 1] = { species = 1, level = 5, hp = 20, maxHp = 20 }
|
|
end
|
|
assert(#session.party == 6, "Party is now full (6)")
|
|
|
|
-- Catch Pidgey (species 16) -> should go to PC
|
|
local foePidgey = {
|
|
species = 16,
|
|
mon = { species = 16, level = 4, hp = 5, maxHp = 18 }
|
|
}
|
|
local resPc = Catching.storeCaught(session, foePidgey, 4)
|
|
assert(resPc.location == "pc", "Pidgey transferred to PC when party is full")
|
|
assert(resPc.firstTimeCaught == true, "First time Pidgey was caught")
|
|
assert(#session.party == 6, "Party still has 6 Pokémon")
|
|
assert(session.pc == nil, "no parallel session.pc table")
|
|
assert(require("src.core.game3.storage").countTotalMons(session.storage) == 1, "PC box has 1 Pokémon")
|
|
assert(session.storage.boxes[resPc.box].mons[resPc.slot].species == 16, "PC mon is Pidgey")
|
|
assert(Dex.isCaught(session.dex, 16) == true, "Pidgey marked caught in Dex")
|
|
|
|
-- Second capture of Caterpie -> firstTimeCaught is false
|
|
local res2 = Catching.storeCaught(session, foeCaterpie, 4)
|
|
assert(res2.firstTimeCaught == false, "Second Caterpie is not firstTimeCaught")
|
|
print("[ok] Deterministic catch simulation and party/PC storage passed")
|
|
|
|
print("[test] 4. In-battle encounter & ball use")
|
|
local battleSession = {
|
|
name = "RED",
|
|
party = { { species = 1, level = 10, hp = 30, maxHp = 30 } },
|
|
dex = Dex.new(),
|
|
}
|
|
local testBag = Bag.new()
|
|
Bag.add(testBag, "POKE_BALL", 2)
|
|
|
|
-- Wild battle start should mark wild opponent as SEEN
|
|
local foeRattata = { species = 19, level = 3, hp = 10, maxHp = 15 }
|
|
assert(Dex.isSeen(battleSession.dex, 19) == false, "Rattata not seen before battle")
|
|
|
|
Battle.start({
|
|
headless = true,
|
|
wild = true,
|
|
playerParty = battleSession.party,
|
|
foe = foeRattata,
|
|
session = battleSession,
|
|
})
|
|
assert(Dex.isSeen(battleSession.dex, 19) == true, "Rattata registered as SEEN on battle start")
|
|
assert(Dex.isCaught(battleSession.dex, 19) == false, "Rattata not yet caught")
|
|
|
|
assert(BattleItems.needsPartySelect(4) == false, "Poké Ball does not need party select")
|
|
assert(BattleItems.needsPartySelect("POKE_BALL") == false, "POKE_BALL does not need party select")
|
|
assert(BattleItems.needsPartySelect(13) == true, "Potion needs party select")
|
|
assert(BattleItems.needsPartySelect("POTION") == true, "POTION needs party select")
|
|
|
|
-- BattleItems.use ball in battle
|
|
local st = Battle._st
|
|
local adapter = Battle._adapter
|
|
local useRes, msgs, endsTurn, endsBattle = BattleItems.use(st, adapter, testBag, battleSession, 4)
|
|
assert(Bag.get(testBag, "POKE_BALL") == 1, "1 Poké Ball consumed from bag")
|
|
assert(endsTurn == true, "Ball throw ends player turn")
|
|
print("[ok] In-battle encounter marking and ball usage passed")
|
|
|
|
print("[test] 5. Pokédex UI Screen lifecycle and navigation")
|
|
local mockInput = {
|
|
_pressed = {},
|
|
wasPressed = function(self, key) return self._pressed[key] == true end,
|
|
press = function(self, key) self._pressed = { [key] = true } end,
|
|
clear = function(self) self._pressed = {} end,
|
|
}
|
|
|
|
local uiDex = Dex.new()
|
|
Dex.setSeen(uiDex, 1) -- Bulbasaur (seen)
|
|
Dex.setCaught(uiDex, 1) -- Bulbasaur (caught)
|
|
Dex.setSeen(uiDex, 4) -- Charmander (seen)
|
|
Dex.setSeen(uiDex, 255) -- Torchic (seen national)
|
|
|
|
Pokedex.show(uiDex, { session = { dex = uiDex }, mode = "kanto" })
|
|
assert(Pokedex.isOpen() == true, "Pokédex is open")
|
|
assert(Pokedex.mode == "kanto", "Pokédex is in Kanto mode")
|
|
assert(Pokedex.page == "list", "Pokédex starts on list page")
|
|
assert(Pokedex.maxSpecies() == 151, "Kanto mode max species is 151")
|
|
|
|
-- Cursor down
|
|
mockInput:press("down")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.cursor == 2, "Cursor moved to No.002 Ivysaur")
|
|
|
|
-- Press A on unseen Ivysaur -> stays on list
|
|
mockInput:press("a")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.page == "list", "Cannot open entry for unseen Pokémon")
|
|
|
|
-- Move to No.001 Bulbasaur and press A -> opens entry
|
|
mockInput:press("up")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.cursor == 1, "Cursor on No.001 Bulbasaur")
|
|
mockInput:press("a")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.page == "entry", "Opens detailed entry page for Bulbasaur")
|
|
|
|
-- Press Down in entry mode -> jumps to next seen Pokémon (No.004 Charmander)
|
|
mockInput:press("down")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.cursor == 4, "Entry view jumps directly to next seen (Charmander)")
|
|
|
|
-- Press B in entry mode -> returns to list
|
|
mockInput:press("b")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.page == "list", "Returns to list page on B")
|
|
|
|
-- Switch to National Mode
|
|
mockInput:press("right")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.mode == "national", "Switched to National Mode")
|
|
assert(Pokedex.maxSpecies() == 386, "National mode max species is 386")
|
|
|
|
-- Press B in list mode -> returns to mode_select
|
|
mockInput:press("b")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.screen == "mode_select", "Returns to mode_select on B")
|
|
|
|
-- Close Pokédex from mode_select
|
|
mockInput:press("b")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.isOpen() == false, "Pokédex is closed")
|
|
|
|
-- Test PokedexChrome data loader
|
|
local PokedexChrome = require("src.ui.game3.pokedex_chrome")
|
|
PokedexChrome.install()
|
|
local bulbaEntry = PokedexChrome.getEntry(1)
|
|
assert(bulbaEntry ~= nil, "Bulbasaur entry exists")
|
|
assert(bulbaEntry.category == "SEED", "Bulbasaur is SEED category")
|
|
assert(bulbaEntry.categoryName == "SEED POKéMON", "Bulbasaur category name formatted")
|
|
assert(bulbaEntry.heightFormatted:find("2'04\"") ~= nil, "Bulbasaur height formatted")
|
|
assert(bulbaEntry.weightFormatted:find("15.2 lbs.") ~= nil, "Bulbasaur weight formatted")
|
|
assert(#bulbaEntry.description > 10, "Bulbasaur has description flavor text")
|
|
|
|
-- Test First-Time Caught Registration Screen
|
|
local regClosed = false
|
|
Pokedex.showRegistration(19, {
|
|
session = { dex = uiDex },
|
|
onDone = function() regClosed = true end,
|
|
})
|
|
assert(Pokedex.isOpen() == true, "Registration screen is open")
|
|
assert(Pokedex.mode == "registration", "Mode is registration")
|
|
assert(Pokedex._regSpecies == 19, "Registered species is Rattata (19)")
|
|
|
|
-- Press A to dismiss registration screen
|
|
mockInput:press("a")
|
|
Pokedex.handleInput(mockInput)
|
|
assert(Pokedex.isOpen() == false, "Registration screen closed on A press")
|
|
assert(regClosed == true, "onDone callback invoked")
|
|
print("[ok] Pokédex UI navigation, chrome entries, and registration view passed")
|
|
|
|
print("[test] 6. Battle Bag pocket navigation (ITEMS -> KEY_ITEMS -> POKE_BALLS) and action back-out")
|
|
local BagMenu = require("src.ui.game3.bag_menu")
|
|
local battleBag = Bag.new()
|
|
Bag.add(battleBag, "POTION", 3)
|
|
Bag.add(battleBag, "POKE_BALL", 5)
|
|
|
|
BagMenu.show(battleBag, {
|
|
session = { party = session.party, bag = battleBag },
|
|
battle = true,
|
|
})
|
|
assert(BagMenu.isOpen() == true, "BagMenu is open in battle")
|
|
assert(BagMenu.mode == "list", "BagMenu starts in list mode (not action mode)")
|
|
assert(BagMenu.currentPocket() == "ITEMS", "Starts on ITEMS pocket")
|
|
BagMenu.settle()
|
|
|
|
-- Swap to POKé_BALLS pocket with right arrow
|
|
mockInput:press("right")
|
|
BagMenu.handleInput(mockInput)
|
|
assert(BagMenu.currentPocket() == "KEY_ITEMS", "Swapped to KEY_ITEMS pocket")
|
|
mockInput:press("right")
|
|
BagMenu.handleInput(mockInput)
|
|
BagMenu.settle()
|
|
assert(BagMenu.currentPocket() == "POKE_BALLS", "Swapped to POKE_BALLS pocket")
|
|
assert(#BagMenu.list() == 1, "1 ball item in pocket")
|
|
assert(BagMenu.list()[1].id == 4 or BagMenu.list()[1].name == "POKé BALL", "Poke ball in list")
|
|
|
|
-- Press A on Poké Ball -> opens action mode
|
|
mockInput:press("a")
|
|
BagMenu.handleInput(mockInput)
|
|
assert(BagMenu.mode == "action", "Action mode opened for Poke Ball")
|
|
|
|
-- Press B in action mode -> backs out cleanly to list mode without closing bag
|
|
mockInput:press("b")
|
|
BagMenu.handleInput(mockInput)
|
|
assert(BagMenu.mode == "list", "Backed out to list mode on B")
|
|
assert(BagMenu.isOpen() == true, "BagMenu remains open")
|
|
assert(BagMenu.currentPocket() == "POKE_BALLS", "Still in POKE_BALLS pocket")
|
|
|
|
-- Swap back to ITEMS pocket with left arrow
|
|
mockInput:press("left")
|
|
BagMenu.handleInput(mockInput)
|
|
mockInput:press("left")
|
|
BagMenu.handleInput(mockInput)
|
|
BagMenu.settle()
|
|
assert(BagMenu.currentPocket() == "ITEMS", "Swapped back to ITEMS pocket")
|
|
|
|
-- Close bag with B in list mode
|
|
mockInput:press("b")
|
|
BagMenu.handleInput(mockInput)
|
|
BagMenu.settle()
|
|
assert(BagMenu.isOpen() == false, "BagMenu closed on B in list mode")
|
|
print("[ok] Battle bag pocket navigation and action back-out passed")
|
|
|
|
print("[test] 7. CatchSeq animation state machine, shakes & breakout vs capture")
|
|
local CatchSeq = require("src.core.game3.battle.catch_seq")
|
|
local Anim = require("src.core.game3.battle.anim")
|
|
local Task = require("src.core.game3.task")
|
|
|
|
-- Test CatchSeq with capture success (4 shakes)
|
|
Anim.reset({ headless = false })
|
|
local mockBattleSt = {
|
|
enemy = { species = 19, mon = { species = 19, name = "RATTATA", hp = 5, maxHp = 15 } },
|
|
}
|
|
local pushedMsgs = {}
|
|
CatchSeq.begin(mockBattleSt, 4, true, 4, {
|
|
pushMsg = function(t) pushedMsgs[#pushedMsgs + 1] = t end,
|
|
headless = false,
|
|
session = session,
|
|
})
|
|
assert(CatchSeq.busy() == true, "CatchSeq is busy after begin")
|
|
assert(#CatchSeq._steps == 3, "3 steps in catch sequence (msg, throw anim, success)")
|
|
assert(CatchSeq._steps[1].kind == "msg", "Step 1 is msg")
|
|
assert(CatchSeq._steps[2].kind == "throw" and CatchSeq._steps[2].data.caseId == 4, "Step 2 is the throw anim with BALL_3_SHAKES_SUCCESS")
|
|
assert(CatchSeq._steps[3].kind == "capture_success", "Step 3 is capture_success")
|
|
|
|
-- Step through tasks until completion
|
|
local safety = 0
|
|
while CatchSeq.busy() and safety < 2500 do
|
|
safety = safety + 1
|
|
Task.update(1 / 60)
|
|
Anim.update(1 / 60)
|
|
CatchSeq.update()
|
|
if CatchSeq._waitingMsg then
|
|
CatchSeq._waitingMsg = false
|
|
end
|
|
end
|
|
assert(CatchSeq.busy() == false, "CatchSeq finished all animation steps")
|
|
assert(CatchSeq.result() == "catch", "Result is catch")
|
|
|
|
-- Test CatchSeq with breakout (1 shake)
|
|
Anim.reset({ headless = false })
|
|
local breakoutMsgs = {}
|
|
CatchSeq.begin(mockBattleSt, 4, false, 1, {
|
|
pushMsg = function(t) breakoutMsgs[#breakoutMsgs + 1] = t end,
|
|
headless = false,
|
|
session = session,
|
|
})
|
|
assert(CatchSeq.busy() == true, "Breakout CatchSeq is busy")
|
|
assert(#CatchSeq._steps == 3, "3 steps in 1-shake breakout (msg, throw anim, breakout)")
|
|
assert(CatchSeq._steps[2].data.caseId == 1, "Step 2 throws with BALL_1_SHAKE")
|
|
assert(CatchSeq._steps[3].kind == "breakout", "Step 3 is breakout")
|
|
|
|
safety = 0
|
|
while CatchSeq.busy() and safety < 2500 do
|
|
safety = safety + 1
|
|
Task.update(1 / 60)
|
|
Anim.update(1 / 60)
|
|
CatchSeq.update()
|
|
if CatchSeq._waitingMsg then
|
|
CatchSeq._waitingMsg = false
|
|
end
|
|
end
|
|
assert(CatchSeq.busy() == false, "Breakout CatchSeq finished")
|
|
assert(CatchSeq.result() == "fail_catch", "Result is fail_catch")
|
|
print("[ok] CatchSeq animation state machine, shakes & breakout vs capture passed")
|
|
|
|
print("[test] 8. LCRNG generator & catch math verification")
|
|
local Rng = require("src.core.game3.rng")
|
|
Rng.SeedRng(12345)
|
|
local r1 = Rng.Random()
|
|
local r2 = Rng.Random()
|
|
assert(r1 ~= r2, "Random advances state")
|
|
|
|
-- Verify deterministic catch rate with seeded RNG
|
|
Rng.SeedRng(42)
|
|
local odds = Catching.catchOdds(4, mockBattleSt.enemy, mockBattleSt, session)
|
|
assert(odds > 0, "Valid catch odds computed")
|
|
|
|
local caughtSeeded, shakesSeeded = Catching.tryCatch(4, mockBattleSt.enemy, mockBattleSt, session, Rng.compat)
|
|
assert(type(caughtSeeded) == "boolean", "Returns boolean caught flag")
|
|
assert(type(shakesSeeded) == "number" and shakesSeeded >= 0 and shakesSeeded <= 4, "Shakes is 0..4")
|
|
print("[ok] LCRNG generator & catch math verification passed")
|
|
|
|
print("[test] 9. Battle.update Pokédex registration input dispatch")
|
|
Battle.start({
|
|
wild = true,
|
|
playerParty = { { species = 25, hp = 20, maxHp = 20, level = 5, moves = { { id = 33, pp = 35 } } } },
|
|
foe = { species = 19, level = 3, hp = 10, maxHp = 10 },
|
|
headless = false,
|
|
session = session,
|
|
})
|
|
assert(Battle.isActive() == true, "Battle is active")
|
|
|
|
-- Manually trigger pokedex_reg phase
|
|
local onDoneCalled = false
|
|
Pokedex.showRegistration(19, {
|
|
session = session,
|
|
onDone = function()
|
|
onDoneCalled = true
|
|
Battle._phase = "ending"
|
|
end,
|
|
})
|
|
Battle._phase = "pokedex_reg"
|
|
assert(Pokedex.isOpen() == true, "Pokedex registration is open during battle")
|
|
|
|
-- Send A press via Battle.update
|
|
mockInput:press("a")
|
|
Battle.update(1 / 60, { input = mockInput })
|
|
assert(Pokedex.isOpen() == false, "Pokedex registration closed via Battle.update input dispatch")
|
|
assert(onDoneCalled == true, "onDone callback invoked successfully")
|
|
assert(Battle._phase == "ending", "Battle transitioned to ending phase")
|
|
print("[ok] Battle.update Pokédex registration input dispatch passed")
|
|
|
|
print("[test] all Pokédex and catch mechanics tests passed successfully!")
|
|
|