diff options
| author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-02-22 23:00:17 +0000 | 
|---|---|---|
| committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-02-22 23:00:17 +0000 | 
| commit | a80b64b045fec86b8475cc11c3d21c2548d1ff5f (patch) | |
| tree | d9de7816cca8a5f1ea4c42d36e7bdec44ec63e1d | |
| parent | 62f92114ee2d69bfb46084cc960a5c182f32df94 (diff) | |
| download | cantedraw-a80b64b045fec86b8475cc11c3d21c2548d1ff5f.tar.gz cantedraw-a80b64b045fec86b8475cc11c3d21c2548d1ff5f.tar.bz2 cantedraw-a80b64b045fec86b8475cc11c3d21c2548d1ff5f.zip  | |
Make card a structure
Card is a structure instead of just a type.  Stronger type checking,
automatic constructor, destructors and existence check.
| -rw-r--r-- | packages.lisp | 8 | ||||
| -rw-r--r-- | src/model.lisp | 66 | 
2 files changed, 38 insertions, 36 deletions
diff --git a/packages.lisp b/packages.lisp index 2f693fd..a6db383 100644 --- a/packages.lisp +++ b/packages.lisp @@ -40,16 +40,18 @@    (:use :cl :5d-lib.macros :5d-lib.functions)    (:export     ;; Types -   :int-card :rank :suit :card :cardset +   :int-card :rank :suit :cardset +   ;; card struct +   :card :make-card :card-suit :card-rank :card-p     ;; Converters     :int->suit :int->rank :int->card     :suit->int :rank->int :card->int     ;; Comparators     :suit< :rank< :card<     ;; Serialisers -   :suit->str :rank->str :card->str :cardset->str +   :suit->str :rank->str :cardset->str     ;; Constructors -   :make-joker :make-deck)) +   :make-deck))  (defpackage cantedraw.player    (:nicknames :5d.player) diff --git a/src/model.lisp b/src/model.lisp index ffa1a4a..002e4f9 100644 --- a/src/model.lisp +++ b/src/model.lisp @@ -26,16 +26,18 @@  (deftype suit ()    `(member :Diamonds :Clubs :Hearts :Spades :Joker)) -(deftype card () `(cons rank suit)) +(defstruct card +  (rank :Ace   :type rank) +  (suit :Joker :type suit))  (deftype int-card () `(integer 0 51))  (deftype cardset () `(and list (satisfies cardsetp)))  (fn cardsetp (lst) (-> (list) boolean) -  (every #'(lambda (x) (typep x 'card)) lst)) +  (every #'card-p lst)) -(fn int->suit (n) (-> (int-card) suit) +(fn int->suit (n) (-> (fixnum) suit)    (case (floor n 13)      (0 :Diamonds)      (1 :Clubs) @@ -51,7 +53,7 @@      (:Spades   3)      (t         4))) -(fn int->rank (n) (-> (int-card) rank) +(fn int->rank (n) (-> (fixnum) rank)    (let ((n (mod n 13)))      (case n        (9 :Jack) @@ -68,15 +70,17 @@      (:Ace    12)      (t      (- rank 2)))) -(fn int->card (num) (-> (int-card) card) -  (cons (int->rank num) -        (int->suit num))) +(fn int->card (num) (-> (fixnum) card) +  (make-card :rank (int->rank num) +             :suit (int->suit num)))  (fn card->int (card) (-> (card) int-card) -  (destructuring-bind (rank . suit) card -    (->> (suit->int suit) -         (* 13) -         (+ (rank->int rank))))) +  (with-slots ((rank rank) (suit suit)) card +    (let ((rank (rank->int rank)) +          (suit (suit->int suit))) +      (->> suit +           (* 13) +           (+ rank)))))  (fn suit< (s1 s2) (-> (suit suit) boolean)    (< (suit->int s1) (suit->int s2))) @@ -85,16 +89,17 @@    (< (rank->int r1) (rank->int r2)))  (fn card< (c1 c2) (-> (card card) boolean) -  (destructuring-bind ((r1 . s1) (r2 . s2)) (list c1 c2) -    (cond -      ;; Check for jokers! -      ((and (eq s1 :Joker) -            (eq s2 :Joker)) -       (rank< r1 r2)) -      ((eq s1 :Joker) nil) -      ((eq s2 :Joker) t) -      ((eq r1 r2) (suit< s1 s2)) -      (t (rank< r1 r2))))) +  (with-slots ((r1 rank) (s1 suit)) c1 +    (with-slots ((r2 rank) (s2 suit)) c2 +      (cond +        ;; Check for jokers! +        ((and (eq s1 :Joker) +              (eq s2 :Joker)) +         (rank< r1 r2)) +        ((eq s1 :Joker) nil) +        ((eq s2 :Joker) t) +        ((eq r1 r2) (suit< s1 s2)) +        (t (rank< r1 r2))))))  (fn suit->str (suit) (-> (suit) string)    (case suit @@ -112,26 +117,21 @@      (:King  "King")      (t      (format nil "~a" rank)))) -(fn card->str (card) (-> (card) string) -  (destructuring-bind (rank . suit) card +(defmethod print-object ((card card) s) +  (with-slots ((rank rank) (suit suit)) card      (if (eq suit :Joker) -        "Joker" -        (format nil "~a[~a]" +        (format s "Joker") +        (format s "~a[~a]"                  (rank->str rank)                  (suit->str suit)))))  (fn cardset->str (cardset) (-> (cardset) string) -  (->> cardset -       (mapcar #'card->str) -       (format nil "~{~a~^, ~}"))) - -(fn make-joker (&optional (rank :ACE)) (-> (&optional rank) card) -  (cons rank :Joker)) +  (format nil "~{~a~^, ~}" cardset))  (fn make-deck (&optional (n 1)) (-> (&optional fixnum) cardset)    (append     (loop :for _ :from 1 :to n           :nconc (loop :for j :from 1 :to 52                        collect (int->card (1- j)))) -   (mapcar ($ x int->rank make-joker) -      (range 0 (* 2 n))))) +   (loop :for _ :from 1 :to (* 2 n) +         :collect (make-card))))  | 
