mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
157 lines
7.1 KiB
Lua
157 lines
7.1 KiB
Lua
-- Driver: regression coverage for #152 "'Selector' on the world map is off and
|
|
-- character location is not shown".
|
|
--
|
|
-- pret/pokered engine/menus/town_map.asm DisplayTownMap draws the Kanto map
|
|
-- with a blinking box cursor CENTERED on the currently selected location plus a
|
|
-- separate blinking "you are here" marker at the player's current map location.
|
|
-- Two independent defects lived in src/ui/TownMap.lua's grid+background path
|
|
-- (the primary path when the extracted Kanto art is present):
|
|
--
|
|
-- DEFECT A (selector off): the 16x16 hollow cursor frame was drawn with its
|
|
-- top-left AT the 8x8 cell's top-left (markerXY), so the frame's center
|
|
-- landed +4,+4 off the cell -- the town square sat in the frame's top-left
|
|
-- quadrant instead of being enclosed. Fix centers the frame (-4,-4).
|
|
--
|
|
-- DEFECT B (character location not shown): the player marker was painted with
|
|
-- setColor(0.75,0.1,0.1) red. The TOWN MAP composites through the SGB
|
|
-- shade-remap shader (PaletteFX.shader), which keys ONLY on the red channel;
|
|
-- red 0.75 falls in the c1 bucket = TOWNMAP {165,214,255}, the exact
|
|
-- light-blue used for water and the town-square fill, so the marker was
|
|
-- painted but recolored invisible. Fix paints it red=0 -> c3 (dark dot).
|
|
--
|
|
-- This driver opens the grid TOWN MAP outdoors at PALLET TOWN, moves the cursor
|
|
-- off the player's town to VIRIDIAN CITY (so the you-are-here marker and the
|
|
-- selection cursor must BOTH be visible), and asserts -- at native resolution,
|
|
-- after replicating the Renderer's TOWNMAP shade-remap pass -- that the player
|
|
-- marker is a visible dark dot (DEFECT B) and the cursor frame is centered on
|
|
-- the selected cell (DEFECT A). Fails on the current build, passes once fixed.
|
|
--
|
|
-- Run:
|
|
-- SHOT_DIR=/tmp/bug152 POKEPORT_IDENTITY=bug152 POKEPORT_TOUCH=0 \
|
|
-- POKEPORT_DRIVER=tests/drivers/townmap_selector_bug152_test.lua love .
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Screens = require("src.ui.Screens")
|
|
local PaletteFX = require("src.render.PaletteFX")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
-- The defect lives in the SGB ('gbc') mode shade-remap; pin it deterministic.
|
|
game.save.options = game.save.options or {}
|
|
game.save.options.colors = "gbc"
|
|
PaletteFX.setMode("gbc")
|
|
|
|
game.save.player = game.save.player or {}
|
|
game.save.player.name = "bryan"
|
|
|
|
-- Outdoor map so the player's map resolves to a town-map location (byMap).
|
|
U.teleport(game, "PALLET_TOWN", 10, 8, "down")
|
|
U.wait(5)
|
|
|
|
Screens.push(game, "TownMap")
|
|
U.wait(6)
|
|
local top = game.stack:top()
|
|
|
|
-- Functional preconditions: the grid path with extracted art, and the
|
|
-- character's location known (playerLoc non-nil) -- otherwise the two draw
|
|
-- defects would not even be on the code path we mean to test.
|
|
assert(top and top.mode == "grid",
|
|
"town map must be in grid mode (extracted art), got " .. tostring(top and top.mode))
|
|
assert(top.bg ~= nil and top.bg.cursor ~= nil,
|
|
"extracted Kanto background + cursor asset must be present for this test")
|
|
assert(top.playerLoc ~= nil and top.playerLoc.name == "PALLET TOWN",
|
|
"character location must resolve to PALLET TOWN, got "
|
|
.. tostring(top.playerLoc and top.playerLoc.name))
|
|
|
|
-- Human-viewable before/after frame: cursor still on the player's own town.
|
|
top.blink = 0
|
|
U.shot(game, DIR .. "/townmap_bug152_pallet.png")
|
|
U.wait(4)
|
|
|
|
-- Move the cursor OFF the player's town up to VIRIDIAN CITY, so the
|
|
-- you-are-here marker (PALLET) and the selection cursor (VIRIDIAN) occupy
|
|
-- different cells and BOTH must render (matches the reporter's should2).
|
|
local guard = 0
|
|
while top.locs[top.sel].name ~= "VIRIDIAN CITY" and guard < 8 do
|
|
U.tap(game, "up"); U.wait(3); guard = guard + 1
|
|
end
|
|
assert(top.locs[top.sel].name == "VIRIDIAN CITY",
|
|
"up must snap the cursor to VIRIDIAN CITY, landed on "
|
|
.. tostring(top.locs[top.sel].name))
|
|
assert(top.locs[top.sel] ~= top.playerLoc,
|
|
"cursor must be on a DIFFERENT cell than the you-are-here marker")
|
|
|
|
top.blink = 0
|
|
U.shot(game, DIR .. "/townmap_bug152_viridian.png")
|
|
U.wait(4)
|
|
|
|
-- ---- deterministic native-resolution pixel gate ----
|
|
-- TownMap:draw() emits raw DMG shades; the Renderer composites the whole
|
|
-- screen through PaletteFX.shader() with the TOWNMAP SGB palette (keyed on
|
|
-- the RED channel only). Replicate that here at native 160x144 so the pixel
|
|
-- checks are scale-independent -- the same offscreen-colorize technique as
|
|
-- battle_hpbar_gbc_bug229_test.lua.
|
|
if not (love and love.graphics and love.graphics.newCanvas and PaletteFX.shader()) then
|
|
error("#152 driver: no shader/canvas support available to verify colorized output")
|
|
end
|
|
|
|
top.blink = 0 -- marker shows while blink<20, cursor while blink%16<10
|
|
local raw = love.graphics.newCanvas(160, 144)
|
|
love.graphics.setCanvas(raw)
|
|
love.graphics.clear(0, 0, 0, 1)
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
top:draw()
|
|
love.graphics.setCanvas()
|
|
|
|
local shader = PaletteFX.shader()
|
|
local colors = PaletteFX.pal(game.data, "TOWNMAP")
|
|
assert(colors, "TOWNMAP palette must resolve")
|
|
local shaded = love.graphics.newCanvas(160, 144)
|
|
love.graphics.setCanvas(shaded)
|
|
love.graphics.clear(0, 0, 0, 1)
|
|
love.graphics.setShader(shader)
|
|
PaletteFX.sendColors(shader, colors)
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.draw(raw)
|
|
love.graphics.setShader()
|
|
love.graphics.setCanvas()
|
|
|
|
local id = shaded:newImageData()
|
|
do -- save the colorized native frame for human viewing
|
|
local d = id:encode("png")
|
|
local f = io.open(DIR .. "/townmap_bug152_viridian_native.png", "wb")
|
|
if f then f:write(d:getString()); f:close() end
|
|
end
|
|
|
|
local function sumAt(x, y)
|
|
local r, g, b = id:getPixel(x, y)
|
|
return r + g + b, r, g, b
|
|
end
|
|
|
|
-- markerXY(loc) = (loc.x*8+16, loc.y*8+8) = the 8x8 cell top-left.
|
|
-- PALLET (x2,y11) -> (32,96); the you-are-here dot fills +2,+2 4x4, center ~ (35,99).
|
|
local ms, mr, mg, mb = sumAt(35, 99)
|
|
-- VIRIDIAN (x2,y8) -> (32,72). Post-fix the centered 16x16 frame's top border
|
|
-- sits ~4px ABOVE the cell top (row ~68) and its left border ~4px LEFT (col ~28).
|
|
local ts = select(1, sumAt(32, 68))
|
|
local ls = select(1, sumAt(28, 78))
|
|
U.log(string.format("marker(35,99) rgb=%.2f/%.2f/%.2f sum=%.2f", mr, mg, mb, ms))
|
|
U.log(string.format("cursor top(32,68) sum=%.2f left(28,78) sum=%.2f", ts, ls))
|
|
|
|
-- DEFECT B: the "you are here" marker must be a VISIBLE dark dot, not the
|
|
-- map-fill light-blue (sum 2.49) the red-channel shade-remap folded it into.
|
|
assert(ms < 0.6, string.format(
|
|
"#152 DEFECT B: player-location marker invisible -- PALLET cell reads sum=%.2f "
|
|
.. "(map-fill blue); expected a dark you-are-here dot (sum<0.6)", ms))
|
|
-- DEFECT A: the 16x16 cursor frame must be CENTERED on the selected cell, so a
|
|
-- dark border pixel exists ~4px above and ~4px left of the VIRIDIAN cell top-left.
|
|
assert(ts < 0.6, string.format(
|
|
"#152 DEFECT A: cursor frame not centered -- no dark top border above VIRIDIAN "
|
|
.. "cell (sum=%.2f, expected <0.6)", ts))
|
|
assert(ls < 0.6, string.format(
|
|
"#152 DEFECT A: cursor frame not centered -- no dark left border of VIRIDIAN "
|
|
.. "cell (sum=%.2f, expected <0.6)", ls))
|
|
|
|
U.log("RESULT bug152 PASS")
|
|
U.wait(2)
|
|
end
|