anchor.diff:       ;; yeah, the vendor will deal with the person
        t)))
   
  +(defun vendor-resolve-hash (self obj-str)
  +  (let ((num (parse-integer obj-str :start 1)))
  +    (unless (or (null num) (not (plusp num)))
  +      (let ((idx (1- num)))
  +        (loop
  +           for obj-sublist on (carrying-of self)
  +           as obj = (first obj-sublist)
  +           as next-obj = (second obj-sublist)
  +           do
  +             (when (zerop idx)
  +               (return obj))
  +             (when (or (null next-obj) (not (same-obj next-obj obj)))
  +               (decf idx)))))))
  +
  +(defun vendor-resolve-name (self obj-str)
  +  (first (resolve-alias self obj-str (carrying-of self))))
  +
  +(defun vendor-inventory (obj list)
  +  (count obj list :test 'same-obj))
  +
  +(defun vendor-make-sale (self ch vars shop)
  +  (when (endp vars)
  +    (send-to-char ch "What do you wish to buy?~%")
  +    (return-from vendor-make-sale))
  +
  +  (let ((num 1)
  +        (obj-str (pop vars)))
  +    (cond
  +      ((every #'digit-char-p obj-str)
  +       (setf num (parse-integer obj-str))
  +       (cond
  +         ((minusp num)
  +          (perform-say-to self ch "You want to buy a negative amount?  Try selling.")
  +          (return-from vendor-make-sale))
  +         ((zerop num)
  +          (perform-say-to self ch "You wanted to buy something?")
  +          (return-from vendor-make-sale))
  +         ((> num 24)
  +          (perform-say-to self ch "I can't sell that many at once.")
  +          (return-from vendor-make-sale)))
  +
  +       (setf obj-str (pop vars)))
  +      ((string= "all" obj-str)
  +       (setf num -1)
  +       (setf obj-str (pop vars))))
  +
  +    ;; Check for hash mark
  +    (let ((obj (if (eql #\# (char obj-str 0))
  +                   (vendor-resolve-hash self obj-str)
  +                   (vendor-resolve-name self obj-str))))
  +      (unless obj
  +        (perform-say-to self ch (sell-noobj-msg-of shop))
  +        (return-from vendor-make-sale))
  +
  +      (cond
  +        ((= num -1)
  +         (when (vendor-produced-p obj shop)
  +           (perform-say-to self ch "I can make these things all day!")
  +           (return-from vendor-make-sale))
  +         (setf num (vendor-inventory obj (carrying-of self))))
  +        ((> num 1)
  +         (let ((obj-count (vendor-inventory obj (carrying-of self))))
  +           (unless (or (vendor-produced-p obj shop)
  +                       (<= num obj-count))
  +             (perform-say-to self ch (format nil "I only have ~d to sell to you." obj-count))
  +             (setf num obj-count)))))
  +      (let ((cost (vendor-get-value obj
  +                                    (markup-of shop)
  +                                    (cost-modifier-of ch self)
  +                                    (currency-of shop)))
  +            (amt-carried (slot-value ch (currency-of shop))))
  +
  +        (when (> cost amt-carried)
  +          (perform-say-to self ch (buyerbroke-msg-of shop))
  +          (when (temper-cmd-of shop)
  +            (interpret-command self (temper-cmd-of shop)))
  +          (return-from vendor-make-sale))
  +
  +        (when (and (> (* cost num) amt-carried) (plusp cost))
  +          (setf num (floor amt-carried cost))
  +          (perform-say-to self ch (format nil "You only have enough to buy ~d." num)))
  +
  +        (when (> (1+ (carry-items-of ch)) (can-carry-items ch))
  +          (perform-say-to self ch "You can't carry any more items.")
  +          (return-from vendor-make-sale))
  +
  +        (when (> (+ (carry-weight-of ch) (weight-of obj)) (can-carry-weight ch))
  +          (perform-say-to self ch (random-elt
  +                                   '("You can't carry any more weight."
  +                                     "You can't carry that much weight."
  +                                     "You can carry no more weight.")))
  +          (return-from vendor-make-sale))
  +
  +        (when (or (> (+ (carry-items-of ch) num) (can-carry-items ch))
  +                  (and (> (+ (carry-weight-of ch) (* num (weight-of obj))) (can-carry-weight ch))
  +                       (plusp (weight-of obj))))
  +          (setf num (min num (- (can-carry-items ch) (carry-items-of ch))))
  +          (setf num (min num (floor (- (can-carry-weight ch)
  +                                       (carry-weight-of ch))
  +                                    (weight-of ch))))
  +          (perform-say-to self ch (format nil "You can only carry ~d." num)))
  +
  +        (cond
  +          ((eql (currency-of shop) 'qp)
  +           (decf (quest-points-of (account-of ch)) (* cost num)))
  +          (t
  +           (decf (slot-value ch (currency-of shop)) (* cost num))
  +           (incf (slot-value self (currency-of shop)) (* cost num))))
  +
  +        (perform-say-to self ch (string-replace "%d" (buy-msg-of shop) (write-to-string (* cost num))))
  +        (act self :target ch :item obj
  +             :subject-emit (format nil "$n sell$% $p ~[~;~;~:;~:*(x~d) ~]to $N for ~d ~a."
  +                                   num
  +                                   (* cost num)
  +                                   (currency-desc (currency-of shop)))
  +             :target-emit (format nil "$n sell$% $p ~[~;~;~:;~:*(x~d) ~]to $N for ~d ~a."
  +                                  num
  +                                  (* cost num)
  +                                  (currency-desc (currency-of shop)))
  +             :not-target-emit (format nil "$n sell$% $p ~[~;~;~:;~:*(x~d) ~]to $N."
  +                                      num))
  +
  +        (slog "~a[~d] sold ~a[~d] (x~d) to ~a ~a[~d] for ~d ~a"
  +              (name-of self)
  +              (vnum-of self)
  +              (name-of obj)
  +              (vnum-of obj)
  +              num
  +              (if (is-npc ch) "NPC" "PC")
  +              (name-of ch)
  +              (if (is-npc ch) (vnum-of ch) (idnum-of ch))
  +              (* cost num)
  +              (currency-desc (currency-of shop)))
  +
  +        (if (vendor-produced-p obj shop)
  +            ;; Load all-new identical items
  +            (let ((vnum (vnum-of obj)))
  +              (loop for index from num downto 1 do
  +                   (obj-to-char (read-object vnum) ch)))
  +            ;; Actually move the items from vendor to player
  +            (loop
  +               with num-left = num
  +               for cur-obj in (copy-list (carrying-of self))
  +               until (zerop num-left)
  +               when (same-obj obj cur-obj)
  +               do
  +                 (decf num-left)
  +                 (obj-from-char cur-obj)
  +                 (obj-to-char cur-obj ch)))))))
  +
  +(defun vendor-invalid-buy (self ch shop obj)
  +  (cond
  +    ((or (is-obj-stat obj +item-nosell+)
  +         (not (approvedp obj))
  +         (plusp (owner-id-of (shared-of obj))))
  +     (perform-say-to self ch (badobj-msg-of shop)))
  +    ((< (cost-of obj) 1)
  +     (perform-say-to self ch "Why would I want that?  It has no value."))
  +    ((null (cdr (assoc (kind-of obj) (will-buy-of shop))))
  +     (perform-say-to self ch (badobj-msg-of shop)))
  +    ((is-obj-stat2 obj +item2-broken+)
  +     (perform-say-to self ch "I'm not buying something that's already broken."))
  +    ((is-obj-stat3 obj +item3-hunted+)
  +     (perform-say-to self ch "This is hunted by the forces of Hell!  I'm not taking this!"))
  +    ((plusp (sigil-idnum-of obj))
  +     (perform-say-to self ch "You'll have to remove that warding sigil before I'll bother."))
  +    ((and (or (is-obj-kind obj +item-wand+)
  +              (is-obj-kind obj +item-staff+))
  +          (zerop (aref (value-of obj) 2)))
  +     (perform-say-to self ch "I don't buy used up wands or staves!"))
  +    (t
  +     (return-from vendor-invalid-buy nil)))
  +  t)
  +
  +(defun vendor-buy-from (self ch vars shop)
  +  (when (eql (currency-of shop) 'quest-points)
  +    (perform-say-to self ch "Hey, I only sell stuff.")
  +    (return-from vendor-buy-from))
  +
  +  (when (endp vars)
  +    (send-to-char ch "What would you like to sell?~%")
  +    (return-from vendor-buy-from))
  +
  +  (let ((num 1)
  +        (obj-str (pop vars)))
  +    (cond
  +      ((every #'digit-char-p obj-str)
  +       (setf num (parse-integer obj-str))
  +       (cond
  +         ((minusp num)
  +          (perform-say-to self ch "You want to sell a negative amount?  Try buying.")
  +          (return-from vendor-buy-from))
  +         ((zerop num)
  +          (perform-say-to self ch "You wanted to sell something?")
  +          (return-from vendor-buy-from)))
  +
  +       (setf obj-str (pop vars)))
  +      ((string= "all" obj-str)
  +       (setf num -1)
  +       (setf obj-str (pop vars))))
  +
  +    (let* ((obj (first (resolve-alias ch obj-str (carrying-of ch)))))
  +      (unless obj
  +        (perform-say-to self ch (buy-noobj-msg-of shop))
  +        (return-from vendor-buy-from))
  +
  +      (when (vendor-invalid-buy self ch shop obj)
  +        (return-from vendor-buy-from))
  +
  +      (let* ((obj-list (remove-if-not (curry 'same-obj obj) (member obj (carrying-of ch))))
  +             (obj-count (length obj-list)))
  +        (when (= -1 num)
  +          (setf num obj-count))
  +
  +        (when (< obj-count num)
  +          (send-to-char ch "You only have ~d of those!~%" obj-count)
  +          (return-from vendor-buy-from))
  +
  +        (when (vendor-produced-p obj shop)
  +          (perform-say-to self ch "I make these.  Why should I buy it back from you?")
  +          (return-from vendor-buy-from))
  +
  +        (let ((cost (vendor-get-value obj
  +                                      (markdown-of shop)
  +                                      (cost-modifier-of ch self)
  +                                      (currency-of shop)))
  +              (amt-carried (if (eql (currency-of shop) 'gold) (gold-of self) (cash-of self))))
  +
  +          (when (< amt-carried cost)
  +            (perform-say-to self ch (selfbroke-msg-of shop))
  +            (return-from vendor-buy-from))
  +
  +          (when (< amt-carried (* cost num))
  +            (setf num (floor amt-carried cost))
  +            (perform-say-to self ch (format nil "I can only afford to buy ~d." num)))
  +
  +          (when (> (+ num (vendor-inventory obj (carrying-of self))) +vendor-max-items+)
  +            (setf num (- +vendor-max-items+ (vendor-inventory obj (carrying-of self))))
  +            (perform-say-to self ch (format nil "I only want to buy ~d." num)))
  +
  +          (perform-say-to self ch (string-replace "%d" (sell-msg-of shop) (write-to-string (* cost num))))
  +          (perform-give-money self ch (* cost num) (currency-of shop))
  +          (slog "~a[~s] bought ~a[~d] (x~d) from ~a ~a[~d] for ~d ~a"
  +                (name-of self)
  +                (vnum-of self)
  +                (name-of obj)
  +                (vnum-of obj)
  +                num
  +                (if (is-npc ch) "NPC" "PC")
  +                (name-of ch)
  +                (if (is-npc ch) (vnum-of ch) (idnum-of ch))
  +                (* cost num)
  +                (currency-desc (currency-of shop)))
  +          (dolist (obj (subseq obj-list 0 num))
  +            (obj-from-char obj)
  +            (obj-to-char obj self)
  +            (unless (or (minusp (damage-of obj)) (minusp (max-dam-of obj)))
  +              (setf (damage-of obj) (max-dam-of obj))))
  +          (when (is-pc ch)
  +            (save-player-to-xml ch)))))))
  +
  +(defun vendor-value-ware (self ch vars shop)
  +  (when (eql (currency-of shop) 'quest-points)
  +    (perform-say-to self ch "I'm not the buying kind.")
  +    (return-from vendor-value-ware))
  +
  +  (when (endp vars)
  +    (send-to-char ch "What do you wish to value?~%")
  +    (return-from vendor-value-ware))
  +
  +  (let* ((obj-str (pop vars))
  +         (obj (first (resolve-alias ch obj-str (carrying-of ch)))))
  +      (unless obj
  +        (send-to-char ch "You don't seem to have any '~a'~%" obj-str)
  +        (return-from vendor-value-ware))
  +
  +      (when (vendor-invalid-buy self ch shop obj)
  +        (return-from vendor-value-ware))
  +
  +      (let ((cost (vendor-get-value obj
  +                                    (markdown-of shop)
  +                                    (cost-modifier-of ch self)
  +                                    (currency-of shop))))
  +        (perform-say-to self ch (format nil "I'll give you ~d ~a for it!"
  +                                        cost
  +                                        (currency-desc (currency-of shop)))))))
  +
   (defun vendor-get-value (obj percent modifier currency)
     "Returns the value of an OBJ, checking for buyability."
     (let ((cost (cost-of obj))
  -        (min-cost (if (= currency 2) 1 100)))
  +        (min-cost (if (eql currency 'qp) 1 100)))
       ;; Adjust cost for wear and tear on a direct percentage basis
       (when (and (/= (damage-of obj) -1)
                  (/= (max-dam-of obj) -1)
  
positive.code:                 (when (minusp (revenue-of shop))
                    (signal 'specparam-error :msg "a negative revenue" :lineno lineno)))
                 ("currency"
                  (let ((currency (assoc value '(("past" 0)
                                                 ("gold" 0)
                                                 ("future" 1)
                                                 ("cash" 1)
                                                 ("qp" 2)
                                                 ("quest" 2))
                                         :test 'string-abbrev)))
                    (unless currency
                      (signal 'specparam-error :msg "invalid currency" :lineno lineno))
  
negative.code:          (when (or (null next-obj)
                     (not (same-obj next-obj obj)))
             (when (or (null vars)
                       (is-alias-of (first vars) (aliases-of obj)))
               (vendor-list-object ch obj
                                   (unless (member (vnum-of obj) (produced-of shop)) counter)
                                   index
  