Tuesday, October 12, 2010

Monster Spawning

A little insight into my monster spawning routines.

The overmap, which holds macro map data with tiles like "a house" and "a subway station," as well as "forest" and "river bank facing east," also holds a number of monster groups.  These groups have a type, an origin (x, y), a population, and a radius.  The type is a moncat_id enum, which includes things like mcat_forest (woodland animals), mcat_zombie (typical zombies), mcat_bee, and many others.
It is assumed that monsters occupy a circular region (trig circular, not roguelike circular), with the greatest population density concentrated at the origin, (x, y).  The population density at any given square is determined by the equation (3.8 - (dist / rad)) * pop; where distance is the trigometric distance from the origin, rad is the group's radius, and pop is the group's population.  This is one of those cases where I wish I'd documented my code better; I'm not sure where the 3.8 value came from, but it's been heavily influenced by game-balancing.

The game holds a value next_spawn, which is a turn number.  When the player moves forward into new territory, the game checks to see if next_spawn is less than or equal to the current turn.  If it is, monsters get spawned, and next_spawn is increased.
The amount that next_spawn is increased by has changed several times, and is one of the single most important calculations for game balance.  Too low, and monsters are a constant worry; the player never gets a chance to breathe.  Too high, and monsters are only sporadic, and the game loses those moments of exiciting pursuit or intense combat.
Right now, next_spawn increases by a random amount from $low to $high.  $low is equal to the number of monsters spawned times three, plus the number in play before the spawn; $high is equal to the number spawned times eight, plus the number in play before the spawn times 10.  So, if there are 5 monsters in play, and 5 more get spawned, next_spawn will increase by an amount between 20 and 90 turns.  Or, if there are 20 monsters in play, and 1 gets spawned, next_spawn will increase by 23 to 208 turns.  And if  there are no monsters in play, and 10 get spawned, next_spawn will increase by 30 to 80 turns.
The idea here is that when there are lots of monsters in play, next_spawn will increase by a lot.  A large spawn on its own won't cause a big increase, but several large spawns in a row--basically, a rush or hoarde of monsters--will cause a very large increase.  This provides for a "cool down" period to reward the player after a big rush, allowing them to reload, heal, collect items, etc.
Note that next_spawn is generally only checked if the player is moving from one overmap square to the next.  This means that a player who is staying in the same place for a long period of time will not see any spawns.  This is good; if a player isn't moving, they're probably trying to heal up, and should be rewarded for their defensive tactics.  However, we do want SOME monsters to show up and disturb sleep occasionally--making traps and constructed defenses necessary.  With this in mind, the game will also check if next_spawn is 400 turns, or 40 minutes, overdue, and will spawn monsters in that event, generally at the very edge of the map (if the player has the Inconspicuous trait, this is changed to 2400 turns, or four hours).  Note that these monsters probably won't find the player right away--they'll spawn outside of the scent cloud, and if the player's smart and is indoors, out of sight of the player.
A few other things affect next_spawn, most importantly noise.  A player firing a gun will produce a sound equal to (20 + (ammo damage * .8))--with 00 shot, this will be 60.  Any sound of volume > 20 will reduce next_spawn by $min to $max; $max is the volume, minus 20 (capped at 50), and $min is $max / 6.  It is not only player-created sounds that cause this decrease; shrieker zombies are an important target because their shrieks are of volume 80.  This means that a 00 shot will, on average, cause next_spawn to decrease by around 25, making shotguns dangerous to use, except in emergencies, or when the player can handle (or desires?) a continuous onslaught.

I'd appreciate any feedback on the spawn system in Cataclysm.  Do monsters spawn too often, not often enough?  Do you feel as though you get a "breather" in between huge hoardes of monsters?  Does the increased spawn penalty for using noisy weapons feel fair?

Cataclysm has an undocument key, 'M', which will display the current turn number and the value of next_spawn.


  1. I would love to see some discussion on this project, like forums or some kind of message board! Or maybe a Q&A with the designer? :D This game looks so exciting and I can't wait for more info on it!

  2. Hello, I was just posting a comment to ask where I could download a compiled version of your game. It seems like a really cool game but I don't have the knowledge to compile...

  3. You learn a little about computers!
    Your skill in computers has increased to 6!
    You learn a little about computers!
    Isaiah Mitchell's brain explodes!
    You learn a little about computers!

  4. I know we're trying to get games that are constantly fighting to survive, but, at least for zombies, it would feel like an accomplishment to eradicate the horde in a town. Since towns are only so useful, and once you've taken the useful things out of it there's not much point in going back, it wouldn't really break the game to have at least some possibility of reclaiming a town. Necromancers could resurrect a town, but if you butchered EVERY zombie ...