Skip to content

Latest commit

 

History

93 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

* decide-mode.el
Random decisions for Emacs, with functions and a minor mode. Roll dice and
generate random numbers and text in a few other ways. Mostly inspired by tools
and activities related to role-playing games, but may be useful beyond that.
** Examples (Quick Overview)
There is a sequence of keys to press, starting with a question-mark, and some
functions will prompt for more input. This is not a complete list of all
functions.
|-----------------------+-------+----------------+-----------------|
| What to decide        | Keys  | Input          | Example Output  |
|-----------------------+-------+----------------+-----------------|
| Yes or no             | ? ?   |                | YES             |
| ... probably yes      | ? +   |                | YES             |
| ... probably no       | ? -   |                | NO              |
| Roll 1d6              | ? 6   |                | 3               |
| Roll 2d6              | ? D   |                | (5 1) = 6       |
| Roll 1d20             | ? 2 0 |                | 20              |
| Roll dice (general)   | ? d   | 2d6+1          | (5 3) +1 = 9    |
| Roll four FATE dice   | ? F   |                | (- 0 + +) = 1   |
| Roll 5d6 and count 6s | ? d   | 5dB6           | (6 3 2 6 4) = 2 |
| Number from range     | ? r   | 1-10           | 5               |
| ... low likely        | ? r   | 1<<10          | 4               |
| ... low more likely   | ? r   | 1<<<<10        | 1               |
| ... high likely       | ? r   | 1>>10          | 7               |
| Choose from list      | ? c   | apple,orange   | orange          |
| Random dir (of 4)     | ? w 4 |                | N               |
| Random dir (of 8)     | ? w 8 |                | NW              |
| Use random table      | ? t   | example-dragon | wise ice dragon |
|-----------------------+-------+----------------+-----------------|
** Introduction
Random results from /decide-mode/ are inserted at point in the current buffer if
possible, otherwise only echoed in the mini-buffer. The default keyboard
bindings for the minor-mode are intended to be convenient to trigger as part of
typing regular text, by pressing ? followed by various other keys.

A ? followed by space, enter, or a closing parenthesis will insert the ? itself
and the next key as expected, so normally /decide-mode/ should not interfere
with typing.

The default binding of "? ?" (since version 0.7) is /decide-dwim-insert/, a function
that looks in the buffer immediately before point and if it finds a dice
or range specification there it will replace it with the result of rolling
the dice or picking a random number from the range. If no dice or range
is found it will fall back to the normal /decide-for-me-normal/ function that
outputs a simple YES or NO result.

See the decide.el file itself for some documentation and a list of all the
keybindings in /decide-mode/. There is an overview of important features
below, but all the details and more features can be found in the source.
** Yes or No
The simplest function of /decide-mode/ is /decide-for-me-normal/ that will insert
a /Yes/ or /No/ with equal probability. By default it is triggered by pressing
"? ?", unless what is in the buffer just before point is a valid
dice-specification or range (see descriptions of those below), in which case
that will be used instead.

To get a Yes only with 33% probability use "? -" (/decide-for-me-unlikely/)
and for 67% probability "? +" (/decide-for-me-likely/).

When inserting a Yes or No using these functions there will sometimes, randomly,
be a + or - inserted as well. Those can be ignored or interpreted as for
instance "and" and "or", for use in some RPG systems. The probability of a +
or - appearing will depend on which of the functions is called (see the
confusingly named function /decide-for-me-dice/ for the exact probabilities).
** Installation
Load the file /decide.el/ (e.g. /(load-file "~/.emacs.d/lisp/decide.el")) and
then enable it in a buffer by running /M-x decide-mode/.

To always have it enabled for a specific major-mode, add it to the appropriate
hook, e.g.:
#+BEGIN_EXAMPLE
(defun my-org-mode-hook ()
        (decide-mode 1))
    (add-hook 'org-mode-hook 'my-org-mode-hook))
#+END_EXAMPLE

To only enable it for a specific file, check the documentation for [[https://www.gnu.org/software/emacs/manual/html_node/emacs/File-Variables.html][GNU Emacs
File Variables]], and of course it can also be [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html][for an entire directory]].
** Die Rolls
Die-rolls are specified in common dice-notation, like 3d6 for rolling 3
6-sided dice, or 2d4+1 to roll 2 4-sided dice and add 1 to the result.
If the number of dice is not given (e.g. d10) it is assumed to be a single die.
If the number of sides is not given (e.g. 2d) a standard d6 is assumed,
but that can be configured in the variable /decide-default-dice-faces/.

There are several ways to roll dice using /decide-mode/. The interactive
function /decide-roll-dice/ will ask for a dice specification and then
immediately insert the results of rolling that. The default keybinding "? d"
will call that function. There are also some bindings that are "?" followed by
one or more digits that will roll a single die immediately, e.g. "? 8" to roll
1d8 or "? 2 0" to roll 1d20. See the list at the end of decide.el. A few special
bindings are also included, like "? %" to 1d100 and "? f" to roll 4dF. Common
1d6 can be rolled with "? 6", or 2d6 with "? D".

