Ryon Posted April 30, 2015 Posted April 30, 2015 Seravy's A.I. guide from the Mugen Wiki Contents 1 General Information 2 AI activation 2.1 AI activation for winmugen/beta mugen 2.2 AI activation for mugen 1.0 3 Coding AI moves 4 Common/System behavior 4.1 Guarding 4.2 Jumping 4.3 Walking General Information This guide is about coding custom AI for mugen. Custom AI means the character acts the way you program it to, and ignores the default "AI" of the engine completely. This is a very important part in characters because this is the way to make characters more intelligent, making the fight more challenging and interesting. The default "AI" doesn't know what each move is for, and just executes them randomly, more often at higher difficulty and less often on low. This however, makes the character look very dumb, because they don't know such basic things as the range and area of their attacks, so pretty often, they are punching the air, or even worse, use suicide attacks when they aren't supposed to. Creating a custom AI can prevent this kind of behavior, by telling exact rules about when and how to use the attacks. An AI consists of three parts: Activation, Commands, and common/system behavior. AI activation AI activation is the part where we decide when to turn the AI on or off. AI activation for winmugen/beta mugen Pre 1.0 mugen versions don't support custom AI directly, so activating an AI is only possible using workarounds. There were several workarounds for this, each having their own strengths and weaknesses. A quick list of the possible methods were Human Impossible commands Helper method XOR method Ishometeam method Winane's AI activation code combined all four together for optimal performance, however, it is pretty complicated and hard to understand. Improper, simplified implementation of the XOR or Helper methods can have false positives, so these methods are not recommended for beginners. Detecting the difficulty level in older mugen is impossible, so the AI will always fight on a pre-set level instead of what the player selected. Most character make it possible to select this level by directly editing a configuration file of the character, but considering how many characters you usually have in your mugen, changing difficulty level this way, one-by-one for every character is completely unreasonable. This is the main reason why winmugen is outdated, and not recommended: Being able to play on the desired difficulty level is a very basic feature, and the lack of it hurts gaming experience a lot. AI activation for mugen 1.0 Mugen 1.0 and above has a new trigger: AILevel that supports custom made AI properly. By using this trigger in your AI code parts directly, you can create an AI without an activation part or variables. However, doing so is not recommended, as it reduces flexibility a lot, and makes it much harder to scale your difficulty levels, or turn the AI on/off on special conditions when necessary. Generally, you'll need two variables for your AI activation. The first variable is the AI variable itself. If it is set to 0, your AI is off, and if it is 1, it is on. Other values can be used if you want multiple AI modes, like a special boss mode for example. The second variable is the difficulty variable. This variable is responsible in determining the chance for attacking: higher values would attack more often, while lower values attack less often, making the AI's reaction time slower, and closer to a human player's. The two can be stored in one variable (0= AI off, 1-1000 =AI on with difficulty chance stored) if you want to save variable space. Example code below, it needs to be placed into one of your minus states: var(59) = AI variable var(50) = Difficulty variable [State -1, AI ON] ; Turn the AI on when Type = VarSet TriggerAll = Var(59) < 1; it is not on yet and TriggerAll = RoundState=2 ; the fight has started and is not over yet and Trigger1 = AILevel>0 ; the computer is playing the character v = 59 value= 1 ; value of 1 will mean the AI is on Ignorehitpause=1 [State -1, AI OFF] ; Turn the AI off when Type=VarSet Trigger1=var(59)>0 ; it is on and Trigger1=RoundState!=2 ; the round is not started yet or is already over Trigger2=!IsHelper ; OR if we are a player, but Trigger2=AILevel=0 ; the computer is not in control v=59 value=0 ; value of 0 will mean the AI is off. values other than 0 and 1 are not used in this example, we have only one AI mode, the normal one. Ignorehitpause=1 [State -1] Type=VarSet Trigger1=1 var(50)=(AILevel=1)*3+(AILevel=2)*7+(AILevel=3)*16+(AILevel=4)*30+(AILevel=5)*58+(AILevel=6)*90+ (AILevel=7)*150+(AILevel=8)*300 Numbers here correspond to the chance for attacking from 1 to 1000. Higher number means less reaction time. Lower number means more. Linear distribution of difficulty (using AILevel*10 for example) is not recommended. Numbers below 10-15 will make the character attack rarely, making the AI play weaker than a human. These values are recommended for the first two (easy) difficulty levels. Numbers around 20-50 are causing the AI to fight more like a human player, attacks will usually have a bit of a reaction time, but generally, the AI will not stay idle for too long and will fight actively. Numbers over 50-100 will reduce the reaction time of the AI significantly, and 1000 completely eliminates it. 1000 will also make the AI perform the first matching attack in each situation unless coded otherwise. These values are recommended for hard (6-8) difficulty levels only, as the reaction time is way faster than what a human player has. Using numbers above 300 is not recommended, as it doesn't make the AI any harder, but it does make it more determined/easier to predict. Average reaction time in ticks for various var(50) values, assuming a situation when only one attack is matching the triggers and is available to use (the current tick not included): 1000 - 0, always attack immediately with the first matching attack 900 - 0.11 tick 800 - 0.25 tick 700 - 0.42 tick 600 - 0.66 tick 500 - 1 tick 400 - 1.5 ticks 300 - 2.33 ticks 200 - 4 ticks 100 - 9 ticks If we consider the human reaction time to be 1/6th of a second which is 10 ticks, then it is clearly visible that any values over 100 are way too fast against a human player for normal levels. Especially as in normal cases, multiple attacks are available for the AI, further reducing the reaction time: 2 available attacks mean half reaction time on average, three means a third, and 10 means a tenth of it only, so the zone over 100 is really meant for hard to impossible difficulty levels. As visible from this, there is basically no difference between values over 500 at all, so linear scaling fails the most in that area: the attacks get 0-1 tick of delay most of the time. Below 100, the reaction time increases non-linearly: 90 - 10.1 ticks 80 - 11.5 ticks 70 - 13.2 ticks 60 - 15.6 ticks 50 - 19 ticks 40 - 24 ticks 30 - 32 ticks 20 - 49 ticks 15 - 65 ticks 10 - 99 ticks 9 - 110 ticks 8 - 124 ticks 7 - 141 ticks 6 - 166 ticks 5 - 199 ticks 4 - 249 ticks 3 - 332 ticks 2 - 499 ticks 1 - 999 ticks making it an ideal range for easy and normal difficulty levels: values below 10 have a reaction time of an entire second to many seconds, while values over 15 have 1 second or less, making it ideal for normal difficulty. Note that characters having more attacks available per situation need slightly lower var(50) values than characters with fewer ones, so in most cases, only the half/third/fourth of this reaction time applies in reality for those situations. Overall, for easy levels, take numbers from the 1-15 interval, for normal, take ones from 10-50, and for hard, take from 50-200 as a general advice. Characters with more moves or better/more versatile moves will generally need lower values like 1-10 for easy, 10-30 for normal and 30-100 for hard. Do note that "reaction time" here means time spent doing nothing before deciding what attack to use, not time spent idle after deciding to use an attack. Also note that all of these are average values: since random is used, there is always a chance for any amount of reaction time from zero to infinite, but during a whole match duration, these even themselves out. To implement an AI that has a real, human like reaction time (delay between deciding on an attack and using it), a more complicated and advanced system is necessary, where you use a timer variable and buffer the attacks that need to be executed, although I don't see much of a reason to go that far: if you want your AI to mess up and use attacks at the wrong timing, you can do that in an easier way by adding low level specific triggers to your attacks, instead of simulating a reaction time. Coding AI moves This is the part where you tell the AI when and how they are supposed to use the moves available. It works pretty much the same way as for the player, except for the conditions themselves. They are changestates that need to activate when the AI wants to use the move, and are placed in state -1. They can be placed in state -3 as well, but placing them into -1 makes more sense. These are pretty much the AI equivalent of a human player's command input. First of all, while the AI is on, we must disable all human player commands from working. The engine spams player commands (this is how the built in AI of the engine works: it simulates commands coming from the keyboard), and we don't want these to have any effect on our character. To do this, add Triggerall=var(59)>0 to all of your regular command changestates. Then, to make the AI able to use the commands, you must make a copy of that changestate, remove the conditions limited to human players (this almost always only means the command="xxx" lines), and add new ones for the AI. An example: Type=Changestate Triggerall=command="super" Triggerall=power>=3000 Triggerall=Statetype=S Triggerall=life<=0.5*Lifemax Trigger1=ctrl Trigger2= Stateno=1000 Trigger2= Movehit value=4000 This is a command block for a human player, it describes a super move that can be used when at 3000 or more power, and below half of maximum life while standing and having control, or as a combo after an attack coded in state 1000. The AI equivalent would be Type=Changestate Triggerall=var(59)>0 ; Use this only if the AI is ON Triggerall=power>=3000 ; Move cost still applies to the AI Triggerall=Statetype=S ; Game rules still apply to the AI Triggerall=life<=0.5*Lifemax ; Game rules still apply to the AI. Removing this line would make the AI cheat by using the move with over half life left. Triggerall=abs(P2Bodydist X)<40 ; use this move only when the opponent is close enough. Moves usually don't hit the entire screen, so specifying the distance this way is necessary Triggerall=P2StateType=S; use it only if the opponent is standing. This way, we don't need to worry about the y position of the opponent, and we won't use it when the opponent is on the ground or is falling. Using other triggers in other cases like P2dist Y, enemynear,pos Y, P2Stateype!=L,!enemynear,hitfall, etc... might be necessary. Triggerall=!Inguarddist; Don't use it if in guard distance. We don't want to run into a hit and get our super interrupted. This line is unnecessary if the super cannot be interrupted by hits. Triggerall=random<var(50)*1.1; 1-1.5="" a="" ai="" and="" around="" attack="" attack.="" attacks="" attacks.="" be="" br="" by="" can="" chance="" combo="" controlled="" determines="" difficulty="" dodging="" easy="" for="" from="" higher="" how="" in="" is="" it="" level.="" likely="" line="" long="" lower="" most="" multiplier="" of="" on="" only="" or="" powerful="" recommended="" reduces="" s="" so="" starter="" t="" that="" the="" this="" to="" triggerall="AILevel>=3;" use="" used="" using="" value="" values="" want="" we="" what=""> Trigger1 = ctrl Trigger2 = Stateno=1000 Trigger2 = Movehit value=4000 You can also merge the player and the AI command activation into a single command block, like this: Type=Changestate Triggerall=power>=3000 Triggerall=Statetype=S Triggerall=life<=0.5*Lifemax Triggerall=ctrl || ((Stateno=1000) && movehit) Trigger1=var(59)=0; The AI is off Trigger1=command="super"; and the command in entered Trigger2=var(59)>0; or the AI is on Trigger2=abs(P2Bodydist X)<40; and all the AI conditions are true Trigger2=P2StateType=S Trigger2=!Inguarddist Trigger2=random<var(50)*1.1 Trigger2=AILevel>=3 value=4000</var(50)*1.1 If you code your AI using the same merged block for human and AI commands, updating conditions on the attack is easier. For example if you want to reduce the cost from 3000 to 2000, or update the attack so that is also works when used in the air, or want to add it as a combo after different attacks, you only need to change it in one place instead of two. This not just reduced your future work, but also eliminates a possible inconsistency: if you update one of them and forget about the other, you might end up with an attack that works under different conditions for the player than the AI unintentionally. Common/System behavior There are a few things a character do without using a move defined in the cmd, and these are: -Jumping -Guarding -Walking If we want to have control over these the way we have over normal attacks, we have to code for it. Guarding To make the AI guard properly, two steps are necessary. The first is a changestate in state -1 to enter the guard states when we want to. This one works well: [State -1] Type=Changestate Triggerall=Ingurddist; Guard when in guard distance Triggerall=var(59)>0; and the AI is on Triggerall=ctrl; and we have control Trigger1 = random< (var(50)*2+(AiLevel>=3)*30); chance is higher than for attacking, but not by too much. value=120 [State -1]; The engine will still guard by through pressing the back button, we need to disable that. Type=Assertspecial Triggerall=StateNo!=[120,160] Trigger1=var(59)>0 flag=noairguard flag2=nocrouchguard flag3=nostandguard Adding Trigger=!Inguarddist to AI attacks greatly helps against taking unnecessary hits, and increases chance of guarding the attack some ticks later if the guarding chance didn't trigger yet (but still fast enough against slower attacks).. Without that, the character will start to execute an attack, and end up getting hit too often, making the AI to dumb. This makes the AI behave like a player, the slower an attack is, the higher the chance that it will be guarded. Generally, you will want to have this line on all of your AI attacks except light punches or other very fast moves, or moves with invincibility. The other part of an AI guarding is keeping the AI in the guarding states long enough, and making it go to the appropriate one for each situation. You need to override all the guard states for that. If you don't want to change the conditions on which the AI changes from crouch to stand guarding or back, you can use the code below: ;--------------------------------------------------------------------------- ; GUARD (start) [Statedef 120] type = U ;Leave state type unchanged physics = U;Leave physics unchanged [State 120] Type=CtrlSet Trigger1=var(59)>0 value=0 [State 120, 1] type = ChangeAnim trigger1 = Time = 0 value = 120 + (statetype = C) + (statetype = A)*2 [State 120, 2] type = StateTypeSet trigger1 = Time = 0 && statetype = S physics = S [State 120, 3] type = StateTypeSet trigger1 = Time = 0 && statetype = C physics = C [State 120, 4] type = StateTypeSet trigger1 = Time = 0 && statetype = A physics = A [State 120, Hi to Lo] type = StateTypeSet triggerall = statetype = S trigger1 = var(59)=0 trigger1 = command = "holddown" trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 statetype = C physics = C [State 120, Lo to Hi] type = StateTypeSet triggerall = statetype = C trigger1 = var(59)=0 trigger1 = command!= "holddown" trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 statetype = S physics = S [State 120, 5] type = ChangeState trigger1 = AnimTime = 0 value = 130 + (statetype = C) + (statetype = A)*2 [State 120, Stop Guarding] type = ChangeState trigger1 = command!= "holdback" trigger1 = var(59)=0 trigger2 =!inguarddist value = 140 ;--------------------------------------------------------------------------- ; Stand guard (guarding) [Statedef 130] type = S physics = S [State 120] Type=CtrlSet Trigger1=var(59)>0 value=0 [State 130, 1] type = ChangeAnim trigger1 = Anim!= 130 value = 130 [State 130, Hi to Lo] type = ChangeState trigger1 = command = "holddown" trigger1 = var(59)=0 trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 value = 131 [State 130, Stop Guarding] type = ChangeState trigger1 = var(59)=0 trigger1 = command!= "holdback" trigger2 =!inguarddist value = 140 ;--------------------------------------------------------------------------- ; Crouch guard (guarding) [Statedef 131] type = C physics = C [State 120] Type=CtrlSet Trigger1=var(59)>0 value=0 [State 131, 1] type = ChangeAnim trigger1 = Anim!= 131 value = 131 [State 131, Lo to Hi] type = ChangeState trigger1 = command!= "holddown" trigger1 = var(59)=0 trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 value = 130 [State 131, Stop Guarding] type = ChangeState trigger1 = var(59)=0 trigger1 = command!= "holdback" trigger2 =!inguarddist value = 140 ;--------------------------------------------------------------------------- ; Air guard (guarding) [Statedef 132] type = A physics = N [State 120] Type=CtrlSet Trigger1=var(59)>0 value=0 [State 132, 1] type = ChangeAnim trigger1 = Anim!= 132 value = 132 [State 132, 2] type = VelAdd trigger1 = 1 y = Const(movement.yaccel) [State 132, 3] type = VarSet trigger1 = 1 sysvar(0) = (pos y >= 0) && (vel y > 0) [State 132, 4] type = VelSet trigger1 = sysvar(0) y = 0 [State 132, 5] type = PosSet trigger1 = sysvar(0) y = 0 [State 132, 6] type = ChangeState trigger1 = sysvar(0) trigger1 = command = "holdback" || (var(59)>0) trigger1 = inguarddist value = 130 [State 132, 7] type = ChangeState trigger1 = sysvar(0) value = 52 [State 132, Stop Guarding] type = ChangeState trigger1 = var(59)=0 trigger1 = command!= "holdback" trigger2 =!inguarddist value = 140 ;--------------------------------------------------------------------------- ; Stand guard hit (shaking) [Statedef 150] type = S movetype= H physics = N velset = 0,0 [State 150, 1] type = ChangeAnim trigger1 = 1 value = 150 [State 150, 2] type = ChangeState trigger1 = HitShakeOver value = 151 + 2*(StateType=C) [State 120, Hi to Lo] type = StateTypeSet triggerall = statetype = S trigger1 = var(59)=0 trigger1 = command = "holddown" trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 statetype = C physics = C [State 120, Lo to Hi] type = StateTypeSet triggerall = statetype = C trigger1 = var(59)=0 trigger1 = command!= "holddown" trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 statetype = S physics = S [State 150, 3] type = ForceFeedback trigger1 = time = 0 waveform = square time = 3 ;--------------------------------------------------------------------------- ; Stand guard hit (knocked back) [Statedef 151] type = S movetype= H physics = S anim = 150 [State 151, 1] type = HitVelSet trigger1 = Time = 0 x = 1 [State 151, 2] type = VelSet trigger1 = Time = GetHitVar(slidetime) trigger2 = HitOver x = 0 [State 151, 3] type = CtrlSet trigger1 = Time = GetHitVar(ctrltime) trigger1 = var(59)=0 value = 1 [State 120, Hi to Lo] type = StateTypeSet triggerall = statetype = S trigger1 = var(59)=0 trigger1 = command = "holddown" trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 statetype = C physics = C [State 120, Lo to Hi] type = StateTypeSet triggerall = statetype = C trigger1 = var(59)=0 trigger1 = command!= "holddown" trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 statetype = S physics = S [State 151, 4] type = ChangeState trigger1 = HitOver value = 130 ctrl =!var(59) ;--------------------------------------------------------------------------- ; Crouch guard hit (shaking) [Statedef 152] type = C movetype= H physics = N velset = 0,0 [State 152, 1] type = ChangeAnim trigger1 = 1 value = 151 [State 152, 3] type = ChangeState trigger1 = HitShakeOver value = 151 + 2*(StateType=C) [State 120, Hi to Lo] type = StateTypeSet triggerall = statetype = S trigger1 = var(59)=0 trigger1 = command = "holddown" trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 statetype = C physics = C [State 120, Lo to Hi] type = StateTypeSet triggerall = statetype = C trigger1 = var(59)=0 trigger1 = command!= "holddown" trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 statetype = S physics = S [State 152, 4] type = ForceFeedback trigger1 = time = 0 waveform = square time = 4 ;--------------------------------------------------------------------------- ; Crouch guard hit (knocked back) [Statedef 153] type = C movetype= H physics = C anim = 151 [State 153, 1] type = HitVelSet trigger1 = Time = 0 x = 1 [State 153, 2] type = VelSet trigger1 = Time = GetHitVar(slidetime) trigger2 = HitOver x = 0 [State 151, 3] type = CtrlSet trigger1 = Time = GetHitVar(ctrltime) trigger1 = var(59)=0 value = 1 [State 120, Hi to Lo] type = StateTypeSet triggerall = statetype = S trigger1 = var(59)=0 trigger1 = command = "holddown" trigger2 = var(59)>0 trigger2 = (abs(P2Dist X)>120) || (P2MoveType=H) || (P2StateType=C) trigger2 = P2StateType!=A trigger2 = AILevel>=3 statetype = C physics = C [State 120, Lo to Hi] type = StateTypeSet triggerall = statetype = C trigger1 = var(59)=0 trigger1 = command!= "holddown" trigger2 = Var(59) > 0 trigger2 = p2statetype = A trigger2 = abs(P2BodyDist X)=3 statetype = S physics = S [State 153, 4] type = ChangeState trigger1 = HitOver value = 131 ctrl =!var(59) ;--------------------------------------------------------------------------- ; Air guard hit (shaking) [Statedef 154] type = A movetype= H physics = N velset = 0,0 [State 154, 1] type = ChangeAnim trigger1 = 1 value = 152 [State 154, 2] type = ChangeState trigger1 = HitShakeOver value = 155;AGUARDHIT2 [State 154, 3] type = ForceFeedback trigger1 = time = 0 waveform = square time = 4 ;--------------------------------------------------------------------------- ; Air guard hit (knocked away) [Statedef 155] type = A movetype= H physics = N anim = 152 [State 155, 1] type = HitVelSet trigger1 = Time = 0 x = 1 y = 1 [State 155, 2] type = VelAdd trigger1 = 1 y = Const(movement.yaccel) [State 151, 3] type = CtrlSet trigger1 = Time = GetHitVar(ctrltime) trigger1 = var(59)=0 value = 1 [State 155, 4] type = VarSet trigger1 = 1 sysvar(0) = (pos y >= 0) && (vel y > 0) [State 155, 5] type = VelSet trigger1 = sysvar(0) y = 0 [State 155, 6] type = PosSet trigger1 = sysvar(0) y = 0 [State 155, 6] type = ChangeState trigger1 = sysvar(0) trigger1 = command = "holdback" || var(59)>0 trigger1 = inguarddist value = 130 [State 155, 7] type = ChangeState trigger1 = sysvar(0) value = 52 Jumping Making the AI jump is as simple as guarding, just add a changestate to your -1 pointing to the common jump state. [state -1] Type=changestate Trigger1=var(59)>0 Trigger1=your Ai jump conditions here value=40 The reverse, making the character not jump when the up button is pressed, or at least limiting how ofter that happens (default AI likes to jump way too often, which makes fights annoying) can be done by overriding state 40: ; Jump Start [Statedef 40] type = S physics = S anim = 40 ctrl = 0 sprpriority = 1 [State 40] Type=Changestate Triggerall=time=0 Triggerall=var(59)>0 Trigger1=random>var(50); Add your limiting condition to AI jumping here value=0; Change back to standing immediately when the AI would start a jump and it is not necessary. ctrl=1 [State 40, 1] type = VarSet trigger1 = Time = 0 sysvar(1) = 0 [State 40, 2] type = VarSet trigger1 = command = "holdfwd" trigger1 = var(59)=0 trigger2 = var(59)>0 trigger2 = condition when the AI needs to jump forward sysvar(1) = 1 [State 40, 3] type = VarSet trigger1 = command = "holdback" trigger1 = var(59)=0 trigger2 = var(59)>0 trigger2 = condition when the AI needs to jump back sysvar(1) = -1 [State 40, 4] type = VelSet trigger1 = AnimTime = 0 x = ifelse(sysvar(1)=0, const(velocity.jump.neu.x), ifelse(sysvar(1)=1, const(velocity.jump.fwd.x), const(velocity.jump.back.x))) y = const(velocity.jump.y) [State 40, 5] type = VelSet trigger1 = AnimTime = 0 trigger1 = prevstateno = 100;RUN_FWD trigger1 = sysvar(1) = 1 x = const(velocity.runjump.fwd.x) [State 40, 6] type = ChangeState trigger1 = AnimTime = 0 value = 50 ctrl = 1 Note, that if you do not want your standing animation to get restarted from frame 0, you need to change your anim=40 line into a changeanim placed below the changestate to state 0 Walking Usually, there is no need to code for walking for two reasons. If you want your AI to move closer/further, you'll use the running moves instead, as most characters have those. Walking is less optimal than running. The walking done by the default AI doesn't hurt character performance either, so there is no need to disable it usually. At least the character does something when idle for a long time at low difficulty levels instead of just standing. This guide was created by Seravy. 00EccoTenshi and ramon garcia 1 1 - Characters - / - Stages - / - Screenpacks - / - Lifebars - / - Fonts - / - Full Games - / - Templates -
Алексей Posted April 30, 2015 Posted April 30, 2015 Where is the TL;DR version?Here you go:1. Put in AI activation 2. Make character do special shit when AI is active 3. Profit? 4. Realized you've made a horrible AI and tweak it a bit 5. Repeat steps 2~4 until you go insane SpookyKujo 1 -[Все слова это только слова.]-
Ryon Posted May 1, 2015 Author Posted May 1, 2015 Where is the TL;DR version? THERE IS NONE! Either read it or GTFO. Gorrinnard, Sir Ghostler, lyr and 1 other 3 1 - Characters - / - Stages - / - Screenpacks - / - Lifebars - / - Fonts - / - Full Games - / - Templates -
Hellzone Posted May 2, 2015 Posted May 2, 2015 I like this method becuase it is very easy to use and understand. Thanks for sharing & thanks to Seravy Find Yourself. Find Peace. Find Creativity
darkblade0v Posted January 30, 2016 Posted January 30, 2016 Not sure if I can properly utilize this detorial, but I know there is a few characters that deserve the love they're creaters never were able to work in... *points finger at the robot masters from megaman2... Going to try reworking crashman, and if I'm successful, metalman, though pulling it off might be hard.
RicePigeon Posted February 1, 2016 Posted February 1, 2016 Something that this guide never addresses is that using random in your AI triggers is bad coding practice. The reason for this for two reasons; Mugen processes states in top-down order, including the negative states (-3, -2, and -1) Random returns a different value every time it is called Take the following code into consideration: [State -1, Shoryuken] type = changestate trigger1 = AILevel trigger1 = ctrl trigger1 = random<300 [State -1, Tatsumaki] type = changestate trigger1 = AILevel trigger1 = ctrl trigger1 = random<300 Looking at each AI changestate at face value, you would think that each one has a 30% chance at activating (random<300 roughly equates to 30% chance). However, because mugen processes states in top-down order, if the first changestate occurs, the second changestate will never process. Thus, the second changestate in actuality only has a 21% chance of occuring (70% chance of the 1st changestate not occuring, plus the 30% chance that the 2nd changestate will occur). When you have multiple AI changestates with similar or identical trigger conditions, you will need to account for this. A common way to do this (and much better practice) is to instead store the result of random into a variable, and compare the variable to different ranges of values in order to determine which changestate should occur. ramon garcia and youxianV 1 1
Ryon Posted February 6, 2016 Author Posted February 6, 2016 A method I do for chain combo AI, is I have a varrandom, randomize a variable for me within the range of 100 or so. and if the variable lands on a number range betwen 0 - 24 25 - 49 50 - 74 75 - 100 it will trigger different states. I know it's not a perfect 1/4 chance, but do you think this is a good method for coding AI CHAIN COMBO RANDOMNESS ? - Characters - / - Stages - / - Screenpacks - / - Lifebars - / - Fonts - / - Full Games - / - Templates -
Ali Posted September 14, 2016 Posted September 14, 2016 Very nice! thank you so much Download my creations here! Hope you like 'em
VTH223 Posted December 21, 2017 Posted December 21, 2017 Welp, this was helpful. It actually stopped my character from jumping 24/7.
Number09 Posted August 9, 2020 Posted August 9, 2020 HI! This thread seems super useful, and though its a few years old hopefully I can get a response or pointed to a new more current thread. I have attempted to input the concept behind the code into my game starting with Kung Fu Man (720p version). It appears I am missing something because it does not effect the way he plays. Per example, I tried to stop him from spamming his taunt (bow) as an AI by doing the following: [State -1, Taunt] type = ChangeState value = 195 triggerall = var(59)>0 ; use only if AI is on triggerall =abs(P2Bodydist X)>50 ; only taunts when enemy is farther triggerall = life>=.05*Lifemax ; only taunts if over 50% life trigger1 = statetype != A trigger1 = var(59)>0 ; use only is AI is on My confusion comes in a bit as to where to place the var(59) check, in the trigger, or in the triggerall as I notice in the original post it switches between the two. Though it is also possible I am not placing the AI activation code in the correct section. It notes to put it in one of the minus states. Can I get a little more clarity then that?
RicePigeon Posted August 9, 2020 Posted August 9, 2020 A lot of the information in this guide was made with WinMugen in mind, before 1.0 was released back in 2009, so much of the variable activation stuff is redundant now as you can simply now use the AILevel trigger instead.
ReneO93 Posted October 15, 2020 Posted October 15, 2020 What RicePigeon said. AILevel is such a blessing of a condition. You no longer have to put dumb commands at the top of a CMD file, and you can even make an AI behave differently depending on the difficulty setting. Here's another tutorial regarding guarding that I found. https://mugenmultiverse.forumotion.com/t7611-shirayuki33desu-s-way-to-make-your-mugen-character-s-a-i-block-guard-better https://archive.is/Eh9T7 It's with winmugen in mind, but that just means to replace var(59) stuff with AILevel. youxianV 1
Mrnoobisnotonfire Posted April 9, 2023 Posted April 9, 2023 Cool! Now I can create an ai for my char! Big helpful indeed!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now