• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

AI Handbook 2.0x readable syntax [stable]

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
CGFalco

Introduction
Since Phantom Wings and Kryal created great tools, a lot of custom characters have been developed by many hackers. They have useful ability to attack or recover from outside of the stage,but no CPs could intentionally use them. You can make CPs use them by making custom AI.

Overview
AI files can be found in FitCharEtc.pac or Fighter.pac. The AI of Fighter.pac defines default AI of CP and the AI of each character override them.
There are three kinds of AI files(AIPD,AIMain,ATKD). AIMain is the main file which defines the character's move. AIMain can be divided into some routines. Each routine has following things.
  • ID
  • Commands
  • Floating point values
The game always evaluates the condition and calls proper AI by ID. For example,80 is the routine for getting the other side of the opponent (Detailed info: AIScript_Notes). Each time the game calls them,it sets a timeout to execute them. If the routine can't be executed by the timeout, the game stops executing it and evaluates the condition again. Some actions stop the game executing it too.

AIScriptpad[stable]
[IMGHLF]http://img59.imageshack.us/img59/6650/aiscriptpad1.png[/IMGHLF]
AIScriptpad is a program to make custom AI. This program uses JavaScript as scripting language,but you don't have to worry about not knowing it. Though it's JavaScript, all you have to do is calling functions which are defined already. You can program AI like programing in PSA.

Params
Temporary Variables 0x0000-0x0018
internally stored as floats
Functions 0x1000->
ASM routines that return a float value
Script Constants 0x2000->
You can add them with "AddGlobal" function in AIScriptpad.

Commands and their usage
[COLLAPSE="Commands"]
Name|Arguments|Description
Finish||Stops executing current routine.
SetVar|1:ID 2:Value|Sets value of internal array.
Label||Sets a label so that "Seek" can find it.
|1:ID|Sets a label with ID
Return||Returns to previous label in the next frame. If there are no labels above this, stops executing current routine.
Seek||Seeks a label. If the game reaches "Return" after using this, next time the game goes to the found label.
|1:ID|Seeks a label specified with an ID.
If|1:Requirement ...|Creates an If block. If the requirement is true,the game executes commands inside of the block.
IfNot|1:Requirement ...|Creates an If block. If the requirement is false,the game executes commands inside of the block.
Else||This command must be located inside of an If block. If the If block is not executed,commands after this are executed alternatively.
EndIf||Ends an If block.
Stick|1:X(-1 to 1)|Inputs stick. X coordinate stretches from the rear to the front.
|1:X(-1 to 1) 2:Y(-1 to 1)|
Button|1:Flag|Inputs buttons specified with the argument. You can input multiple buttons. Bit1: A, Bit2: B, Bit3: R or L, Bit4: X or Y
Add|1:ArrayID 2:value|Adds value to the internally stored value,and restores it into the same place.
|1:ArrayID 2:value 3:value|
Sub|1:ArrayID 2:value|Subtracts value to the internally stored value,and restores it into the same place.
|1:ArrayID 2:value 3:value|
Mul|1:ArrayID 2:value|Multiplies value to the internally stored value,and restores it into the same place.
|1:ArrayID 2:value 3:value|
Div|1:ArrayID 2:value|Divides value to the internally stored value,and restores it into the same place.
|1:ArrayID 2:value 3:value|
Jump||Jumps to the label found by "Seek" in the same frame.
Or|1:Requirement ...|Additional OR requirement for If/IfNot.
OrNot|1:Requirement ...|Additional OR/NOT requirement for If/IfNot.
And|1:Requirement ...|Additional AND requirement for If/IfNot.
AndNot|1:Requirement ...|Additional AND/NOT requirement for If/IfNot.
CallAI||Calls another AI routine specified with SetAIDest.
|1:TrueID|Calls another AI routine specified with the argument.
Seek2||The same usage as "Seek".
TargetStick|1:X(-1 to 1)|Inputs stick. X coordinate stretches from left to right.
|1:X(-1 to 1) 2:Y(-1 to 1)|
SetTimeout|1:Frames|Sets timeout frames. If you set this to 0,timeout is removed.
SetAIDest|1:TrueID|Sets CallAI destination.
[/COLLAPSE]

