Add dice tables
A dice table is a direct translation of a gaming table from a book, where the table has a stated dice expression, and each entry has a numeric range. Most tables can now be taken as is from published sources. Also, if a message from a randomly rolled table contains a dice expression, like Found 2d8 scrolls, the expression is automatically substituted. Finally if a message contains something like: You found a [wolf/fox/badger]. The displayed message will only include on of those entries.
This commit is contained in:
parent
106ed2e6dd
commit
656c168a52
8 changed files with 155 additions and 59 deletions
|
|
@ -1,4 +1,3 @@
|
|||
;; [[file:docs/rpgdm-tables-dice.org::+BEGIN_SRC emacs-lisp][No heading:1]]
|
||||
;;; rpgdm-tables-dice.el --- Rolling dice for choosing items from Tables -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2021 Howard X. Abrams
|
||||
|
|
@ -11,4 +10,77 @@
|
|||
;;
|
||||
;;
|
||||
;;; Commentary:
|
||||
;; No heading:1 ends here
|
||||
;;
|
||||
;; This file contains the source code, but the concept behind what I'm
|
||||
;; calling random dice tables is a bit complex, so I recommend looking
|
||||
;; at the original file in `docs/rpgdm-tables-dice.org'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defstruct dice-table dice rows)
|
||||
|
||||
(defun rpgdm-tables--choose-dice-table (table)
|
||||
"Choose a string from a random dice table."
|
||||
(let* ((roll (rpgdm-roll-sum (dice-table-dice table)))
|
||||
(rows (dice-table-rows table))
|
||||
(results (rpgdm-tables-dice--choose roll rows)))
|
||||
(if (stringp results)
|
||||
results
|
||||
(seq-random-elt results))))
|
||||
|
||||
(defun rpgdm-tables-dice--choose (roll rows)
|
||||
"Given a numeric ROLL, return row that matches.
|
||||
This assumes ROWS is a sorted list where the first element (the
|
||||
`car') is a numeric level that if ROLL is less than or equal, we
|
||||
return the `rest' of the row. Otherwise, we recursively call this
|
||||
function with the `rest' of the rows."
|
||||
(let* ((row (first rows))
|
||||
(level (car row))
|
||||
(answer (rest row)))
|
||||
|
||||
(if (<= roll level)
|
||||
answer
|
||||
(rpgdm-tables-dice--choose roll (rest rows)))))
|
||||
|
||||
(setq rpgdm-tables-dice-table-regexp (rx "Roll"
|
||||
(one-or-more space)
|
||||
(optional (or "on" "for"))
|
||||
(zero-or-more space)
|
||||
"Table:"
|
||||
(zero-or-more space)
|
||||
(group
|
||||
(regexp rpgdm-roll-regexp))))
|
||||
|
||||
(defun rpgdm-tables-dice-table? ()
|
||||
"Return non-nil if current buffer contains a dice-table"
|
||||
(goto-char (point-min))
|
||||
(re-search-forward rpgdm-tables-dice-table-regexp nil t))
|
||||
|
||||
(defun rpgdm-tables--parse-as-dice-table ()
|
||||
"Return `dice-table' of lines matching `rpgdm-tables-dice-table-rows'."
|
||||
(let ((dice (match-string-no-properties 1)) ; Grab expression before moving on
|
||||
(rows ()) ; Modify this with add-to-list
|
||||
(row-splitter (rx (* space) "|" (* space)))) ; Split rest of table row
|
||||
|
||||
(while (re-search-forward rgpdm-tables-dice-table-rows nil t)
|
||||
(let* ((levelstr (match-string-no-properties 1))
|
||||
(level (string-to-number levelstr))
|
||||
(row (match-string-no-properties 2))
|
||||
(choices (split-string row row-splitter t)))
|
||||
(add-to-list 'rows (cons level choices))))
|
||||
(make-dice-table :dice dice
|
||||
:rows (sort rows (lambda (a b) (< (first a) (first b)))))))
|
||||
|
||||
(setq rgpdm-tables-dice-table-rows (rx bol
|
||||
(zero-or-more space) "|" (zero-or-more space)
|
||||
(optional (one-or-more digit)
|
||||
(one-or-more "-"))
|
||||
(group
|
||||
(one-or-more digit))
|
||||
(zero-or-more space) "|" (zero-or-more space)
|
||||
(group (+? any))
|
||||
(zero-or-more space) "|" (zero-or-more space)
|
||||
eol))
|
||||
|
||||
(provide 'rpgdm-tables-dice)
|
||||
;;; rpgdm-tables-dice.el ends here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue