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

159 lines
6.8 KiB
Lua

local U = require("tests.drivers.util")
local X = require("tests.drivers.em_xa_util")
local d = X.new("em_slots", "/tmp/em_slots")
local GC = function() return require("src.core.game3.scripting.natives_game_corner_rse") end
local function hookSnapshots(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
if self.m.ppu.render then
local ok, data = 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(data) h:close() end
end
end
end
end
end
end
return function(game)
local sess = X.newGame(d, game, 0)
if not sess then return d.finish() end
local Constants = require("src.core.game3.constants")
local C = 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, 120)
X.setVar("VAR_DAILY_SLOTS", 0)
d.check(X.goTo(d, game, "EM_MAUVILLE_CITY_GAME_CORNER", 4, 7, "left"), "Mauville Game Corner loads")
U.wait(20)
d.shot(game, "00_game_corner.png")
GC().last = nil
U.tap(game, "a")
local opened = X.waitFor(function() return GC().last and GC().last.screen ~= nil end, 600)
if not d.check(opened, "slot machine 3 script opens the RSE slot machine (" .. tostring(GC().last and GC().last.phase) .. ")") then
return d.finish()
end
local ui = GC().last.screen
d.check(ui.machineId >= 0 and ui.machineId <= 5 and ui.machineId == GC().last.machineId,
"GetSlotMachineId picks machine " .. tostring(ui.machineId) .. " for VAR_0x8004=3")
local snaps = {
{ name = "01_bet_prompt.png", when = function(s) return s.core.state == 5 and s.frames > 40 end },
{ name = "02_reels_spinning.png", when = function(s) return s.core.state == 12 end },
{ name = "03_stopped.png", when = function(s) return s.core.state == 14 or s.core.state == 15 or s.core.state == 20 end },
{ name = "05_reel_time_window.png", when = function(s) return s.reelTimeTaskId and s.m.tasks:get(s.reelTimeTaskId).isActive and s.m.tasks:get(s.reelTimeTaskId).data[0] == 4 end },
{ name = "06_reel_time_outcome.png", when = function(s) return s.reelTimeTaskId and s.m.tasks:get(s.reelTimeTaskId).isActive and (s.m.tasks:get(s.reelTimeTaskId).data[0] == 9 or s.m.tasks:get(s.reelTimeTaskId).data[0] == 16) end },
}
hookSnapshots(ui, snaps)
X.waitFor(function() return ui.core.state == 5 end, 600)
d.check(ui.core.state == 5, "bet prompt reached (state " .. ui.core.state .. ")")
d.check(ui.core.coins == 120, "machine starts with the coin case's 120 coins")
U.wait(10)
d.still(game, "01b_bet_screen.png")
local spins, won = 0, 0
local function spin(maxBet)
local before = ui.core.coins
if maxBet then
U.tap(game, "r")
else
U.tap(game, "down")
U.wait(2)
U.tap(game, "a")
end
local started = X.waitFor(function() return ui.core.state == 12 end, 900)
if not started then return false end
spins = spins + 1
for _ = 1, 3 do
X.waitFor(function() return ui.core.state == 12 end, 900)
U.tap(game, "a")
U.wait(3)
end
local back = X.waitFor(function() return ui.core.state == 5 or ui.core.state == 12 end, 3000)
if ui.core.state == 12 then return "replay" end
if ui.core.coins >= before then won = won + 1 end
return back
end
local r = spin(true)
d.check(r, "max bet spins and stops all three reels")
d.check(ui.core.bet == 0 or ui.core.state == 12, "round resolves back to the bet prompt")
d.still(game, "03b_after_spin.png")
for _ = 1, 6 do
local rr = spin(false)
while rr == "replay" do
for _ = 1, 3 do
X.waitFor(function() return ui.core.state == 12 end, 900)
U.tap(game, "a")
U.wait(3)
end
X.waitFor(function() return ui.core.state == 5 or ui.core.state == 12 end, 3000)
rr = ui.core.state == 12 and "replay" or true
end
end
d.note(string.format("played %d spins, %d without a net loss, coins now %d, bolts %d", spins, won, ui.core.coins, ui.core.pikaPowerBolts))
U.tap(game, "select")
local function infoState()
for i = 0, 15 do
local t = ui.m.tasks:get(i)
if t.isActive and t.func == ui.infoBoxFn then return t.data[0] end
end
return -1
end
local boxOpen = X.waitFor(function() return infoState() == 6 end, 600)
d.check(boxOpen and ui.infoWindow and ui.infoWindow.text, "SELECT opens the Reel Time info box")
d.still(game, "04_info_box.png")
U.tap(game, "b")
local boxClosed = X.waitFor(function() return ui:isInfoBoxClosed() and ui.core.state == 5 end, 600)
d.check(boxClosed, "B closes the info box back to the bet prompt")
ui.core.machineBias = bit.bor(ui.core.machineBias, require("src.core.game3.rse.slot_machine").BIAS.REELTIME)
local rtStart = ui.core.coins
U.tap(game, "r")
local rtRan = X.waitFor(function() return ui.reelTimeTaskId ~= nil end, 600)
d.check(rtRan, "a Reel Time bias starts the Reel Time lottery")
local rtDone = X.waitFor(function() return ui:isReelTimeTaskDone() and ui.core.state == 12 end, 6000)
d.check(rtDone, "Reel Time lottery resolves (draw=" .. ui.core.reelTimeDraw .. ", spins left=" .. ui.core.reelTimeSpinsLeft .. ")")
for _ = 1, 3 do
X.waitFor(function() return ui.core.state == 12 end, 900)
U.tap(game, "a")
U.wait(3)
end
X.waitFor(function() return ui.core.state == 5 end, 3000)
d.note("after Reel Time round coins " .. rtStart .. " -> " .. ui.core.coins)
local daily = spins + 1
X.waitFor(function() return ui.core.state == 5 and not ui.m.ppu.palette.active end, 600)
U.tap(game, "b")
local asked = X.waitFor(function() return ui.message ~= nil and ui.yesNo ~= nil end, 600)
d.check(asked, "B asks to quit")
U.wait(10)
d.still(game, "07_quit_prompt.png")
local final = ui.core.coins
U.tap(game, "a")
local closed = X.waitFor(function() return GC().last.phase == "done" end, 1200)
d.check(closed, "YES fades out and returns 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 (" .. tostring(s.map) .. ")")
d.check(Bag.Coins.get(s) == final, "coin case holds the machine's coins (" .. Bag.Coins.get(s) .. " == " .. final .. ")")
d.check(X.var("VAR_DAILY_SLOTS") >= daily - 1 and X.var("VAR_DAILY_SLOTS") > 0,
"IncrementDailySlotsUses counted the spins (" .. X.var("VAR_DAILY_SLOTS") .. ")")
d.check(not X.scriptRunning(), "slot machine script released")
d.shot(game, "08_back_in_field.png")
for _, w in ipairs(snaps) do d.note("snapshot " .. w.name .. " " .. tostring(w.taken)) end
d.finish()
end