Files
gen1recomp/tests/drivers/route4_downsweep_bug223.lua
T
2026-07-26 13:36:57 -04:00

104 lines
4.2 KiB
Lua

-- #223 exhaustive DOWN-hop sweep for ROUTE_4 (evidence driver).
--
-- The reporter's build (v0.1.25) and HEAD share byte-identical ledge code
-- (checkLedgeHop) and ledge data (tools/rom_manifest.json ->
-- data/generated/field.lua, the 8 rows of data/tilesets/ledge_tiles.asm), so
-- this reproduces exactly what the reporter would see.
--
-- For EVERY ROUTE_4 cell whose tile-at-feet is a south-ledge STANDING tile
-- (44/57, i.e. pokered $2C/$39) with a south-ledge tile (54/55, $36/$37)
-- directly below, teleport the player onto it facing DOWN, hold DOWN, and
-- assert the Gen1 hop fires (p.hopFrames>0) and lands two cells south.
--
-- Finding: all 139 reachable/functional south ledges hop. The only two that
-- do not -- (12,16) and (13,16) -- sit on the SOUTH boundary of the Mt Moon
-- Poke Center plaza, where the cell two south is off the map onto the border
-- mountain (tile 17); there is no landing, so the hop is correctly refused
-- (checkLedgeHop's landing-walkable gate). These are NOT the reporter's spot
-- (an open EAST plateau, cells ~62-80) and refusing a hop into the map border
-- is correct, so they are treated as EXPECTED refusals here.
--
-- Run:
-- POKEPORT_DRIVER=tests/drivers/route4_downsweep_bug223.lua \
-- POKEPORT_IDENTITY=bug223 POKEPORT_TOUCH=0 love .
return function(game)
local U = dofile("tests/drivers/util.lua")
game.save.flags = game.save.flags or {}
game.save.flags.EVENT_GOT_STARTER = true
local Pokemon = require("src.pokemon.Pokemon")
if #game.save.party == 0 then
table.insert(game.save.party, Pokemon.new(game.data, "CHARMANDER", 5))
end
game.save.options = game.save.options or {}
game.save.options.zoom = -2
-- same tile read as Map:cellTile: bottom-left 8x8 of the 2x2-cell block
local def = game.data.maps.ROUTE_4
local ts = game.data.tilesets[def.tileset]
local function cellTile(cx, cy)
local tx, ty = cx * 2, cy * 2 + 1
local bx, by = math.floor(tx / 4), math.floor(ty / 4)
local id
if bx < 0 or by < 0 or bx >= def.width or by >= def.height then id = def.borderBlock
else id = def.blocks[by * def.width + bx + 1] end
local block = ts.blocks[(id or 0) + 1]
return block and block[(ty % 4) * 4 + (tx % 4) + 1] or nil
end
local W, H = def.width * 2, def.height * 2
local function holdDown(x, y, frames)
U.teleport(game, "ROUTE_4", x, y, "down")
require("src.render.Zoom").applyOptions(game.save.options)
U.wait(6)
local p = game.overworld.player
local hop = false
for _ = 1, frames do
table.insert(game.input.pressQueue, "down")
game.input.state.down = true
coroutine.yield()
if (p.hopFrames or 0) > 0 then hop = true end
end
game.input.state.down = false
U.wait(4)
return p.cellX, p.cellY, hop
end
-- (12,16)/(13,16): south ledges on the plaza's map-border edge; the cell two
-- south is off-map (border mountain), so the refusal is correct, not a bug.
local expectedRefusal = { ["12,16"] = true, ["13,16"] = true }
local standers = {}
for cy = 0, H - 2 do
for cx = 0, W - 1 do
local s = cellTile(cx, cy)
local f = cellTile(cx, cy + 1)
if (s == 44 or s == 57) and (f == 54 or f == 55) then
standers[#standers + 1] = { cx, cy }
end
end
end
U.log(("#223 sweep: %d south-ledge standing cells in ROUTE_4"):format(#standers))
local fails, refusals = 0, 0
for _, c in ipairs(standers) do
local cx, cy = c[1], c[2]
-- 2-cell hop is 32 frames (16/cell); budget past it so cellY settles
local ex, ey, hop = holdDown(cx, cy, 44)
local ok = hop and ex == cx and ey == cy + 2
if not ok then
if expectedRefusal[cx .. "," .. cy] then
refusals = refusals + 1
U.log((" refused (expected, map-border edge) (%d,%d) -> (%d,%d) hop=%s")
:format(cx, cy, ex, ey, tostring(hop)))
else
fails = fails + 1
U.log((" FAIL (%d,%d) -> (%d,%d) hop=%s"):format(cx, cy, ex, ey, tostring(hop)))
end
end
end
U.log(("#223 sweep DONE: %d hopped, %d expected border-refusals, %d unexpected FAILS")
:format(#standers - fails - refusals, refusals, fails))
if fails > 0 then error(fails .. " unexpected south-ledge DOWN-hop failure(s)") end
end