about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDarren Bane <darren.bane@gmail.com>2020-05-03 13:53:50 +0100
committerDarren Bane <darren.bane@gmail.com>2020-05-03 13:53:50 +0100
commit22f3ff398f1169b05939305bdac804623212132a (patch)
treec6ec66a626737c11a842306c41640fc255683057
parent1e64fdf07c45e0380f759589b7669bb9bf88fea0 (diff)
downloadlsp-22f3ff398f1169b05939305bdac804623212132a.tar.gz
Another small example
-rwxr-xr-xcloot.lisp41
1 files changed, 41 insertions, 0 deletions
diff --git a/cloot.lisp b/cloot.lisp
new file mode 100755
index 0000000..6192dbf
--- /dev/null
+++ b/cloot.lisp
@@ -0,0 +1,41 @@
+;;; Port of https://en.wikipedia.org/wiki/ModernPascal#Code_Sample[3].
+;;; And then to CL.
+;;; 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+ (vector '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))))
+    (do ((loop 0 (+ loop 1)))
+        ((>= (elt (probabilities self) (mod loop 13)) random-value) (elt +loot-type+ (mod loop 13))))))
+(defmethod initialize-instance :after ((self <looter>) &rest 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 (make-instance (find-class '<looter>))))
+    (do ((n 0 (+ n 1)))
+      ((> n 99))
+      (format *standard-output* "~A~%" (as-string (choose loot))))))
+(main)