Kerkerkruip programming tutorials

Introduction

Kerkerkruip, my IF roguelike, lends itself perfectly to user-contributed content. It can always be improved by having more items, more monsters, more interesting things that can happen; and these can be thought up and programmed in relative isolation. Since Dannii set up a Github repository for the whole ATTACK and Kerkerkruip code, getting hold of the latest development code has become really easy.

(If you’re a complete newbe to repositories and version control systems, as I am, you may want to check out Github for Windows, a nice graphical shell. It is even possible just download the files by hand from the website – it’s only about 15 files, and you can commit any finished code by email.)

But, of course, Kerkerkruip is a big game consisting of a lot of code. Even if you know some Inform 7, it may look pretty intimidating. So in order to lower the threshold and encourage people to join in the development of Kerkerkruip, I am launching a series of Kerkerkruip programming tutorials, in which I will talk about the creation of new things for the game. I hope you’ll enjoy them!

Preliminaries

This is not a tutorial for programming in Inform 7. I’ll assume you already know the language; if you don’t, there are several great tutorials out there (including the Inform 7 manual).

I’ll also assume that you have downloaded the source code from Github, and can compile the game.

But wait… will my code be accepted?

That’s a good question. If you write some code for Kerkerkruip, do I guarantee that it will be accepted into the game? (And if I don’t, why would you spend time writing it?)

No, I can’t absolutely guarantee that we will accept your code, if you decide to write some. Contributions do need to fit into the existing game and its philosophy. So for instance, here are some things that probably would not be acceptable:

  • A monster with an ability that just instantly kills the player 10% of the time. We want Kerkerkruip to be tactical, not based on pure luck.
  • A weapon that is a lot better than all the other weapons in the game. We want Kerkerkruip to be about interesting choices, not about no-brainers.
  • An item that allows you to keep all powers you already have, even if you kill a higher level monster later. This would disrupt the basic strategy of the game too much (and it would be overpowered).
  • A giant marshmallow man. That would be silly. Which is fine, but it wouldn’t fit the atmosphere of the game.
  • And of course anything that is racist, sexist, and so on.

But while not everything goes, a lot does. Kerkerkruip doesn’t insist on a unified theme, and there are a lot of variables that can be tweaked to balance any contribution against what is already in the game. And if we feel that something is in itself acceptable, but is really weird, we can just make it rare – the game will be strengthened by the addition of strange things that the player comes across only occasionally. So the acceptance policy will certainly be liberal.

(Coming to think of it, there might even be a place for that item that allows you to keep all powers you already have, though it would only appear in extraordinary circumstances.)

Of course, the best thing to do is just to discuss your idea before you start implementing it, especially if it will be a lot of work. You can email me, or make a post in this thread.

Onwards!

Yes, onwards! But that’s something for the next post.

TUTORIAL 1: Making a weapon

Coming up with an idea

New monsters are probably what we would like to have most in Kerkerkruip, but monsters are difficult. So we’ll start by doing something that is simpler: making a new weapon.

Now, before we start coding, we need to come up with a good idea. What we want to have is a weapon that is different from the weapons that are already in the game; and that is different in a way that creates interesting tactical choices. (Tactical choices are not the only reason to put something in the game, but it’s a very important one.)

I suggest we implement “the dagger of the double strike”, which has the following characteristics:

  • It is a low-damage weapon. Without a special ability, it would be among the worst weapons in the game.
  • If you miss with the dagger of the double strike, you immediately strike another blow at your enemy. (Once only; this second strike no longer benefits from any concentration bonus.)

This weapon would be bad against opponents with damage reduction, such as the ravenous armadillo; but it would be good in cases where hitting our opponent is more important than dealing a lot of damage, for instance because we need to break the opponent’s concentration.

The dagger kind

The best way to start coding a new item is by looking at the code of an existing item. All weapons, and in fact almost everything the player can carry around, is found in the extension called “Kerkerkruip Items”. So we open up this extenion, and search for a dagger. First, we’ll find the code that defines daggers in general, which reminds us that daggers get better attack and damage bonuses from tension. We also find this numerical information:

