Crashcourse - Part 03

[previous part] [Table of contents] [next part]

In this part of the course, we will concentrate on monsters and their behavior.

Let's start off with a very simple monster called tiny.

FILENAME: tiny.c

As you can see, it's not too much work to code the simplest of monsters. But, you will soon see that you have a lot of choices to make when coding them. There are only 3 new functions in this file. set_level() which is very easy to understand. Using it, you set the monster's level. But, there's more to it. When you set the monster's level, you also set the monster's stats (strength / dexterity / constitution / intelligence) and the monster's hit points and spell points, as they are automatically set and adjusted acording to the level when you call set_level(). As you will see later on, these things can be altered very easily. The next function is set_gender(), which decides which gender a monster shall have. You have three choices, 0, 1 and 2. 0 will make the monster genderless, 1 will make the monster male and 2 will make the monster female. If you don't like memorizing numbers you may also use :


set_al() is last of the new functions and set the alignment of the monster. The alignment can be both positive and negative.

The aligment table looks like this:

Alignment table
Value Align
-1000 and less
-999 to -200
-199 to -40
-39 to 39
40 to 199
200 to 899
900 to 1299
1300 and more

A value of 100, as Tiny has, makes the monster nice.

FILENAME: gnome.c

This dude is tougher than Tiny as you can clearly see from his level. And as usual, new functions have been introduced. set_race() is the first one. It sets which race the monster belongs to. For instance, a tiger would have the race 'cat'. There are no restrictions which races you may use in monsters, but try to have them make sense. The race fish on a bird doesn't make much sense, does it? ;-)
In Bossy, we also set each of his stats individually, using the functions :


We also set how many hitpoints he should have using the function set_hp(). There is an equal function called set_sp() for spell points, also.

Note! When you alter the stats and the hps/sps of a monster, ALWAYS remember to place them AFTER the set_level() function. This is because set_level() changes them to default values.

The last new function in this monster, is set_aggressivity(), which sets how aggressive a monster shall be. It may be an integer from 0 to 100, where 100 is guaranteed an attack and 0 makes the monster not attack anyone. set_aggressivity() only makes a monster aggressive towards players.

NB! An invisible player may not be attacked in this manner, as the monster cannot see him/her.
FILENAME: mage.c

This evil woman has read the ancient books of evil and has decided to spread havoc around her. She also has a lot of new functions to live her up. :-)
This time we have introduced some more interesting features to a monster. If you first take a look at the long description, you will notice that her eyes are evil. Wouldn't it then be logic to be able to look at her eyes? To make that possible we use the function called add_item(). This is a function that exists in all items and monsters. This function gives us coders the possibility to make our monsters (and items) more interesting by giving the players more to examine.
If you take a good look at how we have used the function in the mage, you will probably understand how it works right away. The first parameter to the function is either a string or an array of strings. This string or array contains the ids a player may look at. The second parameter is usually a string containing the text that the player sees when he/she/it looks at one of the ids. I write usually because it may also be a function pointer, but we will come back to that in a later course(#09). The add_item() function has some more parameters you may use, but we'll save it for a later course(#04).

If you now take a look at the set_str() and set_dex() function you see that we have added another functioncall inside it. It's the system function random(). It returns a random integer in the range 0 to the parameter-1. So, for instance, random(5) would yield an integer between 0 and 4. This function is a very nice feature when trying to make your monsters behave differently every time they are created. In the mage we have only used it for random stats, but you can use it for so much more.

You can make the monster change it's appearance totally. Take a quick look at this one:

FILENAME: random.c

As you can see we have created a global variable called ran which is an integer. This variable has been given a random value of 0, 1 or 2. Using this random variable, we can make 3 different monsters in one single file! As you can see we're using arrays of different values to make the monsters different. Using an index(the ran variable), we can tell the mudlib which one in the array we're gonna use this time. But, since the value is random it will change every time the monster is killed and respawned. As you can see random() is a function very well suited for making your mud world versatile. This random file is only meant to show you some of it's potential, but I'm sure you can think of other ways to use it also.

Now, if we jump back to the file we were examining (the mage), we get to the next new function: add_exp(). Experience is a very important part of the mud world. Using experience points you can advance stats and levels. And often skills (depending on the guild you have joined), too. There is no function in monsters that tells you how much experience a player gets for killing it, but it's not too hard to calculate. When a monster is killed, the player gets roughly 1/52 of the monster's experience. This value will be altered if the player have fleed from it, if the player is in a party, etc. When you set the level of the monster, the monster automatically gets a certain amount of experience points (the same as a player of the same level has). But, sometimes you want to alter that. For this use you have two different functions: set_ep() and add_exp().
The first one allows you to set the monster's amount of experience points, but only up to the value that the monster would get by its level and lower. This function is not often used, and I recommend you use the other one, add_exp(). add_exp() alters the amount of experience points the monsters gets. This alteration may be of negative and positive value.

NB! This function, along with the following two _must_ come after the set_level() function since the set_level() function sets some default values. I recommend you use the set_level() function early in the create() block.

The next two functions, set_wc() and set_ac() alter the monster's basic weapon class and armour class. These values are the basic values the monster get, before regular weapons and armours are added to the classes. So a monster wielding a class 10 weapon with a set_wc(20) would gain a weapon class of 30, making it able to do basic damage of 0 to 29 on its attacker (Of course that basic damage may later on be altered to account for the target's armour class).

