Skip to main content

Write interactive fiction played with pencil, paper, and addition

Project description

Addventure

Write interactive fiction played with pencil, paper, and addition.

Players solve games by looking up a Verb ID and an Object ID, adding them together, finding the sum in a potentials list, and reading the corresponding ledger entry. No electronics needed at the table.

How It Works

A game compiles down to a printable PDF with four sheet types:

  • Verb Sheet — lists each action (LOOK, USE, TAKE...) with its numeric ID
  • Room Sheets — one per location, listing objects and their IDs
  • Inventory & Potentials List — tracks carried items; maps every valid sum to a ledger entry
  • Story Ledger — numbered narrative entries with instructions ("cross out X, write Y")

The player's loop: pick a verb, pick a target, add the IDs, look up the sum. If it's in the potentials list, read the ledger entry and follow the instructions (state changes, item transfers, room transitions).

Quick Start

Python 3.10+. Uses uv as the runner. PDF output requires Typst installed on your system.

uv run adv run                     # compile example game to PDF (example.pdf)
uv run adv run games/example       # same thing, explicit path
uv run adv run path/to/game        # your own game
uv run adv run --text              # plain text output instead of PDF
uv run adv run -o output.pdf       # custom output path
uv run adv new my-game             # scaffold a new game directory

If typst is not on your PATH, the compiler falls back to plain text output automatically.

Writing Games

A game is a directory of .md files. You need one index.md for metadata, verbs, and items; all other .md files define rooms and are loaded alphabetically.

index.md

---
title: The Facility
author: Example
---

# Verbs
USE
TAKE
LOOK

# Inventory
CROWBAR
KEYCARD
KNIFE

The frontmatter metadata (title, author) is used in PDF sheet titles and page footers.

Room files

# Control Room
LOOK: Fluorescent lights buzz. Banks of dead equipment line the walls.

TERMINAL
+ LOOK: A dusty CRT. A keycard slot sits beside it.
+ USE + KEYCARD:
  You slide the keycard. The screen floods with data.
  - TERMINAL -> TERMINAL__UNLOCKED
    + LOOK: Scrolling text. A map shows the facility layout.
  - KEYCARD -> trash
  - room -> room__POWERED
    + LOOK: The room hums with energy. A hatch has opened in the floor.
    + HATCH -> room
      + LOOK: A dark opening, just wide enough to squeeze through.
      + USE:
        You lower yourself into the darkness.
        - player -> "Basement"

CRATE
+ LOOK: A heavy wooden crate, nailed shut.
+ USE + CROWBAR:
  You pry it open. A keycard glints inside.
  - CRATE -> CRATE__OPEN
    + LOOK: A splintered crate, lid hanging off.
  - KEYCARD -> room
    + LOOK: A small keycard among the splinters.
    + TAKE:
      You pocket the keycard.
      - KEYCARD -> player
  - CROWBAR -> trash

Script syntax reference

Syntax Meaning
+ VERB: text Interaction on an entity
+ VERB + TARGET: Multi-entity interaction (verb + two things)
ENTITY__STATE Double-underscore separates entity from state
- ENTITY -> destination Arrow — moves/transforms an entity
-> player Move to inventory
-> trash Remove from game
-> "RoomName" Move player to another room
-> room Place in current room
-> ENTITY__STATE Transform entity to a new state
@room Reference to the current room entity
* wildcard Matches all entities in room

Room-level interactions use VERB: text without the + prefix. Entity interactions and arrows use + and - prefixes respectively. Indentation defines the hierarchy: arrows nested under an interaction fire when that interaction triggers, and child interactions on a state-changed entity only apply in that state.

Interactions section

Room files can have a # Interactions section for interactions that don't belong to a specific room object:

# Interactions

USE + KNIFE + BINDINGS:
  You saw through the rope. Your hands are free.
  - BINDINGS -> trash
  - USE__RESTRAINED -> USE

USE__RESTRAINED + *:
  You strain against the bindings. No use.

Example Output

Running uv run adv run generates a PDF with sheets like:

THE FACILITY — VERB SHEET
========================================

  USE                  [ 32 ]
  TAKE                 [ 21 ]
  LOOK                 [ 51 ]
ROOM: CONTROL ROOM
Room ID: 144

Objects in this room:
  TERMINAL                 951
  CRATE                    963
  WALL_PANEL               662
  BINDINGS                 949

The potentials list maps sums to ledger entries (e.g., LOOK + TERMINAL = 51 + 951 = 1002 → Entry #5), and the story ledger contains the narrative with physical instructions for updating your sheets.

IDs are randomly assigned each compilation, so every printout is a unique puzzle.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

addventure-1.3.0.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

addventure-1.3.0-py3-none-any.whl (563.9 kB view details)

Uploaded Python 3

File details

Details for the file addventure-1.3.0.tar.gz.

File metadata

  • Download URL: addventure-1.3.0.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for addventure-1.3.0.tar.gz
Algorithm Hash digest
SHA256 9ffba7f01b6a4f52638b2e0f4dd3d7e410aefa82e4382f3978a876b72ec081f1
MD5 89ff06b6492a43ab89b45f3307e165ed
BLAKE2b-256 9dd0b8e5aaf7ed0393af5d2875e65cdc9a79b728ae24fa1847538087e4db75b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for addventure-1.3.0.tar.gz:

Publisher: publish.yml on SmileyChris/addventure

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file addventure-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: addventure-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 563.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for addventure-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 212fca177fba14e9b080a4e1202d6ed8b292872d13fd867e24e6357231a2fc15
MD5 619f9a54b50031ce18ab1afc0297a78c
BLAKE2b-256 291d9144c0b4fc00a80b82eada5f8e29d4b03a80fb201d4aa4137dcb7aa4331a

See more details on using hashes here.

Provenance

The following attestation bundles were made for addventure-1.3.0-py3-none-any.whl:

Publisher: publish.yml on SmileyChris/addventure

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page