moving to git.lain.church repo

This commit is contained in:
Ambery Rabbit 2023-09-29 16:32:15 -04:00
parent dc615399c6
commit ad788bbbfd
8 changed files with 207 additions and 1 deletions

View File

@ -1,3 +1,8 @@
# lisp_subdecadence
A Subdecadence generator in Common Lisp
I stole the project structure from [Nyx's gema project](https://git.sr.ht/~nyx_land/cl-gema).
I also learned how to make a lisp project from her repo.
Praise Tokhatto.

3
TODO.txt Normal file
View File

@ -0,0 +1,3 @@
TODO: highlight pairs/choices
TODO: matrix of associations with lemurs

7
make.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
if command -v cl-launch; then
cl-launch -o subdec -d ! -Q -s subdecadence -r "subd::main"
else
echo "idk what I'm doing"
fi

5
src/main.lisp Normal file
View File

@ -0,0 +1,5 @@
(in-package #:subdecadence.main)
(defun main ()
(let ((g (make-instance 'aeon)))
(play-aeon g)))

21
src/package.lisp Normal file
View File

@ -0,0 +1,21 @@
(defpackage #:subdecadence.utilities
(:use :cl)
(:export :+base-deck+ :remove-nth :strip-suit
:diff :display-cross :shuffle))
(defpackage #:subdecadence.core
(:use :cl)
(:export :aeon :play-aeon))
(defpackage #:subdecadence.main
(:use :cl :subdecadence.core)
(:export :main))
(defpackage #:subdecadence
(:nicknames :subd)
(:use :cl
:subdecadence.utilities
:subdecadence.core
:subdecadence.main))
(in-package #:subdecadence)

92
src/subdecadence.lisp Normal file
View File

@ -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)))))

63
src/utilities.lisp Normal file
View File

@ -0,0 +1,63 @@
(in-package #:subdecadence.utilities)
;;; base-deck is the unshuffled deck
;;; ♣ / C = Mj+
;;; ♠ / S = Mj-
;;; ♥ / H = Mn+
;;; ♦ / D = Mn-
(defvar +base-deck+
'("0♠" "0♣" "0♥" "0♦"
"1♠" "1♣" "1♥" "1♦"
"2♠" "2♣" "2♥" "2♦"
"3♠" "3♣" "3♥" "3♦"
"4♠" "4♣" "4♥" "4♦"
"5♠" "5♣" "5♥" "5♦"
"6♠" "6♣" "6♥" "6♦"
"7♠" "7♣" "7♥" "7♦"
"8♠" "8♣" "8♥" "8♦"
"9♠" "9♣" "9♥" "9♦"))
(defun remove-nth (seq n)
"Remove the n-th element from the sequence `seq', returns a new sequence with the desired result, the function doesnt modify `seq'"
(unless (typep seq 'list) (error "Type error: seq must be a sequence."))
(unless (typep n 'fixnum) (error "Type error: n must be a fixnum."))
(remove-if #'identity seq :start n :count 1))
(defun strip-suit (card)
(unless (typep card 'string) (error "Type error: card must be a string."))
"Return the integer at the beginning of a card."
(parse-integer (subseq card 0 1)))
(defun diff (x y)
(unless (typep x 'fixnum) (error "Type error: x must be a fixnum."))
(unless (typep y 'fixnum) (error "Type error: y must be a fixnum."))
(abs (- x y)))
(defun display-cross (set)
"Display 5 elements in Atlantean cross."
(unless (typep set 'list) (error "Type error: set must be a list."))
(format t "
~A
~A ~A
~A
~A
"
(elt set 3)
(elt set 2)
(elt set 1)
(elt set 0)
(elt set 4)))
(defun shuffle (deck)
"Shuffle a list."
(unless (typep deck 'list) (error "Type error: deck must be a list."))
(loop for i from (length deck) downto 2
do (rotatef (elt deck (random i (make-random-state t)))
(elt deck (1- i))))
deck)

10
subdecadence.asd Normal file
View File

@ -0,0 +1,10 @@
(asdf:defsystem "subdecadence"
:description "Automated subdecadence games in Common Lisp."
:author "Ambery Rabbit"
:version "0.4.2"
:components
((:module "src"
:components ((:file "package")
(:file "utilities")
(:file "subdecadence")
(:file "main")))))