The damage die of a dagger is usually 3. The weapon attack bonus of a dagger is usually -1. The dodgability of a dagger is usually 3. The passive parry max of a dagger is usually 1. The active parry max of a dagger is usually 1. The weapon damage bonus of a dagger is usually 0.
What does that mean? You can find all of this in the ATTACK manual, but let’s review it.

  • The damage die is the size of the die that is rolled to determine damage. A damage die of 3 means that the basic damage is a random number between 1 and 3; a damage die of 6 that the basic damage is between 1 and 6, and so on.
  • The weapon attack bonus is a bonus you receive to your attack roll.
  • The dodgability is the attack penalty you will get when you attack with a weapon and the defender dodges.
  • On the other hand, when your opponent parries, you will get an attack penalty equal to either the passive parry max of your weapon, or the active parry max of your opponent’s weapon, whichever is lower. For the example of the dagger: it’s easy to parry a dagger (so you could get up to a 3 attack penalty if the opponent parries), but it’s not easy to parry with a dagger (so someone using a dagger to parry will never give his opponent more than 1 attack penalty).
  • The weapon damage bonus is a bonus to the damage you do.

It’s good to know this stuff, because we might want to tweak our dagger of the double strike.

A basic dagger

Looking further, we find the code for the gorgeous dagger, one of the simplest items in the game.

[code]Section - Gorgeous dagger

The gorgeous dagger is a minor dagger.
The gorgeous dagger is civilised.
The gorgeous dagger is iron.

The description of the gorgeous dagger is “Adorned with gold and a large emerald at the end of the hilt, this dagger is not only beautiful, but also perfect for precise attacks in tense situations. The decadence of its design proves it to be of Yahvinnean origin.”.[/code]
Here we see a couple of things. First, items should be declared as being either “minor”, “major”, “epic”, “special”, “unique”, or “non-treasure”. Non-treasure is the standard, and anything that is non-treasure will not be placed in the dungeon by the treasure generation rules. Special and unique aren’t really in use yet, so let’s not worry about them for now. This leaves us with minor, major, and epic. As the names suggest, minor items are the least powerful, while epic items are the most powerful. In addition, epic items should change your playstyle significantly when used. Examples of minor items are the essence of rage, the tormenting necklace, and the fearsome axe. Examples of major items are the executioner’s axe, the magical spade, and the boots of the war dance. Examples of epic items are the cloak of shadows, the glass cannon, and the essence of addiction.

Second, any item should have a “mood”. The moods are civilised, religious, barren, deathly, elemental, magical, alchemical and non-mood. Moods have no effect in play, but they ensure that items are more often placed in rooms with the same mood, that is, rooms where they thematically belong. For instance, Drakul’s lifeblood (a deahtly epic item) will be found in the Crypt (a deathly room) more often than in the Temple of Aite (a religious room).

Third, we should give the item a material. The materials are iron, silver, paper, cloth, wood, leather, flesh, glass, stone, dragon skin, radiance, adamant, and vapour. Materials are already used for a couple of things (for instance, calculating how fast something dissolves in the stomach of the armadillo), and I have bigger plans with them in the future.

Knowing this, we can now write down the basic definition of our dagger.

[code]Section - Dagger of the double strike

The dagger of the double strike is a major dagger.
The dagger of the double strike is civilised.
The dagger of the double strike is iron.

The damage die of the dagger of the double strike is 1.

The description of the dagger of the double strike is “The dagger looks dull and far from dangerous. But appearances deceive, for this weapon has been imbued with a dangerous magic.”.

The special weapon info of the dagger of the double strike is “; allows its wielder to strike again immediately if the first attack did no damage[run paragraph on]”.
[/code]
Our dagger has an atrocious damage output of 1 damage; though concentration and tension can increase this. This makes it perhaps the worst weapon in the game, except for the very powerful ability we haven’t programmed yet. That ability (a second chance to break your enemy’s concentration!) is probably so good that I have decided to make it a “major” item. If we find out in practice that it isn’t good enough, we can either lower it to a minor item or increase its usefulness in some other way.

I’ve also used the “special weapon info” property to explain the dagger’s power in more technical detail to the player.

Testing our dagger

We should now save the extension in which we put the code (this is crucial, otherwise Inform will use the unsaved version), start the game, and use the cheat command “purloin double strike”.

Well, the description looks good, and the dagger works! Of course, we haven’t programmed the most important part of the item yet, so it’s pretty useless right now. Let’s get on to that.

The special ability

Now we write the special ability:

