Files
gen1recomp/tests/drivers/em_roulette.lua
T
bryanthaboi 690f0cd9a1 TOUCHDOWN
2026-09-27 16:07:31 -04:00

136 lines
6.5 KiB
Lua

local U = require("tests.drivers.util")
local X = require("tests.drivers.em_xa_util")
local d = X.new("em_roulette", "/tmp/em_roulette")
local GC = function() return require("src.core.game3.scripting.natives_game_corner_rse") end
local function snapshotHook(screen, wants)
local orig = screen.frame
screen.frame = function(self, inp)
orig(self, inp)
for _, w in ipairs(wants) do
if not w.taken and w.when(self) then
w.taken = true
local ok, bytes = pcall(function() return self.m.ppu:snapshot():encode("png"):getString() end)
if ok then
os.execute('mkdir -p "' .. d.dir .. '" 2>/dev/null')
local h = io.open(d.dir .. "/" .. w.name, "wb")
if h then h:write(bytes) h:close() end
end
end
end
end
end
local function taskName(ui)
local t = ui.m.tasks:get(ui.st.playTaskId)
if not t.isActive then return "none" end
for k, v in pairs(ui.fn) do if v == t.func then return k end end
return "?"
end
return function(game)
local sess = X.newGame(d, game, 1)
if not sess then return d.finish() end
local C = require("src.core.game3.constants").of("emerald")
local Bag = require("src.core.game3.bag")
Bag.add(sess.bag, C:require("items", "ITEM_COIN_CASE"), 1)
Bag.Coins.set(sess, 100)
X.setVar("VAR_DAILY_ROULETTE", 0)
d.check(X.goTo(d, game, "EM_MAUVILLE_CITY_GAME_CORNER", 13, 7, "right"), "Mauville Game Corner loads")
U.wait(20)
GC().last = nil
U.tap(game, "a")
local entry = X.waitFor(function() return GC().last and GC().last.entry and GC().last.entry.state == "yesNo" end, 900)
if not d.check(entry, "left table script runs PlayRoulette to the minimum-wager prompt") then return d.finish() end
local e = GC().last.entry
d.check(e.minBet == 1, "left table minimum wager is 1 (" .. tostring(e.minBet) .. ")")
d.check(e.text and e.text:find("1", 1, true) ~= nil, "prompt names the wager: " .. tostring(e.text))
d.check(require("src.ui.game3.coins_box").isVisible(), "coins window shows during the prompt")
d.shot(game, "00_min_wager_prompt.png")
U.tap(game, "a")
local opened = X.waitFor(function() return GC().last.screen ~= nil end, 900)
if not d.check(opened, "YES fades into the roulette table") then return d.finish() end
local ui = GC().last.screen
local snaps = {
{ name = "01_board.png", when = function(s) return s.st and s.frames > 30 and s.hw == nil and s.st.playTaskId and taskName(s) == "taskWaitForNextTask" end },
{ name = "02_select_grid.png", when = function(s) return s.st and s.st.playTaskId and taskName(s) == "taskHandleBetGridInput" end },
{ name = "03_ball_rolling.png", when = function(s) return s.st and s.st.ballRolling and s.st.ballState == 0 and s.st.ballDistToCenter and s.st.ballDistToCenter < 50 end },
{ name = "04_ball_landed.png", when = function(s) return s.st and s.st.playTaskId and taskName(s) == "taskSlideGridOnscreen" end },
{ name = "05_result.png", when = function(s) return s.st and s.st.playTaskId and taskName(s) == "taskTryIncrementWins" end },
}
snapshotHook(ui, snaps)
local started = X.waitFor(function() return ui.st and ui.st.playTaskId and taskName(ui) == "taskWaitForNextTask" and ui.hw == nil end, 900)
d.check(started, "board fades in with the controls instruction")
d.check(ui.st.minBet == 1 and ui.st.tableId == 0, "table 0, min bet 1")
U.wait(4)
d.still(game, "01b_controls_instruction.png")
local coins = 100
for ball = 1, 3 do
U.tap(game, "a")
local grid = X.waitFor(function() return taskName(ui) == "taskHandleBetGridInput" end, 900)
d.check(grid, "ball " .. ball .. ": bet grid opens on the first empty square (" .. ui:task(ui.st.playTaskId).data[4] .. ")")
if ball == 2 then
U.tap(game, "up")
X.waitFor(function() return ui:task(ui.st.playTaskId).data[4] <= 4 end, 60)
d.check(ui:task(ui.st.playTaskId).data[4] <= 4, "UP moves the selection to a column header")
elseif ball == 3 then
U.tap(game, "left")
U.wait(2)
U.tap(game, "left")
end
U.wait(10)
if ball == 1 then d.still(game, "02b_grid_selection.png") end
local sel = ui:task(ui.st.playTaskId).data[4]
U.tap(game, "a")
local rolled = X.waitFor(function() return ui.st.ballRolling end, 900)
d.check(rolled, "ball " .. ball .. ": bet on " .. sel .. " slides the grid away and rolls the ball")
local landed = X.waitFor(function() return taskName(ui) == "taskSlideGridOnscreen" or taskName(ui) == "taskFlashBallOnWinningSquare" end, 3000)
d.check(landed, "ball " .. ball .. ": ball lands in slot " .. tostring(ui.st.hitSlot) .. " (stuck=" .. tostring(ui.st.ballStuck) .. ")")
local asked = false
for _ = 1, 40 do
if not X.waitFor(function()
return taskName(ui) == "taskCallYesOrNo" or (taskName(ui) == "taskWaitForNextTask" and (ui.st.taskWaitKey or 0) ~= 0)
end, 30000) then break end
if taskName(ui) == "taskCallYesOrNo" then asked = true break end
local next = ui.st.nextTask
U.tap(game, "a")
X.waitFor(function() return taskName(ui) ~= "taskWaitForNextTask" or ui.st.nextTask ~= next end, 120)
end
if not asked then d.note("stuck in " .. taskName(ui) .. " sePlaying=" .. tostring(ui.sound:sePlaying())) end
local dd = ui:task(ui.st.playTaskId).data
d.check(asked, string.format("ball %d: result %s, credit %d -> %d, asks to keep playing", ball,
dd[5] == 1 and "hit" or "miss", coins, dd[13]))
if dd[5] == 1 then
d.check(dd[13] == coins - 1 + dd[2], "payout is min bet x multiplier (" .. dd[2] .. ")")
else
d.check(dd[13] == coins - 1, "a miss costs the min bet")
end
coins = dd[13]
if ball < 3 then
U.tap(game, "a")
X.waitFor(function() return taskName(ui) ~= "taskCallYesOrNo" end, 200)
end
end
d.still(game, "06_keep_playing.png")
U.tap(game, "down")
U.wait(2)
U.tap(game, "a")
local closed = X.waitFor(function() return GC().last.phase == "done" end, 1500)
d.check(closed, "NO fades back to the field")
X.settle(game, 600)
X.waitFor(function() return not X.scriptRunning() end, 600)
U.wait(30)
local s = X.session()
d.check(s.map == "EM_MAUVILLE_CITY_GAME_CORNER", "back in the Game Corner")
d.check(Bag.Coins.get(s) == coins, "coin case holds the table's credit (" .. Bag.Coins.get(s) .. " == " .. coins .. ")")
d.check(X.var("VAR_DAILY_ROULETTE") == 3, "IncrementDailyRouletteUses counted 3 balls (" .. X.var("VAR_DAILY_ROULETTE") .. ")")
d.check(not X.scriptRunning(), "roulette script released")
d.shot(game, "07_back_in_field.png")
for _, w in ipairs(snaps) do d.note("snapshot " .. w.name .. " " .. tostring(w.taken)) end
d.finish()
end