Guest User

Untitled

a guest
Feb 25th, 2017
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 8.30 KB | None | 0 0
  1. (defun inventory-menu (header)
  2.   "Show a menu with each item of the inventory as an option."
  3.   (let* ((items (loop for item in *inventory*
  4.                    ;; show additional information, in case it's equipped
  5.                    if (and (typep item 'equipment) (is-equipped item))
  6.                    collect (format nil "~a (on ~(~a~))" (name item) (equip-slot item))
  7.                    else collect (name item)))
  8.          (options (if (zerop (length *inventory*))
  9.                       (list "Inventory is empty.")
  10.                       items))
  11.          (index (menu header options *inventory-width*)))
  12.     ;; if an item was chosen, return it
  13.     (if (or (not index) (zerop (length *inventory*)))
  14.         nil
  15.         (nth index *inventory*))))
  16.  
  17. (defun make-rect (x y w h)
  18.   (let ((r (make-instance 'rect :x1 x :y1 y)))
  19.     (setf (x2 r) (+ (x1 r) width)
  20.           (y2 r) (+ (y1 r) height)
  21.           (center r) (cons (floor (/ (+ (x1 r) (x2 r)) 2)) (floor (/ (+ (y1 r) (y2 r)) 2))))
  22.     rect))
  23.  
  24. (defun place-objects (room)
  25.   ;; this is where we decide the chance of each monster or item appearing.
  26.   ;; maximum number of monsters per room
  27.   (let ((objects '())
  28.         (max-monsters (from-dungeon-level '((2 . 1) (3 . 4) (5 . 6))))
  29.         ;; chance of each monster
  30.         ;; orc always shows up, even if all other monsters have 0 chance
  31.         (monster-chances `((:orc . 80)
  32.                            (:troll . ,(from-dungeon-level '(( 15 . 3) (30 . 5) (60 . 7)))))))
  33.     ;; choose random number of monsters
  34.     (dotimes (i (tcod:random-get-int tcod:+null+ 0 max-monsters))
  35.       ;; choose random spot for this monster
  36.       (let ((x (tcod:random-get-int tcod:+null+ (+ (x1 room) 1) (- (x2 room) 1)))
  37.             (y (tcod:random-get-int tcod:+null+ (+ (y1 room) 1) (- (y2 room) 1))))
  38.         (unless (is-blocked x y)
  39.           (let ((monster
  40.                  (case (random-choice monster-chances)
  41.                    (:orc (make-instance 'basic-fighter-monster
  42.                                         :x x :y y :cha #\o :name "orc" :color :pale-green
  43.                                         :blocks t :max-hp 20 :defense 0 :power 4 :xp 35
  44.                                         :death-fun #'monster-death))
  45.                    (:troll (make-instance 'basic-fighter-monster
  46.                                           :x x :y y :cha #\T :name "troll"
  47.                                           :color :dark-sea-green :blocks t :max-hp 30
  48.                                           :defense 2 :power 8 :xp 100
  49.                                           :death-fun #'monster-death)))))
  50.             (push monster objects))))))
  51.  
  52.   ;; maximum number of items per room
  53.   (let ((max-items (from-dungeon-level '((1 . 1) (2 . 4))))
  54.         ;; chance of each item (be default they have a chance of 0 at level 1,
  55.         ;; which then goes up
  56.         ;; healing potion always shows up, even if all other items have 0 chance
  57.         (item-chances `((:heal .      35)
  58.                         (:lightning . ,(from-dungeon-level '((25 . 4))))
  59.                         (:fireball .  ,(from-dungeon-level '((25 . 6))))
  60.                         (:confuse .   ,(from-dungeon-level '((10 . 2))))
  61.                         (:sword .     ,(from-dungeon-level '((5  . 4))))
  62.                         (:shield .    ,(from-dungeon-level '((15 . 8))))))
  63.         (item-stats (list (list :heal :cha #\!
  64.                                 :name "healing potion"
  65.                                 :use-function #'cast-heal
  66.                                 :color :purple
  67.                                 :always-visible t)
  68.                           (list :lightning :cha #\#
  69.                                 :name "scroll of lightning bolt"
  70.                                 :use-function #'cast-lightning
  71.                                 :color :light-yellow
  72.                                 :always-visible t)
  73.                           (list :fireball :cha #\#
  74.                                 :name "scroll of fireball"
  75.                                 :use-function #'cast-fireball
  76.                                 :color :light-yellow
  77.                                 :always-visible t)
  78.                           (list :confuse :cha #\#
  79.                                 :name "scroll of confusion"
  80.                                 :use-function #'cast-confuse
  81.                                 :color :light-yellow
  82.                                 :always-visible t)
  83.                           (list :sword :cha #\/
  84.                                 :name "sword"
  85.                                 :equip-slot :right-hand
  86.                                 :power-bonus 3
  87.                                 :color :blue
  88.                                 :always-visible t)
  89.                           (list :shield :cha #\[
  90.                                 :name "shield"
  91.                                 :equip-slot :left-hand
  92.                                 :defense-bonus 1
  93.                                 :color :orange
  94.                                 :always-visible t))))
  95.     ;; items appear below other objects
  96.     (loop for i below (tcod:random-get-int tcod:+null+ 0 max-items) ; choose random number of items
  97.        ;; choose random spot for this item
  98.        for x = (tcod:random-get-int tcod:+null+
  99.                                     (+ (x1 room) 1) (- (x2 room) 1))
  100.        for y = (tcod:random-get-int tcod:+null+
  101.                                     (+ (y1 room) 1) (- (y2 room) 1))
  102.        for choice = (random-choice item-chances)
  103.        ;; only place it if the tile is not blocked
  104.        unless (is-blocked x y)
  105.        do (push (apply #'make-item x y (cdr (assoc choice item-stats)))
  106.                 objects))
  107.     (setf *objects* (append (nreverse objects) *objects*))))
  108.  
  109. (defun make-map ()
  110.   ;; the list of objects with just the player
  111.   (setf *objects* (list *player*))
  112.  
  113.   (setf *map* (make-array (list *map-height* *map-width*)))
  114.   (dotimes (i *map-height*)
  115.     (dotimes (j *map-width*)
  116.       (setf (aref *map* i j) (make-instance 'tile :blocked t))))
  117.  
  118.   (let ((rooms (list (make-rect x y w h))))
  119.     (create-room (first rooms))
  120.     (destructuring-bind (new-x . new-y) (center (first rooms))
  121.       (setf (x *player*) new-x
  122.             (y *player*) new-y))
  123.     (loop repeat *max-rooms* do
  124.        ;; random width and height      
  125.          (let* ((w (tcod:random-get-int tcod:+null+ *room-min-size* *room-max-size*))
  126.                 (h (tcod:random-get-int tcod:+null+ *room-min-size* *room-max-size*))
  127.                 ;; random position without going out of the boundaries of the map
  128.                 (x (tcod:random-get-int tcod:+null+ 0 (- *map-width* w 1)))
  129.                 (y (tcod:random-get-int tcod:+null+ 0 (- *map-height* h 1)))
  130.                 (new-room (make-rect x y w h)))
  131.  
  132.            ;; run through the other rooms and see if they intersect with this one
  133.            (unless (some (lambda (r) (intersect new-room r))
  134.                          rooms)
  135.              ;; this means there are no intersections, so this room is valid
  136.  
  137.              (create-room new-room) ; "paint" it to the map's tiles
  138.  
  139.              ;; connect it to the previous room with a tunnel
  140.              (destructuring-bind (new-x . new-y) (center new-room)
  141.                (destructuring-bind (prev-x . prev-y) (center (first rooms))
  142.                  ;; draw a coin (random number that is either 0 or 1)
  143.                  (if (plusp (tcod:random-get-int tcod:+null+ 0 1))
  144.                      (progn ; first move horizontally, then vertically
  145.                        (create-h-tunnel prev-x new-x prev-y)
  146.                        (create-v-tunnel prev-y new-y new-x))
  147.                      (progn ; first move vertically, then horizontally
  148.                        (create-v-tunnel prev-y new-y prev-x)
  149.                        (create-h-tunnel prev-x new-x new-y)))))
  150.  
  151.              ;; add some contents to this room, such as monsters
  152.              (place-objects new-room)
  153.              
  154.              ;; finally, add the new room to the list
  155.              (push new-room rooms))))
  156.     ;; create stairs at the center of the last room
  157.     (destructuring-bind (new-x . new-y) (center (first rooms))
  158.       (setf *stairs* (make-instance 'object :x new-x :y new-y :cha #\>
  159.                                     :name "stairs" :color :white
  160.                                     :always-visible t))
  161.       (push *stairs* *objects*))))
Advertisement
Add Comment
Please, Sign In to add comment