(when (< (random n) 1)
(setf it (car things))))))
-(defmacro pick (&rest clauses)
+(defmacro pick (&body clauses)
`(funcall (choose ,@(loop for (n . clause) in clauses
collect n
collect `(lambda () ,@clause)))))
-(defconstant druid-spells
- #((detect-danger faerie-fire locate predict-weather)
- (heat-metal obscure produce-fire warp-wood)
- (call-lightning hold-animal protection-from-poison water-breathing)
- (control-temperature-10-ft-radius plant-door protection-from-lightning
- summon-animals)
- (anti-plant-shell control-winds dissolve pass-plant)
- (anti-animal-shell summon-weather transport-through-plants turn-wood)
- (creeping-doom metal-to-wood summon-elemental weather-control)))
+(defmacro pick-matching ((form &key) &body clauses)
+ (let ((formtemp (gensym "FORM")))
+ `(let ((,formtemp ,form))
+ (pick ,@(loop for (prob assertion . code) in clauses
+ collect `((if (assertion-match-p ,formtemp ',assertion)
+ ,prob
+ 0)
+ ,@code))))))
(defconstant cleric-spells
#((cure-light-wounds detect-evil detect-magic light protection-from-evil
(earthquake holy-word raise-dead-fully restore survival travel wish
wizardry)))
+(defconstant druid-only-spells
+ #((detect-danger faerie-fire locate predict-weather)
+ (heat-metal obscure produce-fire warp-wood)
+ (call-lightning hold-animal protection-from-poison water-breathing)
+ (control-temperature-10-ft-radius plant-door protection-from-lightning
+ summon-animals)
+ (anti-plant-shell control-winds dissolve pass-plant)
+ (anti-animal-shell summon-weather transport-through-plants turn-wood)
+ (creeping-doom metal-to-wood summon-elemental weather-control)))
+
+(defconstant druid-spells
+ (make-array 7 :initial-contents (loop for cs across cleric-spells
+ for ds across druid-only-spells
+ collect (append cs ds))))
+
(defconstant magic-user-spells
#((analyse charm-person detect-magic floating-disc hold-portal light
magic-missile protection-from-evil read-languages read-magic shield
(contingency create-any-monster gate heal immunity maze meteor-swarm
power-word-kill prismatic-wall shapechange survival timestop wish)))
-(defun spell-caster-type ()
- (choose 25 :cleric 5 :druid 70 :magic-user))
+(defun spell-caster-type (&optional (form :any))
+ (pick-matching (form)
+ (5 (:user (:cleric :druid :paladin)) :cleric)
+ (1 (:user :druid) :druid)
+ (14 (:user (:magic-user :elf :thief)) :magic-user)))
(defun random-spell (&optional (caster (spell-caster-type))
(level (ecase caster
(let ((list (aref (ecase caster
((:magic-user) magic-user-spells)
((:cleric) cleric-spells)
- ((:druid) druid-spells))
+ ((:druid) druid-only-spells))
level)))
(values (elt list (random (length list)))
caster
level)))
-(defun symbol-match-p (form sym)
- (cond ((eq form t) t)
- ((eq form nil) nil)
- ((eq form sym) t)
- ((atom form) nil)
- (t (ecase (car form)
- ((and) (every (lambda (f) (symbol-match-p f sym)) (cdr form)))
- ((or) (some (lambda (f) (symbol-match-p f sym)) (cdr form)))
- ((not) (not (symbol-match-p (cadr form) sym)))))))
+(let ((magic (list :magic)))
+ (defun assertion-match-p (form assertions)
+ (cond ((eq form :any) t)
+ ((eq form :none) nil)
+ ((atom form) (if (atom assertions)
+ (eql form assertions)
+ (member form assertions)))
+ (t (case (car form)
+ ((and) (every (lambda (f)
+ (assertion-match-p f assertions))
+ (cdr form)))
+ ((or) (some (lambda (f)
+ (assertion-match-p f assertions))
+ (cdr form)))
+ ((not) (not (assertion-match-p (cadr form) assertions)))
+ (t (let ((sub (getf assertions (car form) magic)))
+ (if (eq sub magic)
+ t
+ (assertion-match-p (cadr form) sub)))))))))
(defun choose-distinct-items (n seq)
(let* ((copy (subseq (coerce seq 'vector) 0))
(setf (aref copy j) (aref copy len))))))
(defun magic-item (form)
- (labels ((potion (&key recursivep)
- (pick (2 `(:potion agility))
- (1 `(:potion animal-control))
- (3 `(:potion antidote))
- (2 `(:potion blending))
- (2 `(:potion bug-repellent))
- (2 `(:potion clairaudience))
- (2 `(:potion clairvoyance))
- (2 `(:potion climbing))
- (2 `(:potion defence :bonus ,(choose 3 1
- 2 2
- 2 3
- 2 4
- 1 5)))
- ((if recursivep 0 4)
- `(:potion delusion
- :fakes ,@(cdr (potion :recursivep t))))
- (2 `(:potion diminution))
- (1 `(:potion ,(choose 35 'white-dragon-control
- 15 'crystal-dragon-control
- 35 'black-dragon-control
- 15 'onyx-dragon-control
- 28 'green-dragon-control
- 12 'jade-dragon-control
- 21 'blue-dragon-control
- 9 'sapphire-dragon-control
- 14 'red-dragon-control
- 6 'ruby-dragon-control
- 7 'gold-dragon-control
- 3 'amber-dragon-control)))
- (2 `(:potion dreamspeech))
- (1 `(:potion elasicity))
- (2 `(:potion ,(choose-uniformly 'air-form
- 'water-form
- 'earth-form
- 'fire-form)))
- (2 `(:potion esp))
- (1 `(:potion ethereality))
- (3 `(:potion fire-resistance))
- (3 `(:potion flying))
- (2 `(:potion fortitude))
- (1 `(:potion freedom))
- (3 `(:potion gaseous-form))
- (1 `(:potion ,(choose 5 'hill-giant-control
- 5 'stone-giant-control
- 4 'frost-giant-control
- 2 'fire-giant-control
- 1 'mountain-giant-control
- 1 'sea-giant-control
- 1 'cloud-giant-control
- 1 'storm-giant-control)))
- (3 `(:potion giant-strength))
- (2 `(:potion growth))
- (6 `(:potion healing))
- (3 `(:potion heroism))
- (1 `(:potion human-control))
- (3 `(:potion invisibility))
- (2 `(:potion invulnerability))
- (2 `(:potion levitation))
- (2 `(:potion longevity))
- (1 `(:potion luck))
- (1 `(:potion merging))
- (2 `(:potion plant-control))
- (3 `(:potion poison))
- (3 `(:potion polymorph-self))
- (2 `(:potion sight))
- (2 `(:potion speech))
- (4 `(:potion speed))
- (2 `(:potion strength))
- (3 `(:potion super-healing))
- (3 `(:potion swimming))
- (1 `(:potion treasure-finding))
- (1 `(:potion undead-control))
- (2 `(:potion water-breathing))))
+ (labels ((cursedp (&optional (prob 10))
+ (cond ((assertion-match-p form '(:cursed :unspecified))
+ (zerop (random prob)))
+ ((assertion-match-p form '(:cursed nil))
+ nil)
+ (t t)))
+ (potion (&key recursivep)
+ (pick-matching (form)
+ (2 (:cursed nil) `(:potion agility))
+ (1 (:cursed nil) `(:potion animal-control))
+ (3 (:cursed nil) `(:potion antidote))
+ (2 (:cursed nil) `(:potion blending))
+ (2 (:cursed nil) `(:potion bug-repellent))
+ (2 (:cursed nil) `(:potion clairaudience))
+ (2 (:cursed nil) `(:potion clairvoyance))
+ (2 (:cursed nil) `(:potion climbing))
+ (2 (:cursed nil) `(:potion defence :bonus ,(choose 3 1
+ 2 2
+ 2 3
+ 2 4
+ 1 5)))
+ ((if recursivep 0 4) (:cursed t)
+ (setf form :any)
+ `(:potion delusion
+ :fakes ,@(cdr (potion :recursivep t))))
+ (2 (:cursed nil) `(:potion diminution))
+ (1 (:cursed nil) `(:potion ,(choose 35 'white-dragon-control
+ 15 'crystal-dragon-control
+ 35 'black-dragon-control
+ 15 'onyx-dragon-control
+ 28 'green-dragon-control
+ 12 'jade-dragon-control
+ 21 'blue-dragon-control
+ 9 'sapphire-dragon-control
+ 14 'red-dragon-control
+ 6 'ruby-dragon-control
+ 7 'gold-dragon-control
+ 3 'amber-dragon-control)))
+ (2 (:cursed nil) `(:potion dreamspeech))
+ (1 (:cursed nil) `(:potion elasicity))
+ (2 (:cursed nil) `(:potion ,(choose-uniformly 'air-form
+ 'water-form
+ 'earth-form
+ 'fire-form)))
+ (2 (:cursed nil) `(:potion esp))
+ (1 (:cursed nil) `(:potion ethereality))
+ (3 (:cursed nil) `(:potion fire-resistance))
+ (3 (:cursed nil) `(:potion flying))
+ (2 (:cursed nil) `(:potion fortitude))
+ (1 (:cursed nil) `(:potion freedom))
+ (3 (:cursed nil) `(:potion gaseous-form))
+ (1 (:cursed nil) `(:potion ,(choose 5 'hill-giant-control
+ 5 'stone-giant-control
+ 4 'frost-giant-control
+ 2 'fire-giant-control
+ 1 'mountain-giant-control
+ 1 'sea-giant-control
+ 1 'cloud-giant-control
+ 1 'storm-giant-control)))
+ (3 (:cursed nil) `(:potion giant-strength))
+ (2 (:cursed nil) `(:potion growth))
+ (6 (:cursed nil) `(:potion healing))
+ (3 (:cursed nil) `(:potion heroism))
+ (1 (:cursed nil) `(:potion human-control))
+ (3 (:cursed nil) `(:potion invisibility))
+ (2 (:cursed nil) `(:potion invulnerability))
+ (2 (:cursed nil) `(:potion levitation))
+ (2 (:cursed nil) `(:potion longevity))
+ (1 (:cursed nil) `(:potion luck))
+ (1 (:cursed nil) `(:potion merging))
+ (2 (:cursed nil) `(:potion plant-control))
+ (3 (:cursed t) `(:potion poison))
+ (3 (:cursed nil) `(:potion polymorph-self))
+ (2 (:cursed nil) `(:potion sight))
+ (2 (:cursed nil) `(:potion speech))
+ (4 (:cursed nil) `(:potion speed))
+ (2 (:cursed nil) `(:potion strength))
+ (3 (:cursed nil) `(:potion super-healing))
+ (3 (:cursed nil) `(:potion swimming))
+ (1 (:cursed nil) `(:potion treasure-finding))
+ (1 (:cursed nil) `(:potion undead-control))
+ (2 (:cursed nil) `(:potion water-breathing))))
(scroll ()
- (pick (3 `(:scroll communication))
- (2 `(:scroll creation))
- (8 `(:scroll curse))
- (1 (multiple-value-bind
- (spell caster level)
- (random-spell)
- (declare (ignore level))
- `(:scroll delay :caster ,caster :spells (,spell))))
- (3 `(:scroll equipment
- :items ,(choose-distinct-items 6
- '(grappling-hook
- hammer
- iron-spikes
- lantern
- mirror
- wooden-pole
- rope
- saddle
- backpack
- saddle-bags
- stakes-and-mallet
- wolfsbane))))
- (2 `(:scroll illumination))
- (2 `(:scroll mages))
- (4 `(:map normal-treasure))
- (3 `(:map magical-treasure))
- (2 `(:map combined-treasure))
- (1 `(:map special-treasure))
- (3 `(:scroll mapping))
- (2 `(:scroll portals))
- (6 `(:scroll protection-from-elementals))
- (8 `(:scroll protection-from-lycanthropes))
- (4 `(:scroll protection-from-magic))
- (7 `(:scroll protection-from-undead))
- (2 `(:scroll questioning))
- (1 (multiple-value-bind
- (spell caster level)
- (random-spell)
- `(:scroll repetition
- :caster ,caster
- :level ,level
- :spells (,spell))))
- (2 `(:scroll seeing))
- (2 `(:scroll shelter))
- (3 `(:scroll spell-catching :max-level ,(choose 4 1
- 3 2
- 2 3
- 1 8)))
- (25 (let ((caster (spell-caster-type))
- (spells (choose 50 1 33 2 17 3)))
- `(:scroll spell
- :caster ,caster
- :spells ,(loop repeat spells
- collect (random-spell caster)))))
- (2 `(:scroll trapping))
- (2 `(:scroll truth))))
+ (pick-matching (form)
+ (3 (:cursed nil) `(:scroll communication))
+ (2 (:cursed nil) `(:scroll creation))
+ (8 (:cursed t) `(:scroll curse))
+ (1 (:user (:cleric :druid :magic-user :elf :thief :paladin)
+ :cursed nil)
+ (multiple-value-bind
+ (spell caster level)
+ (random-spell (spell-caster-type form))
+ (declare (ignore level))
+ `(:scroll delay :caster ,caster :spells (,spell))))
+ (3 (:cursed nil)
+ `(:scroll equipment
+ :items ,(choose-distinct-items 6
+ '(grappling-hook
+ hammer
+ iron-spikes
+ lantern
+ mirror
+ wooden-pole
+ rope
+ saddle
+ backpack
+ saddle-bags
+ stakes-and-mallet
+ wolfsbane))))
+ (2 (:cursed nil) `(:scroll illumination))
+ (2 (:cursed nil :user (:magic-user :cleric :druid :elf))
+ `(:scroll mages))
+ (4 (:cursed nil) `(:map normal-treasure))
+ (3 (:cursed nil) `(:map magical-treasure))
+ (2 (:cursed nil) `(:map combined-treasure))
+ (1 (:cursed nil) `(:map special-treasure))
+ (3 (:cursed nil) `(:scroll mapping))
+ (2 (:cursed nil) `(:scroll portals))
+ (6 (:cursed nil) `(:scroll protection-from-elementals))
+ (8 (:cursed nil) `(:scroll protection-from-lycanthropes))
+ (4 (:cursed nil) `(:scroll protection-from-magic))
+ (7 (:cursed nil) `(:scroll protection-from-undead))
+ (2 (:cursed nil) `(:scroll questioning))
+ (1 (:cursed nil
+ :user (:cleric :druid :magic-user :elf :thief :paladin))
+ (multiple-value-bind
+ (spell caster level)
+ (random-spell (spell-caster-type form))
+ `(:scroll repetition
+ :caster ,caster
+ :level ,level
+ :spells (,spell))))
+ (2 (:cursed nil) `(:scroll seeing))
+ (2 (:cursed nil) `(:scroll shelter))
+ (3 (:cursed nil)
+ `(:scroll spell-catching :max-level ,(choose 4 1
+ 3 2
+ 2 3
+ 1 8)))
+ (25 (:cursed nil
+ :user (:cleric :druid :magic-user :elf :thief :paladin))
+ (let ((caster (spell-caster-type form))
+ (spells (choose 50 1 33 2 17 3)))
+ `(:scroll spell
+ :caster ,caster
+ :spells ,(loop repeat spells
+ collect (random-spell caster)))))
+ (2 (:cursed nil) `(:scroll trapping))
+ (2 (:cursed nil) `(:scroll truth))))
(wand-charges () (d 10 3))
(staff-charges () (d 20 2))
(wandlike ()
- (pick (5 `(:wand cold :charges ,(wand-charges)))
- (5 `(:wand enemy-detection :charges ,(wand-charges)))
- (4 `(:wand fear :charges ,(wand-charges)))
- (5 `(:wand fireballs :charges ,(wand-charges)))
- (4 `(:wand illusion :charges ,(wand-charges)))
- (5 `(:wand lightning-bolts :charges ,(wand-charges)))
- (5 `(:wand magic-detection :charges ,(wand-charges)))
- (5 `(:wand metal-detection :charges ,(wand-charges)))
- (4 `(:wand negation :charges ,(wand-charges)))
- (5 `(:wand paralysation :charges ,(wand-charges)))
- (5 `(:wand polymorphing :charges ,(wand-charges)))
- (4 `(:wand secret-door-detection
- :charges ,(wand-charges)))
- (4 `(:wand trap-detection :charges ,(wand-charges)))
- (1 `(:staff commanding :charges nil))
- (2 `(:staff dispelling :charges ,(staff-charges)))
- (3 `(:staff druids :charges ,(staff-charges)))
- (3 `(:staff ,(choose 19 'air
- 19 'earth
- 19 'fire
- 19 'water
- 6 'air-and-water
- 6 'earth-and-fire
- 2 'elemental-power)
- :charges ,(staff-charges)))
- (2 `(:staff harming :charges ,(staff-charges)))
- (7 `(:staff healing :charges ,(staff-charges)))
- (1 `(:staff power :charges ,(staff-charges)))
- (3 `(:staff snake :charges ,(staff-charges)))
- (3 `(:staff striking :charges ,(staff-charges)))
- (2 `(:staff withering :charges ,(staff-charges)))
- (1 `(:staff wizardry :charges ,(staff-charges)))
- (2 `(:rod cancellation))
- (1 `(:rod dominion))
- (1 `(:rod health))
- (2 `(:rod inertia))
- (1 `(:rod parrying))
- (1 `(:rod victory))
- (3 `(:rod weaponry))
- (1 `(:rod wyrm :colour ,(choose 5 'gold
- 3 'blue
- 2 'black)))))
- (ring ()
- (pick (2 `(:ring animal-control))
- (6 `(:ring delusion))
- (1 `(:ring djinni-summoning))
- (4 `(:ring ear))
- (4 `(:ring ,(choose 19 'air-adaptation
- 19 'earth-adaptation
- 19 'fire-adaptation
- 19 'water-adaptation
- 6 'air-and-water-adaptation
- 6 'earth-and-fire-adaptation
- 2 'elemental-adaptation)))
- (6 `(:ring fire-resistance))
- (3 `(:ring holiness))
- (1 `(:ring human-control))
- (5 `(:ring invisibility))
- (3 `(:ring life-protection :charges ,(d 6)))
- (3 `(:ring memory))
- (2 `(:ring plant-control))
- (1 `(:ring protection :bonus 1 :radius 5))
- (10 `(:ring protection :bonus ,(choose 4 1
- 3 2
- 2 3
- 1 4)))
- (4 `(:ring quickness))
- (1 `(:ring regeneration))
- (3 `(:ring remedies))
- (2 `(:ring safety :charges ,(d 4)))
- (3 `(:ring seeing))
- (3 `(:ring spell-eating))
- (2 (let* ((caster (spell-caster-type))
- (spells (loop repeat (d 6)
- collect (random-spell caster))))
- `(:ring spell-storing
- :caster ,caster
- :spells ,(remove-duplicates (sort spells
- #'string<)))))
- (2 `(:ring spell-turning))
- (4 `(:ring survival :charges ,(+ 100 (d 100))))
- (2 `(:ring telekinesis))
- (4 `(:ring truth))
- (3 `(:ring truthfulness))
- (2 `(:ring truthlessness))
- (5 `(:ring water-walking))
- (5 `(:ring weakness))
- (2 `(:ring wishes :charges ,(choose 4 1
- 3 2
- 2 3
- 1 4)))
- (2 `(:ring x-ray-vision))))
+ (pick-matching (form)
+ (5 (:user (:magic-user :elf))
+ `(:wand cold :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand enemy-detection :charges ,(wand-charges)))
+ (4 (:user (:magic-user :elf))
+ `(:wand fear :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand fireballs :charges ,(wand-charges)))
+ (4 (:user (:magic-user :elf))
+ `(:wand illusion :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand lightning-bolts :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand magic-detection :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand metal-detection :charges ,(wand-charges)))
+ (4 (:user (:magic-user :elf))
+ `(:wand negation :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand paralysation :charges ,(wand-charges)))
+ (5 (:user (:magic-user :elf))
+ `(:wand polymorphing :charges ,(wand-charges)))
+ (4 (:user (:magic-user :elf))
+ `(:wand secret-door-detection :charges ,(wand-charges)))
+ (4 (:user (:magic-user :elf))
+ `(:wand trap-detection :charges ,(wand-charges)))
+ (1 (:user (:magic-user :elf :cleric :druid :palatin))
+ `(:staff commanding :charges nil))
+ (2 nil
+ `(:staff dispelling :charges ,(staff-charges)))
+ (3 (:user :druid)
+ `(:staff druids :charges ,(staff-charges)))
+ (3 (:user (:magic-user :elf))
+ `(:staff ,(choose 19 'air
+ 19 'earth
+ 19 'fire
+ 19 'water
+ 6 'air-and-water
+ 6 'earth-and-fire
+ 2 'elemental-power)
+ :charges ,(staff-charges)))
+ (2 (:user (:cleric :druid :paladin))
+ `(:staff harming :charges ,(staff-charges)))
+ (7 (:user (:cleric :druid :paladin))
+ `(:staff healing :charges ,(staff-charges)))
+ (1 (:user (:cleric :druid :magic-user :elf :paladin))
+ `(:staff power :charges ,(staff-charges)))
+ (3 (:user (:cleric :druid :paladin))
+ `(:staff snake :charges ,(staff-charges)))
+ (3 (:user (:cleric :druid :magic-user :elf :paladin))
+ `(:staff striking :charges ,(staff-charges)))
+ (2 (:user (:cleric :druid :paladin))
+ `(:staff withering :charges ,(staff-charges)))
+ (1 (:user (:magic-user :elf))
+ `(:staff wizardry :charges ,(staff-charges)))
+ (2 nil `(:rod cancellation))
+ (1 nil `(:rod dominion))
+ (1 (:user (:cleric :druid :paladin)) `(:rod health))
+ (2 (:user (:dwarf :halfling :elf :fighter
+ :paladin :thief :mystic))
+ `(:rod inertia))
+ (1 nil `(:rod parrying))
+ (1 nil `(:rod victory))
+ (3 (:user (:dwarf :halfling :elf :fighter
+ :paladin :thief :mystic))
+ `(:rod weaponry))
+ (1 nil
+ `(:rod wyrm :colour ,(choose 5 'gold
+ 3 'blue
+ 2 'black)))))
+ (ring (&optional (recursivep nil))
+ (pick-matching (form)
+ (2 (:cursed nil) `(:ring animal-control))
+ ((if recursivep 0 6)
+ (:cursed t)
+ (setf form :any)
+ `(:ring delusion :fakes ,@(cdr (ring t))))
+ (1 (:cursed nil) `(:ring djinni-summoning))
+ (4 (:cursed nil) `(:ring ear))
+ (4 (:cursed nil) `(:ring ,(choose 19 'air-adaptation
+ 19 'earth-adaptation
+ 19 'fire-adaptation
+ 19 'water-adaptation
+ 6 'air-and-water-adaptation
+ 6 'earth-and-fire-adaptation
+ 2 'elemental-adaptation)))
+ (6 (:cursed nil) `(:ring fire-resistance))
+ (3 (:cursed nil :user (:cleric :druid :paladin))
+ `(:ring holiness))
+ (1 (:cursed nil) `(:ring human-control))
+ (5 (:cursed nil) `(:ring invisibility))
+ (3 (:cursed nil) `(:ring life-protection :charges ,(d 6)))
+ (3 (:cursed nil
+ :user (:cleric :druid :magic-user :elf :paladin))
+ `(:ring memory))
+ (2 (:cursed nil) `(:ring plant-control))
+ (1 (:cursed nil) `(:ring protection :bonus 1 :radius 5))
+ (10 (:cursed nil) `(:ring protection :bonus ,(choose 4 1
+ 3 2
+ 2 3
+ 1 4)))
+ (4 (:cursed nil) `(:ring quickness))
+ (1 (:cursed nil) `(:ring regeneration))
+ (3 (:cursed nil) `(:ring remedies))
+ (2 (:cursed nil) `(:ring safety :charges ,(d 4)))
+ (3 (:cursed nil) `(:ring seeing))
+ (3 (:cursed t) `(:ring spell-eating))
+ (2 (:cursed nil)
+ (let* ((caster (spell-caster-type))
+ (spells (loop repeat (d 6)
+ collect (random-spell caster))))
+ `(:ring spell-storing
+ :caster ,caster
+ :spells ,(remove-duplicates (sort spells
+ #'string<)))))
+ (2 (:cursed nil) `(:ring spell-turning))
+ (4 (:cursed nil) `(:ring survival :charges ,(+ 100 (d 100))))
+ (2 (:cursed nil) `(:ring telekinesis))
+ (4 (:cursed nil) `(:ring truth))
+ (3 (:cursed t) `(:ring truthfulness))
+ (2 (:cursed t) `(:ring truthlessness))
+ (5 (:cursed nil) `(:ring water-walking))
+ (5 (:cursed t) `(:ring weakness))
+ (2 (:cursed nil) `(:ring wishes :charges ,(choose 4 1
+ 3 2
+ 2 3
+ 1 4)))
+ (2 (:cursed nil) `(:ring x-ray-vision))))
(misc-item ()
- (pick (2 `(:amulet protection-from-crystal-balls-and-esp))
- (2 `(:bag devouring))
- (5 `(:bag holding))
- (3 `(:boat undersea))
- (2 `(:boots levitation))
- (3 `(:boots speed))
- (2 `(:boots travelling-and-leaping))
- (1 `(:bowl commanding-water-elementals))
- (1 `(:brazier commanding-fire-elementals))
- (2 `(:broom flying))
- (1 `(:censer controlling-air-elementals))
- (3 `(:chime time))
- (2 `(:crystal-ball normal))
- (1 `(:crystal-ball clairaudience))
- (1 `(:crystal-ball esp))
- (2 `(:cloak displacer))
- (1 `(:drums panic))
- (1 `(:bottle efreeti))
- (3 `(:egg ,(choose-uniformly 'rock-baboon
- 'giant-bat
- 'black-bear
- 'grizzly-bear
- 'boar
- 'mountain-lion
- 'panther
- 'giant-ferret
- 'gecko
- 'draco
- 'racer-snake
- 'wolf)))
- (2 `(:boots elven))
- (2 `(:cloak elven))
- (1 `(:carpet flying))
- (2 `(:gauntlets ogre-power))
- (2 `(:girdle giant-strength))
- (2 `(:helm ,(choose-uniformly 'lawful-alignment
- 'neutral-alignment
- 'chaotic-alignment)))
- (2 `(:helm reading))
- (1 `(:helm telepathy))
- (1 `(:helm teleportation))
- (1 `(:horn blasting))
- (2 `(:lamp hurricane))
- (3 `(:lamp long-burning))
- (2 `(:medallion esp-30-ft-range))
- (1 `(:medallion esp-90-ft-range))
- (1 `(:mirror life-trapping)) ;;; fixme include contents
- (3 `(:muzzle training))
- (2 `(:nail finger))
- (3 `(:nail pointing))
- (5 `(:ointment ,(choose-uniformly 'blessing
- 'healing
- 'poison
- 'scarring
- 'soothing
- 'tanning)))
- (3 `(:pouch security))
- (3 `(:quill copying))
- (4 `(:rope climbing))
- (2 `(:scarab protection :charges ,(d 6 2)))
- (3 `(:slate identification))
- (1 `(:stone controlling-earth-elementals))
- (2 `(:talisman ,(choose-uniformly 'air-travel
- 'earth-travel
- 'fire-travel
- 'water-travel
- 'elemental-travel)))
- (3 `(:wheel floating))
- (1 `(:wheel fortune))
- (2 `(:wheel square))))
+ (pick-matching (form)
+ (2 (:cursed nil)
+ `(:amulet protection-from-crystal-balls-and-esp))
+ (2 (:cursed t) `(:bag devouring))
+ (5 (:cursed nil) `(:bag holding))
+ (3 (:cursed nil) `(:boat undersea))
+ (2 (:cursed nil) `(:boots levitation))
+ (3 (:cursed nil) `(:boots speed))
+ (2 (:cursed nil) `(:boots travelling-and-leaping))
+ (1 (:cursed nil) `(:bowl commanding-water-elementals))
+ (1 (:cursed nil) `(:brazier commanding-fire-elementals))
+ (2 (:cursed nil) `(:broom flying))
+ (1 (:cursed nil) `(:censer controlling-air-elementals))
+ (3 (:cursed nil) `(:chime time))
+ (2 (:cursed nil :user (:magic-user :elf))
+ `(:crystal-ball normal))
+ (1 (:cursed nil :user (:magic-user :elf))
+ `(:crystal-ball clairaudience))
+ (1 (:cursed nil :user (:magic-user :elf))
+ `(:crystal-ball esp))
+ (2 (:cursed nil) `(:cloak displacer))
+ (1 (:cursed nil) `(:drums panic))
+ (1 (:cursed nil) `(:bottle efreeti))
+ (3 (:cursed nil) `(:egg ,(choose-uniformly 'rock-baboon
+ 'giant-bat
+ 'black-bear
+ 'grizzly-bear
+ 'boar
+ 'mountain-lion
+ 'panther
+ 'giant-ferret
+ 'gecko
+ 'draco
+ 'racer-snake
+ 'wolf)))
+ (2 (:cursed nil) `(:boots elven))
+ (2 (:cursed nil) `(:cloak elven))
+ (1 (:cursed nil) `(:carpet flying))
+ (2 (:cursed nil) `(:gauntlets ogre-power))
+ (2 (:cursed nil) `(:girdle giant-strength))
+ (2 (:cursed t)
+ `(:helm ,(choose-uniformly 'lawful-alignment
+ 'neutral-alignment
+ 'chaotic-alignment)))
+ (2 (:cursed nil) `(:helm reading))
+ (1 (:cursed nil) `(:helm telepathy))
+ (1 (:cursed nil) `(:helm teleportation))
+ (1 (:cursed nil) `(:horn blasting))
+ (2 (:cursed t) `(:lamp hurricane))
+ (3 (:cursed nil) `(:lamp long-burning))
+ (2 (:cursed nil) `(:medallion esp-30-ft-range))
+ (1 (:cursed nil) `(:medallion esp-90-ft-range))
+ (1 (:cursed nil) `(:mirror life-trapping))
+ ; fixme include contents
+ (3 (:cursed nil) `(:muzzle training))
+ (2 (:cursed nil) `(:nail finger))
+ (3 (:cursed nil) `(:nail pointing))
+ (5 nil `(:ointment ,(pick-matching (form)
+ (1 (:cursed nil) 'blessing)
+ (1 (:cursed nil) 'healing)
+ (1 (:cursed t) 'poison)
+ (1 (:cursed t) 'scarring)
+ (1 (:cursed nil) 'soothing)
+ (1 (:cursed t) 'tanning))))
+ (3 (:cursed nil) `(:pouch security))
+ (3 (:cursed nil :user (:cleric :druid :magic-user :elf))
+ `(:quill copying))
+ (4 (:cursed nil) `(:rope climbing))
+ (2 (:cursed nil) `(:scarab protection :charges ,(d 6 2)))
+ (3 (:cursed nil :user (:cleric :druid :magic-user :elf))
+ `(:slate identification))
+ (1 (:cursed nil) `(:stone controlling-earth-elementals))
+ (2 (:cursed nil)
+ `(:talisman ,(choose-uniformly 'air-travel
+ 'earth-travel
+ 'fire-travel
+ 'water-travel
+ 'elemental-travel)))
+ (3 (:cursed nil) `(:wheel floating))
+ (1 (:cursed nil) `(:wheel fortune))
+ (2 (:cursed nil) `(:wheel square))))
(weapon-bonus (class)
(loop for bonus from 1
for roll = (random 100) then (- roll item)
((d) '(70 18 8 3 1)))
when (< roll item) return bonus))
(armour-size ()
- (choose 68 'human
- 13 'dwarf
- 10 'elf
- 7 'halfling
- 2 'giant))
+ (pick-matching (form)
+ (68 (:user (:cleric :fighter :paladin :druid :thief)) 'human)
+ (13 (:user :dwarf) 'dwarf)
+ (10 (:user :elf) 'elf)
+ (7 (:user :halfling) 'halfling)
+ (2 (:user nil) 'giant)))
(armour-piece (class)
(let* ((bonus (weapon-bonus class))
(power (and (percentp (* 5 (1+ bonus)))
(7 `(remove-curse :charges ,(d 3))))))
(cursedp (if (and power (eq (car power) 'remove-curse))
nil
- (zerop (random 8)))))
+ (cursedp 8))))
`(:bonus ,bonus
,@(and power (cons :power power))
:size ,(armour-size)
,@(and cursedp `(:cursed t)))))
(armour ()
- (pick (10 `((:leather ,@(armour-piece 'd))))
- ( 7 `((:scale-mail ,@(armour-piece 'd))))
- (13 `((:chain-mail ,@(armour-piece 'c))))
- ( 9 `((:banded-mail ,@(armour-piece 'd))))
- (11 `((:plate-mail ,@(armour-piece 'b))))
- ( 5 `((:suit-armour ,@(armour-piece 'b))))
- (20 `((:shield ,@(armour-piece 'a))))
- ( 2 `((:scale-mail ,@(armour-piece 'd))
- (:shield ,@(armour-piece 'a))))
- ( 8 `((:chain-mail ,@(armour-piece 'c))
- (:shield ,@(armour-piece 'a))))
- ( 5 `((:banded-mail ,@(armour-piece 'd))
- (:shield ,@(armour-piece 'a))))
- (10 `((:plate-mail ,@(armour-piece 'b))
- (:shield ,@(armour-piece 'a))))))
+ (pick-matching (form)
+ (10 (:user (:cleric :fighter :paladin :druid :thief
+ :dwarf :elf :halfling))
+ `((:armour leather ,@(armour-piece 'd))))
+ ( 7 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour scale-mail ,@(armour-piece 'd))))
+ (13 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour chain-mail ,@(armour-piece 'c))))
+ ( 9 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour banded-mail ,@(armour-piece 'd))))
+ (11 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour plate-mail ,@(armour-piece 'b))))
+ ( 5 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour suit ,@(armour-piece 'b))))
+ (20 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:shield ,@(armour-piece 'a))))
+ ( 2 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour scale-mail ,@(armour-piece 'd))
+ (:shield ,@(armour-piece 'a))))
+ ( 8 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour chain-mail ,@(armour-piece 'c))
+ (:shield ,@(armour-piece 'a))))
+ ( 5 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour banded-mail ,@(armour-piece 'd))
+ (:shield ,@(armour-piece 'a))))
+ (10 (:user (:cleric :fighter :paladin :dwarf :elf :halfling))
+ `((:armour plate-mail ,@(armour-piece 'b))
+ (:shield ,@(armour-piece 'a))))))
(opponent ()
(choose 6 'bugs
3 'constructs
(missile ()
(multiple-value-bind
(item class)
- (pick (37 (values :arrow 'a))
- (22 (values :quarrel 'a))
- (11 (values :sling-stone 'a))
- (2 (values :blowgun 'd))
- (8 (values :long-bow 'd))
- (5 (values :short-bow 'd))
- (2 (values :heavy-crossbow 'd))
- (5 (values :light-crossbow 'd))
- (8 (values :sling 'd)))
+ (pick-matching (form)
+ (37 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :arrow 'a))
+ (22 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :quarrel 'a))
+ (11 (:user (:cleric :druid :thief :fighter :paladin
+ :mystic :dwarf :elf :halfling))
+ (values :sling-stone 'a))
+ (2 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :blowgun 'd))
+ (8 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :long-bow 'd))
+ (5 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :short-bow 'd))
+ (2 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :heavy-crossbow 'd))
+ (5 (:user (:thief :fighter :paladin :mystic
+ :dwarf :elf :halfling))
+ (values :light-crossbow 'd))
+ (8 (:user (:cleric :druid :thief :fighter :paladin
+ :mystic :dwarf :elf :halfling))
+ (values :sling 'd)))
(ecase class
((a) (let* ((bonus (weapon-bonus 'a))
(cursedp (zerop (random 10)))
(talent (and (percentp (* 5 (- 7 bonus)))
- (choose 4 'biting
- 5 'blinking
- 5 'charming
- 7 'climbing
- 10 'curing
- 3 'disarming
- 4 'dispelling
- 7 'flying
- 7 'lightning
- 5 'penetrating
- 4 'refilling
- 6 'screaming
- 5 'seeking
- 4 'sinking
- 2 'slaying
- 7 'speaking
- 4 'stunning
- 2 'teleporting
- 5 'transporting
- 4 'wounding)))
+ (pick (4 'biting)
+ (5 'blinking)
+ (5 'charming)
+ (7 'climbing)
+ (10 'curing)
+ (3 'disarming)
+ (4 'dispelling)
+ (7 'flying)
+ (7 'lightning)
+ (5 'penetrating)
+ (4 'refilling)
+ (6 'screaming)
+ (5 'seeking)
+ (4 'sinking)
+ (2 `(slaying
+ :opponent ,(opponent)))
+ (7 'speaking)
+ (4 'stunning)
+ (2 'teleporting)
+ (5 'transporting)
+ (4 'wounding))))
(number (ecase bonus
((1) (d 10 2))
((2) (d 8 2))
:number ,number
,@(and cursedp `(:cursed t)))))
((d) (let* ((bonus (weapon-bonus 'd))
- (cursedp (zerop (random 10)))
+ (cursedp (cursedp 10))
(modifier (weapon-modifier bonus :missilep t))
(range (ecase (+ bonus (d 4))
((2 3 4) nil)
(sword ()
(multiple-value-bind
(type class)
- (pick (65 (values :normal-sword 'c))
- (19 (values :short-sword 'c))
- (8 (values :two-handed-sword 'd))
- (8 (values :bastard-sword 'd)))
+ (pick-matching (form)
+ (65 nil (values :normal-sword 'c))
+ (19 nil (values :short-sword 'c))
+ (8 (:user (:fighter :paladin :dwarf :mystic :elf))
+ (values :two-handed-sword 'd))
+ (8 (:user (:fighter :paladin :dwarf
+ :mystic :elf :halfling))
+ (values :bastard-sword 'd)))
(let* ((bonus (weapon-bonus class))
(cursedp (zerop (random 10)))
(modifier (sword-modifier bonus))
,@(and cursedp `(:cursed t))))))
(weapon ()
(multiple-value-bind
- (type returnsp class)
- (pick (7 (values :battle-axe nil 'd))
- (8 (values :hand-axe (choose 3 nil 1 t) 'b))
- (3 (values :blackjack nil 'c))
- (3 (values :bola (choose 2 nil 1 t) 'b))
- (5 (values :club nil 'c))
- (14 (values :dagger (choose 11 nil 3 t) 'b))
- (4 (values :one-handed-flail nil 'c))
- (2 (values :two-handed-flail nil 'd))
- (3 (values :halberd nil 'd))
- (8 (values :war-hammer nil 'c))
- (4 (values :javelin (choose 3 nil 1 t) 'b))
- (4 (values :lance nil 'd))
- (7 (values :mace nil 'c))
- (5 (values :morning-star nil 'c))
- (3 (values :net (choose 2 nil 1 t) 'b))
- (3 (values :pike nil 'd))
- (2 (values :pole-axe nil 'd))
- (12 (values :spear (choose 3 nil 1 t) 'b))
- (3 (values :whip nil 'c)))
+ (type returnsp intelpc class)
+ (pick-matching (form)
+ (7 (:user (:fighter :paladin :mystic :dwarf :elf))
+ (values :battle-axe nil 30 'd))
+ (8 (:user (:fighter :paladin :mystic :dwarf :thief
+ :elf :halfling))
+ (values :hand-axe (choose 3 nil 1 t) nil 'b))
+ (3 (:user (:fighter :paladin :mystic :dwarf :cleric
+ :elf :halfling))
+ (values :blackjack nil nil 'c))
+ (3 (:user (:fighter :paladin :mystic :dwarf :cleric
+ :thief :elf :halfling))
+ (values :bola (choose 2 nil 1 t) nil 'b))
+ (5 (:user (:fighter :paladin :mystic :dwarf
+ :thief :cleric :druid :elf :halfling))
+ (values :club nil nil 'c))
+ (14 (:user (:fighter :paladin :mystic :dwarf :magic-user
+ :thief :elf :halfling))
+ (values :dagger (choose 11 nil 3 t) 50 'b))
+ (4 (:user (:fighter :paladin :mystic :dwarf :cleric
+ :elf :halfling :thief))
+ (values :one-handed-flail nil nil 'c))
+ (2 (:user (:fighter :paladin :mystic :dwarf :cleric :elf))
+ (values :two-handed-flail nil nil 'd))
+ (3 (:user (:fighter :paladin :mystic :dwarf :elf))
+ (values :halberd nil 20 'd))
+ (8 (:user (:fighter :paladin :mystic :dwarf :cleric
+ :druid :elf :halfling :thief))
+ (values :war-hammer nil 30 'c))
+ (4 (:user (:fighter :paladin :mystic :dwarf :thief
+ :elf :halfling))
+ (values :javelin (choose 3 nil 1 t) nil 'b))
+ (4 (:user (:fighter :paladin :mystic :dwarf :elf))
+ (values :lance nil nil 'd))
+ (7 (:user (:fighter :paladin :mystic :dwarf :cleric :thief
+ :elf :halfling :druid))
+ (values :mace nil 35 'c))
+ (5 (:user (:fighter :paladin :mystic :dwarf :cleric :thief
+ :elf :halfling))
+ (values :morning-star nil nil 'c))
+ (3 (:user (:fighter :paladin :mystic :dwarf :cleric :thief
+ :druid :elf :halfling))
+ (values :net (choose 2 nil 1 t) nil 'b))
+ (3 (:user (:fighter :paladin :mystic :dwarf :elf))
+ (values :pike nil 20 'd))
+ (2 (:user (:fighter :paladin :mystic :dwarf :elf))
+ (values :pole-axe nil 20 'd))
+ (12 (:user (:fighter :paladin :mystic :dwarf :thief
+ :elf :halfling))
+ (values :spear (choose 3 nil 1 t) nil 'b))
+ (4 (:user (:fighter :paladin :mystic :dwarf :thief :cleric
+ :druid :elf :halfling :magic-user))
+ (values :staff nil 20 'd))
+ (3 (:user (:fighter :paladin :mystic :dwarf :thief :cleric
+ :druid :elf :halfling))
+ (values :whip nil nil 'c)))
(let* ((bonus (weapon-bonus class))
- (cursedp (zerop (random 10)))
+ (cursedp (cursedp 10))
(modifier (sword-modifier bonus))
- (intel (and (percentp 40)
+ (intel (and intelpc
+ (percentp intelpc)
(weapon-intelligence))))
`(,type
,@(and returnsp `(:returning t))
,@modifier
,@intel
,@(and cursedp `(:cursed t)))))))
- (pick ((if (symbol-match-p form :potion) 25 0) (list (potion)))
- ((if (symbol-match-p form :scroll) 12 0) (list (scroll)))
- ((if (symbol-match-p form :wandlike) 9 0) (list (wandlike)))
- ((if (symbol-match-p form :ring) 6 0) (list (ring)))
- ((if (symbol-match-p form :misc) 10 0) (list (misc-item)))
- ((if (symbol-match-p form :armour) 10 0) (armour))
- ((if (symbol-match-p form :missile) 11 0) (list (missile)))
- ((if (symbol-match-p form :sword) 9 0) (list (sword)))
- ((if (symbol-match-p form :weapon) 8 0) (list (weapon))))))
+ (pick-matching (form)
+ (25 (:type :potion) (list (potion)))
+ (12 (:type :scroll) (list (scroll)))
+ (9 (:type :wandlike :cursed nil) (list (wandlike)))
+ (6 (:type :ring) (list (ring)))
+ (10 (:type :misc) (list (misc-item)))
+ (10 (:type :armour
+ :user (:cleric :druid :fighter :paladin
+ :thief :dwarf :elf :halfling))
+ (armour))
+ (11 (:type :missile) (list (missile)))
+ (9 (:type :sword
+ :user (:fighter :paladin :mystic :thief :dwarf :elf :halfling))
+ (list (sword)))
+ (8 (:type :weapon) (list (weapon))))))
(defun treasure-type (type-code)
(labels ((common-fur-type ()
'mink
'sable))
(special (n)
- (tagged-bag
+ (cons
:special
(loop repeat n
collect
(intern (format nil "STAR-~A"
(string kind))))))))
(gems (n)
- (tagged-bag
+ (cons
:gems
(loop while (plusp n)
for i = (min n (d 5))
(2 (values 'good 4))
(1 (values 'very-good 8)))
(setf mod-list
- (append `(:size ,mod) mod-list))
+ (append `(:quality ,mod) mod-list))
(setf value (* value mult))))
`(:kind ,kind
:value ,(max 1 (round value))
,@mod-list
,@(and (> i 1) `(:quantity ,i))))))))
(jewellery (n)
- (tagged-bag
+ (cons
:jewellery
(loop while (plusp n)
for i = (min n (d 5))
:encumbrance ,enc
,@(and (> i 1) `(:quantity ,i))))))))
(magic (&rest forms)
- (tagged-bag :magic
- (loop with list = nil
- for (form n) on forms by #'cddr do
- (loop repeat n do
- (dolist (item (magic-item form))
- (push item list)))
- finally (return list)))))
+ (cons :magic
+ (loop with list = nil
+ for (form n) on forms by #'cddr do
+ (loop repeat n do
+ (dolist (item (magic-item (list :type form)))
+ (push item list)))
+ finally (return list)))))
(ecase type-code
;; treasure in lair
(and (percentp 50) (gems (d 6 6)))
(and (percentp 50) (jewellery (d 6 6)))
(and (percentp 10) (special (d 2)))
- (and (percentp 30) (magic t 3))))
+ (and (percentp 30) (magic :any 3))))
((b) (bag (tagged-bag :coins
(and (percentp 50) `(:cp ,(* 1000 (d 8))))
(and (percentp 25) `(:sp ,(* 1000 (d 6))))
(and (percentp 50) (gems (d 6 6)))
(and (percentp 50) (jewellery (d 6 6)))
(and (percentp 5) (special (d 2)))
- (and (percentp 10) (magic t 2))))
+ (and (percentp 10) (magic :any 2))))
((d) (bag (tagged-bag :coins
(and (percentp 10) `(:cp ,(* 1000 (d 8))))
(and (percentp 15) `(:sp ,(* 1000 (d 12))))
(and (percentp 30) (gems (d 8)))
(and (percentp 30) (jewellery (d 8)))
(and (percentp 10) (special (d 2)))
- (and (percentp 10) (magic t 1 :potion 1))))
+ (and (percentp 10) (magic :any 1 :potion 1))))
((e) (bag (tagged-bag :coins
(and (percentp 5) `(:cp ,(* 1000 (d 10))))
(and (percentp 30) `(:sp ,(* 1000 (d 12))))
(and (percentp 10) (gems (d 10)))
(and (percentp 10) (jewellery (d 10)))
(and (percentp 15) (special (d 2)))
- (and (percentp 25) (magic t 3 :scroll 1))))
+ (and (percentp 25) (magic :any 3 :scroll 1))))
((f) (bag (tagged-bag :coins
(and (percentp 30) `(:sp ,(* 1000 (d 10 2))))
(and (percentp 20) `(:ep ,(* 1000 (d 8))))
(and (percentp 25) (gems (d 6 3)))
(and (percentp 25) (jewellery (d 10)))
(and (percentp 30) (special (d 3)))
- (and (percentp 35) (magic t 4 :scroll 1))))
+ (and (percentp 35) (magic :any 4 :scroll 1))))
((h) (bag (tagged-bag :coins
(and (percentp 25) `(:cp ,(* 1000 (d 8 3))))
(and (percentp 50) `(:sp ,(* 1000 (d 100))))
(and (percentp 50) (gems (d 100)))
(and (percentp 50) (jewellery (* 10 (d 4))))
(and (percentp 10) (special (d 2)))
- (and (percentp 15) (magic t 4 :potion 1 :scroll 1))))
+ (and (percentp 15) (magic :any 4 :potion 1 :scroll 1))))
((i) (bag (tagged-bag :coins
(and (percentp 30) `(:pp ,(* 1000 (d 8)))))
(and (percentp 50) (gems (d 6 2)))
(and (percentp 50) (jewellery (d 6 2)))
(and (percentp 5) (special (d 2)))
- (and (percentp 15) (magic t 1))))
+ (and (percentp 15) (magic :any 1))))
((j) (bag (tagged-bag :coins
(and (percentp 25) `(:cp ,(* 1000 (d 4))))
(and (percentp 10) `(:sp ,(* 1000 (d 3)))))))
(and (percentp 5) (gems (d 2)))
(and (percentp 5) (gems (d 4)))
(and (percentp 2) (special 1))
- (and (percentp 2) (magic t 1))))
+ (and (percentp 2) (magic :any 1))))
((v) (bag (tagged-bag :coins
(and (percentp 10) `(:sp ,(d 100)))
(and (percentp 5) `(:ep ,(d 100)))
(and (percentp 10) (gems (d 2)))
(and (percentp 10) (gems (d 4)))
(and (percentp 5) (special 1))
- (and (percentp 5) (magic t 1))))
+ (and (percentp 5) (magic :any 1))))
;; unguarded treasures
((unguarded-1)
(and (percentp 50) `(:gp ,(* 10 (d 6)))))
(and (percentp 5) (gems (d 6)))
(and (percentp 2) (jewellery (d 6)))
- (and (percentp 2) (magic t 1))))
+ (and (percentp 2) (magic :any 1))))
((unguarded-2 unguarded-3)
(bag (tagged-bag :coins
`(:sp ,(* 100 (d 12)))
(and (percentp 50) `(:gp ,(* 100 (d 6)))))
(and (percentp 10) (gems (d 6)))
(and (percentp 5) (jewellery (d 6)))
- (and (percentp 8) (magic t 1))))
+ (and (percentp 8) (magic :any 1))))
((unguarded-4 unguarded-5)
(bag (tagged-bag :coins
`(:sp ,(* 1000 (d 6)))
`(:gp ,(* 200 (d 6))))
(and (percentp 20) (gems (d 8)))
(and (percentp 10) (jewellery (d 8)))
- (and (percentp 10) (magic t 1))))
+ (and (percentp 10) (magic :any 1))))
((unguarded-6 unguarded-7)
(bag (tagged-bag :coins
`(:sp ,(* 2000 (d 6)))
`(:gp ,(* 500 (d 6))))
(and (percentp 30) (gems (d 10)))
(and (percentp 15) (jewellery (d 10)))
- (and (percentp 15) (magic t 1))))
+ (and (percentp 15) (magic :any 1))))
((unguarded-8 unguarded-9)
(bag (tagged-bag :coins
`(:sp ,(* 5000 (d 6)))
`(:gp ,(* 1000 (d 6))))
(and (percentp 40) (gems (d 12)))
(and (percentp 20) (jewellery (d 12)))
- (and (percentp 20) (magic t 1)))))))
+ (and (percentp 20) (magic :any 1)))))))
+
+(defconstant combine-treasures
+ '((:coins (t . +))
+ (t . append)))
+
+(defun combine2 (spec a b)
+ (labels ((comb (tag x y)
+ (dolist (pair spec)
+ (let ((label (car pair)))
+ (when (or (eq label t)
+ (eq label tag))
+ (return-from comb
+ (let ((method (cdr pair)))
+ (etypecase method
+ (list (combine2 method x y))
+ ((member +) (list (+ (car x) (car y))))
+ ((or symbol function)
+ (funcall method x y))))))))
+ (error "No combiner found for ~S." tag)))
+ (let ((list nil))
+ (dolist (pair a)
+ (let* ((tag (car pair))
+ (match (assoc tag b)))
+ (push (if (null match)
+ pair
+ (cons tag
+ (comb tag (cdr pair) (cdr match))))
+ list)))
+ (dolist (pair b)
+ (let* ((tag (car pair))
+ (match (assoc tag a)))
+ (unless match
+ (push pair list))))
+ (nreverse list))))
+
+(defun combine (spec &rest lists)
+ (reduce (lambda (x y) (combine2 spec x y)) lists))
+
+(defun treasure (types)
+ (apply #'combine
+ combine-treasures
+ (loop for type in types
+ collect (treasure-type type))))
+
+(defun select-spells (table spells)
+ (loop for n in spells
+ for list across table
+ collect (sort (loop repeat n collect (apply #'choose-uniformly list))
+ #'string<)))
\def\nil{\multicolumn{2}{c}{---}}
\def\lnil{\multicolumn{2}{l}{---}}
-\makeatletter
-\def\subsect#1{\goodbreak\medskip\textbf{#1}\par\nobreak\@nobreaktrue}
-
\renewenvironment{description}{%
\basedescript{%
\let\makelabel\textit%
\desclabelstyle{\pushlabel}%
\desclabelwidth{2em}%
\parsep\z@%
- \itemsep\medskipamount%
+ \itemsep\smallskipamount%
}%
}{%
\endbasedescript%
97--98 & Wishes \\ \hlx{+}
99--00 & X-ray vision \\ \hlx*{vh}
\end{tabular}
+\line
+\begin{tabular}{\shade cl} \hlx*{hv}
+ \tt{Elements (for staff/ring)} \\
+ \th{d\%} & \th{Element} \\ \hlx{vhv}
+ 01--21 & Air \\ \hlx{+}
+ 22--42 & Earth \\ \hlx{+}
+ 43--63 & Fire \\ \hlx{+}
+ 64--84 & Water \\ \hlx{+}
+ 85--91 & Air and Water \\ \hlx{+}
+ 92--98 & Earth and Fire \\ \hlx{+}
+ 99--00 & All elements \\ \hlx*{vh}
+\end{tabular}
+
\end{set}
\begin{set}
76--00 & 86--00 & Talent \\ \hlx*{vh}
\end{tabular}
\colgap
-\begin{tabular}{\shade cl} \hlx*{hv}
- \tt{Opponents} \\
- \th{d\%} & \th{Type} \\ \hlx{vhv}
- 00--06 & Bugs \\ \hlx{+}
- 05--09 & Constructs \\ \hlx{+}
- 10--15 & Dragonkind \\ \hlx{+}
- 16--24 & Enchanted monsters \\ \hlx{+}
- 25--36 & Giantkind \\ \hlx{+}
- 37--48 & Lycanthropes \\ \hlx{+}
- 49--52 & Planar monsters \\ \hlx{+}
- 53--58 & Regenerating monsters \\ \hlx{+}
- 59--67 & Reptiles, dinosaurs \\ \hlx{+}
- 68--70 & Spell-immune monsters \\ \hlx{+}
- 71--76 & Spellcasters \\ \hlx{+}
- 77--88 & Undead \\ \hlx{+}
- 89--94 & Water-breathing monsters \\ \hlx{+}
- 95--00 & Weapon-using monsters \\ \hlx*{vh}
-\end{tabular}
-\colgap
\begin{tabular}{\shade cl} \hlx*{hv}
\tt{Missile talents} \\
- \th{d\%} & \th{Talent} \\ \hlx{vhv}
- 01--04 & Biting \\ \hlx{+}
- 05--09 & Blinking \\ \hlx{+}
- 10--14 & Charming \\ \hlx{+}
- 15--21 & Climbing \\ \hlx{+}
- 22--31 & Curing \\ \hlx{+}
- 32--34 & Disarming \\ \hlx{+}
- 35--38 & Dispelling \\ \hlx{+}
- 39--45 & Flying \\ \hlx{+}
- 46--52 & Lightning \\ \hlx{+}
- 53--57 & Penetrating \\ \hlx{+}
- 58--61 & Refilling \\ \hlx{+}
- 62--67 & Screaming \\ \hlx{+}
- 68--72 & Seeking \\ \hlx{+}
- 73--76 & Sinking \\ \hlx{+}
- 77--78 & Slaying \\ \hlx{+}
- 79--85 & Speaking \\ \hlx{+}
- 86--89 & Stunning \\ \hlx{+}
- 90--91 & Teleporting \\ \hlx{+}
- 92--96 & Transporting \\ \hlx{+}
- 97--00 & Wounding \\ \hlx*{vh}
+ \th{d\%} & \th{Talent} \\ \hlx{vhv}
+ 01--04 & Biting \\ \hlx{+}
+ 05--09 & Blinking \\ \hlx{+}
+ 10--14 & Charming \\ \hlx{+}
+ 15--21 & Climbing \\ \hlx{+}
+ 22--31 & Curing \\ \hlx{+}
+ 32--34 & Disarming \\ \hlx{+}
+ 35--38 & Dispelling \\ \hlx{+}
+ 39--45 & Flying \\ \hlx{+}
+ 46--52 & Lightning \\ \hlx{+}
+ 53--57 & Penetrating \\ \hlx{+}
+ 58--61 & Refilling \\ \hlx{+}
+ 62--67 & Screaming \\ \hlx{+}
+ 68--72 & Seeking \\ \hlx{+}
+ 73--76 & Sinking \\ \hlx{+}
+ 77--78 & Slaying \emph{opp.} \\ \hlx{+}
+ 79--85 & Speaking \\ \hlx{+}
+ 86--89 & Stunning \\ \hlx{+}
+ 90--91 & Teleporting \\ \hlx{+}
+ 92--96 & Transporting \\ \hlx{+}
+ 97--00 & Wounding \\ \hlx*{vh}
\end{tabular}
\quad
\begin{tabular}{\shade cl} \hlx*{hv}
95--99 & Watching \\ \hlx{+}
00 & Wishing \\ \hlx*{vh}
\end{tabular}
+\colgap
+\begin{tabular}{\shade cl} \hlx*{hv}
+ \tt{Opponents} \\
+ \th{d\%} & \th{Type} \\ \hlx{vhv}
+ 00--06 & Bugs \\ \hlx{+}
+ 05--09 & Constructs \\ \hlx{+}
+ 10--15 & Dragonkind \\ \hlx{+}
+ 16--24 & Enchanted monsters \\ \hlx{+}
+ 25--36 & Giantkind \\ \hlx{+}
+ 37--48 & Lycanthropes \\ \hlx{+}
+ 49--52 & Planar monsters \\ \hlx{+}
+ 53--58 & Regenerating monsters \\ \hlx{+}
+ 59--67 & Reptiles, dinosaurs \\ \hlx{+}
+ 68--70 & Spell-immune monsters \\ \hlx{+}
+ 71--76 & Spellcasters \\ \hlx{+}
+ 77--88 & Undead \\ \hlx{+}
+ 89--94 & Water-breathing monsters \\ \hlx{+}
+ 95--00 & Weapon-using monsters \\ \hlx*{vh}
+\end{tabular}
\quad
\end{set}
01--10 & Clairaudience \\ \hlx{+}
11--20 & Clairvoyance \\ \hlx{+}
21--30 & ESP \\ \hlx{+}
- 31--35 & Extra damage ($\times\,5$ or more)\s d
+ 31--35 & Extra damage ($\times\,4$ or more)\s d
\\ \hlx{+}
36--40 & Flying \\ \hlx{+}
41--45 & Healing (6\,hp)\s d \\ \hlx{+}
\end{tabular}
\end{set}
-\sect{Magical items}
-
-\begin{multicols}{2}
+\begin{multicols}{2}[\sect{Magical items}]
\raggedright
\subsect{Potions}
-\begin{itemize*}
-\item \textbf{Level:} Treat as 6th level.
-\item \textbf{Duration:} Usually $\d{1d6} + 6$ turns.
-\item \textbf{Control:} User must concentrate to control victims: cannot
- fight, half movement; victim allowed SvS, but attempt may be repeated each
- round. Range is $60'$.
-\end{itemize*}
+Treat as 6th level magic. Duration usually $\d{1d6} + 6$ turns.
+
+\textbf{Control potions:} User must concentrate to control victims: cannot
+fight, half movement; victim allowed SvS, but attempt may be repeated each
+round. Range is $60'$.
\begin{description}
\subsect{Wands}
-\begin{itemize*}
-\item \textbf{Charges:} Usually 2d10.
-\item \textbf{Level:} Treat as 6th level.
-\end{itemize*}
+Usually 2d10 charges. Treat as 6th level magic.
\begin{description}
\subsect{Staves}
-\begin{itemize*}
-\item \textbf{Charges:} Usually 3d10.
-\item \textbf{Level:} Treat as 8th level.
-\end{itemize*}
+Usually 3d10 charges. Treat as 8th level magic.
\begin{description}
Usable as $+2$ weapon.
- \begin{tabular}[C]{\shade cl} \hlx*{hv}
- \th{d\%} & \th{Element} \\ \hlx{vhv}
- 01--21 & Air \\ \hlx{+}
- 22--42 & Earth \\ \hlx{+}
- 43--63 & Fire \\ \hlx{+}
- 64--84 & Water \\ \hlx{+}
- 85--91 & Air and Water \\ \hlx{+}
- 92--98 & Earth and Fire \\ \hlx{+}
- 99--00 & Elemental power \\ \hlx*{vh}
- \end{tabular}
-
\item[Harming] Does $\d{1d6} + 1$ extra damage (uses charge). Also
\emph{cause blindness} (2), \emph{cause disease} (2), \emph{cause serious
wounds} (3), \emph{create poison} (4).
\item[Power] As \emph{staff of striking}; also \emph{fire ball},
\emph{lightning bolt}, \emph{ice storm}, \emph{continual light}, or
- \emph{telekinesis} (up to 2400\,cn, 6 rounds), one charge each.
+ \emph{telekinesis} (inanimate objects up to 2400\,cn, 6 rounds), one charge
+ each.
\item[Snake staff] Usable as $+1$ weapon. Turns into snake on command; SvS
- or coils round man-size target for 1d4 turns or commanded. MV60; HD3,
- 20\,hp, C3, XP6; AC5, T17, coil; ML12. Spend charges to improve hit roll,
- or transfer \emph{cure} (no range limit).
+ or coils round man-size target for 1d4 turns or commanded. MV60; HD3(M),
+ 20\,hp, C3, XP6; AC5, T17, coil; A; ML12. Spend charges to improve hit
+ roll, or transfer \emph{cure} (no range limit).
\item[Striking] Causes 2d6 damage per hit (uses charge).
\item[Inertia] Spear $+3$. Stops or releases on command; stores momentum
while stopped.
+\item[Parrying] Rod $+5$ (does $\d{1d8} + 5$ damage, no $\delta S$); may
+ \emph{parry} attacks ($+5$ to AC in mel\'ee).
+
+\item[Victory] Combat Results roll biased by $+25$; combat results difference
+ capped at 100.
+
+\item[Weaponry] Rod $+5$; may split into two $+2$ rods which may each split
+ into two $+1$ rods. Cannot divide by accident; easily reassembled. All
+ rods do $\d{1d8} + \delta G$ damage (no $\delta S$).
+
+\item[Wyrm] Rod $+5$ (does $\d{1d8} + 5$ damage, no $\delta S$). On command,
+ once per day, changes into small dragon (d10: 1--5 10 gold, 6--8 blue,
+ 9--10 black) with 30\,hp, harmed only by magic; may be magically healed.
+
+\end{description}
+
+\subsect{Rings}
+
+Maximum one ring per hand.
+
+\begin{description}
+
+\item[Animal control] Command 1d6 normal or one giant animal; no save;
+ requires concentration; animals may flee or attack afterwards. Usable once
+ per turn.
+
+\item[Delusion] Believed to be some other kind of ring.
+
+\item[Djinni summoning] Summon djinni to serve for one day. Usable once per
+ week.
+
+\item[Ear] Worn as earring. Placed against surface; user hears sounds within
+ $60'$ of surface. Usable three times per day.
+
+\item[Elemental adaptation] Permits vision and breathing on elemental plane.
+
+\item[Fire resistance] Withstand normal fire; $+2$ to save against fire and
+ damage biased by $-1$ per die.
+
+\item[Holiness] Worn during meditation for spells; gain 1 spell each of
+ levels 1--3. Cleric gains $+1$ on Turning rolls.
+
+\item[Human control] Control up to 6HD (NM is $\tfrac{1}{2}$), similar to
+ \emph{charm person}. Lasts until cancelled, ring removed, or charm removed
+ by \emph{dispel magic} or \emph{remove charm}.
+
+\item[Invisibility] Wearer becomes invisible (with items carried) while ring
+ worn; becomes visible if attacking or casting spells. Usable once per
+ turn; no duration limit.
+
+\item[Life protection] Negates 1d6 energy drain attacks. At zero, becomes
+ \emph{ring of protection $+1$}; at $-1$, disintegrates.
+
+\item[Memory] Recall one spell cast within 1 turn. Usable once per day.
+
+\item[Plant control] Control plants (and plantlike monsters) in $30'$ square
+ within $60'$; plants can entangle but not damage. Requires concentration.
+
+\item[Protection] Bonus to AC and saving throws. A \emph{ring of protection
+ $+1$, 5$'$ radius} applies to all within area.
+
+\item[Quickness] Move and attack at double speed for one turn. Usable once
+ per day.
+
+\item[Regeneration] Regenerates 1\,hp per turn; fingers regrow in 24 hours,
+ limbs in 1 week. Cannot regenerate fire or acid damage. Will revive dead
+ characters.
+
+\item[Remedies] Once per day, \emph{cure blindness}, \emph{cure disease},
+ \emph{remove curse} or \emph{neutralize poison}, as C25.
+
+\item[Safety] Can retrospectively make saving throws; works 1d4 times and
+ disintegrates.
+
+\item[Seeing] Can see all hidden, invisible and Ethereal objects within
+ $120'$, in their true forms, undisguised; experience and power (level/HD)
+ and basic character traits (alignment-ish) detected. Duration 3 turns;
+ usable once per day.
+
+\item[Spell eating] As \emph{ring of spell turning}, but `eats' user's memory
+ of spells after first one cast. A \emph{remove curse} from C25 allows
+ removal of ring; from C36 turns it into a \emph{ring of spell turning}.
+
+\item[Spell storing] Contains 1d6 spells; wearer knows spells and effects.
+ Spells replaced by casting at ring. About 20\% of rings contain cleric
+ spells. Effects dispelled as M5 or C8.
+
+\item[Spell turning] Reflects 2d6 spells back to caster per day.
+
+\item[Survival] Contains $\d{1d\%} + 100$ charges; one charge for survival
+ without food or water for 24 hours, or without air for 1 hour; turns black
+ when 5 charges left.
+
+\item[Telekinesis] Move inanimate objects of up to 2000\,cn by concentration,
+ for distance of $50'$.
+
+\item[Truth] Detects lies, three times per day. Ring informs wearer of power
+ telepathically.
+
+\item[Truthfulness] Ring informs wearer it is \emph{ring of truth}; when
+ activated, wearer cannot lie (or evade). A \emph{remove curse} by C26
+ allows removal.
+
+\item[Truthlessness] Ring informs wearer it is \emph{ring of truth}; when
+ activated, wearer cannot tell the truth. A \emph{remove curse} by C26
+ allows removal.
+
+\item[Water walking] Allows walking on any body of water without sinking.
+
+\item[Weakness] Strength becomes 3 within 1d6 rounds; \emph{remove curse}
+ allows removal.
+
+\item[Wishes] Grants 1--4 wishes (1d10: 1--4 1, 5--7 2, 8--9 3, 10 4).
+
+\item[X-ray vision] See $30'$ through stone walls (or $60'$ through wood,
+ cloth or water) by concentrating, detecting traps and secret doors; blocked
+ by gold or lead; inspect $10' \times 10'$ area per turn. Usable once per
+ hour.
+
+\end{description}
+
+\subsect{Miscellaneous items}
+
+\begin{description}
+
+\item[Amulet of protection from crystal balls and ESP] Wearer cannot be spied
+ upon by a crystal ball or any form of \emph{ESP}.
+
+\item[Bag of devouring] Looks like small sack. Items in the bag are lost
+ forever after $\d{1d6} + 6$ turns.
+
+\item[Bag of holding] Looks like small sack. Holds up to 10\,000\,cn of $10'
+ \times 5' \times 3'$ items; weighs only 600\,cn when full.
+
+\item[Boat, undersea] Looks like riverboat; AC4, 40 hull points. Obeys
+ commands to start, stop, turn, submerge, level off, and surface; bestows
+ \emph{water breathing} on passengers and crew.
+
+\item[Boots of levitation] Move up and down (only) at $20'$ per round,
+ carrying up to 2000\,cn. No duration limit.
+
+\item[Boots of speed] Move at 240 for 12 hours (must rest for 1 day
+ afterwards).
+
+\item[Boots of travelling and leaping] Need no rest during normal movement;
+ may jump $10'$ and $30'$ across.
+
+\item[Bowl of commanding water elementals] $3'\phi$; summons a 12HD water
+ elemental (takes 1 turn), allowing control (requires concentration;
+ elemental is hostile afterwards). Usable once per day.
+
+\item[Brazier of commanding fire elementals] Summons a 12HD fire elemental
+ (takes 1 turn), allowing control (requires concentration; elemental is
+ hostile afterwards). Usable once per day.
+
+\item[Broom of flying] On command, carries owner at MV\flying240 (can carry
+ 2000\,cn at MV\flying180).
+
+\item[Censer of controlling air elementals] Summons a 12HD air elemental
+ (takes 1 turn), allowing control (requires concentration; elemental is
+ hostile afterwards). Usable once per day.
+
+\item[Chime of time] $3''$ silvery metal stick. On command keeps track of
+ time, chiming every hour (audible by all within $60'$; a \emph{silence
+ 15$'$ radius} spell dampens it to $30'$, but is dispelled). On command,
+ shows time as gold colour extending from one end to other.
+
+\item[Crystal ball] See any place or object thought about; image clarity
+ depends on familiarity with target. Image lasts 1 turn; usable three times
+ per day.
+
+\item[Crystal ball with clairaudience] As \emph{crystal ball}, but can hear
+ sound through ears of creature in area viewed.
+
+\item[Crystal ball with ESP] As \emph{crystal ball}, but can listen to
+ thoughts of creature in area viewed.
+
+\item[Displacer cloak] Wearer appears to be $5'$ from actual position; $+2$
+ on saves against spells, wands, turn-to-stone; $-2$ to hit in mel\'ee;
+ most missile attacks fail automatically.
+
+\item[Drums of panic] Hearers $10'$--$240'$ away must SvS or flee for 3
+ turns.
+
+\item[Efreeti bottle] Heavy jug $3'$ high. When unsealed and unstoppered,
+ efreeti emerges to serve once per day for 101 days.
+
+\item[Egg of wonder] Thrown up to $60'$ range; creature emerges and grows to
+ full size, obeys thrower's commands; disappears after one hour.
+ \begin{tabular}[C]{\shade cl|cl} \hlx*{hv}
+ \th{1d12} & \th{Animal} & \th{1d12} & \th{Animal} \\ \hlx{vhv}
+ \01 & Baboon, rock & \07 & Cat, leopard \\ \hlx{+}
+ \02 & Bat, giant & \08 & Ferret, giant \\ \hlx{+}
+ \03 & Bear, black & \09 & Lizard, gecko \\ \hlx{+}
+ \04 & Bear, grizzly & 10 & Lizard, draco \\ \hlx{+}
+ \05 & Boar & 11 & Snake, racer \\ \hlx{+}
+ \06 & Cat, mountain lion & 12 & Wolf, normal \\ \hlx*{vh}
+ \end{tabular}
+
+\item[Elven cloak] Wearer almost invisible (detectable 1 in 6); becomes
+ visible when attacking or casting spell, cannot become invisible for 1
+ turn.
+
+\item[Elven boots] Move almost completely silently (detectable 1 in 10).
+
+\item[Flying carpet] Carry one passenger at MV\flying300, two at MV\flying
+ 240 or three at MV\flying180.
+
+\item[Gauntlets of ogre power] Strength of 18.
+
+\item[Girdle of giant strength] THAC0 12, double damage with weapon.
+
+\item[Helm of alignment changing] Changes wearer's alignment; \emph{remove
+ curse} allows removal but wearer will resist.
+
+\item[Helm of reading] Wearer can read any writings (strange languages,
+ magical writing, codes, etc.). May (1 in 10) be destroyed when wearer hit;
+ destroyed if wearer killed.
+
+\item[Helm of telepathy] Send messages by thought to creature within $90'$,
+ may read thoughts (requires concentration, SvS allowed to avoid thought
+ reading).
+
+\item[Helm of teleportation] Allows \emph{teleport} as spell. After first
+ use, or any use to teleport another creature, stops working until user
+ casts \emph{teleport} on it.
+
+\item[Horn of blasting] Cone of sound $100' \times 20'$; 2d6 damage to those
+ in area, SvS or deafened for 1 turn. Usable once per turn.
+
+\item[Lamp, hurricane] As \emph{lamp of long burning}. Shutters closed when
+ found; when opened the first time each day, emits gusts of wind and rain,
+ drenching all within $30'$. All must SvS (holder automatically fails) or
+ be knocked over with carried items scattered within $60'$.
+
+\item[Lamp of long burning] Burns and illuminates without using oil. Becomes
+ nonmagical if flame doused with water.
+
+\item[Metallion of ESP] Read thoughts of one creature within range by
+ concentrating for 1 round (SvS to avoid); 1 in 6 chance broadcasts thoughts
+ to all in range.
+
+\item[Mirror of life trapping] If looking into mirror, SvS or be sucked into
+ it with all items. Stores up to 20 man-size or smaller creatures, who do
+ not need food or air. Can communicate with those trapped inside. Breaking
+ mirror or \emph{wish} (one each) releases those trapped.
+
+\item[Muzzle of training] Adjusts to fit any monster with bite attack.
+ Victim can breathe but not bite or talk. Locks in place (as if
+ \emph{wizard lock} by M15) and unlocks by command.
+
+\item[Nail, finger] Looks like $1''$--$4''$ carpentry nail. Disappears if
+ commanded as \emph{nail of pointing}; thereafter, if user attempts to hide
+ from enemy (e.g., by using \emph{invisibility}), may appear (always first
+ time, 1 in 4 chance thereafter) as glowing finger pointing at user for 1d6
+ rounds. A \emph{remove curse} removes the nail forever.
+
+\item[Nail of pointing] Looks like $1''$--$4''$ carpentry nail. If
+ commanded, turns into bony finger and points to named nonmagical item.
+ Cannot detect living or undead creatures; no range limit. Usable once per
+ day.
+
+\item[Ointment] Salve in small box.
+ \begin{enumerate*}
+ \item \emph{Blessing:} Bonus $+2$ on AC and saves for 1 turn.
+ \item \emph{Healing:} Cures $\d{2d6} + 2$\,hp damage.
+ \item \emph{Poison:} Seems like \emph{blessing}; SvPn at $-2$ or die.
+ \item \emph{Scarring:} Seems like \emph{healing}; causes $\d{2d6} + 2$\,hp
+ burn damage curable by \emph{ointment of soothing}, \emph{cureall},
+ \emph{heal} or \emph{wish}.
+ \item \emph{Soothing:} Cures all burn damage.
+ \item \emph{Tanning:} Skin turns bright colour; wears off in 1d4 months.
+ \end{enumerate*}
+
+\item[Pouch of security] Size of large sack. Attempts to steal cause it to
+ scream `I am being stolen!' for 1 hour or until held by owner and commanded
+ to stop.
+
+\item[Quill of copying] Copies spell on scroll: burn original scroll, mix
+ ashes with rare ink (1000\,gp cost), place on blank scroll with inkwell and
+ command to write; quill writes two copies of the spell. Only copies one
+ spell (one of lowest level on original scroll). Blots 1 in 4, ruining
+ scroll unless fixed with \emph{wish}.
+
+\item[Rope of climbing] Thin rope $50'$ long: climbs in any direction on
+ command, fastens to any protruding surface and supports 10\,000\,cn.
+
+\item[Scarab of protection] Absorbs curses, or \emph{finger of death}; usable
+ 2d6 times.
+
+\item[Slate of identification] Identifies magical items placed on it, with a
+ (new, if possible) command word; cannot detect \emph{cursed} items or
+ numbers of charges. Ten charges usable per day; uses: potion~(2),
+ missile~(3), wand~(4), staff~(5), permanent weapon~(6), armour or
+ shield~(7), miscellaneous item~(10 or more).
+
+\item[Stone of controlling earth elementals] $3''\phi$; summons a 12HD earth
+ elemental (takes 1 turn), allowing control (requires concentration;
+ elemental is hostile afterwards). Usable once per day.
+
+\item[Talisman of elemental travel] Cast \emph{conjure elemental} while
+ touching elemental symbol on talisman to enter elemental plane; talisman
+ allows clear vision ($120'$--$1200'$ range) and breathing. Talisman may be
+ of any element or greater talisman with all four symbols (equal chances for
+ all five). Greater talisman can (on command) be used to control
+ elementals, usable ten times per trip.
+
+\item[Wheel of floating] Allows wagon to be towed across river or stream.
+ First wheel allows 10\,000\,cn to be carried; each extra wheel allows extra
+ 5000\,cn, up to maximum of four.
+
+\item[Wheel of fortune] Wheel, $10'\phi$, mounted on wall and easily rotated,
+ contains black (with white skull) and white (with red heart) wedges. When
+ spun, rotates for 3 rounds. Cannot be affected by magic; a \emph{wish}
+ will make the wheel disappear. Requires 26HD to move, weighs 20\,000\,cn.
+ Usable by each person once per day; cannot be used by \emph{charmed}
+ creatures.
+ \begin{tabular}[C]{\shade c>{\raggedright}p{5pc}|c>{\raggedright}p{5pc}}
+ \hlx*{hv}
+ \th{1d12} & \th{Effect} &
+ \th{1d12} & \th{Effect} \\ \hlx{vhv}
+ \01 & 1000\,gp appear &
+ \07 & ability score drops by 1 \\ \hlx{+}
+ \02 & 10 garnets (100\,gp each) appear &
+ \08 & PR drops by 1 \\ \hlx{+}
+ \03 & 1 brooch (1000\,gp) appears &
+ \09 & $C$ drops by 1 \\ \hlx{+}
+ \04 & 1 misc magic item appears &
+ 10 & least valuable magic item disintegrates \\ \hlx{+}
+ \05 & ability score rises by 1 &
+ 11 & nonmagical items disintegrate \\ \hlx{+}
+ \06 & PR or $C$ rises by 1 &
+ 12 & die \\ \hlx*{vh}
+ \end{tabular}
+
+\item[Wheel, square] Useless on roads or flat terrain. Allows movement on
+ mountains and deserts (MV20 with one, MV30 with two, MV40 with three and
+ MV60 with four).
+
+\end{description}
+
+\subsect{Armour and shields}
+
+Cursed 1 in 8: revealed in earnest combat; \emph{remove curse} allows
+removal, C36 removes curse entirely.
+
+Special powers usable once per day.
+
+\begin{description}
+
+\item[Absorption] Energy drains lose one `plus' instead of affecting wearer;
+ armour disintegrates at zero; no daily limit.
+
+\item[Charm] When hit, opponent must SvS or be \emph{charmed} ($+4$ bonus if
+ using weapon). Only one \emph{charm} per day.
+
+\item[Cure wounds] Cures half wearer's damage.
+
+\item[Electricity] When charged by command, inflicts 6d6 damage (SvS for
+ half, $+4$ bonus if using weapon) against next attacker to hit. Only one
+ blast per day.
+
+\item[Energy drain] When charged by command, inflicts 1ED:Wt (SvS to avoid,
+ $+4$ bonus if using weapon) against next attacker to hit. Only one drain
+ per day.
+
+\item[Ethereality] Become ethereal or return to prime by command, once each
+ once per day.
+
+\item[Fly] On command allows flight (MV\flying360, for 12 turns). Usable
+ once per day.
+
+\item[Gaseous form] Assume gaseous form (with items carried) for up to 6
+ turns. Usable once per day.
+
+\item[Haste] Double movement and attacks for 1 turn. Usable once per day.
+
+\item[Invisibility] Become invisible on command with all items carried, until
+ attacking or casting spell. Usable three times per day.
+
+\item[Reflection] Reflects \emph{light} or \emph{continual light} at caster
+ (who may SvS to avoid), three times per day. Meet gaze attacks as if using
+ mirror, but without $-2$ to hit.
+
+\item[Remove curse] Cannot be \emph{cursed}; removes curses as if C36.
+ Usable three times in total.
+
+\end{description}
+
+\subsect{Missiles}
+
+\begin{description}
+
+\item[Biting] On hit, becomes poisonous snake: SvPn or die.
+
+\item[Blinking] Blinks in and out of existence to pass allies.
+
+\item[Charming] Target must SvS or be \emph{charmed}.
+
+\item[Climbing] If shot at object, fastens securely and creates $50'$ rope
+ supporting any number of climbers. Disappears with rope after 1 turn.
+
+\item[Curing] Obviously blunt and inscribed with holy symbol: cures $\d{2d6}
+ + 2\delta G$ damage.
+
+\item[Disarming] SvS or drop weapon.
+
+\item[Dispelling] Creates \emph{dispel magic} (by M15) on target.
+
+\item[Flying] Ranges increased by factor of 5.
+
+\item[Lighting] Creates \emph{light} ($30'$ radius, 12 turns) on demand or
+ on hit (SvS or blinded) and disintegrates.
+
+\item[Penetrating] Not slowed by underbrush, webs, or other cover; no hit
+ modification for cover.
+
+\item[Refilling] If left in container with normal missiles, creates 1d20 more
+ normal missiles each day.
+
+\item[Screaming] Emits screams as it flies; all within $30'$ of path must
+ check morale or retreat for 1d8 rounds.
+
+\item[Seeking] Automatically hits target object (misses creatures). Can be
+ used for disarming.
+
+\item[Sinking] Causes $\d{1d10} + 10$ hull points damage to ships.
+
+\item[Slaying] Designated \emph{opponent}s must SvDR or die.
+
+\item[Speaking] Misses creatures: may be shot at target or named place within
+ 10 miles; repeats 20 word spoken message.
+
+\item[Stunning] Target must SvS or be stunned for 1d6 rounds.
+
+\item[Teleporting] Target must SvS (with $+2$ bonus) or be \emph{teleported}
+ 1d\% miles in random direction; will land safely.
+
+\item[Transporting] Target must SvS or be sent $360'$ to place of user's
+ choosing.
+
+\item[Wounding] Causes 1\,hp damage per round until magically cured; cannot
+ affect constructs or undead.
+
+\end{description}
+
+\subsect{Sword primary powers}
+
+Usually usable once per round as often as desired.
+
+\begin{description}
+
+\item[Detect evil/good] Detects good or ill intentions within $20'$.
+
+\item[Detect gems] Points to gems within $60'$, detecting amounts.
+
+\item[Detect magic] Detects magical items and effects within $20'$. Usable
+ three times per day.
+
+\item[Detect metal] Points to metal of requested type within $60'$, but
+ cannot detect amount.
+
+\item[Detect shifting walls] Within $10'$.
+
+\item[Detect slopes] Within $10'$.
+
+\item[Find secret doors] Within $10'$. Usable three times per day.
+
+\item[Find traps] Within $10'$. Usable three times per day.
+
+\item[See invisible] Find invisible and hidden creatures and objects (not
+ secret doors) within $20'$.
+
+\end{description}
+
+\subsect{Sword extraordinary powers}
+
+Usually usable once per round, up to three times per day.
+
+\begin{description}
+
+\item[Clairaudience] Hear sound through ears of creature within $60'$.
+
+\item[Clairvoyance] See through eyes of creature within $60'$.
+
+\item[ESP] Listen to thoughts of creature within $60'$.
+
+\item[Extra damage] Damage multiplied by 4 (or 5, 6, \dots\ for duplicates).
+ Duration 1d10 rounds.
+
+\item[Flying] Allows flight MV\flying360 for 3 turns.
+
+\item[Healing] Heals 6\,hp (or 12, 18, \dots\ for duplicates) per day, at
+ 1\,hp per round.
+
+\item[Illusion] Creates illusion in $20'$ cube within $240'$ while user
+ concentrates. Monsters are AC9 and disappear when hit. Victim may SvS to
+ disbelieve the illusion. Never causes damage; effects wear off in 1d4
+ turns.
+
+\item[Levitation] Move up and down (only) at $20'$ per round, carrying up to
+ 2000\,cn, for 3 turns.
+
+\item[Telekinesis] Move inanimate objects of up to 2000\,cn by concentration,
+ for distance of $50'$.
+
+\item[Telepathy] Send messages by thought to creature within $90'$, may read
+ thoughts (requires concentration, SvS allowed to avoid thought reading).
+
+\item[Teleportation] As spell. Usable once per day.
+
+\item[X-ray vision] See $30'$ through stone walls (or $60'$ through wood,
+ cloth or water) by concentrating, detecting traps and secret doors; blocked
+ by gold or lead; inspect $10' \times 10'$ area per use.
+
+\end{description}
+
+\subsect{Weapon talents}
+
+Usually usable once per day. Missile weapon talents usually apply to
+missiles fired.
+
+\begin{description}
+
+\item[Breathing] Allows \emph{water breathing} (for 1 day) or \emph{create
+ air} (for one hour).
+
+\item[Charming] Can \emph{charm} one humanoid within $120'$.
+
+\item[Deceiving] Change appearance of user (facial features, equipment, but
+ not size) while carried (unsheathed); cannot disguise itself.
+
+\item[Defending] Bonus can be applied to AC instead of hit/damage.
+
+\item[Deflecting] Optionally used to deflect energy drain, losing one `plus';
+ disintegrates at $-1$. Applies to missile weapon itself.
+
+\item[Draining] Can drain $\d{1d4} + 4$ levels, as 1ED:Wh. Missile weapons
+ lose one `plus' per drain.
+
+\item[Extinguishing] Cool to touch. Double $\delta G$ against fire-using
+ creatures. Douses normal fire.
+
+\item[Finding] Sense direction of one known object within $120'$ (but not
+ distance). Will not locate creatures.
+
+\item[Flaming] Harmless to weapon and user. Bonus $+2$ to hit and damage
+ hippogriff, pegasis, roc and troll, $+3$ to hit and damage treant and
+ undead. Usable as required.
+
+\item[Flying] Must first be used normally in each battle; on command attacks
+ by itself for three rounds (or on command). Missile weapons create
+ ammunition as needed.
+
+\item[Healing] Cures $\d{2d6} + 2$\,hp of the user only.
+
+\item[Hiding] Can render the user invisible (with all items, becomes visible
+ when attacking or casting spells). Additionally, weapon only can become
+ invisible three times per day.
+
+\item[Holding] Up to four humanoids within $180'$ SvS or paralysed for 9
+ turns. Penalty $-2$ on save if cast on single individual. Cancelled by
+ \emph{dispel magic} or \emph{free person}.
+
+\item[Lighting] Create \emph{light} at $120'$ range.
+
+\item[Silencing] Cause \emph{silence} in $15'$ radius, at $180'$ range, for
+ 12 turns.
+
+\item[Slicing] (Only edged weapons.) If $\textrm{hit roll} + \delta G \ge
+ 19$, opponent must SvDR or be killed. Doesn't work against constructs or
+ undead.
+
+\item[Slowing] Opponent hit moves and attacks at half speed for 1 turn (no
+ save).
+
+\item[Speeding] Doubles user's movement and attack rate for 1 turn.
+
+\item[Translating] User can understand any languages heard for 6 turns.
+
+\item[Watching] On command, weapon will watch for monster type and vibrate
+ slightly if any come within $60'$.
+
+\item[Wishing] Grants 1d3 wishes.
+
\end{description}
\end{multicols}