-- The Forge port of Adventures in Videoland: Rollercoaster, driven and traced as the original -- is. local here = ((debug.getinfo(1, "S").source:gsub("^@", "")):match("^(.*[/\\])") or "") local library = os.getenv("SINGE_LIBRARY") or (os.getenv("HOME") .. "/claude/singetest") local game = os.getenv("PORT_GAME") or "Rollercoaster" local name = (os.getenv("PORT_SCRIPT") or (game .. "/" .. game .. ".singe")):gsub("%.singe$", "") local stem = name:match("([^/\\]+)$") dofile("Forge/AuthorCompile.singe") dofile(here .. "videolandDrive.singe") -- The game seeds its random draws from os.time at load; the original's driver pins it, and so -- does this, to the same number. os.time = function(...) return 12345 end local realSkip = discSkipToFrame discSkipToFrame = function(frame) videolandTraceSeek(frame) return realSkip(frame) end local realSearch = discSearch discSearch = function(frame) videolandTraceSeek(frame) return realSearch(frame) end dofile(authorBuild(library .. "/" .. name .. ".forge", singeGetDataPath() .. stem .. ".port.singe")) local realUpdate = onOverlayUpdate -- A key, as the engine hands one to the runtime in the whole keyboard mode: its keysym on the -- switch channel, then the key itself. The return and backspace keys' keysyms are switch -- numbers too, and the runtime drops those while the key is down, which a driven run cannot -- show it; they go by the key alone, as they arrive in play. function videolandKey(keysym, scancode) if (keysym ~= 13) and (keysym ~= 8) then authorSwitchDown(keysym, nil) end authorKeyDown(keysym, scancode) end local function view() local q = authorEntity("game").q return { state = q.state, next = q.next, room = q.L, turns = q.T, keyboard = q.keyboard, keyhit = q.keyhit, delay = q.delay, still = (q.still ~= nil), endFrame = q.endFrame, frame = discGetFrame(), prints = q.prints, last = q.screen[q.lines], input = q.input } end onOverlayUpdate = function(...) local result = realUpdate(...) videolandDrive(view()) return result end