Files
gen1recomp/tests/engine/game3_emerald_profile_test.lua
T
bryanthaboi ff9cc6d172 YELLOWCARD
2026-09-28 06:45:52 -04:00

129 lines
6.4 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
local GameVersion = require("src.core.GameVersion")
local Profile = require("src.core.game3.profile")
local Capabilities = require("src.core.game3.capabilities")
local Ctx = require("src.core.game3.scripting.ctx")
local prevVersion = GameVersion.get()
Profile.reset()
GameVersion.set("firered")
local em = Profile.of("emerald")
eq(em.id, "emerald", "the Emerald row loads")
eq(em.label, "Emerald", "Emerald label")
eq(em.family, "rse", "Emerald is the rse family")
eq(em.generation, 3, "Emerald is generation 3")
eq(em.engine, "game3", "Emerald runs on the game3 engine")
check(Profile.of("emerald") == em, "the row is cached")
eq(em.map.prefixes[1], "EM_", "Emerald map prefix")
eq(em.map.enginePrefix, "EM_", "Emerald engine prefix")
eq(em.map.newGameStart.map, "EM_INSIDE_OF_TRUCK", "new game starts in the truck")
eq(em.map.newGameStart.x, 2, "truck spawn x is the layout centre")
eq(em.map.newGameStart.y, 2, "truck spawn y is the layout centre")
eq(em.map.newGameStart.facing, "down", "new game faces south")
eq(em.species.num, 412, "Emerald NUM_SPECIES")
eq(em.species.egg, 412, "Emerald SPECIES_EGG")
eq(em.badges.count, 8, "eight Hoenn badges")
eq(em.badges.flagBase, 0x867, "badge flags start at FLAG_BADGE01_GET")
local badgeNames = { "STONE", "KNUCKLE", "DYNAMO", "HEAT", "BALANCE", "FEATHER", "MIND", "RAIN" }
for i, name in ipairs(badgeNames) do
eq(em.badges.names[i], name, "badge " .. i .. " is " .. name)
end
local okAudit, problems = Capabilities.audit(em.capabilities)
check(okAudit, "the Emerald capability row audits clean"
.. (okAudit and "" or (": " .. table.concat(problems, "; "))))
for _, cap in ipairs({ "helpSystem", "tmCase", "fameChecker", "teachyTV", "vsSeeker", "trainerTower",
"seagallop", "trainerFanClub", "berryPouch", "sevii", "questLog", "mapPreview", "signpostFrame",
"trainersEyes" }) do
check(em.capabilities[cap] == nil, "Emerald leaves " .. cap .. " off")
end
for _, cap in ipairs({ "contests", "secretBase", "battleTower", "pokeNav", "matchCall", "rtc", "tv",
"berryTrees", "battleFrontier", "battlePyramid", "pyramidBag", "frontierPass", "apprentice",
"trainerHill", "lilycoveLady", "rayquazaScene", "battleTents", "easyChat", "daycare" }) do
eq(em.capabilities[cap], true, "Emerald enables " .. cap)
end
for cap in pairs(Capabilities.RSE) do
eq(em.capabilities[cap], true, "Emerald carries RSE capability " .. cap)
end
eq(Capabilities.RSE.matchCall, nil, "Match Call is Emerald-only, not RSE-wide")
eq(Capabilities.gate({ version = "emerald" }, "fame_checker"), false, "Fame Checker is gated off on Emerald")
eq(Capabilities.gate({ version = "emerald" }, "battle_frontier"), true, "Battle Frontier is open on Emerald")
eq(Capabilities.nativeAllowed({ version = "emerald" }, "natives_tower"), false,
"Trainer Tower natives are filtered out on Emerald")
eq(type(em.nativeModules), "table", "Emerald names its natives modules")
local SHARED = { natives_daycare = true, natives_elevator = true, natives_gift = true, natives_moveteach = true }
for _, m in ipairs(em.nativeModules) do
check(SHARED[m] or (Capabilities.nativeFeature(m) ~= nil and not Capabilities.nativeAllowed({ version = "firered" }, m)),
"Emerald natives module " .. m .. " is RSE-gated, not a FireRed module")
end
eq(type(em.extractors), "table", "Emerald names its extractor list")
eq(type(em.coreSpecials), "table", "Emerald allow-lists shared core specials")
for _, key in ipairs({ "module", "widths", "smallWidths" }) do
eq(type(em.font[key]), "string", "Emerald font block has " .. key)
end
local fr = Profile.of("firered")
eq(fr.family, "frlg", "FireRed is the frlg family")
eq(Profile.of("leafgreen").family, "frlg", "LeafGreen inherits the frlg family")
local FRLG_CAPS = {
"berries", "berryPouch", "braille", "daycare", "easyChat", "eggs", "fameChecker", "helpSystem",
"marts", "moveRelearner", "mysteryGift", "pokecenter", "seagallop", "sevii", "sizeRecord",
"teachyTV", "tmCase", "trainerFanClub", "trainerTower", "unionRoom", "vsSeeker",
}
local seen = {}
for cap, value in pairs(fr.capabilities) do
seen[#seen + 1] = cap
eq(value, true, "FireRed capability " .. cap .. " is on")
end
table.sort(seen)
eq(table.concat(seen, ","), table.concat(FRLG_CAPS, ","), "FireRed capability set is unchanged")
local frlgSet = {}
for cap in pairs(Capabilities.FRLG) do frlgSet[#frlgSet + 1] = cap end
table.sort(frlgSet)
eq(table.concat(frlgSet, ","), table.concat(FRLG_CAPS, ","), "Capabilities.FRLG is unchanged")
eq(Profile.forSession({ version = "emerald" }).id, "emerald", "forSession reads the session version")
eq(Profile.forSession(nil).id, "firered", "forSession falls back to the active version")
eq(Profile.family({ version = "emerald" }), "rse", "family() reads the session row")
GameVersion.set("emerald")
eq(Profile.active().id, "emerald", "active() follows an Emerald session")
eq(Profile.forSession({}).id, "emerald", "a session without a version uses the active game")
GameVersion.set("red")
eq(Profile.active().id, "firered", "non-Gen3 processes still resolve to FireRed")
eq(Profile.of("not-a-game").id, "firered", "unknown non-Gen3 ids still fall back")
GameVersion.VERSIONS.gen3_fixture = { id = "gen3_fixture", generation = 3, engine = "game3" }
T.raises(function() return Profile.of("gen3_fixture") end, "gen3_fixture",
"a Gen 3 id without a profile row raises instead of becoming FireRed")
GameVersion.set("gen3_fixture")
T.raises(function() return Profile.active() end, "gen3_fixture",
"an active Gen 3 id without a row raises")
GameVersion.set("red")
GameVersion.VERSIONS.gen3_fixture = nil
GameVersion.set("firered")
local frCtx = Ctx.new({})
eq(frCtx.specialVars[0x8012], Ctx.TEXT_COLOR_DEFAULT, "FireRed seeds VAR_TEXT_COLOR")
check(not Ctx.isSpecial(0x8015), "0x8015 is not a FireRed special var")
local emCtx = Ctx.new({ version = "emerald" })
eq(emCtx.specialVars[0x8012], nil, "Emerald does not seed VAR_MON_BOX_ID with a text colour")
emCtx.specialVars[0x8012] = 3
Ctx.wipeSpecial(emCtx)
eq(emCtx.specialVars[0x8012], nil, "Emerald wipe leaves 0x8012 clear")
GameVersion.set("emerald")
check(Ctx.isSpecial(0x8015), "VAR_TRAINER_BATTLE_OPPONENT_A is an Emerald special var")
check(not Ctx.isSpecial(0x8016), "0x8016 is past SPECIAL_VARS_END")
eq(Ctx.specialLayout().trainerBattleOpponentA, 0x8015, "Emerald layout names 0x8015")
Profile.reset()
GameVersion.set(prevVersion)
T.finish("game3_emerald_profile_test")