mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
87 lines
3.8 KiB
Lua
87 lines
3.8 KiB
Lua
-- Badges are one store, not two.
|
|
--
|
|
-- luajit tests/gen2_badges_test.lua
|
|
--
|
|
-- On the cart ENGINE_ZEPHYRBADGE is bit 0 of wJohtoBadges
|
|
-- (constants/engine_flags.asm), so `setflag ENGINE_ZEPHYRBADGE` and "the player
|
|
-- owns the Zephyr Badge" are the same write. The port had two stores: gym
|
|
-- scripts wrote save.engineFlags, while FieldMoves.hasBadge, VAR_BADGES, the
|
|
-- trainer card and the save summary all read save.player.badges -- which
|
|
-- nothing ever assigned.
|
|
--
|
|
-- The visible bug, found by the Gold route bot after it beat Falkner and Bugsy:
|
|
-- CUT refused with "Sorry! A new BADGE is required" while holding the badge
|
|
-- that grants it, so Ilex Forest could never be left and no HM was usable for
|
|
-- the rest of the game.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local S = require("tests.harness").suite("gen2 badges")
|
|
local check, eq = S.check, S.eq
|
|
|
|
local FieldMoves = require("src.world.gen2.FieldMoves")
|
|
local World = require("src.world.gen2.World")
|
|
|
|
-- The bit order is wJohtoBadges', not the order a player earns them: Jasmine's
|
|
-- MINERALBADGE sits at bit 4 and Chuck's STORMBADGE at bit 5, even though Chuck
|
|
-- is fought first. Getting this backwards maps SURF's and FLY's gates onto
|
|
-- each other's bits.
|
|
eq(FieldMoves.JOHTO_BADGES[5], "MINERAL", "bit 4 is MINERAL")
|
|
eq(FieldMoves.JOHTO_BADGES[6], "STORM", "bit 5 is STORM")
|
|
|
|
-- The ids come from constants/engine_flags.asm's const_def run.
|
|
eq(FieldMoves.BADGE_FLAG[26].name, "ZEPHYR", "ENGINE_ZEPHYRBADGE is 26")
|
|
eq(FieldMoves.BADGE_FLAG[27].name, "HIVE", "ENGINE_HIVEBADGE is 27")
|
|
eq(FieldMoves.BADGE_FLAG[30].name, "MINERAL", "ENGINE_MINERALBADGE is 30")
|
|
eq(FieldMoves.BADGE_FLAG[31].name, "STORM", "ENGINE_STORMBADGE is 31")
|
|
eq(FieldMoves.BADGE_FLAG[26].store, "badges", "Johto badges go to player.badges")
|
|
eq(FieldMoves.BADGE_FLAG[34].store, "kantoBadges",
|
|
"ENGINE_BOULDERBADGE goes to player.kantoBadges")
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- The round trip: what a gym script writes is what a field move reads.
|
|
-- ---------------------------------------------------------------------------
|
|
|
|
local save = { player = { badges = {}, kantoBadges = {} }, engineFlags = {} }
|
|
local world = setmetatable({ game = { save = save } }, { __index = World })
|
|
|
|
eq(world:engineFlag(27), false, "no HIVEBADGE to begin with")
|
|
eq(FieldMoves.hasBadge(save, FieldMoves.BADGE.CUT), false, "so CUT is gated")
|
|
|
|
-- What BugsyScript does: `setflag ENGINE_HIVEBADGE`.
|
|
world:setEngineFlag(27, true)
|
|
|
|
eq(world:engineFlag(27), true, "the flag reads back as set")
|
|
eq(save.player.badges.HIVE, true, "and it landed in the badge store")
|
|
check(FieldMoves.hasBadge(save, FieldMoves.BADGE.CUT),
|
|
"CUT is now allowed -- the bug was that this stayed false forever")
|
|
|
|
-- VAR_BADGES counts the same store, so a script branching on badge count
|
|
-- (section 09's "if VAR_BADGES == 6, the Rockets appear in Goldenrod") sees it.
|
|
local counted = 0
|
|
for _, has in pairs(save.player.badges) do
|
|
if has then counted = counted + 1 end
|
|
end
|
|
eq(counted, 1, "the badge count sees it too")
|
|
|
|
-- Clearing works, and does not leave a stale copy in the flag table.
|
|
world:setEngineFlag(27, false)
|
|
eq(world:engineFlag(27), false, "cleared")
|
|
eq(save.player.badges.HIVE, nil, "cleared in the badge store")
|
|
eq(save.engineFlags[27], nil, "and never shadowed by a second copy")
|
|
|
|
-- Non-badge engine flags still use the ordinary table.
|
|
world:setEngineFlag(1, true) -- ENGINE_MAP_CARD
|
|
eq(world:engineFlag(1), true, "a non-badge flag still round-trips")
|
|
eq(save.engineFlags[1], true, "...through save.engineFlags")
|
|
|
|
-- Every gate FieldMoves.BADGE names must be a real Johto badge.
|
|
for move, badge in pairs(FieldMoves.BADGE) do
|
|
local found = false
|
|
for _, name in ipairs(FieldMoves.JOHTO_BADGES) do
|
|
if name == badge then found = true break end
|
|
end
|
|
check(found, ("%s is gated on a real badge (%s)"):format(move, badge))
|
|
end
|
|
|
|
S.finish()
|