blob: 6192dbf163b7cd2ba7d8581a246900a27020a94a (
plain) (
tree)
|
|
;;; 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)
|