src/robots/rpg-shopkeeper.lisp @ 496f6e33e468
Update to compiling version of Chancery
author |
Steve Losh <steve@stevelosh.com> |
date |
Wed, 18 Jan 2017 18:07:55 +0000 |
parents |
d5c110b938cb |
children |
8163984906d6 |
(in-package :magitek.robots.rpg-shopkeeper)
(named-readtables:in-readtable :chancery)
;;;; General ------------------------------------------------------------------
(define-rule (bonus :distribution (:zipf :exponent 1.8))
1 2 3 4 5)
;;;; Materials ----------------------------------------------------------------
(defclass* material ()
(name multiplier))
(defun make-material (name multiplier)
(make-instance 'material :name name :multiplier multiplier))
(defmethod print-object ((o material) s)
(print-unreadable-object (o s :type t)
(princ (material-name o) s)))
(defmacro define-material (name multiplier)
`(defparameter ,(symb '* (string-upcase (substitute #\- #\space name)) '*)
(make-material ,name ,multiplier)))
(define-material "iron" 1.0)
(define-material "steel" 1.5)
(define-material "silver" 2.0)
(define-material "meteoric iron" 4.0)
(define-material "mithril" 10.0)
(define-material "adamantine" 11.0)
(define-material "cloth" 1.0)
(define-material "leather" 1.5)
(define-material "silk" 2.0)
(define-material "spider silk" 6.0)
(define-material "pine" 1.0) ; http://www.wood-database.com/wood-articles/bow-woods/
(define-material "poplar" 1.2)
(define-material "walnut" 1.3)
(define-material "maple" 2.0)
(define-material "oak" 3.0)
(define-material "yew" 5.0)
(define-material "rosewood" 10.0)
(define-rule (metal :distribution :zipf)
!*iron*
!*steel*
!*silver*
!*meteoric-iron*
!*mithril*
!*adamantine*)
(define-rule (textile :distribution :weighted)
(1.00 !*cloth*)
(1.00 !*leather*)
(0.80 !*silk*)
(0.01 !*spider-silk*))
(define-rule (wood :distribution (:zipf :exponent 0.8))
!*pine*
!*poplar*
!*walnut*
!*maple*
!*oak*
!*yew*
!*rosewood*)
;;;; Monsters -----------------------------------------------------------------
(defclass* monster ()
(singular multiplier plural adjective))
(defun make-monster (singular multiplier plural adjective)
(make-instance 'monster
:singular singular
:multiplier multiplier
:plural plural
:adjective adjective))
(defmethod print-object ((o monster) s)
(print-unreadable-object (o s :type t)
(princ (monster-singular o) s)))
(defmacro define-monster (singular multiplier plural adjective)
`(defparameter ,(symb '* (string-upcase singular) '*)
(make-monster
,singular
,multiplier
,plural
,adjective)))
(define-monster "goblin" 1.00 "goblins" "goblin")
(define-monster "kobold" 1.00 "kobolds" "kobold")
(define-monster "elf" 1.00 "elves" "elven")
(define-monster "dwarf" 1.00 "dwarves" "dwarven")
(define-monster "halfling" 1.00 "halflings" "halfling")
(define-monster "gnome" 1.00 "gnomes" "gnomish")
(define-monster "gnoll" 1.10 "gnolls" "gnollish")
(define-monster "ogre" 1.20 "ogres" "ogre")
(define-monster "troll" 1.60 "trolls" "troll")
(define-monster "vampire" 5.00 "vampires" "vampire")
(define-monster "dragon" 9.00 "dragons" "dragon")
(define-rule (monster :distribution :weighted)
(1.00 !*goblin*)
(1.00 !*kobold*)
(1.00 !*elf*)
(1.00 !*dwarf*)
(1.00 !*halfling*)
(1.00 !*gnome*)
(1.00 !*ogre*)
(1.00 !*troll*)
(1.00 !*gnoll*)
(0.10 !*vampire*)
(0.01 !*dragon*))
;;;; Roles --------------------------------------------------------------------
(define-rule role
"cleric"
"warrior"
"wizard"
"rogue")
;;;; Elements -----------------------------------------------------------------
(define-rule element
("ice" "icy")
("fire" "flaming")
("electricity" "electrified")
("poison" "venomous"))
;;;; Armor --------------------------------------------------------------------
(define-rule armor-piece
"scale mail"
"ring mail"
"chain mail"
"plate mail")
(define-rule clothing-piece
"robe"
"shirt"
"pants"
"dress"
"skirt")
(define-rule armor-enchantment
(:protection-from monster)
(:resistance element)
(:bonus bonus))
(define-rule vanilla-armor
(metal armor-piece)
(textile clothing-piece))
(define-rule (armor :distribution :weighted)
(2 (vanilla-armor nil))
(1 (vanilla-armor armor-enchantment)))
(defgeneric enchanted-armor-description
(base enchantment-type enchantment-arguments))
(defmethod enchanted-armor-description
(base (e (eql :protection-from)) enchantment-args)
(destructuring-bind (monster) enchantment-args
(format nil "~A of protection from ~A" base (monster-plural monster))))
(defmethod enchanted-armor-description
(base (e (eql :resistance)) enchantment-args)
(destructuring-bind ((noun adjective)) enchantment-args
(declare (ignore adjective))
(format nil "~A of ~A resistance" base noun)))
(defmethod enchanted-armor-description
(base (e (eql :bonus)) enchantment-args)
(destructuring-bind (val) enchantment-args
(format nil "+~D ~A" val base)))
(defun vanilla-armor-description (vanilla-armor)
(destructuring-bind (material piece) vanilla-armor
(format nil "~A ~A" (material-name material) piece)))
(defun armor-description (armor)
(destructuring-bind (vanilla enchant) armor
(let ((vanilla-description (vanilla-armor-description vanilla)))
(if enchant
(enchanted-armor-description vanilla-description
(first enchant)
(rest enchant))
vanilla-description))))
;;;; Weapons ------------------------------------------------------------------
(define-rule melee-weapon
"dagger"
"longsword"
"short sword"
"hand axe"
"battleaxe"
"spear"
"halberd"
"scythe"
"scimitar"
"lance"
"hammer"
"staff"
"mace"
"flail")
(define-rule (bow-weapon :distribution :weighted)
(2 "shortbow")
(2 "longbow")
(1 "crossbow")
(1 "compound bow"))
(define-rule weapon-enchantment
(:slaying monster)
(:element element)
(:bonus bonus))
(define-rule vanilla-weapon
(metal melee-weapon)
(wood bow-weapon))
(define-rule (weapon :distribution :weighted)
(1 (vanilla-weapon nil))
(1 (vanilla-weapon weapon-enchantment)))
(defgeneric enchanted-weapon-description
(base enchantment-type enchantment-arguments))
(defmethod enchanted-weapon-description
(base (e (eql :slaying)) enchantment-args)
(destructuring-bind (monster) enchantment-args
(format nil "~A of ~A-slaying" base (monster-singular monster))))
(defmethod enchanted-weapon-description
(base (e (eql :element)) enchantment-args)
(destructuring-bind (element) enchantment-args
(format nil "~A ~A" (second element) base)))
(defmethod enchanted-weapon-description
(base (e (eql :bonus)) enchantment-args)
(destructuring-bind (val) enchantment-args
(format nil "+~D ~A" val base)))
(defun vanilla-weapon-description (vanilla-weapon)
(destructuring-bind (material piece) vanilla-weapon
(format nil "~A ~A" (material-name material) piece)))
(defun weapon-description (weapon)
(destructuring-bind (vanilla enchant) weapon
(let ((vanilla-description (vanilla-weapon-description vanilla)))
(if enchant
(enchanted-weapon-description vanilla-description
(first enchant)
(rest enchant))
vanilla-description))))
;;;; Flavor -------------------------------------------------------------------
(define-string scene
("images of" [monster monster-plural] "fighting" [monster monster-plural])
("a picture of a famous" [monster monster-singular] role))
(define-string picture
"painted with"
"adorned with")
(define-string flavor
(picture scene))
(define-string sales-pitch
"Only used once!"
"Brand new!"
("I bought it from" [monster monster-adjective a] role :. ".")
"Look at the workmanship!"
"This is gonna go fast!")
;;;; Main ---------------------------------------------------------------------
(define-rule base-item
!(weapon-description @weapon)
!(armor-description @armor))
(define-string (item :distribution :weighted)
(2 base-item)
(1 (base-item :. "," flavor)))
(define-string offer
("FOR SALE:" [item cap]
:. #\newline #\newline :.
sales-pitch))
;;;; API ----------------------------------------------------------------------
(defun random-string ()
(offer))