Files
gen1recomp/tests/drivers/arena_boot_loopback.lua
T
2026-08-28 10:14:44 -04:00

150 lines
4.2 KiB
Lua

-- Driver: boots straight into an online arena battle (POKEPORT_ARENA_SPEC),
-- plays it against an in-process headless guest over Net.loopbackPair, and
-- screenshots the battle and the launcher the arena returns to.
--
-- SHOT_DIR=/tmp/shots POKEPORT_ARENA_SPEC=tests/drivers/arena_boot_spec.lua \
-- POKEPORT_DRIVER=tests/drivers/arena_boot_loopback.lua love .
return function(game)
local U = dofile("tests/drivers/util.lua")
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
os.execute('mkdir -p "' .. DIR .. '" 2>/dev/null')
local ctx = _G.POKEPORT_ARENA_TEST
if not ctx then
U.log("FAIL POKEPORT_ARENA_SPEC did not run (no loopback context)")
love.event.quit(1)
return
end
local arena = game.stack.states[1]
U.log("arena state:", tostring(arena and arena.screenId),
"stage:", tostring(arena and arena.stage))
if not (arena and arena.screenId == "ArenaState") then
U.log("FAIL the game did not boot into ArenaState")
love.event.quit(1)
return
end
if arena.stage ~= "running" then
U.log("FAIL the arena battle did not construct")
love.event.quit(1)
return
end
local shots = {
[60] = DIR .. "/arena_0_battle.png",
[400] = DIR .. "/arena_1_turns.png",
}
local function verify()
local ok = true
for _, path in pairs(shots) do
local f = io.open(path, "rb")
if f then
f:close()
U.log("captured", path)
else
ok = false
U.log("FAIL screenshot did not reach disk:", path)
end
end
U.log("arena finished: host result", tostring(ctx.result),
"guest result", tostring(ctx.guestResult))
if ctx.result ~= "win" and ctx.result ~= "lose" and ctx.result ~= "draw" then
ok = false
U.log("FAIL the arena reported no battle result")
end
return ok
end
local baseDraw = love.draw
local launcherShot, launcherFrames = false, 0
love.draw = function()
baseDraw()
if ctx.result and not launcherShot then
launcherFrames = launcherFrames + 1
if launcherFrames > 45 then
launcherShot = true
love.graphics.captureScreenshot(function(imagedata)
local encoded = imagedata:encode("png")
local path = DIR .. "/arena_2_launcher.png"
local f = io.open(path, "wb")
if f then
f:write(encoded:getString())
f:close()
U.log("captured", path)
else
U.log("FAIL screenshot did not reach disk:", path)
end
love.event.quit(verify() and 0 or 1)
end)
end
end
end
local LinkBattle = require("src.link.LinkBattle")
local SaveData = require("src.core.SaveData")
local guestInput = {
pressed = { a = true },
state = {},
pressQueue = {},
wasPressed = function(_, button) return button == "a" end,
isDown = function() return false end,
step = function() end,
}
local guestStack = { list = {} }
function guestStack:push(state, ...)
table.insert(self.list, state)
if state.enter then state:enter(...) end
end
function guestStack:pop() return table.remove(self.list) end
function guestStack:top() return self.list[#self.list] end
function guestStack:update(dt)
local top = self:top()
if top and top.update then top:update(dt) end
end
local guestGame = {
data = game.data,
input = guestInput,
stack = guestStack,
save = SaveData.newGame(),
}
local guest, why = LinkBattle.newGuest(guestGame, ctx.guestNet, {
myParty = ctx.guestParty,
theirParty = ctx.hostParty,
theirName = "RED",
seed = ctx.seed,
verdict = "full",
strict = true,
keepNetOpen = true,
})
if not guest then
U.log("FAIL headless guest could not start:", tostring(why))
love.event.quit(1)
return
end
guest.onFinish = function(result) ctx.guestResult = result end
guestStack:push(guest)
U.log("headless guest running")
for step = 1, 8000 do
table.insert(game.input.pressQueue, "a")
guestStack:update(1 / 60)
if shots[step] then game.capturePath = shots[step] end
coroutine.yield()
if ctx.result then break end
end
if not ctx.result then
U.log("FAIL the arena battle never finished")
love.event.quit(1)
return
end
while true do
coroutine.yield()
end
end