HELLTH: A 7DRL Design Story

MiroslavMiroslav
14 min read

This year was the 20th anniversary of the Seven Day Roguelike (7DRL) challenge where, quite understandably, you have seven days to make a roguelike game! What exactly is a roguelike? It's hard to define as it's been many things over the years, but in the context of 7DRL, I guess it would most traditionally be a turn-based, grid-based, single-player dungeon-dive that ends in either victory or death in which your character and your progress completely perish. Starting in the 80s with the game Rogue and going strong through the next forty odd years, roguelikes are really cool to both play and make. They often have very simple interfaces and an abundance of systemic content that leads to a lot of emergent gameplay, surprise, and fun that you get to experience once, then, there, which may never be repeated.

This year, I worked on a game called HELLTH. The idea was to have spell duration be tied to health bars in a very practical way: when you cast a spell, you get your health points (HP) enchanted. If you lose the enchanted ones, you lose the spell -- sounds simple enough.

Mobs can also enchant you, and you can enchant them, of course. There's also a "focus" system that plays into your turn economy: if you spend turns waiting and focusing on your spell, you can move where exactly it will land. For example, after a turn of focusing, the same spell from above would be like this:

This system then comes into contact with other factors and creates diverse opportunities, here's some player stories one could tell:

  • I love my health and I want my health bar to be full, but one third is enchanted with a spell that corrupts any of the items I pick up, so I need to lose it as fast as possible, but like... not die lol.

  • I have an enchantment that doesn't do anything too great (gives me +1 wisdom, which I don't need), but I'm saving it anyway because I can override curses that enemies toss at me with lousy spells -- they're far from useless!

  • HP starts emptying from the right, which means that those are the effects that are going to disappear first if I lose life. If I could spend my turns focusing on the spell I'm casting to move the enchantment to the left more, I'd use that a lot to secure my spellcasting.

  • If I could focus, I'd be sniping enemies with curses before running at them to take at least half of their life while they're under their influence.

  • It would be really cool if you could cast a spell that has different targets depending on the focus the spell was cast at. Like, say it's "Darkness" (like in D&D), then if I spend two turns focusing and cast it real deep, it spreads to like a circle of 5 tiles around the target, and if I spend one turn focusing, 3 tiles, and for fewer than that, affects only the target?

  • Can we have spells that activate once you lose the health point they're on? That would be like a trigger, it's very cool! Even, like, death itself could be a trigger like that, which means that if you know how to override it, you can make undead things. You basically get necromancers from this magic system without including them from the get-go!

  • I'm playing a barbarian build, right, just strength and agility. If I'm going against a lot of nerdy spellcasters in a game like this, I know that they can enchant me with more spells if I have more life, so it's a solid plan to lose life before attacking, get it down to some level where I think I can survive and then leap into combat and kill them before they can do too much harm!

I love writing player stories when designing games - they help me relax into thinking about an idea in different ways and approaching from the player's perspective. Hopefully, you now get how this works!

Contact with the Real World

Some time early in the jam (day 2 maybe), I realized I don't enjoy the Bevy UI I was going to use, and that most of my mechanics are... UI-based. My toolkit was suddenly feeling really narrow, but I wanted to see how it would work anyway! At this point, I started thinking about what my options are, and how I was going to tell people about what's happening. In MSPaint, it's easy to just draw things like "S" for spell, and people will understand, but imagine if I started complicating stuff...

This was one of the best designs in my early thoughts about HELLTH, a situation where two enemies cursed me with a burning spell and one that corrupts my items, but I'm just standing there focusing twice, and then removed one of the initially three Cs via casting Sanctuary, which would stop all negative effects while in play. This seemed like a very powerful moment for me, like "Yeah! I'd feel really cool - they did so many actions of casting for that focused burn, and now they have NOTHING!", but then I thought about the presentation and realized that... for most people, it's just reading like BB SCC, which... good if that means something to you, but I doubt that people will take the time to understand. Especially when my interface is lacking in tooltips and sprites (the imgui library itself has them, but to load them from a Bevy game isn't, if at all possible afaik). At this point, it was day 3 and I had stats in. Stats... came because I panicked about how to do spell UI, so I procrastinated and added them in. Of course I need stats to facilitate spell effects, right? It's not a waste!

Stats as a basis for spells

I started thinking about spells in health bars because I was playing Baldur's Gate, someone cast Haste, and the screen flashed Haste (9). I thought "how boring, it would be so cool if I could DO something about that duration". Being combat-oriented, the first thought that came to mind was "imagine if I could hit that spell out of a character, wouldn't that be cool". We would maybe have to go and target the caster for a couple of rounds to get the spell out of the enemy I actually want to get at because the caster made them faster or indestructible, or something cool... This all started with speed, so of course I need a stat to represent it in the game!

