Attenzione: questo è un manuale che contiene informazioni non aggiornate... ma è meglio di niente ;-)
MVS stands for multi-versatile system; which is exactly what this Inform library is: a collection of independent object and classes that let you recreate a role playing like system in your Inform adventures.
In the library you will find little stand-alone mechanisms that would be useful in your adventure even if you don't want to replicate a full range role play, like the Follower and the MagicalGenerator classes, and the TimeScale and Sky system.
But you will find also a full-fledged magical system with spells, books, scrolls, wands and the like, with three magical subsystem at your disposal: Cast-and-Forget, in which you memorize and cast spells as bullets to shoot, Magic-Points, that gives the player the ability to cast any spell until all it's magic points are over, or Fatigue-Generating, that will hurt (fatigue) the player when magical powers are drawn. You can have instant or timed spells (which gives the thrill of wait), and even NPC (non-player characters) with magical abilities!
And you'll find a great fighting system that allow your player to fight against any kind and any number of enemy. You can also display battles in which the player is only a spectator, giving (if he wishes) orders to it's allied, with two or more alliance of warriors fighting each other. Armors, weapons, magical bonuses (independent from magic system) are also included.
And now, after this announcement, let's take a closer look to the library.
The library is built up with modules, which can contain one or more classes or objects that are related to a certain subsystem. Subsystem are the following:
Damage: base damage system for role-play-like adventures; used heavily by everything that could hurt an object or a living being: the fighting system, the aggressive spells and the fatigue generating magic system.
Magic: defines spells, spells sources (memory, books, scrolls, wands etc.), and spell like objects.
Fighting: defines fighting rules, included the behavior of non-player characters in fight.
Other than that, we have some utility module:
Following: the "following" system is useful to create companions for the player, or to threat it with "sticky" opponents. They can be simple animate creatures, or they can be warriors or even mages.
Time: subsystem useful for showing the passing of time under an open sky, or to wake up objects at a certain time without having to StartDaemon them.
Standard Spells: collection of useful standard spells, that can be used as an example to create your own spells, or used directly in your adventure.
Magic Objects: useful collection of magical objects, like magical potions and the like.
Each module is independent. You can even use Standard Spells without the magical system, if you manage the spell casting directly; and sometime this can be useful.
The subsystem are in separate files, to help your job and keep clean the code form undesired heavy objects:
"MVS_Damage.h" contains the Damage subsystem, and is included from Magic, Standard Spells and Fighting systems. It's a very little module, with a lot of useful constants.
"MVS_Magic.h" contains the magic system. Since it's grammar rules will not redefine any Inform library grammar line, the file contains also the rules.
"MVS_War.h" contains the fighting system.
"MVS_WarGrammar.h" contains the grammar rules for fighting system, and should be included after "Grammar.h" Inform library file.
"MVS_Time.h" contains the time system; since it doesn't redefine any standard verb, it's grammar rules are inside this file.
"MVS_StdSpells.h" contains the Standard spells definition. Include only if you plan to use them, otherwise they are only a dead weight in your code (a "Spell" is a small object).
"MVS_Following.h" contains the Following system; since it doesn't redefine any standard verb, it's grammar rules are inside this file.
"MVS_MagicObject.h" contains magical objects.
"MVS.h" includes all the above files, except for "MVS_WarGrammar.h", that you have to include at the end of your file, and (maybe) before your story grammar definitions.
If the player has to damage some object in your story, this library comes useful. It simply defines the damage common property which will be held by any object that can be damaged. The damage property should be a routine in the form:
integer damage(amount, type)
amount - how much damage the object is going to receive
type - (optional) the type of damage, which could be one of the following...
if omitted, the type is intended to be DMG_GENERAL. The types can be combined adding them; i.e. a flaming sword could cause a damage of fire and cut type.
Returns - 0 to signal that the target is immune, and won't accept the damage; a greater value means that the target accepted the returned amount of damage. Could be lesser than the amount if the target filters only a part of the damage. If amount is 0, that means that the sender is only willing to check if the target is immune to a certain source. Damage will behave as usual, returning 0 or a value greater than 0, but without harming in any way the object.
The target can "filter" (refuse to accept) the damage if it's immune to a certain type or a certain source. The source of the damage is the sender object that generated the damage message toward the target. A fireball like spell generates a fire type damage; a magical tree could be immune to normal fire, but not if the damage is generated form a spell. A wizard could be immune to magic (test if sender ofclass Spell). And so on...
The damage system define also IsDamageable routine, that returns true if ...
IsDamagable is meant to be used with grammar definitions; Inform library damaging means will generate an "Attack" action directed to the Life routine of an object. MVS fighting system will generate an AttackDamagable action if the attack is against an object that provides Damage with this grammar rule:
Extend "attack" only
* noun = IsDamageable -> AttackDamageable;
This will let alone a trivial attack against a living being (which will receive the Attack action in Life) or against an object (which will generate a default dummy message), but will transform an attack against a "willing" object in a RPG like attack. You can use IsDamageable like that to filter actions against evolved RPG behaving objects. This means also that for the MVS is enough that an object provides a damage property to know that as a RPG interactive object. No need to declare it derived from exotic and complex classes; just build it as usual, and equip it with a damage routine.
The damage routine have not to be complex. In WarMage story, the wooden door of the magic shop can be opened if hit with a fire generating attack. It's damage routine checks for a greater than 0 amount, and a type equals to DMG_FIRE; if that's matched, the door is removed, and the damage routine returns true. This allow the ferdem spell (fire bolt) to acquire the door as a valid target. The Burn action could be easily used with the same objective, using a Before routine or adding a grammar line like that
Extend "burn"
* noun = IsDamageable -> BurnDamagable;
The BurnDamagable routine would check for a fire generating object to be in player (a torch?), and then generate a damage message towards the damageable object. This would let alone non damageable objects which will continue to behave as usual.
The magic system is very flexible, and allow a deep customization. Above all, there are three types of magic systems: Cast and Forget, Magic Points, and Fatigue Generating.
The CF system is alike the classical Infocom magical system. A mage can learn a certain number of spells. When the mage puts in memory a spell it become available for casting. Once cast, the spell is forgotten, and has to be learned again to be used a second time. A mage can learn a spell more than one time; so he will be able to cast the spell a number of times equal to the number of times he "committed" the spell to memory.
When a mage tries to learn more spells than he can, a previously learned spells will be randomly forgotten.
The MP system gives the mage a limited amount of power, the "magic points" (at which can be given different names: mana, mental power, will points, etc.). A spell consumes one or more magic points. When the points are over, the mage has to rest (or to do other things) to restore them. This means also that spells, once learned, can be never forgotten, and can be used any time the mage wishes, provided he has enough magic points to cast them.
The FG system is much alike the MP system, but the casting cost is not subtracted form a given "power lot". The spell cost is directly sent to the damage property of the caster, if he has one. Normally, this should affect the mage health, driving the caster nearer to death as he uses his spells. A mage can cast a spell even if he hasn't enough health left; this extreme sacrifice will lead him to death (but you can always make him win: a great final!).
All the system can be configured with two different variables: verbosity of known spells listing, and timing. The latter (timing) will force the player to wait (to type the "wait" command) a given amount of turns, depending on the spell which the mage is casting. If the player does something else (flees? Attacks?) before the spell-casting is done, or if he receives a damage message, the concentration is broken. The spell won't be launched, but no cost will be charged to the mage. If the system is configured as "instant", all the spells will take effect when the player casts them.
Verbosity of the system is meant to prevent the player from reading undesired information. With high verbosity, when the player lists the spells in it's memory, all the statistics of the spells (casting time, casting cost and power) will be shown. With low verbosity, the player will read only the name and the purpose of the spell. If you are using a CF system with instant timing, all the data of the spell are useless, thus showing them is misleading for the player.
The magic capability of an actor is referred as his memory. The magic system is encoded in four classes: the BaseMemory, that handles the common codes and should never be used directly, the CF_Memory, the MP_Memory and the FG_Memory, which handle the specialized part of codes. Other than that there is a NPC_Memory which is meant to be used by non-player characters, and is simplified in many ways.
To see how magic system works, we have to see how the player will interact with it. Casting a spell is a simple matter, like entering the wording ">cast the zifmia at the frog". This activates a CAST action which will be sent to the zifmia_spell object's before routine. The target will receive the fake action CastAt. Both are group 2 actions, which means that they generate both before and after routines. The player can also type in ">zifmia the frog", that is, it can type the name of the spell followed by it's target, without having to enter the "cast" verb. Well this brings up a problem: the standard hooking routine UnknownVerb must be used to identify the spell names, and generate a coherent Cast action, so you can't use it in your story.
Spells can have no target, in which case the player would type in ">cast zifmia" or "zifmia" only.
Player can even learn and scribe spells. To learn a spell, he must simply type ">learn zifmia" or ">memorize zifmia"; the system will take care of searching a proper learning source for the spell. The spell will receive a Memorize action, which is a group 2 action again. If he wants, he can record memorized spells on a valid support (like a scroll or a book) entering ">scribe the zifmia on the scroll"; again, zifmia spell will receive the Scribe action, which belongs to group 2.
Finally, a player can unfold a scroll, freeing all it's powers at once, typing "> unfold the scroll", or ">unroll the scroll"; an Unfold action (group 2) will be generated and sent to the object.
The memory is responsible of all the magical interaction with the world after the grammar checking of a Cast action (see below) is passed.
To make an animate object a mage, simply move a memory object to it like that:
MP_Memory mpm;
[Initialize;
move mpm to player;
]
This will make the player object a mage with standard Magic Points capabilities. Memory objects are invisible to inventory, and can't be referenced from player. The choice of making a mage simply moving a memory in an animate being has been made for two reason:
If the powers of the mage radically change temporally or permanently, you can simply remove the memory or move a different memory to the mage.
If the player (or other actor) is transformed in something else by an hostile mage, it can easily loose it's powers, that remains bounded to the original player object. But is easy to carry magical powers with the mage if he willful shifts form: simply, move them to the new form.
To retrieve the memory of a player, there is the function:
object GetMemory(actor);
actor - the person from which you want to retrieve the memory.
Returns - the memory of the actor, or nothing if the actor is not a mage.
For the player only, available spells are in memory; to make a spell available, simply move it to the memory of the player. However, it's better to use the know_spell(spell) property of a memory, that will handle also committing spells in memory more than once. This also has been chosen for two reasons:
The parent-child relationship is very simple and fast processed. Player object will (likely) use spells often, and a fast and neat mechanism to handle known spells is a godsend.
Arrays property are limited to 16 word entry in Inform, while the relationship parent-child has no limitation. 16 spells are enough for an NPC mage which duration in the game is short, but they could be a serious limitation for the player character.
Putting a spell in memory is not enough to make it available to the player. He must have red the name of the spell at least once in the game, but this will be discussed later, and is not a limitation: is a precise choice. However, know_spell will take care of all the handling needed to make a spell available to player.
Memory is responsible for learning and casting spells. A Cast action will be converted in a start_cast message for the memory of the actor, and, after a few handling, the memory itself calls its cast property; if the spell system is not timed, this is immediately converted in a fire message to the memory itself, else the fire will be delayed by a waiting daemon.
Learning works like that: a Learn action will send a learn_spell message to the actor's memory, that is responsible to find a valid source for the spell, and to handle all the exceptions.
Spells are the core of the spell casting system, and are responsible of impress their effect on the objects in the game. There are two ways in which a spell can generate an effect: spell driven and target driven. In a spell driven effect, the spell will completely handle the application of effect on the target(s): i.e. a spell which gives light attribute to a location or an object, or a spell which opens a locked openable object. The target driven method require some collaboration of the target: i.e. the "uncurse" spell of Standard Spells will check for an uncurse property in the target object, and then will send the uncurse message to the target. Same as a spell that damages a target: they will check for a damage property, and if they find one, they will call the damage of the target. There is no formal difference between the two, except that if you program a target driven effect, you'll have to write down some object capable of interact with the spell, while a spell driven effect is completely independent from environment.
Spells can be targeted at objects, or cast without a specific target. Anyway, some spell are valid only if cast at something, while others can't take a specific target. This is determined as follow:
If the spell provides a fire property, this means that the spell can be targeted at an object. The target will be passed as the parameter of the fire routine of the spell.
If the spell provides a fire_to_all property, this means that the spell can be cast without a target. The fire_to_all will be called, and it's a duty of the spell to find a valid target, or to manage the effect without a target. Some spells are applicable only if fired by the player. Those spells do not require any parameter: fire_to_all will refer to the location. If the spell can be cast by NPCs (like all aggressive spells), the fire_to_all routine gets a parameter, that could be either the caster of the spell (if the spell is launched by some actor) or the place in which the spell will take effect. Memory and library objects take care of calling the fire_to_all with the return of FindCaster(object), that retrieves the person who is holding the casting object (even memory is in player) or the place in which the object lays.
A spell can provide a fire, a fire_to_all or both. I.e. , the litdem standard spell (give light an object or a place) provides both fire and fire_to_all. If the player casts litdem on an object, that becomes the target, and the memory of the actor calls litdem.fire(target). The routine will give the light attribute to the target. The player can legally cast also a litdem spell without targets. In that case, the memory will call litdem.fire_to_all(caster) that gives light to the location parent of the caster.
A player can't reference a spell if he have never red of it in any place in the game. When this happens, the spell receives the attribute known_about, which is a common attribute for magical items that becomes available to the player for use. This attribute is automatically given to spells if their short_name is displayed; that means that when the name of the spell is listed somehow, i.e. as a memory or book content listing, the spell can be typed by the player and will be understood as a legal spell by the parser. Sometimes you'll have to give this attribute in the code of your story: i.e., if you give a spell to player's memory as a reward for a solved quest like that:
print "As a reward, the Lady of the Lake teaches you the bandor spell.^";
move bandor_spell to GetMemory(player);
give bandor_spell known_about;
This because is not polite to tell the player that "bandor" is an unknown word after giving him the spell. Same effect can be achieved with:
print "As a reward, the Lady of the Lake teaches you",
(the) bandor_spell,".^";
move bandor_spell to GetMemory(player);
That forces the system to display the name of the bandor_spell, and to give known_about to it.
Note: the know_spell property do the same thing, but take cares of commit spells to memory even more than one time.
There are three kind of spells. The simple ones, derived from Spell class, are the most basic ones. The have three statistics: power, casting_time, and casting_cost. The power of a spell is used to determine if a mage is expert enough to learn a spell. If not, the player won't be able to learn the spell, and will have to launch it from a valid casting source (i.e. scrolls). The power of a spell could be used also in magical combat, to determine if a spell can beat another spell. Casting time is used by the memory (if it is timed) to determine how long to wait before firing the spell, after the player casts it. Casting cost will be used in MP and FG systems to determine the cost of a spell casting. Other than that, the spells should provide a purpose property (string) which is a short description of the spell effect.
Other than that, they have a committed property, which tells how many times a spell has been committed to memory by the player mage.
The verb "explain" has been added to the standard grammar to explain spells in details. The description property (as usual string or routine) will be displayed if the player types "explain spell_name" (i.e. "explain bandor"), and should provide a deeper description of the effect, and possibly the different effects of a targeted and an untargeted cast. In addition, the "explain" verb will display the statistics of the spell. This could be excluded if the verbosity of the spell is reduced: since explaining the effect of the spell is a matter concerning the spell itself, and not the memory, the spell verbosity overrides the verbosity of the memory. Spell_Verbosity global variable will hold a value like MVS_SPELL_VERB_HI or MVS_SPELL_VERB_LO to indicate the stile of description generate by "explain".
Note: the "explain" command is implemented translating it in a Examine action, and then trapping the action with the before rules.
The other types of spells are derived from the base Spell class: the AggressiveSpell class and the free spells. The first one encapsulates standard behavior of all the spells that interact with the damage property of the target. They implement also the fire_to_all property. As default, the fire_to_all seeks the first target in range that provides damage and isn't a "declared" friend of the caster (if the target is immune, the spell will hit it anyway even if it won't deal any damage). If you set the multiple_target property, fire_to_all will hit all the nearby targets that match that description (mass destruction spells like the fire ball).
The Free Spells implement spells that overcome standard rules of spell casting. To make a spell free, only give it the for_free attribute; this will let you change the freedom of spells during the game, i.e. as a reward.
A free spell is launched immediately even from a timed memory, and generates no cost. It can never be forgotten, and thus, never learned more than once. It's listed differently in memory contents listing, as they specifically don't generate any cost. This class has been added to emulate the gnusto spell: for those unlucky ones that never played "Enchanter" of Infocom, the gnusto spell is a way to scribe spells from scrolls to books. In "Enchanter" and it's sequels, it was implemented as a special verb "disguised" as a spell, but it inspired me to create a class of spells always available. This adds the flexiblity of the spells mixed with the power of a command verb. There is a personal version of the "gnusto" spell in the Standard Spell library as an example.
Spell sources are (as they name should suggest to a clever mind) things from which spells come from. They are an easy way to introduce spells in the story. The SpellSource base class provides basic functionality of referring spells, adding them or deleting them; it could be viewed as a "spell container" in which you could put spells or from which you can extract or copy magic writings. Note that the contents of a spell source are not the spells, that will always be standing by themselves or be into the player memory, but reference to them. For that reason, a spell source can reference 16 spells at his maximum.
The spell sources have a content property which is intended as an array of objects references (the spells). When you derive an object from a spell source, you can fill the content field with spell references or with zeroes. Zeroes are understood as empty spaces that can be filled with new spells.
A spell source will allow multiple copy of spells written on itself. So you can write:
SpellSource myscroll "My Scroll"
With
Content ferdem_spell ferdem_spell litdem_spell 0 0;
Myscroll is a spell source with two ferdem spell and one litdem spell written on it. It has also room for two more spells that can be written onto it.
Base SpellSource does nothing exiting, and is not worth of any further attention (for now). We'll focus on it's derived classes: MagicBook and Scroll.
MagicBooks are meant to hold known spells in a CF_Memory system. You can learn spells from book as many times as you will; books can also be written with new spells memorized from scrolls, or with a gnusto like spell or device (directly from scrolls to books). In FG or MP system, utility of books is lesser, since the player never forgets the spells, but they can still used to teach some new spell to the player.
Scrolls are much more powerful objects. They can be used to learn spells, but also to cast them. A player can "prepare" a scroll for casting, and cast a spell from that scroll. This destroys the written spell, but the spell is launched instantly (even in timed systems) without any cost for the player: a magical gun. More than that, a scroll can be "unfolded" by the player; this will release all the spells still in the scroll, launching their fire_to_all property: a magical shotgun!
Scrolls can be scribed if player (or actor) has a device of class MagicalPen, transferring spells from memory to them. If a scroll has been used to cast or learn a spell, it won't be usable to scribe spells anymore.
When the last spell written on the scroll is gone, so does the magical device.
To get deeper in this topic, we'll have to say that books and scrolls are learning sources; scrolls are also casting sources, but we have to wait a while to see what that means...
Magical devices are a secondary way to give magic capabilities to a player. At first glance, they seems normal everyday objects, sometimes disguising as precious jewels, other times masking as useless rubbish, until a discover_magic message is sent to them: when this happens, they explain their powers to the player, and become active. To make a MagicalDevice active from the beginning, you only have to give it known_about.
Class MagicalDevice has a content property which is a vector of spell references, and provides standard "describe" and "discover_magic" routines to explain it's powers. Since you'll want to make your own description of the object, if you don't want to bother with telling the player what marvelous things the device can do (once it has known_about) just remember to put a self.MagicalBattery::describe() or self.MagicalGenerator:: describe() after your own description of the object (depending on from which subclass of MagicalDevice you will derive your object).
The power of a MagicalDevice could be infinite, but more often it will have a certain number of charges, that will diminish as they are used to cast spells; a device can be recharged using the appropriate spell, or by other means, in your story.
As you noted, there are two subclasses for MagicalDevice, which differs in several ways.
The first one is the MagicalBattery, that you can think of as it was a secondary memory for a skilled mage. Once active (that is, once it has the know_about flag), the battery will be available for use: if "prepared" by the player (with "prepare object") it will intercept casting actions. If they have the spell being cast as an entry of their content array, the spell will be immediately cast (even if player has a timed memory), and no cost will be charged upon the player. As you can understand, batteries are, like scrolls, casting sources.
The second one is the MagicalGenerator. A magical generator can be used by every actor, even if it's not a mage. The generator will be activated by "power words", that the player must type to get a desired effect. When the player types the a word registered in its activation array, the MagicalGenerator will call the fire_to_all property of the corresponding spell in the content array. Note that a spell in a magical generator must provide fire_to_all to be useful.
A spell source is something that can somehow puts a spell in the game. But this definition is too restricted to build a flexible magic system, in which you can cast spells from memory, scrolls, enchanted weapons, etc. The same can be said for spell learning. A spell can be teach by a book, but why not to give the chance to teach spells to other objects, like magical weapons, or something alike?
Learning and casting sources are not classes by themselves. You define a learning source by providing an object with both can_learn and learn routines. The first will returns a value greater than -1 if a spell (passed as parameter) can be learned at this moment from that object. The second will handle the consequence of a successful learning. For a MagicBook, this property does nothing, for a Scroll it removes the spell from itself, and eventually destroys itself if no spell is left.
Similarly, a casting source is defined by providing an object with the can_cast and cast routines, that behave as the learning routine.
Actually, can_learn and can_cast return -1 if the object is unable to teach or cast the desired spell, at this moment. If all the condition to provide a certain spell are met, the routines return a value greater or equal than 0, which represents the priority of the casting object.
When a memory receives start_cast message, it searches all the casting sources in scope for some source ready to fire the desired spell. Every objects returns a value, and the one with the highest value returned wins the bid. In case of parity, the first object that gave the highest value wins the bid. Then, memory sends the cast message to the object that won. Same thing happens for learning.
As you have already guessed, a memory is a casting source, and it's always in scope because is "in player". And you can easily guess that memory is the casting source with lower priority, that means that if no one is willing to cast a spell instead of the memory, the bid will end eventually in considering the offer of the memory, and calling it's cast routine. Learning process is exactly the same, except that memory is not a learning source; if a valid learning source is found, the desired spell is moved to memory, and the learn routine of the source is called.
Below are the library defined priority:
Value |
Casting Priority |
Learning Priority |
0 |
MVS_Memory_Priority |
|
1 |
MVS_Scroll_Priority |
MVS_Scroll_Priority |
2 |
MVS_Object_Priority |
MVS_Book_Priority |
The highest priority in casting process is given to the objects (like MagicalGenerators), which are considered less precious than a scroll (that could be used also to learn or that can be scribed in a book). So if a scroll and a MagicalBattery are both willing to cast a certain spell, the battery will be chosen, because the designer thought that it was the way it ought to be. Next, follows the memory. The casting of a spell inflicts a certain cost on the player; moreover, a scroll (and generally other magical devices) must be somehow prepared before the can cast a spell, indicating a deliberate will of the player to use them instead of it's memory. Because of this, memory comes last, when other resources are over.
Learning priorities assume the same philosophy: learning from a book is without cost, while a scroll bound learning has a relevant cost: loosing the ability to cast the spell directly from that scroll. So, if a book is in touch and it can teach a certain spell, it should win over a scroll.
You can create a magical device with less casting cost than a normal device (i.e. with a great or infinite number of charges); is evident that this object should be used instead of more costing spell sources, so it will return a great value (greater than 2, maybe 10) if can_cast assumes that the object is ready to cast the spell.
Remember: can_cast and can_learn are called upon every object providing them in the owner of the memory that is trying to cast or learn a spell.
If you want to make the player (or actor) learn spells from shrines nearby, or use magical totems in sight to cast spells (in example), you'll have to trap CAST or LEARN actions in react_before routine. This will prevent the normal spell resolving process, which is also consistent: the caster will not use the "external object" as he could use it's memory: simply, the object is going to cast a spell by itself, coping with the intentions of the caster.
The fighting system is a collection of objects that will let you put realistic combat scenes in your story. This subsystem is much more versatile than the magic system in a certain way: there is no (functional) difference between the player warrior and other actors with fighting abilities. While an NPC mage has severe limitations upon using magic, and is consistent only if used cast some spells at the player, an NPC warrior has no limitations, and you can consider it exactly as your player fighter.
Fighting scenes can be very complex, having two or more parties in field (group of one or more cooperating fighters is called an alliance), each built up of one or more components. There is even no need for the player to be a part in the battle; provided that he has a way to communicate with his allied in the battle, he can even give orders to them. And there is no need of player cooperation: if the player is not in scope while fight goes on, the system will take care of (silently) resolving the battle; so when the player comes back, the battle could be already over.
You can even build up a number of fighting scenes in different areas of the game, and you don't have to worry about casual wandering warriors: an encounter will automatically end up in a fight, if you set up fighters to be aggressive in advance.
To understand the fighting system, we have to start from the grammar extensions.
A fighter can attack an object that provides damage, generating a damage message that has a type depending on the weapon currently used. He can attack with its "bare hands", or its natural weapons, if it's a monster of some sort, or use a prepared weapon.
So there have been added the commands ">draw weapon" and ">undraw weapon", (generating Draw and Undraw group 2 actions), where weapon is an object of class Weapon that provides draw and undraw property. Then, the player can attack an enemy using ">Attack enemy" where enemy is any object. If the object does not provides damage, the attack action is send to the life property of the object as usual, or handled by the standard library. If the object provides damage, a new group 2 action called AttackDamagable is generated, and that activates the Fighting System.
AttackDamagableSub (the action routine) will call the attack_enemy property of the actor, if provided. If not, it will print a polite message that tells that the actor is now unable to attack anything. As everything in fighting system, this message is sensible to context: if actor is player, the player is told that it can't do that. If the actor isn't the player, but the player is in range, the player is told that the actor is not a warrior and can't do that. If player is not in scope, no message is printed. Usually, the AttackDamagable action will be generated for an actor different from the player only after a direct order of him, because fighting between NPC is handled by daemons only. So a third-party object can't intercept fighting actions generated automatically by NPCs, but this is quite sensible: you can prevent player from attacking someone in one room with a before trapping routine, but if you had to take care of all the AttackDamagable actions generated by NPCs, that would be a real headache. There are other (direct) methods to prevent NPCs from attacking or to govern their behavior beyond standard rules.
Here are described the rules used by the Fighting System. Each fighter has some statistics that determine it's power in combat and its resistance to hits. They are the following:
Maximum health: number of health points that can be sustained as damage before to die.
Current health: number of health point remaining at this moment.
Attack: bonus in the "attack roll" against a defender
Defense: bonus in the "defense roll" against an attacker
Base damage: Minimum damage dealt by the warrior when he hits, whichever weapon he uses.
Minimum damage: minimum damage dealt by warrior if he hits, when not using a weapon.
Maximum damage: maximum damage dealt by warrior if he hits, when not using a weapon.
Armor: number of damage points "absorbed" by the fighter's natural armor; this amount will be subtracted from the damage dealt by an attack.
Initiative: the "speed" of the fighter in attack.
Alliance: determines which fighters are friends, and which are enemies.
The fighting sequence goes as follows: every fighter rolls a random number between 1 and 10, and sums the results to its initiative value; the warrior with highest result attacks first, and then the second, the third, etc. until the last (provided he's still alive...).
The attacker rolls a 1 to 10 random "virtual dice" roll, and sums his attack value. The defender rolls too, and sums his defense value. The resulting sums are called respectively attack and defense roll. If the attack roll is greater than the defense roll, the attacker has hit, and will inflict damage. The amount of damage is calculated generating a random number between the attacker's (or his weapon's) minimum and maximum damage value, and the adding the attacker base damage. Then, the armor of the victim is subtracted from this sum. If the resulting sum is above zero, this amount will be the damage dealt, and unless the victim is (at least partially) immune to the source of the damage, that will be subtracted from the current health of the victim. If his health reaches zero, the victim dies.
The attack "must be declared"; fighters announces which enemy they will attack before throwing the initiative dice. When their attack turn comes, if the declared target is no longer there they "loose" the right to attack.
Objects in fighter's possessions can interact with the process, giving bonuses to attack (generally weapons), defense (like weapon and shields) armor and base damage, or giving some sort of immunity to some sources. Spells can temporarily or permanently alter these values.
A fight is a complex matter, in which every actor has certain rights (attack turn ranking, designed target etc.). Moreover, there can be an undetermined number of fighters wandering through the game, being allied or enemy, and the there can be different battle scenarios running at the same time. For this reason, we need a superpartes object which will take care of tell the warriors what they can do, and when they can do that. The Fight_Referee is a very small objects, which provides found_in and each_turn. The Figth_Referee is found in every room, and thus it's each_turn is always called after the after_routines of all objects in scope of player. It basically does three things: it searches for every object that has the attribute hostile (defined by this system) set, and calls their attack_enemy property (if provided). In this routine, the warrior will search for a likely enemy: a living being that provides damage and has not alliance, or that has a different alliance. If it finds some enemy, it will choose a random one (you can build a smarter routine that targets the weaker enemy, or the most dangerous), and signal it's intention to attack, giving the fight_arena attribute to it's parent (room), and setting it's will_attack property to it's designed target; it will also roll a "dice", a random value from 1 to 10, and will sum the result to the initiative property and all the initiative bonuses it receives from objects. This value will be held by the initiative_roll property. This three actions (choosing an enemy, declaring a fight arena and declaring the initiative) are called "subscription", because they are a subscription to the following fight resolving process.
By the time the hostile objects have subscribed, a player warrior will already have subscribed itself, if it wants to. An AttackDamagable action will subscribe the player object, if he is of class Warrior, exactly as an hostile object is subscribed by the referee. The player can make a friendly warrior to subscribe giving him a direct order to attack some enemy. Other than that, a NPC_Warrior which hasn't hostile and has the same alliance of the player, will subscribe itself reacting after a player attack.
In other words: the player can subscribe attacking, or can make a friendly actor to subscribe ordering him to attack an enemy. If he attacks, NPC_Warrior derived objects have a react_after property that will help the player: if they have the same alliance of the player, and if they are not hostile (that would make them attack on their own decision), they will subscribe attacking the same target as the player.
When all the subscriptions are made, the systems enters the combat resolution phase. In this phase, every room which has fight_arena is searched for Warrior class derived objects willing to attack a target; a ranking is filled with the initiative_roll property, and the first in rank is allow to complete the attack. It's complete_attack is called, so he will handle the fight with his target. Then, the second in rank is picked up, and so on until the last. If a warrior is removed (maybe killed) before its turn to attack, he looses right to attack. If the target of a warrior is removed before the fighter has the chance to attack it, the attacker will remain without target; its complete_attack will be called anyway, but it should do nothing if its target (stored in its will_attack property) has moved away (is not in warrior's parent).
When the fight is over, the Fight_Referee resets the fight_arena attribute of all rooms, and starts the healing routine. Every object (not necessarily of class Warrior) that provides heal and healing property will receive the heal message if their healing value is (currently) greater than 0. So you can have healing monsters that will heal themselves differently: some of them will heal only when there is no enemy nearby, while some others could heal themselves even in the heart of a fight!
You can stop all fights as once by giving absent to Fight_Referee, or you can suspend fights under certain condition assigning a different routine to found_in property. You can also have neutral zones (for player), if you suspend fights while player is in the room (coding its each_turn routine). If you want a room to be neutral for every Warrior in it, give "absent" to it: the Fight_Referee will act as usual, but will reset all the fight_arena that have also absent before running the resolving combat phase. In those neutral room you'll have to intercept AttackDamagable actions (and simple Attack actions too), to print a sensible message explaining why no combat is allowed (i.e. "Killing someone in a church is not polite.").
Note: all the fighting system refers to "room" and not "scope" to determine the availability of targets. An enemy can be hit only if it's in the same warrior's location; it's scope is not considered. An enemy in a glass jar would be in scope, but still can't be hit. Same is for an enemy on the other end of the telephone line. And the same is for enemies out of scope but in the same location: in a large battle field you can't touch an enemy up on a hill (out of "touch" scope), but you can still shoot to him.
The base class of the system is the Warrior class. This class provides some standard attributes: the attribute used by the RPG Fighting System, and the name of the "bare hands", which could be "long fangs" for (i.e.) a tiger.
Every active fighter will use an his own daemon; that means that you should take care of never having too many fighting actors in the game, or you'll have to rise the global value of MAX_DAEMONS standard library switch. Anyway, a fighter will activate its daemon only when an hostile being enters in touch, and will take care of shutting itself off when every threat has ceased.
English text