mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
235 lines
8.0 KiB
Lua
235 lines
8.0 KiB
Lua
local U = require("tests.drivers.util")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_corner_slots"
|
|
|
|
local CORNER = "FR_CELADON_CITY_GAME_CORNER"
|
|
-- pokefirered/include/constants/flags.h:604
|
|
local FLAG_GOT_COIN_CASE = 0x243
|
|
|
|
local failures = 0
|
|
local function result(ok, label)
|
|
print((ok and "PASS " or "FAIL ") .. label)
|
|
if not ok then failures = failures + 1 end
|
|
return ok
|
|
end
|
|
|
|
local function finish()
|
|
if failures == 0 then
|
|
print("PASS corner_slots")
|
|
love.event.quit(0)
|
|
else
|
|
print("FAIL corner_slots failures=" .. failures)
|
|
love.event.quit(1)
|
|
end
|
|
end
|
|
|
|
return function(game)
|
|
for _ = 1, 900 do
|
|
if game.phase == "boot" and game.boot then break end
|
|
U.wait(1)
|
|
end
|
|
|
|
game:_handleBootAction({ action = "new_game", name = "RED" })
|
|
U.wait(240)
|
|
|
|
local Runtime = require("src.core.game3.runtime")
|
|
local Map = require("src.core.game3.map")
|
|
local Space = require("src.core.game3.scripting.space")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Player = require("src.core.game3.player")
|
|
local Message = require("src.ui.game3.message")
|
|
local Choice = require("src.ui.game3.choice")
|
|
local Bag = require("src.core.game3.bag")
|
|
local Slots = require("src.core.game3.slot_machine")
|
|
local SlotUi = require("src.ui.game3.slot_machine")
|
|
|
|
local session = Runtime.getSession()
|
|
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
|
|
|
|
local function ctx() return Space.vm and Space.vm.ctx end
|
|
local function coins() return Bag.Coins.get(session) end
|
|
|
|
Flags.setFlag(Space.store, ctx(), FLAG_GOT_COIN_CASE, true)
|
|
Bag.Coins.set(session, 120)
|
|
|
|
Map.load(nil, game, CORNER, { x = 1, y = 7, facing = "left" })
|
|
Player.cellX, Player.cellY = 1, 7
|
|
Player.px, Player.py = 16, 7 * 16
|
|
Player.targetX, Player.targetY = 1, 7
|
|
Player.facing = "left"
|
|
if game.session then
|
|
game.session.x, game.session.y, game.session.facing = 1, 7, "left"
|
|
end
|
|
U.wait(90)
|
|
result(Space.mapId == CORNER, "standing in the Celadon Game Corner, map=" .. tostring(Space.mapId))
|
|
U.shot(game, DIR .. "/corner_slots_01_game_corner.png")
|
|
|
|
-- pokefirered/data/maps/CeladonCity_GameCorner/scripts.inc:243
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
for _ = 1, 80 do
|
|
if SlotUi.isOpen() then break end
|
|
if Message.isOpen() or Choice.active or (Space.vm and Space.vm:isRunning()) then
|
|
U.tap(game, "a")
|
|
end
|
|
U.wait(10)
|
|
end
|
|
if not result(SlotUi.isOpen(), "the slot machine sign opened the machine") then
|
|
print("[driver] vm running=" .. tostring(Space.vm and Space.vm:isRunning()) ..
|
|
" message=" .. tostring(Message.isOpen()))
|
|
return finish()
|
|
end
|
|
local st = SlotUi.state
|
|
result(st ~= nil and st.machineIdx >= 0 and st.machineIdx < Slots.NUM_MACHINE_CLASSES,
|
|
"GetRandomSlotMachineId chose luck class " .. tostring(st and st.machineIdx))
|
|
-- pokefirered/src/slot_machine.c:2087
|
|
result(not SlotUi.fadeActive() and (SlotUi._fadeY or 0) == 0,
|
|
"the machine faded in from black, fade=" .. tostring(SlotUi._fadeY))
|
|
U.wait(20)
|
|
U.shot(game, DIR .. "/corner_slots_02_machine_open.png")
|
|
|
|
-- pokefirered/src/slot_machine.c:993
|
|
U.tap(game, "right")
|
|
for _ = 1, 60 do
|
|
if SlotUi.helpPhase == "shown" then break end
|
|
U.wait(2)
|
|
end
|
|
result(SlotUi.task == "help" and SlotUi.helpPhase == "shown",
|
|
"DPAD_RIGHT slid the payout help panel in, task=" .. tostring(SlotUi.task))
|
|
U.wait(10)
|
|
U.shot(game, DIR .. "/corner_slots_03_payout_help.png")
|
|
-- pokefirered/src/slot_machine.c:1089
|
|
U.tap(game, "left")
|
|
for _ = 1, 60 do
|
|
if SlotUi.task == "bet" then break end
|
|
U.wait(2)
|
|
end
|
|
result(SlotUi.task == "bet" and (SlotUi.helpX or 0) == 0,
|
|
"DPAD_LEFT slid it back out, task=" .. tostring(SlotUi.task))
|
|
|
|
local function spinOnce()
|
|
local before = coins()
|
|
U.tap(game, "down")
|
|
U.wait(6)
|
|
U.tap(game, "down")
|
|
U.wait(6)
|
|
local betTwo = st.bet
|
|
U.tap(game, "down")
|
|
U.wait(6)
|
|
local bet = st.bet
|
|
local afterBet = coins()
|
|
for _ = 1, 120 do
|
|
if SlotUi.task ~= "bet" and SlotUi.task ~= "spin" then break end
|
|
U.wait(2)
|
|
end
|
|
return before, betTwo, bet, afterBet
|
|
end
|
|
|
|
local before, betTwo, bet, afterBet = spinOnce()
|
|
result(betTwo == 2, "two presses of DOWN bet two coins, got " .. tostring(betTwo))
|
|
result(bet == 3, "a third press bets the maximum of three, got " .. tostring(bet))
|
|
result(afterBet == before - 3, string.format("the bet debited three coins (%d to %d)", before, afterBet))
|
|
result(SlotUi.task == "stopping", "the reels are spinning, task=" .. tostring(SlotUi.task))
|
|
result(Slots.isReelSpinning(st, 0) and Slots.isReelSpinning(st, 1) and Slots.isReelSpinning(st, 2),
|
|
"all three reels spin at once")
|
|
U.wait(20)
|
|
U.shot(game, DIR .. "/corner_slots_04_reels_spinning.png")
|
|
|
|
local function stopAllReels()
|
|
for reel = 0, 2 do
|
|
for _ = 1, 40 do
|
|
if not Slots.isReelSpinning(st, reel) then break end
|
|
U.tap(game, "a")
|
|
U.wait(6)
|
|
end
|
|
result(not Slots.isReelSpinning(st, reel), "reel " .. reel .. " stopped on the A press")
|
|
end
|
|
for _ = 1, 120 do
|
|
if SlotUi.task ~= "stopping" then break end
|
|
U.wait(2)
|
|
end
|
|
end
|
|
|
|
stopAllReels()
|
|
result(SlotUi.task == "win" or SlotUi.task == "lose",
|
|
"the machine scored the spin, task=" .. tostring(SlotUi.task))
|
|
local icons = Slots.visibleIcons(st)
|
|
print(string.format("[driver] reels %d %d %d / %d %d %d / %d %d %d rank=%s payout=%s",
|
|
icons[0], icons[3], icons[6], icons[1], icons[4], icons[7], icons[2], icons[5], icons[8],
|
|
tostring(st.slotRewardClass), tostring(st.payout)))
|
|
U.shot(game, DIR .. "/corner_slots_05_reels_stopped.png")
|
|
|
|
local Audio = require("src.core.game3.audio")
|
|
local sawFanfare = false
|
|
local wonPayout, wonCoinsBefore = nil, nil
|
|
if SlotUi.task == "win" then
|
|
-- pokefirered/src/slot_machine.c:1177
|
|
sawFanfare = not Audio.isFanfareFinished()
|
|
wonPayout, wonCoinsBefore = st.payout, coins()
|
|
end
|
|
|
|
local plays = 1
|
|
while wonPayout == nil and plays < 24 and coins() >= 3 do
|
|
for _ = 1, 200 do
|
|
if SlotUi.task == "bet" then break end
|
|
U.wait(2)
|
|
end
|
|
if SlotUi.task ~= "bet" then break end
|
|
plays = plays + 1
|
|
spinOnce()
|
|
stopAllReels()
|
|
if SlotUi.task == "win" then
|
|
sawFanfare = not Audio.isFanfareFinished()
|
|
wonPayout, wonCoinsBefore = st.payout, coins()
|
|
end
|
|
end
|
|
print("[driver] plays=" .. plays .. " payout=" .. tostring(wonPayout))
|
|
|
|
if result(wonPayout ~= nil and wonPayout > 0,
|
|
"a paying line landed within " .. plays .. " plays") then
|
|
result(sawFanfare, "the win started the payout fanfare")
|
|
U.shot(game, DIR .. "/corner_slots_06_payout.png")
|
|
-- pokefirered/src/slot_machine.c:1199
|
|
for _ = 1, 400 do
|
|
if st.payout == 0 or (SlotUi._winPhase == 2 and Audio.isFanfareFinished()) then break end
|
|
U.wait(2)
|
|
end
|
|
print("[driver] payout left when the fanfare ended: " .. tostring(st.payout))
|
|
if st.payout > 0 then
|
|
U.tap(game, "start")
|
|
result(Audio.isFanfareFinished(), "START is only taken once the fanfare is over")
|
|
end
|
|
for _ = 1, 400 do
|
|
if st.payout == 0 then break end
|
|
U.wait(3)
|
|
end
|
|
result(st.payout == 0, "the payout counter emptied, left=" .. tostring(st.payout))
|
|
result(coins() == wonCoinsBefore + wonPayout,
|
|
string.format("the win paid %d coins (%d to %d)", wonPayout, wonCoinsBefore, coins()))
|
|
U.shot(game, DIR .. "/corner_slots_07_paid.png")
|
|
end
|
|
|
|
for _ = 1, 200 do
|
|
if SlotUi.task == "bet" then break end
|
|
U.wait(2)
|
|
end
|
|
local coinsAtQuit = coins()
|
|
U.tap(game, "b")
|
|
U.wait(20)
|
|
U.shot(game, DIR .. "/corner_slots_08_quit_prompt.png")
|
|
U.tap(game, "a")
|
|
U.wait(30)
|
|
result(not SlotUi.isOpen(), "answering YES closed the machine")
|
|
result(coins() == coinsAtQuit, "quitting kept the purse intact")
|
|
|
|
for _ = 1, 120 do
|
|
if not (Space.vm and Space.vm:isRunning()) then break end
|
|
U.wait(5)
|
|
end
|
|
result(not (Space.vm and Space.vm:isRunning()), "the script resumed and released the player")
|
|
result(Space.mapId == CORNER, "the player is back in the Game Corner")
|
|
U.wait(30)
|
|
U.shot(game, DIR .. "/corner_slots_09_back_in_corner.png")
|
|
|
|
finish()
|
|
end
|