Requirements and their usage
[COLLAPSE="Requirements"]
Name|Arguments|Description
Distance|1:Distance|If the distance between the character and the opponent is shorter than the argument,it returns true.
Frames|1:Frames|If the frame count which has passed since the current routine started being executed is larger than the argument,it returns true.
Idle||If both the character and the opponent is normal state,it returns true.
Dashing||If the character is dashing, it returns true.
InAir||If the character is in the air,it returns true.
GT|1:value 2:object of comparison|arg1>arg2
LT|1:value 2:object of comparison|arg1<arg2
GE|1:value 2:object of comparison|arg1>=arg2
LE|1:value 2:object of comparison|arg1<=arg2
Throughable||If the current plane can be fell through,it returns true.
CalledAs|1:TrueID|If the current routine was called as the ID,it returns true.
IsCounterChance|1:0x1 or 0x2|If the argument is 1,it returns whether or not the character is spotdodging. If 2,returns whether or not the character was attacked during guarding.
IsInvincible||If the character is invincible(star,final smash),it returns true.
IsGrabbing||If the character is grabbing and able to throw the opponent,it returns true.
OAttacking||If the opponent is attacking,it returns true.
OWiring||If the opponent is using wire(samus,zero suit,link,etc),it returns true.
OInAir||If the opponent is in the air,it returns true.
TurnRunBraking||If the character is "TurnRunBrak"ing,it returns true.
IsCharOf|1:ID|If the character is the character specified with the argument,it returns true.
OIsCharOf|1:ID|If the opponent is the character specified with the argument,it returns true.
CharID
Code:
0 Mario
1 Donkey
2 Link
3 Samus
4 Yoshi
5 Kirby
6 Fox
7 Pikachu
8 Luigi
9 Falcon
A Ness
B Bowser
C Peach
D Zelda
E Shiek
F Popo
10 Nana
11 Marth
12 G&W
13 Falco
14 Ganondorf
15 Wario
16 Metaknight
17 Pit
18 Zerosuit Samus
19 Pikmin
1A Lucas
1B Diddy
1D Lizardon
1E Zenigame
1F Fushigisou
20 DDD
21 Lucario
22 Ike
23 Robot
25 Purin
29 Toonlink
2C Wolf
2E Snake
2F Sonic
[/COLLAPSE]

Functions and their usage
[COLLAPSE="Functions"]
Name|Description
Direction|If the character is looking right,returns -1,looking left,1.
OPosition|If the opponent is right of the character,returns -1 ,left ,1.
XCoord|Returns the character's X coordinate.
OXCoord|Returns the opponent's X coordinate.
DistToOEdge|Returns distance to the opponent-side edge.
FrameCount|Returns frame count from beginning of the current routine.
XAcceleration|Returns X acceleration.
YCoord|Returns the character's Y coordinate.
OYCoord|Returns the opponent's Y coordinate.
YAcceleration|Returns Y acceleration.
JumpCount|Returns the character's remained jump count.
DistToLookedEdge|Returns distance to the edge looked by the character.
OXSpeed|Returns X speed of the opponent.
OYSpeed|Returns Y speed of the opponent.
ExactXCoord|Returns the character's exact X coordinate.
ExactYCoord|Returns the character's exact Y coordinate.
ExactOXCoord|Returns the opponent's exact X coordinate.
ExactOYCoord|Returns the opponent's exact Y coordinate.
DamageAmount|Returns the character's damage amount.
ODamageAmount|Returns the opponent's damage amount.
ODirection|If the opponent is looking right,returns -1,looking left,1.
OJumpCount|Returns the opponent's remained jump count.
DistToNotLookedEdge|Returns distance to the edge not looked by the character.
BBoundary|Returns distance to the bottom boundary.
TBoundary|Returns distance to the top boundary.
LBoundary|Returns distance to the left boundary.
RBoundary|Returns distance to the right boundary,
DistBetPlaneTBoundary|Returns distance between the current plane and the top boundary.
[/COLLAPSE]

