Colossal Cave Adventure over Gemini
Project description
Colossal Cave Adventure over Gemini
A faithful port of the classic 350-point Colossal Cave Adventure (Crowther & Woods, 1977) served over the Gemini protocol. Players explore the cave, solve puzzles, and collect treasure — all through a Gemini client.
Built with xitzin (a Gemini web framework) and nauyaca (a Gemini server).
Features
- Full 350-point game with all rooms, items, puzzles, and encounters from the original
- Player authentication via Gemini client certificates
- Per-player game state persisted in SQLite
- Dwarf and pirate encounters with faithful AI behavior
- Structured logging with optional fingerprint hashing for privacy
Quickstart
Requires Python 3.13+ and uv.
# Install dependencies
uv sync
# Generate TLS certificates (required for Gemini)
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-days 365 -nodes -keyout key.pem -out cert.pem \
-subj "/CN=localhost"
# Start the server
ADVENTURE_CERTFILE=cert.pem ADVENTURE_KEYFILE=key.pem uv run adventure
Then connect with any Gemini client to gemini://localhost:1965/.
Configuration
All settings are read from environment variables prefixed with ADVENTURE_:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
sqlite:///./adventure.db |
SQLite database path |
HOST |
localhost |
Bind address |
PORT |
1965 |
Bind port |
CERTFILE |
— | Path to TLS certificate (required) |
KEYFILE |
— | Path to TLS private key (required) |
LOG_LEVEL |
INFO |
Logging level |
LOG_FILE |
— | Log to file instead of stdout |
JSON_LOGS |
false |
Output logs as JSON |
HASH_FINGERPRINTS |
true |
Hash client fingerprints in logs for privacy |
Project Structure
src/adventure/
├── engine/ # Synchronous, pure-Python game logic
│ ├── world.py # Immutable data structures (Room, Obj, Word, Hint, World)
│ ├── state.py # Mutable GameState (position, inventory, lamp, dwarves, score)
│ ├── loader.py # Parses the 12-section advent.dat into a World
│ └── commands.py # Command dispatch: movement, items, puzzles, combat, scoring
├── routes/ # Xitzin route handlers
│ ├── play.py # Game routes (require client certificate)
│ └── home.py # Public pages: /, /help, /about
├── templates/ # Jinja2 .gmi templates for Gemtext responses
├── app.py # App factory
├── config.py # Configuration from environment variables
├── logging.py # structlog setup
├── models.py # SQLModel entities (Player, SavedGame)
├── session.py # Load/save/reset game state from DB
└── users.py # Player upsert by fingerprint
data/
└── advent.dat # Original game data file
Development
# Run tests
uv run pytest
# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/
# Type check
uv run ty check src/
Credits
- Original game: Will Crowther (1976) and Don Woods (1977)
- Data file format: Public domain
- Parsing reference: Brandon Rhodes' python-adventure (Apache 2.0)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file adventure_gemini-0.1.5.tar.gz.
File metadata
- Download URL: adventure_gemini-0.1.5.tar.gz
- Upload date:
- Size: 49.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6994dfb64cfbc6494d980c0d94c5b5c1e2b2ca1629bcd1ab61030606b2098993
|
|
| MD5 |
ffbe8ff39d20eb7537d4de192fbf7855
|
|
| BLAKE2b-256 |
d5cd37ef05d5a5a042527890ad59f8b41ce4e3a786295571467b54edc1be6036
|
Provenance
The following attestation bundles were made for adventure_gemini-0.1.5.tar.gz:
Publisher:
release-pypi.yml on alanbato/adventure-gemini
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adventure_gemini-0.1.5.tar.gz -
Subject digest:
6994dfb64cfbc6494d980c0d94c5b5c1e2b2ca1629bcd1ab61030606b2098993 - Sigstore transparency entry: 1188981874
- Sigstore integration time:
-
Permalink:
alanbato/adventure-gemini@59c44c402f8b3849d59d6498a86b7d3e42bb245f -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/alanbato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@59c44c402f8b3849d59d6498a86b7d3e42bb245f -
Trigger Event:
push
-
Statement type:
File details
Details for the file adventure_gemini-0.1.5-py3-none-any.whl.
File metadata
- Download URL: adventure_gemini-0.1.5-py3-none-any.whl
- Upload date:
- Size: 55.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3ad5b5b6cf0589ece10f69e43b883c3b50c53b9594920bcff71c2f148fb6afa
|
|
| MD5 |
9612c5dbb9a2d51c73ba0d336338ffd8
|
|
| BLAKE2b-256 |
e21c7bdcf4eacb6e3ddf6e0ded7a6d3d82feee258bc16be1064189a4abe3aeed
|
Provenance
The following attestation bundles were made for adventure_gemini-0.1.5-py3-none-any.whl:
Publisher:
release-pypi.yml on alanbato/adventure-gemini
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adventure_gemini-0.1.5-py3-none-any.whl -
Subject digest:
b3ad5b5b6cf0589ece10f69e43b883c3b50c53b9594920bcff71c2f148fb6afa - Sigstore transparency entry: 1188981875
- Sigstore integration time:
-
Permalink:
alanbato/adventure-gemini@59c44c402f8b3849d59d6498a86b7d3e42bb245f -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/alanbato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@59c44c402f8b3849d59d6498a86b7d3e42bb245f -
Trigger Event:
push
-
Statement type: