News:

Happy 20th, FFvT3R!

Main Menu

m25 AI in depth discussion

Started by ELECTR0, March 20, 2014, 05:38:47 PM

Previous topic - Next topic

ELECTR0

I've noticed when making M25 AI that it can be a little tough because the code seems to be very precise. So a simple mistake in the code will make the powers not work correctly. I don't know how many times I've fired up watchmode and wondered when a character is going to do a certain action in a certain situation and never do it because I have written it wrong, LoL. So let's discuss so we can cut back on these problems. Feel free to post your own hero file questions and code.

First up we have Flash.

['-All-Star=flash',
["target enemy",

],
["timer", 'auto',
'TUseRemedy()',
'TFleeMelee(type="any",subtype="emitting_damage",time=0.88)',
"TSpeedingBullet('speeding bullet',pct=80,time=0.88,mindist=80,maxdist=300)",
                "TCloak('faster than the eye',pct=10,time=3,subtype='ranged_crushing or ranged_energy or ranged_piercing',)",
"TRangedExplosive('vibrations',pct=60,time=3)",
"TArea('hyper spin',pct=60,time=3,subtype='melee_crushing or melee_energy or melee_piercing',situation='swarmed')",
"TRanged('wirlwind',pct=60,time=3)",
"TMelee('jla combo',pct=80,time=2.23)",
"TMelee('hyper punchs',pct=80,time=3)",
"TMelee('uppercut',pct=80,time=3.59)",
"TSprintAway('hyper speed',pct=40,time=0.88,maxdist='infinite',subtype='ranged_crushing or ranged_energy or ranged_piercing or melee_crushing or melee_energy or melee_piercing',objectdist='long')",
'TMoveTo(mindist=\'medium\',time=0.88,subtype=["not emitting_damage","flying"])',
'TMoveTo(mindist="melee",subtype=["not emitting_damage","not flying"],time=0.88)',
],
]


Just so i'm clear on what's going on here with his defensive tatics. I have TSprintAway with a pct of 40 and TCloak with a pct of 10. Are these two powers only rolling the dice between themselves when the situation comes into play or are they in a pool with all the other powers? My next question is can TSpeedingBullet range be increased above a movedist of 300?

detourne_me

It looks like a pretty good AI file to me, however I think you might want to group the defenses closer together... maybe?
From what I remember, the AI runs down the list and looks to see what the situation is, so order priority goes into play before percentage does.  I may be mistaken with that.
For example, it goes through the steps one by one, checks to see if the conditions are met, and then rolls to see if it is the right percentage to complete the action.

ElijahSnowFan

#2
Hey, Electro!

First of all: I LOVE THIS THREAD. I can talk about this stuff all day.

But could you do me a favor? I tweaked your AI a bit, based off observations I've made over the years. I absolutely AM NOT trying to offend you, but could you run this and see if the behavior matches what you want a little more closely? I think, based on your questions, it might be something you could use:

['-All-Star=flash',
["target enemy",
'ranged_cold',
'fastest',
],
["timer", 'auto',
'TUseRemedy()',
'TFleeMelee(type="any",subtype="emitting_damage",time=0.88)',
"TSpeedingBullet('speeding bullet',pct=80,time=3.27,mindist=80,maxdist=300)",
                "TCloak('faster than the eye',pct=10,time=3,subtype='ranged_crushing or ranged_energy or ranged_piercing',)",
"TRangedExplosive('vibrations',pct=35,time=3)",
"TArea('hyper spin',pct=60,time=3,subtype='melee_crushing or melee_energy or melee_piercing',situation='swarmed')",
"TRanged('wirlwind',pct=25,time=3)",
"TMelee('jla combo',pct=30,time=2.23)",
"TMelee('hyper punchs',pct=30,time=3)",
"TMelee('uppercut',pct=30,time=3.59)",
"TSprintAway('hyper speed',pct=15,mindist=800,maxdist='infinite',subtype='ranged_crushing or ranged_energy or ranged_piercing or melee_crushing or melee_energy or melee_piercing',objectdist='long')",
'TMoveTo(mindist=\'medium\',time=0.88,subtype=["not emitting_damage","flying"])',
'TMoveTo(mindist="melee",subtype=["not emitting_damage","not flying"],time=0.88)',
],
['subtype',
            'superspeed',
        ],
['delay',
0.1,
],
]

ElijahSnowFan

#3
What I see in your original AI is, based on my own AI experiences over the years, that Sprint percentages above 20, for whatever reason, make the AI default to that almost continuously.

Also, with melee percentages at 60 or above, you won't get as much variety as you would by taking the percentages lower -- I find 30, 35 percent works well, if you want variance in your melee attacks.

I added more time to your SpeedingBullet clock, and eliminated the clock entirely for your Sprint power. Those tweaks, in my experience, seem to work well for speedster characters.