Resources
[COLLAPSE="Debugging codes"]
This code forces the game load only one routine.
Code:
Force AI Into Routine v2.0 [Dantarion]
C29188B0 00000002
3B40XXXX B3590078
60000000 00000000


Where XXXX = Routine ID
This code visualizes CPU input.
Code:
CPU GFX [Shanus]
4A000000 90000000
1619F000 000003F0
00000000 FFFFFFFF
00000006 00000030
00000000 00000000
00000000 00000001
00000000 00000000
00000001 00000000
00000001 000493E0
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 0000EA60
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000003 00000000
00000006 00000030
00000000 00000001
00000000 00000003
00000000 00000000
00000001 00000000
00000001 00075300
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 0000EA60
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000003 00000000
00000006 00000030
00000000 00000002
00000000 00000005
00000000 00000000
00000001 0003A980
00000001 000493E0
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 0000EA60
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000003 00000000
00000006 00000030
00000000 00000003
00000000 0000000C
00000000 00000000
00000001 0003A980
00000001 00075300
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 0000EA60
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000003 00000000
00000000 0000001E
00000000 00000000
00000005 000003F5
00000005 000003FA
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 0000EA60
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000001 00000000
00000003 00000000
00000001 0000EA60
00000000 00000001
00000003 00000000
00000003 00000000
00000000 00000003
00000003 00000000
00000003 00000000
00000000 00000005
00000003 00000000
00000003 00000000
00000000 0000000C
00000003 00000000
00000003 00000000
00000000 0000001E
00000003 00000000
00000003 00000000
00040100 9019F000
000A0200 9019F008
11001000 9019F018
000F0000 00000000
000A0200 9019F098
11001000 9019F0A8
000F0000 00000000
000A0200 9019F128
11001000 9019F138
000F0000 00000000
000A0200 9019F1B8
11001000 9019F1C8
000F0000 00000000
11001000 9019F248
00010100 9019F2C8
11050300 9019F2D0
11050300 9019F2E8
11050300 9019F300
11050300 9019F318
11050300 9019F330
00050000 00000000
1819F400 9019F348
21FF0004 00000000
0689D858 00000008
3C609019 6063F448
[/COLLAPSE]
AI process image
http://opensa.dantarion.com/ai_dumps/x.png

Coding idioms

Approach to the opponent(walk)
Code:
SetVar(var0,OPosition);
Mul(var0,0.5);
TargetStick(var0,0);
Return();


Special thanks
Dantarion: Thank you for helping me looking into AI system. Your suggestion was always correct.
Kryal: Author of BrawlLib. AIScriptpad uses modded BrawlLib.
Jint develop team:I used Jint.dll to interpret JavaScripts.
WPG develop team:I used WPF property grid for property editor.
Phantom Wings:He made File Patch Code. Without it,any SSBB modding wouldn't have been achieved.

See Also
OpenSA-AIScript Notes

In conclusion,this is the source code of CG Falco. I used Force AI Into Routine v2.0 and CPU GFX to record CG Falco video.
Code:
//True ID:1120
//Set AIID
SetID(0x1120);

//Set Unknown
SetUnknown(0x40000);

//Strings

//Set Globals
AddGlobal(2);//0
AddGlobal(0);//1
AddGlobal(5);//2
AddGlobal(-1);//3

SetTimeout(0x2002);
//Commands
Label();//Approach routine
If(IsGrabbing);
    Seek(0x0);
    Return();
EndIf();
IfNot(Distance,0x2000);
    IfNot(LT,DistToOEdge,0x2000);
        TargetStick(OPosition);
    EndIf();
Else();
    Seek(0x1);
EndIf();
Return();

Label(0x1);//Grabbing routine
Button(0x5);
Return();

Label(0x0);//Throwing routine
//Stick(0x2001,0x2003);//Down
TargetStick(0x2001,0x2003);
Finish();
Return();
Return();
 

Evilagram

Smash Journeyman
Joined
Oct 4, 2007
Messages
420
Astounding job! Great work! I hope to see new AIs released soon. Hell, maybe you could improve level 9 AI to be more punishing!
 