And, now it's time to turn our attention to perhaps the most interesting part of a monster's fighting abilities: spells.
Spells can make the monster much more interesting to fight, especially if the spell messages are well thought through and cool. :-) Standard monster only have the ability to cast one single spell. (You can of course use random() here, but it will still only cast one type of spell each time it is spawned.) In later courses(#05+#06), we will make monsters that cast more than one spell.

To make a monster cast a spell, the easiest way would be to use the standard spell functions. To make a single spell you have to use 5 different functions. The first two functions define the messages to be sent. set_spell_mess1() defines the message that shall be sent to all the players in the room, except the attacker. In this message it is possible to include special format codes. Do a 'man format_message' to read more about the special format codes. In the mage we have only used the code #N which will be changed into the attacker's name capitalized before the message is written to the room. These format codes make it possible to include names and pronouns inside spell messages at runtime. The second function set_spell_mess2() defines the message to be sent to the player himself.
Now that we have defined the messages to be written when the spell is cast, we have to tell the mudlib how much and what type of damage the spell is supposed to do. set_spell_dam() will define how many hps damage the spell is supposed to do on the attacker (it will do random damage from 0 to the integer specified in the function). set_spell_dam_type() sets the type of damage that is to be done on the attacker. In this case the spell will do fire damage on a random location on the attacker. If we had written the damage type with a capital letter, the spell would have done the specified damage on ALL of the player. ('Fire' instead of 'fire')
Read more about this and all the different damage types with: 'man damage'

It should be noted that you don't have to set a single type of damage for the spell. You can use an array of different damagetypes if the spell suggests it.

set_spell_dam_type(({"fire","impact"}));    // fire + impact

The last function concerning this type of spell casting is set_spell_chance(). This function sets the procentage chance for the spell to occur every combat round. If you set set_spell_chance(100); the spell will be cast EVERY single combat round.

Now, it's time to further improve our monsters. They are a bit quiet, don't you think? More messages would be nice.

FILENAME: colussus.c

This one is different from the other ones in two aspects. He talks and he walks. To take the last one first, to make a wandering monster, we need to inherit I_WMONSTER, and of course replace_program the same one. When inheriting I_WMONSTER we automatically also inherit I_MONSTER since I_WMONSTER inherits I_MONSTER. By inheriting the wandering monster file, we get access to a few new functions. We have only used two of them in the colussus example, but there are more('man monster' for a more detailed list). The two functions we are using in this example are: set_wandering_chance() and set_wandering_time() . The first one sets the procentage chance(0-100) of the monster trying to wander into a new room. set_wandering_time() defines how often(in seconds) the monster shall try to wander off. In the colussus example, he will have 80% chance every 10 seconds to wander into a new room. It is important to notice here that a walking monster cannot wander into a room that has the 'no_wander' property set.

If you clone this monster, make sure he can't escape you! If you are standing inside your workroom when you clone him, he will wander off into the exits in your workroom. These exits are usually set to in-game rooms, and monsters not passed QC are NOT allowed in the game! So if you want to try it inside your workroom without him wandering off, you can do this:
'patch . remove_exit exitname' for every exit in the room. For instance 'patch . remove_exit south' to remove a south exit. When you have tested him and destroyed him, you can get the room back to its initial state by 'fresh .' which will reload your workroom.

Now it's time to take a look at the chat functions for the monsters. There are two functions for this purpose: load_chat() and load_a_chat(), where the first one is for chatting outside of combat and the other one is for chatting during combat rounds.
If you take a look at the two functions you will notice that the first parameter is an integer, while the other one is an array of strings. The integer tells the mudlib how much chance there is for the monster to talk every round. In colussus we have used 20% chance each round for both talk functions. If you make a talking monster keep in mind that any higher procentage than 15-20, will make the monster a bit annoying. Too much is not much better than too little. ;-)
The second parameter is the array of strings. If a talk occurs, the mudlib will choose a random string from that array to send as the message to the players in the same room.
As you can see, some of the strings start with the characters ! and *. These are special cases which the mudlib interprets and translates into commands. *command means that the monster shall execute the string following the * as a command. For instance, '*sigh' will make the monster sigh deeply. It is important to remember that monsters can only use the standard player commands (not guild commands) unless their command paths are altered. We will get back to this in a later course(#06).
The ! character is only used in the combat talks (load_a_chat()) and will cause the mudlib to insert the attackers name directly after the command. Almost directly, anyways, since the mudlib inserts a space between the name and the command also. ;-)
'!kick' would then cause the monster to "kick" the attacker. The feeling kick, that is.

