Another quick observation from my perusal of "Call of Duty 2" for Xbox 360. I've noticed rather often that, when I toss a grenade, the intended "recipients" seem to know that it is coming as soon as it leaves my hand. They will yell some German variant of "Holy crap, there is a grenade! Run, dude!" This is all well and good if they are seeing the grenade coming and would like to amscray prior to its arrival. However, the quirky behavior comes in when I am doing something like bouncing it off a wall around a corner. I will hear them shout prior to the offending pineapple even making it to the corner that I am trying to circumnavigate. In other words, they either saw the grenade through the wall, or there is some sort of mirror-like sheen on the wall that allows them to see it coming.
The programmers seem to be using a messaging architecture wherein an event triggers a reaction in all agents within range. For example, if the grenade were to explode in front of them, the explosion itself would send a message out to nearby agents saying "if in range, die violently". Messaging architectures are opposed to polling architectures where the agent is constantly looking through his environment to see if there is something to react to. Using the same example, the agent would constantly have to scan the nearby world to see if a grenade has exploded. Since grenade explosions are relatively rare, this would be a lot of wasted CPU. As you can see, messaging architectures are more efficient for event based situations.
In this case, the landing area of the grenade is roughly calculated. If the projected landing spot is near an agent, they react appropriately. They yell out warnings and move away if necessary.
However, the programmers would have faced a quandary as to when the grenade itself should send a message. If you wait until it lands or bounces off of something, it would discount the very possible scenario that they could have seen it flying through the air in the first place. If it is triggered when it is thrown, it creates the issue I observed above - that they know it is there despite the fact that they should not be able to see it at all.
One solution (albeit not a very efficient one) would be line of sight checks along the path of the grenade. Once a grenade launch has happened - and a message dispatched to the agent - the agent would now have to do a line of sight (LOS) check. If the grenade is visible, all is well - react appropriately. If it is not visible, the agent would have to change techniques to a polling architecture specifically doing periodic LOS checks at the grenade. When you consider that there may be 10 or 20 agents (friend and foe) in the area, multiple grenades in the area, and each agent-grenade LOS check would need to be done many times per second, the computational overhead adds up very quickly.
Another potential workaround would be to create a plane that is the intersection point of the path of the grenade and the visible area of the agent. At that point, the "see grenade" event can be triggered once the grenade passes that point. That seems to be not much of an improvement since there would be as many planes as there are agents and the grenade would now have to poll the planes many times per second. The overhead would be similar to the first example.
There is another way of handling that, however. Once the plane is generated, the distance from the source to the intersection of the plane can be calculated. Since the velocity of the grenade is near constant, the time delay until the projectile reaches the plane can be established. The message can be sent with a delay of x number of frames (or any other way that the game loop timer is built) so that the message is delivered and activated at the point that the grenade would have come into sight. No polling is necessary at this point. Just like before, a single event message is sent. The only additional overhead would be creating the planes representing the lines of sight for the agents in the area. In fact, if the LOS check is successful at the beginning of the throw, the plane creation is not even necessary. If an agent is going to yell to his squadmates about the throw, you don't need to do LOS checks for them at all - they already know. It would take some testing to find out how much overhead this eats up, but the result would be that you could do stealth/surprise grenades in a much more realistic fashion rather than the current "I saw it coming around the corner" effect.
I was playing Call of Duty 2 on XBox 360 last night. I've already gone through the full campaign on the normal difficulty and am now about halfway on "Veteran" ("...you will not survive").
Enemy Invulnerability: "I can't be bothered right now."
I was on the level where your convoy through the town in Tunisia gets ambushed. I had to start it over and over because I was getting pelted by the guys on top of the walls. I finally got down where I should hide and who I should tag first. One thing kept bugging me. There was a string of guys appearing on one wall in order. Most of them were gunners shooting at me - but there was one that had a Panzerschreck. I would try to shoot him over and over and he wouldn't die until he had fired at one of the tanks/trucks in my convoy and blown it up. In the mean time, another one would pop up and take me down. I realized that it was pointless to try to kill this dude at all. He wasn't going to kill me and that tank/truck was going to blow up anyway. It was part of the level.
What annoys me, however, is that it took me a number of times before I realized that, until that guy got his shot off, he was invulnerable. As soon as he was done with his job (that I was trying to prevent) he was now able to be shot. I wasted valuable time and got very frustrated by the fact that the level designers had decided that this was such a required series of actions on the level that they would break the rules.
I have found other instances where I have tried to peg some dude that was threatening me and was dead in my sights only to find that he had some sort of mission that couldn't be stopped. That really exposes the scripting in the game. I understand why the scripting is there - and, in general, it is very well done in the game. I very much love some of the actions that happen despite the fact that I can tell you the exact line I crossed in order to trigger the action - but usually they are too fast for me to react to or something that is meant to be just watched anyway. Don't let me point at a guy and unload an entire clip into his spleen while he doesn't seem to care that I am there.
To me, it seems like this is a case of the "anti-sandbox" concept. Sure, a somewhat linear game like CoD isn't meant to be a sandbox - and there are certain things that have to happen to advance the plot. That's fine, but I always feel cheated when I can't change the series of events even if I do the right thing to disrupt it.
Enemy Omniscience: "Am I wearing an orange hunting vest?"
The other thing that I noticed the other day is that, while I can sneak up on some people from the side once in a while - which is very satisfying - there are other times when someone will spin 45 degrees to point right at me despite the fact that I am peeking between some crates or barrels or sandbags. It is almost as if I just barely moved into a place where the ray-trace succeeded and told the enemy that I was now visible. This is fine if I walk around the corner or pop up behind something, but it seems odd when only 2% of my body is visible. The result is that it seems like the AI is omniscient (i.e. cheating) as to my whereabouts. In some respects it creates excitement, in others frustration. I know that they aren't trying to create Thief or Splinter Cell. Stealth isn't the focus of CoD. Still, there are times when hiding is a requirement of the game. Don't cheat me out of those brief moments of respite.
A possible solution to this is to measure how much of me is visible and then combine that with a coefficient based on how far "off center" I am from their current direction of vision. Perhaps another factor based on movement. I know that is a bit expensive to calculate for each AI (since their fields of view would all be different).
Another potential solution is to cast multiple rays to different parts of my body - perhaps shoulders, head and a couple of lower torso spots. If more than ONE is visible, then I can be seen. Not knowing exactly what mechanism they are using, it's difficult to know how to improve upon it.
This is even more alarming when it is obvious that there is a bias towards firing at ME. I may have 10 squad members all hidden behind objects and taking pot shots at the enemy - or even running around in the open, but damn it if the AI doesn't want to fire at me instead. It doesn't happen all the time, but it is obviously biased more towards me than my squad-mates. This is an obvious design decision to make it more exciting. I understand that. However, when combined with the omniscience above, it's kinda creepy.
[note: I've realized that waiting to write one complete writeup on a game is sometimes prohibitive - so I will write as I think of things... and tag them by game so you can find all relevant stuff]
Just a quick note, make sure you check out our other blog, "IA on AI". That is where we will be posting links to interesting stuff on the web about AI or game development. Just thought you may want to know!
Over the past 4 years, my family has spent way too much time playing Mario Kart: Double Dash. Given that my kids are teenagers, we billed it as “driving lessons.” Only one of them has taken the wheel rather than the controller pad since that point and we have yet to see any ramifications (if you will pardon an obvious homonymic pun). However, there were times when my wife and I would feel an overwhelming need to swerve to avoid a non-existent red shell or banana peel. At that point, you begin to realize that you have played a game too much. Which had about the same effect as me realizing that I need to lose 20 pounds – it’s nice to acknowledge it, but changing the behavior is something else entirely. Which is why we continue to have family fests and beat the snot out of each other to the ultimate climatic moment of Rainbow Road.
Anyway, many years of playing the game have taken another toll on me – I have not been able to stop myself from making mental notes about the AI and the game design decisions that went into making it tantalizingly addictive. I even mentioned as much to Steve Rabin, Senior Software Engineer at Nintendo of America, while we were having a beer at one of the ubiquitous evening fests during GDC in 2003. If you have ever met Steve, you know that he would make for a fantastic poker player in his ability to not show a reaction. Therefore, I have little idea if the observations and conjecture I made about the DD AI at the time were even remotely close. I would like to think, however, that there was a twinkle and a smirk. Of course, I have no reason to believe that Steve was even involved in the development – perhaps he was just amused at my enthusiasm.
Anyway, here are some of the observations that I made over the past few years. (Has it been that long?) Forgive me if I get either too simplistic or too esoteric…
The State of Racing...
One of the obvious characteristics of the AI is its use of FSMs. This is something that is in use in most games today on some level or another. However, there were some distinct points where it was very noticeable that the AI was switching. For example, once you crossed the finish line, your team either went into “celebrate” mode or “whiny pout” mode. These were simply repeating animations that continued throughout the duration of the post-race promenade (for example, while you are waiting for your wife to finish because you left an ocean of banana peels for her to wade through causing her to look strikingly like Kristi Yamaguchi doing non-stop toe loops down the final stretch). However, if you are to get whacked in the behind by an errant shell, you will immediately transition into the crash state, then the “stunned recovery” state for a few cycles of the animation (about 2 seconds). Then, magically, you will begin to celebrate once again. It makes it very easy to see that there are very defined edges to the states (and likewise the animations).
The major states, then, seem to be as follows:
Pre-race
Driving (with occasional sub-animations)
Toting and throwing items
Crashing (various types)
Recovering (such as dragging along behind the car)
Post-race victory or bitching
There are some sub-states mixed in there for the more subtle animations, but they are usually very short-lived. The driving mode, especially, has extra states for turning, sliding, punching, taunting or even just looking around because there’s nothing going on.
One side effect of this is that the animation will get slightly muddled, for example, when you have multiple collisions in a row (especially in a tunnel). The way they get out of this is to give up trying to transition properly and simply reset the car on its wheels. It makes for an awkward flip
To Drive... the Invisible Path...
The AI racers don’t necessarily navigate freely along the track. They follow the technique of using invisible paths laid over (under?) the course. There are multiple lines on any given track and the AI will choose which one to follow at any one time.
The reason that this became apparent to me was the first time that I saw two opponents in front of me fighting for the exact same stretch of road. There was more than enough room for them to maneuver, but they insisted on being in the same spot for some reason. What’s more, that “spot” was meandering back and forth along the course… as one car drifted left, the other went right along with him. As they drifted back, they did so together like Ben Hur’s chariot trying to dice up his competitor’s wheels. Not only was the path dumb and the colliding dumb, they were being dumb in sync with each other. Solution? Put a repulsion vector on each other so that following the path is not as high a priority as keeping from scraping paint.
I’m not entirely sure what causes the AI to switch paths. Obviously an event like a spin or crash would cause the AI to pick up a new line. However, it is difficult to tell of the AI changes lines when nothing else is happening – like a cross-country skier stepping into a new pair of tracks. This does, happen, however. I’m just curious as to when and why. Certainly not when they are bumping and grinding down the straightaway, however.
There is another factor, it seems, behind why the paths are the way they are. Not all paths are created for all cars. If the AI is in one of the big heavy cars, for example, they will tend to pick a path that wanders back and forth across the track. This is very noticeable with Wario’s purple beast. He drives like he has imbibed heavily. This is an interesting balancing mechanism – Wario’s car, like other larger cars, is fast once it gets up to speed. If that were left unchecked, once he passed you, he would be a bitch to catch up with. However, if that speed were spent meandering all over non-optimum lines, it slows down his progress and makes for a neat stylistic appearance as to what we get out of ol’ Wario’s character. It is difficult to know what exactly is happening behind you in the race except on such short tracks as Baby Park. Does Wario drive like a drunk moron when he’s 3 places back or only when he’s in front of you?
That brings me to another point… rubber banding.
The Search For Equality…
Rubber banding is one of the most misunderstood aspects of Double Dash – and probably many other games that utilize this technique. Really, it is also a point that blurs the lines between AI, simulation modeling and the basic game design decisions. There is a staggering amount of this going on in DD.
First there is the speed of the cars. In general, when you start a new “Cup” (group of races) and the game “picks teams”, the AI will also assign a general skill level for each car. Throughout that cup, the running order will generally be the same give or take a couple of places. The same 2 cars will generally be in the top 3 and the same two cars will generally be in the back of the pack. This is obvious after having finished a 16-race cup and having one car have a single-digit score – which is only possible if you are continually finishing either last or 7th. Also, if you are a trained professional like I am (I have to look into some form of Mario Kart accreditation or certificate), you will realize by about the 2nd lap of Luigi circuit which of the cars you will have to put up with for all 16 races. [misc. editorial rant: Damn big, fat Peety-head!]
There seems to be three ways they go about stringing out the pack like this:
1) By simply using the published speed of the cars. The fast cars will tend to be toward the front, whereas the putt-putt-mobiles will be in the rear. That means that those first two cars you have to contend with as a good driver will be the big, fast cars. 2) By varying the published speed of the cars. Just because two cars are 3-star speed, doesn’t mean they will always go 3-star speed. This is good in that there are more speeds in practice than the 5 possible stars that the cars are rated at. 3) By varying the time they have their “foot on the gas and brake”. Again, this is visible on Baby Park when you lap someone. If you watch, you will see them move forward in fits and starts as if they are only “hitting the button” intermittently. It’s a nice effect that makes them seem unsure of themselves.
However, the above isn’t rubber banding – it’s just spreading out the pack. As you improve in your skills throughout the game, you will notice that you will usually have a fair amount of company… within reason. If you stop dead in the middle of the track for a minute, don’t expect the AI racers to be sitting around having coffee waiting for you to catch up. However, there will be some noticeable slow-down of the entire pack. Likewise, if you are good, the whole pack will be slightly better than normal. One way of noticing this is if you have two human players of differing ability. You will see such things as the pack stringing out more than usual to accommodate the different players, the lead player running away with the race as the pack holds back or the poor player getting completely skunked as the lead player pulls the pack along with him. I’ve spent too much time racing and not enough time testing this phenomenon, however.
Another method of rubber banding is one that people refer to as “cheating.” (This is likely because it is frustrating… imagine that.) If you are in the back of the pack, you can plan on getting better “stuff” from the boxes. If you are in last, you will be fed a steady diet of mushrooms, stars, lightning bolts and blue shells. If you are in front, however, expect to get green shells, fake blocks and the occasional potassium fix from bananas. It should come as no surprise, therefore, that the AI racers in the back of the pack are the ones getting the lightning bolts and the blue shells. (One note, it IS possible to have a blue shell by accident when you are in front… which means you get to hit yourself with your own blue shell!) If you watch on Baby Park, or keep your eyes on who is the one not getting zapped by the lightning bolt, you will see that the AI is getting much the same load of goodies that you are. I concede that it is possible that they are getting more aggressive stuff, but it is not outright “cheating” in the AI sense.
Now, there does seem to be a change in that algorithm as the race progresses. If you are in last on the first lap, there isn’t as much of a sense of urgency. If you are in first on the first lap, you won’t be getting assaulted non-stop. However, in both of those positions, things seem to change as the race wears on. If it has been smooth sailing for the first two laps, you can expect to have attracted a bit of attention on the third one. Perhaps it is this phenomenon (and the resultant indignation that ensues) that causes people to cry foul. However, once you have been in the position of playing catch-up on the final lap, you will realize that the game is more than happy to dispense one killer weapon after another in order to help facilitate retribution upon the AI. This is even in play on a multi-player race without the AI even being present. So again, this is a game design decision in order to further exciting races.
In the Pursuit of High Drama…
A couple of notes on artificially generated excitement… I can’t tell you how many times (probably because it is now into 4 digits) I have been on the final lap, in 2nd place and within striking distance of the 1st place car, but seemingly without hope… and it has driven straight into the only banana on the entire planet. It is almost as if the AI has gone out of its way to encounter the treacherous fruit leavings! Sometimes that is enough for me to make that last pass to win. Other times it is only enough to make the ending that much more exciting. Is the AI hitting that banana on purpose? Is it simply that the object was dropped onto one of the invisible paths? Does the AI drop objects onto the paths on purpose? This I can’t tell you.
Another observation I have made in this vein is that things that green shells don’t seem to have studied for their Physics 101 final. I swear that green shells, upon hitting walls or other obstacles, will uncannily bounce so as to cross in front of you. It happens too often to be coincidental. Similarly, I have seen green shells bounce off of objects at unlikely angles to strike the AI car in front of me a la the “lone banana” phenomenon above. I know that this is not a hard computation to make… just a little quick vector math based on the path of your car. Therefore, it is my estimation that this is a subtle trick to make the game environment a little busier in the right way. Make it look like things were really dangerous – especially when my back-seat sister forgets what she’s doing and throws green shells forwards instead of backwards.
Things That Work…
In general, Double Dash is a very well done game from the point of AI. I remember way back when we started, I never felt hopeless (until I hit Rainbow Road for the first time and fell off so many times I started laughing until I cried). On the other hand, now that I can’t even beat my own best times any more and have therefore maxed out my own (rather capable) abilities, I still run the risk of not finishing first on some of the races. I prefer winning games only about half the time, and, even after all these years, Double Dash hasn’t slumped back into the role of being a pillow for me to beat on mercilessly. While I tend to finish first on most of the races (80%?), getting a perfect 160 is still a goal rather than a given. I attribute this to the excellent rubber banding in the AI and design decisions.
The characters use their weapons well and intelligently for the most part. The driving makes sense, even when it wanders around the track. The character animations are engaging and amusing at times. (Being a Yoshi player, I am always tickled when he stands on the back of the kart looking “vigilant” glancing left and right to see what’s up.)
Things That Could Improve…
Sometimes, I wish that the AI states were just a little more obscure. It isn’t distracting or annoying, but I want there to be a little more subtlety to them. This is not that big of a deal, however, especially since we aren’t dealing with life-like, human characters. The effect goes quite well with the cartoony feel that is a trademark of the Mario games.
All in all, for the style of game that Double Dash is, the AI worked very well. Otherwise it wouldn’t be one of the top Game Cube games in the history of ever… still. And I wouldn’t still be playing it!
So… is there anything that you have experienced that I may have missed? Is there anything I said in here that is completely out of whack? Drop in a comment! One thing I would be very amused to find out is that I have chalked some effect up to the AI when it wasn’t really there in the first place. Now THAT is the sign of a good design (or an AI programmer who wants to believe in things waaayyy too badly!).
Well, as I get my thoughts together (the process of which always involves the decision on whether to use a fish net or a butterfly net) on which games I should do first, it brings me to a larger concept of "what games should I do at all?" Of course, I am necessarily limited to commenting on games that I have already played. What would be the point of analyzing the AI of a game that I haven't played? On the other hand, I have experienced some games where, despite having played all the way through, it was as if the AI was never there. Anyway, I digress. (Where's my net?)
I thought that I could toss out a list of games that I remember having made mental notes on regarding the AI and see what you, my loyal readersthe hapless wanderer into this site, may be interested in hearing about. So, here's a partial list of games that I may be interested in, and at least minimally prepared to comment on.
The games I have been playing recently are as follows:
Madden 2003 (PC) (is there's a point since this is now 4-5 versions old?)
Some classics that I would like to revisit at some point:
Railroad Tycoon II (PC) (did that game have legs or what?)
Civilization II (PC) (speaking of replayability!)
Creatures (the original one) (PC)
Rainbow 6 (PC)
Starcraft (PC)
What would really be crazy is for me to go back to the 80s and talk about some of the games I played back then... like North Atlantic '86. It's kinda funny to think that a game in 1985 actually had AI, isn't it?
Anyway, if anyone has any preferences on that list, let me know. I will probably bust loose on something either very recent (like my meandering through NWN2) or something I can write at length on (like how my whole family has picked apart MarioKart: DD) for my first review. Keep an eye open!
For a long time now, I have been reading other people's blogs. As we all know, that can either be a good thing or a bad thing. (Strangely, this seems to depend largely on the quality of the blogger. Something to consider.) Also, for many years, I have been active on message boards all across the Internet. I've had my say on an item or two... but even the most Homeric of posts and threads always seem to get scattered in the Winds of the Net - never to be found again.
As a game developer, I play many games. I consider it "research". This is not a stretch, really. After all, scientists read each other's papers and even cite them while composing their own... and they call THAT research, right? And when I am playing games, I can't help but analyze them. What makes them tick? What ticks me off? What makes them tick me off? I can't help it. I'm wired that way.
Putting the two of them together makes for an interesting experiment, however. After all, it was playing games - and either lauding or complaining about those very games to my brothers and my friends, that got me interested in developing them in the first place. You see, I felt that the observations and opinions that I was expressing at the time were actually worth something - even if only to me by making me ponder a career in the "gaming arts." Since that time, I have had the opportunity to share comments with many people - both in and out of the industry. I have found that the process of breaking things down and discussing them makes for an educational experience.
However, it has always been disheartening to have my comments (and the conversations of which they were a part) be so ephemeral. It occurred to me (during a fairly frenetic bitch session about the current game I was playing and really to no one other than myself) that I would like to make my observations, discoveries and feelings known - but in a way that didn't evaporate into an abyss of tangentelized commentary that public message boards have a wont to do. So, gee... I figured I would jump on board the ever-burgeoning bandwagon of blogs on the net in some misguided, narcissistic fantasy that people really care what I say.
And for some odd reason, you are reading this post. (Probably because you are a friend or family member... and you feel sorry for me.)
I am not sure how often I will post my analyses. Even using my company's funds for a "research budget" has its limitations (like every dollar that IA pays out doesn't go into my pocket in the end... duh.). I plan on going back through some of my favorites from by-gone eras. And since I started gaming in the early 80's, that is almost something equivalent to saying I'm going to start reviewing literature with tomes that were penned in about the BC/AD changeover. That's a bloody long time ago as far as computer gaming is concerned!
My plan is to be a spin-off of the industry concept of a "post-mortem". That is, when a project is through with development, the team goes back through and analyzes what happened. What worked? What didn't? What did we learn? Well, in that spirit, I've decided that a "post-play'em" would be my musings after having played a game. What worked? What didn't? What did I learn? What the hell were they thinking?
Of course, being an AI and simulation modeling kind of guy, I will generally have a tendency to lean in that direction. I fully expect that my ramblings will make far more sense to an AI guy. (Which is, actually, almost a pejorative.) Given that, however, I'm rather hoping that my audience can go beyond the handful of scary AI programmers that I associate with (Hi Alex!). I mean, I will in no way be the Irate Gamer or Yahtzee of Zero Punctuation fame. As much as I admire their snarky wit in a twisted sort of way, that's just not my function here. Not that I won't rip on an AI programmer or level designer from time to time... sometimes that is just necessary... and even a bit cathartic. I guess we'll just see, eh?
So you don't have to continue to check back, however, I invite you to subscribe to the RSS feed that is available. Tuck it into the rest of your feeds and give it a glace once in a while. I hope to at least amuse you from time to time even if I don't have any salient points to make about whatever game I am reviewing at the time. And if you are not educated or amused? Well... it's the internet, right? Who told you that everything on the 'net was quality stuff?