Isatis

If specified, this will repl[0x00000000]ce the
Premium
BRoomer
Joined
Dec 18, 2008
Messages
10,253
Location
San Francisco, CA
NNID
reverite
THIS IS SWEEEEEEEEET!

Time to test some Brawl-related stuff :)

Good job Bero + Dant!

edit: might be nitpicky, but is there a way so that instead of typing out 0x2000 we can type out 8192 instead? or is there some specific way to code the value =o
 
D

Deleted member

Guest
awesomesauce.

can't wait to mess around with this when I'm back home
 

Yikarur

Smash Master
Joined
May 29, 2007
Messages
4,595
Location
Germany
"This code visualizes CPU input."

does it show the input like in Controltesting? o: if yes It would be awesome to do this for human too.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
"This code visualizes CPU input."

does it show the input like in Controltesting? o: if yes It would be awesome to do this for human too.
It needs to have the graphics updated to a location off-character, but it displays 4 unique graphics for Button press 0-4, as well as joystick direction.



Also, really nice work Bero.
 

Eternal Yoshi

I've covered ban wars, you know
Joined
Mar 3, 2007
Messages
5,450
Location
Playing different games
NNID
EternalYoshi
3DS FC
3394-4459-7089
It's great to see an update to this.

I'm trying to update how the CPU must recover and I wonder.
What are the directions that the AI holds the analog stick?

I see TargetStick(0x2000,0x2009); which I would assume is tapping up on the analog stick.
What about the other directions?
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Could somebody upload AIMain and other stuff from fighter.pac? For some reason, I'm getting crashes trying to open it up in BBox.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
i guess, dantarion mentioned fighter_CE and I thought it was a subfile within fighter.pac?

either way, this seems to have all the functions in it, i've just historically looked at dantarion's dump files and not in the editor itself.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Also, Dantarion generated this graphic which is useful for monitoring AI event flow:
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
CE is the old name of AIMain. I thought it only contained Condition Evaluation.
 

Wiscus

(◕ω◕✿)
Joined
Mar 27, 2009
Messages
4,414
3DS FC
3840-5663-0679
Wow this is incredible!
Good job Bero and Dant.
♥
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
That's strange... I can find two files. One is a file named "Build" and the other is the target file whose AIMain is replaced.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
When you save files, it doesn't update their date modified. This can be annoying to deal with with SVN as it doesn't update the changes. Additionally, could you try and update some of the syntax to better match dantarion's dumps, it makes it a little more readable. Also, indentation has errors where long codes such as 6040 keep on getting more and more indented rather than every truly returning all the way.

Great work though bero, trying to make CPU's do things in PM has been difficult so far though.
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
When you save files, it doesn't update their date modified.
Umm... When I saved a script,the program updated its modified date...
Could you tell me what you did more concretely?

Additionally, could you try and update some of the syntax to better match dantarion's dumps, it makes it a little more readable.
I'll do my best...

If there is an else direct followed by an if, interpret it as an elif, as in, one indentation, not two.
Wow! I've never thought like that! To tell the truth,I didn't look your dump recently.

EDIT
Thanks for using the editor. Any opinions will be appreciated.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
It updates their contents, but not the actually file date modified.

For example, if I build a file and save with new data in ai_common, it will not show the file as updated even though the new data is in it. It will still say date modified, 800 AM despite it being done ay 9PM.
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
Thank you, I've understood. I'll make the program explicitly update the file date modified.
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
I managed...
Most of the syntax has been improved. The program now outputs scripts which resemble Dantarion's dumps.
I'll upload it later. Sorry for inconvenience.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Great! Looking forward to it. Also, can you make variables output something like:

SetTimeout 0x2006 be something more like: SetTimeout 15 (0x2006)?

Small things like that would really enhance the interface to be more and more versatile.
 

Dantarion

Smash Champion
Joined
May 21, 2007
Messages
2,492
Location
Santa Barbara, CA
You should be able to do this for the globals so you can enter them as numbers instead of defining them at the top.

If you run into a float value...

