-- Blue-line shot eval. States bl1..blNS. Outcome: goal (our score byte changes) / save (SOG counter) / block / wide. local sp=manager.machine.devices[":maincpu"].spaces["program"] local ports=manager.machine.ioport.ports local function F(b) return ports[":ctrl1:mdpad:PAD"].fields["P1 "..b] end local K={U=F("Up"),D=F("Down"),L=F("Left"),R=F("Right"),C=F("C")} local function w(a) local v=sp:read_u16(a); if v>=0x8000 then v=v-0x10000 end return v end local lf=io.open(os.getenv("EVOUT") or "blev2.txt","w") local NS=tonumber(os.getenv("NS") or "12") local trials={} for s=1,NS do for _,d in ipairs({"U","UL","UR","L","R",""}) do for _,h in ipairs({3,30}) do for _,dl in ipairs({6,12}) do trials[#trials+1]={s=s,d=d,h=h,dl=dl} end end end end local first=tonumber(os.getenv("START") or "1"); local last=tonumber(os.getenv("STOP") or tostring(#trials)) local i=first-1; local t=-1; local fr=0; local cur local S={n=0,goal=0,save=0,block=0,wide=0} local function clr() for _,k in pairs(K) do k:clear_value() end end local CAND={0xffc474,0xffc782,0xffca3f,0xffcaf3,0xffcb04,0xffcd75,0xffcd91} local function sc() local s={} for _,a in ipairs(CAND) do s[#s+1]=sp:read_u8(a) end return table.concat(s,",") end emu.register_frame_done(function() fr=fr+1 if t<0 then if fr>20 then i=i+1 if i>last then lf:write(string.format("SUMMARY n=%d goal=%d save=%d block=%d wide=%d\n",S.n,S.goal,S.save,S.block,S.wide)); lf:close(); manager.machine:exit() return end manager.machine:load("bl"..trials[i].s); t=0; clr(); cur={maxy=-999} end return end t=t+1; local tr=trials[i]; local A=tr.dl if t==1 and os.getenv('RATE') then local b=0xffb04a+sp:read_u16(0xffc320)*0x80; local k=0x66 for hx in os.getenv('RATE'):gmatch('%x%x') do if k~=0x6f then sp:write_u8(b+k,tonumber(hx,16)) end; k=k+1 end end if t==2 then cur.sog0=sp:read_u8(0xffc6cf); cur.sc0=sc() end if t==A then for c in tr.d:gmatch(".") do K[c]:set_value(1) end; K.C:set_value(1) end if t==A+tr.h then clr() end if os.getenv("SNAP") and (t==A+40 or t==A+60 or t==A+120) then manager.machine.video:snapshot() end if t>A then local own=w(0xffb7aa); local px,py=w(0xffb74a),w(0xffb75e); local vy=w(0xffb774) if os.getenv("TRACE") and t%4==0 then lf:write(string.format(" t=%d own=%d p=(%d,%d,h%d) v=(%d,%d) g=(%d,%d) sc=%s\n",t,own,px,py,w(0xffb762),w(0xffb772),vy,w(0xffb04a+11*0x80),w(0xffb04a+11*0x80+0x14),sc())) end if own<0 and not cur.fired and vy>0 then cur.fired=t; cur.d3=w(0xfff000); cur.dir=w(0xffbedc); cur.soft=sp:read_u8(0xfff002); cur.y0=py; cur.x0=px; cur.v=math.floor(math.sqrt(w(0xffb772)^2+vy^2)) end if cur.fired then if py>cur.maxy then cur.maxy=py; cur.mx=px end if sp:read_u8(0xffc6cf)~=cur.sog0 then cur.sog=true end if sc()~=cur.sc0 then cur.scch=sc() end if py>=262 and math.abs(px)<=22 and not cur.inbox then cur.inbox=string.format("(%d,%d,h%d)",px,py,w(0xffb762)) end if vy<0 and not cur.rev then cur.rev=py end if py>=225 and not cur.at225 then cur.at225=string.format('p(%d,h%d)g(%d,%d)',px,w(0xffb762),w(0xffb04a+11*0x80),w(0xffb04a+11*0x80+0x14)) end if py>=260 and not cur.gl then cur.gl=string.format('gl(%d,h%d)',px,w(0xffb762)) end end end if t==A+tr.h+300 then local res if cur.scch then res="goal" elseif cur.sog then res="save" elseif cur.rev and cur.rev<200 then res="block" else res="wide" end S.n=S.n+1; S[res]=S[res]+1 lf:write(string.format("bl%d %-2s h=%d dl=%d v=%s maxy=%d mx=%s -> %s soft=%s dir=%s d3=%s from(%s,%s) %s %s sc=%s>%s\n",tr.s,tr.d,tr.h,tr.dl,tostring(cur.v),cur.maxy,tostring(cur.mx),res,tostring(cur.soft),tostring(cur.dir),tostring(cur.d3),tostring(cur.x0),tostring(cur.y0),tostring(cur.at225),tostring(cur.gl),cur.sc0,tostring(cur.scch))); lf:flush() t=-1; fr=0 end end)