[code]Making-double-strike is a truth state that varies. Making-double-strike is false.

Last after reporting an actor hitting (this is the hit again with the dagger of double strike rule):
if the global attacker weapon is the dagger of double strike:
if making-double-strike is false:
if the attack damage is 0:
if the global attacker is alive and the global defender is alive:
now making-double-strike is true;
say “The dagger of the double strike slashes out again!”;
try the global attacker hitting the global defender;
now making-double-strike is false.[/code]
If we are well acquainted with (the newest version of) ATTACK, we will know that a “last after reporting an actor hitting” rule is the very last thing that will run when someone hits someone. Which is exactly what we need here, of course.

The “global attacker weapon” is the weapon used to attack, and the “global attacker” and the “global defender” are the guy who attacks and the guy who defends respectively. The “attack damage” is the amount of damage that was dealt. The conditions should explain themselves; e.g., we don’t want to double strike if either the attacker or the defender is dead. (But how can either of them be dead if the previous attack missed? Well, there might be special rules that allow this to happen, for instance, a weapon that deals damage to the attacker whenever it is used. We need to be careful and take nothing for granted.) The making-double-strike variable ensures that only one double strike is made, not a series that terminates only once a hit is scored.

Having written this code, we run the game again and test the dagger. It turns out to be much more powerful than I originally thought, because the defender doesn’t get an extra turn to dodge or parry. This means that the second attack hits very often. In fact, it hits too often, so I decide to cripple the dagger a little more:

The weapon attack bonus of the dagger of double strike is -2.

That’s it. The dagger of double strike is ready to see some action. During play it might still turn out to be either too powerful or not powerful enough, in which case I’ll come back to tweak it; but for now, we have an interesting new addition to Kerkerkruip.

Iiiiinteresting. All in favour of user-created content for those IF games which are suited to it, and Kerkerkruip is one of the more obvious candidates.

So you’re limiting it to marshmallow men of moderate and smaller sizes? I guess that makes sense. I mean, it would need to fit into the room …

No promises, but small-to-medium sized marshmallow men could be discussed. :wink:

So my idea of the pack of Nazi bunnies is out?

[ETA: Um, so no one gets the wrong idea, look here.]

I’m planning to change it so that you can throw grenades into adjacent rooms. Hopefully will make them a little more useful!

Yeah I always tried doing that with grenades: I’ve never successfully used them in a fight.

We should talk about grenades, but maybe not in this thread. I’ve made a new Kerkerkruip discussions thread, so we can keep this one for the tutorials.

TUTORIAL 2: the cursed backstabber

For our second tutorial, we will apply the lessons learned last time, and create another weapon. Remember those nasty items in Kerkerkruip that can turn out to be something else, like the goggles of acuity turning out to be the goggles of blindness? It sounds like a good idea to make a cursed weapon that the dagger of the double strike we made last time can turn out to be. Here is the design idea:

  • The backstabber is a cursed dagger that sometimes attacks a random person instead of your chosen target. This random person can be you yourself.

The fastest way to find out how to make an item that does X is almost always to look at some other code that does X. In this case, we can easily check the code for the goggles of acuity / goggles of blindness (or some other noncursed/cursed pair) to see how hidden identity works. Copying the relevant code and combining it with what we wrote about the dagger of the double strike leads to this:

[code]The backstabber is a cursed curse-identified dagger. The backstabber is proper-named.
The backstabber is iron.

A treasure placement rule (this is the double strike can be backstabber rule):
if a random chance of 1 in 4 succeeds:
now the hidden identity of the dagger of double strike is the backstabber.[/code]
Unlike a normal item, the backstabber has no valuation, i.e., it is not “minor”, “major”, or “epic”. (Technically, it has the default valuation “non-treasure”.) This means that it will never be generated in the dungeon. Instead, we generate the dagger of the double strike, and use a treasure placement rule that gives it a 25% chance of having the backstabber as its “hidden identity”. Kerkerkruip will automatically turn any piece of clothing or any weapon with a hidden identity into its hidden identity as soon as it is worn or wielded.*

For the same reason that the backstabber has no valuation, it also has no mood.

