mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 08:11:35 +02:00
big bug squash
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
-- 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: STATS / SWITCH / DIG)
|
||||
Screens.push(game, "PartyMenu")
|
||||
U.wait(5)
|
||||
U.tap(game, "a") -- open the per-mon submenu
|
||||
U.wait(2)
|
||||
U.tap(game, "down") -- STATS -> SWITCH
|
||||
U.wait(2)
|
||||
U.tap(game, "down") -- SWITCH -> 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
|
||||
Reference in New Issue
Block a user