Files
gen1recomp/tests/engine/prize_window_bug1867.lua
T

245 lines
8.7 KiB
Lua

-- engine/events/prize_menu.asm (#1867)
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")
local realFont = package.loaded["src.render.Font"]
local realTextBox = package.loaded["src.render.TextBox"]
local calls = {}
local FontStub
FontStub = {
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
draw = function(text, x, y) calls[#calls + 1] = { "draw", text, x, y } end,
drawCode = function(code, x, y) calls[#calls + 1] = { "code", code, x, y } end,
drawBox = function(tx, ty, tw, th) calls[#calls + 1] = { "box", tx, ty, tw, th } end,
width = function(text) return #tostring(text) * 8 end,
split = function(text)
local out = {}
for i = 1, #tostring(text) do out[i] = i end
return out
end,
}
package.loaded["src.render.Font"] = FontStub
package.loaded["src.render.TextBox"] = {
new = function(_, text, onDone, opts)
return { text = text, onDone = onDone, opts = opts, isTextBox = true }
end,
}
package.loaded["src.core.Sound"] = { play = function() end }
local version = "red"
package.loaded["src.core.GameVersion"] = {
isBlue = function() return version == "blue" end,
isYellow = function() return version == "yellow" end,
}
package.loaded["src.ui.PrizeCounter"] = nil
package.loaded["src.ui.Theme"] = nil
local PrizeCounter = require("src.ui.PrizeCounter")
local M = assert(loadfile("data/scripts/story3.lua"))()
local counters = M.GAME_CORNER_PRIZE_ROOM.talk
local function found(kind, pred)
for _, c in ipairs(calls) do
if c[1] == kind and pred(c) then return c end
end
return nil
end
local pressed, done
local function mkGame(coins)
done = false
local mons = {}
for _, n in ipairs({ "ABRA", "CLEFAIRY", "NIDORINA", "VULPIX",
"WIGGLYTUFF" }) do
mons[n] = { name = n }
end
return {
data = {
text = {},
pokemon = mons,
items = {
TM_DRAGON_RAGE = { name = "TM23" },
TM_HYPER_BEAM = { name = "TM15" },
TM_SUBSTITUTE = { name = "TM35" },
},
},
save = { coins = coins, inventory = { COIN_CASE = 1 } },
input = {
wasPressed = function(_, b) return pressed == b end,
isDown = function() return false end,
},
stack = {
states = {},
push = function(self, s) self.states[#self.states + 1] = s end,
pop = function(self) return table.remove(self.states) end,
top = function(self) return self.states[#self.states] end,
},
}
end
local function open(n, coins)
local game = mkGame(coins or 5000)
local ow = {}
counters["TEXT_GAMECORNERPRIZEROOM_PRIZE_VENDOR_" .. n](
game, ow, nil, function() done = true end)
local exchange = game.stack:pop()
exchange.onDone()
local which = game.stack:top()
which.opts.stay.onShown()
return game, which, game.stack:top(), ow
end
do
local game, which, window = open(1)
check(tostring(which.text):find("Which prize", 1, true) ~= nil,
"WhichPrizeText goes up before the window")
check(which.opts.stay ~= nil and which.opts.stay.prompt == nil,
"it ends in `done`: no prompt, and PrintText leaves it up")
check(getmetatable(window) == PrizeCounter,
"the prize window is the CeladonPrizeMenu overlay")
check(window.isOpaque ~= true,
"so the prize room keeps drawing around it")
local names = {}
for i, row in ipairs(window.prizes) do names[i] = row.name end
eq(#window.prizes, 3, "one window is three prizes (#623)")
eq(table.concat(names, ","), "ABRA,CLEFAIRY,NIDORINA",
"Red's first window, by GetMonName")
for _, row in ipairs(window.prizes) do
check(tostring(row.name):find("L%d") == nil,
row.name .. " carries no level: GetPrizeMonLevel is not menu chrome")
end
eq(window.prizes[1].cost, 180, "with prizes.asm's coin prices")
eq(window.prizes[3].cost, 1200, "including the third row's")
calls = {}
window:draw()
check(found("box", function(c)
return c[2] == 11 and c[3] == 0 and c[4] == 9 and c[5] == 3
end) ~= nil, "PrintPrizePrice's coin box is 9x3 at hlcoord 11,0")
check(found("draw", function(c)
return c[2] == "COIN" and c[3] == 96 and c[4] == 0
end) ~= nil, "with COIN on its top border at hlcoord 12,0")
local coins = found("draw", function(c) return c[2] == "5000" end)
if check(coins ~= nil, "and the balance on the row below") then
eq(coins[3] + FontStub.width("5000"), 136,
"right-aligned through the BCD field (hlcoord 13,1)")
eq(coins[4], 8, "on the box's middle row")
end
check(found("box", function(c)
return c[2] == 0 and c[3] == 2 and c[4] == 18 and c[5] == 10
end) ~= nil, "the prize box is 18x10 at hlcoord 0,2, clear of columns 18-19")
for i, name in ipairs({ "ABRA", "CLEFAIRY", "NIDORINA" }) do
local y = 32 + (i - 1) * 16
check(found("draw", function(c)
return c[2] == name and c[3] == 16 and c[4] == y
end) ~= nil, name .. " sits at (16, " .. y .. ")")
local cost = found("draw", function(c)
return c[2] == tostring(window.prizes[i].cost)
end)
if check(cost ~= nil, "its price is drawn") then
eq(cost[4], y + 8, "one tile row below the name (hlcoord 13, 5/7/9)")
eq(cost[3] + FontStub.width(cost[2]), 136, "right-aligned with the coins")
end
end
check(found("draw", function(c)
return c[2] == "NO THANKS" and c[3] == 16 and c[4] == 80
end) ~= nil, "NoThanksText is the fourth row at hlcoord 2,10")
check(found("draw", function(c) return c[2] == "PRIZES (COINS)" end) == nil,
"and there is no full-screen page title")
pressed = "up"
window:update(1 / 60)
eq(window.index, 1, "Up on the first prize does nothing")
pressed = "down"
for _ = 1, 6 do window:update(1 / 60) end
eq(window.index, 4, "Down stops on NO THANKS, the fourth row")
pressed = "a"
window:update(1 / 60)
pressed = nil
check(done, "A on NO THANKS ends the conversation (cp 3 -> .noChoice)")
eq(#game.stack.states, 0,
"with the window and WhichPrizeText both taken down")
end
do
local game, _, window = open(3)
calls = {}
window:draw()
eq(window.prizes[1].name, "TM23", "vendor 3 is GetItemName, not GetMonName")
eq(window.prizes[3].cost, 7700, "PrizeMenuTMsEntries prices")
check(found("draw", function(c)
return c[2] == "3300" and c[4] == 40
end) ~= nil, "TM prices sit on the row below their name too")
end
do
version = "yellow"
local game, _, window = open(1)
local names = {}
for i, row in ipairs(window.prizes) do names[i] = row.name end
eq(table.concat(names, ","), "ABRA,VULPIX,WIGGLYTUFF",
"pokeyellow/data/events/prizes.asm restocks window 1")
eq(window.prizes[3].cost, 2680, "with Yellow's prices")
version = "red"
end
do
local game, _, window, ow = open(1, 5000)
window.index = 1
pressed = "a"
window:update(1 / 60)
pressed = nil
local ask = game.stack:top()
check(ask.isTextBox and tostring(ask.text):find("ABRA", 1, true) ~= nil,
"SoYouWantPrizeText names the prize out of wNameBuffer")
check(tostring(ask.text):find("wNameBuffer", 1, true) == nil,
"with the token filled in")
check(ask.opts.choice ~= nil, "and a YES/NO over it")
-- engine/events/prize_menu.asm:24-28,42
check(ow.prizeWindow ~= nil, "the overworld takes the window's pixels over")
eq(ow.prizeWindow.prizes, window.prizes, "with the same three prizes")
eq(ow.prizeWindow.index, 1, "and the cursor parked on the picked row")
eq(#game.stack.states, 1, "the menu state itself is off the stack")
eq(game.save.coins, 5000, "no coins move before the answer")
ask.opts.choice(false)
local oh = game.stack:top()
check(oh.isTextBox and tostring(oh.text):find("fine then", 1, true) ~= nil,
"answering NO prints OhFineThenText")
check(ow.prizeWindow ~= nil, "with the window still drawn underneath it")
check(not done, "and the conversation not over yet")
oh.onDone()
eq(ow.prizeWindow, nil, "only that box closing gives the rows back")
check(done, "and ends the conversation")
end
do
local _, _, window = open(1, 5000)
calls = {}
window:draw()
local withCursor = #calls
local cursors = 0
for _, c in ipairs(calls) do if c[1] == "code" then cursors = cursors + 1 end end
eq(cursors, 1, "the live menu draws the cursor")
calls = {}
PrizeCounter.drawWindow(window.game, window.prizes, nil)
eq(#calls, withCursor - 1, "the persistent window draws the same boxes and rows")
for _, c in ipairs(calls) do
check(c[1] ~= "code", "minus the cursor, which the menu owns")
end
end
package.loaded["src.render.Font"] = realFont
package.loaded["src.render.TextBox"] = realTextBox
package.loaded["src.core.Sound"] = nil
package.loaded["src.core.GameVersion"] = nil
package.loaded["src.ui.PrizeCounter"] = nil
package.loaded["src.ui.Theme"] = nil
require("src.ui.Screens").invalidate()
T.finish()