Artificial Intelligence

From Infinitywiki

Jump to: navigation, search

Artificial Intelligence (or A.I.) in reference to the M.U.G.E.N game engine is the computer opponent's ability to perform as if it was a sentient fighter. The internal AI setting for the Mugen game engine have little effect of the difficulty of the opponent since they computer's basic A.I. tends to be no match for any game player. Because of these issues many programmers have developed ways to give the illusion of A.I. through the use of the CNS and CMD files.

With the release of Mugen 1.0 the ability to control the level of the A.I. through the in-game options is now available. Programmers can now use the trigger "AILevel" to accomplish this. The main difference between Mugen 1.0 A.I. versus the older Winmugen A.I. is that any character coded with the new A.I. are not backwards compatible, they will not work in older versions of mugen. You need to decide if gaining the ability to choose difficult levels in the game is more important to you than backwards compatability.

Contents

Mugen 1.0 A.I.

This tutorial will help you set up a very difficult AI (level 8) then use other portions of code to allow mugen to decrease the difficulty level according to the level selected through the in-game options screen.

Activation

The following sctrl should be placed directly under the title [statedef -1]. The purpose of this code is to allow the program to turn the A.I. on and off in random sequences according to the game difficulty. The easier the difficult the more often the custom A.I. will be turned off. The more difficult the game setting then the more often the A.I. will be turned on.

Also note that the following code uses var(59). If var(59) is being used in your caracter already for another purpose then you will need to chose a different number. Although it is not necessary to use a variable (var) for the new "AIlevel" code, creating boolean trigger simplifies the process:

   [State -1, AI Activation]
   type = varset
   triggerall = AILevel > 2
   triggerall = (roundstate = 2) && (var(59) = 0)
   trigger1 = Random <= ((AILevel-2)*100)
   v = 59
   value = 1
   [State -1, AI Deactivation]
   type = varset
   triggerall = AIlevel < 7
   triggerall = var(59) = 1
   trigger1 = Random > ((AILevel-2)*100)
   trigger2 = roundstate != 2
   v = 59
   value = 0

Details

Now that you have set the A.I. activation, you can make a series of sctrls to tell the computer when to perform each statedef(action). Below is an explanation of how a variety of codes could work.

The most important part of this code are the Triggers. Take note that each code contains the same line 'triggerall = (roundstate = 2) && (var(59) != 0)'. This simply means that the move will only work when the players are both in a fighting state and when the computer's A.I. has been activated. There is also always a line that states 'triggerall = (Ctrl)' which means the character has to be in a position to control their character (note bring thrown or hit). For more details refer to List of Triggers.

Guarding

All of the following code would work in tandum to create a relistic guarding opponent.

   [State -1, AI Guarding, Easy/Medium AI]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = AILevel <=5
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = S)
   trigger1 = (p2bodydist x <= 250) && (random = [200,899]) && (vel x < 0)
   trigger2 = (p2bodydist x <= 250) && (random = [800,899]) && (vel x > 0)
   trigger3 = (p2bodydist x <= 250) && (random = [400,899]) && (vel x = 0)
   trigger4 = (anim = 21)
   trigger5 = (prevstateno > 5000) && (random < 200)
   value = 130
   [State -1, AI Guarding, Easy/Medium AI]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = AILevel <=5
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = C)
   trigger1 = (p2bodydist x <= 250) && (random = [500,899])
   trigger2 = (prevstateno > 5000) && (random < 200)
   value = 131
   [State -1, AI Guarding, Easy/Medium AI]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = AILevel <=5
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = A)
   trigger1 = (p2bodydist x <= 250) && (random = [700,899])
   trigger2 = (anim = 43) || (anim = 46)
   trigger3 = (prevstateno > 5000) && (random < 200)
   value = 132
   [State -1, AI Guarding, Hard AI]
   type = ChangeState
   triggerall = (var(59) != 0) && Numenemy && (stateno != [120,155])
   triggerall = AILevel > 5
   triggerall = Random <= (AILevel * 10)
   triggerall =!(enemynear,hitdefattr=SCA,AT)
   triggerall = inguarddist
   trigger1 = ctrl
   value = 120