The backstabber is “cursed”, which means that it cannot be removed once wielded, and “curse-identified”, which means that the player can see that it is cursed. Normally, cursed items are not curse-identified, because then the player would never wear or wield them; they only turn curse-identified when it is too late and they already stick to the player. Items with a “hidden identity” work a little differently: we are actually going to replace the dagger of the double strike with the backstabber once it is readied, so there is no reason not to have the backstabber be curse-identified from the start.

We need to give the backstabber a description:

The description of the backstabber is "This treacherous blade sometimes strikes out at random people -- including yourself.". The special weapon info of the backstabber is "; sometimes attacks a random person instead of the intended target[run paragraph on]"
And now we need to code the special ability of the weapon. Looking at our code from last time, this shouldn’t be hard. We just need to randomly substitute one hitting action for another:

[code]Making-backstab is a truth state that varies. Making-backstab is false.

First check an actor hitting (this is the hitting with the backstabber rule):
if the global attacker weapon is the backstabber:
if making-backstab is false:
if a random chance of 1 in 2 succeeds:
let X be a random alive person in the location of the actor;
unless X is the noun:
say “The [bold type]backstabber[roman type] attacks [X] instead!”;
now making-backstab is true;
try the actor hitting X instead.

Check an actor hitting (this is the reset backstab rule):
now making-backstab is false.[/code]
The making-backstab variable ensures that the backstabber doesn’t redirect the action more than once. The current code will make the player attack himself 25% of the time in 1-on-1 fights. In bigger fights, the possibility of attacking someone you don’t mean to can rise to 50%. Obviously, this is not a weapon you want to be wielding!

Of course, you want to test this item to see whether it works as expected. To do so, it is smart to change both the random chance that the dagger of the double strike is the backstabber and the random chance that the backstabber redirects your attack to 100%, and then to add a “When play begins” rule that puts the dagger of the double strike in the Entrance Hall. That way, you can easily test whether the code works as it should.

  • Actually, this is only true for weapons since I wrote that code today. This was an oversight, but we never had weapons with hidden identity before.

TUTORIAL 3: Cloak of reflection

The backstabber, which turns an attack to someone other than the intended target, gave me the idea of implement the cloak of reflection, a cloak that sometimes turns ranged attacks back to the person who makes them. There aren’t that many ranged in the game currently: Bodmal’s lightning bolt and the staff used by the tormentor of Aite both count as ranged, and so does the glass cannon. So such a cloak would be of only minor usefulness, but it might be a fun addition to the game.

Therefore we write:

[code]The cloak of reflection is a minor cloak.
The cloak of reflection is magical.
The cloak of reflection is cloth.

The description of the cloak of reflection is “A piece of silk with thousands of small magical mirrors sewn on it, this cloak is both beautiful and useful. It will sometimes, though not infallibly, reflect back ranged attacks to the attacker.”.[/code]
All of this should be straightforward. Cloaks are one of the pre-defined pieces of clothing, as you can see in the Kerkerkruip Items file. The mood is “magical”, the valuation is “minor”, the material is “cloth”. (Kerkerkruip only supports one material per item, so we don’t define it as cloth, glass and silver, even though the description of the item might make us assume that all these materials are part of it.)

The code that will actually turn around the attacks is really easy. The only new ingredient we need to know is that a weapon can be “ranged”.

First check an actor hitting (this is the cloak of reflection rule): if the noun wears the cloak of reflection: if the global attacker weapon is ranged: if a random chance of 2 in 7 succeeds: say "The cloak of reflection [bold type]reflects[roman type] the attack back to [the actor]!"; try the actor hitting the actor instead.
It then suddenly seemed like a good idea to sometimes give the cloak of reflection to Malygris, just to make the final fight a little more unpredictable. (We probably need more random changes to Malygris in the game.) Turning the glass cannon on Malygris and finding out that he is wearing the cloak of reflection is going to be… interesting. For this purpose, we use a dungeon interest rule. These rules run after the dungeon has been made and the monsters and treasure have been placed, and they’re meant to add some spice to the dungeon.

A dungeon interest rule (this is the Malygris sometimes wears the cloak of reflection rule): if a random chance of 1 in 10 succeeds: if Malygris does not wear a cloak: now Malygris wears the cloak of reflection; if generation info is true, say "* Malygris wears the cloak of reflection.".
That’s it!

By the way, you may be wondering whether the dungeon doesn’t get too full if we keep adding more item. The answer is no: the game places a specified number of minor (6-12), major (3-6) and epic (1-2) items, which does not depend on the total number of items we have defined.

