News:

MFG's Character of the Month: September 2026 Voting

Main Menu

Coding A.I

Started by mkfreak89, June 03, 2020, 08:57:32 PM

Previous topic - Next topic

mkfreak89

Hi everyone, i am working on my project and adding new special moves to Characters, while i am in able to give Characters new moves i cant seem to understand how to make the A.I. perform these moves more often when i fight against them. Any help would be aprecciated.

Nep Heart

 The chances of an AI performing specific actions is very much dependent on not only the values of random triggers, but the ordering of their changestates since MUGEN parses state controllers from top to bottom (therefore, AI changestates that are higher up are more likely to occur. If you've seen an AI block too much, for example, it may be due to their guard changestate being placed too high). There's other major nuances such as conditions that will allow a changestate to occur (i.e.: p2dist/p2bodydist, what statetype and movetype P2 is in, stateno that P1 and/or P2 are in, etc) that will also. There is no such thing as a universal method in achieving this, it's a very trial and error kind of thing that will have you spend hours testing frequency of how the AI chooses actions.

mkfreak89

Quote from: Nep Heart on June 03, 2020, 09:10:10 PM
The chances of an AI performing specific actions is very much dependent on not only the values of random triggers, but the ordering of their changestates since MUGEN parses state controllers from top to bottom (therefore, AI changestates that are higher up are more likely to occur. If you've seen an AI block too much, for example, it may be due to their guard changestate being placed too high). There's other major nuances such as conditions that will allow a changestate to occur (i.e.: p2dist/p2bodydist, what statetype and movetype P2 is in, stateno that P1 and/or P2 are in, etc) that will also. There is no such thing as a universal method in achieving this, it's a very trial and error kind of thing that will have you spend hours testing frequency of how the AI chooses actions.

Could you give me any example of what i need to change in order to have the A.I use that move more often as all the others moves it uses. Maybe copy paste something here and explain it a bit more.
As far as i know there has to be some kind of random number which you can set up to make the char use the move more likely or less, but i just cant figure it out as for now.

Nep Heart

 Not really, no, because it varies by each character, hence why I said no universal standard exists. I did give you a very basic example, however, such as guard AI chantestates will make an AI block too much if the changestate is too high up.

I mostly draw from Muteki's guide of AI coding, which generally has AI changestate order in statedef -1 look something like this.

Spoiler (click to show)
PrevStateNo (including 120-159 and 5000-5270, and in relation to throws
When in Guarding Distance
When the enemy is knocked down and the player is on the ground
When the enemy is knocked down and the player is in the air
When the enemy is in guardstun on the ground
Ground Combos
When the enemy is in guardstun in the air
Air whiff punish
Juggles
Counterpoking
Grounded movement
And everything else

If you want a character to perform something more often, just increase the value of their random triggers and put that specific AI changestate higher in statedef -1. Likewise, if you want an AI to perform something less frequently, just put the changestate lower in the statedef -1 ordering and lower its random value. Trust me, there is no shortcut, it takes me 1 to 2 months to actually complete an AI and I've been making AI since June of last year, although the result does end up making them particularly brutal to deal with.

mkfreak89

Quote from: Nep Heart on June 03, 2020, 09:37:51 PM
Not really, no, because it varies by each character, hence why I said no universal standard exists. I did give you a very basic example, however, such as guard AI chantestates will make an AI block too much if the changestate is too high up.

I mostly draw from Muteki's guide of AI coding, which generally has AI changestate order in statedef -1 look something like this.

Spoiler (click to show)
PrevStateNo (including 120-159 and 5000-5270, and in relation to throws
When in Guarding Distance
When the enemy is knocked down and the player is on the ground
When the enemy is knocked down and the player is in the air
When the enemy is in guardstun on the ground
Ground Combos
When the enemy is in guardstun in the air
Air whiff punish
Juggles
Counterpoking
Grounded movement
And everything else

If you want a character to perform something more often, just increase the value of their random triggers and put that specific AI changestate higher in statedef -1. Likewise, if you want an AI to perform something less frequently, just put the changestate lower in the statedef -1 ordering and lower its random value. Trust me, there is no shortcut, it takes me 1 to 2 months to actually complete an AI and I've been making AI since June of last year, although the result does end up making them particularly brutal to deal with.

Yes this is what i actually meant, i am a beginner when it comes to coding, but here is the part of the move which i would like the A.I to perform more often when fighting against me, please show me what i need to change here as i do not really see any "statedef - 1" or "random".



;========================================

[Statedef 1119]; Butterfly Kick
type    = S
movetype= A
physics = N
juggle  = 4
anim = 1119
Velset = 0, 0
sprpriority = 2
ctrl = 0


[State 2000, 2]
type = Varset
trigger1 = time = 0
v = 11
value = 0

[State 2000, 2]
type = Varset
trigger1 = backedgebodydist < 12
v = 11
value = 1

[State 2000, 0.5]
type = Playsnd
trigger1 = time = 0
value = 4,13
volumescale = 200
channel = 0

[State 2000, 0.5]
type = Playsnd
trigger1 = time = 0
value = 999,0
volumescale = 200
channel = 0


[State 2000, 0.5]
type = Playsnd
trigger1 = movecontact
value = 4,19
volumescale = 200
persistent = 0

[State 2000, 2]
type = Veladd
trigger1 = animelem = 3
x = 10

[State 600, 1.5]
type = varset
trigger1 = animelem = 3
fv = 2
value = 1
ignorehitpause = 1

[State 600, 1.5]
type = varset
trigger1 = animelemtime(3) > 4
fv = 2
value = fvar(2)*0.96875
ignorehitpause = 1

[State 2, Roundhouseblood]
type = Helper
triggerall = movehit
trigger1 = anim = 1119
triggerall = numhelper(28) < 1
ID = 28
stateno = 27
postype = p1
persistent = 0
ignorehitpause = 1



[State 2000, 2]
type = Veladd
trigger1 = animelemtime(3) > 4
trigger1 = vel x > 6.017181396484375
x = -0.3125*fvar(2)

[State 2000, 2]
type = Veladd
trigger1 = animelemtime(3) > 0 && animelemtime(6) < 0
trigger1 = enemy,backedgebodydist < 3
trigger1 = p2bodydist x < 12 && p2statetype = C && !movecontact
x = -1.265

[State 2000, 2]
type = Velset
trigger1 = movehit
x = 4

[State 2000, 2]
type = Velset
trigger1 = moveguarded
x = 0


[State 1050, 4]
type = HitDef
trigger1 = !movecontact
trigger1 = p2statetype != C || p2stateno = [120,159]
attr = S, NA
damage    = 220,30
animtype  = back
air.animtype  = Back
hitflag = MAF
guardflag = HL
priority = 7
pausetime = 0, 2
sparkno = -1
guard.sparkno = -1
sparkxy = 18,-60
hitsound   = 5,0
guardsound = 5,14
ground.type = High
ground.slidetime = 12
ground.hittime  = 12
guard.velocity = 0
ground.velocity = ifelse(var(11) = 0,-8,-4),-6
air.velocity = ifelse(var(11) = 0,-8,-4),-6
yaccel = 0.375
guard.slidetime = 12              ;Values for guarded attack (def: ground.slidetime)
guard.ctrltime = 5               ;Time to regain control after guard (def: guard.slidetime)
guard.dist = 120
kill       = (Var(9) = 0)
fall.kill  = (Var(9) = 0)
guard.kill = (Var(9) = 0)
envshake.freq = 90
envshake.time = 12
envshake.ampl = 6
hitonce = 1


[State 2000, 0.5]
type = targetvelset
trigger1 = moveguarded = [1,12]
x = -2
ignorehitpause = 1

[State 181, DIED]
type = statetypeset
trigger1 = moveguarded > 12 || p2dist x < 0
trigger2 = animelem = 6 && p2stateno != [120,159]
trigger3 = animelem = 7
movetype = I

[State 1050, 7]
type = changeanim
trigger1 = moveguarded = 12
value = anim
elem = 7

[State 1050, 7]
type = playerpush
trigger1 = movehit || p2stateno = 5120
value = 0

[State 1050, 7]
type = selfstate
trigger1 = animtime = 0
value = 0
ctrl = 1

Nep Heart

 Well, first off, AI is usually coded in statedef -1/-2/-3 (most pos-WinMUGEN coders prefer statedef -1), not the actual positive states themselves unless they involve commands. AI is basically just substituting commands with AIlevel (or a var if you're using WinMUGEN). You might actually want to study how AIlevel works in other characters (like Infinite's or Sennou-Room's PotS-inspired characters), assuming you do MUGEN 1.0 and above. If you don't even know the very basics of AI, you might want to study that first before even attempting the creation of one.

beterhans

Quote from: mkfreak89 on June 03, 2020, 10:11:42 PM
Quote from: Nep Heart on June 03, 2020, 09:37:51 PM
Not really, no, because it varies by each character, hence why I said no universal standard exists. I did give you a very basic example, however, such as guard AI chantestates will make an AI block too much if the changestate is too high up.

I mostly draw from Muteki's guide of AI coding, which generally has AI changestate order in statedef -1 look something like this.

Spoiler (click to show)
PrevStateNo (including 120-159 and 5000-5270, and in relation to throws
When in Guarding Distance
When the enemy is knocked down and the player is on the ground
When the enemy is knocked down and the player is in the air
When the enemy is in guardstun on the ground
Ground Combos
When the enemy is in guardstun in the air
Air whiff punish
Juggles
Counterpoking
Grounded movement
And everything else

If you want a character to perform something more often, just increase the value of their random triggers and put that specific AI changestate higher in statedef -1. Likewise, if you want an AI to perform something less frequently, just put the changestate lower in the statedef -1 ordering and lower its random value. Trust me, there is no shortcut, it takes me 1 to 2 months to actually complete an AI and I've been making AI since June of last year, although the result does end up making them particularly brutal to deal with.

Yes this is what i actually meant, i am a beginner when it comes to coding, but here is the part of the move which i would like the A.I to perform more often when fighting against me, please show me what i need to change here as i do not really see any "statedef - 1" or "random".



;========================================

[Statedef 1119]; Butterfly Kick
type    = S
movetype= A
physics = N
juggle  = 4
anim = 1119
Velset = 0, 0
sprpriority = 2
ctrl = 0


[State 2000, 2]
type = Varset
trigger1 = time = 0
v = 11
value = 0

[State 2000, 2]
type = Varset
trigger1 = backedgebodydist < 12
v = 11
value = 1

[State 2000, 0.5]
type = Playsnd
trigger1 = time = 0
value = 4,13
volumescale = 200
channel = 0

[State 2000, 0.5]
type = Playsnd
trigger1 = time = 0
value = 999,0
volumescale = 200
channel = 0


[State 2000, 0.5]
type = Playsnd
trigger1 = movecontact
value = 4,19
volumescale = 200
persistent = 0

[State 2000, 2]
type = Veladd
trigger1 = animelem = 3
x = 10

[State 600, 1.5]
type = varset
trigger1 = animelem = 3
fv = 2
value = 1
ignorehitpause = 1

[State 600, 1.5]
type = varset
trigger1 = animelemtime(3) > 4
fv = 2
value = fvar(2)*0.96875
ignorehitpause = 1

[State 2, Roundhouseblood]
type = Helper
triggerall = movehit
trigger1 = anim = 1119
triggerall = numhelper(28) < 1
ID = 28
stateno = 27
postype = p1
persistent = 0
ignorehitpause = 1



[State 2000, 2]
type = Veladd
trigger1 = animelemtime(3) > 4
trigger1 = vel x > 6.017181396484375
x = -0.3125*fvar(2)

[State 2000, 2]
type = Veladd
trigger1 = animelemtime(3) > 0 && animelemtime(6) < 0
trigger1 = enemy,backedgebodydist < 3
trigger1 = p2bodydist x < 12 && p2statetype = C && !movecontact
x = -1.265

[State 2000, 2]
type = Velset
trigger1 = movehit
x = 4

[State 2000, 2]
type = Velset
trigger1 = moveguarded
x = 0


[State 1050, 4]
type = HitDef
trigger1 = !movecontact
trigger1 = p2statetype != C || p2stateno = [120,159]
attr = S, NA
damage    = 220,30
animtype  = back
air.animtype  = Back
hitflag = MAF
guardflag = HL
priority = 7
pausetime = 0, 2
sparkno = -1
guard.sparkno = -1
sparkxy = 18,-60
hitsound   = 5,0
guardsound = 5,14
ground.type = High
ground.slidetime = 12
ground.hittime  = 12
guard.velocity = 0
ground.velocity = ifelse(var(11) = 0,-8,-4),-6
air.velocity = ifelse(var(11) = 0,-8,-4),-6
yaccel = 0.375
guard.slidetime = 12              ;Values for guarded attack (def: ground.slidetime)
guard.ctrltime = 5               ;Time to regain control after guard (def: guard.slidetime)
guard.dist = 120
kill       = (Var(9) = 0)
fall.kill  = (Var(9) = 0)
guard.kill = (Var(9) = 0)
envshake.freq = 90
envshake.time = 12
envshake.ampl = 6
hitonce = 1


[State 2000, 0.5]
type = targetvelset
trigger1 = moveguarded = [1,12]
x = -2
ignorehitpause = 1

[State 181, DIED]
type = statetypeset
trigger1 = moveguarded > 12 || p2dist x < 0
trigger2 = animelem = 6 && p2stateno != [120,159]
trigger3 = animelem = 7
movetype = I

[State 1050, 7]
type = changeanim
trigger1 = moveguarded = 12
value = anim
elem = 7

[State 1050, 7]
type = playerpush
trigger1 = movehit || p2stateno = 5120
value = 0

[State 1050, 7]
type = selfstate
trigger1 = animtime = 0
value = 0
ctrl = 1

this is move not AI

AI is in def -1 which is your command.def or command.cmd file

NotAGoodName

Ok.  I'm not going to dig through another character and try to reverse engineer it's AI.  But I'll give a brief breakdown of how an AI move can (should) work.

Basically, it's just like a normal command state, but written to work for the AI.  Some coders even combine the two into one huge mess.  I use the AILevel variable built into Mugen 1.x, but a lot of coders are still using the old winmugen style AI.  The most common AI variable then is var(59).

So, here's a really command state for a move.  It's just a basic anti-air throw.
[State -1, AAT]
type = ChangeState
value = 299
triggerall = command = "Butt"
triggerall = statetype != A
trigger1 = ctrl
trigger2 = movehit
trigger2 = stateno = [200,400]


If I do the command "butt" (dp+K), I'm not in the air, and I have ctrl (or I just hit with weak punch or weak kick), then the move will execute.  Why should an anti-air throw be cancellable?  I dunno.  Why not?

So the AI version is going to have all of the same triggers, but the AI doesn't need to check for a command input.  Instead, it will activate based on the difficulty level and location of the opponent.

[state -2, AI AAT]
type = ChangeState
value = 299
triggerall = (AILevel > 0) && (roundstate = 2)
triggerall = random < ((AILevel * (AILevel / 2.75)) + (ifelse((p2bodydist x < 30),100,50)) + (ifelse((enemynear, pos y < -45),100,50)))
triggerall = statetype != A
triggerall = p2dist y < -45
trigger1 = ctrl
trigger2 = stateno = [200,400]
trigger2 = movehit


Ok, so I check if the character is AI controlled and the match is actually going.  I should probably have added more failsafe variable checks, but whatever.  Random is going to generate a number between 0 and 255 (or something like that).  If the sum total of all of those things is greater than whatever random number, the move can execute.  Long story short, on high mugen difficulty, my AI is constantly trying to grab any opponent that is in reach of the air throw.  There is another check for p2dist y to make sure that the AI isn't going to use the move when it won't hit, even if the random generated number is 0.

Nep Heart

 As I've mentioned before, changestate priority (the order in which changestates are placed in statedef -1) also factors in what choices an AI will do more or less frequently because of how MUGEN's parser works (reads from top to bottom), and considering random resets every tick in statedef -1, the higher up changestates will happen more often when factored, more so if they have higher random values than the ones below.

If you've only started on the AI, chances are, it will perform those few actions pretty frequently because not all the changestates are there yet. At any rate, I would suggest adding more triggers to define conditions against P2 so the AI isn't doing reckless stuff like trying to grab P2 while they attempt a hyper move or attempt to block throws for example.

Here is an example of how I define conditions for air throwing that I have in my Akari Ichijou's AI. I'll place notes in arrows to indicate the purpose of each relevant trigger.

Spoiler (click to show)
[State -1, AI Air Throw]
type = ChangeState
value = 830
triggerall = AIlevel && numenemy
triggerall = !ishelper
triggerall = roundstate = 2
triggerall = enemy,hitdefattr != SCA,AT <---- Will not attempt air throw if enemy is also attempting throw.
triggerall = statetype = A && enemy,statetype = A <---- Will only attempt air throw if the enemy is also in the air.
triggerall = (p2dist x = [0,30+30*(vel x > 0)]) <---- Will attempt air throw at a slightly farther horizontal distance if moving forward. Reason for lack of p2dist y is because the air throw has Akari fall downwards with a separate hitdef if the throw whiffs.
triggerall = (random <= 200+133*(backedgedist < frontedgedist) || NumExplod(10381)*(AILevel**2)/64) && var(25) < 2 Randomness for air throw chances increases if Akari's back is closer to a corner or if Akari's last move hit a reversaldef (the explod determines this condition). Will also only attempt air throws in specific combos as var(25) is my AI combo variable.
trigger1 = (ctrl || (stateno = [120,132])) && (enemy,movetype = I || (prevstateno = [5201,5210]) || enemy,ctrl = 0) <----- Will attempt air throw during teching, if the enemy is idle or has no control.
trigger2 = stateno = 420 && movehit && (power < 1000 && random%10 || p2life <= 50) <----- If that particular air normal hits, she will attempt an air throw if her power is less than 1000 or if P2 has 50 or less life remaining.