MeteorStrike's amazingly detailed FAQ on the Item Exploitation/Disappearance Bug explains so many of the memory addresses beautifully here:
http://faqs.ign.com/articles/974/974431p1.html
Thanks to him doing ALL of the memory digging for me, I had a nice headstart on the script I wanted to make, and after a couple hours, I came up with this (probably really ugly) "Find the Best Frame to All-Out" script.
-- This script, when running correctly, will
-- brute force checking All-Out for a full
-- minute and keeps track of the best frame
-- for time and best frame for health of group.
local i=0;
local frame=0;
local framecount=0;
local bestframes=0;
local bestframesframes=99999;
local bestframeshealth=0;
local besthealth=0;
local besthealthframes=99999;
local besthealthhealth=0;
local health=0;
local endloop=5;
local enemies=0;
local statell=savestate.create(9);
local myinputs = joypad.read(1);
FCEU.speedmode("maximum");
savestate.save(statell);
--Increase the second number here to brute force for more than a minute of gameplay.
while (frame<(100)) do
framecount=0;
endloop=5;
myinputs.A = nil;
joypad.write(1,myinputs);
savestate.load(statell);
for i=0,frame do
if (i~=frame) then
joypad.write(1,myinputs);
gui.text(8,150,"So far... Fastest: "..bestframes..", "..bestframesframes.." frames w/"..bestframeshealth.."HP.\n Healthiest: "..besthealth..", with "..besthealthhealth.."HP in "..besthealthframes.." frames.");
FCEU.frameadvance();
end;
end;
myinputs.A = true;
joypad.write(1,myinputs);
--Increase the latter number if you don't mind winning All_Outs longer than 5 minutes of gameplay.
while (framecount<15000> bestframeshealth) then
bestframes = frame;
bestframeshealth = health;
bestframesframes = framecount + frame;
end;
end;
if ((framecount + frame) < bestframesframes) then
bestframes = frame;
bestframeshealth = health;
bestframesframes = framecount + frame;
end;
if (health == besthealthhealth) then
if ((framecount + frame) <besthealthframes> besthealthhealth) then
besthealthhealth = health;
besthealth = frame;
besthealthframes = frame + framecount;
end;
endloop=1;
end;
if endloop==1 then
framecount=18001;
end;
gui.text(8,8,frame.." "..framecount.." "..enemies.." "..endloop)
gui.text(8,150,"So far... Fastest: "..bestframes..", "..bestframesframes.." frames w/"..bestframeshealth.."HP.\n Healthiest: "..besthealth..", with "..besthealthhealth.."HP in "..besthealthframes.." frames.");
FCEU.frameadvance();
framecount = framecount + 1;
end;
savestate.load(statell);
--Printing bests to screen
gui.text(8,150,"So far... Fastest: "..bestframes..", "..bestframesframes.." frames w/"..bestframeshealth.."HP.\n Healthiest: "..besthealth..", with "..besthealthhealth.."HP in "..besthealthframes.." frames.");
frame = frame + 1;
end;
-- Loop the message forever until you choose to end the script.
-- In the future I should change this to set state 7 to fastest's start and state 8 to healthiest's start via an anonymous state,
-- maybe even set 6 to alternate healthiest or faster in case two come out equal so I can test both and see which is more entertaining to the viewer, say multiple consecutive crits/misses? I dunno.
FCEU.speedmode("normal");
gui.text(8,150,"All done! Fastest: "..bestframes..", with "..bestframesframes.." frames w/"..bestframeshealth.."HP.\n Healthiest: "..besthealth..", with "..besthealthhealth.."HP in "..besthealthframes.." frames.");
FCEU.pause();
This will save a new state and press A on the first frame and record the results, reload the state, wait one frame, and do it again, up through however many times you tell it to (right now it's set really low, to 100). It automatically knows if all of the enemies are dead, and if that round was faster or had a healthier party (in case it's not too far behind in frames you have an alternative) and keeps records of which was best, displaying the results on screen during the whole exploration.
It has its flaws still, though: You have to manually comment out the lines that check whether any of your allies have died if they enter the battle already dead (I can fix this later though), and when the script is ALL done, it loads the state and then advances a frame to right the final result to the screen. This is probably an easy fix. The idea was just to get something out there that works. (I wish I could figure out why it won't actually save to State 9 like the documentation says it should, though. It would be nice to add features later where it saves states for the best runs and you can just load those states to go straight to the frame.)
And it DID work. Setting it to test for 100 frames, the script found a solution that was 134 frames faster than even your improvement, with ally generals having a cumulative health that was 15 more, after more than a second of consecutive failure frames, something I doubt a real person would've had the patience to go through!
This script is only good for finding ways through the battle by hitting A and letting it run. It would require some serious math to come up with a bot that could possibly improve the battle with the B button to exit All-Out at precisely the right time,and then go right back into it, hmm. I also intend to write up a script that does the same thing as this one but presses the B button after a goal is reached, say, all Rebel Forces have been slain, so as to potentially make the rest of the battle faster if we have to switch to Tactics by removing their longwinded "Attacks! Damage done!" texts. Maybe I can combine them all into one dialog box with buttons and a fancy range 'o' knobs with iup i dunnos!
Good idea about equipping the Flails without taking a step first, it makes a lot of sense. Add those frames in before the 92 frames of wait my script found, and there's potentially enough time to even go into the menu again and set Liu Bei as tactician or equip a Robe or something, just to see what it can do to save health or whatevs, since we'll be waiting anyway. In the 92 frame battle, Zhang Fei never takes any damage, hence the quicker ending, by Guan Yu is dropped to 22HP. If the Robe can save another few HP then we've got something good. I'll play around more after work.