;;; -*- mode: lisp; syntax: common-lisp -*-

(in-package :cl-user)

(eval-when (:compile-toplevel :load-toplevel :execute)
  (require :iterate)
  (require :hunchentoot)
  (require :cl-who)
  (require :cl-ppcre))

(defpackage :spellcaster
  (:use :common-lisp :iterate :cl-who) 
  (:export :start :stop))

(in-package :spellcaster)

;;; Default parameters
(defparameter *default-users* '(("Emó" nil) ("Peti" nil)))
(defparameter *default-port* 2001)


;;; HTML texts... (defparameter *css* "<!-- h1 { text-align: center; font-family: sans } .chat { width: 100%; height: 10em; overflow: auto; font-family: serif } .time { color: green } .player1 { color: red } .player2 { color: blue } .hide-form { display: inline } .hidden { color: magenta } .shown { color: brown } textarea { font-family: monospace; font-size: large; overflow: auto } pre { font-size: large } -->") (defparameter *spells* " Spells in Forward Order C-D-P-W Dispel magic P-S-D-F Charm person C-S-W-W-S Summon elemental P-S-F-W Summon ogre C-(w Magic mirror P-W-P-F-S-S-S-D Finger of death D-F-F-D-D Lightning bolt P-W-P-W-W-C Haste D-F-P-W Cure heavy wounds S-D Missile D-F-W Cure light wounds S-F-W Summon goblin D-P-P Amnesia S-P-F Anti-spell D-S-F Confusion S-P-F-P-S-D-W Permanency D-S-F-F-F-C Disease S-P-P-C Time stop D-W-F-F-(d Blindness S-S-F-P Resist cold D-W-S-S-S-P Delayed effect S-W-D Fear D-W-W-F-W-C Raise dead S-W-W-C Fire storm D-W-W-F-W-D Poison W-D-D-C + Lightning bolt F-F-F Paralysis W-F-P Cause light wounds F-P-S-F-W Summon troll W-F-P-S-F-W Summon giant F-S-S-D-D Fireball W-P-F-D Cause heavy wounds P Shield W-P-P Counter-spell \(p ! Surrender W-S-S-C Ice storm P-D-W-P Remove enchantment W-W-F-P Resist heat P-P-(w-(s Invisibility W-W-P Protection from evil P-S-D-D Charm monster W-W-S Counter-spell ! This is not a spell + Each wizard may use this spell once per battle, then the gestures have no effect. Spells in Reverse Order \(read your last few gestures backwards to see if you've made a spell) C-D-D-W + Lightning bolt (p ! Surrender C-F-F-F-S-D Disease P-F-S-S Resist cold C-P-P-S Time Stop P-F-W Cause Light wounds C-S-S-W Ice storm P-F-W-W Resist heat C-W-F-W-W-D Raise dead P-P-D Amnesia C-W-W-P-W-P Haste P-P-W Counter spell C-W-W-S Fire storm P-S-S-S-W-D Delayed effect D-D-F-F-D Lightning bolt P-W-D-P Remove enchantment D-D-S-P Charm monster P-W-W Protection from evil D-D-S-S-F Fireball (s-(w-P-P Invisibility \(d-F-F-W-D Blindness S-W-W Counter-spell D-F-P-W Cause heavy wounds S-W-W-S-C Summon elemental D-S Missile (w-C Magic mirror D-S-S-S-F-P-W-P Finger of death W-D-S-P-F-P-S Permanency D-W-F-W-W-D Poison W-F-D Cure light wounds D-W-S Fear W-F-S Summon goblin F-D-S-P Charm person W-F-S-P Summon ogre F-F-F Paralysis W-F-S-P-F Summon troll F-P-S Anti-spell W-F-S-P-F-W Summon giant F-S-D Confusion W-D-D-C Dispel magic P Shield W-P-F-D Cure heavy wounds") (defparameter *rules* " Waving Hands from /Duel Purpose/ A game by Richard Bartle. A number of years ago, Richard Bartle published a zine called _Sauce of the Nile_. One feature I particularly liked was the rules for new games which he produced. One game appealed to me more than the others but it never seemed to achieve the fame it deserved. Since then Richard has rewritten some of its rules and has tried to have it produced commercially but, as his proposed publishers have been using delaying tactics for some time now, he has given me permission to reprint the game. The original name of the game was Spellbinder but, as that name has been used in a commercial game since Richard thought of it, he told me to think up some other name. The game is a rarity as it can be classed as a *fairy game* which is totally dependent upon skill! Andrew Buchanan Introduction This is a game concerning the imaginary conflict between two powerful wizards in a duel of sorcery. The two opponents perform magical gestures with their hands to create their supernatural weapons - spells. Some spells are so potent as to be able to blind a man, call forth terrifying creatures, or even kill the unfortunate victim instantly. Consequently, each wizard must rely on his own cunning to be able to time enough defensive spells to avoid the brunt of his adversary's attack, yet deliver sufficient offensive spells of his own to crack the magical armour of his opponent, and kill the wizard outright. The game is an attempt to capture the spirit of such a battle in as simple yet exciting way as possible. The only equipment needed is pencil, paper and opponent. Time taken varies between 15 - 30 minutes. The inventor wishes to state that he has never been involved in a magical duel but would be interested to discover how realistic the game is for those who have been involved in such a bout. The Turn Each turn both player's will write down in secret the directions for their wizards and the monsters under their wizards control. After both players have written their directions for this turn, the moves are revealed at the same time and dealt with as if the actions specified therein occur simultaneously. Certain spells may alter these circumstances. For example, you don't get to see all of your opponent's moves if their wizard is invisible. Each turn a player's wizard can either gesture with their hands to weave part of a spell, stab with their knife, or do nothing. They use both hands and each hand can act independently or in concord with the other. Monsters will obey their master's commands exactly. Monster's may change hands (as it were) as a result of enchantment. From that point on the monster's attacks are directed by the new master. Monsters may make a single attack each turn against a target chosen by their master or they may spend the turn doing nothing. Monsters may attack on the turn in which they are summoned. Monsters are untrained, unintelligent creatures and can neither gesture nor cast spells. Players personally acquainted with monsters who wish to vouch for their ability to cast spells are requested to keep quiet. Gestures Spells are created by strings of gestures made with the hands. There are five single-handed gestures: * the wiggled fingers (F) * the proferred palm (P) * the snap (S) * the wave (W) * the digit pointing (D) There is one two-handed gesture: the clap (C). Both hands must be specified as clapping in the same turn for this gesture to be valid. There also two non-gestures: * stab (stab) * nothing ( ) The abbreviation for each gesture (or non-gesture) is used when specifing directions for the turn. Spells are cast using an ordered series of gestures. A list of spells and the gestures used to cast them is given in the final section. For example, three wiggling finger gestures on consecutive turns (noted as F-F-F) evokes a *paralysis* spell. The uniqueness of the game, however, is that a single gesture in more than one series and, hence, can be used to cast more than one spell. Gestures may be used in multiple series provided that: * the gestures have been made in the correct sequence without interruption * no more than one spell is created per gesture * all gestures for one spell are made with the same hand For instance, the left hand could cast the F-F-F above. In the following four turns the left hand could gesture (S-S-D-D) to finish off a *fireball* spell since the last five gestures would then be (F-S-S-D-D). Another alternative is to simply perform another (F) for a second *paralysis* spell, as the last three gestures are still (F-F-F). If spells are used in a wise manner and frequently overlap, the overall number of gestures needed to cast them can be cut dramatically. If a gesture can be construed to create two or more spells then the caster chooses which one to cast. For example, the last two gestures of a *finger of death* are the same as *missile*, yet only on odd occasions would the latter spell be chosen in preference to the former. Another example of the one-spell-per-gesture concept is the following: Right hand: P P W S Last 4 gestures form *invisibility* Left hand: W W W S Last 3 gestures form *counter-spell* The trouble here is the *invisibility* spell needs both hands to perform certain gestures. However, since the final S of the left hand cannot be used to cast two spells, it is clear that a choice must be made between the W-W-S of the *counter-spell* and the P-P-(w-(s of the *invisibility*. Here and in the rest of the document an open parenthesis, followed by a lowercase letter, denotes a gesture to be performed with /both hands/ simultaneously. E.g. (w denotes a W by each hand. If the caster completes a series that casts a spell, intentionally or unintentionally, the spell must be cast. Most of these are shot off to nowhere if not required but some cannot be easily discarded. For example *fire storm* gets you no matter where it is released. Note also that some of the larger spells have smaller ones incorporated within their casting series. All spells and monsters need a target, someone or something to be the victim. Usually the target is obvious. Normally enchantments and damaging spells are cast at on your opponent's wizard, whereas protection and summonning spells are cast on your wizard. However, if your target is not the usual one, it must be noted along with the gestures. For example, you may wish to cast a *counter-spell* on your own monster to stop a *charm monster* spell from making it attack you. The target need not exist at the time the gestures are made. \"The elemental he's about to create\" is a valid target but if it still doesn't exist when you actually cast the spell then the spell is discarded (but, once again, recall that certain spells /cannot/ be discarded). Monsters will usually attack their master's opponent but if the target is different, e.g. another monster, then it must be written down along with the monster's action. Spells can be aborted at any point during their development simply by performing a gesture which breaks up the series for that spell. There is no penalty, save having wasted some time. Note that no spells contain *stab* or *nothing*. Also note that nonsense (Zen?)( gestures such as (C with just one hand are considered the same as *nothing* (which is a fairly Zenlike concept, in and of itself). Consequently, after one of these options is taken, all spells must start from scratch. Note also that wizards carry only one dagger and so cannot stab with both hands at the same time. Wizards can, however, change hands for stabbing without wasting time. Such are the disadvantages of physical violence. Certain spells cancel one another if they take effect simultaneously. An obvious example is *finger of death* and *raise dead*. Cancellation occurs when the subjects of the spells concerned are the same, although there are some of the heat versus cold variety which don't care who is the subject. Most other spells which cancel harmlessly are contradictory enchantments (e.g. a wizard cannot both repeat last turn's gestures and give a random gesture with one hand when *amnesia* and *confusion* are cast at the same time). If two spells seem to cancel yet are not mentioned explicitly in the section on spells, use your common sense and you can't go far wrong (henceforth this will be known as the *Cosmic Encounter Rule*). Since spells detonate simultaneously, there is occasionally confusion over spells which don't cancel yet which seem to depend on which happened first. The best example is when a monster is created and, on the same turn, hit by a *fireball*, or something else sufficient to kill it. Since both are simultaneous, the monster will attack that turn whilst being destroyed. There are some examples explicitly mentioned in the final section. For example, ice elementals in an *ice storm* and *counter-spell* or *dispel magic* versus all other spells. Another seeming conflict occurs when a target that is resistant to fire has both a *remove enchantment* and *fireball* cast on them. The enchantment is removed as the fireball explodes (since they are simultaneous) hence the poor victim is fried. If the target were not resistant to fire and was hit by a *resist fire* and *fireball* then they would start to resist fire just as the fireball exploded and be saved. Before the battle commences, the referee casts a *dispel magic* followed by an *anti-spell* at each of the wizards so they cannot commence gesturing prematurely in order to nearly finish a spell when they start the battle. For the same reason, being made resistant to fire in your last battle doesn't do you any good in the next. Winning Each wizard can sustain fourteen points of damage but dies when fifteen or more points of damage are done. The surviving wizard (if any) is declared the winner. Simultaneous death is a posthumous draw. Damage to wizards and monsters is cumulative (so you don't have to do it all in one go!). Dead monsters take no further part in the game. Wizards may also choose to surrender. This is not a spell, but a pair of P gestures made by both hands at the same time signals your surrender. See the final section for details. Spells Below you will find a list of spells (plus *surrender*), what they do, how long they last, and the series of gestures used to cast them. In the notation used for gesture series, upper case letters are used as abbreviations except when two simultaneous single-handed gestures are required. In those cases an open bracket followed by a lower case letter \(e.g. (w ) will be used instead. Finally there is a short list of spells in forward and reverse order, intended for use as a reference sheet for players during the battle. To see if a spell has been cast, look up in the reverse section the last gesture and follow back. Protection Spells Shield gesture P. This spell protects the subject from all attacks from monsters (that is, creatures created by a summonning spell), from missile spells, and from stabs by wizards. The shield will block any number of such attacks but lasts for only one round. The shield protects the subject on the turn in which it is cast. Remove enchantment gestures P-D-W-P. Terminates the effects of all *Enchantment Spells* that have been cast on the subject including those that are cast on the subject at the same time as the *remove enchantment*. Effects which have already passed are not reversed. For example, the victim of a *blindness* spell would not be able to see what their opponent's gestures were on the the *blindness* is removed. Note that all enchantments are removed and the caster may not pick and choose. *Remove enchantment* also destroys any monster upon which it is cast, although the monster can attack in that turn. Wizards suffer no adverse effects from this spell, aside from the removal of their enchantments. Magic Mirror gestures C-(w. Any spell cast on a subject protected by this spell is reflected back upon the caster of that spell. The *magic mirror* protects only during the turn in which it was cast. The protection includes spells like *missile* and *lightning bolt* but does not include attacks by monsters or stabs from wizards. The mirror does not affect spells which are cast upon oneself (e.g. spells from this section and the *Summonning* section). The mirror is countered totally if either a *counter-spell* or *dispel magic* are cast on the subject in the same turn as the mirror. The mirror has no effect on spells which affect more than one person (such as *fire storm*). Two mirrors cast at one subject simultaneously combine to form a single mirror. Counter-spell gestures W-P-P *or* W-W-S. Any other spell cast upon the subject in the same turn has no effect. In the case of blanket spells, which affect more than one person, the subject of the *counter-spell* alone is protected. For example, a *fire storm* spell could kill off a monster but not if a *counter-spell* were cast on the monster in the same turn. Everyone else would be affected as usual by the *fire storm* unless they had their own protection. The *counter-spell* will cancel all the spells cast at the subject for that turn (including *remove enchantment* and *magic mirror*) except *dispel magic* and *finger of death*. It will combine with another spell of its own type for the same effect as if it were alone. The *counter-spell* will also act as a *shield* on the final gesture in addition to its other properties, but the shield effect is on the same subject as its other effect. Dispel Magic gestures C-D-P-W. This spell acts as a combination of *counter-spell* and *remove enchantment*, but its effects are universal rather than limited to the subject of the spell. It will stop any spell cast in the same turn from working (apart from another dispel magic spell which combines with it for the same result), and will remove all enchantments from all beings before they have effect. In addition, all monsters are destroyed although they can attack that turn. *Counter-spells* and *magic mirrors* have no effect. The spell will not work on stabs or surrenders. As with a *counter-spell* it also acts as a *shield* for its subject. Raise Dead gestures D-W-W-F-W-C. The subject of this spell is usually a recently-dead (not yet decomposing) human corpse though it may be used on a dead monster. When the spell is cast, life returns to the corpse and all damage is cured. All enchantments are also removed (as per the spell) so any *diseases* or *poisons* will be neutralized and all other enchantments removed. If swords, knives, or other implements of destruction still remain in the corpse when it is raised, they will of course cause it damage as usual. The subject will be able to act normally immediately after the spell is cast. On the turn a monster is raised it may attack. Wizards may begin gesturing on the turn following their return from the dead. This is the only spell which affects corpses. It therefore cannot be stopped by a *counter-spell*. A *dispel magic* spell will prevent its effect, since *dispel magic* affects all spells no matter what their subject. If the spell is cast on a live individual, the effect is that of a *cure light wounds* recovering five points of damage, or as many as have been sustained if less than five. Note that any diseases the live subject might have are /not/ cured. Cure Light Wounds gestures D-F-W. If the subject has received damage then he is cured by one point as if that point had not been inflicted. Thus, for example, if a wizard was at ten points of damage and was hit simultaneously by a *cure light wounds* and a *lightning bolt* he would finish that turn on fourteen points rather than fifteen (or nine if there had been no *lightning bolt*). The effect is not removed by a *dispel magic* or *remove enchantment*. Cure Heavy Wounds gestures D-F-P-W. This spell is similar to *cure light wounds* in effect but two points of damage are cured. Note that only one point is cured if only one point of damage has been sustained and the spell has no effect if the subject is completely undamaged. This spell will also cure any diseases the subject might have at the time. Summonning Spells Summon Goblin gestures S-F-W. This spell creates a goblin under the control of the subject upon whom the spell is cast (or if cast on a monster, the subject monster's /controller/, even if the monster later dies or changes loyalty). The goblin can attack immediately and its victim can be any any wizard or other monster the controller desires, stating which at the time he writes his gestures. It does one point of damage to its victim per turn and is destroyed after one point of damage is inflicted upon it. The summoning spell cannot be cast at an elemental, and if cast at something which doesn't exist, the spell has no effect. Summon Ogre gestures P-S-F-W. This spell is the same as *summon goblin* but the ogre created inflicts and is destroyed by two points of damage rather than one. Summon Troll gestures F-P-S-F-W. This spell is the same as *summon goblin* but the troll created inflicts and is destroyed by three points of damage rather than one. Summon Giant gestures W-F-P-S-F-W. This spell is the same as *summon goblin* but the giant created inflicts and is destroyed by four points of damage rather than one. Summon Elemental gestures C-S-W-W-S. This spell creates either a fire elemental or an ice elemental at the discretion of the person upon whom the spell is cast after he has seen all the gestures made that turn. Elementals must be cast at someone and cannot be \"shot off\" harmlessly at some inanimate object. The elemental will, for that turn and until destroyed, attack everyone who is not resistant to its type (heat or cold), causing three points of damage per turn. The elemental takes three points of damage to be killed but may be destroyed by spells of the opposite type (e.g. *fire storm*, *resist cold* or *fireball* will kill an ice elemental), and will also neutralize the canceling spell. Elementals will not attack on the turn they are destroyed by such a spell. An elemental will also be engulfed and destroyed by a storm of its own type but, in such an event, the storm is not neutralized although the elemental still does not attack in that turn. Two elementals of the opposite type will also destroy each other before attacking, and two of the same type will join together to form a single elemental of normal strength. Note that only wizards or monsters resistant to the type of elemental, or who are casting a spell which has the effect of a *shield* do not get attacked by the elemental. Casting a *fireball* upon yourself when being attacked by an ice elemental is no defence! (Cast it at the elemental...) Damaging Spells Missile gestures S-D. This spell creates a material object of hard substance which is hurled towards the subject of the spell and causes him one point of damage. The spell is thwarted by a *shield* in addition to the usual *counter-spell*, *dispel magic* and *magic mirror* (the latter causing it to hit whoever cast it instead). Finger of Death gestures P-W-P-F-S-S-S-D. Kills the subject stone dead. This spell is so powerful that it is unaffected by a *counter-spell* although a *dispel magic* spell cast upon the final gesture will stop it. The usual way to prevent being harmed by this spell is to disrupt it during casting using, for example, an *anti-spell*. Lightning Bolt gestures D-F-F-D-D *or* W-D-D-C. The subject of this spell is hit by a bolt of lightning and sustains five points of damage. Resistance to heat or cold is irrelevant. There are two gesture combinations for the spell, but the shorter one may be used only once per day (i.e. per battle) by any wizard. The longer one may be used without restriction. A *shield* spell offers no defence. Cause Light Wounds gestures W-F-P. The subject of this spell is inflicted with two points of damage. Resistance to heat or cold offers no defence. A simultaneous *cure light wounds* will serve only to reduce the damage to 1 point. A *shield* has no effect. Cause Heavy Wounds gestures W-P-F-D. This has the same effect as *cause light wounds* but inflicts three points of damage instead of two. Fireball gestures F-S-S-D-D. The subject of this spell is hit by a ball of fire and sustains five points of damage unless he is resistant to fire. If at the same time an *ice storm* prevails, the subject of the *fireball* is instead not harmed by either spell, although the storm will affect others as normal. If directed at an ice elemental, the fireball will destroy it before it can attack, but has no other effect on the creatures. Fire Storm gestures S-W-W-C. Everything not resistant to heat sustains 5 points of damage that turn. The spell cancels wholly, causing no damage, with either an *ice storm* or an ice elemental. It will destroy but not be destroyed by a fire elemental. Two *fire storms* act as one. Ice Storm gestures W-S-S-C. Everything not resistant to cold sustains 5 points of damage that turn. The spell cancels wholly, causing no damage, with either a *fire storm* or a fire elemental, and will cancel locally with a *fireball*. It will destroy but not be destroyed by an ice elemental. Two *ice storms* act as one. Enchantment Spells Amnesia gestures D-P-P. If the subject of this spell is a wizard, next turn he must repeat identically the gestures he made in the current turn, including stabs. If the subject is a monster it will attack whoever it attacked this turn. If the subject is simultaneously the subject of any of *confusion*, *charm person*, *charm monster*, *paralysis* or *fear* then none of the spells work. Confusion gestures D-S-F. If the subject of this spell is a wizard, next turn he writes down his gestures as usual and after exposing them, rolls 2 dice to determine which gesture is superseded due to his being confused. The first die indicates left hand on 1-3, right on 4-6. The second roll determines what the gesture for that hand shall be replaced with: 1=C, 2=D, 3=F, 4=P, 5=S, 6=W. If the subject of the spell is a monster, it attacks at random that turn. If the subject is also the subject of any of: *amnesia*, *charm person*, *charm monster*, *paralysis* or *fear*, none of the spells work. Charm Person gestures P-S-D-F. Except for cancellation with other enchantments, this spell only affects humans. The subject is told which of his hands will be controlled at the time the spell hits, and in the following turn, the caster of the spell writes down the gesture he wants the subject's named hand to perform. This could be a stab or nothing. If the subject is only so because of a reflection from a *magic mirror* the subject of the mirror assumes the role of caster and writes down his opponent's gesture. If the subject is also the subject of any of *amnesia*, *confusion*, *charm monster*, *paralysis* or *fear*, none of the spells work. Charm Monster gestures P-S-D-D. Except for cancellation with other enchantments, this spell only affects monsters (excluding elementals). Control of the monster is transferred to the caster of the spell (or retained by him) as of this turn, i.e. the monster will attack whosoever its new controller dictates from that turn onwards including that turn. Further charms are, of course, possible, transferring as before. If the subject of the charm is also the subject of any of: *amnesia*, *confusion*, *charm person*, *fear* or *paralysis*, none of the spells work. Paralysis gestures F-F-F. If the subject of the spell is a wizard, then on the turn the spell is cast, after gestures have been revealed, the caster selects one of the wizard's hands and on the next turn that hand is paralyzed into the position it is in this turn. If the wizard already had a paralyzed hand, it must be the same hand which is paralyzed again. Certain gestures remain the same but if the hand being paralyzed is performing a C, S or W it is instead paralyzed into F, D or P respectively, otherwise it will remain in the position written down \(this allows repeated stabs). A favourite ploy is to continually paralyze a hand (F-F-F-F-F-F etc.) into a non-P gesture and then set a monster on the subject so that he has to use his other hand to protect himself, but then has no defence against other magical attacks. If the subject of the spell is a monster (excluding elementals which are unaffected) it simply does not attack in the turn following the one in which the spell was cast. If the subject of the spell is also the subject of any of *amnesia*, *confusion*, *charm person*, *charm monster* or *fear*, none of the spells work. Fear gestures S-W-D. In the turn following the casting of this spell, the subject cannot perform a C, D, F or S gesture. This obviously has no effect on monsters. If the subject is also the subject of *amnesia*, *confusion*, *charm person*, *charm monster* or *paralysis*, then none of the spells work. Anti-spell gestures S-P-F. On the turn following the casting of this spell, the subject cannot include any gestures made on or before this turn in a spell sequence and must restart a new spell from the beginning of that spell sequence. The spell does not affect spells which are cast on the same turn nor does it affect monsters. Protection from Evil gestures W-W-P. For this turn and the following 3 turns the subject of this spell is protected as if using a *shield* spell, thus leaving both hands free. Concurrent *shield* spells offer no further protection and compound *protection from evil* spells merely overlap offering no extra cover. Resist Heat gestures W-W-F-P. The subject of this spell becomes totally resistant to all forms of heat attack (*fireball*, *fire storm* and fire elementals). Only *dispel magic* or *remove enchantment* will terminate this resistance once started (although a *counter-spell* will prevent it from working if cast at the subject at the same time as this spell). A *resist heat* cast directly on a fire elemental will destroy it before it can attack that turn, but there is no effect on ice elementals. Resist Cold gestures S-S-F-P. The effects of this spell are identical to *resist heat* but resistance is to cold (*ice storm* and ice elementals) and it destroys ice elementals if they are the subject of the spell but doesn't affect fire elementals. Disease gestures D-S-F-F-F-C. The subject of this spell immediately contracts a deadly (non-contagious) disease which will kill him at the end of 6 turns counting from the one upon which the spell is cast. The malady is cured by *remove enchantment* or *cure heavy wounds* or *dispel magic* in the meantime. Poison gestures D-W-W-F-W-D. This is the same as the disease spell except that *cure heavy wounds* does not stop its effects. Blindness gestures D-W-F-F-(d. For the next 3 turns not including the one in which the spell was cast, the subject is unable to see. If he is a wizard, he cannot tell what his opponent's gestures are, although he must be informed of any which affect him (e.g. summons spells, *missile* etc cast at him) but not *counter- spells* to his own attacks. Indeed he will not know if his own spells work unless they also affect him (e.g. a *fire storm* when he isn't resistant to fire.) He can control his monsters (e.g. \"Attack whatever it was that just attacked me\"). Blinded monsters are instantly destroyed and cannot attack in that turn. Invisibility gestures P-P-(w-(s. This spell is similar to *blindness* only the subject of the spell becomes invisible to his opponent and his monsters. All spells he creates, though not gestures, can be seen by his opponent and identified. The subject cannot be attacked by any monsters although they can be directed at him in case he becomes visible prematurely. Wizards can still stab and direct spells at him, with the same hope. Any monster made invisible is destroyed due to the unstable nature of such magically created creatures. Haste gestures P-W-P-W-W-C. For the next 3 turns, the subject (but not his monsters if a wizard) makes an extra set of gestures due to being speeded up. This takes effect in the following turn so that instead of giving one pair of gestures, 2 are given, the effect of both being taken simultaneously at the end of the turn. Thus a single *counter-spell* from his adversary could cancel 2 spells cast by the hastened wizard on 2 half-turns if the phasing is right. Non-hastened wizards and monsters can see everything the hastened individual is doing. Hastened monsters can change target in the extra turns if desired. Time stop gestures S-P-P-C. The subject of this spell immediately takes an extra turn, on which no-one can see or know about unless they are harmed. All non-affected beings have no resistance to any form of attack, e.g. a wizard halfway through the duration of a *protection from evil* spell can be harmed by a monster which has had its time stopped. Time-stopped monsters attack whoever their controller instructs, and time-stopped elementals affect everyone, resistance to heat or cold being immaterial in that turn. Delayed effect gestures D-W-S-S-S-P. This spell only works if cast upon a wizard. The next spell he completes, provided it is on this turn or one of the next 3 is \"banked\" until needed, i.e. it fails to work until its caster desires. This next spell which is to be banked does not include the actual spell doing the banking. The spell must be written down to be used by its caster at the same time that he writes his gestures. Note that spells banked are those cast by the subject not those cast at him. If he casts more than one spell at the same time he chooses which is to be banked. Remember that P is a *shield* spell, and surrender is not a spell. A wizard may only have one spell banked at any one time. Permanency gestures S-P-F-P-S-D-W. This spell only works if cast upon a wizard. The next spell he completes, provided it is on this turn or one of the next 3, and which falls into the category of \"Enchantments\" (except *anti-spell*, *disease*, *poison*, or *time-stop*) will have its effect made permanent. This means that the effect of the extended spell on the first turn of its duration is repeated eternally. For example, a *confusion* spell will be the same gesture rather than re-rolling the dice, a *charm person* will mean repetition of the chosen gesture, etc. If the subject of the *permanency* casts more than one spell at the same time eligible for permanency, he chooses which has its duration extended. Note that the person who has his spell made permanent does not necessarily have to make himself the subject of the spell. A *permanency* spell cannot increase its own duration, nor the duration of spells saved by a *delayed effect* (so if both a *permanency* and *delayed effect* are eligible for the same spell to be banked or extended, a choice must be made, the losing spell being neutralized and working on the next spell instead). Non-spells Surrender gestures (p. This is not a spell and consequently cannot be cast at anyone. The wizard making these gestures, irrespective of whether they terminate spells or not, surrenders and the contest is over. The surrendering wizard is deemed to have lost unless his gestures completed spells which killed his opponent. Two simultaneous surrenders count as a draw. It is a skill for wizards to work their spells so that they never accidentally perform 2 P gestures simultaneously. Wizards can be killed as they surrender if hit with appropriate spells or attacked physically, but the \"referees\" will cure any diseases, poisons etc immediately after the surrender for them. Stab gesture stab. This is not a spell but an attack which can be directed at any individual monster or wizard. Unless protected in that turn by a *shield* spell or another spell with the same effect, the being stabbed suffers 1 point of damage. The wizard only has one knife so can only stab with one hand in any turn, although which hand doesn't matter. The stab cannot be reflected by a *magic mirror* or stopped by *dispel magic* (although its *shield* effect *could* stop the stab). Wizards are not allowed to stab themselves and must choose a target for the stab. Knives cannot be thrown. Example Game There follows a sample game with following comments. Significant spells are marked +. Null gestures are in brackets. Underlined gestures and above cannot be used further due to the effects of an *anti-spell*. Turn BLACK WHITE Left Right Damage Left Right Damage 1 W W + 0 W + P 0 2 W P + W + D 3 D F + F + + W 4 D + D + P + + W 3 5 F + P S + S + 6 F + P 1 W D + 7 S D W + + D 8 S W W + + S + 9 F F + S + + F + 10 P + (C) + D + + W ++ 11 Stab + P P ++ + D + 12 P + S P + D + 13 P + S 6 C C + 14 W + W S + + S 15 + S + + S W + + P 16 + D + D W + + F 5 --------------- 17 W + S + 11 C + C 18 D + P + + S + S 19 D + F + 13 + D + D --------------- 20 C + + C S + S 10 21 W + W P + W 22 P P F + W Annotation 1. Black starts with 2 W's hoping to use the left as a possible W-W-S *counter- spell* in the event of White opening with an attack, or as a possible W-W-F-P *resist heat* spell. His right hand also opens for a possible *counter-spell* or W-P-F-D *cause heavy wounds* if White has no possible attack; the second P will also cover against any S-D *missile attack*. White has the same ideas for his left hand as Black and opens with a P for his right hand in case Black tries a stab, leading to P-D-W-P *remove enchantment* hopefully. 2. Both complete their second gestures as intended and both notice that neither can use an offensive spell on the third turn so they can switch their left hands to W-W-F-P *resist fire*. Black notices that the only spell White could be preparing with his right hand is remove enchantment and hence his own *resist fire* would be canceled. Since he cannot adjust his right hand sequence to produce a *counter-spell* he resolves to use his latest W to start a W-D-D-C *lightning bolt*. 3. White had to continue his *remove enchantment* in case Black called his bluff but now knows it is pointless to continue as there will be nothing to cancel. Black is certain to hit White with an unstoppable *cause heavy wounds* next time but notices too late that, had he instead of gesturing a D with his left hand, gestured a W, he could have cast a W-W-S *counter-spell* at White and stopped his *resist heat* from working. However, he has a *lightning bolt* coming as compensation... 4. Black hits White with his *cause heavy wounds* and White becomes fire- resistant. White notes that had he gone ahead with his *remove enchantment* spell he would have been doing two P gestures this turn - surrendering! Instead he performs a W with his right hand to time a *counter-spell* after Black's last continuation. 5. Black aborts his *lightning bolt* spell, but White still follows through with his *counter-spell*, just in case. Black switches to the other combination for *lightning bolt*, D-F-F-D-D and sneaks in the start of an amnesia D-P-P. White commences a *summon ogre* P-S-F-W with his left hand, but upon seeing that next time he will be struck by *amnesia* realizes that he won't be able to continue it. Knowing the nature of the spell, he decides to switch next time to a spell starting off with 2 identical gestures, a W-W-S *counter-spell* for safety. 6. Black hits White with the predicted D-P-P amnesia spell, meaning that White must repeat his gestures next time with the same hands. White knows that he has a \"free\" S-D *missile* on Black since Black cannot do a P shield to defend himself or he would be performing the *surrender* gestures. 7. Since Black knows White's gestures, he can tell that White will be able to time a *counter-spell* to ward off the proposed *lightning bolt* D-F-F-D-D, so he changes to a *fireball* F-S-S-D-D. However, White is resistant to fire so a P-D-W-P *remove enchantment* is called for from the right hand. 8. White surprised Black by repeating his W gesture in the left hand so he can now time a counter spell for the next round and thus prevent the *remove enchantment* from affecting his fire invulnerability (although his resistance to fire will be unaffected by the *counter-spell* since he has already cast the spell on himself in round 4). With his right hand, White half-heartedly starts off a *confusion* spell to interrupt Black next time. 9. Black does 2 F gestures having to change in mid-spells after White's cunning gestures last round. He decides to go for a *blindness* spell D-W-F-F-(d with his right hand, and for *cold resistance* S-S-F-P with his left, to cut his losses. White casts the counter spell W-W-S on himself so that his *confusion* D-S-F will work on Black. 10. Black writes down P for his left hand and F for his right, and White writes D and W. Since Black was hit by a *confusion* last time one of his gestures will be affected. He rolls a C on the right hand and this supersedes the F he had written down. Since he didn't C with his other hand and C is a 2-handed gesture, it counts as a null. Note that if he had rolled for a P he would have surrendered. White finishes off a *summon goblin* spell S-F-W, and a *missile* S-D. Black's left hand finishes a *resist cold* S-S-F-P but he decides to use only the last gesture as a P *shield* so that neither of White's attacks harm him. Now he will wish to dispose of the goblin as soon as possible so he can stop performing P's to protect himself. 11. Black stabs the goblin and, since only 1 hit is required to kill it, eliminates it. He also gestures a P *shield* so that it cannot harm him in that turn. White gestures for an *amnesia* D-P-P and a *lightning bolt* W-D-D-C (the sort which can only be used once per wizard). He also performed a P *shield* but didn't notice and since it is in the \"protection\" section it was cast upon himself. If he had cast it at the goblin it wouldn't have been killed. Black realizes that he will have no defence against either of White's forthcoming attacks, so chooses to work 2 spells beginning with the same gesture next time so that the amnesia won't be too damaging. 12. Black must start off both gestures from scratch after the stab and half-C and opts for P-P-(w-(s *invisibility* and *resist cold* S-S-F-P. White's *amnesia* spell is completed so Black must repeat next time as expected. 13. Black repeats, and White does a C gesture with both hands to terminate a W-D-D-C *lightning bolt* giving 5 points of damage to Black. White cannot cast another *lightning bolt* using the same gestures now, even if he does W-D-D-C since this type is allowed only once per battle. However, he may use the alternate gestures if he desires. 14. Black aborts his right-hand spell since a W with both hands is needed for the *invisibility*. White does 2 S gestures, hoping for a C-S-W-W-S *summon elemental* and either an *anti-spell* S-F-F or *summon goblin* S-F-W. 15. Black goes invisible for the next 3 turns so White won't be able to see his gestures. White continues with his *summon elemental* but has the option to change to a *fire storm* sequence if he so desires. 16. Realizing that he is about to be hit by an *anti-spell* S-P-F from White, Black opens up with 2 *missiles* S-D and catches White off guard. Next time Black must gesture from scratch again. Although White does not see Black's gestures he knows he has been hit by 2 *missiles* so can work them out. 17. For the second time, Black starts up for a *lightning bolt* W-D-D-C, hoping this time to complete it, and a covering *anti-spell* S-P-F so that White will be unable to defend himself from it. Meanwhile White realizes he is resistant to fire and unleashes a *fire storm* giving 5 points of damage to all those not fire-resistant which just happens to be Black. 18. White does 2 S gestures again hoping to fool Black into thinking that he will repeat the sequence he used after the last C gesture, whereas he intends to hit out with 2 S-D *missiles* next turn (when Black becomes visible again). Black continues with his plan. 19. Black is surprised by the 2 *missiles* from White and is not performing a P *shield* which would protect him. White is hit by Black's *anti-spell* S-P-F but is unaware of the impending *lightning bolt* anyway... 20. Black hits White with his *lightning bolt* as White prepares 2 more *missiles* which would kill Black if they hit, but, noting Black's C he daren't risk the possibility of it being followed by a pair of W's for a C-(w *magic mirror* which would reflect them back at White. Hence White decides to go for another *anti-spell* and *fire storm*. 21. Black does perform the 2 W's planning to *cause heavy wounds* or defend with *counter-spell*. White continues as planned and Black becomes aware that he is about to be burned to death. 22. Resigning himself to defeat Black surrenders just as White's *anti-spell* hits him. The battle ends before White can make the final C gesture which would have disposed of his enemy. White wins the contest. Credits _Waving Hands_ (also known as _Spellcaster_) © Richard Bartle Taken from _Duel Purpose_ fanzine, written by Mike Lean Scanned, OCRed, and edited by Andrew Buchanan buchanan@heron.enet.dec.com March 3, 1993 Edited by Ken Tidwell, April 9, 1994 Follow up can be directed via snailmail to: Mike Lean 74 Friary Park, Ballabeg, ISLE OF MAN. (Near UK) Andrew's current understanding is that Richard Bartle is deceased. His \(and my) apologies and compliments to Richard should he reads this page. Richard Bartle has been in contact and reports that his wife finds him in good health. He can be contacted at richard@mud.co.uk <mailto:richard@mud.co.uk>. The Game Cabinet <../> - editor@gamecabinet.com <mailto:editor@gamecabinet.com> - Ken Tidwell <../biography/KenTidwell.html> ")
;;; Main code (defvar *spellcaster-server*) (defvar *users*) (defvar *chat*) (defvar *notes*) (defvar *hidden-count*) (defun login-user (user) (hunchentoot:start-session) (setf (hunchentoot:session-value 'user) user) (with-html-output-to-string (*standard-output* nil :prologue t :indent t) (:html (:head (:meta :http-equiv "Refresh" :content "0; URL=/cast")) (:body "Logging in... if nothing happens, click " (:a :href "/cast" "here."))))) (defun display-login (&key with-warning) (with-html-output-to-string (*standard-output* nil :prologue t :indent t) (:html (:head (:title "Spellcaster Server - Login")) (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8") (:body (:h1 "Spellcaster Login") (when with-warning (htm (:b "Invalid password."))) (:form :method "post" (:table (:tr (:td "User:") (:td (:select :name "user" (loop for (user pass) in *users* and i upfrom 0 do (htm (:option :value i (str user))))))) (:tr (:td "Password:") (:td (:input :type "password" :name "password")))) (:input :type "submit" :value "Login")))))) (defun get-user () (hunchentoot:session-value 'user)) (declaim (inline get-user)) (defun login-page () (when (get-user) (hunchentoot:remove-session hunchentoot:*session*)) (let ((user-str (hunchentoot:post-parameter "user")) (pass (hunchentoot:post-parameter "password"))) (if (and user-str pass) (let ((user (parse-integer user-str))) (cond ((null (second (elt *users* user))) (setf (second (elt *users* user)) pass) (login-user user)) ((string= (second (elt *users* user)) pass) (login-user user)) (t (display-login :with-warning t)))) (display-login)))) (defun access-denied () (with-html-output-to-string (*standard-output* nil :prologue t :indent t) (:html (:head (:title "Spellcaster Server")) (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8") (:body (:h1 "Access denied") (:p "Please log in " (:a :href "/" "here.")))))) (defun format-time (time) (multiple-value-bind (second minute hour date month year day daylight-p zone) (decode-universal-time time) (declare (ignore second year day daylight-p zone)) (format nil "[~@r.~d/~2,'0d:~2,'0d]" month date hour minute))) (defun display-chat () (with-html-output (*standard-output* nil :indent t) (loop for message in *chat* do (htm (:span :class "time" (str (format-time (first message)))) " " (:span :class (if (= (second message) 0) "player1" "player2") (fmt "~a: " (first (elt *users* (second message))))) (loop for (contents type) in (third message) do (case type (normal (str contents)) (shown (htm (:span :class "shown" (str contents)))) (t (if (= (second message) (get-user)) (htm (:span :class "hidden" (str contents))) (htm (:form :class "hide-form" :method "post" (:input :type "submit" :name type :value "Show"))))))) (:br))))) (defun display-main-page (&optional time) (with-html-output-to-string (*standard-output* nil :prologue t :indent t) (:html (:head (:title "Spellcaster Server")) (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8") (:style :type "text/css" (str *css*)) (:body (:h1 "Spellcaster") (:form :method "post" (:input :type "text" :name "message" :size 80 :autocomplete "off") (:input :type "submit" :value "Send")) (:div :class "chat" (display-chat)) (:hr) (:form :method "post" (:textarea :name "notes" :rows 10 :cols 70 (str (elt *notes* (get-user)))) (:br) (:input :type "submit" :value "Save notes / Refresh") (when time (fmt " Saved ~a" (format-time time)))) (:hr) (:pre (str *spells*)) (:hr) (:pre (str *rules*)))))) (defun parse-message (message) (let ((start (position #\{ message))) (if start (let ((end (position #\} message :start start))) (if end (cons (list (subseq message 0 start) 'normal) (cons (list (subseq message (1+ start) end) (format nil "hidden~d" (incf *hidden-count*))) (parse-message (subseq message (1+ end))))) (list (list message 'normal)))) (list (list message 'normal))))) (defun create-message (message) (list (get-universal-time) (get-user) (parse-message message))) (defun look-for-hidden-parameter () (iter (for (key . value) in (hunchentoot:post-parameters*)) (when (cl-ppcre:scan "^hidden[0-9]+$" key) (leave key)))) (defun show-hidden-message (key) (iter (for message in *chat*) (iter (for part in (third message)) (when (and (stringp (second part)) (string= (second part) key)) (setf (second part) 'shown) (return-from show-hidden-message))))) (defun cast-page () (let ((message (hunchentoot:post-parameter "message")) (notes (hunchentoot:post-parameter "notes")) (hidden (look-for-hidden-parameter))) (cond ((null (get-user)) (access-denied)) (notes (setf (elt *notes* (get-user)) notes) (display-main-page (get-universal-time))) (message (push (create-message message) *chat*) (display-main-page)) (hidden (show-hidden-message hidden) (display-main-page)) (t (display-main-page)))))
;;; Server setup (defun generate-notes () (labels ((spaces (k) (iter (repeat k) (collect #\Space))) (center-string (str n) (let ((k (length str))) (format nil "~{~a~}~a~{~a~}" (spaces (ceiling (- n k) 2)) str (spaces (floor (- n k) 2)))))) (format nil " ~a ~a Comments Health: IIIIIIIIIIIIIII IIIIIIIIIIIIIII --------------------------------------------------------------------- Round 01 ~a ~a~%" (center-string (first (first *users*)) 15) (center-string (first (second *users*)) 15) (center-string "? ?" 15) (center-string "? ?" 15)))) (defun start (&key (port *default-port*) users) (setf *spellcaster-server* (make-instance 'hunchentoot:easy-acceptor :port port) *users* (or (and users (mapcar (lambda (u) (list u ())) users)) (copy-tree *default-users*)) *chat* () *notes* (list (generate-notes) (generate-notes)) *hidden-count* 0) (setf hunchentoot:*dispatch-table* (list (hunchentoot:create-regex-dispatcher "^/$" #'login-page) (hunchentoot:create-regex-dispatcher "^/cast$" #'cast-page))) (hunchentoot:start *spellcaster-server*)) (defun stop () (let ((hunchentoot:*acceptor* *spellcaster-server*)) (hunchentoot:reset-sessions)) (hunchentoot:stop *spellcaster-server*))