moving to git.lain.church repo
This commit is contained in:
parent
dc615399c6
commit
ad788bbbfd
@ -1,3 +1,8 @@
|
||||
# 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