mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
229 lines
7.7 KiB
Lua
229 lines
7.7 KiB
Lua
#!/usr/bin/env luajit
|
|
-- Game3 battle bag: catch odds, medicine, X items, doll.
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
require("tests.game3_cache").mountOrSkip("game3_battle_bag_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 Bag = require("src.core.game3.bag")
|
|
local ItemsData = require("src.core.game3.items_data")
|
|
local BattleItems = require("src.core.game3.battle.items")
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local Battle = require("src.core.game3.battle")
|
|
local State = require("src.core.game3.battle.state")
|
|
local Adapter = require("src.core.game3.battle.adapter")
|
|
|
|
require("tests.fixture_data.game3_items").install()
|
|
Pokemon.install(nil)
|
|
|
|
print("[test] 1. Catch odds / Master Ball")
|
|
local foe = State.makeBattler({
|
|
species = 16, level = 5, hp = 20, maxHp = 20,
|
|
moves = { 33 }, pp = { 35 },
|
|
}, "enemy")
|
|
local odds = BattleItems.catchOdds(4, foe, { turn = 1 })
|
|
check(odds > 0, "POKE BALL odds > 0 (" .. tostring(odds) .. ")")
|
|
local lowHp = State.makeBattler({
|
|
species = 16, level = 5, hp = 1, maxHp = 20,
|
|
moves = { 33 }, pp = { 35 },
|
|
}, "enemy")
|
|
local oddsLow = BattleItems.catchOdds(4, lowHp, { turn = 1 })
|
|
check(oddsLow > odds, "lower HP raises catch odds")
|
|
local caught, shakes = BattleItems.tryCatch(1, foe, { turn = 1 }, function() return 0 end)
|
|
check(caught == true and shakes == 4, "MASTER BALL always catches")
|
|
|
|
print("[test] 2. Battle medicine / X item / doll")
|
|
local bag = Bag.new()
|
|
Bag.add(bag, 13, 2)
|
|
Bag.add(bag, 75, 1)
|
|
Bag.add(bag, 80, 1)
|
|
Bag.add(bag, 4, 5)
|
|
|
|
local session = {
|
|
name = "RED",
|
|
bag = bag,
|
|
party = {
|
|
{ species = 1, name = "BULBASAUR", hp = 5, maxHp = 20, moves = { 33 }, pp = { 35 } },
|
|
},
|
|
dex = { seen = {}, owned = {} },
|
|
}
|
|
local player = State.makeBattler(session.party[1], "player", { partyIndex = 1 })
|
|
local st = {
|
|
wild = true,
|
|
turn = 3,
|
|
player = player,
|
|
enemy = foe,
|
|
playerParty = session.party,
|
|
}
|
|
local msgs = {}
|
|
local ad = Adapter.new(st, function(t) msgs[#msgs + 1] = t end)
|
|
|
|
local r1 = BattleItems.use(st, ad, bag, session, 13, 1)
|
|
check(r1 == "heal", "POTION heals in battle")
|
|
check(session.party[1].hp > 5, "HP restored")
|
|
check(Bag.get(bag, 13) == 1, "POTION consumed")
|
|
|
|
local r2 = BattleItems.use(st, ad, bag, session, 75, nil)
|
|
check(r2 == "xitem", "X ATTACK used")
|
|
check((player.stages.attack or 0) >= 1, "attack stage rose")
|
|
|
|
local r3 = BattleItems.use(st, ad, bag, session, 80, nil)
|
|
check(r3 == "doll", "POKE DOLL flees wild")
|
|
|
|
print("[test] 3. Catch stores mon")
|
|
bag = Bag.new()
|
|
Bag.add(bag, 1, 1) -- Master Ball
|
|
session = {
|
|
name = "RED",
|
|
bag = bag,
|
|
party = {
|
|
{ species = 1, name = "BULBASAUR", hp = 20, maxHp = 20, moves = { 33 }, pp = { 35 } },
|
|
},
|
|
dex = { seen = {}, owned = {} },
|
|
}
|
|
st = {
|
|
wild = true,
|
|
turn = 1,
|
|
player = State.makeBattler(session.party[1], "player", { partyIndex = 1 }),
|
|
enemy = State.makeBattler({
|
|
species = 19, level = 3, hp = 10, maxHp = 15, moves = { 33 }, pp = { 35 },
|
|
}, "enemy"),
|
|
playerParty = session.party,
|
|
}
|
|
ad = Adapter.new(st, function() end)
|
|
local rc = BattleItems.use(st, ad, bag, session, 1, nil)
|
|
check(rc == "catch", "Master Ball catch result")
|
|
check(#session.party == 2, "caught mon added to party")
|
|
check(session.dex.owned[19] == true, "dex owned RATTATA")
|
|
check(Bag.get(bag, 1) == 0, "Master Ball consumed")
|
|
|
|
print("[test] 4. Trainer blocks balls")
|
|
st.wild = false
|
|
Bag.add(bag, 4, 1)
|
|
local rt = BattleItems.use(st, ad, bag, session, 4, nil)
|
|
check(rt == "error", "ball blocked in trainer battle")
|
|
check(Bag.get(bag, 4) == 1, "ball not consumed when blocked")
|
|
|
|
print("[test] 5. Meta bag catch ends battle")
|
|
local Runtime = {
|
|
_session = {
|
|
name = "RED",
|
|
bag = Bag.new(),
|
|
party = {
|
|
{ species = 1, level = 5, hp = 20, maxHp = 20, moves = { 33, 45 }, pp = { 35, 40 } },
|
|
},
|
|
dex = { seen = {}, owned = {} },
|
|
},
|
|
}
|
|
function Runtime.getSession() return Runtime._session end
|
|
package.loaded["src.core.game3.runtime"] = Runtime
|
|
Bag.add(Runtime._session.bag, 1, 1)
|
|
|
|
if Battle.isActive() then
|
|
-- force clean
|
|
Battle._active = false
|
|
end
|
|
local Ui = require("src.core.game3.battle.ui")
|
|
local started = Battle.start({
|
|
wild = true,
|
|
playerParty = Runtime._session.party,
|
|
foe = { species = 16, level = 2, hp = 5, maxHp = 15, moves = { 33 }, pp = { 35 } },
|
|
onDone = function(r) Runtime._lastResult = r end,
|
|
})
|
|
check(started == true, "battle started (interactive)")
|
|
Ui._headless = true
|
|
Ui._queue = {}
|
|
Ui._showing = false
|
|
Battle._phase = "actions"
|
|
Battle._actions = {}
|
|
Battle._actionI = 1
|
|
Battle._metaAct = { kind = "bag", itemId = 1, user = "player" }
|
|
Battle.update(0, nil)
|
|
check(Battle._pendingEnd == "catch" or Battle.getResult() == "catch"
|
|
or #Runtime._session.party >= 2,
|
|
"catch meta sets catch / stores mon (pending="
|
|
.. tostring(Battle._pendingEnd) .. " party=" .. tostring(#Runtime._session.party) .. ")")
|
|
for _ = 1, 20 do
|
|
if not Battle.isActive() then break end
|
|
Battle._phase = Battle._phase == "ending" and "ending" or "ending"
|
|
Ui._queue = {}
|
|
Battle.update(0, nil)
|
|
end
|
|
check(Runtime._lastResult == "catch" or #Runtime._session.party >= 2,
|
|
"onDone catch or mon stored")
|
|
|
|
print("[test] 6. Battle Bag exit restores menu mode cleanly")
|
|
local BagMenu = require("src.ui.game3.bag_menu")
|
|
Bag.add(Runtime._session.bag, 13, 5) -- Add potions so bag is not empty
|
|
Ui._session = Runtime._session
|
|
Ui._queue = {}
|
|
Ui._showing = false
|
|
Ui._linger = false
|
|
Ui._timed = nil
|
|
Ui._headless = false
|
|
Battle._active = true
|
|
Battle._phase = "command"
|
|
Battle._st = { player = State.makeBattler(Runtime._session.party[1], "player"), playerParty = Runtime._session.party }
|
|
Ui.bindState(Battle._st)
|
|
Ui.openMenu()
|
|
check(Ui._mode == "menu", "initial battle UI mode is menu")
|
|
local fakeInputA = { wasPressed = function(self, k) local key = (k ~= nil) and k or self; return key == "a" end }
|
|
local fakeInputB = { wasPressed = function(self, k) local key = (k ~= nil) and k or self; return key == "b" end }
|
|
local fakeInputNone = { wasPressed = function() return false end }
|
|
|
|
-- Select BAG
|
|
Ui._menuIndex = 2
|
|
Ui.handleInput(fakeInputA)
|
|
check(Ui._mode == "bag", "Ui._mode transitioned to bag")
|
|
check(BagMenu.isOpen() == true, "BagMenu is open")
|
|
|
|
-- Allow opening curtain animation to finish
|
|
BagMenu.settle()
|
|
|
|
-- Simulate pressing B in BagMenu
|
|
BagMenu.handleInput(fakeInputB)
|
|
-- Allow closing transition to finish
|
|
BagMenu.settle()
|
|
check(BagMenu.isOpen() == false, "BagMenu closed after B press")
|
|
check(Ui._mode == "menu", "Ui._mode restored to menu after bag exit")
|
|
|
|
-- Verify battle update accepts subsequent command input without freeze
|
|
Battle.update(0, { input = fakeInputNone })
|
|
check(Ui._mode == "menu", "Ui._mode remains menu in command phase")
|
|
|
|
print("[test] 7. In-battle Party Item Selection validation")
|
|
Bag.add(Runtime._session.bag, 13, 1) -- Potion
|
|
local monFull = { species = 1, hp = 20, maxHp = 20 }
|
|
local monHurt = { species = 1, hp = 5, maxHp = 20 }
|
|
local monFaint = { species = 1, hp = 0, maxHp = 20 }
|
|
local canHurt, _ = BattleItems.canUseOn(nil, 13, 1, monHurt)
|
|
local canFull, _ = BattleItems.canUseOn(nil, 13, 1, monFull)
|
|
local canFaint, _ = BattleItems.canUseOn(nil, 13, 1, monFaint)
|
|
check(canHurt == true, "Potion can be used on hurt mon")
|
|
check(canFull == false, "Potion cannot be used on full HP mon")
|
|
check(canFaint == false, "Potion cannot be used on fainted mon")
|
|
|
|
local canReviveFaint, _ = BattleItems.canUseOn(nil, 24, 1, monFaint) -- Revive
|
|
local canReviveHurt, _ = BattleItems.canUseOn(nil, 24, 1, monHurt)
|
|
check(canReviveFaint == true, "Revive can be used on fainted mon")
|
|
check(canReviveHurt == false, "Revive cannot be used on alive mon")
|
|
|
|
Battle._active = false
|
|
|
|
if failed > 0 then
|
|
print(string.format("\n%d FAILED", failed))
|
|
os.exit(1)
|
|
end
|
|
print("\nAll battle-bag tests passed.")
|
|
os.exit(0)
|