Beware, there's plenty of things in here I'm sure could be done more elegantly, but I was mostly experimenting.
local buttons = { B = 1, right = 1 }
local safer = savestate.create(5)
local risky = savestate.create(6)
local temp = savestate.create()
savestate.save(safer)
savestate.save(risky)
local frames_alive = 0
local frames_stopped = 0
local lastbutton = 0
local endinglevel = false
--start movie recording to random filename, set speed to maximum
FCEU.speedmode("turbo")
while true do
joypad.set(1, buttons)
local mariostate = memory.readbyte(0x000E)
local abyssstate = memory.readbyte(0x07B1)
local marioxspeed = memory.readbyte(0x57)
local marioyspeed = memory.readbyte(0x9F)
local changetimer = memory.readbyte(0x06DE)
local altcontrol = memory.readbyte(0x0752)
local screenflag = memory.readbyte(0x0774)
local screentimer = memory.readbyte(0x07A0)
local demotimer = memory.readbyte(0x07A2)
local flagsound = memory.readbyte(0x0713)
gui.text(0, 0, "alive: " .. frames_alive .." stopped: " .. frames_stopped);
gui.text(0, 8, "xs: " .. marioxspeed .. " st: " .. screentimer .. " ct: " .. changetimer .. " ac: " .. altcontrol .. " sf: " .. screenflag);
if flagsound > 0 then
endinglevel = true
end
if screentimer > 0 then
endinglevel = false
end
--if mario dies, reload.
if mariostate == 0x06 or mariostate == 0x0B or abyssstate == 1 or frames_stopped > 40 then
if math.random(0, 10) == 1 then
savestate.load(safer)
frames_alive = 0
else
savestate.load(risky)
frames_alive = 60
end
frames_stopped = 0
--compare input to previous inputs, dump results into a buttons table
end
frames_alive = frames_alive + 1
if frames_alive == 60 then
savestate.save(risky)
elseif frames_alive == 180 then
savestate.save(temp)
savestate.load(risky)
savestate.save(safer)
savestate.load(temp)
frames_alive = 0
end
if marioxspeed < 8 and screentimer == 0 and changetimer == 0 and altcontrol == 0 and screenflag == 0 and not endinglevel then
frames_stopped = frames_stopped + 1
else
frames_stopped = 0
end
--TODO: pseudo-randomize input, weighted according to previous attempts, try to jump if we're against a wall
--but for now, just jump up and down like an idiot
resetbuttons = math.random(0,20)
if frames_stopped > 0 then
if lastbutton > 4 and marioyspeed == 0 then
lastbutton = 0
buttons.A = nil
else
lastbutton = lastbutton + 1
buttons.A = 1
end
elseif resetbuttons == 1 and marioxspeed > 4 then
buttons.A = math.random(0,2)
if buttons.A == 0 then buttons.A = nil end
end
if demotimer > 0 and math.random(0,1) == 1 then
buttons.start = 1
buttons.right = nil
buttons.B = nil
buttons.A = nil
else
buttons.start = nil
buttons.right = 1
buttons.B = 1
end
--incrementally save every N frames
--detect instant death
--detect end of level, drop out of warp
FCEU.frameadvance()
end