Dev Diary: Metrocide’s AI & Systems
This is a developer blog by Rohan originally posted on Gamasutra, titled “METROCIDE, or, How I Rolled My Own Cyberpunk Dystopia“.
In early April, a collection of us at Flat Earth Games, fresh off a family-friendly crafting/city-building game, decided to kill a lot of people. Virtually, of course. I suppose partly it was a reflex reaction from a year or more of making a game where it was literally impossible to die. But it was also prompted by the question of “what kind of Cyberpunk game would we want to play?”
See, it was a game jam. A ten day one – the 2014 Cyberpunk game jam. And to us, used to 48-72 hour jams, 10 days felt like a life-time. So why not really go to town? We could surely do an action game in that time. What if we did a full-on cyberpunk action game where you played as a contract killer? We were thinking a real-time, action version of the kind of game we imagined we were playing with the 1994 Genesis “Shadowrun” game.
Of course, that’s insane – but slightly less so if you cut down your scope a great deal. So it’d be totally top-down, pixel-art, and permadeath. The art could be turned out by all of us, I could build the city out of tiles so a map editor would be easy to create, and by focusing on a death-at-every-turn permadeath style, we’d limit the need for save formats AND give a nice, bleak feel to the gameplay.
It’s now October, and we never finished the jam. Instead, finding what we had was something we really loved to play… we just kept going. We release on Early Access in a few weeks on Steam, having created – largely from scratch – a pretty solid 2.5D semi-open-world hitman game. We’re pretty psyched. But really, I’m only explaining this to give some context to what I’m about to talk about – which was building the AI and behaviour of cops, citizens and bureaucracies of a cyberpunk dystopia.
One of the first things I knew I needed were citizens. Poor, unhappy schmoes milling about the world, acting both as landscape and – more importantly – terrified figures who’d react realistically if they saw you, y’know, murdering, lugging bodies around or aiming high-powered rifles about the place. And I was going to need a lot of them. We’d decided on splitting up the city into several zones – each getting larger and more difficult as you unlocked them. This was partly, of course, because a one-person coding team like yours truly isn’t going to be able to create a fully scalable open-world city like you see in AAA titles these days. The other reason was that perma-death and escalating difficulty seemed to lend itself naturally to escalation in its areas, too.
But each area was still going to be large. In our future world, jetsons-style hovercars and mag-lev trains are the only forms of transport other than walking – what used to be streets for cars are cracked, strewn with garbage and essentially just oversized pedestrian walkways. But even with our Pixelzens and our player moving about solely on foot, the levels were big enough that we knew we needed a good several hundred NPCs at any time to give the different areas the right level of “busyness”.
So I began to figure out ways to let me run hundreds of NPCs without slowdowns, despite not being anything close to a Carmack when it comes to designing engines. (Our last game maxed out at around 16 mobs on the level)
The first trick was to keep it grid-based. The map is assembled, as I’ve said, out of tiles. This meant that even though all NPCs ar free to move about the map as they choose, I could do all the pathfinding on a tile-by-tile basis. Some tiles have walls on one edge, and some are entirely solid (buildings, etc). This meant that a basic A* path-finding algorithm would do for making our NPCs calmly walk around the streets. Each tile would become a node.
Then, when moving between nodes, I’d have to do proper collision detection. I broke up all objects in the game world into ‘passable’ and ‘non-passable’ items, and kept the non-passable items in chunks so I could do make the broad-phase collision detection fairly inexpensive.
Then came the real fun. Artificial Intelligence.
Once I had NPCs pathing, I had to make the world come alive.
For lots of game developers, the illusion of a living world is enough. But for me, there’s a reason my “perfect games” have tended to be things like Ultima VII. And that reason is I just love watching virtual worlds. I spend hours in open-world games just watching people react to each other, and do things without my prompting.
So, while it’s not always the best design solution (simulating, that is) for my own personal enjoyment… that’s what we did in Metrocide.
I began by generating personalities, at least in terms that’d make a difference for behaviour and purpose in the world. Are they confident? Are they violent? Are they law-abiding? Are they smokers? Are they paranoid? These were either sliders or binary settings, and with all these generated using a dice-roll style (to skew roughly towards the middle in every case), I began to give them behaviour.
After generating a name, a sex, a sexuality, a marital status, a family, pets (okay, so I was going overboard a bit), a personality and a home for each person, I then tried to figure out what they were doing. Visiting friends? Going out to a club? (We labelled clubs and other notable places on the map as ‘points of interest’) If they’re a smoker, perhaps they’re just walking around the corner to huff a cigarette without their partner finding out?
As a result, each person walking about the city has a specific purpose. Some will kill time wandering for ages, others will hurriedly walk two blocks away to have a cigarette in an alleyway before heading home, checking behind them all the while.
It’s a little detail that almost no players will ever notice, but internally it made sense to me to know just what the characters were doing and why. It meant that when I then got to code the reactions our NPCs should have to seeing acts of violence or dead bodies, I could better figure out what they might do.
On your way home from the shops and you see a body, drenched in blood? Damn! Better see if the poor guy is okay, and then call the cops if he’s not.
What if you see a person with their gun out? Well, how would YOU react? Would you freeze right there and desperately struggle for your phone so you could call the cops? Would you leg it home? And then call the cops? Or are you some gun-toting nut with a high aggression and few law-abiding tendencies? Maybe you’ll turn vigilante.
But here’s the rub: this isn’t just the code for NPCs reacting to the player; this is reacting to each other, too. Genoa Smythe, a 31-year-old vex-head who’s quite psychotic and carries a pistol, will react to seeing someone with a gun out whether or not that person is our player character – the world reacts to itself. That was important to us.
The result is exactly what we’d hoped for – an environment where all sorts of insane things can happen. A typical story might be that you’re hiding in an alleyway, waiting for your target to pass so you can blast him apart with your blaster. Raising your weapon and starting it charging makes a sound, and your target turns to face you. Unluckily for you, the reaction times of the target and the fact that he is *also* armed mean that he is very quickly pointing his weapon at you.
For a moment, you think you’re dead, as his pistol will fire much faster than your crappy blaster. But then there’s a loud bang as a shotgun goes off – neither of you noticed some gang-member standing on the corner until he saw your target (but not you, as you were hidden in the alley) raise a weapon… and he reacted as you’d expected. Some guy with a gun on my turf? I’m putting this fella down!
And of course this begin a chain-reaction. Someone sees this exchange and calls the cops – identifying the gang-member as the victim.
Soon the cops turn up, and a firefight with the gang-member ensue. Of course, all of this is good for you – you were paid to ensure your target became fish-food. Just how that happened was never specified. Result? No blame, but all the reward. Good job, TJ Trench!
It opens up a lot of interesting play-styles, too. Achievements for tricking bodyguards into shooting their own employers, hacking the police system to replace your wanted mug at a crime scene with some other poor innocent. It may have always been designed as a very tense, fast game, but that doesn’t mean we couldn’t find other ways to add nuance and complexity by the very way we built the simulation.
A created a fleet of cleaning droids, which would scour the city for waste, in a vain attempt to keep the city clean. They’d pick up cigarette butts dropped by smokers, newspapers dropped by other grotty humans… and even clean up the human remains and stains at crime scenes, replacing them with chalk outlines.
And then we got to the cops.
I began to muck about with Cop code. AI to make some of these little fellas 1940s-style beat-cops. Firstly: that’s kinda tricky. Engaging in complex fire-fights when multiple people should be working together as a team was more than the scope of (what had become) a six-month project would allow. Secondly: This is a horrible cyberpunk dystopia.
In the ’80s, our idea of a horrible cyberpunk dystopia was corporations running everything. Boy, how scary! Unfortunately, that’s more or less true now. The amount of power corporations and people with vast amounts of wealth have is enough to make that seem less like science fiction and more like, well… just the nightly news.
So what’d make this seem like a nastier update to the cyberpunk style?
Drones. That’s what. The military uses them now. UAVs. UCAVs. Hell, lots of private citizens do, too. You can buy drones at the Apple store that you can control from your phone.
It’s not the most unique idea in the world, of course, but from a gameplay and world-building perspective it seemed fascinating to me. Why not have our awful world of Metro City dominated by quad-copter-like things, repeating robotic phrases such as “REMEMBER: A productive person is a happy person” and “REMEMBER: Stay safe, citizens”.
Our world started becoming a little less Blade Runner and a little more A Boy And His Dog, and that was fine.
Soon I had police drones around the city, and began to code the back-end bureaucracy of PoliceManager. This was much more fun than I’d suspected. I created different modes for our flying police drones. Were they patrolling, escorting a specific citizen (Hey! Even police drones can be corrupt apparently), enforcing the area around a crime scene, scanning citizens for illegal weapons, or hunting down a specific person that had been identified? I created an internal management suite for the crime scenes. When a body was reported by citizens or cleaning droids, when a violent citizen was reported, the back-end looks to see if it’s near or similar to existing crimes, and may lump it into the one crime scene, or create a new one.
If it’s a new crime scene, or another one where a second or third body was found, a patrolling police droid might be re-tasked to investigate the scene. Once there, it will scan nearby citizens to see if they’re carrying illegal weapons. If they find someone armed nearby, they’ll try to take them out.
And if crimes persist… the police alertness level increases. Suddenly instead of two drones flying around the city, you might have six. So the more crime scenes the police find, the more invasive the police presence becomes.
Keep in mind that this means any violent activity can increase the police presence.
They may be after a gang member, but if you accidentally trigger a gun-fight that results in two new cop drones blocking off a main street and scanning passers-by, that just makes your job harder.
The more we added these kind of mechanics, the more we began to find what the game was really about. Given there’s no way to un-do actions, hiding bodies in sewers or water – or simply not being seen for as long as possible – became the most important thing to do in order to survive long enough to finish a level.
Almost all the gameplay elements we added came out of the emergent AI.
The idea of check-points to block off high-security areas like the rich residential areas in level 3 came out. Security cameras.
And then, finally… after months of play-testing and refining, we added one final thing to our sprawling mess of NPCs, drones and virtual bureaucracies.
Are the cops doing a bad job? Sure someone’s out there committing these crimes, but they can’t catch them? Has escalating the cop presence not done the right job? Well, then – there’s nothing for it: they’ll quietly call in a hitman.
They may not know your face, but by the time a handful of hitmen are hiding around the streets, watching and waiting with a subtly that the loud drones can’t manage… anyway… melodrama aside, the AI for those was quite fun.
So that’s what Metrocide is – a game which almost entirely came out of exploring what we could do with a virtual city.
I’ve got to admit that this has been a real blast. As much fun as it can be to play the game, I reckon I had as much fun crafting it over the past few months.
I’d always wanted to code a play-ground for emergent behaviour, and having done it now I can both see why people love games that do it, and why most game developers try to avoid it as much as possible.
We probably spent about half our design time dealing with emergent problems that broke gameplay. From cops scanning gang-members and all-out wars that turned a play-through almost un-finishable to bizarre combinations of game-stats that put our AIs into race conditions… it was a challenge. If we were doing this in 3D, or with more complicated mechanics such as driving and public transport systems… well, that’d probably have driven us insane.
And I am sure that even twelve months after release players will be finding strange ways to use (or mis-use?) the AI’s quirks and patterns to power-game or even just generate strange bugs.
But that’s kinda the fun of emergent (or simulation-based?) game design.