mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
174 lines
7.9 KiB
Lua
174 lines
7.9 KiB
Lua
#!/usr/bin/env luajit
|
|
-- pokefirered/src/battle_main.c:2611, pokefirered/src/battle_script_commands.c:4526, pokefirered/src/battle_script_commands.c:9463, pokefirered/src/battle_script_commands.c:9497, pokefirered/src/battle_script_commands.c:9617, pokefirered/src/pokemon.c:3686, pokefirered/src/pokemon.c:3692, pokefirered/src/new_game.c:56, pokemon.c:3692
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
require("tests.game3_cache").mountOrSkip("game3_scenario_capture_test")
|
|
require("tests.fixture_data.game3_items").install()
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local function finish()
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|
|
os.exit(0)
|
|
end
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
GameVersion.set("firered")
|
|
|
|
local Dex = require("src.core.game3.dex")
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local Bag = require("src.core.game3.bag")
|
|
local Catching = require("src.core.game3.battle.catching")
|
|
local BattleItems = require("src.core.game3.battle.items")
|
|
local Battle = require("src.core.game3.battle")
|
|
|
|
Pokemon.install(nil)
|
|
|
|
-- battle_script_commands.c:9463
|
|
local function rigRoll(lo)
|
|
return lo
|
|
end
|
|
|
|
local function newSession()
|
|
return {
|
|
name = "ASH",
|
|
id = 4242,
|
|
trainerId = 4242,
|
|
party = {
|
|
{ species = 1, name = "BULBASAUR", level = 8, hp = 25, maxHp = 25, moves = { 33 }, pp = { 35 } },
|
|
},
|
|
dex = Dex.new(),
|
|
bag = Bag.new(),
|
|
}
|
|
end
|
|
|
|
local session = newSession()
|
|
Bag.add(session.bag, 4, 3)
|
|
|
|
print("[test] 1. Wild Rattata appears: battle opens and the dex marks it seen")
|
|
local okStart = Battle.start({
|
|
wild = true,
|
|
headless = true,
|
|
autoFight = false,
|
|
playerParty = session.party,
|
|
foe = { species = 19, level = 3, hp = 6, maxHp = 15 },
|
|
session = session,
|
|
rng = rigRoll,
|
|
})
|
|
check(okStart == true, "the wild battle started")
|
|
check(Battle.isActive() == true, "the battle is active and waiting (not auto-run)")
|
|
local st = Battle.getState()
|
|
check(st ~= nil and st.wild == true, "battle state flags the encounter as wild")
|
|
-- battle_main.c:2611, battle_script_commands.c:4526
|
|
check(Dex.isSeen(session.dex, 19) == true, "Rattata registered as seen on encounter")
|
|
check(Dex.isCaught(session.dex, 19) == false, "Rattata is not caught yet")
|
|
check(Dex.countSeen(session.dex, "kanto") == 1, "kanto seen count is 1")
|
|
check(Dex.countCaught(session.dex, "kanto") == 0, "kanto caught count is 0")
|
|
check(st.enemy.mon.otId == 4242, "wild mon stamped with the trainer id (pokemon.c:3692 contract)")
|
|
check(type(session.secretId) == "number", "playerSecretId minted a session secret id")
|
|
check(st.enemy.mon.otSecretId == session.secretId, "the wild mon carries that secret id")
|
|
check(Catching.playerSecretId(session) == session.secretId, "playerSecretId is stable across calls")
|
|
|
|
print("[test] 2. Before throwing: ball identification and catch odds (battle_script_commands.c:9463)")
|
|
local foe = st.enemy
|
|
check(Catching.isBall(4) == true, "item 4 (POKE BALL) is a ball")
|
|
check(Catching.isBall(13) == false, "item 13 (POTION) is not a ball")
|
|
check(BattleItems.needsPartySelect(4) == false, "a ball throw needs no party target")
|
|
check(BattleItems.needsPartySelect(13) == true, "a potion asks which mon to heal")
|
|
check(Catching.ballMultiplier(2, foe, st, session) == 20, "Ultra Ball bonus is 2.0x (x10 scale)")
|
|
check(Catching.ballMultiplier(4, foe, st, session) == 10, "Poke Ball bonus is 1.0x")
|
|
check(Catching.catchOdds(1, foe, st, session) == 255, "Master Ball odds are always 255")
|
|
local curHp = foe.mon.hp
|
|
foe.mon.hp = foe.mon.maxHp
|
|
local fullOdds = Catching.catchOdds(4, foe, st, session)
|
|
foe.mon.hp = curHp
|
|
local curOdds = Catching.catchOdds(4, foe, st, session)
|
|
foe.mon.hp = 3
|
|
local lowOdds = Catching.catchOdds(4, foe, st, session)
|
|
foe.mon.hp = curHp
|
|
check(fullOdds < curOdds and curOdds < lowOdds,
|
|
string.format("odds improve as HP drops (%d < %d < %d)", fullOdds, curOdds, lowOdds))
|
|
check(fullOdds < 255 and curOdds < 255, "under 255, so the rigged roll is what decides this throw")
|
|
|
|
print("[test] 3. Throw #1: the Poke Ball is consumed and the rigged roll holds")
|
|
check(Bag.get(session.bag, 4) == 3, "three Poke Balls in the bag before the throw")
|
|
local result1, msgs1, endsTurn, endsBattle =
|
|
BattleItems.use(st, Battle._adapter, session.bag, session, 4)
|
|
check(result1 == "catch", "the throw caught the wild mon (got " .. tostring(result1) .. ")")
|
|
check(endsTurn == true and endsBattle == true, "a successful catch ends the turn and the battle")
|
|
check(Bag.get(session.bag, 4) == 2, "exactly one Poke Ball consumed")
|
|
local text1 = table.concat(msgs1, "\n")
|
|
check(text1:find("Gotcha", 1, true) ~= nil, "the Gotcha line was printed")
|
|
check(text1:find("added to the POK", 1, true) ~= nil,
|
|
"the first-time catch announces the Pokedex entry (got: " .. text1:gsub("\n", " / ") .. ")")
|
|
|
|
print("[test] 4. The capture lands: dex caught + party gains the mon (battle_script_commands.c:9617)")
|
|
check(#session.party == 2, "party grew from 1 to 2")
|
|
local caughtMon = session.party[2]
|
|
check(caughtMon.species == 19, "party slot 2 holds the Rattata")
|
|
check(caughtMon.pokeball == 4, "recorded with the Poke Ball it was caught in")
|
|
check(caughtMon.ot == "ASH", "OT name is the player")
|
|
check(caughtMon.otId == 4242, "OT id is the trainer id (pokemon.c:3692)")
|
|
check(caughtMon.otSecretId == session.secretId, "OT secret id matches the session's")
|
|
check(Dex.isCaught(session.dex, 19) == true, "Rattata marked caught in the dex")
|
|
check(Dex.countCaught(session.dex, "kanto") == 1, "kanto caught count is 1")
|
|
check(Dex.registerEncounter(session.dex, 19) == true,
|
|
"meeting it again reports it was already seen")
|
|
|
|
print("[test] 5. Second encounter: Pidgey, thrown at with the one Ultra Ball")
|
|
Battle.abort("caught")
|
|
check(Battle.isActive() == false, "the first battle is finished")
|
|
Bag.add(session.bag, 2, 1)
|
|
local okStart2 = Battle.start({
|
|
wild = true,
|
|
headless = true,
|
|
autoFight = false,
|
|
playerParty = session.party,
|
|
foe = { species = 16, level = 4, hp = 15, maxHp = 18 },
|
|
session = session,
|
|
rng = rigRoll,
|
|
})
|
|
check(okStart2 == true, "the second wild battle started")
|
|
local st2 = Battle.getState()
|
|
check(Dex.isSeen(session.dex, 16) == true, "Pidgey registered as seen")
|
|
check(Dex.countSeen(session.dex, "kanto") == 2, "kanto seen count is 2")
|
|
check(Bag.get(session.bag, 2) == 1, "one Ultra Ball in the bag before the throw")
|
|
local beforeCount = #session.party
|
|
local result2, msgs2 = BattleItems.use(st2, Battle._adapter, session.bag, session, 2)
|
|
check(result2 == "catch", "the Ultra Ball caught Pidgey (got " .. tostring(result2) .. ")")
|
|
check(Bag.get(session.bag, 2) == 0, "the Ultra Ball stack is emptied (slot removed)")
|
|
check(Bag.get(session.bag, 4) == 2, "the Poke Balls are untouched")
|
|
check(#session.party == beforeCount + 1, "the party gained another mon")
|
|
local pidgey = session.party[#session.party]
|
|
check(pidgey.species == 16, "the new party slot holds Pidgey")
|
|
check(pidgey.pokeball == 2, "recorded with the Ultra Ball")
|
|
check(Dex.countCaught(session.dex, "kanto") == 2, "kanto caught count is 2")
|
|
local text2 = table.concat(msgs2, "\n")
|
|
check(text2:find("added to the POK", 1, true) ~= nil,
|
|
"a first Pidgey still announces its dex entry (got: " .. text2:gsub("\n", " / ") .. ")")
|
|
|
|
print("[test] 6. Out of Ultra Balls: the throw is refused, nothing changes")
|
|
local result3, msgs3 = BattleItems.use(st2, Battle._adapter, session.bag, session, 2)
|
|
check(result3 == "error", "an empty pocket refuses the item (got " .. tostring(result3) .. ")")
|
|
check(table.concat(msgs3, "\n"):find("don't have", 1, true) ~= nil, "the player is told they have none")
|
|
check(#session.party == 3, "party unchanged: starter + two catches")
|
|
check(Bag.get(session.bag, 2) == 0, "still zero Ultra Balls")
|
|
check(Bag.get(session.bag, 4) == 2, "Poke Balls still untouched")
|
|
check(Dex.countCaught(session.dex, "kanto") == 2, "no phantom dex entry from the refused throw")
|
|
Battle.abort("caught")
|
|
check(Battle.isActive() == false, "battles closed down; nothing left open")
|
|
|
|
finish()
|