So our Davis AI fight did take place live, even if probably no one saw it live. But that may be better that way because my streaming capabilities were so bad that I had to use Suriks FPS changer at max to recognize any action going on. You should be able to view it [here] once the processing is done. (edit: scroll down to the bottom of this post to get high quality recordings for each match) But better yet you copy our two AIs from below and let them fight locally for yourself (keep in mind to give them unused AIs as original AIs still use ranged moves):
A little explanation on those two:
While I had basically worked all week on mine Azriel only took the last day for it, that's why mine pretty much gets straight wins all the time. However mine still has about 4 flaws left and is only optimized for fighting another Davis (I have yet to make it counter other characters and maybe even do some crowd control and tactic running away so it can maybe get through some stages on its own).
that was cool, esp the discussion. gonna keep working on it tonight, and try to get an ai that can actually fight close range =d, and also gonna try make the code look neater.
hm, there's no forum for ai, (maybe this be in a new thread in lf2 general) but anyways, reworked my ai, and pitted it against itself. this is what i got:
When is the original video going to be uploaded in watchable quality?
I'm highly interested in this, but unfortunately I don't have the software to try this out myself right now :(By the way, YinYin really must really be awful at streaming. Besides having like 0,02 fps, the video also just shows each fiftieth frame or so. :DAzriel, what makes the red Davis suddenly change his behavior?
>> Azriel, what makes the red Davis suddenly change his behavior?
the distance limit must've changed (went past 275 pixels? i think). otherwise it was the original ai that pressed the jump
btw, my new ai for davis (compatible up to version 0.6). works much better than the old one.
C-Code:
// === classifiers === //
var CLOSE_RANGE =0;
var MID_RANGE =1;
var LONG_RANGE =2;
var OUT_OF_RANGE =3;// === environment === //
var xRange = self_x - target_x;
var yRange = self_y - target_y;
var zRange = self_z - target_z;
var facingSameDir =(self_facing == target_facing);
var facingTarget;// whether self is facing the target// === function pointers === //
var approachTargetX;
var departTargetX;
var approachXKeyState;
var departXKeyState;
var approachTargetZ;
var departTargetZ;
var moveForward;// if facing right, right();
var moveBackward;// if facing right, left();// === setup environment === //if((self_facing ==0&& xRange <0)||(self_facing ==1&& xRange >0)){// facing right and standing to the left of target OR// facing left and standing to the right of target
facingTarget =true;}else{
facingTarget =(self_facing == target_facing);}// === setup functions === //// setup x commandsif(xRange <=0){
approachTargetX = right;
departTargetX = left;
approachXKeyState = self_right;
departXKeyState = self_left;}else{
approachTargetX = left;
departTargetX = right;
approachXKeyState = self_left;
departXKeyState = self_right;}// setup z commandsif(zRange <=0){
approachTargetZ = down;
departTargetZ = up;}else{
approachTargetZ = up;
departTargetZ = down;}// setup forward/backwardif(self_facing ==0){// facing right
moveForward = right;
moveBackward = left;}else{
moveForward = left;
moveBackward = right;}// === utility functions === //
def classifyXDistance(xDistance){
var absXDistance = abs(xDistance);if(absXDistance <50){return0;}if(absXDistance <150){return1;}if(absXDistance <275){return2;}return3;}
def classifyZDistance(zDistance){
var absZDistance = abs(zDistance);if(absZDistance <=16){return0;}if(absZDistance <=27){return1;}if(absZDistance <=45){return2;}return3;}
def isDragonPunchProbable(targetMp, targetState, targetFrame){if(targetMp <225){returnfalse;}if(targetState ==11|| targetState ==16|| targetFrame ==300){returntrue;}returnfalse;}// === low level ai functions === //// walkApproachTargetX(approachTargetX, approachXKeyState);
def walkApproachTargetX(approachXFunction, xKeyState){if(xKeyState ==0){
approachXFunction();}}// walkDepartTargetX(departTargetX, departXKeyState);
def walkDepartTargetX(departXFunction, xKeyState){if(xKeyState ==0){
departXFunction();}}// runApproachTargetX(approachTargetX, approachXKeyState);
def runApproachTargetX(approachXFunction, xKeyState){if(xKeyState ==0){
approachXFunction();}}// runApproachTarget(approachTargetX, approachXKeyState, approachTargetZ);
def runApproachTarget(approachXFunction, xKeyState, approachZFunction){
runApproachTargetX(approachXFunction, xKeyState);
approachZFunction();}// runDepartTargetX(departTargetX, departXKeyState);
def runDepartTargetX(departXFunction, xKeyState){if(xKeyState ==0){
departXFunction();}}// dashApproachTargetX(approachTargetX, approachXKeyState, self_state);
def dashApproachTargetX(approachXFunction, xKeyState, char_state){
runApproachTargetX(approachXFunction, xKeyState);if(char_state ==2){
J();}}// dashDepartTargetX(departTargetX, departXKeyState, self_state);
def dashDepartTargetX(departXFunction, xKeyState, char_state){
runDepartTargetX(departXFunction, xKeyState);if(char_state ==2){
J();}}// dashApproachTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);
def dashApproachTarget(approachXFunction, xKeyState, approachZFunction, char_state){
runApproachTargetX(approachXFunction, xKeyState);
approachZFunction();if(char_state ==2){
J();return1;}return0;}// dashDepartTarget(departTargetX, departXKeyState, departTargetZ, self_state);
def dashDepartTarget(departXFunction, xKeyState, departZFunction, char_state){
runDepartTargetX(departXFunction, xKeyState);
departZFunction();if(char_state ==2){
J();return1;}return0;}// === mid level ai functions === //// selectiveApproachTargetX(approachTargetX, approachXKeyState, self_state, xRange);
def selectiveApproachTargetX(approachXFunction, xKeyState, char_state, xDistance){
var xDistanceClass = classifyXDistance(xDistance);if(xDistanceClass <=1){return0;}//walkApproachTargetX(approachXFunction, xKeyState);elseif(xDistanceClass ==2){ runApproachTargetX(approachXFunction, xKeyState);}else{ dashApproachTargetX(approachXFunction, xKeyState, char_state);}}// selectiveApproachTarget(approachTargetX, approachTargetZ, approachXKeyState, self_state, xRange, zRange);
def selectiveApproachTarget(approachXFunction, approachZFunction, xKeyState, char_state, xDistance, zDistance){
selectiveApproachTargetX(approachXFunction, xKeyState, char_state, xDistance);
approachZFunction();}// === mid-high level ai functions === //// runAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);
def runAttackTarget(approachXFunction, xKeyState, approachZFunction, char_state){if(char_state ==3){return1;}
runApproachTarget(approachXFunction, xKeyState, approachZFunction);if(char_state ==2){
A();return1;}return0;}// runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, xRange, self_mp);
def runSelectiveAttackTarget(approachXFunction, xKeyState, approachZFunction, char_state, char_mp, xDistance, needsEvasion){if(char_state ==3){return1;}
runApproachTarget(approachXFunction, xKeyState, approachZFunction);if(char_state ==2){if(xDistance <=80){if(char_mp >=225){
DuA();}elseif(char_mp >=75&& needsEvasion ==false){
DdA();}else{
D();}}else{if(char_mp <150){
A();}// otherwise we wait so we can do a special move}return1;}return0;}// dashAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);
def dashAttackTarget(approachXFunction, xKeyState, approachZFunction, char_state){if(char_state ==5){
approachXFunction();
approachZFunction();
A();return1;}return dashApproachTarget(approachXFunction, xKeyState, approachZFunction, char_state);}// === variables === ///*
* Commands
* 0 means no input for that command has been issued.
*/
var defensiveCommand =0;
var xRangeClass = classifyXDistance(xRange);
var zRangeClass = classifyZDistance(zRange);
var probableDragonPunch = isDragonPunchProbable(target_mp, target_state, target_frame);// === attack chains === //// ending frame of strafeif(self_frame ==281){if(target_state ==12&& target_frame >=180){
J();return1;}}// jump_hit (D^J) frameif(self_frame ==292){// make sure they are not "rowing"if((target_state !=6&& target_y -12> self_y)|| self_y >-25){
A();}return1;}// === evasion/defensive === //// caught move-breaker (doesn't work for davis since his jump attack takes so long)if(self_state ==10){// A();// return 1;}// try to block hitsif(self_state ==11|| self_state ==16){if(self_mp >=225){
DuA();}elseif(self_mp >=75){
DdA();}else{
D();}}// close rangeif(zRangeClass ==0&& xRangeClass ==0){if(self_frame ==110&& self_shake >0){
DdA();return1;}if(self_weapon_type ==6){if(self_state ==17){
D();return1;}else{return dashAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);}}if(target_state ==8){// broken defense
DdA();return1;}elseif(target_state ==16){// DoPif(abs(xRange)<7){
departTargetX();}else{
approachTargetX();}return1;}elseif(target_state ==10){// caught
A();return1;}elseif(target_state ==11){// injuredif(target_mp >=225){
DuA();}elseif(target_fall <=40){
A();}else{
DdA();}return1;}elseif(target_state ==12){// fallingif(self_mp >=225&& self_state <=2){
DuA();return1;}}elseif(target_state <=3|| target_mp >=225|| target_DuA ==3){if(target_frame <270|| target_frame >282){if(target_frame >=303&& self_state !=12){// attempt to counter dragon punchif(self_facing == target_facing){
moveForward();if(self_mp >=225){
DuA();return1;}elseif(self_mp >=75&& target_frame >=304){
DdA();return1;}return runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, self_mp, xRange,false);}else{
moveBackward();// face same way as targetreturn1;}}else{if(self_facing == target_facing){
approachTargetX();if(self_frame <85&& self_frame >=90){// not run attack
A();}return1;}else{if(facingTarget){if(target_state ==3|| probableDragonPunch){
D();}else{// attack only if not already attacking (don't want to cancel run attack)if(self_state !=3){
A();}elseif(self_state ==2){return runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, self_mp, xRange, probableDragonPunch);}}}else{if(probableDragonPunch){
approachTargetX();
D();}else{// dodge
departTargetZ();
departTargetX();}}return1;}}}else{
dashDepartTarget(departTargetX, departXKeyState, departTargetZ, self_state);
D();return1;}}elseif(target_state ==4){return runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, self_mp, xRange,false);}}elseif(zRangeClass ==0&& xRangeClass ==1){if(target_frame >=303&& self_state !=12){// attempt to counter dragon punchif(self_facing == target_facing){
moveForward();if(self_mp >=225){
DuA();return1;}elseif(self_mp >=75&& target_frame >=304){
DdA();return1;}
runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, self_mp, xRange,false);}else{
moveBackward();// face same way as targetreturn1;}}else{if(self_weapon_type ==6){if(self_state ==17){
D();return1;}else{return dashAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);}}if(self_facing == target_facing){
approachTargetX();if(self_frame <85&& self_frame >=90){// not run attack
A();}return1;}else{if(facingTarget){if(target_state ==3){
D();}else{return runSelectiveAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state, self_mp, xRange, probableDragonPunch);//runAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);}}else{if(probableDragonPunch){
approachTargetX();
D();}else{// dodge
departTargetZ();
departTargetX();}}return1;}}}elseif( zRangeClass ==1&&(xRangeClass ==1|| xRangeClass ==2)){if(self_weapon_type ==6){if(self_state ==17){
D();return1;}else{return dashAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);}}return dashAttackTarget(approachTargetX, approachXKeyState, approachTargetZ, self_state);}elseif(zRangeClass <=2&& xRangeClass >=2){//runApproachTargetX(approachTargetX, approachXKeyState);
approachTargetX();
departTargetZ();}else{
selectiveApproachTarget(approachTargetX, approachTargetZ, approachXKeyState, self_state, xRange, zRange);}return0;
I blame the bad quality on the sh**** software
it just isn't made for streaming games i guess (or my graphics card doesn't like it)
because notice how smooth all mouse and window movement actions are ... - while the game screen only updates every 10 seconds!
gosh
and this when i even told the screen recorder to only capture the lf2 application
anyway both my computer and upload speed should not be the problem as i can easily record gameplay at full resolution and the stream of my screen was fluent as you can see from the mouse movement ...
i got about 3 other programs to try, maybe they will do the job better next time
if not we really need someone else to stream these matches (+ have a poll beforehand to find out at what time most would actually watch this live - it didnt seem like we had many/any watching my fail stream as it was getting recorded)
i don't really have the time and patience to re record the matches soon so i send the files to silva
... and now its time to see how much your AI has improved azzy :D
edit: hell yes, lots of dash attacks - thats what i expected from you on the first match
these matches are much more thrilling - still i think yours isnt better than mine yet
you actually sometimes waste a dragon punch directly from running when the opponent isnt even close enough
edit: a tip for your isDragonPunchProbable:
if (self_hp <= 114 && target_mp >= 225) {
return true;
}
because my davis is an opportunistic a**hole