mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
190 lines
7.3 KiB
Lua
190 lines
7.3 KiB
Lua
-- Driver: regression coverage for #196 "Dig not working exactly as intended".
|
|
--
|
|
-- Report (v0.1.23): using DIG, the character appears SPINNING INSIDE the
|
|
-- Pokemon Center in front of the nurse, and there is no spin-before-fade on
|
|
-- departure. Expected (reporter + triage cluster E + the file's own code
|
|
-- comments): the sprite begins to spin, the screen fades, and the player
|
|
-- fades in OUTSIDE the nearest town's Pokemon Center door -- exactly like Fly.
|
|
--
|
|
-- Gen1/pokered references this exercises:
|
|
-- engine/overworld/player_animations.asm _LeaveMapAnim (SFX_TELEPORT_EXIT_1
|
|
-- + PlayerSpinWhileMovingUp) for the departure spin-up;
|
|
-- EnterMapAnim (PlayerSpinWhileMovingDown) for the arrival spin-down;
|
|
-- engine/items/item_effects.asm ItemUseEscapeRope (Dig/Teleport share it).
|
|
--
|
|
-- Two defects, two assertions:
|
|
-- FIX A: a DEPARTURE spin must appear on the origin (cave) map BEFORE the
|
|
-- warp -- ow.teleportOut set / player spinning while still in the cave.
|
|
-- FIX B: the landing map must be the town (VIRIDIAN_CITY) at the in-front-of
|
|
-- -door fly spot (23,26), NOT the interior VIRIDIAN_POKECENTER.
|
|
-- Pre-fix this driver documents the bug (lands in VIRIDIAN_POKECENTER, no
|
|
-- departure spin); post-fix it passes.
|
|
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local Screens = require("src.ui.Screens")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
local failures = {}
|
|
local function check(cond, msg)
|
|
if cond then
|
|
U.log("PASS:", msg)
|
|
else
|
|
U.log("FAIL:", msg)
|
|
table.insert(failures, msg)
|
|
end
|
|
end
|
|
|
|
-- ---- set up a heal record with a remembered Viridian town door ----
|
|
-- Simulate having healed at the Viridian Pokemon Center: lastHeal points
|
|
-- at the INTERIOR (the buggy landing), but carries the outdoor town door
|
|
-- so the fix can relocate the escape-warp outside like Fly does.
|
|
game.save.player = game.save.player or {}
|
|
game.save.player.name = game.save.player.name or "bryan"
|
|
game.save.lastOutdoor = { id = "VIRIDIAN_CITY", x = 23, y = 25 }
|
|
game.save.lastHeal = {
|
|
map = "VIRIDIAN_POKECENTER", x = 3, y = 3,
|
|
outdoor = { id = "VIRIDIAN_CITY", x = 23, y = 25 },
|
|
}
|
|
-- field.flyWarps.VIRIDIAN_CITY = {23,26} is the canonical in-front-of-door
|
|
-- fly landing (one tile south of the PC door warp at 23,25).
|
|
local fw = game.data.field.flyWarps.VIRIDIAN_CITY
|
|
U.log("viridian flyWarp:", tostring(fw and fw.x), tostring(fw and fw.y))
|
|
|
|
-- ======================= LEG 1: DIG via the party menu ==============
|
|
-- A DIG-knowing party mon. Pokemon.movesAtLevel never grants DIG, so
|
|
-- inject the move directly (DIG needs no badge and works in CAVERN maps).
|
|
local digger = Pokemon.new(game.data, "NIDOKING", 40)
|
|
digger.moves = { { id = "DIG", pp = 10 } }
|
|
game.save.party = { digger }
|
|
|
|
-- MT_MOON_1F tileset is CAVERN (in DIG_TILESETS); a walkable cave cell.
|
|
U.teleport(game, "MT_MOON_1F", 14, 34, "down")
|
|
local ow = game.overworld
|
|
U.log("start map:", tostring(ow and ow.map and ow.map.id),
|
|
"tileset:", tostring(ow and ow.map and ow.map.def and ow.map.def.tileset))
|
|
U.shot(game, DIR .. "/dig_00_cave.png")
|
|
U.wait(4)
|
|
|
|
-- open the party menu and pick DIG on slot 1
|
|
-- (submenu order for a DIG-only mon: DIG / STATS / SWITCH -- #768)
|
|
Screens.push(game, "PartyMenu")
|
|
U.wait(5)
|
|
U.tap(game, "a") -- open the per-mon submenu, cursor on DIG
|
|
U.wait(2)
|
|
U.tap(game, "a") -- choose DIG
|
|
U.wait(2)
|
|
|
|
-- ---- FIX A: watch for a DEPARTURE spin on the cave map before the warp ----
|
|
-- A departure spin counts only if it happens while we are still in the cave
|
|
-- (map.id == MT_MOON_1F). The pre-fix code only spins on arrival, inside the
|
|
-- Center, so this stays false pre-fix.
|
|
local sawDepartureSpin = false
|
|
local spinShotTaken = false
|
|
local leftCave = false
|
|
for _ = 1, 240 do
|
|
local stillCave = ow.map and ow.map.id == "MT_MOON_1F"
|
|
-- departure-only markers: ow.teleportOut is the new pre-warp spin state,
|
|
-- and player.spinRise is the rising spin (the arrival uses spinDrop), so
|
|
-- neither can be confused with the interior arrival spin-down
|
|
if stillCave and (ow.teleportOut ~= nil or ow.player.spinRise) then
|
|
sawDepartureSpin = true
|
|
if not spinShotTaken then
|
|
U.shot(game, DIR .. "/dig_01_spin.png")
|
|
spinShotTaken = true
|
|
end
|
|
end
|
|
if ow.map and ow.map.id ~= "MT_MOON_1F" then
|
|
leftCave = true
|
|
break
|
|
end
|
|
U.wait(1)
|
|
end
|
|
U.log("sawDepartureSpin:", tostring(sawDepartureSpin),
|
|
"leftCave:", tostring(leftCave))
|
|
|
|
-- ---- settle the arrival, then FIX B: where did we land? ----
|
|
local landedMap
|
|
for _ = 1, 240 do
|
|
landedMap = ow.map and ow.map.id
|
|
-- wait until the transition settles onto a stable map that isn't the cave
|
|
if landedMap and landedMap ~= "MT_MOON_1F" and not ow.transitioning then
|
|
break
|
|
end
|
|
U.wait(1)
|
|
end
|
|
U.wait(8)
|
|
U.shot(game, DIR .. "/dig_02_land.png")
|
|
U.wait(4)
|
|
landedMap = ow.map and ow.map.id
|
|
U.log("DIG landed map:", tostring(landedMap),
|
|
"cell:", tostring(ow.player.cellX), tostring(ow.player.cellY))
|
|
|
|
check(sawDepartureSpin,
|
|
"DIG: departure spin appears in the cave before the fade (FIX A)")
|
|
check(landedMap == "VIRIDIAN_CITY",
|
|
"DIG: lands OUTSIDE at VIRIDIAN_CITY, not the interior (FIX B) -- got "
|
|
.. tostring(landedMap))
|
|
check(ow.player.cellX == 23 and ow.player.cellY == 26,
|
|
"DIG: lands at the in-front-of-door fly spot 23,26 -- got "
|
|
.. tostring(ow.player.cellX) .. "," .. tostring(ow.player.cellY))
|
|
|
|
-- ======================= LEG 2: ESCAPE ROPE via the bag =============
|
|
-- Same shared departure path, but driven through BagMenu's escape_rope
|
|
-- branch so src/ui/BagMenu.lua is exercised too.
|
|
game.save.party = { Pokemon.new(game.data, "PIDGEY", 8) }
|
|
game.save.bagOrder = nil
|
|
game.save.inventory = { ESCAPE_ROPE = 1 }
|
|
game.save.money = game.save.money or 3000
|
|
|
|
U.teleport(game, "MT_MOON_1F", 14, 34, "down")
|
|
ow = game.overworld
|
|
U.shot(game, DIR .. "/dig_03_rope_cave.png")
|
|
U.wait(4)
|
|
|
|
Screens.push(game, "BagMenu")
|
|
U.wait(5)
|
|
U.tap(game, "a") -- choose ESCAPE ROPE (only item) -> USE / TOSS menu
|
|
U.wait(3)
|
|
U.tap(game, "a") -- USE (first option) -> escape_rope branch
|
|
U.wait(2)
|
|
|
|
local ropeSpin = false
|
|
for _ = 1, 240 do
|
|
local stillCave = ow.map and ow.map.id == "MT_MOON_1F"
|
|
if stillCave and (ow.teleportOut ~= nil or ow.player.spinRise) then
|
|
ropeSpin = true
|
|
end
|
|
if ow.map and ow.map.id ~= "MT_MOON_1F" then break end
|
|
U.wait(1)
|
|
end
|
|
local ropeLanded
|
|
for _ = 1, 240 do
|
|
ropeLanded = ow.map and ow.map.id
|
|
if ropeLanded and ropeLanded ~= "MT_MOON_1F" and not ow.transitioning then
|
|
break
|
|
end
|
|
U.wait(1)
|
|
end
|
|
U.wait(8)
|
|
U.shot(game, DIR .. "/dig_04_rope_land.png")
|
|
U.wait(4)
|
|
ropeLanded = ow.map and ow.map.id
|
|
U.log("ESCAPE ROPE landed map:", tostring(ropeLanded),
|
|
"cell:", tostring(ow.player.cellX), tostring(ow.player.cellY))
|
|
|
|
check(ropeSpin,
|
|
"ESCAPE ROPE: departure spin appears in the cave before the fade (FIX A)")
|
|
check(ropeLanded == "VIRIDIAN_CITY",
|
|
"ESCAPE ROPE: lands OUTSIDE at VIRIDIAN_CITY (FIX B) -- got "
|
|
.. tostring(ropeLanded))
|
|
|
|
if #failures == 0 then
|
|
U.log("RESULT bug196 PASS")
|
|
else
|
|
U.log("RESULT bug196 FAIL (" .. #failures .. "):")
|
|
for _, m in ipairs(failures) do U.log(" -", m) end
|
|
end
|
|
end
|