mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 19:24:01 +02:00
more buggies
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
-- Parity test: Lance room walk-in stays on the floor, and defeat dialogue
|
||||
-- includes the rival-became-champion after-battle text.
|
||||
--
|
||||
-- Sources: scripts/LancesRoom.asm (WalkToLance / LancesRoomLanceEndBattleScript),
|
||||
-- text/LancesRoom.asm (_LancesRoomLanceAfterBattleText).
|
||||
-- Self-contained: run via `luajit tests/parity_lance.lua`; also dofile'd
|
||||
-- by tests/run_tests.lua's aggregator.
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
if not _G.love then _G.love = require("tests.love_stub") end
|
||||
local Data = require("src.core.Data")
|
||||
if not (Data.maps and Data.maps.LANCES_ROOM) then Data:load() end
|
||||
local Font = require("src.render.Font")
|
||||
if not pcall(Font.encode, "A") then Font.load(Data) end
|
||||
local S = require("tests.harness").suite("parity lance")
|
||||
local check, eq = S.check, S.eq
|
||||
|
||||
local mapScripts = require("data.scripts.init")
|
||||
local hooks = mapScripts.get("LANCES_ROOM")
|
||||
check(hooks and hooks.walkInRoute, "LANCES_ROOM exposes walkInRoute")
|
||||
|
||||
local D = { up = { 0, -1 }, down = { 0, 1 }, left = { -1, 0 }, right = { 1, 0 } }
|
||||
|
||||
-- === (1) walk-in RLE lands on the door-lock trigger (6,11) ===
|
||||
do
|
||||
local x, y = 24, 16
|
||||
local steps = 0
|
||||
for _, seg in ipairs(hooks.walkInRoute) do
|
||||
local d = D[seg[1]]
|
||||
check(d ~= nil, "walk segment direction " .. tostring(seg[1]))
|
||||
for _ = 1, seg[2] do
|
||||
x, y = x + d[1], y + d[2]
|
||||
steps = steps + 1
|
||||
end
|
||||
end
|
||||
eq(x, 6, "walk-in ends at x=6")
|
||||
eq(y, 11, "walk-in ends at y=11 (door-lock / arena entry)")
|
||||
check(steps > 0, "walk-in has steps")
|
||||
end
|
||||
|
||||
-- === (2) every cell of the route is walkable with the entrance open ===
|
||||
do
|
||||
local Map = require("src.world.Map")
|
||||
local def = Data.maps.LANCES_ROOM
|
||||
local tileset = Data.tilesets[def.tileset]
|
||||
-- mutate a copy of the block list so we don't poison the registry
|
||||
local blocks = {}
|
||||
for i, b in ipairs(def.blocks) do blocks[i] = b end
|
||||
local copy = {}
|
||||
for k, v in pairs(def) do copy[k] = v end
|
||||
copy.blocks = blocks
|
||||
-- LanceShowOrHideEntranceBlocks with the door unlocked
|
||||
blocks[6 * def.width + 2 + 1] = 0x31
|
||||
blocks[6 * def.width + 3 + 1] = 0x32
|
||||
local map = Map.new(copy, tileset)
|
||||
local x, y = 24, 16
|
||||
check(map:isWalkableCell(x, y), "start (24,16) walkable")
|
||||
for _, seg in ipairs(hooks.walkInRoute) do
|
||||
local d = D[seg[1]]
|
||||
for _ = 1, seg[2] do
|
||||
x, y = x + d[1], y + d[2]
|
||||
check(map:isWalkableCell(x, y),
|
||||
("walk-in cell (%d,%d) is floor, not void/wall"):format(x, y))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- === (3) after-battle text names the rival as the real champion ===
|
||||
do
|
||||
local after = Data.text._LancesRoomLanceAfterBattleText
|
||||
check(after ~= nil, "_LancesRoomLanceAfterBattleText extracted")
|
||||
check(after:find("ELITE", 1, true) or after:find("{RIVAL}", 1, true),
|
||||
"after text mentions rival / Elite Four")
|
||||
check(after:find("champion", 1, true) or after:find("CHAMPION", 1, true),
|
||||
"after text has the champion reveal")
|
||||
check(after:find("before you", 1, true) or after:find("before you!", 1, true)
|
||||
or after:find("FOUR before", 1, true),
|
||||
"after text says rival beat the Elite Four first")
|
||||
local header = Data:trainerHeader("LancesRoom", 1)
|
||||
check(header and header.after == "_LancesRoomLanceAfterBattleText",
|
||||
"trainer header wires the after-battle label")
|
||||
check(header and header.won == "_LancesRoomLanceEndBattleText",
|
||||
"trainer header wires the won label")
|
||||
end
|
||||
|
||||
-- === (4) onStep win callback pushes the after text (not only won text) ===
|
||||
do
|
||||
local pushed = {}
|
||||
local game = {
|
||||
data = Data,
|
||||
save = {
|
||||
flags = {},
|
||||
defeatedTrainers = {},
|
||||
player = { name = "RED", rival = "BLUE" },
|
||||
},
|
||||
stack = {
|
||||
push = function(_, state)
|
||||
pushed[#pushed + 1] = state
|
||||
end,
|
||||
},
|
||||
}
|
||||
local lance = {
|
||||
def = { name = "LANCESROOM_LANCE", index = 1,
|
||||
trainerClass = "OPP_LANCE", trainerParty = 1, text = 1 },
|
||||
id = "LANCES_ROOM:1",
|
||||
facePlayer = function() end,
|
||||
}
|
||||
local engaged = false
|
||||
local ow = {
|
||||
npcs = { lance },
|
||||
player = { cellX = 6, cellY = 2 },
|
||||
trainerDefeated = function(_, npc)
|
||||
return game.save.defeatedTrainers[npc.id] == true
|
||||
end,
|
||||
engageTrainer = function(_, npc, onDone)
|
||||
engaged = npc == lance
|
||||
-- simulate engageTrainer's win path: flag the trainer, then onDone
|
||||
game.save.defeatedTrainers[npc.id] = true
|
||||
game.save.flags.EVENT_BEAT_LANCES_ROOM_TRAINER_0 = true
|
||||
if onDone then onDone() end
|
||||
end,
|
||||
}
|
||||
local handled = hooks.onStep(game, ow, 6, 2)
|
||||
check(handled == true, "Lance coord trigger engages")
|
||||
check(engaged, "engageTrainer called for Lance")
|
||||
check(#pushed == 1 and pushed[1].pages ~= nil, "after-battle TextBox pushed")
|
||||
-- TextBox.substitute already expanded {RIVAL}/{PLAYER}; page glyphs
|
||||
-- are opaque, so re-check the source label via the header + that a
|
||||
-- box was queued on win only.
|
||||
check(#pushed[1].pages > 0, "after-battle TextBox has pages")
|
||||
-- loss path must not show after text
|
||||
pushed = {}
|
||||
game.save.defeatedTrainers = {}
|
||||
ow.engageTrainer = function(_, npc, onDone)
|
||||
-- lose: do not mark defeated
|
||||
if onDone then onDone() end
|
||||
end
|
||||
hooks.onStep(game, ow, 6, 2)
|
||||
eq(#pushed, 0, "loss does not push after-battle text")
|
||||
end
|
||||
|
||||
print("parity_lance: ok")
|
||||
Reference in New Issue
Block a user