TUTORIAL 4: Spiked mace of the ape king

Let’s make another weapon. This time, we take our cue from the blood ape, the level 1 monster who grows in size every time he damages someone. What about a weapon that grows in size every time it damages someone? We’ll call it the “spiked mace of the ape king”. When it’s small, it won’t be very powerful, but as it grows it gets better and better, until it starts becoming too big and unwieldy. In the end, it becomes so big that you can’t use it any more. Tactically speaking, then, the player should increase the mace’s size against easy monsters until it reaches a point where it becomes an effective weapon; then use the mace at its best against worthy foes; and stop using it once it stops being worth it.

There is no mace kind. While this is not necessary, we’ll start by making one:

[code]A mace is a kind of weapon.
A mace is usually iron.

The damage die of a mace is usually 5.
The weapon attack bonus of a mace is usually 0.
The weapon damage bonus of a mace is usually 1.
The dodgability of a mace is usually 2.
The passive parry max of a mace is usually 2.
The active parry max of a mace is usually 2.[/code]
This makes maces middle of the road weapons: more damage than daggers and swords, but less than axes; average dodge/parry statistics.

We now define the spiked mace of the ape king:

[code]The spiked mace of the ape king is a major mace.
The spiked mace of the ape king is barren.
The spiked mace of the ape king is iron.

The spiked mace of the ape king has a size.[/code]
Sizes are already used for the blood ape, so why not use them here as well? However, we will make the changes in the mace more fine-grained than just the couple of sizes that Kerkerkruip defines, and to do so, we will set up a table.

Table of Spiked Mace of the Ape King Blood Dam WAB WDB DOD PPM APM Size 0 3 1 0 1 2 2 tiny 1 3 1 0 1 2 2 tiny 2 4 1 0 1 2 2 small 3 4 1 1 1 2 2 small 4 5 0 1 1 2 2 small 5 5 0 1 1 2 2 medium 6 6 0 2 2 2 2 medium 7 6 0 2 2 2 2 medium 8 7 0 2 2 2 1 large 9 7 -1 3 2 1 1 large 10 8 -1 3 2 1 1 large 11 8 -1 3 3 1 1 huge 12 9 -2 3 3 1 1 huge 13 9 -2 4 3 1 0 huge 14 10 -2 4 4 1 0 gargantuan 15 10 -3 4 4 0 0 gargantuan
Blood is the number of hits that have been made, and the other columns are damage die, weapon attack bonus, weapon damage bonus, dodgability, passive parry max, active parry max, and size. The middle rows define a very good weapon: 1d6+2 damage with no significant drawbacks is definitely above-average. The early rows define a weak weapon: 1d3+0 damage is just not a lot, and a +1 attack bonus is not enough to counteract this. The late rows define a powerful weapon that is very hard to hit with; 1d10+4 damage is amazing, but the -3 attack penalty combined with the fact that a dodging opponent gives you another -4 penalty, makes doing that damage nigh impossible.

Now we need code that will change the weapon to reflect this table.

[code]Spiked-mace-blood is a number that varies. Spiked-mace-blood is 0.

To set stats for the spiked mace of the ape king:
now the spiked mace of the ape king is iron;
now the spiked mace of the ape king is not rusted;
if spiked-mace-blood is less than 16:
choose row with a blood of spiked-mace-blood in the Table of Spiked Mace of the Ape King;
now the damage die of the spiked mace of the ape king is Dam entry;
now the weapon attack bonus of the spiked mace of the ape king is WAB entry;
now the weapon damage bonus of the spiked mace of the ape king is WDB entry;
now the dodgability of the spiked mace of the ape king is DOD entry;
now the passive parry max of the spiked mace of the ape king is PPM entry;
now the active parry max of the spiked mace of the ape king is APM entry;
now the size of the spiked mace of the ape king is Size entry;
otherwise:
let guy be a random person who has the spiked mace of the ape king;
unless guy is nothing: [who knows whether we program animated weapons at some point?]
say “The [bold type]spiked mace of the ape king[roman type] suddenly grows so big that [guy] cannot hold on to it. It [bold type]crashes[roman type] to the floor!”;
move spiked mace of the ape king to location of guy;
otherwise:
say “The [bold type]spiked mace of the ape king[roman type] suddenly [bold type]crashes[roman type] to the floor!”;
move spiked mace of the ape king to location of spiked mace of the ape king;
now spiked mace of the ape king is not readied;
now spiked mace of the ape king is fixed in place;
now description of spiked mace of the ape king is “The mace has grown to such proportions that not even the strongest man in the world would be able to lift it.”.[/code]
The first if-block sets the new properties of the mace after it has grown, while the second handles the case where the mace has grown too big to use: it falls down and becomes a fixed in place object. We do some subtle things here. First, we assume that growing turns the mace back into an iron, unrusted weapon. This is mostly because otherwise, the interaction with Bodmall’s turn-to-wood power would become really weird; perhaps we will implement a more elegant solution once we get round to implementing a more powerful materials system. We also ensure that the dropping-and-fixing-in-place stuff also works correctly when nobody is holding the mace. While this is useless code in the current Kerkerkruip, one can imagine scenarios in which this might become essential: animated weapons, thrown weapons, stuff like that. We prefer to always be cautious and make as few assumptions as possible.

