Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;;; Page 40 of Volume 2 Monsters and Treasure of the 1974 edition of
- ;;; Dungeons and Dragons provides rules for randomly generating gems.
- ;;; This Common Lisp script will randomly generate a number of gems
- ;;; according to these rules. If the number is not given on the command-
- ;;; line, then 1000 is assumed.
- ;;; The script prints the number of gems generated, the total value in gp,
- ;;; the sample mean value, and the sample standard deviation.
- ;;; We only expect to see about 3 500,000gp gems generated per 1,000,000
- ;;; runs, so in order to get an accurate value of the mean and sd, I
- ;;; recommend running this script for 1 to 10 million iterations.
- ;;; I wrote this script in response to the post
- ;;; Analysis of OD&D treasure types
- ;;; http://odd74.proboards.com/index.cgi?board=monterstreasure&action=display&thread=7606&page=1
- ;;; I first wrote a Mathematica script to calculate the mean and sd exactly.
- ;;; Then I wrote this Common Lisp simulation to confirm these results.
- ;;; Written by Elisha "aher" Abuyah
- ;;; 2 Feb 2013
- ;;; @ Copyleft All Wrongs Reserved
- ;;; For reproducibility, CLISP always starts with the same random state.
- ;;; So uncomment the next line if you want different random results each
- ;;; time you run this simulation.
- (setq *random-state* (make-random-state t))
- ;;; Get number of repetitions from command-line
- ;;; or default to 1000
- (setf *N*
- (cond
- ((null *ARGS*) 1000)
- (T (parse-integer (first *ARGS*)))))
- ;;; Dice roller
- (defun roll (&optional (ndice 1) (nsides 6) (accum 0))
- (if (>= ndice 1)
- (roll (1- ndice) nsides (+ (random nsides) 1 accum))
- accum))
- (defun get-gem-d100-result ()
- (let ((d100 (roll 1 100)))
- (cond
- ((and (>= d100 1) (<= d100 10)) 1)
- ((and (>= d100 11) (<= d100 25)) 2)
- ((and (>= d100 26) (<= d100 75)) 3)
- ((and (>= d100 76) (<= d100 90)) 4)
- ((and (>= d100 91) (<= d100 100)) 5))))
- (defun get-gem-d6-result (&optional (number-of-ones 0))
- (if (and (= (roll) 1) (< number-of-ones 10)) ; upper limit on how many 1s
- (get-gem-d6-result (1+ number-of-ones))
- number-of-ones))
- (defun gem-category->gp (gem-category)
- (case gem-category
- (1 10)
- (2 50)
- (3 100)
- (4 500)
- (5 1000)
- (6 5000)
- (7 10000)
- (8 25000)
- (9 50000)
- (10 100000)
- (otherwise 500000)))
- (defun get-gem-gp ()
- (gem-category->gp (+ (get-gem-d100-result) (get-gem-d6-result))))
- (defun mean ()
- (/ *X* *N*))
- ;;; See Property #4 at http://www.math.uah.edu/stat/sample/Variance.html
- (defun sample-variance ()
- (let ((M (mean)))
- (- (* (/ 1 (1- *N*)) *X-squared*) (* (/ *N* (1- *N*)) M M))))
- (defun sd ()
- (sqrt (sample-variance)))
- (defvar *X* 0)
- (defvar *X-squared* 0)
- ;;; MAIN LOOP
- (dotimes (n *N*)
- (let ((x (get-gem-gp)))
- (setf *X* (+ x *X*))
- (setf *X-squared* (+ (* x x) *X-squared*))))
- ;;; Print results
- (format t "~&Number of runs ~d~%" *N*)
- (format t "Total value of gems (in gp) ~d~%" *X*)
- (format t "Mean value of gems ~,4F~%" (mean))
- (format t "Standard deviation ~,4F~%" (sd))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement