1 files changed, 193 insertions, 0 deletions
diff --git a/rusle.scm b/rusle.scm
new file mode 100644
index 0000000..7f4e31c
--- /dev/null
+++ b/rusle.scm
@@ -0,0 +1,193 @@
+;; rusle - wordle clone in scheme macros
+;; to play: (play (R U L E S))
+;; X: letter in correct spot
+;; +: letter in wrong spot
+;; -: letter not present
+;; scroll to bottom for spoilers
+
+;; using extradimensional manipulation techniques we can fit several pigeons
+;; into a single hole
+(define-syntax fit-pigeon
+ (syntax-rules ()
+ ((fit-pigeon (pigeon ...)
+ (hole ...) (full ...)
+ (outer-hole ...) (outer-full ...)
+ (next next* ...))
+ (next (pigeon ...) (outer-hole ...) (outer-full ... (full ...)) next* ...))))
+
+(define-syntax send-pigeons
+ (syntax-rules ()
+ ((send-pigeons () () holes rest ...)
+ holes)))
+
+;; (continue* (values) (upcoming-symbols) (past-symbols)
+(define-syntax continue*
+ (syntax-rules (<> ->)
+ ((continue* () (hole ...) (full ...) (next next* ...))
+ (next () () (full ... hole ...) next* ...))
+ ((continue* (pigeon ...) () (full ...) (next next* ...))
+ (next (pigeon ...) () (full ...) next* ...))
+ ((continue* (pigeon pigeon* ...) (<> hole ...) (full ...) next)
+ (continue* (pigeon* ...) (hole ...) (full ... pigeon) next))
+ ((continue* (pigeon ...) (-> (hole ...) hole* ...) (full ...) next)
+ (continue* (pigeon ...) (hole ...) ()
+ (fit-pigeon (hole* ...) (full ...) (continue* next))))
+ ((continue* (pigeon ...) (hole hole* ...) (full ...) next)
+ (continue* (pigeon ...) (hole* ...) (full ... hole) next))))
+
+;; hellish continuation passing type guy
+;; (continue (quote <>) 4) -> (quote 4)
+;; (continue (quote -> (<> <>)) foo bar) -> (quote (foo bar))
+(define-syntax continue
+ (syntax-rules (<> ->)
+ ((continue holes pigeons ...)
+ (continue* (pigeons ...) holes () (send-pigeons)))))
+
+;; (alphabetize* list-of-symbols next-replacement output next
+;; (alphabetize* (W O R D L E) (chk chk) () (continuation))
+(define-syntax alphabetize*
+ (syntax-rules ()
+ ((alphabetize* () replacement output next)
+ (continue next output))
+ ((alphabetize* ((sym ...) syms ...) replacement (output ...) next)
+ (alphabetize* (syms ...) replacement (output ... (sym ...)) next))
+ ((alphabetize* (sym syms ...) (replacement ...) (output ...) next)
+ (letrec-syntax
+ ((replace
+ ;; replace (sym sym sym) (outsym outsym) next
+ (syntax-rules ooo (sym)
+ ((replace () outsyms next*)
+ (continue next* outsyms))
+ ((replace (sym syms* ooo) (outsyms ooo) next*)
+ (replace (syms* ooo) (outsyms ooo (replacement ...)) next*))
+ ((replace (sym* syms* ooo) (outsyms ooo) next*)
+ (replace (syms* ooo) (outsyms ooo sym*) next*)))))
+ (replace (syms ...)
+ ()
+ (alphabetize* <>
+ (replacement ... chk)
+ (output ... (replacement ...))
+ next))))))
+
+;; turns an opaque list of letters into a list of actually-manipulable
+;; symbols (just lists of nonsense data where the length of the list
+;; determines what it is)
+;; (alphabetize (P E N I S O U I J A) next)
+(define-syntax alphabetize
+ (syntax-rules ()
+ ((alphabetize syms next)
+ (alphabetize* syms () () next))))
+
+(define-syntax zip*
+ (syntax-rules ()
+ ((zip* () () output next)
+ (continue next output))
+ ((zip* (a a* ...) (b b* ...) (output ...) next)
+ (zip* (a* ...) (b* ...) (output ... a b) next))))
+
+(define-syntax zip
+ (syntax-rules ()
+ ((zip a b next)
+ (zip* a b () next))))
+
+(define-syntax unzip*
+ (syntax-rules ()
+ ((unzip* () a* b* next)
+ (continue next a* b*))
+ ((unzip* (a b rest ...) (a* ...) (b* ...) next)
+ (unzip* (rest ...) (a* ... a) (b* ... b) next))))
+
+(define-syntax unzip
+ (syntax-rules ()
+ ((unzip syms next)
+ (unzip* syms () () next))))
+
+(define-syntax sym-equal
+ (syntax-rules ()
+ ;; if lists are contained within we bail
+ ((sym-equal ((thing ...) thing* ...) whatever yes no)
+ no)
+ ((sym-equal whatever ((thing ...) thing* ...) yes no)
+ no)
+ ((sym-equal (a a* ...) (b b* ...) yes no)
+ (sym-equal (a* ...) (b* ...) yes no))
+ ((sym-equal (a a* ...) () yes no)
+ no)
+ ((sym-equal () (b b* ...) yes no)
+ no)
+ ((sym-equal () () yes no)
+ yes)))
+
+(define-syntax greens*
+ (syntax-rules ()
+ ((greens* () () secret guess next)
+ (continue next secret guess))
+ ((greens* (key key* ...) (hole hole* ...) (secret ...) (guess ...) next)
+ (sym-equal key
+ hole
+ (greens* (key* ...) (hole* ...)
+ (secret ... ((X))) (guess ... ((X))) next)
+ (greens* (key* ...) (hole* ...)
+ (secret ... key) (guess ... hole) next)))))
+
+(define-syntax greens
+ (syntax-rules ()
+ ((greens key hole next)
+ (greens* key hole () () next))))
+
+(define-syntax oranges*
+ (syntax-rules ()
+ ((oranges* () () secret guess next)
+ (continue next guess))
+ ((oranges* (key key* ...) (hole hole* ...) (secret ...) (guess ...) next)
+ (sym-equal key
+ hole
+ (oranges* (key* ...) (guess ... ((+)) hole* ...)
+ (secret ... ((+))) ()
+ next)
+ (oranges* (key key* ...) (hole* ...)
+ (secret ...) (guess ... hole)
+ next)))
+ ((oranges* (key key* ...) () (secret ...) (guess ...) next)
+ (oranges* (key* ...) (guess ...) (secret ... key) () next))
+ ((oranges* () (hole ...) (secret ...) (guess ...) next)
+ (continue next (guess ... hole ...)))))
+
+(define-syntax oranges
+ (syntax-rules ()
+ ((oranges key hole next)
+ (oranges* key hole () () next))))
+
+(define-syntax grays*
+ (syntax-rules ()
+ ((grays* () guess next)
+ (continue next guess))
+ ((grays* (((state)) hole ...) (guess ...) next)
+ (grays* (hole ...) (guess ... state) next))
+ ((grays* (fail hole ...) (guess ...) next)
+ (grays* (hole ...) (guess ... -) next))))
+
+(define-syntax grays
+ (syntax-rules ()
+ ((grays guess next)
+ (grays* guess () next))))
+
+(define-syntax compare
+ (syntax-rules ()
+ ((make-guess secret guess next)
+ (zip secret guess
+ (alphabetize
+ <>
+ (unzip
+ <>
+ (greens <> <> (oranges <> <> (grays <> next)))))))))
+
+(define-syntax make-game
+ (syntax-rules ()
+ ((make-game name word)
+ (define-syntax name
+ (syntax-rules ()
+ ((name guess)
+ (compare word guess (quote <>))))))))
+
+(make-game play (F O L L Y))
|