A.I. Normal Attacks

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && ((statetype = S)                      ;character is standing
   trigger1 = p2bodydist X <= 20                                ;P2 is less than or equal to 20 away on the x-axis,
   trigger1 = random <= 200                                     ;perform this move 20% of the time
   value = 200                                                  ;change to [Statedef 200] which is light punch**

(*Hint: This entire set of code called a sctrl can be repeated multiple times in the CMD file, just change the 'value' to reference a different [Statedef] each time. Also remember to change the 'statetype' to A or C for Air or Crouch attacks respectivly.)

A.I. Combo

This type of code will require some insight as to how the character should act. The point of this specific code shown below is to make the character follow up a jump attack with crouch hard kick.

   [State -1, Followup jump attack with crouch hard kick]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (p2movetype = H)                      ;opponent has been hit
   triggerall = AILevel >= 4                                    ;difficulty level is 4 or higher*
   trigger1 = (p2bodydist X <= 25)                              ;close to opponent
   trigger1 = Prevstateno = 50                                  ;falling from attack
   trigger1 = random <= 750                                     ;This will happen 75%
   value = 450


(*Hint: Depending on the severity of the attack you may want to set this higher, lower or remove it completely.)

Another common combo would be to Super Jump following a 'launcher' attacks.

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = AILevel >= 3                                     ;difficulty level is 3 or higher
   trigger1 = stateno = 420                                      ;character is doing a crouch hard punch which is a launcher
   trigger1 = movehit = 1                                        ;move has connected (P2 was hit)
   trigger1 = random <= 900                                      ;perform this move 90% of the time
   value = 7000                                                  ;change to [Statedef 7000] which is a super jump

A.I. Special Attacks

Below is a variation of the code, used for a ground projectile.

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   triggerall = AILevel >= 3                                      ;difficulty level is 3 or higher
   triggerall = random = [0,100]                                  ;performed 10% of the time*
   trigger1 = p2bodydist x >= 130                                 ;P2 is futher than 130 distance fomr character
   trigger1 = p2movetype != H                                     ;P2 has not been hit
   trigger1 = statetype != A                                      ;character is not jumping
   value = 1000                                                   ;change to [Statedef 1000] which is throwing a projectile

(*Hint: This version of 'Random' means that the move is only performed while a number between 0 and 100 is chosen from a range of 0 through 999. In essence, the move is performed 10% of the time, but durring a different 10% than a move with 'random= [101,200] or random = [201,300]. To optimize your A.I. you'll want to have similar moves use similar random values. Light punch, light kick or any other normal move that may be chosen by a real player should all use the same random values. For a special attack you may chose a different range such as [200,399] for the move to still be activated 20% of the time but not to compete with the normal attacks.)


Here is some code for anti-air move like a Shoryuken.

   ;Hard Shoryuken following fireball with opponent jumping over fireball
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   triggerall = AILevel >= 3                                  ;difficulty level is 3 or higher
   trigger1 = random = [0,400]                                ;performed 40% of the time
   trigger1 = p2bodydist x <= 50                              ;P2 is closer than 50 distance
   trigger1 = p2movetype != H                                 ;P2 has not been hit
   trigger1 = statetype != A                                  ;character is not jumping
   trigger1 = (prevstateno = 1000) || (prevstateno = 1020)    ;character was in [Statedef 1000] or [Statedef 1020] (both projectiles)
   value = 1320                                               ;change to [Statedef 1320] which is a shoryuken**
   ;Light Shoryuken when the opponent is jumping close
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   triggerall = AILevel >= 3                                  ;difficulty level is 3 or higher
   trigger1 = random = [0,400]                                ;performed 40% of the time
   trigger1 = p2bodydist x <= 50                              ;character is closer than 50 distance
   trigger1 = p2statetype = A                                 ;P2 in jumping
   trigger1 = statetype != A                                  ;character is not jumping
   value = 1300                                               ;change to [Statedef 1300] which is a shoryuken**

(**Hint: These are two great examples of bringing strategy into the A.I. The Hard Shoryuken is only being used when the opponent is jumping over a fireball and thus more vulnerable while the Light Shoryuken is only being used when the opponent is just simply jumping which menas they may be less vulnerable. The Hard Shoryuken does more damage but the Light Shoryuken has a swifter recovery time so if the attack misses your character will not be an easy target to a counter attack.)

A.I. Hyper Attack

By now you probably have a good idea of how this code works. Let's do one more, particularly a Hyper called Shinku Hadouken.

   ;Shinku Hadouken
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   triggerall = AILevel >= 4                                  ;difficulty level is 4 or higher
   triggerall = p2statetype != L                              ;P2 is not lieing down
   triggerall = stateno < 3000                                ;Add to avoid chaining hypes*
   trigger1 = prevstateno != 5120                             ;character is not in [Statedef 5120] which is "getting up"
   trigger1 = statetype != A                                  ;character is not jumping
   trigger1 = p2bodydist x >= 150                             ;P2's distance is greater than 150
   trigger1 = power >= 1000                                   ;Hyper Bar has at least 1000 power
   trigger1 = random = [500,699]                               ;Perform this move 10% of the time
   value = 3000

(*Hint: In a typical mugen character, [statedef] 0 through 999 are normal states, 1000 through 1999 are special states, 3000 through 3999 are hyper states and 5000 through 5999 are get hit states. By stating that this move can only be performed while the character is in a [statedef] less than 3000 then your basically saying this move can not be performed during another hyper or while your character is getting hit.)

Win Mugen A.I.

The following is the most popular method for programming A.I. due to its simplicity and effectiveness, although other means can produce much more exacting results.

Activation Part 1

The [Commmand] code seen below should be place above any other [Command] code in the CMD file. The purpose of this code is to create a series of commands that a human player would not be able to perform but the computer will easily be able to complete in order to avoid accidentally activating the A.I. while a human is controlling the character. Notice that the commands are series of button presses completed within 1 game tick.

   [Command]
   name = "AI_1"
   command = a, x, F, D, a, a, D
   time = 1
   
   [Command]
   name = "AI_2"
   command = a, a, a, a, a, a, b
   time = 1
   
   [Command]
   name = "AI_3"
   command = a, a, b, D, F, b, x
   time = 1
   
   [Command]
   name = "AI_4"
   command = y, a, F, b, B, y, a
   time = 1
   
   [Command]
   name = "AI_5"
   command = a, b, x, y, y, b, b
   time = 1
   
   [Command]
   name = "AI_6"
   command = b, y, y, F, b, B, B
   time = 1
   
   [Command]
   name = "AI_7"
   command = a, y, F, a, x, a, F, b
   time = 1
   
   [Command]
   name = "AI_8"
   command = a, a, b, y, x, B, x
   time = 1
   
   [Command]
   name = "AI_9"
   command = x, x, a, F, F, b, D
   time = 1
   
   [Command]
   name = "AI_10"
   command = x, x, a, F, y, a, a, F
   time = 1
   
   [Command]
   name = "AI_11"
   command = a, b, a, x, a, y, a
   time = 1
   
   [Command]
   name = "AI_12"
   command = b, y, a, F, y, a, x
   time = 1
   
   [Command]
   name = "AI_13"
   command = x, a, y, y, x, B, B
   time = 1
   
   [Command]
   name = "AI_14"
   command = a, F, F, x, B, F, x
   time = 1
   
   [Command]
   name = "AI_15"
   command = y, x, b, b, a, x, y
   time = 1

Activation Part 2

This sctrl should be placed directly under the title [statedef -1]. The purpose of this code is to set variable 59 to a value of 1 when ever the computer performs one of the [command]s listed above. Later on we'll create code that basically says "when var(59) = 1 activate the A.I." Now if your character is already using var(59) for another purpose then you will need to chose a different number.

   [State -1, AI]
   type = VarSet
   trigger1 = command = "AI_1"
   trigger2 = command = "AI_2"
   trigger3 = command = "AI_3"
   trigger4 = command = "AI_4"
   trigger5 = command = "AI_5"
   trigger6 = command = "AI_6"
   trigger7 = command = "AI_7"
   trigger8 = command = "AI_8"
   trigger9 = command = "AI_9"
   trigger10 = command = "AI_10"
   trigger11 = command = "AI_11"
   trigger12 = command = "AI_12"
   trigger13 = command = "AI_13"
   trigger14 = command = "AI_14"
   trigger15 = command = "AI_15"
   v = 59
   value = 1

(Hint: Don't confuse [Statedef -1] which is the main statedef in the CMD file with [state -1] which is the title for one of many sctrls in the CMD file.)

Details

Now that you have set up a way for the engine to detect if the computer is controlling the character or not, you can make a series of sctrls to tell the computer when to perform each statedef. Below is an explanation of how a variety of codes could work.

The most important part of this code are the Triggers. Take note that each code contains the same line 'triggerall = (roundstate = 2) && (var(59) != 0)'. This simply means that the move will only work when the players are both in a fighting state and when the computer's A.I. has been activated. There is also always a line that states 'triggerall = (Ctrl)' which means the character has to be in a position to control their character (not bring thrown or hit). For more details refer to List of Triggers.

A.I. Guarding

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0) 
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = S)   ;P2 is attacking, character is standing
   trigger1 = p2bodydist X <= 250                               ;P2 is less than or equal to 250 away on the x-axis,
   trigger1 = random <= 799                                     ;perform this move 79% of the time*
   value = 130                                                  ;change to [Statedef 130] which is standing block
   
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0) 
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = C)   ;P2 is attacking, character is standing
   trigger1 = p2bodydist X <= 250                               ;P2 is less than or equal to 250 away on the x-axis,
   trigger1 = random <= 799                                     ;perform this move 79% of the time*
   value = 131                                                  ;change to [Statedef 131] which is jumping block
   
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0) 
   triggerall = (Ctrl) && (p2movetype = A) && (statetype = A)   ;P2 is attacking, character is standing
   trigger1 = p2bodydist X <= 250                               ;P2 is less than or equal to 250 away on the x-axis,
   trigger1 = random <= 799                                     ;perform this move 79% of the time*
   value = 132                                                  ;change to [Statedef 132] which is crouching block


