mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
200 lines
6.2 KiB
Lua
200 lines
6.2 KiB
Lua
-- engine/events/pokemart.asm:212-219
|
|
-- engine/events/pokemart.asm:199-206
|
|
-- luajit tests/engine/mart_bag_full_bug2162.lua
|
|
|
|
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 function glyphs(text)
|
|
local n = 0
|
|
for _ in tostring(text):gmatch("[%z\1-\127\194-\244][\128-\191]*") do
|
|
n = n + 1
|
|
end
|
|
return n
|
|
end
|
|
|
|
local realFont = package.loaded["src.render.Font"]
|
|
package.loaded["src.render.Font"] = {
|
|
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
|
|
draw = function() end,
|
|
drawCode = function() end,
|
|
drawBox = function() end,
|
|
width = function(text) return glyphs(text) * 8 end,
|
|
split = function(text)
|
|
local out = {}
|
|
for s in tostring(text):gmatch("[%z\1-\127\194-\244][\128-\191]*") do
|
|
out[#out + 1] = s
|
|
end
|
|
return out
|
|
end,
|
|
spansFitting = function(spans, pixels)
|
|
return math.min(#spans, math.floor(pixels / 8))
|
|
end,
|
|
encode = function(text) return { text } end,
|
|
advanceOf = function() return 8 end,
|
|
}
|
|
|
|
local RELOAD = {
|
|
"src.ui.QuantityBox", "src.ui.ShopMenu", "src.ui.ListMenu",
|
|
"src.ui.ChoiceBox", "src.ui.Menu", "src.ui.Theme", "src.render.TextBox",
|
|
}
|
|
for _, m in ipairs(RELOAD) do package.loaded[m] = nil end
|
|
|
|
local Bag = require("src.inventory.Bag")
|
|
local ShopMenu = require("src.ui.ShopMenu")
|
|
local TextBox = require("src.render.TextBox")
|
|
|
|
local BAG_FULL = "You can't carry\nany more items."
|
|
local NO_MONEY = "You don't have\nenough money."
|
|
local ANYTHING = "Is there anything\nelse I can do?"
|
|
|
|
local function boxText(box)
|
|
local out = {}
|
|
for _, page in ipairs(box.pages or {}) do
|
|
for _, line in ipairs(page) do out[#out + 1] = line end
|
|
end
|
|
return table.concat(out, " ")
|
|
end
|
|
|
|
local function newGame(money, ballCount)
|
|
local events, stack = {}, {}
|
|
local game
|
|
game = {
|
|
data = {
|
|
items = { POKE_BALL = { name = "POKe BALL", price = 200 } },
|
|
text = {
|
|
_PokemartItemBagFullText = BAG_FULL,
|
|
_PokemartNotEnoughMoneyText = NO_MONEY,
|
|
_PokemartAnythingElseText = ANYTHING,
|
|
},
|
|
constants = {},
|
|
},
|
|
save = { money = money, inventory = {}, bagOrder = {} },
|
|
input = {
|
|
wasPressed = function() return false end,
|
|
isDown = function() return false end,
|
|
},
|
|
}
|
|
if ballCount then
|
|
game.save.inventory.POKE_BALL = ballCount
|
|
game.save.bagOrder = { "POKE_BALL" }
|
|
end
|
|
game.stack = {
|
|
push = function(_, s)
|
|
events[#events + 1] = { "push", s }
|
|
stack[#stack + 1] = s
|
|
end,
|
|
pop = function()
|
|
local s = table.remove(stack)
|
|
events[#events + 1] = { "pop", s }
|
|
return s
|
|
end,
|
|
top = function() return stack[#stack] end,
|
|
}
|
|
return game, events, stack
|
|
end
|
|
|
|
local function drain(game)
|
|
for _ = 1, 600 do
|
|
local top = game.stack:top()
|
|
if not (top and top.stay and not top.stayShown) then return end
|
|
top:update(1 / 60)
|
|
end
|
|
end
|
|
|
|
local function buyOne(game, stack)
|
|
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
|
|
menu.items[1].onSelect()
|
|
drain(game)
|
|
local list = stack[#stack]
|
|
list.onChoose({ value = "POKE_BALL" })
|
|
local qty = stack[#stack]
|
|
qty.onDone(1)
|
|
local confirm = stack[#stack]
|
|
game.stack:pop()
|
|
confirm.choice(true)
|
|
return menu, list, qty
|
|
end
|
|
|
|
do
|
|
local game = newGame(3000, 99)
|
|
eq(Bag.add(game.save, "POKE_BALL", 1, game.data), false,
|
|
"AddItemToInventory refuses a 100th POKe BALL")
|
|
eq(game.save.inventory.POKE_BALL, 99, "and adds nothing")
|
|
end
|
|
|
|
for _, case in ipairs({
|
|
{ name = "bag full", money = 3000, count = 99, text = BAG_FULL },
|
|
{ name = "not enough money", money = 100, count = nil, text = NO_MONEY },
|
|
}) do
|
|
local game, events, stack = newGame(case.money, case.count)
|
|
local menu, list, qty = buyOne(game, stack)
|
|
local box = stack[#stack]
|
|
if check(getmetatable(box) == TextBox, case.name .. ": a text box is pushed") then
|
|
check(boxText(box):find(case.text:gsub("\n", " "), 1, true) ~= nil,
|
|
case.name .. ": the clerk's refusal is the text")
|
|
end
|
|
eq(stack[#stack - 1], qty, case.name .. ": the quantity box is still under the box")
|
|
eq(stack[#stack - 2], list, case.name .. ": the list is under the quantity box")
|
|
local popsBefore = 0
|
|
for _, ev in ipairs(events) do
|
|
if ev[1] == "push" and ev[2] == box then break end
|
|
if ev[1] == "pop" and ev[2] == list then popsBefore = popsBefore + 1 end
|
|
end
|
|
eq(popsBefore, 0,
|
|
case.name .. ": PrintText runs before LoadScreenTilesFromBuffer1")
|
|
eq(game.save.money, case.money, case.name .. ": no money changes hands")
|
|
|
|
game.stack:pop()
|
|
box.onDone()
|
|
drain(game)
|
|
eq(stack[#stack], nil, case.name .. ": A closes the list")
|
|
eq(menu.footer, ANYTHING, case.name .. ": the mart menu asks again")
|
|
eq(game.save.money, case.money, case.name .. ": money is still untouched")
|
|
end
|
|
|
|
do
|
|
-- pokemart.asm:113
|
|
local game, events, stack = newGame(3000)
|
|
game.data.items.BICYCLE = { name = "BICYCLE", price = 0, keyItem = true }
|
|
game.data.text._PokemartUnsellableItemText = "I can't put a\nprice on that."
|
|
game.save.inventory.BICYCLE = 1
|
|
game.save.bagOrder = { "BICYCLE" }
|
|
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
|
|
menu.items[2].onSelect()
|
|
drain(game)
|
|
local list = stack[#stack]
|
|
list.onChoose({ value = "BICYCLE" })
|
|
local box = stack[#stack]
|
|
check(getmetatable(box) == TextBox, "unsellable: a text box is pushed")
|
|
eq(stack[#stack - 1], list, "unsellable: the sell list is still under it")
|
|
game.stack:pop()
|
|
box.onDone()
|
|
drain(game)
|
|
eq(stack[#stack], nil, "unsellable: A closes the sell list")
|
|
eq(menu.footer, ANYTHING, "unsellable: the mart menu asks again")
|
|
end
|
|
|
|
do
|
|
-- the bag-empty refusal has no list of its own (pokemart.asm:50)
|
|
local game, _, stack = newGame(3000)
|
|
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
|
|
game.data.text._PokemartItemBagEmptyText = "You don't have\nanything to sell."
|
|
menu.items[2].onSelect()
|
|
local box = stack[#stack]
|
|
check(getmetatable(box) == TextBox, "empty bag: only a text box is pushed")
|
|
game.stack:pop()
|
|
box.onDone()
|
|
drain(game)
|
|
eq(menu.footer, ANYTHING, "empty bag: the mart menu asks again")
|
|
end
|
|
|
|
package.loaded["src.render.Font"] = realFont
|
|
for _, m in ipairs(RELOAD) do package.loaded[m] = nil end
|
|
require("src.ui.Screens").invalidate()
|
|
|
|
T.finish()
|