anchor.diff:    (princ ", and a strength of ")
     (princ *player-strength*))
   
  +;; monster class
  +(defstruct monster (health (randval 10)))
  +
  +(defun monster-dead (m)
  +  (<= (monster-health m) 0))
  +
  +(defun monsters-dead ()
  +  (every #'monster-dead *monsters*))
  +
  +(defmethod monster-hit (m x)
  +  (decf (monster-health m) x)
  +  (if (monster-dead m)
  +      (progn (princ "You killed the ")
  +             (princ (type-of m))
  +             (princ "! "))
  +      (progn (princ "You hit the ")
  +             (princ (type-of m))
  +             (princ ", knocking off ")
  +             (princ x)
  +             (princ " health points! "))))
  +
  +(defmethod monster-show (m)
  +  (princ "A fierce ")
  +  (princ (type-of m)))
  +
  +(defmethod monster-attack (m))
  +
  +(defun random-monster ()
  +  (let ((m (aref *monsters* (random (length *monsters*)))))
  +    (if (monster-dead m)
  +        (random-monster)
  +        m)))
  +
  +(defun pick-monster ()
  +  (fresh-line)
  +  (princ "Monster #:")
  +  (finish-output nil)
  +  (let ((x (read)))
  +    (if (not (and (integerp x) (>= x 1) (<= x *monster-num*)))
  +        (progn (princ "That is not a valid monster number.")
  +               (pick-monster))
  +        (let ((m (aref *monsters* (1- x))))
  +          (if (monster-dead m)
  +              (progn (princ "That monster is alread dead.")
  +                     (pick-monster))
  +              m)))))
  +
  +(defun show-monsters ()
  +  (fresh-line)
  +  (princ "Your foes:")
  +  (let ((x 0))
  +    (map 'list
  +         (lambda (m)
  +             (fresh-line)
  +             (princ "    ")
  +             (princ (incf x))
  +             (princ ". ")
  +             (if (monster-dead m)
  +                 (princ "**dead**")
  +                 (progn (princ "(Health=")
  +                         (princ (monster-health m))
  +                         (princ ") ")
  +                         (monster-show m))))
  +         *monsters*)))
  +
  +;; orc
  +
  +(defstruct (orc (:include monster)) (club-level (randval 8)))
  +(push #'make-orc *monster-builders*)
  +
  +(defmethod monster-show ((m orc))
  +  (princ "A wicked orc with a level ")
  +  (princ (orc-club-level m))
  +  (princ " club"))
  +
  +(defmethod monster-attack ((m orc))
  +  (let ((x (randval (orc-club-level m))))
  +       (princ "An orc swings his club at you and knocks off ")
  +       (princ x)
  +       (princ " of your health points. ")
  +       (decf *player-health* x)))
  +
  +;; hydra
  +
  +(defstruct (hydra (:include monster)))
  +(push #'make-hydra *monster-builders*)
  +
  +(defmethod monster-show ((m hydra))
  +  (princ "A malicious hydra with ")
  +  (princ (monster-health m))
  +  (princ " heads."))
  +
  +(defmethod monster-hit ((m hydra) x)
  +  (decf (monster-health m) x)
  +  (if (monster-dead m)
  +      (princ "The corpse of the fully decapitated and decapacitated hydra
  +falls to the floor!")
  +      (progn (princ "You lop off ")
  +              (princ x)
  +              (princ " of the hydra's heads! "))))
  +
  +(defmethod monster-attack ((m hydra))
  +  (let ((x (randval (ash (monster-health m) -1))))
  +    (princ "A hydra attacks you with ")
  +    (princ x)
  +    (princ " of its heads! It also grows back one more head! ")
  +    (incf (monster-health m))
  +    (decf *player-health* x)))
  +
  +;; slime mold
  +
  +(defstruct (slime-mold (:include monster)) (sliminess (randval 5)))
  +(push #'make-slime-mold *monster-builders*)
  +
  +(defmethod monster-show ((m slime-mold))
  +  (princ "A slime mold with a sliminess of ")
  +  (princ (slime-mold-sliminess m)))
  +
  +(defmethod monster-attack ((m slime-mold))
  +  (let ((x (randval (slime-mold-sliminess m))))
  +       (princ "A slime mold wraps around your legs and decreases your agility
  +by ")
  +       (princ x)
  +       (princ "! ")
  +       (decf *player-agility* x)
  +       (when (zerop (random 2))
  +         (princ "It also squirts in your face, taking away a health point! ")
  +         (decf *player-health*))))
  +
  +;; brigand
  +
  +(defstruct (brigand (:include monster)))
  +(push #'make-brigand *monster-builders*)
  +
  +(defmethod monster-attack ((m brigand))
  +  (let ((x (max *player-health* *player-agility* *player-strength*)))
  +    (cond ((= x *player-health*)
  +           (princ "A brigand hits you with his slingshot, taking off 2 health
  +points! ")
  +           (decf *player-health* 2))
  +          ((= x *player-agility*)
  +           (princ "A brigand catches your leg with his whip, taking off 2
  +agility points! ")
  +           (decf *player-agility* 2))
  +          ((= x *player-strength*)
  +           (princ "A brigand cuts your arm with his whip, taking off 2
  +strength points! ")
  +           (decf *player-strength* 2)))))
  +
  +;; turn function
   (defun player-attack ()
     (fresh-line)
     (princ "Attack style: [s]tab [d]ouble swing [r]oundhouse:")
  
positive.code:                  (unless (monsters-dead)
                     (monster-hit (random-monster) 1))))))
  
  (defun random-monster ()
    (let ((m (aref *monsters* (random (length *monsters*)))))
      (if (monster-dead m)
          (random-monster)
          m)))
  
  (defun pick-monster ()
    (fresh-line)
    (princ "Monster #:")
    (finish-output nil)
    (let ((x (read)))
      (if (not (and (integerp x) (>= x 1) (<= x *monster-num*)))
          (progn (princ "That is not a valid monster number.")
                 (pick-monster))
          (let ((m (aref *monsters* (1- x))))
            (if (monster-dead m)
                (progn (princ "That monster is alread dead.")
                       (pick-monster))
                m)))))
  
  (defun init-monsters ()
    (setf *monsters*
          (map 'vector
               (lambda (x)
                 (funcall (nth (random (length *monster-builders*))
                           *monster-builders*)))
               (make-array *monster-num*))))
  
  (defun monster-dead (m)
    (<= (monster-health m) 0))
  (defun monsters-dead ()
    (every #'monster-dead *monsters*))
  
  (defun show-monsters ()
    (fresh-line)
    (princ "Your foes:")
    (let ((x 0))
      (map 'list
           (lambda (m)
               (fresh-line)
               (princ "    ")
               (princ (incf x))
               (princ ". ")
               (if (monster-dead m)
                   (princ "**dead**")
                   (progn (princ "(Health=")
                           (princ (monster-health m))
                           (princ ") ")
                           (monster-show m))))
           *monsters*)))
  
  (defstruct monster (health (randval 10)))
  
  (defmethod monster-hit (m x)
    (decf (monster-health m) x)
    (if (monster-dead m)
        (progn (princ "You killed the ")
               (princ (type-of m))
               (princ "! "))
        (progn (princ "You hit the ")
               (princ (type-of m))
               (princ ", knocking off ")
               (princ x)
               (princ " health points! "))))
  
  (defmethod monster-show (m)
    (princ "A fierce ")
    (princ (type-of m)))
  
  (defmethod monster-attack (m))
  
  (defstruct (orc (:include monster)) (club-level (randval 8)))
  (push #'make-orc *monster-builders*)
  
  (defmethod monster-show ((m orc))
    (princ "A wicked orc with a level ")
    (princ (orc-club-level m))
    (princ " club"))
  
  (defmethod monster-attack ((m orc))
    (let ((x (randval (orc-club-level m))))
         (princ "An orc swings his club at you and knocks off ")
         (princ x)
         (princ " of your health points. ")
         (decf *player-health* x)))
  
  (defstruct (hydra (:include monster)))
  (push #'make-hydra *monster-builders*)
  
  (defmethod monster-show ((m hydra))
    (princ "A malicious hydra with ")
    (princ (monster-health m))
    (princ " heads."))
  
  (defmethod monster-hit ((m hydra) x)
    (decf (monster-health m) x)
    (if (monster-dead m)
        (princ "The corpse of the fully decapitated and decapacitated hydra
  falls to the floor!")
        (progn (princ "You lop off ")
                (princ x)
                (princ " of the hydra's heads! "))))
  
  (defmethod monster-attack ((m hydra))
    (let ((x (randval (ash (monster-health m) -1))))
      (princ "A hydra attacks you with ")
      (princ x)
      (princ " of its heads! It also grows back one more head! ")
      (incf (monster-health m))
      (decf *player-health* x)))
  
  (defstruct (slime-mold (:include monster)) (sliminess (randval 5)))
  (push #'make-slime-mold *monster-builders*)
  
  (defmethod monster-show ((m slime-mold))
    (princ "A slime mold with a sliminess of ")
    (princ (slime-mold-sliminess m)))
  
  (defmethod monster-attack ((m slime-mold))
    (let ((x (randval (slime-mold-sliminess m))))
         (princ "A slime mold wraps around your legs and decreases your agility
  by ")
         (princ x)
         (princ "! ")
         (decf *player-agility* x)
         (when (zerop (random 2))
           (princ "It also squirts in your face, taking away a health point! ")
           (decf *player-health*))))
  
  (defstruct (brigand (:include monster)))
  (push #'make-brigand *monster-builders*)
  
  (defmethod monster-attack ((m brigand))
    (let ((x (max *player-health* *player-agility* *player-strength*)))
      (cond ((= x *player-health*)
             (princ "A brigand hits you with his slingshot, taking off 2 health
  points! ")
             (decf *player-health* 2))
            ((= x *player-agility*)
             (princ "A brigand catches your leg with his whip, taking off 2
  agility points! ")
             (decf *player-agility* 2))
            ((= x *player-strength*)
             (princ "A brigand cuts your arm with his whip, taking off 2
  strength points! ")
             (decf *player-strength* 2)))))
  
  
negative.code: ;;; orc-battle.lisp --- an epic battle
  
  (defpackage :net.raydeejay.orc-battle
    (:use :cl)
    (:export :start))
  
  (in-package :net.raydeejay.orc-battle)
  
  (defvar *player-health* nil)
  (defvar *player-agility* nil)
  (defvar *player-strength* nil)
  
  (defvar *monsters* nil)
  (defvar *monster-builders* nil)
  (defvar *monster-num* 12)
  
  ;; a little helper function
  (defun randval (n)
    (1+ (random (max 1 n))))
  
  ;; player related functions
  (defun init-player ()
    (setf *player-health* 30)
    (setf *player-agility* 30)
  