All of our stats work the same: actions are based on a stat, and the stat determines how fast that action is done. For example, walking depends on agility, meaning that a higher AGI will make your character spend fewer action points on movement. I've implemented what Kyzrati has written about here, where every turn you start with 100 action points, and every action reduces that. All actors are in a priority queue, so as soon as you take an action, you've already changed position in the queue and the next in line takes theirs. The stats only change that price: an AGI of 3 makes moving cost 100 points, while an AGI of 6 makes the cost 50 points. This basically means you get two moves per turn! If you commit to melee attacks, your AGI doesn't matter anymore - you're now using STR and your strength allows you to hit faster! You do more damage per turn, but not necessarily per action.

What's Haste in this lingo? Well, basically, it could just lift your AGI by 3. You'd be moving double-time. What's Stone Skin? Lift whatever your constitution stat is. You drink the Potion of Hill Giant Strength and simply raise STR by 6. Spells became more transparent to me at this point, which was good. Now, however, something connected in my head:

Health points get reduced one by one, and stat points are affected point by point...

What if they actually are the same? Does this increase our design space? Basically, if I say that Haste is +3 AGI, and I interpret that as enchanting three health points, isn't it possible to draw it like...

This representation would allow us to lose the effect of the spell as we lose health and not only once we lose all of the enchanted health points! It's amazingly simple to do now that we have stats in place, and it sounds like it's simple to show if we can color-code the stats (and we can!), so there we go!

Technical Difficulties and Revelations

I spent the next day fighting the UI and writing my own. I gave up but lost a lot of time. At this point, I'm thinking I'm late, I'm tired, and coming down with a cold, so I take the time to implement spells as stats - for starters, random stats. I just make spells that are called [+3 STR, +1 AGI] for example. It isn't too fun, but it is enough to prove to me that this idea works. I also implement Focus but forget it quickly, and forget to even mention it in the UI or initial key mappings...

Along the way, I realized that constant spells cast deep into a health bar are very annoying. I have enough experience to know that the solution shouldn't be "yeah, alleviate the constraint", but in my state then, I said ah, fudge it - your body rejects thaumaturgy based on your STR stat. So, the higher your strength, the faster the spells in your health bar drain. What started as a way to get away from haste lasting nine turns was now closer to home, but! There's some nice design space here: if we take stronger characters as those off of whom spells slide off more quickly, won't they be too strong? Both strong (take health away quickly) and resistant (magic wears off quicker) seemed OP until I realized something: if they can be enchanted, that STR stat can be reduced. Take a look at this:

A character with STR that is naturally 9 with a full HP, almost all of which is enchanted with -1 STR means that this character has a STR value of 2! All of a sudden, this character doesn't hit strongly, nor do they heal strongly. They are, all of a sudden, very vulnerable. Stats affect stats in this vicious way. I liked this, it seemed emergent in design time and I kept it.

This whole thing meant that the perfect barbarian build in the game is something like this:

It's only the last hitpoint that matters, they say. It's a character that is almost pure, unenchantable, hits like a machine gun, and yet can die very quickly if something just overwhelms them. I fell asleep that day with a grin - this felt good.

This, mostly, is what got implemented the day after as well: at this point I started working on the actual game progression. The initial idea for this was that you have a spell that creates the staircase, but it was too late to see how staircase-building magic fits into the stats, so I just made it easier: you just sacrifice yourself for it.

Sacrificium [sacer+facere]: to make sacred

Sacrifices seemed to be what this messed up story world would require - your health is your magic, but it is still yours, so still tied to your terrestrial existence. Make it holy, lose it, make it into something more. Descend into the depths.

Sacrifices work in a bit of a convoluted way, here's an algorithmic view:

If you have a stat that is 9+, you've SATISFIED the rite.

If you haven't SATISFIED the rite, permanently lose (9 - highest stat) health points -- they can't be recovered.

Fill how ever many health points you have to the top, and enchant them all with -1 of your highest stat.

Congratulations, you're now on the next level.

I made this into an action - you can do it at any time! And I hear you now: if I can do it at any time, what if I just start the game and sacrifice hard?

