Просмотр исходного кода

moving to git.lain.church repo

master
Ambery Rabbit 7 месяцев назад
Родитель
Сommit
ad788bbbfd
8 измененных файлов: 207 добавлений и 1 удалений
  1. +6
    -1
      README.md
  2. +3
    -0
      TODO.txt
  3. +7
    -0
      make.sh
  4. +5
    -0
      src/main.lisp
  5. +21
    -0
      src/package.lisp
  6. +92
    -0
      src/subdecadence.lisp
  7. +63
    -0
      src/utilities.lisp
  8. +10
    -0
      subdecadence.asd

+ 6
- 1
README.md Просмотреть файл

@@ -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
- 0
TODO.txt Просмотреть файл

@@ -0,0 +1,3 @@

TODO: highlight pairs/choices
TODO: matrix of associations with lemurs

+ 7
- 0
make.sh Просмотреть файл

@@ -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
- 0
src/main.lisp Просмотреть файл

@@ -0,0 +1,5 @@
(in-package #:subdecadence.main)

(defun main ()
(let ((g (make-instance 'aeon)))
(play-aeon g)))

+ 21
- 0
src/package.lisp Просмотреть файл

@@ -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
- 0
src/subdecadence.lisp Просмотреть файл

@@ -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
- 0
src/utilities.lisp Просмотреть файл

@@ -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
- 0
subdecadence.asd Просмотреть файл

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

Загрузка…
Отмена
Сохранить