Lastly, I gave him a reaction time of 0.1, way down at the bottom. The default reax time is like...0.4, I believe? So what you'll find is that your Flash will now react much faster than "base" characters. That means that he will run through his powerset more quickly, which means that offsets some of the lower percentages that you will see in your Sprint and Cloaking powers -- because he will have more opportunity to activate them, based on scenarios -- and also, your passive defenses will be more effective because he will attack more often, especially after dodges.

Again: Trust me, I am NOT trying to offend you. I just thought you might see some value in those, based on your questions.


ElijahSnowFan

Oh, and before I post another thing in this thread:

I don't want to give the impression that I figured ANY of this stuff out by myself. I wouldn't know jack about this stuff if it wasn't for TaskmasterX's hero files/tutorials from back in the day. I couldn't script a damn thing without M25's tool, which creates AIs with no errors. And I wouldn't understand other assorted things without guys like Stumpy and Epimethee, who have answered multiple questions from me in the scripting forum.

I just wanted to say that because, as always -- this game is really fun, once you pop the hood. But I wouldn't have ever known how to do that without other people, so I am eternally grateful for that.

Epimethee

As I never spent nearly enough time working with M25's amazing AI code (I just have a hard time debugging AI issues, I guess), I find these tips very useful. Thanks, Elijah!
FFX add-on for FFvsTTR at ffx.freedomforce4ever.com

ElijahSnowFan

You're welcome! I hope we keep this thread going, too! :thumbup:

trebean

Bumping this. Is it possible to special target heroes? Like let's say, I want Sabretooth to hunt down Wolverine if he's in battle, is that possible? Also for some reason, characters with at least somewhere near the max or have the max number of attacks take longer to do stuff? I made a herofile that had a full slot of attacks, ran him in the M25AI Generator and when I tried fighting him, he doesn't really do much. Granted I never did the more indept customizations like giving percentages to the frequency of the attacks, but then again, most of my AI Files don't really have thise and work just fine.

ElijahSnowFan

Quote from: trebean on May 16, 2014, 12:09:14 PM
Bumping this. Is it possible to special target heroes? Like let's say, I want Sabretooth to hunt down Wolverine if he's in battle, is that possible? Also for some reason, characters with at least somewhere near the max or have the max number of attacks take longer to do stuff? I made a herofile that had a full slot of attacks, ran him in the M25AI Generator and when I tried fighting him, he doesn't really do much. Granted I never did the more indept customizations like giving percentages to the frequency of the attacks, but then again, most of my AI Files don't really have thise and work just fine.

Those are interesting questions. As always, I don't want to appear like I know everything, because I don't, but I'll try to answer as best I can.