Well, at the start, every stat is at 3, so the sacrifice would take 9-3 points off of your health. You start with 10 HP so this leaves you at 4. You also have one stat just ruined by a -4 enchantment cast onto your health. If you do it again, the math is quite telling: you would permanently lose 6 HP again, and you only have four, so you die as your cold body hits level 3. It's a good way to go in terms of exploring, though, and might hold the hot sauce to building a good barbarian, if you control it just well enough!

The most vanilla HELLTH playthrough would have you pick different stats to focus on in every level, so that you can go through a wave-like state of recovery while collecting items to boost your next stat, then sacrifice it and repeat the process to level five. Levels get smaller over time, and filled more with obstacles like forests, making your life more dangerous as you see fewer tiles ahead and enemies mostly become aggressive casters who can curse you at a distance if you see them while they chant. This makes the open world you walked on previous levels feel like a danger zone, in addition to the forest that already felt like danger zones before. If there's a feeling of tension near the end, it's mostly that.

Well, that, and the fact that you can't reliably depend on your build too much. You see, somewhere around day 6, it was obvious that people find their build very early and just carry them through. I wanted a bit more of the feeling I get from playing games like Innovation, where the world doesn't allow that: you're forced to change. One thing I wanted to make is that gear has stats that are minimally required. If you're wearing something and lose stats, it breaks. No time, however, turned that into a very simple and annoying "things disappear between levels". It gets the job done, however, and plays nicely with every level feeling like a small, somewhat guided beginning. You know that you now have a major flaw, and you know that you have some items that might help you out somehow. Each item can be used both on others and on oneself:

  • weapons can be equipped (increase in stats), or thrown (hits for the number of stats they enchant + 1);

  • thaumaturgical artifacts (the bones of thy enemies in the 7DRL version, but I planned to add more!) can be consumed (enchanting your health bar at your focus) or thrown (enchanting the enemy's health bar at your focus);

The currently updated post-jam version 1.5 also contains arcane writs that don't give you too much choice: if you pick them up, you can only examine them. They give you a hint and replenish one point of health, if you've lost it in a non-permanent way. This is the closest we come to healing items - only something alien to the place we're in can even understand healing. Speaking of, the main boss, who ruined the world by trying to make all life magical and thus not separated from its spiritual component that allows healing, lives at the bottom of this spire. In a (hopefully) densely populated ruined room compared to the previous open levels, lives...

The Healer

The Healer [of the World] has gone mad. They have been reduced to their instincts for caring and healing, but the world has changed and those instincts now simply change. They mutate what's there and it dies faster.

They are not a well-crafted enemy - with 15 HP, they're a bit above what we start with, and their main forte is casting a lot of deeply focused curses while the wailing thaumaturges help beat you to a pulp with a book.

The plan for the healer was to have two phases, actually. To be cocooned in the first, in something akin to the Eye of the World (from Robert Jordan's Wheel of Time), kept there by his clergy who are trying to help (again, driven to madness and NOT helping at all -- just propagating the problem). You'd kill them, and then crack the cocoon to free the Healer. He'd attempt to, well, heal, but would actually awaken the enemies you've just killed, and maybe raise some other things that you haven't seen before.

The battle would be interesting in that the Healer would basically be a necromancer who hates his creations - if they spend enough time in his view, he'd have them blow up for damage, lighting the dense foliage on fire. I had zero time for environmental effects, so this whole idea was scrapped clean off!

The other part that was scrapped was the way back. I like a good ascent, and the thing that I wanted to do here is to make it so that the spheres you've descended through have come to necromantic life after the Healer came from the cocoon, so you'd have your hands full. However, time wasn't on my side at all, so I just wrote it down and-- no crying over spilled milk. The game has to be finished!

At any rate, I wish to continue working on HELLTH. I think it has something very nice in it, and I have a lot of ideas that I want to use with it. However, it isn't a fast game, I don't think it can be. I've learned that much in this investigation, and I'm grateful for people willing to play it in this shape, it helped me solidify my thoughts and learn a lot! I think you'll see me talk more about this as the year progresses. I plan to release the 1.666 version next month, that may have some more story, a proper boss fight, and potentially more things, but no promises - it IS hellish, what with my incoming projects, a move to Ireland, and some other stuff in development...

Thank you for reading up to here and hope you're doing well. Also hope you'll join in the next 7DRL adventure. It's not only a fun week, but also a fun rest of the year afterwards!

0
Subscribe to my newsletter

Read articles from Miroslav directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Miroslav
Miroslav

I'm a developer from Serbia, and I love roguelikes and Rust! I've worked in AAA game development, been indie, done software engineering, web development; at different times did functional languages, embedded, as well as working at UCSB as a researcher and educator. Came back to making games!