mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
170 lines
5.6 KiB
Lua
170 lines
5.6 KiB
Lua
-- engine/events/pokemart.asm (#1887)
|
|
|
|
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 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,
|
|
encode = function() return {} end,
|
|
spansFitting = function(spans) return #spans end,
|
|
advanceOf = function() return 8 end,
|
|
}
|
|
package.loaded["src.render.Font"] = FontStub
|
|
for _, mod in ipairs({ "src.ui.ListMenu", "src.ui.Theme", "src.ui.Menu",
|
|
"src.ui.ShopMenu", "src.render.TextBox" }) do
|
|
package.loaded[mod] = nil
|
|
end
|
|
local ShopMenu = require("src.ui.ShopMenu")
|
|
local ListMenu = require("src.ui.ListMenu")
|
|
|
|
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
|
|
local game
|
|
game = {
|
|
data = {
|
|
text = {},
|
|
items = {
|
|
POKE_BALL = { name = "POKe BALL", price = 200 },
|
|
GREAT_BALL = { name = "GREAT BALL", price = 600 },
|
|
TOWN_MAP = { name = "TOWN MAP", price = 0, keyItem = true },
|
|
HM_CUT = { name = "HM01", price = 0 },
|
|
POTION = { name = "POTION", price = 300 },
|
|
},
|
|
},
|
|
save = { money = 3000, inventory = {}, bagOrder = {} },
|
|
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) table.remove(self.states) end,
|
|
top = function(self) return self.states[#self.states] end,
|
|
},
|
|
}
|
|
|
|
local function drain()
|
|
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 openList(which)
|
|
game.stack.states = {}
|
|
local menu = ShopMenu.new(game, { "POKE_BALL", "GREAT_BALL" }, function() end)
|
|
game.stack:push(menu)
|
|
menu.index = which
|
|
pressed = "a"
|
|
menu:update(1 / 60)
|
|
pressed = nil
|
|
drain()
|
|
return menu, game.stack:top()
|
|
end
|
|
|
|
do
|
|
local menu = ShopMenu.new(game, { "POKE_BALL" }, function() end)
|
|
eq(menu.tx, 0, "BUY/SELL/QUIT sits at column 0")
|
|
eq(menu.ty, 0, "and row 0")
|
|
eq(menu.tw, 11, "11 tiles wide, flush with the money box at column 11")
|
|
eq(menu.th, 7, "7 tiles tall (data/text_boxes.asm:34)")
|
|
|
|
calls = {}
|
|
menu:draw()
|
|
check(found("draw", function(c)
|
|
return c[2] == "BUY" and c[4] == 8
|
|
end) ~= nil, "BUY prints on interior row 1 (wTopMenuItemY 1)")
|
|
-- text_boxes.asm:35
|
|
check(found("box", function(c)
|
|
return c[2] == 11 and c[3] == 0 and c[4] == 9 and c[5] == 3
|
|
end) ~= nil, "the money box is MONEY_BOX 11,0 - 19,2")
|
|
check(found("draw", function(c)
|
|
return c[2] == "MONEY" and c[3] == 104 and c[4] == 0
|
|
end) ~= nil, "with MONEY captioned on its top border at column 13")
|
|
end
|
|
|
|
do
|
|
local menu, list = openList(1)
|
|
check(getmetatable(list) == ListMenu, "BUY opens a list menu")
|
|
eq(list.itemBox, true, "PRICEDITEMLISTMENU draws LIST_MENU_BOX")
|
|
eq(list.isOpaque, false, "so the mart floor and clerk keep drawing")
|
|
eq(list.title, nil, "no BUY header row: the ROM list has no title")
|
|
eq(list.items[#list.items].cancel, true, "the terminator's CANCEL row")
|
|
eq(list.items[2].price, "¥600", "prices ride item.price, not the name row")
|
|
|
|
calls = {}
|
|
list:draw()
|
|
check(found("box", function(c)
|
|
return c[2] == 4 and c[3] == 2 and c[4] == 16 and c[5] == 11
|
|
end) ~= nil, "LIST_MENU_BOX 4,2 - 19,12")
|
|
check(found("draw", function(c)
|
|
return c[2] == "GREAT BALL" and c[3] == 48 and c[4] == 48
|
|
end) ~= nil, "the second name sits at (48, 48)")
|
|
check(found("draw", function(c)
|
|
return c[2] == "¥600" and c[4] == 56
|
|
end) ~= nil, "its price is one tile row below the name")
|
|
local price = found("draw", function(c) return c[2] == "¥600" end)
|
|
if price then
|
|
eq(price[3] + FontStub.width("¥600"), 136,
|
|
"right-aligned through the BCD field (home/list_menu.asm:410-424)")
|
|
end
|
|
check(found("draw", function(c) return c[2] == "CANCEL" end) ~= nil,
|
|
"CANCEL is a real row (home/list_menu.asm:523-528)")
|
|
|
|
list.index = #list.items
|
|
pressed = "a"
|
|
list:update(1 / 60)
|
|
pressed = nil
|
|
drain()
|
|
eq(game.stack:top(), menu, "A on CANCEL returns to the mart menu")
|
|
end
|
|
|
|
do
|
|
game.save.inventory = { POTION = 3, TOWN_MAP = 1, HM_CUT = 1 }
|
|
local _, list = openList(2)
|
|
check(getmetatable(list) == ListMenu, "SELL opens a list menu")
|
|
eq(list.itemBox, true, "ITEMLISTMENU draws the same box")
|
|
eq(list.title, nil, "and carries no SELL header")
|
|
local byId = {}
|
|
for _, it in ipairs(list.items) do
|
|
if it.value then byId[it.value] = it end
|
|
end
|
|
eq(byId.POTION.count, 3, "ordinary stock keeps its quantity")
|
|
eq(byId.TOWN_MAP.count, nil, "IsKeyItem_ skips the quantity")
|
|
eq(byId.HM_CUT.right, nil, "and so do the HMs")
|
|
eq(list.items[#list.items].cancel, true, "CANCEL closes the sell list too")
|
|
game.save.inventory = {}
|
|
end
|
|
|
|
package.loaded["src.render.Font"] = realFont
|
|
for _, mod in ipairs({ "src.ui.ListMenu", "src.ui.Theme", "src.ui.Menu",
|
|
"src.ui.ShopMenu", "src.render.TextBox" }) do
|
|
package.loaded[mod] = nil
|
|
end
|
|
require("src.ui.Screens").invalidate()
|
|
|
|
T.finish()
|