collapse

Author Topic: [TUTO] Mugen AI basic tutorial  (Read 906 times)

0 Members and 1 Guest are viewing this topic.

Offline O Ilusionista

  • Since 1999 and kicking :)
  • IMT Content Architect
  • *
  • Posts: 12459
  • Country: Brazil br
  • Last Login:Today at 01:17:37 AM
  • OpenBOR & Mugen addicted
    • BMT - Brazil Mugen Team
    • Email
[TUTO] Mugen AI basic tutorial
« on: July 13, 2020, 04:18:33 PM »
Mugen Artificial Intelligence short tutorial
By O Ilusionista - 2020.07.13

Note: There are more ways to control this, different triggers to use, etc. This is one of the methods and the method I use on my characters, with some extra things here and there.

AI got easier in Mugen 1.0 and beyond, since now we have a trigger to identify that the character is being controlled by the CPU (AiLevel)

AI is all about to tell the engine to do what you want -  in other words, you just set the desired triggers and it will execute it.
To make it non-cheap is what makes it hard to do.

For example, take a look at those block of codes from RMM, for to make the character to block:
Quote
;--|-AI Defense-|-----------------------------------------------------------
[State -1, AI Defense]
type = ChangeState
triggerall = (roundstate = 2) && (AiLevel) 
triggerall = (Ctrl) && (p2movetype = A) && (statetype = S)
trigger1 = (p2bodydist X <= 250) && random <= (800 * (AiLevel ** 2 / 64.0))
value = 130

[State -1, AI Defense]
type = ChangeState
triggerall = (roundstate = 2) && (AiLevel)
triggerall = (Ctrl) && (p2movetype = A) && (statetype = C)
trigger1 = (p2bodydist X <= 250) && random <= (800 * (AiLevel ** 2 / 64.0))
value = 131

[State -1, AI Defense]
type = ChangeState
triggerall = (roundstate = 2) && (AiLevel)
triggerall = (Ctrl) && (p2movetype = A) && (statetype = A)
trigger1 = (p2bodydist X <= 250) && random <= (800 * (AiLevel ** 2 / 64.0))
value = 132

Let me break down the code:

The first line is what triggers the AI
Quote
triggerall = (roundstate = 2) && (AiLevel) 
Roundstate = 2 means "while the fight is going on" (read the manual about Roundstate)
AiLevel is what tells you that the character is being controlled by the AI.

You will see that I use the codes between "()", this is to help the engine to check then faster/easily, since all the code between () must be valid.
So if AiLevel is great than 0, (AiLevel) will be TRUE. Its the same than writing "AiLevel >0", but instead of integer numbers, we are using boolean logic (1 = True, 0 FALSE) - which is faster than integer.

Quote
triggerall = (Ctrl) && (p2movetype = A) && (statetype = S)
(Ctrl) = The character must have control AND (&&)
(p2movetype = A) = P2movetype (the enemy who is attacking) should be an ATTACK
(statetype = S) = the character should be in STANDING state

Quote
trigger1 = (p2bodydist X <= 250) && (random <= 800)
(p2bodydist X <= 250) = P2 body (not only the axis) X distance needs do be equal or less than 250 (We could use "inguarddist" here too)
"random <= 800"  (so the random change should be less than 800 - the engine will calculate it from 0 to 1000)

We can make it more complex if we add the AiLevel check / modifier
Quote
trigger1 = (p2bodydist X <= 250) && random <= (800 * (AiLevel ** 2 / 64.0))

random <= (800 * (AiLevel ** 2 / 64.0)) = This line looks more complicated, but we are using POTS method to calculate the AiLevel.
It would be the same of writing "random <= 800"  (so the random change should be less than 800 - the engine will calculate it from 0 to 1000, and remember Mugen will only use positive values) but we are adding a multiplier for to make it scalable, so it will take the game AiLevel setting in count

Quote
value = 130
In this line, I am telling the engine to change the character randomly to Mugen Default Standing Guard Start state.

NOTE 2: Pay attention that the first two lines are TRIGGERALL, while the third one is a TRIGGER1.
Everything in TRIGGERALL is mandatory to be valid. If it's not, Mugen will skip* all other triggers
(it will still reads it for synthax errors, but won't parse it)
Read more about it here

NOTE 3: we have a bad habit of making the triggers to look more compact, as it would be faster to read by the engine, like this:
Quote
triggerall = (roundstate = 2) && (AiLevel)  && (Ctrl) && (p2movetype = A) && (statetype = S)
But that is not true, because the engine will read the first block and calculate if its valid (roundstate=2 is TRUE or FALSE), then proceeds to the next condition (AiLevel), and all others until the end of the line and ONLY WHEN IT FINISHES the line, it will check if ALL conditions are true (and all needs to be true). If not, the engine will skip it.

But we should use a less elegant (graphic wise) but faster (coding wise) solution: each trigger in one line
Quote
triggerall = (roundstate = 2)
triggerall = (AiLevel)
triggerall = (Ctrl)
triggerall = (p2movetype = A)
triggerall = (statetype = A)
And why? Because if the first triggerall is false (roundstate is not 2), the engine will stop doing logic checks for the rest of this block code.
Remember that TRIGGERLALL needs to be valid, so if just one line is false, the rest doesn't care.

The other blocks are the same, just changing the check (and the state change) for C (crouching) and A (air) states.



Tags:
 


* IMT Facebook

Help us by Donating!

IMT Discord

Join us at our Discord! Click the image below!

* IMT Shoutbox

Sorry, this shoutbox does not exist.

* Recent Posts

* IMT Calendar

April 2024
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 [27]
28 29 30

SimplePortal 2.3.5 © 2008-2012, SimplePortal