1) Check and see if that value exists in the globals list, if so, write it in the file properly using the index
2) If not, add it to the globals list and write it in the file

That is why my scripts don't require you to ever type 0x20XX in, just the number
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Nice work Bero, update looks great!


Also, I believe Req 1011 is previousAI-ID, but this hasn't been tested.


6040 encodes for the decision as to which aerial to use, then quickly transitions to 1080 which maps out how to DI towards an opponent. Therefore, to not break that DI, we need to loop Button(R) during 1080 if the previous state was 6041-6045. I envision with this, I could enable L-canceling (that is, if the fighter.pac offset is unchanged at growing the file pac size), with the following syntax:

Code:
In 1080 Initializer		
	First change SetTimeout to 40 frames, then add in:	
	SetVar(var8,0);	
		
		
In 1080, End of Label 0x0, prior to Return(), Add in:		
		
	If(GE,Req1011, 0x6041); And(LE,Req1011,0x6045);	
		SetVar(var8,2);
	EndIf;	
	If(GT,var8,0);	
		Seek(var8);
		Jump();
	End If;	
		
At the end of 1080;		
		
	Label(0x2);	
	Button(R);	
	Seek(0);	
	Jump();
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
I think this info is useful for a person who are going to look into AI.
Code:
Credit to Dantarion

20 - Get on same platform
40 - Walk up to you
50 - Jump!
60 - Dash up to you
70 - Shield+Roll
80 - Gets on the other side of you
1010 - Stick toward?(Meta used Down b to approach with this)
1020 - Stick toward
1030 - Stick towards (Did not change platforms)
1040 - Stand still (Meta used Side B though)
1050 - Get on same platform (Olimar did NOT do this)
1060 - Same platform or under(Olimar went under)
1070 - Jump repeatedly (No R or L, just double jumping till out of jumps)
1080 - Same platform, or DIRECTLY UNDER (Olimar still didn't want to jump. INSANE perfect dashdance on either side of target)
1090 - Same as above?
10A0 - Character specific stuff
10D0 - Nothing?
1120
1130 - Marth did netral B offstage with this?
1140 - Follow Offstage (For edgeguarding?)
1160 - MK spammed down b
1170 - Follow to end of ledge? (For edgeguarding?)
2010 - Jump Recovery (Edge)
2020 - Side+B Recovery [All Chars]
2030 - Jump Recovery (Land on Stage)
2040 - Recovery [Character Specific]
3020 - Premptive Shield?
3090 - Walk in range?(Not too close though)
30A0 - Spotdodge
30B0 - Dodge when attacked
30D0 - Airdodge when attacked
6030 - Rapid Attack
6040 - Attack
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Some of that isn't right.

6040 = aerial attacks or aerial specials
1080 = aerial DI depending on opponent location, this is why when you were on a platform they dashdanced.


Check out the image map on the previous page which helps show which of these are used when.
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
Some of that isn't right.

6040 = aerial attacks or aerial specials
1080 = aerial DI depending on opponent location, this is why when you were on a platform they dashdanced.


Check out the image map on the previous page which helps show which of these are used when.
That is a bit obsolete info so we need to update it.
 

Bero

Smash Journeyman
Joined
Jan 10, 2010
Messages
409
Location
Japan
I know the picture if out of date, but i know im correct on 6040 and 1080 given their coding :)
Ah, I meant my info was obsolete:)

Because still few people seem to be interested in AI, I'd like to add syntax high light to make AI scripting enjoyable.


I have a request, not sure how easy it is:

Could someone make a perfect planking Meta Knight?
I think it can be done but programming it is hard. Even making CGFalco was hard for me...
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
it'd be kind of cool if you could build a simulator, i.e., if runs through the syntax flow and outputs the operations and results on the fly. So like, if you placed in assumptions, it could show you how your script will operate.
 

shanus

Smash Hero
Joined
Nov 17, 2005
Messages
6,055
Really? I think it was natural that you should have made wrong list because no commands were known then.

@shanus
It sounds hard but I'll try it...
Not necessary if its hard, don't worry about it. Maybe work on figuring out how to make it not move every fighter.pac injection?
 
Top Bottom