--Welcome! This Lua AI was developed to run inside of BizHawk 2.8's built-in Lua Console.
--The AI plays the 1981 Intellivision game Meteor (the prototype to Astrosmash) with immeasurably greater efficiency than any human. While this is great performance, many issues still need fixing:
--Current issues that still need fixing:
--The script is completely reactionary. It does not analyze RNG to predict when, where, or what hazards will spawn. It also has no idea where it will teleport to when it decides to teleport.
--More efficient targeting...
--The player's projectile is so small and so fast that it commonly misses targets by skipping over it from one frame to the next, especially at higher levels.
--Sometimes for very fast targets, by the time the player rotates to face the target, the target has aleady moved past intersection for that axis. This results in the player making several rotations without ever shooting.
--Objects are targeted only if INTERSECTION is detected. If, for instance, an object has only horizontal velocity and is just below the East/West targeting axis, NaN will be computed for that axis's object intersection, even though shooting along said axis would CLEARLY hit the object.
--The code is set up with the following targeting priority: UFO > Large Asteroid > Small Asteroid.
--There is no higher priority given to targeting closer objects, although such an additional prioritization scheme would be more efficient.
--let's begin by defining some random variables we'll be using later; all of these represent pixel tolerances when targeting or teleporting away from objects
sathi = 3
satlo = -6
lathi = 3
latlo = -7
ufothi = 6
ufotlo = -6
sawhix = 5
sawlox = -9
sawhiy = 5
sawloy = -5
ufowhix = 11
ufowlox = -11
ufowhiy = 8
ufowloy = -6
lawhix = 11
lawlox = -11
lawhiy = 7
lawloy = -7
ubwhix = 5
ubwlox = -8
ubwhiy = 7
ubwloy = -5
whix = 5
wlox = -9
whiy = 9
wloy = -5
--define arrays for variables that need to be updated for all 5 hazards every frame
shotxspd90 = {}
shotyspd90 = {}
oid = {}
osid = {}
ox = {}
oy = {}
oxspd = {}
oyspd = {}
ospd = {}
oxspd90 = {}
oyspd90 = {}
oxend = {}
oyend = {}
ufo = {}
smast = {}
lgast = {}
ufoblast = {}
explosion = {}
t = {}
traj = {}
fire = {}
warp = {}
--define what frame to start the game on
start = 16 --9, 14, 17, 19 yield duplicate RNGs of previous ones
while true do
--look in the main ram memory domain to track the current level (0-19 based on current score)
memory.usememorydomain("Main RAM")
level = memory.readbyte(0x67)
--swith to system ram memory domain
memory.usememorydomain("System Ram")
--track the player's current x & y positions (converted to pixel units) and facing angle
px = memory.readbyte(0x023E) + (memory.readbyte(0x023F))/256
py = memory.readbyte(0x0240) + (memory.readbyte(0x0241))/256
heading = memory.readbyte(0x023A) + (memory.readbyte(0x0245))*8
--calculate the speed of the player's shot on every frame for each angle, should one be fired (converted to pixels/frame units)
if level < 4
then
shotxspd = {0,3,5.625,7.375,8,7.375,5.625,3,0,-3,-5.625,-7.375,-8,-7.375,-5.625,-3}
shotyspd = {-8,-7.375,-5.625,-3,0,3,5.625,7.375,8,7.375,5.625,3,0,-3,-5.625,-7.375}
elseif level < 8
then
shotxspd = {0,3.75,7,9.25,10,9.25,7,3.75,0,-3.75,-7,-9.25,-10,-9.25,-7,-3.75}
shotyspd = {-10,-9.25,-7,-3.75,0,3.75,7,9.25,10,9.25,7,3.75,0,-3.75,-7,-9.25}
elseif level < 12
then
shotxspd = {0,4.5,8.5,11.125,12,11.125,8.5,4.5,0,-4.5,-8.375,-11,-12,-11,-8.375,-4.5}
shotyspd = {-12,-11,-8.375,-4.5,0,4.5,8.5,11.125,12,11.125,8.5,4.5,0,-4.5,-8.375,-11}
elseif level < 16
then
shotxspd = {0,5.25,9.875,12.875,14,12.875,9.875,5.25,0,-5.25,-9.875,-12.875,-14,-12.875,-9.875,-5.25}
shotyspd = {-14,-12.875,-9.875,-5.25,0,5.25,9.875,12.875,14,12.875,9.875,5.25,0,-5.25,-9.875,-12.875}
elseif (level >= 16)
then
shotxspd = {0,5.875,11.125,14.5,15.75,14.5,11.125,5.875,0,-5.875,-11.125,-14.5,-15.75,-14.5,-11.125,-5.875}
shotyspd = {-15.75,-14.5,-11.125,-5.875,0,5.875,11.125,14.5,15.75,14.5,11.125,5.875,0,-5.875,-11.125,-14.5}
end
--calculate the 90-degree counter-clockwise speed of each shot (needed for targeting calcs)
for m=1, 16, 1 do
shotxspd90[m] = shotyspd[m]
shotyspd90[m] = -shotxspd[m]
end
--neutralize inputs shortly after a death to prevent locking
deaths1 = memory.readbyte(0X0289)
if (deaths1 ~= deaths2)
then
for j=1, 2, 1 do
joypad.set({N=false, NNE=false, NE=false, ENE=false, E=false, ESE=false, SE=false, SSE=false, S=false, SSW=false, SW=false, WSW=false, W=false, WNW=false, NW=false, NNW=false, Top=false}, 1)
joypad.set({N=false, NNE=false, NE=false, ENE=false, E=false, ESE=false, SE=false, SSE=false, S=false, SSW=false, SW=false, WSW=false, W=false, WNW=false, NW=false, NNW=false, Top=false}, 2)
emu.frameadvance()
end
end
for k=1, 5, 1 do
--define each of the nested arrays we'll be using
t[k] = {}
traj[k] = {}
fire[k] = {}
oxend[k] = {}
oyend[k] = {}
for m=1, 16, 1 do
--track the "object ID" and "object sub-ID" which will be used to identify what each of the 5 hazards are
oid[k] = memory.readbyte(0x026A+(k-1)*0x10)
osid[k] = memory.readbyte(0x026B+(k-1)*0x10)
--classify hazards as ufo, small asteroid, large asteroid, ufo blast, or explosion based on known variables
ufo[k] = ((oid[k] == 120) and (osid[k] == 143))
smast[k] = ((oid[k] >= 88 and oid[k] <= 94) and (osid[k] < 138))
lgast[k] = ((oid[k] == 120) or ((oid[k] >= 122) and (oid[k] <= 126))) and osid[k] ~= 143
ufoblast[k] = ((oid[k] == 88) and (osid[k] == 143))
explosion[k] = ((oid[k] == 88) and (osid[k] == 138))
--track the x and y positions of each of the 5 hazards (converted to pixel units)
--x and y positions are adjusted so the origin for each hazard is the center; this makes calculations later much easier
if smast[k]
then
ox[k] = memory.readbyte(0x026E+(k-1)*0x10) + (memory.readbyte(0x026F+(k-1)*0x10))/256 + 2
oy[k] = memory.readbyte(0x0270+(k-1)*0x10) + (memory.readbyte(0x0271+(k-1)*0x10))/256 - 2
elseif lgast[k]
then
ox[k] = memory.readbyte(0x026E+(k-1)*0x10) + (memory.readbyte(0x026F+(k-1)*0x10))/256 + 4
oy[k] = memory.readbyte(0x0270+(k-1)*0x10) + (memory.readbyte(0x0271+(k-1)*0x10))/256
elseif ufo[k]
then
ox[k] = memory.readbyte(0x026E+(k-1)*0x10) + (memory.readbyte(0x026F+(k-1)*0x10))/256 + 4
oy[k] = memory.readbyte(0x0270+(k-1)*0x10) + (memory.readbyte(0x0271+(k-1)*0x10))/256 - 1
else
ox[k] = memory.readbyte(0x026E+(k-1)*0x10) + (memory.readbyte(0x026F+(k-1)*0x10))/256 + 2
oy[k] = memory.readbyte(0x0270+(k-1)*0x10) + (memory.readbyte(0x0271+(k-1)*0x10))/256 - 2
end
--track the x and y speeds of each hazard (converted to pixels/frame units)
oxspd[k] = (memory.read_s8(0x0272+(k-1)*0x10))/8
oyspd[k] = (memory.read_s8(0x0273+(k-1)*0x10))/8
--calculate the magnitude of each hazard's velocity
ospd[k] = (oxspd[k]^2 + oyspd[k]^2)^0.5
--calculate the 90-degree counter-clockwise speed of each hazard (needed for targeting calcs)
oxspd90[k] = oyspd[k]
oyspd90[k] = -oxspd[k]
--time till an object will intersect each of the player's target rays
t[k][m] = math.ceil((((px-ox[k])*shotxspd90[m])+((py-oy[k])*shotyspd90[m]))/((oxspd[k]*shotxspd90[m])+(oyspd[k]*shotyspd90[m])))
--time a bullet would take to intersect an object for each of the player's target rays
traj[k][m] = math.ceil((((ox[k]-px)*oxspd90[k])+((oy[k]-py)*oyspd90[k]))/((shotxspd[m]*oxspd90[k])+(shotyspd[m]*oyspd90[k])))
--pixels the object will be from the player's target ray at the time of bullet intersection
fire[k][m] = (t[k][m] - math.abs(traj[k][m]))*ospd[k]
--determines at what x/y position a bullet will hit an object; used to determine whether a bullet can reach the object before despawning offscreen
oxend[k][m] = ox[k] + oxspd[k]*traj[k][m]
oyend[k][m] = oy[k] + oyspd[k]*traj[k][m]
end
--the following m loop defines how to point toward and fire upon the 3 target types
--the targets are ordered in increasing targeting priority (ie small asteroid targeting has least priority while ufo targeting has highest)
for m=1, 16, 1 do
if (smast[k])
then
if (fire[k][1] <= sathi) and (fire[k][1] >= satlo)
then
if (oy[k] + t[k][1]*oyspd[k] < py) and (oyend[k][1] > 0)
then
joypad.set({N=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 24
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][2] <= sathi) and (fire[k][2] >= satlo)
then
if (ox[k] + t[k][2]*oxspd[k] > px) and (oy[k] + t[k][2]*oyspd[k] < py) and (oxend[k][2] < 168) and (oyend[k][2] > 0)
then
joypad.set({NNE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 34
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][3] <= sathi) and (fire[k][3] >= satlo)
then
if (ox[k] + t[k][3]*oxspd[k] > px) and (oy[k] + t[k][3]*oyspd[k] < py) and (oxend[k][3] < 168) and (oyend[k][3] > 0)
then
joypad.set({NE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 42
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][4] <= sathi) and (fire[k][4] >= satlo)
then
if (ox[k] + t[k][4]*oxspd[k] > px) and (oy[k] + t[k][4]*oyspd[k] < py) and (oxend[k][4] < 168) and (oyend[k][4] > 0)
then
joypad.set({ENE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 50
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][5] <= sathi) and (fire[k][5] >= satlo)
then
if (ox[k] + t[k][5]*oxspd[k] > px) and (oxend[k][5] < 168)
then
joypad.set({E=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 58
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][6] <= sathi) and (fire[k][6] >= satlo)
then
if (ox[k] + t[k][6]*oxspd[k] > px) and (oy[k] + t[k][6]*oyspd[k] > py) and (oxend[k][6] < 168) and (oyend[k][6] < 104)
then
joypad.set({ESE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 54
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][7] <= sathi) and (fire[k][7] >= satlo)
then
if (ox[k] + t[k][7]*oxspd[k] > px) and (oy[k] + t[k][7]*oyspd[k] > py) and (oxend[k][7] < 168) and (oyend[k][7] < 104)
then
joypad.set({SE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 46
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][8] <= sathi) and (fire[k][8] >= satlo)
then
if (ox[k] + t[k][8]*oxspd[k] > px) and (oy[k] + t[k][8]*oyspd[k] > py) and (oxend[k][8] < 168) and (oyend[k][8] < 104)
then
joypad.set({SSE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 38
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][9] <= sathi) and (fire[k][9] >= satlo)
then
if (oy[k] + t[k][9]*oyspd[k] > py) and (oyend[k][9] < 104)
then
joypad.set({S=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 30
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][10] <= sathi) and (fire[k][10] >= satlo)
then
if (ox[k] + t[k][10]*oxspd[k] < px) and (oy[k] + t[k][10]*oyspd[k] > py) and (oxend[k][10] > 0) and (oyend[k][10] < 104)
then
joypad.set({SSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 36
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][11] <= sathi) and (fire[k][11] >= satlo)
then
if (ox[k] + t[k][11]*oxspd[k] < px) and (oy[k] + t[k][11]*oyspd[k] > py) and (oxend[k][11] > 0) and (oyend[k][11] < 104)
then
joypad.set({SW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 44
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][12] <= sathi) and (fire[k][12] >= satlo)
then
if (ox[k] + t[k][12]*oxspd[k] < px) and (oy[k] + t[k][12]*oyspd[k] > py) and (oxend[k][12] > 0) and (oyend[k][12] < 104)
then
joypad.set({WSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 52
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][13] <= sathi) and (fire[k][13] >= satlo)
then
if (ox[k] + t[k][13]*oxspd[k] < px) and (oxend[k][13] > 0)
then
joypad.set({W=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 60
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][14] <= sathi) and (fire[k][14] >= satlo)
then
if (ox[k] + t[k][14]*oxspd[k] < px) and (oy[k] + t[k][14]*oyspd[k] < py) and (oxend[k][14] > 0) and (oyend[k][14] > 0)
then
joypad.set({WNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 48
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][15] <= sathi) and (fire[k][15] >= satlo)
then
if (ox[k] + t[k][15]*oxspd[k] < px) and (oy[k] + t[k][15]*oyspd[k] < py) and (oxend[k][15] > 0) and (oyend[k][15] > 0)
then
joypad.set({NW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 40
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
if (fire[k][16] <= sathi) and (fire[k][16] >= satlo)
then
if (ox[k] + t[k][16]*oxspd[k] < px) and (oy[k] + t[k][16]*oyspd[k] < py) and (oxend[k][16] > 0) and (oyend[k][16] > 0)
then
joypad.set({NNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 32
then
joypad.set({Top=true}, 1)
--joypad.set({Top=true}, 2)
end
end
end
end
if (lgast[k])
then
if (fire[k][1] <= lathi) and (fire[k][1] >= latlo)
then
if (oy[k] + t[k][1]*oyspd[k] < py) and (oyend[k][1] > 0)
then
joypad.set({N=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 24
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][2] <= lathi) and (fire[k][2] >= latlo)
then
if (ox[k] + t[k][2]*oxspd[k] > px) and (oy[k] + t[k][2]*oyspd[k] < py) and (oxend[k][2] < 168) and (oyend[k][2] > 0)
then
joypad.set({NNE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 34
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][3] <= lathi) and (fire[k][3] >= latlo)
then
if (ox[k] + t[k][3]*oxspd[k] > px) and (oy[k] + t[k][3]*oyspd[k] < py) and (oxend[k][3] < 168) and (oyend[k][3] > 0)
then
joypad.set({NE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 42
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][4] <= lathi) and (fire[k][4] >= latlo)
then
if (ox[k] + t[k][4]*oxspd[k] > px) and (oy[k] + t[k][4]*oyspd[k] < py) and (oxend[k][4] < 168) and (oyend[k][4] > 0)
then
joypad.set({ENE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 50
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][5] <= lathi) and (fire[k][5] >= latlo)
then
if (ox[k] + t[k][5]*oxspd[k] > px) and (oxend[k][5] < 168)
then
joypad.set({E=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 58
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][6] <= lathi) and (fire[k][6] >= latlo)
then
if (ox[k] + t[k][6]*oxspd[k] > px) and (oy[k] + t[k][6]*oyspd[k] > py) and (oxend[k][6] < 168) and (oyend[k][6] < 104)
then
joypad.set({ESE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 54
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][7] <= lathi) and (fire[k][7] >= latlo)
then
if (ox[k] + t[k][7]*oxspd[k] > px) and (oy[k] + t[k][7]*oyspd[k] > py) and (oxend[k][7] < 168) and (oyend[k][7] < 104)
then
joypad.set({SE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 46
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][8] <= lathi) and (fire[k][8] >= latlo)
then
if (ox[k] + t[k][8]*oxspd[k] > px) and (oy[k] + t[k][8]*oyspd[k] > py) and (oxend[k][8] < 168) and (oyend[k][8] < 104)
then
joypad.set({SSE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 38
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][9] <= lathi) and (fire[k][9] >= latlo)
then
if (oy[k] + t[k][9]*oyspd[k] > py) and (oyend[k][9] < 104)
then
joypad.set({S=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 30
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][10] <= lathi) and (fire[k][10] >= latlo)
then
if (ox[k] + t[k][10]*oxspd[k] < px) and (oy[k] + t[k][10]*oyspd[k] > py) and (oxend[k][10] > 0) and (oyend[k][10] < 104)
then
joypad.set({SSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 36
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][11] <= lathi) and (fire[k][11] >= latlo)
then
if (ox[k] + t[k][11]*oxspd[k] < px) and (oy[k] + t[k][11]*oyspd[k] > py) and (oxend[k][11] > 0) and (oyend[k][11] < 104)
then
joypad.set({SW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 44
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][12] <= lathi) and (fire[k][12] >= latlo)
then
if (ox[k] + t[k][12]*oxspd[k] < px) and (oy[k] + t[k][12]*oyspd[k] > py) and (oxend[k][12] > 0) and (oyend[k][12] < 104)
then
joypad.set({WSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 52
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][13] <= lathi) and (fire[k][13] >= latlo)
then
if (ox[k] + t[k][13]*oxspd[k] < px) and (oxend[k][13] > 0)
then
joypad.set({W=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 60
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][14] <= lathi) and (fire[k][14] >= latlo)
then
if (ox[k] + t[k][14]*oxspd[k] < px) and (oy[k] + t[k][14]*oyspd[k] < py) and (oxend[k][14] > 0) and (oyend[k][14] > 0)
then
joypad.set({WNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 48
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][15] <= lathi) and (fire[k][15] >= latlo)
then
if (ox[k] + t[k][15]*oxspd[k] < px) and (oy[k] + t[k][15]*oyspd[k] < py) and (oxend[k][15] > 0) and (oyend[k][15] > 0)
then
joypad.set({NW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 40
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][16] <= lathi) and (fire[k][16] >= latlo)
then
if (ox[k] + t[k][16]*oxspd[k] < px) and (oy[k] + t[k][16]*oyspd[k] < py) and (oxend[k][16] > 0) and (oyend[k][16] > 0)
then
joypad.set({NNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 32
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
end
if (ufo[k])
then
if (fire[k][1] <= ufothi) and (fire[k][1] >= ufotlo)
then
if (oy[k] + t[k][1]*oyspd[k] < py) and (oyend[k][1] > 0)
then
joypad.set({N=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 24
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][2] <= ufothi) and (fire[k][2] >= ufotlo)
then
if (ox[k] + t[k][2]*oxspd[k] > px) and (oy[k] + t[k][2]*oyspd[k] < py) and (oxend[k][2] < 168) and (oyend[k][2] > 0)
then
joypad.set({NNE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 34
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][3] <= ufothi) and (fire[k][3] >= ufotlo)
then
if (ox[k] + t[k][3]*oxspd[k] > px) and (oy[k] + t[k][3]*oyspd[k] < py) and (oxend[k][3] < 168) and (oyend[k][3] > 0)
then
joypad.set({NE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 42
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][4] <= ufothi) and (fire[k][4] >= ufotlo)
then
if (ox[k] + t[k][4]*oxspd[k] > px) and (oy[k] + t[k][4]*oyspd[k] < py) and (oxend[k][4] < 168) and (oyend[k][4] > 0)
then
joypad.set({ENE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 50
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][5] <= ufothi) and (fire[k][5] >= ufotlo)
then
if (ox[k] + t[k][5]*oxspd[k] > px) and (oxend[k][5] < 168)
then
joypad.set({E=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 58
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][6] <= ufothi) and (fire[k][6] >= ufotlo)
then
if (ox[k] + t[k][6]*oxspd[k] > px) and (oy[k] + t[k][6]*oyspd[k] > py) and (oxend[k][6] < 168) and (oyend[k][6] < 104)
then
joypad.set({ESE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 54
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][7] <= ufothi) and (fire[k][7] >= ufotlo)
then
if (ox[k] + t[k][7]*oxspd[k] > px) and (oy[k] + t[k][7]*oyspd[k] > py) and (oxend[k][7] < 168) and (oyend[k][7] < 104)
then
joypad.set({SE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 46
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][8] <= ufothi) and (fire[k][8] >= ufotlo)
then
if (ox[k] + t[k][8]*oxspd[k] > px) and (oy[k] + t[k][8]*oyspd[k] > py) and (oxend[k][8] < 168) and (oyend[k][8] < 104)
then
joypad.set({SSE=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 38
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][9] <= ufothi) and (fire[k][9] >= ufotlo)
then
if (oy[k] + t[k][9]*oyspd[k] > py) and (oyend[k][9] < 104)
then
joypad.set({S=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 30
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][10] <= ufothi) and (fire[k][10] >= ufotlo)
then
if (ox[k] + t[k][10]*oxspd[k] < px) and (oy[k] + t[k][10]*oyspd[k] > py) and (oxend[k][10] > 0) and (oyend[k][10] < 104)
then
joypad.set({SSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 36
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][11] <= ufothi) and (fire[k][11] >= ufotlo)
then
if (ox[k] + t[k][11]*oxspd[k] < px) and (oy[k] + t[k][11]*oyspd[k] > py) and (oxend[k][11] > 0) and (oyend[k][11] < 104)
then
joypad.set({SW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 44
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][12] <= ufothi) and (fire[k][12] >= ufotlo)
then
if (ox[k] + t[k][12]*oxspd[k] < px) and (oy[k] + t[k][12]*oyspd[k] > py) and (oxend[k][12] > 0) and (oyend[k][12] < 104)
then
joypad.set({WSW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 52
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][13] <= ufothi) and (fire[k][13] >= ufotlo)
then
if (ox[k] + t[k][13]*oxspd[k] < px) and (oxend[k][13] > 0)
then
joypad.set({W=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 60
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][14] <= ufothi) and (fire[k][14] >= ufotlo)
then
if (ox[k] + t[k][14]*oxspd[k] < px) and (oy[k] + t[k][14]*oyspd[k] < py) and (oxend[k][14] > 0) and (oyend[k][14] > 0)
then
joypad.set({WNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 48
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][15] <= ufothi) and (fire[k][15] >= ufotlo)
then
if (ox[k] + t[k][15]*oxspd[k] < px) and (oy[k] + t[k][15]*oyspd[k] < py) and (oxend[k][15] > 0) and (oyend[k][15] > 0)
then
joypad.set({NW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 40
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
if (fire[k][16] <= ufothi) and (fire[k][16] >= ufotlo)
then
if (ox[k] + t[k][16]*oxspd[k] < px) and (oy[k] + t[k][16]*oyspd[k] < py) and (oxend[k][16] > 0) and (oyend[k][16] > 0)
then
joypad.set({NNW=true, Top=false}, 1)
joypad.set({Top=false}, 2)
if heading == 32
then
joypad.set({Top=true}, 1)
joypad.set({Top=true}, 2)
end
end
end
end
end
end
--if a hazard is within a defined rectangle from the player's position, hold the teleport key until the player position changes
for k=1, 5, 1 do
if ( smast[k] )
then
if --(((math.floor(px)-math.floor(ox[k]+3*oxspd[k]) <= sawhix) and (math.floor(px)-math.floor(ox[k]+3*oxspd[k]) >= sawlox)) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) <= sawhiy) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) >= sawloy))
--(((math.floor(px)-math.floor(ox[k]+2*oxspd[k]) <= sawhix) and (math.floor(px)-math.floor(ox[k]+2*oxspd[k]) >= sawlox)) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) <= sawhiy) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) >= sawloy))
(((math.floor(px)-math.floor(ox[k]+oxspd[k]) <= sawhix) and (math.floor(px)-math.floor(ox[k]+oxspd[k]) >= sawlox)) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) <= sawhiy) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) >= sawloy))
or (((math.floor(px)-math.floor(ox[k]) <= sawhix) and (math.floor(px)-math.floor(ox[k]) >= sawlox)) and (math.floor(py)-math.floor(oy[k]) <= sawhiy) and (math.floor(py)-math.floor(oy[k]) >= sawloy))
then
joypad.set({["Key 3"]=true}, 2)
if (px ~= px2) or (py ~= py2) then end
end
end
if ( ufo[k] )
then
if --(((math.floor(px)-math.floor(ox[k]+3*oxspd[k]) <= ufowhix) and (math.floor(px)-math.floor(ox[k]+3*oxspd[k]) >= ufowlox)) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) <= ufowhiy) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) >= ufowloy))
--(((math.floor(px)-math.floor(ox[k]+2*oxspd[k]) <= ufowhix) and (math.floor(px)-math.floor(ox[k]+2*oxspd[k]) >= ufowlox)) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) <= ufowhiy) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) >= ufowloy))
(((math.floor(px)-math.floor(ox[k]+oxspd[k]) <= ufowhix) and (math.floor(px)-math.floor(ox[k]+oxspd[k]) >= ufowlox)) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) <= ufowhiy) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) >= ufowloy))
or (((math.floor(px)-math.floor(ox[k]) <= ufowhix) and (math.floor(px)-math.floor(ox[k]) >= ufowlox)) and (math.floor(py)-math.floor(oy[k]) <= ufowhiy) and (math.floor(py)-math.floor(oy[k]) >= ufowloy))
then
joypad.set({["Key 3"]=true}, 2)
if (px ~= px2) or (py ~= py2) then end
end
end
if ( lgast[k] )
then
if --(((math.floor(px)-math.floor(ox[k]+3*oxspd[k]) <= lawhix) and (math.floor(px)-math.floor(ox[k]+3*oxspd[k]) >= lawlox)) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) <= lawhiy) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) >= lawloy))
--(((math.floor(px)-math.floor(ox[k]+2*oxspd[k]) <= lawhix) and (math.floor(px)-math.floor(ox[k]+2*oxspd[k]) >= lawlox)) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) <= lawhiy) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) >= lawloy))
(((math.floor(px)-math.floor(ox[k]+oxspd[k]) <= lawhix) and (math.floor(px)-math.floor(ox[k]+oxspd[k]) >= lawlox)) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) <= lawhiy) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) >= lawloy))
or (((math.floor(px)-math.floor(ox[k]) <= lawhix) and (math.floor(px)-math.floor(ox[k]) >= lawlox)) and (math.floor(py)-math.floor(oy[k]) <= lawhiy) and (math.floor(py)-math.floor(oy[k]) >= lawloy))
then
joypad.set({["Key 3"]=true}, 2)
if (px ~= px2) or (py ~= py2) then end
end
end
if ( ufoblast[k] )
then
if --(((math.floor(px)-math.floor(ox[k]+3*oxspd[k]) <= ubwhix) and (math.floor(px)-math.floor(ox[k]+3*oxspd[k]) >= ubwlox)) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) <= ubwhiy) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) >= ubwloy))
--(((math.floor(px)-math.floor(ox[k]+2*oxspd[k]) <= ubwhix) and (math.floor(px)-math.floor(ox[k]+2*oxspd[k]) >= ubwlox)) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) <= ubwhiy) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) >= ubwloy))
(((math.floor(px)-math.floor(ox[k]+oxspd[k]) <= ubwhix) and (math.floor(px)-math.floor(ox[k]+oxspd[k]) >= ubwlox)) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) <= ubwhiy) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) >= ubwloy))
or (((math.floor(px)-math.floor(ox[k]) <= ubwhix) and (math.floor(px)-math.floor(ox[k]) >= ubwlox)) and (math.floor(py)-math.floor(oy[k]) <= ubwhiy) and (math.floor(py)-math.floor(oy[k]) >= ubwloy))
then
joypad.set({["Key 3"]=true}, 2)
if (px ~= px2) or (py ~= py2) then end
end
end
if ( explosion[k] )
then
if --(((math.floor(px)-math.floor(ox[k]+3*oxspd[k]) <= whix) and (math.floor(px)-math.floor(ox[k]+3*oxspd[k]) >= wlox)) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) <= whiy) and (math.floor(py)-math.floor(oy[k]+3*oyspd[k]) >= wloy))
--(((math.floor(px)-math.floor(ox[k]+2*oxspd[k]) <= whix) and (math.floor(px)-math.floor(ox[k]+2*oxspd[k]) >= wlox)) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) <= whiy) and (math.floor(py)-math.floor(oy[k]+2*oyspd[k]) >= wloy))
(((math.floor(px)-math.floor(ox[k]+oxspd[k]) <= whix) and (math.floor(px)-math.floor(ox[k]+oxspd[k]) >= wlox)) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) <= whiy) and (math.floor(py)-math.floor(oy[k]+oyspd[k]) >= wloy))
or (((math.floor(px)-math.floor(ox[k]) <= whix) and (math.floor(px)-math.floor(ox[k]) >= wlox)) and (math.floor(py)-math.floor(oy[k]) <= whiy) and (math.floor(py)-math.floor(oy[k]) >= wloy))
then
joypad.set({["Key 3"]=true}, 2)
if (px ~= px2) or (py ~= py2) then end
end
end
end
--this line is needed to get the for loop below deaths1 to function properly
deaths2 = memory.readbyte(0X0289)
--controls exiting from the teleport routine
px2 = memory.readbyte(0x023E) + (memory.readbyte(0x023F))/256
py2 = memory.readbyte(0x0240) + (memory.readbyte(0x0241))/256
--used for starting the game
if (emu.framecount() <= start-1 or emu.framecount() == start+1)
then
joypad.set({N=false, NNE=false, NE=false, ENE=false, E=false, ESE=false, SE=false, SSE=false, S=false, SSW=false, SW=false, WSW=false, W=false, WNW=false, NW=false, NNW=false, Top=false}, 1)
joypad.set({N=false, NNE=false, NE=false, ENE=false, E=false, ESE=false, SE=false, SSE=false, S=false, SSW=false, SW=false, WSW=false, W=false, WNW=false, NW=false, NNW=false, Top=false}, 2)
end
if emu.framecount() == start
then
joypad.set({Top=true}, 1)
end
if (emu.framecount() >= start+2 and emu.framecount() <= start+7)
then
joypad.set({["Key 2"]=true}, 1)
joypad.set({["Enter"]=true}, 2)
end
--close original while loop
emu.frameadvance()
end