about summary refs log tree commit diff stats
path: root/loot.lsp
blob: 4dfb2c81f8ff4ee23c32fbc7c185ea6828d6ce4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
;;; Port of https://en.wikipedia.org/wiki/ModernPascal#Code_Sample[3].
;;; And then to CL and ISLisp.
;;; I prefer my version.
(defconstant +max-probability+ 1000)
;; Because this is a simple enum and not a full sum/product type,
;; I use symbols instead of CLOS.
(defconstant +loot-type+ #(bloodstone copper emeraldite gold
                           heronite platinum shadownite silver
                           soranite umbrarite cobalt iron
                           nothing))
(defclass <looter> () ((probabilities :accessor probabilities)))
(defgeneric choose (self))
(defmethod choose ((self <looter>))
   (let ((random-value (random (- +max-probability+ 1))))
	(for ((loop 0 (+ loop 1)))
	     ((>= (elt (probabilities self) (mod loop 13)) random-value) (elt +loot-type+ (mod loop 13))))))
(defmethod initialize-object :after ((self <looter>) initargs)
   (setf (probabilities self) (vector 10 77 105 125 142 159 172 200 201 202 216 282 +max-probability+)))
(defun as-string (l)
   ;; Could use assoc here, but this is closer to the original.
   ;; Also saves translating nil to "".
   (case l
	 ((bloodstone) "Bloodstone")
	 ((copper) "Copper")
	 ((emeraldite) "Emeraldite")
	 ((gold) "Gold")
	 ((heronite) "Heronite")
	 ((platinum) "Platinum")
	 ((shadownite) "Shadownite")
	 ((silver) "Silver")
	 ((soranite) "Soranite")
	 ((umbrarite) "Umbrarite")
	 ((cobalt) "Cobalt")
	 ((iron) "Iron")
	 (t "")))
(defun main ()
   (let ((loot (create (class <looter>))))
	(for ((n 0 (+ n 1)))
             ((> n 99))
	     (format (standard-output) "~A~%" (as-string (choose loot))))))
(main)