We shouldn’t forget to call this routine at the beginning of the game:

When play begins: set stats for the spiked mace of the ape king.
We want the description of the mace to reflect its size (the numerical statistics are shown automatically):

The description of spiked mace of the ape king is "A ball studded with sharp spikes and put at the end of a stick makes a simple but effective weapon. It is currently of [size of spiked mace of the ape king] size.".

Finally, we need to make a rule that actually makes the mace grow! For special stuff that happens at the end of an attack, the aftereffects rules are the place to go:

An aftereffects rule (this is the spiked mace grows rule): if the global attacker weapon is the spiked mace of the ape king: if the attack damage is greater than 0: increase spiked-mace-blood by 1; set stats for the spiked mace of the ape king; if spiked-mace-blood is less than 16: say "The spiked mace of the ape king grows!"
There we have it: a new, and quite peculiar weapon.

A couple of concerns about Malygris’s wearing the cloak of reflection (and I haven’t source-dived, so take this with a grain of salt):

If the game places the cloak in the dungeon and then gives it to Malygris, is the player deprived of an extra item?

Should the cloak of reflection rule say “Malygris’s cloak of reflection…” when Malygris is wearing it? I think I’d be pretty confused about what had happened with this message.

I also wonder about the balance effects of giving Malygris the cloak – it seems like every time you use the glass cannon on Malygris, there’s a 1/35 chance of getting wiped out yourself, and there’s nothing you can do to avoid it. Though maybe there are other items that would let you recover. It might at least be a bit user-friendly to include something in Malygris’s description that changes when he has the cloak, so the alert player only gets burned once. It can be good to have something on the final boss that sometimes prevents a superweapon from working, as long as there’s a workaround (nethack spoilers):

The high priest of Moloch has something like a 1/13 chance of being generated with a cloak of magic resistance instead of a robe, which can be a problem for my strategy of walking in and blasting him with a wand of death. He got me down to single-digit HP before I got the door shut. Fortunately, the high priest didn’t realize that when you’re generated next to a cockatrice, it’s a good idea to block the door.

Matt, would your concerns be lessened by the fact that you can see what items an NPC is wielding / wearing by examining the NPC? So the player doesn’t need to be taken by surprise, and can of course decide not to use a ranged weapon. (The cloak of reflection can even be examined itself to see what it does, so an alert player doesn’t even need to be burned once.)

Do you think this would be confusing?

I guess I would assume that it was something Malygris was wearing, but if you think it is confusing, I can word the phrase differently.

And yes, the player is deprived of an item, but the number of items is random anyway, and other random events can add items to the player’s pool of possible loot. So this doesn’t concern me.

It would indeed. I haven’t played for, ah, a while, and had forgotten about that.

I guess I’d probably figure it out pretty quickly, but if it said “Malygris’s cloak of reflection” I’d figure it out even quicker. And the fix is pretty simple, isn’t it?

"[if the noun is the player]The[otherwise][The noun]'s[end if] cloak of reflection [bold type]reflects[roman type] the attack back to [the actor]!"

Done, except that I always use “[Possessive of the noun]” rather than “[The noun]'s”. (I don’t know if this ever makes any difference?)

It makes a difference if you haven’t included Plurality for some reason, which I usually haven’t in my toy test examples.