Dice are also rolled when pressing "? ?" (/decide-dwim-insert/) if point is
immediately preceded by what can be parsed as a valid dice-specification.

It is also possible to use custom named dice that can have any number of sides
that has any text on. Each side must still be given a value, as the sum of all
rolled dice is always printed. Custom dice are specified in the variable
/decide-custom-dice/ Included by default are dice F (for Fudge/Fate dice), S
(results in Fail or Success), B6 (for rolling a bucket of dice, counting 6s as
hits), B5 (like B6 but hits on 5-6), B4 (you get the idea), B3, B2, and A
(average dice, a 6-sided die labelled 2, 3, 3, 4, 4, 5). To roll a custom die
just use its name where the number of sides of a die would normally be, e.g. 4dF
to roll 4 Fudge/Fate dice.

Custom dice can be given names of any length, but case is ignored, so a dF is
the same as a df. It is thus not possible to specify dice that have the same
names only differing in case.
** Random Ranges
Ranges are a simpler way to specify a range of random numbers than to use dice.
The default key-binding for ranges is "? r". The simplest range is just n-m,
where n and m are integers (m must be positive) and m is greater than n. The
inserted random number will be from n to m, inclusive. The range 1-6 is
equivalent to rolling a standard 1d6.

Ranges also support some special syntax to make some numbers in the range
more likely. Including more dashes between the numbers makes results
in the middle of the range more likely by effectively generating as many
random values as the number of dashes and then picking the median of
all those numbers. The range 10---20 for instance would insert a number
from 10 to 20, but numbers close to 15 would be more likely. Using
greater-than or lower-than characters instead between the numbers will
tend towards higher or lower numbers, by generating as many numbers
as indicated and then picking the highest or lowest, so 1>>6 is effectively
like rolling 2d6 and picking the highest rolled. It makes no sense to use
only a single < or >.

The default binding for "? ?" will generate a random number from a range
if point is immediately preceded by what can be parsed as a valid range
specification.
** Random Choices
The function /decide-random-choice/, by default bound to "? c", asks for
a comma-separated list of things and then inserts one of those chosen
at random. A random direction can for instance be requested by pressing
"? c" and then "N,S,W,E" or a random color with "red,blue,green".

Some lists of choices are available at default key-bindings that can be seen at
the end of the decide.el file. For instance the random directions in the last
paragraph are available by pressing "? w 4" and there are several other similar
bindings included.

See the Random Tables below for a more powerful way of asking for a random
choice. A random choice using "? c" is good for a quick ad-hoc choice as it does
not require setting up a table with choices. Choices are saved in mini-buffer
history, and thus easily available to make new similar choices again until Emacs
is restarted, but for more permanent lists of things to draw from it is better
to create a table or set up a key-binding to call /decide-random-choice/ (see
the functions at the end of decide.el for how to do that easily).
** Random Tables
The function /decide-from-table/, by default bound to "? t" when /decide-mode/ is
enabled, inserts random text generated from the table in variable /decide-table/.
The table can be set up using elisp, but since version 0.8 there is a new, simpler,
way of setting up the tables by using plain-text files. Text is generated by
starting from a given table and picking a random phrase from that table. Phrases
can be weighted to make some more likely to be chosen. A phrase can also contain
references to other tables, which will be substituted by a random phrase from
that table. It is also possible to insert die-rolls and random numbers from
a given range.

The functions /decide-table-load-file/ and /decide-table-load-dir/ can be used
to load random tables from text files into the /decide-tables/ variable. The
latter recursively loads all files in a directory, while the former only loads a
single file. Each file contains a single table, with one phrase per line.
Weights are set by prefixing a line with a number and a comma, with no
white-space before or after.

A line that begins with a semicolon begins a new table, and the name of the
table is the text on the line after the semicolon. As a special case if
the name is /main/ (case-insensitie match) instead the name of the file
(sans extension) will be used for that table.

To refer to another table from a phrase, include the name of that table
in brackets. Die-rolls can similarly be inserted by putting it in brackets.
To get a simple random number in a range from n to m use [n-m], but
it is also possible to use more advanced range-specifiers as described

References to other tables are first searched for in the same file.
If no table matches in the file all file-names are searched instead.
A name like /fff.ttt/ can be used for table /ttt/ that was declared in
file /fff/.

A simple table to generate a primary color, with green being twice
as likely to be chosen could look like this (in file /primary-color.txt/):
#+BEGIN_EXAMPLE
;main
red
2,green
blue
#+END_EXAMPLE

The following table in another file, /paint-buckets.txt/
refers to the previous table, and it also makes use of both
a random range and a die-roll, where one of the
phrases will be used four times as often as the other:
#+BEGIN_EXAMPLE
;main
4,[2-4] buckets of [primary-color] paint
[1d3+2] empty paint buckets
#+END_EXAMPLE

