Files
gen1recomp/tests/engine/vending_machine_bug1876.lua
T

215 lines
7.1 KiB
Lua

-- engine/events/vending_machine.asm (#1876)
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 = {}
package.loaded["src.render.Font"] = {
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.TextBox"] = {
new = function(_, text, onDone, opts)
return { text = text, onDone = onDone, opts = opts, isTextBox = true }
end,
}
local sounds = {}
package.loaded["src.core.Sound"] = {
play = function(_, name) sounds[#sounds + 1] = name end,
}
local bagFull = false
local bagged = {}
package.loaded["src.inventory.Bag"] = {
add = function(_, id)
if bagFull then return false end
bagged[#bagged + 1] = id
return true
end,
}
package.loaded["src.ui.Menu"] = nil
package.loaded["src.ui.Theme"] = nil
local M = assert(loadfile("data/scripts/story4.lua"))()
local machine = M.CELADON_MART_ROOF.talk.TEXT_CELADONMARTROOF_VENDING_MACHINE1
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(cash)
sounds, bagged, done = {}, {}, false
return {
data = {
text = {
_VendingMachineText1 = "A vending machine!\nHere's the menu!",
_VendingMachineText4 = "Oops, not enough\nmoney!",
_VendingMachineText5 = "{RAM:wStringBuffer}\npopped out!",
_VendingMachineText6 = "There's no more\nroom for stuff!",
_VendingMachineText7 = "Not thirsty!",
},
items = {
FRESH_WATER = { name = "FRESH WATER" },
SODA_POP = { name = "SODA POP" },
LEMONADE = { name = "LEMONADE" },
},
},
save = { money = cash, inventory = {} },
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(cash)
local game = mkGame(cash)
machine(game, nil, nil, function() done = true end)
local intro = game.stack:top()
return game, intro
end
do
local game, intro = open(3000)
check(intro.isTextBox, "talking to the sign prints VendingMachineText1")
check(tostring(intro.text):find("vending machine", 1, true) ~= nil,
"with the machine's own greeting")
check(intro.opts.money ~= nil, "DisplayTextBoxID MONEY_BOX rides along")
check(intro.opts.stay ~= nil and intro.opts.stay.prompt,
"the greeting prompts, then stays up under the list")
intro.opts.stay.onShown()
local menu = game.stack:top()
check(menu ~= intro and menu.items ~= nil, "the drink list opens over it")
eq(menu.tx, 0, "TextBoxBorder at hlcoord 0,3")
eq(menu.ty, 3, "row 3")
eq(menu.tw, 14, "14 tiles wide (b=8, c=12)")
eq(menu.th, 10, "10 tiles tall")
eq(#menu.items, 4, "wMaxMenuItem 3: three drinks and CANCEL")
eq(menu.items[4].label, "CANCEL", "CANCEL is the last row")
eq(menu.noWrap, true,
"wMenuWrappingEnabled is never set (home/window.asm:56-83)")
calls = {}
menu:draw()
for i, name in ipairs({ "FRESH WATER", "SODA POP", "LEMONADE", "CANCEL" }) do
local y = (5 + (i - 1) * 2) * 8
check(found("draw", function(c)
return c[2] == name and c[3] == 16 and c[4] == y
end) ~= nil, name .. " sits at (16, " .. y .. ")")
end
for i, price in ipairs({ "¥200", "¥300", "¥350" }) do
local y = (6 + (i - 1) * 2) * 8
check(found("draw", function(c)
return c[2] == price and c[3] == 72 and c[4] == y
end) ~= nil, price .. " sits a row under its drink at (72, " .. y .. ")")
end
end
do
local game, intro = open(3000)
intro.opts.stay.onShown()
local menu = game.stack:top()
menu.items[1].onSelect()
local waiter = game.stack:top()
check(waiter ~= menu and waiter.update ~= nil,
"the delivery rumble runs before the text")
eq(game.save.money, 3000, "money is still untouched during the rumble")
for _ = 1, 120 do
if game.stack:top() ~= waiter then break end
waiter:update(1 / 60)
end
eq(#sounds, 60, "SFX_PUSH_BOULDER restarts 60 times")
eq(sounds[1], "Push_Boulder", "and it is the boulder push, not Cut")
check(bagged[1] == "FRESH_WATER", "the drink lands in the bag")
eq(game.save.money, 2800, "SubBCDPredef takes the drink's price")
local result = game.stack:top()
check(result.isTextBox and tostring(result.text):find("popped out") ~= nil,
"then VendingMachineText5 names the drink")
check(tostring(result.text):find("FRESH WATER", 1, true) ~= nil,
"out of wStringBuffer")
check(result.opts ~= nil and result.opts.money ~= nil,
"the money box is redrawn with the new balance")
eq(#game.stack.states, 1,
"the drink list and the greeting are gone by then")
result.onDone()
check(done, "dismissing it hands control back to the script")
end
do
local game, intro = open(3000)
intro.opts.stay.onShown()
local menu = game.stack:top()
menu.index = 4
pressed = "a"
menu:update(1 / 60)
pressed = nil
local result = game.stack:top()
check(result.isTextBox and tostring(result.text):find("thirsty") ~= nil,
"CANCEL prints VendingMachineText7")
eq(#game.stack.states, 1, "with the list and the greeting closed")
eq(#bagged, 0, "and nothing bought")
game, intro = open(3000)
intro.opts.stay.onShown()
menu = game.stack:top()
pressed = "b"
menu:update(1 / 60)
pressed = nil
check(tostring(game.stack:top().text):find("thirsty") ~= nil,
"B does the same (.notThirsty)")
end
do
local game, intro = open(100)
intro.opts.stay.onShown()
game.stack:top().items[1].onSelect()
local result = game.stack:top()
check(tostring(result.text):find("enough", 1, true) ~= nil,
"no money prints VendingMachineText4")
eq(game.save.money, 100, "and spends nothing")
eq(#bagged, 0, "and hands over no drink")
bagFull = true
game, intro = open(3000)
intro.opts.stay.onShown()
game.stack:top().items[1].onSelect()
result = game.stack:top()
check(tostring(result.text):find("room for stuff", 1, true) ~= nil,
"a full bag prints VendingMachineText6")
eq(game.save.money, 3000, "with the money untouched (.BagFull)")
bagFull = false
end
package.loaded["src.render.Font"] = realFont
package.loaded["src.render.TextBox"] = realTextBox
package.loaded["src.core.Sound"] = nil
package.loaded["src.inventory.Bag"] = nil
package.loaded["src.ui.Menu"] = nil
package.loaded["src.ui.Theme"] = nil
require("src.ui.Screens").invalidate()
T.finish()