ATTACK itself includes Plurality, it’s very dependent on it.

RIght, I just meant that when I write little code snippets I tend not to use things that depend on Plurality, because I’m not experienced in it. This will probably change if I ever write a real game.

Tutorial 5: The Arcane Vault

Today we’ll be making a room. This is a rare magical room known as the Arcane Vault. In the middle of the Arcane Vault is crystal pedestal on which the player will find an exotic and powerful magical book – and when I say “exotic and powerful”, I mean bizarre. That is why the room is rare.

How do we make a room? The first part is easy.

The Arcane Vault is a room. "An oppressive silence pervades the marble hall, as if all earthly sounds are smothered by the alien force of magic. For magic is strong here, and seems to be radiating outward from a crystal pedestal in the middle of the room."

But if we look at the rooms in the Kerkerkruip Rooms extension, we will see that immediately after the description, a lot of properties are defined that we are unfamiliar with.

The Arcane Vault is connectable. The Arcane Vault is not connection-inviting. The Arcane Vault is placeable. The Arcane Vault is not habitable. The Arcane Vault is not treasurable. The Arcane Vault is teleportable. The Arcane Vault is not extra-accepting. The Arcane Vault is vp-agnostic. The Arcane Vault is magical.
What does all that mean?

If a room is not connectable, then (a) the dungeon generation rules will not connect any later-placed rooms to it, and (b) you cannot dig to or from it. This property is meant for rooms like the bridge of doom, where it would make no sense for the dungeon generator (or the player with a magical spade) to connect it to a room above it, say. Normally, we don’t need to worry about that, so almost all rooms in the game are connectable.

A room that is connection-inviting will always be linked up with rooms that are generated next to it. We use this for rooms that should feel like transportation hubs (like the Entrance Hall) or that are just more fun if there are more rooms connected to it (like the Hall of Vapours).

A room that is placeable can be placed by the normal dungeon generating rules. It should only be used for rooms that can be part of the normal dungeon. The Hidden Treasury, the Maze and the Elemental Plane of Smoke are not placeable, for instance.

The dungeon generation rules will only place monsters in habitable rooms, treasures in treasurable rooms, and extra scenery objects in extra-accepting rooms.

Teleportation will only ever take you to teleportable rooms. (We don’t want teleportations to end up in the Lake of Lava, or the Eterenal Prison, or places like that.)

A vp-agnostic room is one which doesn’t care whether it is placed high or low in the dungeon. (Some rooms have a preference – just for flavour. It is probably not noticed by players.)

Finally, just like items rooms have moods, which are used to match items to rooms. The mood of the Arcane Vault is of course magical.

Now, what we want is the following. Sometimes, but rarely, the Arcane Vault will be found in the dungeon itself. And sometimes, but also rarely, it will lie waiting around for an enterprising player with a magical spade. We ensure the first by giving the room a rarity of 5 (making it 32 times less likely to spawn than a normal room), and the second by a rule we copy more or less verbatim from the other hidden rooms:

[code]The rarity of Arcane Vault is 5.

A dungeon interest rule (this is the potentially add the Arcane Vault rule):
if Arcane Vault is not placed:
if a random chance of 1 in 30 succeeds:
put Arcane Vault in a near location;
now Arcane Vault is not teleportable.[/code]
Note two things: we only add the Arcane Vault in a random location if the dungeon generation rules have not already made it “placed”; and if it is placed in a random, unconnected location, we remove the ‘teleportable’ attribute. We don’t want the player to end up in a place she can’t escape from.

Let’s add this, because it goes well with the room description:

Instead of listening to the Arcane Vault: say "All sounds seem muffled and unreal.".
And now we write the crystal pedestal:

[code]The crystal pedestal is scenery in Arcane Vault. The crystal pedestal is a supporter. The description of crystal pedestal is “The pedestal is made of a pale purple crystal you have never seen before. On top of it lies [if at least one tome is on the crystal pedestal][a random tome on the crystal pedestal][otherwise]a tome-shaped piece of air[end if].”

A dungeon interest rule (this is the place a tome on the pedestal rule):
let item be a random off-stage tome;
move item to the crystal pedestal;
if generation info is true, say “* Put [item] on the pedestal.”.

