dungeon-mode - synchronous and asynchronous world sharing and change resolution
We’ve moved! Visit us elsewhere on GitHub
An hack-and-slash style mult-player dungeon crawl blending the heuristics of NetHack with a combat engine inspired by Minnesota Dungeon (Minneapolis Dungeon, Larry’s Maze, et. al.).
Requires GNU Emacs 26.3 or later, available here for most platforms: http://gnu.org/software/emacs
We’re extreemly grateful for the internet hosting we receive from GNU (“non-GNU”, by GNU) Savannah and to Fosshost who provides a smashing virtualized environment for testing and experimentation, and eventually to host our “Arcade”. Fosshost could really use financial support, if you are in a position. Appologies for any sense we misrepresent our cloud provider’s need here: GH auto-rendering of org for README is ugly which may be our bad.
This file is a part of dungeon-mode. It is not a part of GNU Emacs. This softare is released under the GNU Public Licence version three or, at your disgression, any newer version of the GNU Public License. For specific terms please see LICENSE at end-of-file.
We’re writing POC code for the two features targeted for the initial Minimum Learning Product, which we call our “Minimum Play-Testable Product”, or MPTP.
- Rendering levels of dungeon maze as SVG graphics
- Erik (Tigersbite) is hand authoring sample maps in SVG and
org-mode. We’ll use these eventually in test code, we think. Currently they are serving to flush out the complexities of expressing the data and driving out design for Corwin’s work.
- Corwin (mplsCorwin) is writing lisp packages to read in data
from the org-mode tables and draw SVG graphics and including some basic optimizations targeting a server that needs to build draw instructions from secret information and send them to multiple clients that must redraw sections of the display as revealed secrets change players understanding of previously uncovered parts of the map.
- The Battle Board is the primary player display interface during combat, while combat and movement about the map are the two primary states of play for Dungeon. We’ll take this on once we like our designs for mapping, and especially for interacting with source material written in/with/for/by org-mode.
This is currently the offical repository of dungeon-mode et. al.
Lots of the documentation is aspirational. We spent the first six or so weeks of the project considering what we might want dungeon-mode to do. Since then we’ve turned our attention to POC code, as mentioned above.
Eventually, as play-testing moves forward, we can come back and see what parts of our conceptual visions stuck and feel like they should be part of the package and which feel extra.
- Our current approach is pitching all manner of sources every which way while taking little to no care for repository hygiene.
- We’ll continue in this manner until we can build the MPTP.
Generally look at this we’ve committed recently for a more tacitical and less aspirational view of the project.
- Recently pushed .el files give a sense what our code is looking like
- Recently pushed .svg files are demo the (limited) graphics capabilities planned.
- This document, while aspirational, give a great sense of what dungeon-mode might be able to do.
- Other Org documents in the Docs, especially Docs/Maps folders, provide feature specific designs or prototypes of a more and less aspirational nature.
- Generally, the more recently someone has committed something the more likely it is tactical with respect to the MPTP.
- Ask! Open an issue and ask your question or pop over to our Discord server (linked at EOF).
Even if all you feel like doing is grooming this repo a bit we’d love you’re help and enthusiasm! Reach out via issue for commit access.
Dungeon-mode is a game engine and REPL for creating and playing multi-user dungeons written primarily in emacs lisp. While playing a game created with dungeon-mode doesn’t necessarily require Emacs authoring game environments (e.g. worlds) does, as do assigning special powers, resolving Ghod calls, Sage encounters, and Ubic -if enabled- or any other or custom events with a dm-intractable property set to a non-nil value. Dungeon Masters may specify delegation rosters to support cooperative oversight and enable teams to direct the play experience.
Dungeon-mode works by maintaining an eventually current journal of the all REPL interactions and results associated with each world. The REPL is responsible for accepting input (traditionally with keyboard and mouse, or via REST), resolving and brokering inputs and authorities, and publishing and persisting changes to the journal.
dungeon-mode provides nine interactive modes for Emacs, each with different display characteristics and default key-bindings. Generally the key major-modes are battle-board for players and dungeon-master for game creators and team Dungeon Master.
major-mode providing the REPL, an interactive environment for directly interacting with the game engine and working with journals.
Major- or minor-mode for reading journals and adding entries. Major mode supports display of a journal with org-like tree expansion. Minor mode supports ‘dungeon crawl’, a mode-line like display interface for viewing events from the local repl in battle-board-mode and dungeon-master-mode. Inital development will focus on private (for REPL use) and public (interactive) API with UX concerns to follow (likely) at a lesser priority.
major-mode to display a party of characters creatures, NPCs, etc., shows health, armor, primary weapon &ct. This mode includes the ability to compose others creating a complete interface intended to meet most player needs.
major-mode to display opposition. Similar to battle-board but includes a “fog-of-war” allowing details to be masked or omitted from display. Also available as a minor-mode such that the baddie-board can be included in the battle-board to give a consolidated view of party and opp.
major-mode to create and display dungeon levels. map-mode is also available as a minor-mode so you can use it with battle-board to provide a full, thumbnail, or positional slice of the map from the same interface which displays.
major-mode for display of a party’s undivided spoils and any other unresolved events associated with treasure collection. Also available as a minor mode, such that unresolved treasure and events may be listed alongside party status display.
major-mode for display of a character, NPC, etc., and to display options for resolving an action. This can be used within the battle-board to display the actions available to the next actor and select one via an accompanying minor-mode.
Major mode for writing and associating tables, such as of creatures, treasure, and dungeon levels. This mode is also available as a minor-mode enabling display of (know) baddie information within battle-board mode.
Minor-mode used to display the active worlds and descents for a REPL.
Major-mode used to create games and perform Dungeon Master actions. It is generally a superset of the features provided by battle-board with additional capabilities supporting multiple simultaneous games and multiple simultaneous descents into each, as well as for changing game, action, and inspecting and updating event properties on the fly.
The general approach to game mechanics is taken from Minnesota Dungeon (or Minneapolis Dungeon, or just “Dungeon” if you happen to be from there), a contemporary to early D&D featuring an extremely simple rule-set and a zero or near-zero cost to play. Larry Brawmer is generally crediting with creating the first Dungeon. Dungeon is characterized by borrowing heavy from prior art (e.g. other people’s Dungeons that you’ve played in) as well as Science Fiction and Fantasy sources. This has the effect of requiring lore as well as ingenuity on the part of players, who complete with baddies, traps, and curses to win treasure and go up in rank.
Typical requirements are a pair of six sided dice, pencils, and a pad of quad-ruled graph-paper. Apocryphally, a “good” Dungeon can be created in one to two hours and will provide entertainment for a few weeks to a few months depending on how intricate the game and how determined the players.
An interesting distinction of Dungeon is the Special Power, a unique intrinsic provided to each character the rules for which are negotiated with the Dungeon Master prior to play. Some Dungeon Masters have add included the ability for special powers to be altered during or by play, for example as a result of certain events further complicating the problem spaces from a system design perspective.
Dungeon-mode handles this complexity by defining a emacs-lisp function for each special power at the time the character is registered for play in a world. Special power resolution functions may then carry the dm-interactive property specifying circumstances under which direct involvement by the Dungeon Master may be needed to resolve the use, attempted use, etc., of the special power.
Character Name and Character Memo notwithstanding, Special Power is the only unique-per-character attribute supported by the vanilla game engine provided by this package. All other character properties are either counters (Karma, Gold, …) or are values taken from tables designed by the Dungeon Master (Possessions, Intrinsics, …). Creators are free to build additional table or function based intrinsics which may depend upon or otherwise interact with each-other such that Ghod calls from 3rd level Wizards may be ignored while those from 2nd level Priests trigger Dungeon Master involvement.
That said, by the versions of Dungeon which have reached the maintainers of this document a great number of the creatures, treasure, events, curses, traps and so on require a close narrative quite disrupting the orderly rows and columns neatly describing the more generic baddies and treasure. Similarly, the Dungeon author typically eventually resorts to narrative or semi-narrative forms to describe rank tables as well as any more complex puzzles baked into the game. For more common puzzles (moving pillar in the center of a 30x30 area, anyone?) common notation conventions essentially create custom syntax specific, for example, to a small section of the map.
This project addresses such complexity by enabling the Dungeon author to define the world in terms of a free-form mixture of data and expressions. This may be either a sexp or a function receiving world and action-token and returning a journal entry. In the case of sexp the expression is simply a macro run with world and action-token lexically defined. The journal entry returned will generally resolve and advance the action. Additionally it may change aspects of the world (e.g. permanently change the game for all current and future players) or the decent, party, encounter or characters (living, dead, or incapacitated), or to player or info sections associated with any of these (e.g. the manual) presently associated to the action token. Such actions implicitly update these associations.
Dungeon-mode writes to the file-sytem. For the moment devlopers are focusing on a release that supliments or replaces our graph-paper and dice. We assume players will connect via VPN to one-and-others’ private networks and there our curiousity about Information Security dies. We may come to wonder further once we start opening ports &ct.
- Expression Syntax
Expressions read by dungeon-mode include implicit quoting of the symbols directly in the command sequence as well as of the &rest forms composing the docstring.
dungeon-mode is a complete game engine written in emacs lisp. It provides an interactive process to redefine worlds based on an action token which associates entities related by a single turn of the game.
Game turns represent one slice of play-time in the context of map-movement, character or baddie action in combat, treasure collection, or event or NPC encounter. While the specific references associated with an action-token vary based on the context, generally they include a character, party, decent and dungeon level and often also include baddies and treasure as well as npcs and events.
Executing an expression within the game engine produces a journal entry chronicling the change. This include narrative forms of any information to be returned to players or Dungeon Masters, which should provide detailed human-readable descriptions of any changes to the local or general game environment:
((-1 'maybe-to-body Biff<1>) "Biff The Hunter has taken 1 damage (body 2/3)")
((-1 'body-hits Biff<1>) "Biff The Hunter has lost 1 body-hit! (body 2)")
REPL returns journal entry update statements as lists where car the expression applied to the journal and &rest are a mix of text and expressions to create the narrative text explaining what has occurred for players and Dungeon Masters.
Texts are optional decorated with indicators to provide UI hints (context) and secrecy (publication scope):
((-1 'maybe-to-body Biff<1>)
:incapacitation-warning "Biff The Hunter has taken 1 damage (body 1/3)")
((-1 'body-hits '(warriors :level 1)) ;; REPL echo and *dm-messages* only!
:dm "Shhhh: Warriors start with 2 body-hits now ([email protected])")
Input to the REPL is only slightly different from it’s output in that the expression component may specify necessary authorities or otherwise establish predicates for application of the resulting journal entry while narrative elements may include intermixed macros expressed as functions and function arguments which may generate some or all of the text. Narrative input to the REPL consisting of more than a single string of text is recursively processed until only a single string of text remains, which is then included in REPL outputs (e.g. the journal, REPL echo, **DM Messages**, **Dungeon**, and any buffers or regions which track changes to a property mentioned as having been updated in the narrative. REPL provides for additional decorations to support this. Unlike those for secrecy and UI hinting these are not passed though in the REPL output:
# ((:character Biff<1> quaff-cast-use from-pocket full-heal)
describe-use ,actor "used" ,item-used (describe-body-hits))
> ((full-heal (destroy-consumed Biff<1>))
:full-heal "Biff The Hunter used a full-heal (body 3/3)")
Note the use of the substitution operator (comma) rather than the keyword indicator (colon) for REPL narrative input decorations. This helps visually to distinguish decorations affect REPL behavior from those which assist in heuristically interpreting and presenting results.
The Journal is a log of the present state of a world in terms of a history from it’s inception to the current moment. It is persisted as a mixed set of emacs-lisp expressions and JSON data named according to SHA256 sum. Taken as a whole, the journal entries for a world provide both the complete code needed to provide the world for interaction and a full narrative, or human-readable form of this same information adorned with hints regarding secrecy and importance.
The eventually concurrent part of our approach to journaling takes inspiration from Apache Cassandra and similar “NoSQL” technologies which guarantee that all instances of the database cluster will eventually have the most current data and focus on directing queries to the most current source for the specific information requested.
In our case we mean simply two things:
- A client is not guaranteed to receive information anytime before
a character (&ct.) attached to that client will become eligible
to act upon it.
This could mean that you don’t see you have taken damage until your next swing, even if you hammer refresh. The change hasn’t been persisted to the journal you’re reading. Don’t panic. It will be there by the time you can do anything about it.
- A client will eventually receive of all information to which it is entitled.
By presenting the constructs of the game as RESTful services web, mobile, and other clients are possible outside of Emacs; however, the REPL accepts sexp as input only from the local authority (e.g. the host’s Emacs), limiting other forms of access to the symbols defined when accepting the command.
Needless to say, trusted Emacs instances are under no such limitation and may use the full power of emacs-lisp to create whatever new functionality is needed to fully enhance the dungeon experience.
We recommend GNU Emacs for authoring worlds and leading the party.
Our vision identifies two use cases, a primary and a secondary. Task priority derives from importance to the minimum learning product for the first use case, or both use cases or by issue vote or scrum-master fiat in the event of a tie. The scrum master will be the ultimate and final arbiter determining import of a task with respect to the goals for a given scrum and for the project at large while that scrum is in progress.
Anyone is welcome to join in the development process. You can make contact by sending a pull request or a opening an issue. We might also be able find one and other in #emacs on irc.freenode.net.
Provide Emacs with features for remote cooperative real-time computer assisted role-playing.
In this vision, a DM and 1-8 players use Emacs as a replacement for dice, pencils and paper to play Dungeon in otherwise the same way it has traditionally been played. In the event tables have been input it provides lookup facilities otherwise it asks the DM to input updates to share with the players.
Players connect, perhaps via VPN, to the network of the DM’s host emacs process and launch emacs or web browsers providing previously shared identity tokens to authenticate and authorize. The data on/from the host Emacs is always considered authoritative such that we can stop and resume the game without need for clients to retain state between sessions.
Provide additional features to support fully and semi-autonomous computer based dungeoning.
In this vision, DMs may support (read: interfere with) the game experience as any number of people comprising any number of parties descend into different worlds. The system allows definition of rules for “portaling” such that characters and possessions may be allowed to pass between worlds. We can suspend DM Interactivity to allow Dungeon authors to play in their own games, responding to dm-interactable between descents by enhancing the automated behaviours.
For this use case, in the event of a fully automated game accessed by external clients (e.g. Web, Mobile, etc), Emacs may act primarily or even exclusively as a server rather than an interface provider.
We are creating a complete new game-engine writting within a text editor. We’d love your input and participation!
This project started in late 2019 as a collaboration between Erik (tigersbite) and Corwin (mplsCorwin). Shortly thereafter Erik got engaged, and moved, and started new work, and things of this nature.
Erik is on creating the game sources for “Default Dungeon”, which will ship with the game as a playable example of most/all out-of-box features. He’s currently focused specifically on flushing out edge-cases around storing information about map levels as org-mode documents.
Meanwhile, Corwin is developing programs to load and update elisp data structures from org-document. This work is currently focused on creating an exporter that provides a declarative for transforming documents, etc., into Emacs Lisp expressions.
We’re meeting about once a week to exchange progress reports. There are some others who join us on discord or IRC in the evenings. You are welcome among them.
Both Erik and Corwin are using the opportunity of this project to teach our kids some programing concepts. We welcome those learning or interested in learning Emacs Lisp and C who share our love of abstract self-made semi-disposable hack-and-slash dungeon-crawl and RPG games.
As Corwin is the only elisp dev currently involved (We both know C), this is the area where we could use the most help. Find us on Discord or join #dungeon-mode on Freenet.net IRC. Additional input, including general interest such as kibitzing the design, planned features, etc., are also welcomed. We draw the line and point and jeering. Get your own discord/irc channel for that please.
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 https://www.gnu.org/licenses/.