moving to git.lain.church repo
This commit is contained in:
parent
dc615399c6
commit
ad788bbbfd
@ -1,3 +1,8 @@
|
|||||||
# lisp_subdecadence
|
# lisp_subdecadence
|
||||||
|
|
||||||
A Subdecadence generator in Common Lisp
|
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
3
TODO.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
TODO: highlight pairs/choices
|
||||||
|
TODO: matrix of associations with lemurs
|
7
make.sh
Executable file
7
make.sh
Executable 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
5
src/main.lisp
Normal 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
21
src/package.lisp
Normal 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
92
src/subdecadence.lisp
Normal 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
63
src/utilities.lisp
Normal 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
10
subdecadence.asd
Normal 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")))))
|
Loading…
Reference in New Issue
Block a user