A Subdecadence generator in Common Lisp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.7KB

  1. (in-package #:subdecadence.core)
  2. (defclass aeon ()
  3. ((deck :accessor deck
  4. :initform (subd::shuffle
  5. (copy-list subd::+base-deck+))
  6. :type list
  7. :documentation
  8. "The deck of cards.")
  9. (cross-set :accessor cross-set
  10. :initform nil
  11. :type list
  12. :documentation
  13. "The Set-1 cards. They go on the cross.")
  14. (match-set :accessor match-set
  15. :initform nil
  16. :type list
  17. :documentation
  18. "The Set-2 cards. They are dealt face-down.")
  19. (score :accessor score
  20. :initform 0
  21. :type integer
  22. :documentation
  23. "The score for the current draw.")
  24. (total-score :accessor total-score
  25. :initform 0
  26. :type integer
  27. :documentation
  28. "The total score for this Aeon."))
  29. (:documentation "A game of Subdecadence."))
  30. (defmethod reset-deck ((self aeon))
  31. "Create a new deck to continue an Aeon."
  32. (setf (deck self) (subd::shuffle
  33. (copy-list subd::+base-deck+))))
  34. (defmethod draw-sets ((self aeon))
  35. "Draw 5 cards for cross-set, 5 for match-set, and update deck."
  36. (with-slots (deck cross-set match-set) self
  37. (setf cross-set (subseq deck 0 5))
  38. (setf match-set (subseq deck 5 10))
  39. (setf deck (nthcdr 10 deck))))
  40. (defmethod get-match ((self aeon) &key card)
  41. "Find pairs for a card and calculate score."
  42. (unless (typep card 'fixnum) (error "Card must be a fixnum."))
  43. (with-slots (score match-set) self
  44. (loop :for match :in match-set
  45. :for index :from 0
  46. :do (setq match (subd::strip-suit match))
  47. ;; if there's a pair, remove matched card from set to avoid
  48. :when (= (+ card match) 9) ; interfering with later matches
  49. :do (setf match-set (subd::remove-nth match-set index))
  50. :and :return (setf score ; and add the diff. of pair to score
  51. (+ score (subd::diff card match)))
  52. ;; otherwise, subtract card # from score
  53. :finally (setf score (- score card)))))
  54. (defmethod make-matches ((self aeon))
  55. "Call get-match for every card on the cross."
  56. (with-slots (cross-set match-set) self
  57. (loop :for card :in cross-set
  58. :do (get-match self :card (subd::strip-suit card)))))
  59. (defmethod play-draw ((self aeon))
  60. "Play a single draw of an Aeon."
  61. (with-slots (cross-set match-set score) self
  62. (draw-sets self)
  63. (subd::display-cross cross-set)
  64. (format t "~A~%~%" match-set)
  65. (make-matches self)
  66. (format t "Score: ~A~%" score)))
  67. (defmethod play-aeon ((self aeon))
  68. "Play a single Aeon."
  69. (play-draw self)
  70. (with-slots (total-score score deck) self
  71. (unless deck
  72. (reset-deck self))
  73. (setf total-score (+ total-score score))
  74. (format t "Total Score: ~A~%" total-score)
  75. (when (> score 0)
  76. (progn
  77. (setf score 0)
  78. (play-aeon self)))))