For the targeting of specific heroes, in theory, you should be able to do it, but not by name. You could place a priority target on them based on something like -- but not limited to -- their material type or specific powers they display -- take, for example, the sample AI from the beginning of the thread:
['-All-Star=flash',
["target enemy",
'ranged_cold',
'fastest',
],


What that is saying is that, in theory, Flash should default to attacking first a character with ranged_cold or is faster than another character who is with him. So, in theory, if that Flash is fighting Captain Cold (who would likely have a freeze/cold blast power) and Captain Boomerang, then that Flash SHOULD, repeat SHOULD, attack Captain Cold first.

What I see in-game a lot is that it's not that hard-and-fast in the targeting -- the game does have limitations. But there are times when you can see preferences being cycled through and executed.

Now, where you can really make some trouble is with your powers themselves, via scripting through the use of priorities. For example, I'll post my Flash AI:.

['Flash',
["target enemy",
'ranged_cold',
'fastest',
],
["timer", 'auto',
"TRandMoveOnTargetType(pct=80,mindist=200,maxdist=2000,subtype='throwing or metal or flying')",
"TSpreadOut(pct=20,maxdist=400,subtype='metal',priority=5)",
"TRandMove(pct=25,mindist=150,maxdist=600,priority=5)",
"TFleeMelee(pct=20,time=2.5,mindist=300,subtype='higherstrength 4')",
'TFleeMelee(type="any",subtype="emitting_damage",time=1.48)',
"TSpeedingBullet('speeding bullet',time=3.27,mindist=100,maxdist=1500)",
"TMelee('sonic punch',time=0.88,subtype='stunned',priority=11)",
"TMelee('sonic punch',time=0.88,subtype='higherstrength 4 or metal or stone',priority=11)",
"TArea('whirlwind',time=2.52)",
"TArea('whirlwind',time=2.52,pct=90,subtype='flying',priority=11)",
"TMelee('superspeed punches',pct=30,time=1.19)",
"TRanged('wind fury',time=2.59,maxdist=250,subtype='flying or ranged_piercing or ranged_cold or ranged_electrical',priority=11)",
"TMelee('haymaker',pct=30,time=1.25,subtype=['not stone', 'not metal'])",
"TSprintAway('sprint',pct=15,mindist=800,maxdist=2000,subtype='ranged_energy or ranged_fire or ranged_electrical',priority=5)",
"TMelee('punch',pct=40,time=0.98,subtype=['not stone', 'not metal'])",
"TRandMove(pct=50,mindist=300,maxdist=600,situation='lowerhealth 100')",
"TRandMove(pct=40,mindist=400,maxdist=800,situation='lowerhealthpct 40',priority=11)",
          'TMoveTo(pct=90,mindist=300,maxdist=10000,subtype="flying")',
'TMoveTo(mindist="melee",subtype=["not emitting_damage","not flying"],time=1.88)',
],
['subtype',
            'superspeed',
        ],
['delay',
0.1,
],
]


Now, again: Please remember that anything I have done is simply extrapolating work pioneered by others, so a lot of what I'm saying is based on trial-and-error. Not taking credit for figuring out how this stuff works, or the coding ideas.

But my version of Barry Allen as the Flash has Captain Cold as his arch-enemy, so I did, indeed, have him target ranged_cold attackers first, and also via the placement of the priority=11 on the "wind fury" power, and also due to the fact that I have him with the potential of creating distance with a "sprint away" power  when he's up against ranged_fire and ranged_electrical powers (think Heat Wave and Weather Wizard, who I usually have running around with Captain Cold). That means that when he does activate the sprint power, when he re-engages the Rogues, he's more likely than not going to target the ranged_cold character first.

That Flash, when he's up against Captain Cold, Heat Wave and Weather Wizard, or some other mix of characters, does tend to address Captain Cold first. Not always, but enough to make me think the targeting and prioritizing do work.

As for the second question...I'd maybe have to see the AI for the character to get a feel for what it's trying to choose from. There are some things I've noticed that make AIs a little wonky -- for instance, having multiple area attacks seems to mess with the AI a bit -- but I'd have to see what it's being asked to do to offer a real opinion -- sometimes, even the order of powers can make an AI a little hinky.

trebean

#9
I can't exactly post the AI since I'm using my phone, but the problem causers all have 3-4 Meelees, 1-2 Ranged Projectiles, 1-2 Area, 1 Special,  *one Passive Defenceand one Active Defence.
They also all have the Team Player, Gymnast, Combat Master (Expert), Body Armor 05 attributes with the exception of one having Field Commander, and another having no Team Player but a hugher body armor. Most of them have sorta missalligned movesets like 3 Meelees in a row, then a ranged, then a Meelee again.
Edit::
So I'm guessing you can't target by attribute too? Like Regenerative or Tough Guy? Do you know of another guide in making AIs other than the one in FFX Freedom Force Forever? I want to try looking at how percentages work, like in a moveset with at least 4 moves, I'm guessing something above 20% will be used a lot?


*Edit

ElijahSnowFan

Quote from: trebean on May 16, 2014, 05:16:00 PM
I can't exactly post the AI since I'm using my phone, but the problem causers all have 3-4 Meelees, 1-2 Ranged Projectiles, 1-2 Area, 1 Special,  *one Passive Defenceand one Active Defence.
They also all have the Team Player, Gymnast, Combat Master (Expert), Body Armor 05 attributes with the exception of one having Field Commander, and another having no Team Player but a hugher body armor. Most of them have sorta missalligned movesets like 3 Meelees in a row, then a ranged, then a Meelee again.
Edit::
So I'm guessing you can't target by attribute too? Like Regenerative or Tough Guy? Do you know of another guide in making AIs other than the one in FFX Freedom Force Forever? I want to try looking at how percentages work, like in a moveset with at least 4 moves, I'm guessing something above 20% will be used a lot?


*Edit

Huh.

Now, again, these are just guesses. But one thing I'd look at is "Gymnast." For whatever reason, the "Acrobat" attribute has always made my characters freeze after it's triggered, and that's a part of that attribute.

I realize with some characters, that attribute matters a lot. But a quick check to see if your characters would work a little more how you'd prefer might be to take that out and replace it with "Clumsy Jumper," which works fine, and see if that solves your issues -- you'd probably want to make sure you do that, because you'll have some type of Superleap attribute in the AI that you don't want to break.

Again, sometimes multiple area attacks can make things a little wonky, and so can movesets like you described, where the character go melee for multiple attacks, then ranged, then melee again, or vice versa. But, again, the first thing I'd do is swap out Gymnast and see if that helps.

And as far as I know -- again, I could be wrong -- but I don't believe you can target by attribute. With the enhanced materials provided, you could easily label a Wolverine as "adamantium," or Black Canary with "sonic_scream," stuff like that. There are a ton of really descriptive materials in the most recent releases of FFX that helped a lot with that.

And yes, percentages matter A TON. You can totally change the feel of any character by using percentages -- it's amazing how much you can do with percentages and priorities.

My rule of thumb is this: If you want to see a power most frequently in a series of four movesets, make it pct=35. If you want to see it fourth-most, make it pct=15. Make the other two pct=25. You'll get the variety you're looking for, I would think.


spydermann93

#11
Quote from: ElijahSnowFan on May 16, 2014, 05:38:12 PMFor whatever reason, the "Acrobat" attribute has always made my characters freeze after it's triggered, and that's a part of that attribute.

Just to clarify (I am not trying to be rude here), but it's the "Low Jump" attribute that usually causes the AI to lock up.

What I do, and this is if I ever use "Gymnast", is I simply remove the line from the AI file.  Of course, the AI won't be able to use it, but your character will still have the ability.

Never really tried "Clumsy Jumper", though.  Sounds like that swap just might work.

EDIT: Also, I have no idea if this is true or if this even works, but couldn't you make your own subtype in the AI file?  Like, for Wolverine, couldn't he add a "wolverine" subtype to Wolverine's AI file and have Sabretooth target "Wolverine" characters?

ElijahSnowFan

Quote from: spydermann93 on May 16, 2014, 05:50:12 PM
Quote from: ElijahSnowFan on May 16, 2014, 05:38:12 PMFor whatever reason, the "Acrobat" attribute has always made my characters freeze after it's triggered, and that's a part of that attribute.

Just to clarify (I am not trying to be rude here), but it's the "Low Jump" attribute that usually causes the AI to lock up.

What I do, and this is if I ever use "Gymnast", is I simply remove the line from the AI file.  Of course, the AI won't be able to use it, but your character will still have the ability.

Never really tried "Clumsy Jumper", though.  Sounds like that swap just might work.

EDIT: Also, I have no idea if this is true or if this even works, but couldn't you make your own subtype in the AI file?  Like, for Wolverine, couldn't he add a "wolverine" subtype to Wolverine's AI file and have Sabretooth target "Wolverine" characters?

You're totally fine -- I was hoping others would jump in, because one thing I know is that a sample size of one is subject to error/bias, so I'm TOTALLY glad you/others want to comment.

I ddn't think -- repeat, think -- you can make a subtype that was outside of the game parameters, but that was just my interpretation of reading the FFX Manual. I could be wrong, and if I am, please do not hesitate to tell me!

ELECTR0

When I use subtypes, for example "robot" & then have my hero have a specific attack that should only target a robot. My hero will still target none robot chars with the specific attack that do not have a robot subtype. Is this supposed to happen or does it tend to target a robot char first, but still use the attack even if no robot subtypes are in battle?

trebean

I was thinking, is there a way for AIs to like, avoid others and pick off weaker heroes? Like let's say I wany my Bullseye to avoid conflict and just attack those with the lowest health? Is that possible? (The lowest health thing)

Also a bit unrelated but how do you handle character specific attacks? Like I want Flash to use his speed stealing on the fastest enemy frequently only, can I make another percentage for a different subtype? (Is that the correct term? For Fastest?)or how do you handle stuff like Kryptonite Attacks only being used on Kryptonians?

Epimethee

Sorry about the Low Jumper bug... sigh... too much of a hack, I guess.

Quote from: trebean on May 16, 2014, 12:09:14 PM
Bumping this. Is it possible to special target heroes? Like let's say, I want Sabretooth to hunt down Wolverine if he's in battle, is that possible?
A wee bit late, but, assuming your target hero file is named "wolverine" (without caps), you could probably create an attribute called "aivswolverine" in FFEdit and give to Sabretooth. In ffx.py, you could add something like this:

def initaivswolverine(char,update=0):
    if update==0:
        RegTimer('updateAIvsWolverine', 10, 0, char)

def updateAIvsWolverine(event):
    char = event.object
    if not Object_Exists(char):
        return
    if FFX_ObjectGetAttr(char, 'psychotherapy'):
        return
    initialized = event.user
    RegTimer('updateAIvsWolverine', 10, 1, char)
    if not Object_IsAlive(char):
        return
    if cshelper.isPlaying():
        return
    if initialized == 0:
        return
    wolverines = []
    for target in getAllCharacters(checkLiving = 1, lures = 0, specialCharacters = 0):
        if FFX_GetTemplate(target) == 'wolverine':
            wolverines.append(target)
    if wolverines == []:
        return
    else:
        for wolverine in wolverines:
            cshelper.addKillGoal(char, wolverine, PRI_HI)


Disclaimers: a) Not tested. b) As of FFX 3.3, there is no more place in ffx.py for new attributes. You'd either need to remove an unused attribute (such as Car Chaser – no one uses that, right?) or move it to ffx2.py and add the required prefixes. c) Back up everything first.
FFX add-on for FFvsTTR at ffx.freedomforce4ever.com