Advertisement
aher

gems.lsp

Feb 7th, 2013
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 3.07 KB | None | 0 0
  1. ;;; Page 40 of Volume 2 Monsters and Treasure of the 1974 edition of
  2. ;;; Dungeons and Dragons provides rules for randomly generating gems.
  3. ;;; This Common Lisp script will randomly generate a number of gems
  4. ;;; according to these rules. If the number is not given on the command-
  5. ;;; line, then 1000 is assumed.
  6.  
  7. ;;; The script prints the number of gems generated, the total value in gp,
  8. ;;; the sample mean value, and the sample standard deviation.
  9.  
  10. ;;; We only expect to see about 3 500,000gp gems generated per 1,000,000
  11. ;;; runs, so in order to get an accurate value of the mean and sd, I
  12. ;;; recommend running this script for 1 to 10 million iterations.
  13.  
  14. ;;; I wrote this script in response to the post
  15. ;;; Analysis of OD&D treasure types
  16. ;;; http://odd74.proboards.com/index.cgi?board=monterstreasure&action=display&thread=7606&page=1
  17.  
  18. ;;; I first wrote a Mathematica script to calculate the mean and sd exactly.
  19. ;;; Then I wrote this Common Lisp simulation to confirm these results.
  20.  
  21. ;;; Written by Elisha "aher" Abuyah
  22. ;;; 2 Feb 2013
  23. ;;; @ Copyleft All Wrongs Reserved
  24.  
  25. ;;; For reproducibility, CLISP always starts with the same random state.
  26. ;;; So uncomment the next line if you want different random results each
  27. ;;; time you run this simulation.
  28. (setq *random-state* (make-random-state t))
  29.  
  30. ;;; Get number of repetitions from command-line
  31. ;;; or default to 1000
  32. (setf *N*
  33.   (cond
  34.     ((null *ARGS*) 1000)
  35.     (T (parse-integer (first *ARGS*)))))
  36.  
  37. ;;; Dice roller
  38. (defun roll (&optional (ndice 1) (nsides 6) (accum 0))
  39.   (if (>= ndice 1)
  40.     (roll (1- ndice) nsides (+ (random nsides) 1 accum))
  41.     accum))
  42.  
  43. (defun get-gem-d100-result ()
  44.   (let ((d100 (roll 1 100)))
  45.     (cond
  46.       ((and (>= d100  1) (<= d100  10)) 1)
  47.       ((and (>= d100 11) (<= d100  25)) 2)
  48.       ((and (>= d100 26) (<= d100  75)) 3)
  49.       ((and (>= d100 76) (<= d100  90)) 4)
  50.       ((and (>= d100 91) (<= d100 100)) 5))))
  51.  
  52. (defun get-gem-d6-result (&optional (number-of-ones 0))
  53.   (if (and (= (roll) 1) (< number-of-ones 10)) ; upper limit on how many 1s
  54.     (get-gem-d6-result (1+ number-of-ones))
  55.     number-of-ones))
  56.  
  57. (defun gem-category->gp (gem-category)
  58.   (case gem-category
  59.     (1 10)
  60.     (2 50)
  61.     (3 100)
  62.     (4 500)
  63.     (5 1000)
  64.     (6 5000)
  65.     (7 10000)
  66.     (8 25000)
  67.     (9 50000)
  68.     (10 100000)
  69.     (otherwise 500000)))
  70.  
  71. (defun get-gem-gp ()
  72.   (gem-category->gp (+ (get-gem-d100-result) (get-gem-d6-result))))
  73.  
  74. (defun mean ()
  75.   (/ *X* *N*))
  76.  
  77. ;;; See Property #4 at http://www.math.uah.edu/stat/sample/Variance.html
  78. (defun sample-variance ()
  79.   (let ((M (mean)))
  80.     (- (* (/ 1 (1- *N*)) *X-squared*) (* (/ *N* (1- *N*)) M M))))
  81.  
  82. (defun sd ()
  83.   (sqrt (sample-variance)))
  84.  
  85. (defvar *X* 0)
  86. (defvar *X-squared* 0)
  87.  
  88. ;;; MAIN LOOP
  89. (dotimes (n *N*)
  90.     (let ((x (get-gem-gp)))
  91.       (setf *X* (+ x *X*))
  92.       (setf *X-squared* (+ (* x x) *X-squared*))))
  93.  
  94. ;;; Print results
  95. (format t "~&Number of runs ~d~%" *N*)
  96. (format t "Total value of gems (in gp) ~d~%" *X*)
  97. (format t "Mean value of gems ~,4F~%" (mean))
  98. (format t "Standard deviation ~,4F~%" (sd))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement