Defining the Dungeon; How I Learned to Love Changing Numbers


Hello Itch, welcome to the inaugural devlog for Skulk. We’re building a game in the spirit of traditional ASCII roguelikes. You’ll be tasked with delving deep below the earth in a desperate search to free your neighbors. Gather food, conserve your steps and watch your back as you find your way through the cavernous mine.

Clears throat.

Please don’t mind my shameless hawking, but this is the first time I’ve spoken about our project on Itch. We’re excited to be close to an initial release! Let’s go over the progress we made last week, and then I’ll provide a preview of what we’re working on now.

Code Distillation

Over the week of July 22-26 2024 we finished building a prototype that was fun to play. It included the food, weapon, and mob mechanics, each with the simplest possible implementation. When evaluating this prototype we kept an eye toward the overall feel of the game, given that the numbers can always be tweaked around. I found that exploring the caves and trying to find the exit while scrounging food was enjoyable, and started to think about ways I could efficiently add depth and texture to the experience. An obvious first place to go was the mob/enemy generation system!

As it stood, we only had one type of mob to instantiate, the Orc. We examined the code and made a list of attributes that any mob would need, then created a CSV (comma-separated value) file matching that structure. We fed in the Orc’s existing data, then went to work on a subsystem to retrieve this “prototype” from the file. On engine initialization, the MobGenerator will check this CSV file and keep copies of each record’s values. The engine can then ask the generator for N mobs of type X, causing it to search its registry and perform the necessary die rolls to create a new entity.

Now we have a system where at runtime we can get as many copies of a pre-defined mob as we want. To test it, we simply replaced the existing mob generation code with a call to this new module. As expected, the game behaved exactly the same as before. We then created a few new mobs (the Gremlin and Zombie), afterwards editing the mob generation code to divide the total number of mobs by 3. It would generate 1/3 of them as Zombies and 2/3 as Gremlins, and everything was working as expected!

With the success we saw in loading Mobs dynamically, we decided to do something similar for the dungeon floors. We broke down a floor into a few attributes:

  1. Depth:
  • Integer.
  • First floor is depth 1.
  1. Mob1…Mob5:
  • String.
  • Every time we generate a mob on this floor, we will randomly choose one of these five.
  1. Weapon roll:
  • Die formula.
  • Quantity of weapons to generate.
  1. Weapon value:
  • Die formula.
  • Damage roll of each weapon.
  1. Mob roll:
  • Die formula.
  • Number of mobs to instantiate on this floor.
  1. Ration roll:
  • Die formula.
  • Number of ration packs to instantiate on this floor.

Satisfied with this structure, we created another CSV file matching the structure and loaded some test data for the first floor. Then we generalized the code we wrote earlier to be able to use it for both of these purposes, and integrated the data into the existing floor generation function. We started the game up and were pleasantly surprised to find that everything worked! The data from the CSV file was easy to load and plug directly into the existing logic. Thanks to the xdice Python library we were able to store die formulas within the data. We’re fans of tabletop RPGs here, so being able to think about things in terms of dice rolls makes it easier to reason about and tweak numbers.

Fleshing out the Dungeon

This week we’ve had a focus on the more creative aspects of the game. We wrote up quite a few more mobs and finished the floor definitions from 1-5! Then we spent some time playtesting and tweaking parameters to get the game’s economy humming. It’s difficult to strike the balance between the player accumulating too much food and starving to death, but we don’t think it will be impossible.

There was, however, a gnawing issue in our stomach as we played through the game…it’s too easy! As long as you aren’t turned to dust in one hit by a Tarantula there’s a very straightforward way to regenerate HP during combat. There are a few ways we’re considering to juice up the gameplay:

  1. Invisible traps:
  • Immobilization traps to discourage kiting.
  • Hunger traps to tax food.
  • Damage traps to introduce unexpected bursts of damage.
  1. Delay on player HP regeneration:
  • Currently the player heals every time they move onto an unoccupied tile and have more than zero food.
  • Proposed solution would cause player to be unable to regenerate for N turns after taking damage.

Get Skulk

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.