Check taking a tome (this is the do no remove tomes from the pedestal rule):
if the noun is on the crystal pedestal:
say “The magical forces binding the tome to the pedestal are too great.” instead.[/code]
“dungeon generation” is a truth state that is false in released versions of the game, but that as developers we sometime toggle to true. (It is in the main source file.) It is good design to announce all decisions of the dungeon generating process if generation info is true.

If you are wondering what it looks like, check this:
[rant]Generating map…

  • north of Entrance Hall (0, 0, 0) is Alchemical Laboratory (1, 0, 0).
  • west of Entrance Hall (0, 0, 0) is Hall of Mirrors (0, -1, 0).
  • down of Hall of Mirrors (0, -1, 0) is Portal Room (0, -1, -1).
  • east of Portal Room (0, -1, -1) is Crypt (0, 0, -1).
  • south of Entrance Hall (0, 0, 0) is Workshop of the Blademaster (-1, 0, 0).
  • north of Hall of Mirrors (0, -1, 0) is Bridge of Doom (1, -1, 0).
  • north of Bridge of Doom (1, -1, 0) is Library (2, -1, 0).
  • down of Bridge of Doom (1, -1, 0) is Lake of Lava (1, -1, -1).
  • south of Workshop of the Blademaster (-1, 0, 0) is Drawing Room (-2, 0, 0).
  • Placed Quartering Room west of Drawing Room.
  • west of Library (2, -1, 0) is Hall of Vapours (2, -2, 0).
  • Adding connection between Entrance Hall and Crypt.

Placing monsters…

  • Placing blood ape (level 1) in Workshop of the Blademaster.
  • Placing Reaper (level 2) in Hall of Mirrors.
  • Placing Miranda (level 1) in Bridge of Doom.
  • Placing mindslug (level 3) in Drawing Room.
  • Placing chain golem (level 2) in Portal Room.
  • Placing Bodmall (level 4) in Library.
  • Placing Malygris (level 5) in Hall of Vapours.

Placing treasures…

  • Decided that small-rust-grenade-pack is too rare.

  • placed crown of the empire in Library

  • placed small-scroll-of-summoning-pack in Library

  • placed small-scroll-of-identify-pack in Hall of Vapours

  • placed small-flash-grenade-pack in Drawing Room

  • placed fearsome axe in Entrance Hall

  • placed second-small-scroll-of-identify-pack in Entrance Hall

  • placed small-scroll-of-shadows-pack in Drawing Room

  • placed suit of plate mail in Library

  • placed deathly-pack in Drawing Room

  • placed Blessed Grenade in Quartering Room

  • placed large-scroll-of-teleportation-pack in Drawing Room

  • placed large-fragmentation-grenade-pack in Drawing Room

  • placed cloak of shadows in Drawing Room

  • placed robe of the dead mage in Quartering Room

  • Putting small-scroll-of-skill-pack in sarcophagus.

  • Cursed cloak of reflection.

  • Cursed cursed boots of wandering.

  • Cursed monk’s robe.

  • Cursed vampiric dagger.

  • Malygris wears the cloak of reflection.

  • Put Tome of Transmutation on the pedestal.

  • placed flickering lamps in Drawing Room

  • placed holy symbols in Workshop of the Blademaster

  • scroll labelled MORT EILYSH: scroll-death.

  • scroll labelled NAAR OD ERAE: scroll-ghoulification.

  • scroll labelled DOLP ZEEZ: scroll-teleportation.

  • scroll labelled CHETNAK: scroll-remove-curse.

  • scroll labelled CISTROB JIRSGEV: scroll-shadows.

  • scroll labelled TWAN METIER: scroll-protection.

  • scroll labelled HERMEI LE SCHIM: scroll-blade.

  • scroll labelled LONSIFIRA: scroll-skill.

  • scroll labelled KRIPMETEEL: scroll-ethereal.

  • scroll labelled SOUSPENOT: scroll-identify.

  • scroll labelled SHALM SAWESAS: scroll-summoning.

  • scroll labelled ZYXYZ: scroll-fireworks.
    Finishing the dungeon…[/rant]

By the way, this code assumes that we have a tome kind, which is not in Kerkerkruip version 5: I just added it. But we already did have a tome, namely, the Tome of Transmutation, which turns all objects of a randomly chosen material into objects of another randomly chosen material. We’ll make more tomes in our next few tutorials.