Paste number 46964: traveller world generation

Paste number 46964: traveller world generation
Pasted by: adeht
When:2 years, 5 months ago
Share:Tweet this! | http://paste.lisp.org/+108K
Channel:None
Paste contents:
Raw Source | XML | Display As
(defun roll-die (sides)
  (1+ (random sides)))

(set-dispatch-macro-character
 #\# #\d
 (lambda (stream char times)
   (declare (ignore char))
   (let ((sides (read stream t nil t))
         (times (or times 1)))
     `(loop repeat ,times summing (roll-die ,sides)))))

(defmacro generate-world (&rest rules)
  `(let* ,(loop for (name . rest) in rules
                for arrow = (member '-> rest)
                for body = (cdr arrow)
                for transform = (car (ldiff rest arrow))
                collect `(,name ,@(if transform
                                      `((funcall ,transform ,@body))
                                      body)))
     (list ,@(mapcar #'car rules))))

(defun range (&key from to)
  (lambda (value)
    (when (numberp value)
      (min to (max from value)))))

(defun in-range (value &key from to)
  (and (numberp value)
       (<= from value to)))

(defun choose (n list)
  (nth (1- n) list))

(defun table (alist key)
  (or (cdr (assoc key alist))
      (error "Can't find key ~S in table ~S." key alist)))

(defun collecting (&rest values)
  (remove nil values))

(defparameter *starport-tech*
  '((A . 6)
    (B . 4)
    (C . 2)
    (D . 0)
    (E . 0)
    (X . -4)))

(defparameter *government-tech*
  '((0  . 1)
    (1  . 0)
    (2  . 0)
    (3  . 0)
    (4  . 0)
    (5  . 1)
    (6  . 0)
    (7  . 0)
    (8  . 0)
    (9  . 0)
    (10 . 1)
    (11 . 1)
    (12 . 1)
    (13 . -2)))

(defun my-worlds-generator ()
  (generate-world
   (starport                             -> (choose (1- #2d6) '(A A A B B C C D E E X)))
   (size (range :from 0 :to 10)          -> (- #2d6 2))
   (atmosphere (range :from 0 :to 12)    -> (if (= 0 size) 0 (+ #2d6 -7 size)))
   (hydrographics (range :from 0 :to 10) -> (if (= 0 size)
                                                0
                                                (+ #2d6 -7 atmosphere
                                                   (if (in-range atmosphere :from 3 :to 8)
                                                       -4
                                                       0))))
   (population (range :from 0 :to 10)    -> (- #2d6 2))
   (government (range :from 0 :to 13)    -> (+ #2d6 -7 population))
   (law (range :from 0 :to 9)            -> (+ #2d6 -7 government))
   (dash                                 -> '-)
   (tech-level                           -> (+ #1d6
                                               (table *starport-tech* starport)
                                               (choose (1+ size) '(2 2 1 1 1 0 0 0 0 0 0))
                                               (choose (1+ atmosphere) '(1 1 1 1 0 0 0 0 0 0 1 1 1))
                                               (choose (1+ hydrographics) '(0 0 0 0 0 0 0 0 0 1 2))
                                               (choose (1+ population) '(0 1 1 1 1 1 0 0 0 2 4))
                                               (table *government-tech* government)))
   (naval-base                           -> (choose (1- #2d6) '(~ ~ ~ ~ ~ ~ N N N N N)))
   (scout-base                           -> (choose (1- #2d6) '(~ ~ ~ ~ ~ S S S S S S)))
   (gas-giant                            -> (choose (1- #2d6) '(G G G G G G G G ~ ~ ~)))
   (trade-codes                          -> (collecting
                                             (and (in-range atmosphere :from 4 :to 9)
                                                  (in-range hydrographics :from 4 :to 8)
                                                  (in-range population :from 5 :to 7)
                                                  'Ag)
                                             (and (<= atmosphere 3)
                                                  (<= hydrographics 3)
                                                  (>= population 6)
                                                  'Na)
                                             (and (member atmosphere '(0 1 2 4 7 9))
                                                  (>= population 9)
                                                  'In)
                                             (and (<= population 6)
                                                  'Ni)
                                             (and (in-range government :from 4 :to 9)
                                                  (member atmosphere '(6 8))
                                                  (in-range population :from 6 :to 8)
                                                  'Ri)
                                             (and (in-range atmosphere :from 2 :to 5)
                                                  (<= hydrographics 3)
                                                  'Po)
                                             (and (= 10 hydrographics)
                                                  'Wa)
                                             (and (= 0 hydrographics)
                                                  'De)
                                             (and (= 0 atmosphere)
                                                  'Va)
                                             (and (= 0 size)
                                                  'As)
                                             (and (member atmosphere '(0 1))
                                                  (>= hydrographics 1)
                                                  'Ic)))))  

This paste has no annotations.

Colorize as:
Show Line Numbers

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.