FILENAME: soldier.c

The last monster for this lesson is the strong soldier.
As usual we introduce some new functions for your pleasure. ;-) The new function add_eq() is a very important function. It is the function you use when providing your monsters with equipment. The add_eq() function automatically senses what kind of eq it is, and if it's a weapon the monster will attempt to wield it and if it's an armour the monster will try to wear it. As you can see, we've been a bit lazy and just used the equipment we created in the previous course for the soldier. The parameters for the function is first a filename and the second is an integer telling the mudlib how many objects to create.
The add_skill() function is used to alter the skills of the monster. The skill 'two_weapon' makes him able to wield two weapons, one in each hand. The value 100 means that he is fully (100%) trained in the skill. The 'prot_magic' skill means that the soldier is somewhat protected against magic(10% in this case).

There are several different skills the monster may have, such as prot_fire, prot_cold, prot_blunt, etc. Skills usually start with: prot_, vuln_ or resist_, and end with the damage type (fire, cold, magic, acid, etc).
Skills starting with prot_ are skills that try to "block" some damage totally. For instance prot_ of 10 will make it 10% chance that the damage will not do ANY damage at all. Skills starting with vuln_ will make the monster/player more vulunrable to the specified damage type. A vuln_ of 10 will make it 10% chance that the damage done to the monster/player will be doubled. The resist_ skills try to reduce the damage done on the monster/player. A resist_ skill of 10 will make it 10% chance that the damage is reduced to 1/3.

If you take a look at the load_a_chat() function, you see that this one could be tough to fight since there's a 20% chance every round that he will eat or drink something and thereby heal himself a bit. This type of use of load_a_chat() is an easy way of making the monster heal during combat. Of course it is a very random healing and the monster will get drunk/stuffed by it.
There are some new properties in this soldier also. And a short description follows:

guardian Monsters with this property are guardians and will not be moved by spells or other dark forces.
no_disarm Monsters with this property are impossible to disarm. No spells and no abilities shall be able to make the monster unwield its weapons.
no_disease This property will make the monster totally protected against diseases.
no_poison This property will make the monster totally protected against poisons.

As a closing note, we have not gone through all (far from it) RESERVED functions available to monsters, only the most common ones. If you do a 'man monster' you will find more functions to play around with.

Just remember, don't be afraid to try and don't be afraid to ask for help.

WRITTEN: 30 - Sep - 1996 - Gunner
LAST UPDATE: 26 - May - 1998 - Gunner
HTML Version: 30 - Jan - 2000 - Ghorwin

[previous part] [to the top] [Table of contents] [next part]