Author Topic: How to code the AI  (Read 23626 times)

Offline Phezzan

  • Sergeant
  • **
  • Posts: 37
  • Twilight
    • View Profile
How to code the AI
« on: July 08, 2013, 12:40:49 am »
I'm interested in tweaking, or perhaps overhauling the AI to make X-Com scare me as much as it did back when I was 13.

So far, I've managed only to tweak the formula that attempts to find and retrieve weapons.  (hooray - stun damage is no longer instant win)

While banging my head against that - I noticed the game seems to have 'AI states' and that these operate for a while, and then it maybe decides to pick a new state - perhaps on the same turn as it picked the last one...  Additionally there doesn't seem to be any alien group consciousness.

The melee AI will target flying or otherwise unreachable targets. (like the rear tile of a tank despite the fact that it's within a blocked entrance)
The AI does attempt to hit units from the rear (less armor), but it doesn't choose targets based on armor.
(a Chryssalid will wail on a Tank it can't hurt rather than take two steps and hit a soldier in personal armor.)

Aliens do not react as a group - ie: they will not stop patrolling and come help defend the UFO, but they will retreat from visual range until they are pressed against the edge of the map.
Even Sectopods will retreat despite being nearly invincible on their front armor.

Aliens act individually, they do not come in 'teams' or squads -
If Aliens prepare ambushes, I haven't seen that yet - and I bet they wouldn't wait long before attempting a patrol anyway.

Somehow I want to fix some or all of these things

I imagine that 'threat to tile' can be tweaked to keep a 'max power' estimate so that heavily armored units can ignore the 'threat' of 20 troops with LasPistols.
The 'find cover' logic perhaps could be tweaked to allow units to hide behind large units.
The 'choose target' logic might weigh armor, hit probability, and cover (with a double penalty for cover from our own units).

But maybe I'm wrong and this stuff is implemented (or implemented and turned off)?

Phez

Offline kkmic

  • Commander
  • *****
  • Posts: 582
  • Undefined
    • View Profile
Re: How to code the AI
« Reply #1 on: July 08, 2013, 09:52:21 am »
The AI is in "playable" condition right now (with some extra highlights compared to the original one), and it is open for improvements.

You up for it? :)

Offline Phezzan

  • Sergeant
  • **
  • Posts: 37
  • Twilight
    • View Profile
Re: How to code the AI
« Reply #2 on: July 08, 2013, 04:19:11 pm »
We'll see.    I'm certainly no expert - I had exactly two college courses in AI, and that was a long long time ago.

At the very least I'd like to improve target selection.

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: How to code the AI
« Reply #3 on: July 10, 2013, 03:28:24 pm »
i WILL answer all this... i just need to find an opportunity to sit down and write it all out.

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: How to code the AI
« Reply #4 on: July 14, 2013, 02:59:46 pm »
I'm interested in tweaking, or perhaps overhauling the AI to make X-Com scare me as much as it did back when I was 13.

So far, I've managed only to tweak the formula that attempts to find and retrieve weapons.  (hooray - stun damage is no longer instant win)

all you needed to do to acheive that was add some attraction values of like... 8 or so to plasma weapons, blaster launchers, small launchers and their ammunitions.

The melee AI will target flying or otherwise unreachable targets. (like the rear tile of a tank despite the fact that it's within a blocked entrance)

The AI does attempt to hit units from the rear (less armor), but it doesn't choose targets based on armor.
(a Chryssalid will wail on a Tank it can't hurt rather than take two steps and hit a soldier in personal armor.)

it shouldn't, it should only be targetting units it can pathfind to.
it doesn't prioritize rear armour, it prioritizes attacking whatever's closest. and for the record, a chryssalid should have no problem reducing a tank to a pile of rubble.

Aliens do not react as a group - ie: they will not stop patrolling and come help defend the UFO, but they will retreat from visual range until they are pressed against the edge of the map.
Even Sectopods will retreat despite being nearly invincible on their front armor.

Aliens act individually, they do not come in 'teams' or squads -
If Aliens prepare ambushes, I haven't seen that yet - and I bet they wouldn't wait long before attempting a patrol anyway.

they do to some extent, aliens will use squad sight for targetting far away units with blaster launchers, and once the aliens spot a player unit, they keep "psychic" track of him for a few turns, leaving him vulnerable to mind control/panic. they don't use squad sight for regular shooting YET, but i have some thoughts on this.


I imagine that 'threat to tile' can be tweaked to keep a 'max power' estimate so that heavily armored units can ignore the 'threat' of 20 troops with LasPistols.
The 'find cover' logic perhaps could be tweaked to allow units to hide behind large units.
The 'choose target' logic might weigh armor, hit probability, and cover (with a double penalty for cover from our own units).
the "threat to tile" is based on the number of units that can see the tile. taking into account what those units are holding is a bit... iffy, i mean, they might be holding motion scanners and medikits, but have a blaster launcher in their backpack.

The 'find cover' logic was deliberately tweaked to STOP units using each other as cover, as hilarious as it was, they often decided that directly behind/beside your men was a pretty good place to keep out of sight. even more hilariously, it often worked.

the "choose target" logic, generally speaking, prioritizes whoever's closest, because naturally, there's a better chance of hitting them, and in the case of melee, it means more TUs left over when you reach them to use on chewing and swallowing.


about the AI states: the ai functions in two basic modes, "patrol", where he just wanders from map node to map node, looking for something to kill/eat/experiment on, and "aggro", when he has found somebody he doesn't like.

in the patrol state, he reserves a % of TUs as he wanders about, in case some hapless soldier wanders into his field of vision.

in the aggro state, he stalks his prey, and when he spots it, he makes a quick (very slow and cpu intensive) assessment of the cover around him, chooses a spot to move to, and reserves enough TUs to get there, spending the rest on shooting at his opponent.

unless he's psionic or has a blaster launcher, in which case he tries to use those instead.

Offline Phezzan

  • Sergeant
  • **
  • Posts: 37
  • Twilight
    • View Profile
Re: How to code the AI
« Reply #5 on: July 15, 2013, 12:42:50 am »
all you needed to do to acheive that was add some attraction values of like... 8 or so to plasma weapons, blaster launchers, small launchers and their ammunitions.

I'm using that option, and most of the original code, but I streamlined it a bit -
The old code picked only weapons it really liked and was really close to, then filtered it out based on some extra criteria.
Once it filtered it didn't go for a second choice it just gave up.
The result was that almost never finds a weapon because it's scared of being seen, or some other reason.

I combined the extra criteria into the finding function.  Aliens never fail to find a weapon now - anything with an attraction above 0 will do.

it shouldn't, it should only be targetting units it can pathfind to.
it doesn't prioritize rear armour, it prioritizes attacking whatever's closest. and for the record, a chryssalid should have no problem reducing a tank to a pile of rubble.

I haven't modified pathfinding and the chryssalid paces away all his TU in the two sqaures on the ground in front of my flying armor/hovertank.

I've seen melee units walk past the front and around the back before attacking - perhaps because it was out of sight ?
Yes in the unmodified game, a Chryssalid kills almost anything in one round and most things in one hit...
In the unmodified source code, any hit kills literally any woundable unit at the end of turn regardless of armor or damage - it doesn't even have to deal damage to kill.
Some people may like it that way, but I didn't, so I fixed it. 
My chryssalids actually have to inflict 1 damage to infect you and infection is a degenerative state instead of instakill. ... etc.

they do to some extent, aliens will use squad sight for targetting far away units with blaster launchers, and once the aliens spot a player unit, they keep "psychic" track of him for a few turns, leaving him vulnerable to mind control/panic. they don't use squad sight for regular shooting YET, but i have some thoughts on this.

I did see that - sometimes aliens just kind of ignore me and just keep pacing back and forth.
I ran into some Mutons in a barn - I surrounded the entrance with guys w/Laser pistols (veteran difficulty)
The Mutons would generally attempt to leave the barn, then realize I was shooting at them and re-enter the barn.  They rarely fired back.
I spent a lot of turns playing fish in a barrel.

The other aliens didn't try to flank me - they stayed in the UFO.
Eventually I knocked out the back wall and they ran -  had to chase them. 
Admittedly I had 8+ guys covering the door with LasPistols... so the 'threat' was pretty huge and it probably decided to run, but had only one place to go and it had no exit.

the "threat to tile" is based on the number of units that can see the tile. taking into account what those units are holding is a bit... iffy, i mean, they might be holding motion scanners and medikits, but have a blaster launcher in their backpack.

The 'find cover' logic was deliberately tweaked to STOP units using each other as cover, as hilarious as it was, they often decided that directly behind/beside your men was a pretty good place to keep out of sight. even more hilariously, it often worked.

Ah yes the old giant weapon hiding in backpack trick...
I really wouldn't mind that problem - I mean if the aliens were really calculating and I wanted to draw them into a trap it's what I'd do.
And OTOH if I were the alien commander it's not something I'd really worry about - alien forces are infinite - They can lose every battle and win the war.

Ex: Sectopods usually take me 10-15 shots to take down due to their armor.  But they rarely fire back.  Instead they run and hide. I simply must fix this.

the "choose target" logic, generally speaking, prioritizes whoever's closest, because naturally, there's a better chance of hitting them, and in the case of melee, it means more TUs left over when you reach them to use on chewing and swallowing.

And that works great your units can likely damage anything (or aren't supposed to be smart enough to worry about it)
I admit I don't know how to keep my reapers dangerous by the end if they aren't overpowering in the early game.  I'm thinking about balancing it with an armor piercing damage property - it would reduce the effectiveness of armor for purposes of determining damage, but wouldn't become damage after successful armor penetration.

about the AI states: the ai functions in two basic modes, "patrol", where he just wanders from map node to map node, looking for something to kill/eat/experiment on, and "aggro", when he has found somebody he doesn't like.

in the patrol state, he reserves a % of TUs as he wanders about, in case some hapless soldier wanders into his field of vision.

in the aggro state, he stalks his prey, and when he spots it, he makes a quick (very slow and cpu intensive) assessment of the cover around him, chooses a spot to move to, and reserves enough TUs to get there, spending the rest on shooting at his opponent.

unless he's psionic or has a blaster launcher, in which case he tries to use those instead.

So if I were to 'aggro' all 'patrolling' alien units at the beginning of any alien turn in which an xcom unit is spotted, the result would be the battle of Normandy !?

Phez
« Last Edit: July 15, 2013, 03:18:02 am by Phezzan »

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: How to code the AI
« Reply #6 on: July 16, 2013, 04:37:13 pm »
i've made a bunch of adjustments to the AI routines, you should see many of these issues fixed.

Offline Phezzan

  • Sergeant
  • **
  • Posts: 37
  • Twilight
    • View Profile
Re: How to code the AI
« Reply #7 on: July 17, 2013, 06:30:21 am »
I'll be chewing on that  merge for a bit. :)

I see you touched unconscious item loss - you should know that:

1 - convertUnitToCorpse() is called for unconscious units
2 - line 225 removes the Chryssalid's weapon.

therefore stunning a chryssalid will disarm it.

The easiest way to fix this is to condition line 225 on the unit actually being dead - as the fixed weapon already refused to drop in the preceding loop.
Well I don't know what your change (setting owner to 0) will do to an item that refused to drop.  Perhaps nothing.

I imagine that clearing the inventory vector would be dangerous if we had actually added a fixed weapon to the _game's _items.

« Last Edit: July 17, 2013, 07:07:46 am by Phezzan »

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: How to code the AI
« Reply #8 on: July 17, 2013, 07:20:21 am »
nice catch, thanks.

Offline Phezzan

  • Sergeant
  • **
  • Posts: 37
  • Twilight
    • View Profile
Re: How to code the AI
« Reply #9 on: July 20, 2013, 07:27:26 am »
So I'm playing with changes to fire mode selection, target selection, grenade determination, aggression (cover determination) and psiAttack estimation.
I've been reloading saves a lot more.  It's really powerful to allow the PsiAttack AI to pick-up weapons - it tends to panic a unit, then mind-control it.  Of course that unit now needs a weapon, and they might decide the harmless pistol they dropped is less appealing than the heavy plasma next to that dead alien. This really messes with my simple solution of giving all the weak minded people weak weapons.

Probably the biggest difference is my fire mode selection calculation tends to prefer auto-fire... I take into account the probability of hitting once in three shots compared to the probability of hitting with snap or aimed.  The game only considers distance - not the accuracy of the fire mode or number of shots.
formula: (100 - Accuracy) ^ 3 / (100 ^ 3)   * 100
More shots in the air means more lucky hits to penetrate armor, and more 'misses' that hit a different target.

Another change - I factored armor into the target choice.  I simply take the front armor of the target, double it and subtract my weapon power. This is added to the distanceSq() value and I choose the minimum result. I need to introduce some randomness and a tweak for facing.  This makes the aliens much less likely to harmlessly shoot your tank unless you actually hide behind it for cover or send it out well ahead of your troops.

Warboy's recent change makes the value moot but  SECTOPODs only had an aggression of '1' (the middle value in the cover calculation).  Considering they're tougher than almost anything on the battlefield and large there's not much effective cover for them anyway.

I tried to make grenades / explosiveEvaluation consider target armor when tallying effectiveness but I think my formula is too conservative and predictable, I want to have a shortage of loot due to all the explosions.

I haven't figured out what to do with melee units.

Between WarBoy's improvements and my own I admit I now have great difficulty with Ethereals - basically I can't send a rookie team, and I have to give all my weak minded guys weak weapons which are useless against Sectopods.

Mutons give me some trouble because they tend to live through several turns and can get lucky with auto fire plasma.

I want to give Chryssalids a 'sneaky' AI and Reapers a 'charge' AI which at higher difficulties hunt in packs and synchronize attacks.  Perhaps this would be a 'NinjaBAIState' and 'PackBAIState'.  Neither would 'Patrol'
Ninja would prefer small spaces and would avoid 'seen' tiles like the 'sneaky' AI.  Additionally they would prefer targets that are not visible to other targets.
Pack would always attempt to be 8-12 distance from the group's center, and would avoid any path less than 4 spaces wide unless it isn't visible to the enemy.  The 'group' would move by pathfinding this center to a new area and then allowing the individual units to find paths that place them within a 12 square radius.

Sectoids should use a 'hidden team' AI - basically a ranged version of 'Pack' but the whole group picks a target and then decides who shoots first, second, etc.  Everyone in the team 'sees' the target regardless of distance, cover, etc and each member offers up a guess on how much damage they can do to the target.  The best estimate is allowed to take their shot until the target is out - At which  point a new target is chosen.  The members who have no line of sight will either:
calculate a nearby tile to move to that has LOS, or
Force ignore LOS and autofire if the cover is weak (hedge) and more than 2 spaces from the AI unit, or
Grenade - either the target or one of the 8 squares surrounding the target if no direct arc is found.
They don't need to consider walls likely damage or secondary enemy targets - the idea is to destroy the cover.

If I get any of this to work (and still have hair) I'll post about the terrible terrible changes I made to the game.
Currently I'm thinking that there's a single 'GroupBAIState' and all 'squadmates' add themselves to it as _members.
Then since every member uses the same instance of 'GroupBAIState' it will do all the thinking for each _member the first time any member->think() is called. Future calls to its think() will simply return until a new turn is processed.

Offline wsmithjr

  • Colonel
  • ****
  • Posts: 149
    • View Profile
Re: How to code the AI
« Reply #10 on: July 20, 2013, 05:35:00 pm »
Very interested to see this and looking forward to the results.  Was watching a Let's Play and while I didn't think the guy played particularly well, he muddled through because the aliens just seemed to wander about and never go after him.  (Not sure what version it was.)  Thanks for the efforts.

Offline 54x

  • Colonel
  • ****
  • Posts: 208
    • View Profile
Re: How to code the AI
« Reply #11 on: July 23, 2013, 02:02:10 pm »
Just remember that if you're introducing randomness to the AI it should seed in a way that's reproducable in battlescape saves, so we can reproduce bugs still. :)

Offline pmprog

  • Commander
  • *****
  • Posts: 647
  • Contributor
    • View Profile
    • Polymath Programming
Re: How to code the AI
« Reply #12 on: July 23, 2013, 02:11:31 pm »
Maybe a Quake-style console should be added to battlescape, then you can call something like "Seed {n}", and "GetSeed" :)

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2160
    • View Profile
Re: How to code the AI
« Reply #13 on: July 23, 2013, 05:36:43 pm »
Saves already store the seed, if he uses the same RNG it should still be reproducible.

Offline mercy

  • Colonel
  • ****
  • Posts: 338
    • View Profile
Re: How to code the AI
« Reply #14 on: August 05, 2013, 11:27:05 am »
Respected coders here might wanna take a look at the best AI ever seen in UFO DEFENSE:

Version 1.31.2
https://www.strategycore.co.uk/forums/topic/10341-ufo-extender/

On Superhuman that AI feels real, visceral. I feel like a victim in the movies Predator 1 & 2. Exactly what is needed! It is a real thrill to win a bloody battle there. The entire gaming experience is narrowed down to tight spaces, where XCOM soldiers are screaming and begging for their lifes and the hungry aliens are hunting them down like prey.

OpenXCom has the best UI in the world, awesome MODs, still it lacks a good frightening AI (beyond Warboys awesome surround Skyranger-feature, which should remain!!), which aliens are all about.

OpenXCom does a good job at making aliens surround the Skyranger and shoot, but later the aliens should move, use surprising tactics and must be deadly as hell.  Check out above link!