Dungeon design journal #2: further dungeon generation
After getting the basics of randomly generating the dungeon map in place, I spent some time cleaning up the code. This is a necessary step in any larger project: whatever you have written after several hours of obsessed coding may work, but it is almost certainly not pretty. Cleaning up the code can be as easy an rearranging it and adding headings, but more commonly also involves separation (any part of a routine that might come in useful elsewhere should be written as a stand-alone routine) and rewriting (of code that is either ugly or not as general as it could be).
One thing I tried to do this time is reducing the number of global variables I used -- using local variables for local properties is neater and less prone to strange bugs later. However, I don't think you can send local variables to rulebooks. You cannot, for instance, write "consider the monster scoring rules for (guy - a monster) at (place - a location)" and then use "guy" and "place" as local variables within all the monster scoring rules, like you can do for a routine. So you have to use global variables to send information to a rulebook -- right?
I also implemented a check on the generated map to see whether it is not too narrow in the beginning: we don't want the player to be stuck on a linear path at the start of the game which might be blocked by an obstacle he or she cannot overcome. I'm certainly not striving for total fairness, but some fairness is good; and we want the player to be able to make decisions.
My basic design idea at the moment is that there are five levels of monsters, levels 1 to 5. Every dungeon contains two monsters of levels 1 and 2, and one monster of each of the other levels. Killing the level 5 monster ends the game. (Obviously, the exact numbers can all be changed during play testing.)
When you kill a monster, your character absorbs its soul, which will heal you and grant you a set of powers specific to that monster. These powers will in general include simple statistics increases, but also more specific and fun abilities or resistances, and they will be more powerful when the level of the monster is higher. However, absorbing a level n soul will immediately destroy all level n and lower powers you already have. So if you have a level 2 power and kill a level 3 monster, you lose the level 2 power; but if you then kill another level 2 monster, you will gain its power without losing the level 3 power.
This should be tactically interesting because it generates a basic risk-reward problem: killing a higher level monster is easier when you have already absorbed the souls of lower level monsters; but you can only keep the souls of the lower level monsters for the next fight if you first kill the higher level monster. E.g., before taking on the final monster, you would ideally kill a level 4, 3, 2 and 1 monster in that order. But killing the level 4 monster without the help of having absorbed a level 3 soul is going to be quite difficult. Add to this the fact that different souls will help you more or less against specific monsters, and the player might face some hard tactical decisions even when he is just trying to decide in what order to defeat his enemies.
Of course, we'll need to see how it works out in practice.
By the way, I tried to think of a way to generate a name from this basic mechanic. Soulstealer and Souldrinker sounded too much like bad Michael Moorcock fan-fic, so I have gone a slightly more mystical route: the current working title is The Breaking of the Vessels.
Now a vague theme of mysticism gives me some basis for creating a set of locations, mechanics, monsters, and so forth, with a coherent feel; but I'm not sure it's going to be the easiest or most successful route. If anyone has a better idea, I'd love to hear about it. At all costs do I want to avoid the "throw in every fantasy trope you can think of"-feel that can be found in so many rogue-likes: I want something more coherent. Also, preferably not too clichéd. I'm very open to suggestions -- my head has been so preoccupied with the mechanical side of things that the fictional side has not yet received a lot of thought.
Getting back to the actual work, I implemented a system to distribute monsters across the map. Basically what I'm doing is that I sort the rooms by their distance from the Entrance Hall, and then put the strongest monsters farthest away. This ensures that all rooms are reachable (nothing can be beyond the final monster), and that the player can always get to the weaker monsters before he has to defeat the stronger ones -- although it is very possible that he could take on the stronger ones early on, because the maps resulting from my generation algorithm have a lot of branches.
There are, of course, also easy ways to specify that certain rooms cannot contain monsters; or that certain monsters are more likely to be found in certain rooms.
Finally, I put in a basic framework for "treasure" generation, but I think that's something I'd like to mostly leave to more specific code. I then wrapped everything into an extension and added ATTACK to my source code.
So at this point I have a game in which you get to walk through a random dungeon and fight the stock ATTACK monster under different names. Not quite awesome, from a gameplay perspective, but a good basis for further development.
One thing I tried to do this time is reducing the number of global variables I used -- using local variables for local properties is neater and less prone to strange bugs later. However, I don't think you can send local variables to rulebooks. You cannot, for instance, write "consider the monster scoring rules for (guy - a monster) at (place - a location)" and then use "guy" and "place" as local variables within all the monster scoring rules, like you can do for a routine. So you have to use global variables to send information to a rulebook -- right?
I also implemented a check on the generated map to see whether it is not too narrow in the beginning: we don't want the player to be stuck on a linear path at the start of the game which might be blocked by an obstacle he or she cannot overcome. I'm certainly not striving for total fairness, but some fairness is good; and we want the player to be able to make decisions.
My basic design idea at the moment is that there are five levels of monsters, levels 1 to 5. Every dungeon contains two monsters of levels 1 and 2, and one monster of each of the other levels. Killing the level 5 monster ends the game. (Obviously, the exact numbers can all be changed during play testing.)
When you kill a monster, your character absorbs its soul, which will heal you and grant you a set of powers specific to that monster. These powers will in general include simple statistics increases, but also more specific and fun abilities or resistances, and they will be more powerful when the level of the monster is higher. However, absorbing a level n soul will immediately destroy all level n and lower powers you already have. So if you have a level 2 power and kill a level 3 monster, you lose the level 2 power; but if you then kill another level 2 monster, you will gain its power without losing the level 3 power.
This should be tactically interesting because it generates a basic risk-reward problem: killing a higher level monster is easier when you have already absorbed the souls of lower level monsters; but you can only keep the souls of the lower level monsters for the next fight if you first kill the higher level monster. E.g., before taking on the final monster, you would ideally kill a level 4, 3, 2 and 1 monster in that order. But killing the level 4 monster without the help of having absorbed a level 3 soul is going to be quite difficult. Add to this the fact that different souls will help you more or less against specific monsters, and the player might face some hard tactical decisions even when he is just trying to decide in what order to defeat his enemies.
Of course, we'll need to see how it works out in practice.
By the way, I tried to think of a way to generate a name from this basic mechanic. Soulstealer and Souldrinker sounded too much like bad Michael Moorcock fan-fic, so I have gone a slightly more mystical route: the current working title is The Breaking of the Vessels.
Now a vague theme of mysticism gives me some basis for creating a set of locations, mechanics, monsters, and so forth, with a coherent feel; but I'm not sure it's going to be the easiest or most successful route. If anyone has a better idea, I'd love to hear about it. At all costs do I want to avoid the "throw in every fantasy trope you can think of"-feel that can be found in so many rogue-likes: I want something more coherent. Also, preferably not too clichéd. I'm very open to suggestions -- my head has been so preoccupied with the mechanical side of things that the fictional side has not yet received a lot of thought.
Getting back to the actual work, I implemented a system to distribute monsters across the map. Basically what I'm doing is that I sort the rooms by their distance from the Entrance Hall, and then put the strongest monsters farthest away. This ensures that all rooms are reachable (nothing can be beyond the final monster), and that the player can always get to the weaker monsters before he has to defeat the stronger ones -- although it is very possible that he could take on the stronger ones early on, because the maps resulting from my generation algorithm have a lot of branches.
There are, of course, also easy ways to specify that certain rooms cannot contain monsters; or that certain monsters are more likely to be found in certain rooms.
Finally, I put in a basic framework for "treasure" generation, but I think that's something I'd like to mostly leave to more specific code. I then wrapped everything into an extension and added ATTACK to my source code.
So at this point I have a game in which you get to walk through a random dungeon and fight the stock ATTACK monster under different names. Not quite awesome, from a gameplay perspective, but a good basis for further development.
I've been kicking around for a procedural IF combat game that probably wouldn't suit you. That's that the PC is a composite golem of some sort, absorbing and expelling different substances as they fight and win. This would provide some justification for hit points (bits of you are actually being destroyed) as well as for gains for defeating enemies (you absorb the defeated substance), and it would also provide for systematic puzzles and maybe even emergent effects -- you can use Stone and Steel bits to create a spark that will light Oil bits to Fire bits, which burns Wood bits (and itself), but Water bits quench Fire and create steam -- well, something like that. Kind of like adapting Metamorphoses to combat. But it doesn't seem like it'd fit your theme.
ReplyDeleteMaybe a better framework that is perhaps a little cliched but better than dwarves 'n' elves would be the deadly sins? You could have sloth-based powers (slowing the enemy, of course), anger-based powers (higher damage?), and... well, it'd be up to you. But each soul you absorb might demand that its sin be the ruling one, so it expels the lesser sins you already have; but if you absorb a lesser sin later it's subordinate to your current dominant sin and is OK.
Best of all, you currently have seven monsters.
I wonder if the Abulafia generator couldn't provide some inspiration (or perhaps even a fiction generator?).
ReplyDelete