(*Hint: Although this 'Random' trigger says to activate this move 79% of time time, it will still not activate unless all the other trigger's conditions are met as well. For more details refer to List of Triggers.)

A.I. Normal Attacks

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && ((statetype = S)                      ;character is standing
   trigger1 = p2bodydist X <= 20                                ;P2 is less than or equal to 20 away on the x-axis,
   trigger1 = random <= 750                                     ;perform this move 75% of the time
   value = 200                                                  ;change to [Statedef 200] which is light punch**

(**Hint: This code can be repeated multiple times in the CMD file, just change the 'value' to a different [Statedef] each time. Also remember to change the 'statetype' to A or C for Air or Crouch attacks respectivly.)

A.I. Combo

This type of code will require some insight as to how the character should act. The point of this specific code shown below is to make the character follow up a jump attack with crouch hard kick.

   [State -1] 
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (p2movetype = H)                       ;P2 has been hit
   trigger1 = (p2bodydist X <= 25)                               ;close to opponent
   trigger1 = Prevstateno = 1400                                 ;falling from air attack
   trigger1 = random <= 750                                      ;perform this move 75% of the time
   value = 450                                                   ;change to [Statedef 450] which is crouch hard kick

Another common combo would be to Super Jump following a 'launcher' attacks.

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   trigger1 = stateno = 420                                      ;character is doing a crouch hard punch which is a launcher
   trigger1 = movehit = 1                                        ;move has connected (P2 was hit)
   trigger1 = random <= 750                                      ;perform this move 75% of the time
   value = 7000                                                  ;change to [Statedef 7000] which is a super jump

A.I. Special Attacks

Below is a variation of the code, used for a ground projectile.

   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   triggerall = random = [0,100]                                  ;performed 10% of the time***
   trigger1 = p2bodydist x >= 130                                 ;character is futher than 130 distance
   trigger1 = prevstateno != 5120                                 ;character is not in [Statedef 5120] which is "getting up"
   trigger1 = p2movetype != H                                     ;P2 has not been hit
   trigger1 = statetype != A                                      ;character is not jumping
   value = 1000                                                   ;change to [Statedef 1000] which is throwing a projectile

(***Hint: This version of 'Random' means that the move is only performed while a number between 0 and 100 is chosen from a range of 0 through 999. In essence, the move is performed 10% of the time, but durring a different 10% than a move with 'random= [101,200] or random = [201,300])


Here is some code for anti-air move like a Shoryuken.

   ;Hard Shoryuken following fireball with opponent jumping over fireball
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl) && (Statetype = S)
   trigger1 = random = [0,400]                                ;performed 40% of the time
   trigger1 = p2bodydist x <= 50                              ;character is closer than 50 distance
   trigger1 = p2movetype != H                                 ;P2 has not been hit
   trigger1 = statetype != A                                  ;character is not jumping
   trigger1 = (prevstateno = 1000) || (prevstateno = 1020)    ;character was in [Statedef 1000] or [Statedef 1020] (both projectiles)
   value = 1320                                               ;change to [Statedef 1320] which is a shoryuken****
   ;Light Shoryuken when the opponent is jumping close
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   trigger1 = random = [0,400]                                ;performed 40% of the time
   trigger1 = p2bodydist x <= 50                              ;character is closer than 50 distance
   trigger1 = p2statetype = A                                 ;P2 in jumping
   trigger1 = statetype != A                                  ;character is not jumping
   value = 1300                                               ;change to [Statedef 1300] which is a shoryuken****

(****Hint: These are two great examples of bringing strategy into the A.I. The Hard Shoryuken is only being used when the opponent is jumping over a fireball and thus more vulnerable while the Light Shoryuken is only being used when the opponent is just simply jumping which menas they may be less vulnerable. The Hard Shoryuken does more damage but the Light Shoryuken has a swifter recovery time so if the attack misses your character will not be an easy target to a counter attack.)

A.I. Hyper Attempt

By now you probably have a good idea of how this code works. Let's do one more, particularly a Hyper called Shinku Hadouken.

   ;Shinku Hadouken
   [State -1]
   type = ChangeState
   triggerall = (roundstate = 2) && (var(59) != 0)
   triggerall = (Ctrl=1) && (Statetype = S)
   triggerall = p2statetype != L                              ;P2 is not lieing down
   triggerall = stateno < 3000                                ;Add to avoid chaining hypes*****
   trigger1 = prevstateno != 5120                             ;character is not in [Statedef 5120] which is "getting up"
   trigger1 = statetype != A                                  ;character is not jumping
   trigger1 = p2bodydist x >= 150                             ;P2's distance is greater than 150
   trigger1 = power >= 1000                                   ;Hyper Bar has at least 1000 power
   trigger1 = random = [0,300]                                ;Perform this move 30% of the time
   value = 3000

(*****Hint: In a typical mugen character, [statedef] 0 through 999 are normal states, 1000 through 1999 are special states, 3000 through 3999 are hyper states and 5000 through 5999 are get hit states. By stating that this move can only be performed while the character is in a [statedef] less than 3000 then your basically saying this move can not be performed during another hyper or while your character is getting hit.)

Personal tools
Infinity Network