The *random-tables* sub-directory contains a few example tables.
The /decides-tables/ variable by default includes tables "card", "card.suit",
and "card.rank" that can be used to draw random cards from an infinite deck. To
load the other examples (all with names prefixed "example-") use the
/decide-table-load-dir/ function. It makes sense to gather all table files in a
directory and put a single call like
/(decide-table-load-dir "~/.emacs.d/random-generators")/
in emacs' init script to make sure all tables are always loaded.

Blank lines in table files are ignored. If a blank phrase is needed (as in the
/random-tables/example-dragon-prefix.txt/ file) a weight can be used alone on a
line, just a number followed by a comma. Lines beginning with a # are comments
and are ignored.

The format of the table files is based on the format used by [[http://www.random-generator.com/][Abulafia (random-generator.com)]],
that is a site containing thousands of random-generator tables, but lacking
most of the advanced functions on that site. (NOTE: It seems like Abulafia
has had issues for many years now, and currently (August 2024) the site seems
broken with just error messages and almost empty pages). The format is
also similar to the format used for [[https://campaignwiki.org/hex-describe][Hex Describe's rules]] (but lacking
most of the features supported by that generator).
** Customizing Output
Since version 0.10.0 there is a variable /decide-output-format/ that
can be used to control what is inserted by decide-mode functions.

If set to a string it is used as the format-string for a call to
the standard emacs-lisp format function, that will also receive
two strings: /what/ is being generated (e.g. a dice-specifier or
name of a table) and the /result/ that was generated. The format-string
can use %1$s and %2$s respectively to refer to the /what/ and /result/
strings (or use %s for both if used in that order).

For example to only output the generated result (without describing
what was generated) and add a single trailing space:
#+BEGIN_EXAMPLE
(setq decide-output-format "%2$s ")
#+END_EXAMPLE

This outputs the result only, and also makes it appear
bold in org-mode:
#+BEGIN_EXAMPLE
(setq decide-output-format "**%2$s** ")
#+END_EXAMPLE

If set to a function that function will be called with the two
string arguments /what/ and /result/ and is expected to return
the string to be inserted. If nil is returned nothing is inserted
(other than what the function itself may already have inserted).

When creating custom functions for decide-mode, for instance to when binding a
key to roll some special dice, note that /decide-output-format/ can be
bound using /let/ around calls to /decide-mode/ functions to control the way the
results are inserted without affecting the global (or buffer-local)
configuration.
** Use in yasnippets
Not a feature of /decide-mode/ itself, but it is easy to embed calls to
various /decide-/ functions in yasnippet files. A random table
set up to generate Victorian names (hint: you can easily make one based on [[http://www.random-generator.com/index.php?title=Victorian_Names&action=edit][the
random Victorian names table on Abulafia]], but doing that is left as an exercise)
can be used in a yasnippet snippet like this:
#+BEGIN_EXAMPLE
`(decide-choose-from-table "names-victorian")`.
#+END_EXAMPLE
** Versions
*** 0.10.0 2024-10-13
- decide-output-format variable to control output format
- Support +0 dice modifier bugfix (thanks wkmanire)
- Bugfixed and cleaned up dice spec parser in general
- ERT tests added
- Added bucket-of-dice custom dice B2, B3, B4, B5, B6
*** 0.9.1 2022-07-18
- Updated README with changelog for 0.9.0.
*** 0.9.0 2022-07-18
- Multiple tables in the same file
- Tables with name beginning with dash no longer hidden
  (but all tables other than the first one in each file is)
- Fixes decide-roll-die-nonempty typo (thanks thezeroalpha)
- New helper function decide-string-from-table
*** 0.8 2021-11-28
- Weighted decide-tables
- Parse decide-tables from text-files
- Default faces for dice (decide-default-dice-faces variable, default 6)
- Success dice (S) to roll Success or Fail
- Dice-specification parser more forgiving
- Tables with new format only parsing parts in square brackets
*** 0.7 2017-07-03
- Do What I Mean (dice or range spec before ? ? in buffer)
*** 0.6.2 2017-07-03
- Fixed regression with parsing dice in tables.
*** 0.6.1 2017-07-03
- Cleaned up dice-parsing and improved error-handling.
*** 0.6 2017-07-02
- Custom dice can be added in decide-custom-dice variable.
- Various minor fixes.
*** 0.5 2016-03-06
- First public version.
** Help
Suggestions and bug-fixes are very much appreciated. This was
my first attempt at writing a mode for Emacs, and I have very
little experience with elisp (or any lisp) in general.
** License
 Copyright 2016, 2017, 2019, 2021-2024 Pelle Nilsson et al

 Author: Pelle Nilsson <perni@lysator.liu.se>
 Version: 0.10.0

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

About

Random decisions for emacs, with functions and a minor mode. Roll various types of dice etc.

Resources

Stars

60 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages