{"id":4113,"date":"2009-08-19T09:53:51","date_gmt":"2009-08-19T13:53:51","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=4113"},"modified":"2009-08-20T09:45:34","modified_gmt":"2009-08-20T13:45:34","slug":"ai-follies-targeting","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=4113","title":{"rendered":"AI Follies: Targeting"},"content":{"rendered":"<p>So, your AI routine is running.  Taking into account for the enemy field of view, light levels, camouflage, distance, cover, and general threat awareness (like, are there any suspicious dead bodies lying around?) the program has determined that the bad guy has, in fact, spotted the player.  Time to start shooting.<\/p>\n<p>Not so fast.<\/p>\n<p><!--more-->Just as bad guys will always know where the player is unless you tell them not to know that, they will always hit the player flawlessly unless you make them miss.  Left to their own devices, bad guys will be able to ding the player right between the eyes with a Luger at a half mile.  Auf wiedersehen, dummkopf!<\/p>\n<p>Like figuring out if you can see the player, figuring out if you can hit them is likewise going to keep your programmer busy for a long time. <\/p>\n<p><strong>Area Targeting<\/strong><\/p>\n<p>You want to shoot the player.  But where do you aim?  The <em>head<\/em> seems a likely spot.  But remember the I-can&#8217;t-see-you-you-can&#8217;t-see-me problem we had with <a href=\"?p=4093\">detection<\/a>.  If the player is crouching behind cover with their butt sticking out, the AI needs to be smart enough to forgo the headshot and aim for the sticking-out stuff.  If not, players will eventually realize they can take cover behind ridiculously small things &#8211; anything that can cover their head. <\/p>\n<p><strong>Weapon Behavior<\/strong><\/p>\n<p><table width='384'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/stalker_town.jpg' class='insetimage' width='384' alt='stalker_town.jpg' title='stalker_town.jpg'\/><\/td><\/tr><\/table>The obvious thing to do is to make sure the AI will [seem to] live under the same rules as the player.  Effective range, crosswind, weapon accuracy, and movement all need to impact the accuracy of the shot.  A lot of games seem to have two sets of rules: One for players and one for AI&#8217;s. STALKER was really bad about this, in that weapons were far more accurate in the hands of enemies than they were in the hands of the player.  Each bad guy most likely had a single &#8220;accuracy&#8221; rating that was applied to all situations. You would be crouching, with a good-quality weapon, with the bad guy perfectly lined up, but the bullet spread would cause you to miss.  The bad guy would be not just standing but <em>walking<\/em>, using the same weapon but in worse condition, and would hit you more often than you hit him.  On easy difficulty. This was flat-out unfair and frustrating.<\/p>\n<p>But having enemies operate under the same rules as the player means the AI will need to be aware of how each weapon should be used and how to correct for it.  This isn&#8217;t as much of a problem for linear indoor tunnel games &#8211; just put the shotgun guys in small rooms and the snipers up on catwalks and you&#8217;re all good.  But once you&#8217;re trying to make a freeform game where the player can approach an encounter from many different angles you can no longer dictate how the battle will play out, and thus you can&#8217;t just hand your AI a random gun and trust it to Do The Interesting thing. <\/p>\n<p>Some weapons are fine for running around and spraying bullets, but others require that you stabilize yourself.  This variety makes the weapons more interesting, and lets players have a lot of freedom in selecting arms to suit their play style. But this depth and variety comes back to bite the developer when it comes time to write the AI.  It will look stupid if the AI is using the sniper rifle by shooting from the hip, or trying (and failing) to snipe you from the guard tower with his sidearm.  Now the AI needs to understand effective range and be able to weigh all sorts of very hairy tradeoffs.  To wit:<\/p>\n<p><em>Hmm. The shotgun isn&#8217;t particularly useful at this range.  I should get about twenty meters closer.  But that means leaving cover and rushing the player. Is it worth it?<\/em><\/p>\n<p>That last question is an incredibly complex value judgment.  The AI needs to weight just how much it&#8217;s getting out of the weapon versus their chances of survival if they move. I doubt any game has really solved it, which explains why sometimes the bad guys fire away uselessly at long range, or dash out into the open and certain death.  When they make the wrong decision they come off as either morons or lemmings. <\/p>\n<p>But this type of decision-making falls more under &#8220;behavior&#8221; than &#8220;targeting&#8221;. I&#8217;ll come back to it later in the series. <\/p>\n<p><strong>Aim<\/strong><\/p>\n<p><table width='384'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/ai_targeting1.jpg' class='insetimage' width='384' alt='The bot in the distance is using a gun which shoots green orbs which travel in a perfect line without ever dropping.  Note how scattered they are.  A human would have to shake their mouse very fast to get this effect.' title='The bot in the distance is using a gun which shoots green orbs which travel in a perfect line without ever dropping.  Note how scattered they are.  A human would have to shake their mouse very fast to get this effect.'\/><\/td><\/tr><tr><td class='insetcaption'>The bot in the distance is using a gun which shoots green orbs which travel in a perfect line without ever dropping.  Note how scattered they are.  A human would have to shake their mouse very fast to get this effect.<\/td><\/tr><\/table>Foes should not have superhuman aim.  The old-school approach was to just have the enemy determine the perfect shot (an effortless calculation) and then have their aim randomly spread around that point in some sort of Gaussian distribution.  This is serviceable in many cases, but falls apart when the enemy is using visible projectiles.  In Unreal Tournament, low-challenge bots  would spray projectiles like they were shooting from a sputtering garden hose.  This distribution never tightened. Even if both the bot and their target were stationary, the bot would keep the same bullet spread.  Human  players don&#8217;t shoot like this unless they&#8217;re being electrocuted while playing.  <\/p>\n<p><table width='384'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/ai_targeting2.jpg' class='insetimage' width='384' alt='ai_targeting2.jpg' title='ai_targeting2.jpg'\/><\/td><\/tr><\/table>A struggling human player will generally begin aiming with large, sweeping motions, making smaller and smaller adjustments until they settle on the target, even if it&#8217;s moving.  The target can quickly change relative velocity to foul this process. The result is human players weaving and hopping to keep their relative velocity as unpredictable as possible.  For AI, the accuracy should start out very low on a moving target and go up to near 100% as the AI draws a bead on the player.  It doesn&#8217;t make sense for the AI to miss 30% of the time when they&#8217;re shooting at an immobile player at point blank and also missing 30% of the time when they&#8217;re shooting at a sprinting player at thirty meters. Just having them miss 30% of the time (with the number going up as distance increases) will not produce believable behavior.  More importantly, it will homogenize enemy combat effectiveness, thus making player choices less meaningful (why bother to engage in a way that&#8217;s unfavorable to the weapons the enemy has, if they will perform just fine anyway?  Might as well just charge headlong into every fight) and thus less <a href=\"?p=4496\">interesting<\/a>. Battles will start to all feel same-y, and people will complain that the combat feels &#8220;bland&#8221;. <\/p>\n<p>Beyond this, how the AI aims depends a lot on what sort of game you&#8217;re making.  Are you going for a &#8220;tactical shooter&#8221; type simulation like Operation Flashpoint, STALKER, or WWII game?  Or is this a run-and-gun action game like DOOM or Max Payne?  (FEAR is an interesting example, since the AI behaves like they&#8217;re in a tactical shooter but the player can act like they&#8217;re Sgt. Bullet Sponge. You&#8217;re Duke Nukem up against the foes of Operation Flashpoint. This might be a big part of the appeal of the AI in that game.  They act like like a plausibly realistic squad, but you can charge in using slo-mo and <em>see<\/em> them at work instead of fighting them from a distance where their teamwork isn&#8217;t as visible.) In a more action-styled game, you actually want a bit of unrealistic behavior because you&#8217;re trying to keep up the action-movie feeling of the hero rushing through a hail of bullets.  The bad guys are <em>supposed<\/em> to miss, up to a point, but they need to just &#8220;nearly&#8221; miss.  Ideally they should be using lots of tracer rounds, and when they do decide to miss they should be aiming in such a way that their bullets still pass somewhere in front of the camera or strike nearby objects that will do interesting things.  Glass bottles shattering, wood splintering, pipes leaking.  <\/p>\n<p><strong>Friendly Fire<\/strong><\/p>\n<p><table width='400'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/ai_targeting3.jpg' class='insetimage' width='400' alt='Kane &#038; Lynch' title='Kane &#038; Lynch'\/><\/td><\/tr><tr><td class='insetcaption'>Ignoring the fact that the officers seem to be firing into the crowd, or the fact that they shot up the wall for no apparent purpose, and the fact that one of them seems to have taken cover in FRONT of the squad car&#8230; Actually, that&#8217;s an awful lot to ignore.  Anyway, Officer Dumbass (right) is being pretty relaxed about shooting over the head of Officer Fodder. (center)<\/td><\/tr><\/table> Assuming the AI is playing the part of rational human soldiers (as opposed to heartless aliens, mind-controlled forces, or robots) then the AI should hold fire if it would be at risk for hitting friendlies.  Either you&#8217;ll have enemy soldiers mindlessly shooting their comrades in the back, or you&#8217;ll have them shooting through their comrades to hit the player.  Either one is an AI failure. Most games have nailed this, but I think foes are usually inhumanly aggressive when shooting around their allies.  They basically do a hit test and see if pulling the trigger would result in hitting any ally.  If not, they fire away.  This results in bad guy #1 standing shooting at you, and bad guy #2 standing ten feet behind him, shooting just 10cm over #1&#8217;s left ear.  <\/p>\n<p><strong>Ammo Conservation<\/strong><\/p>\n<p>This is one that games have yet to tackle (among games I&#8217;ve played, anyway)  but it&#8217;s a major annoyance of mine.  A bad guy pins you down behind some cover and then just plinks away at your hiding spot.  Endlessly. Even if you hold your position for five minutes, the AI will just drill away at you without ever worrying about running out of ammo.  And when you finally DO get out and kill him, he has nine bullets.  Maybe he shot at you for five minutes, or maybe you took him down in a surprise attack. Either way, you always kill him nine bullets short of empty.  <\/p>\n<p>It would be nice if suppressing fire started out intense, then fell of to bursts, then eventually tapered off to single rounds.  (Depending on the weapon.) You do want the bad guys to try to pin down the player, but you don&#8217;t want them to abuse their gift of infinite ammunition.  They should at least <em>pretend<\/em> they don&#8217;t have infinite ammo. (And actually running out of ammo is out of the question.  It would make the game very exploitable, and programming proper behavior for a weaponless AI would be very difficult.  You don&#8217;t want to spend ages developing and polishing a situation you don&#8217;t want to have happen in the first place.)<\/p>\n<p>And while we&#8217;re on the subject of cover fire, AI is usually very bad about cheating when you go into hiding.  If you duck behind some crates and slip out of the room, the AI generally won&#8217;t continue to douse the crates in suppressing fire.  Instead, they move to give chase because they&#8217;re clairvoyant and know you have left the room, even if they can&#8217;t see you.  There was one game (I think it was <a href=\"?p=1321\">FEAR<\/a>, but I&#8217;m not positive) where the AI didn&#8217;t cheat like this and I was able to flank them.  I came around and found a group of guys blasting away at the spot where they had last spotted me.  This was a very impressive moment, and blindsiding them was a right and proper reward for my quick thinking.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>So, your AI routine is running. Taking into account for the enemy field of view, light levels, camouflage, distance, cover, and general threat awareness (like, are there any suspicious dead bodies lying around?) the program has determined that the bad guy has, in fact, spotted the player. Time to start shooting. Not so fast.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-4113","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/4113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4113"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/4113\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}