76 lines
3.8 KiB
EmacsLisp
76 lines
3.8 KiB
EmacsLisp
(defun rpgdm--fate-die ()
|
|
"Return a cons of a Fate die and its visual representation."
|
|
(seq-random-elt '((-1 . "[-]")
|
|
( 0 . "[ ]")
|
|
( 1 . "[+]"))))
|
|
|
|
(defun rpgdm--fate-roll-dice (&optional number)
|
|
"Return a list of Fate roll results. Each element of the list
|
|
is a cons of its value and its visual representation, see
|
|
`rpgdm--fate-die'."
|
|
(unless number
|
|
(setq number 4))
|
|
(let (results)
|
|
(--dotimes number
|
|
(push (rpgdm--fate-die) results))
|
|
results))
|
|
|
|
(defun rpgdm--fate-roll (modifier &optional number)
|
|
"Simulate a FATE dice roll and return the results.
|
|
Return a list where the first element is the total results,
|
|
and the second element is a user-formatted view of the results. "
|
|
(unless number (setq number 4))
|
|
(let* ((roll (rpgdm--fate-roll-dice number))
|
|
(vals (-map 'car roll))
|
|
(dice (-map 'cdr roll))
|
|
(roll (s-join " " dice))
|
|
(sum (apply '+ vals))
|
|
(total (+ sum modifier))
|
|
(results (propertize (number-to-string total) 'face '(:foreground "green"))))
|
|
(list total (format "Rolled: %s :: %s + %d" results roll modifier))))
|
|
|
|
(defun rpgdm-fate-roll (modifier)
|
|
"Simulate a FATE dice roll and display the results.
|
|
The total is the difference of the `+' to `-' plus the MODIFIER.
|
|
Note that the NUMBER of dice defaults to 4."
|
|
(interactive (list (rpgdm-fate-ladder "effort level")))
|
|
(rpgdm-message (second (rpgdm--fate-roll modifier 4))))
|
|
|
|
(let ((rpgdm-fate-ladder-values '((-2 "t" "Terrible" "Trivial") (-1 "p" "Poor" "Easy") (0 "m" "Mediocre" "Simple") (1 "a" "Average" "Average") (2 "f" "Fair" "") (3 "g" "Good" "Hard") (4 "r" "Great" "Daunting") (5 "s" "Superb" "Extreme") (6 "f" "Fantastic" "Impossible") (7 "e" "Epic" "") (8 "l" "Legendary" ""))))
|
|
(defvar rpgdm-fate-ladder rpgdm-fate-ladder-values "The FATE RPG ladder of challenge levels.")
|
|
)
|
|
|
|
(defun rpgdm-fate-ladder (&optional request-type)
|
|
"Prompt for a choice on the FATE ladder, and return the numeric value of that level.
|
|
The REQUEST-TYPE is an optional string inserted into the prompt to describe the request."
|
|
(interactive)
|
|
(unless request-type (setq request-type "challenge level"))
|
|
(let* ((choices (mapconcat 'rpgdm--fate-ladder-prompt rpgdm-fate-ladder " "))
|
|
(prompt (format "What is the %s?\n%s"
|
|
(propertize request-type 'face '(:foreground "yellow"))
|
|
choices))
|
|
(choice (char-to-string (read-char prompt)))
|
|
(entry (--filter (equal (second it) choice) rpgdm-fate-ladder)))
|
|
(first (first entry))))
|
|
|
|
(defun rpgdm--fate-ladder-prompt (entry)
|
|
(let* ((entry-number (format "[%d]" (first entry)))
|
|
(render-number (propertize entry-number
|
|
'face '(:foreground "#888888")))
|
|
(keyed-prompt (propertize (second entry) 'face '(:foreground "green"))))
|
|
(format "%s) %s %s" keyed-prompt (third entry) render-number))))
|
|
|
|
(defun rpgdm-fate-challenge (opposition-level effort-level)
|
|
"Return a user message for a FATE dice challenge.
|
|
Given a numeric EFFORT-LEVEL as well as the OPPOSITION-LEVEL,
|
|
this function rolls the Fate dice and interprets the results."
|
|
(interactive (list (rpgdm-fate-ladder "opposition level")
|
|
(rpgdm-fate-ladder "effort level")))
|
|
(let* ((die-roll (rpgdm--fate-roll effort-level))
|
|
(shifts (- (first die-roll) opposition-level))
|
|
(results (cond
|
|
((< shifts 0) (propertize "Failed" 'face '(:foregound "red")))
|
|
((= shifts 0) (propertize "Tie" 'face '(:foreground "yellow")))
|
|
((> shifts 3) (propertize "Succeed with Style!" 'face '(:foregound "green")))
|
|
(t (propertize "Success" 'face '(:foregound "green"))))))
|
|
(rpgdm-message "%s ... %s" results (second die-roll))))
|