A living ASCII ecosystem simulation for your terminal
Project description
Terrarium
A living ASCII ecosystem that runs in your terminal. Watch plants spread, herbivores graze and predators hunt—all while you leave your terminal open.
Overview
Terrarium is an idle simulation game. The player watches—and occasionally nudges— a self-sustaining world of plants, herbivores and predators. The core fantasy is:
"I grew something beautiful just by leaving my terminal open."
Requirements
- Python 3.11+
rich- A terminal at least 80 × 24 characters (120 × 30+ recommended)
Installation
Install from PyPI
pip install terrarium-game
terrarium-game
Install from source
git clone https://github.com/minoangelo/terrarium
cd terrarium
pip install -r requirements.txt
python main.py
Controls
| Key | Action |
|---|---|
r |
Drop rain: boosts all moisture for 20 seconds |
f |
Fertilise a random region: boosts nutrients |
h |
Introduce a new herbivore |
p |
Place a new predator (if below the cap) |
q |
Quit and save |
The game is designed to be satisfying to watch without touching the keyboard.
How It Works
The Grid
The world is a 2-D tile grid (up to 60 × 24, scaled to your terminal). Each tile tracks moisture and nutrients (0–100) that slowly regenerate over time. Static water tiles (~) boost nearby moisture. Dead organic matter (%) fertilises the soil as it decays.
Plants
| Symbol | Name | Behaviour |
|---|---|---|
, |
Seedling | Grows into a bush after ~30 s if soil is fertile |
♣ |
Bush | Grows into a tree after ~120 s; spreads seeds more aggressively |
↑ |
Tree | Fully mature; highest seed-spread rate |
Plants die when soil nutrients reach zero, leaving organic matter behind.
Animals
| Symbol | Name | Cap | Behaviour |
|---|---|---|---|
o |
Herbivore | 20 | Wanders and eats adjacent plants; reproduces when well-fed |
@ |
Predator | 5 | Hunts the nearest herbivore within 5 tiles; second one unlocks at 2 min |
Both animals starve if hunger reaches 100—health then decays until death, leaving organic matter.
Milestones
| Milestone | Trigger |
|---|---|
| First Tree Matured | A tree reaches full growth |
| Old Growth Forest | More than 10 trees exist simultaneously |
| Population Boom | Herbivore count exceeds 12 |
| Ecosystem Balanced | All three species co-exist for 60 consecutive seconds |
| Apex Predator | A predator survives 5+ minutes (it earns a name) |
| The Great Dying | All herbivores go extinct |
Save Files
The game auto-saves every 30 seconds to ~/.terrarium/save.json. On next launch
you will be asked whether to resume. Quitting with q always saves immediately.
Project Structure
terrarium/
├── main.py # Entry point, game loop, keyboard input
├── world.py # Grid, Tile and soil simulation
├── entities.py # Entity classes and per-tick simulation logic
├── renderer.py # Rich layout, viewport drawing, sidebar
├── events.py # Event log and milestone tracking
├── persistence.py # JSON save/load
├── state.py # Shared runtime/render state dataclasses
└── requirements.txt
Contributing
Contributions are welcome. This project currently uses a lightweight workflow.
1) Set up locally
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
2) Run and validate
# run the app
python main.py
# basic syntax/import check
python -m compileall .
# lint (primary)
pylint main.py <file>
# lint tests (with project root on PYTHONPATH)
PYTHONPATH=. pylint tests/<file>
# optional fast lint
ruff check .
3) Tests
The repository includes tests under tests/. Use pytest to run them, and keep
adding coverage there as features and bug fixes evolve.
# run all tests
pytest
# run a single test file
pytest tests/test_entities.py
# run a single test case
pytest tests/test_entities.py::test_predator_moves_toward_nearest_prey
# run by expression
pytest -k "predator and not slow"
4) Commit and PR style
- Follow Conventional Commits
(for example:
feat: ...,fix: ...,docs: ...). - Keep changes focused and small when possible.
- In your PR description, include:
- what changed,
- why it changed,
- which validation commands you ran.
5) Releases and PyPI publishing
- Versioning and release PRs are automated with Release Please.
- Conventional Commit messages are used to determine version bumps and changelog entries.
- Publishing to PyPI runs from GitHub Actions when a GitHub Release is published.
- Configure PyPI trusted publishing for this repository before the first release.
6) Scope guidance
- Keep architecture boundaries intact:
world.pyfor terrain/soil rules,entities.pyfor simulation behavior,renderer.pyfor presentation,persistence.pyfor save/load,main.pyfor orchestration and input loop.
- Avoid blocking I/O in the main loop.
- Preserve save compatibility where practical.
License
See LICENSE.md.
Contact
- Carmine (Mino) Siena, dev@mino-siena.de
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 terrarium_game-1.1.0.tar.gz.
File metadata
- Download URL: terrarium_game-1.1.0.tar.gz
- Upload date:
- Size: 27.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b470b10a4e015506b231debe6fd7cd00f8238cb1d0790a82a3527b221eccc68f
|
|
| MD5 |
05658036661203a1df3866706460148c
|
|
| BLAKE2b-256 |
238ebd32ef916563e72a458aa24fc59970e3f188a83724a1bc88cabc458e98b4
|
Provenance
The following attestation bundles were made for terrarium_game-1.1.0.tar.gz:
Publisher:
publish-pypi.yml on Minoangelo/terrarium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
terrarium_game-1.1.0.tar.gz -
Subject digest:
b470b10a4e015506b231debe6fd7cd00f8238cb1d0790a82a3527b221eccc68f - Sigstore transparency entry: 1239341886
- Sigstore integration time:
-
Permalink:
Minoangelo/terrarium@4a17844eca945c84951a6e383b79998ef54fbdff -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/Minoangelo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4a17844eca945c84951a6e383b79998ef54fbdff -
Trigger Event:
release
-
Statement type:
File details
Details for the file terrarium_game-1.1.0-py3-none-any.whl.
File metadata
- Download URL: terrarium_game-1.1.0-py3-none-any.whl
- Upload date:
- Size: 21.4 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 |
f362207a2e83d126bac0463cca997fddbe0510ec56e9794f89091f4d0c3331c8
|
|
| MD5 |
edae1745724fb1f7bda7c527effd44f6
|
|
| BLAKE2b-256 |
4092ad6975e3ffabfa0c578a805b8c66896d8444df70b5a29458aa98d917f133
|
Provenance
The following attestation bundles were made for terrarium_game-1.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on Minoangelo/terrarium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
terrarium_game-1.1.0-py3-none-any.whl -
Subject digest:
f362207a2e83d126bac0463cca997fddbe0510ec56e9794f89091f4d0c3331c8 - Sigstore transparency entry: 1239341887
- Sigstore integration time:
-
Permalink:
Minoangelo/terrarium@4a17844eca945c84951a6e383b79998ef54fbdff -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/Minoangelo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4a17844eca945c84951a6e383b79998ef54fbdff -
Trigger Event:
release
-
Statement type: