;;; wasp-tcg --- trading card game -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: (require 'cl-lib) (require 'ht) (require 'f) (require 'wasp-twitch) (require 'wasp-user) (defconst w/tcg-past-sets '( "Cloaking Device" )) (defconst w/tcg-current-set "Emerald Isle" ) (defconst w/tcg-bases (-map #'f-base (f-entries "/home/llll/src/newton/crates/renderer/src/assets/textures/tcg/bases"))) (cl-defstruct (w/tcg-card (:constructor w/make-tcg-card)) name type depicted-subject element color faction faction-color equity boost-level rarity rarity-level body-text base-image-name set minted-date flags ;; comma-separated strings: inverse, etc. ) (defun w/tcg-determine-rarity () "Return a rarity level." (let ((ret 0)) (while (= (random 2) 0) (cl-incf ret)) ret)) (defun w/tcg-render-rarity (r) "Convert rarity R to a string." (cond ((= 0 r) "C") ((= 1 r) "R") (t (s-concat (s-repeat (- r 1) "S") "R")))) (defun w/tcg-pick-flags (u) "Return flags for the user U." (ignore u) (-concat (when (= (random 20) 0) (list "inverse")))) (defun w/tcg-generate-theme () "Consult the themes table." (let ((result (+ 1 (random 100)))) (cond ((= result 1) "Risk") ((= result 2) "Ability") ((= result 3) "Price") ((= result 4) "Ally") ((= result 5) "Battle") ((= result 6) "Safety") ((= result 7) "Survival") ((= result 8) "Weapon") ((= result 9) "Wound") ((= result 10) "Shelter") ((= result 11) "Leader") ((= result 12) "Fear") ((= result 13) "Time") ((= result 14) "Duty") ((= result 15) "Secret") ((= result 16) "Innocence") ((= result 17) "Renown") ((= result 18) "Direction") ((= result 19) "Death") ((= result 20) "Honor") ((= result 21) "Labor") ((= result 22) "Solution") ((= result 23) "Tool") ((= result 24) "Balance") ((= result 25) "Love") ((= result 26) "Barrier") ((= result 27) "Creation") ((= result 28) "Decay") ((= result 29) "Trade") ((= result 30) "Bond") ((= result 31) "Hope") ((= result 32) "Superstition") ((= result 33) "Peace") ((= result 34) "Deception") ((= result 35) "History") ((= result 36) "World") ((= result 37) "Vow") ((= result 38) "Protection") ((= result 39) "Nature") ((= result 40) "Opinion") ((= result 41) "Burden") ((= result 42) "Vengeance") ((= result 43) "Opportunity") ((= result 44) "Faction") ((= result 45) "Danger") ((= result 46) "Corruption") ((= result 47) "Freedom") ((= result 48) "Debt") ((= result 49) "Hate") ((= result 50) "Possession") ((= result 51) "Stranger") ((= result 52) "Passage") ((= result 53) "Land") ((= result 54) "Creature") ((= result 55) "Disease") ((= result 56) "Advantage") ((= result 57) "Blood") ((= result 58) "Language") ((= result 59) "Rumor") ((= result 60) "Weakness") ((= result 61) "Greed") ((= result 62) "Family") ((= result 63) "Resource") ((= result 64) "Structure") ((= result 65) "Dream") ((= result 66) "Community") ((= result 67) "War") ((= result 68) "Potent") ((= result 69) "Prize") ((= result 70) "Destiny") ((= result 71) "Momentum") ((= result 72) "Power") ((= result 73) "Memory") ((= result 74) "Ruin") ((= result 75) "Mysticism") ((= result 76) "Rival") ((= result 77) "Problem") ((= result 78) "Idea") ((= result 79) "Revenge") ((= result 80) "Health") ((= result 81) "Fellowship") ((= result 82) "Enemy") ((= result 83) "Religion") ((= result 84) "Spirit") ((= result 85) "Fame") ((= result 86) "Desolation") ((= result 87) "Strength") ((= result 88) "Knowledge") ((= result 89) "Truth") ((= result 90) "Quest") ((= result 91) "Pride") ((= result 92) "Loss") ((= result 93) "Law") ((= result 94) "Path") ((= result 95) "Warning") ((= result 96) "Relationship") ((= result 97) "Wealth") ((= result 98) "Home") ((= result 99) "Strategy") ((= result 100) "Supply")))) ;; (defun w/tcg-generate-flavor-text (nm k) ;; "Generate random TCG-style flavor text for NM and pass it to K." ;; (w/ai ;; (format "%s - %s" nm (w/tcg-generate-theme)) ;; k ;; "Please generate trading-card-game style flavor text for the given card name and linguistic theme. Focus primarily on the theme. Try to write in a way that evokes the given theme through style and word choice. Try to capture the feeling of badly-translated Japanese. Use less descriptive language to keep things short. Do not reference the card itself - the text should be from an in-universe perspective. Do not use adjectives or adverbs. Do not mention whispering or secrets or shadows - these are not the theme! Use the theme instead!" ;; (list ;; "Blue-Eyes White Dragon - Power" ;; "Insect Knight - Lore" ;; "Shapesnatch - Mystery" ;; ) ;; (list ;; "This legendary dragon is a powerful engine of destruction. Virtually invincible, very few have faced this awesome creature and lived to tell the tale." ;; "Of all Insect fighters, he is the paragon of the Indestructible Insect Invaders, which only the elite of the elite can join. We can no longer ignore their unmatched battle prowess." ;; "A bow tie with horrible power, it attacks an opponent by controlling others." ;; ))) (defun w/tcg-generate-flavor-text (nm k) "Generate random TCG-style flavor text for NM and pass it to K." (funcall k (w/irish-fill-template (w/pick-random w/irish-templates) (list nm (s-downcase (w/tcg-generate-theme)))))) (defun w/tcg-random-user-card (k) "Generate a random `w/tcg-card' for a random user and pass it to K." (let* ( (users (-map #'car w/twitch-chat-history)) (name (w/pick-random users))) (w/tcg-user-card name k))) (defun w/tcg-user-card (name k) "Generate a random `w/tcg-card' for NAME and pass it to K." (w/user-id-from-name name (lambda (uid) (w/user-get-property uid "element" (lambda (element) (w/user-get-property uid "faction" (lambda (faction) (w/user-get-property uid "boost" (lambda (boost) (w/user-get-stat uid "equity" (lambda (equity) (let* ( (colornm (or (cadr (alist-get element w/user-elements nil nil #'s-equals?)) "grey")) (color (w/color-value-to-html-code (color-values colornm))) (faction-color (w/color-value-to-html-code (color-values (cl-case faction (nate "pink") (lever "lightblue") (tony "lightgreen") (t "white"))))) (rarity-level (w/tcg-determine-rarity)) (rarity (w/tcg-render-rarity rarity-level))) (w/twitch-get-user-avatar name (lambda () (w/tcg-generate-flavor-text name (lambda (body) (funcall k (w/make-tcg-card :name name :type "user" :depicted-subject name :element (or element "neutral") :color color :faction (format "%s" (or faction "none")) :faction-color faction-color :equity (format "%s" (or equity 0)) :boost-level (or boost "ABSTAINER") :rarity rarity :rarity-level (format "%s" rarity-level) :body-text body :base-image-name (w/pick-random w/tcg-bases) :set w/tcg-current-set :minted-date (format-time-string "%Y-%m-%d" (current-time)) :flags (s-join "," (w/tcg-pick-flags nil))))))))))))))))))) nil) (defun w/tcg-encode-card (user userid c) "Encode giving C to USER with USERID to a string." (s-join "\t" (list user userid (w/. name c) (w/. type c) (w/. depicted-subject c) (w/. element c) (w/. color c) (w/. faction c) (w/. faction-color c) (w/. equity c) (w/. boost-level c) (w/. rarity c) (w/. rarity-level c) (w/. body-text c) (w/. base-image-name c) (w/. set c) (w/. minted-date c) (w/. flags c)))) (defun w/tcg-generate-card (user c) "Generate the card C and give it to USER." (w/chat-write-event (format "Generating card for %s..." user)) (w/twitch-get-user-id user (lambda (userid) (let ((msg (format "%s" (w/tcg-encode-card user userid c)))) (w/binary-pub "overlay tcg generate" msg))))) (provide 'wasp-tcg) ;;; wasp-tcg.el ends here