|
|
@@ -0,0 +1,92 @@ |
|
|
|
(in-package #:subdecadence.core) |
|
|
|
|
|
|
|
(defclass aeon () |
|
|
|
((deck :accessor deck |
|
|
|
:initform (subd::shuffle |
|
|
|
(copy-list subd::+base-deck+)) |
|
|
|
:type list |
|
|
|
:documentation |
|
|
|
"The deck of cards.") |
|
|
|
|
|
|
|
(cross-set :accessor cross-set |
|
|
|
:initform nil |
|
|
|
:type list |
|
|
|
:documentation |
|
|
|
"The Set-1 cards. They go on the cross.") |
|
|
|
|
|
|
|
(match-set :accessor match-set |
|
|
|
:initform nil |
|
|
|
:type list |
|
|
|
:documentation |
|
|
|
"The Set-2 cards. They are dealt face-down.") |
|
|
|
|
|
|
|
(score :accessor score |
|
|
|
:initform 0 |
|
|
|
:type integer |
|
|
|
:documentation |
|
|
|
"The score for the current draw.") |
|
|
|
|
|
|
|
(total-score :accessor total-score |
|
|
|
:initform 0 |
|
|
|
:type integer |
|
|
|
:documentation |
|
|
|
"The total score for this Aeon.")) |
|
|
|
|
|
|
|
(:documentation "A game of Subdecadence.")) |
|
|
|
|
|
|
|
(defmethod reset-deck ((self aeon)) |
|
|
|
"Create a new deck to continue an Aeon." |
|
|
|
(setf (deck self) (subd::shuffle |
|
|
|
(copy-list subd::+base-deck+)))) |
|
|
|
|
|
|
|
(defmethod draw-sets ((self aeon)) |
|
|
|
"Draw 5 cards for cross-set, 5 for match-set, and update deck." |
|
|
|
(with-slots (deck cross-set match-set) self |
|
|
|
(setf cross-set (subseq deck 0 5)) |
|
|
|
(setf match-set (subseq deck 5 10)) |
|
|
|
(setf deck (nthcdr 10 deck)))) |
|
|
|
|
|
|
|
(defmethod get-match ((self aeon) &key card) |
|
|
|
"Find pairs for a card and calculate score." |
|
|
|
(unless (typep card 'fixnum) (error "Card must be a fixnum.")) |
|
|
|
(with-slots (score match-set) self |
|
|
|
(loop :for match :in match-set |
|
|
|
:for index :from 0 |
|
|
|
:do (setq match (subd::strip-suit match)) |
|
|
|
;; if there's a pair, remove matched card from set to avoid |
|
|
|
:when (= (+ card match) 9) ; interfering with later matches |
|
|
|
:do (setf match-set (subd::remove-nth match-set index)) |
|
|
|
:and :return (setf score ; and add the diff. of pair to score |
|
|
|
(+ score (subd::diff card match))) |
|
|
|
;; otherwise, subtract card # from score |
|
|
|
:finally (setf score (- score card))))) |
|
|
|
|
|
|
|
(defmethod make-matches ((self aeon)) |
|
|
|
"Call get-match for every card on the cross." |
|
|
|
(with-slots (cross-set match-set) self |
|
|
|
(loop :for card :in cross-set |
|
|
|
:do (get-match self :card (subd::strip-suit card))))) |
|
|
|
|
|
|
|
(defmethod play-draw ((self aeon)) |
|
|
|
"Play a single draw of an Aeon." |
|
|
|
(with-slots (cross-set match-set score) self |
|
|
|
(draw-sets self) |
|
|
|
(subd::display-cross cross-set) |
|
|
|
(format t "~A~%~%" match-set) |
|
|
|
(make-matches self) |
|
|
|
(format t "Score: ~A~%" score))) |
|
|
|
|
|
|
|
(defmethod play-aeon ((self aeon)) |
|
|
|
"Play a single Aeon." |
|
|
|
(play-draw self) |
|
|
|
(with-slots (total-score score deck) self |
|
|
|
(unless deck |
|
|
|
(reset-deck self)) |
|
|
|
|
|
|
|
(setf total-score (+ total-score score)) |
|
|
|
(format t "Total Score: ~A~%" total-score) |
|
|
|
|
|
|
|
(when (> score 0) |
|
|
|
(progn |
|
|
|
(setf score 0) |
|
|
|
(play-aeon self))))) |