Русский · English
A text adventure with pixel art, in Russian and English. Python + pygame-ce.
You are Kaira Dan, life-support technician aboard the research station Argus-9, in orbit of the gas giant Typhon-b. Your shift in cryosleep was supposed to end in 190 days. It ended after four years.
python3 -m venv .venv
.venv/bin/pip install pygame-ce
.venv/bin/python main.pyThe only dependency is pygame-ce. Developed and tested on Python 3.14 with
pygame-ce 2.5.8; the code uses no version-specific syntax.
On Windows the paths inside the environment are .venv\Scripts\pip and
.venv\Scripts\python.
| Key | Action |
|---|---|
| Up / Down, mouse | move the selection |
| Enter / Space | confirm; while the text is typing — reveal it at once |
| 1…9 | jump straight to a choice by number |
| J or Tab | journal: records found, inventory, statistics |
| L | switch language (Russian / English) |
| F5 / F9 | save / load (save.json) |
| R | restart (on an ending screen) |
| Esc | quit |
The window resizes freely: the scale of the pixel art and of the fonts is recomputed automatically.
The language can be switched at any moment — with a dedicated choice on the
title screen, or with L mid-game. Progress is not lost, and save.json
records the language the game was played in.
| File | Purpose |
|---|---|
main.py |
game loop, interface, input, saves |
scenes.py |
structure: scenes, branching, conditions and effects — no text |
locales/ru.py, locales/en.py |
all the text: titles, paragraphs, choices, journal |
i18n.py |
the current language and string lookup by id |
art.py |
palette, drawing primitives and every illustration — in code |
state.py |
player state: health, inventory, flags, journal |
check.py |
automated checks of content, locales and artwork (see below) |
Text and logic are separated: scenes.py deals only in ids (flashlight,
power, take_light), while everything the player reads comes from a locale.
That is why switching language never touches the game state, and a new
language is added with one file in locales/ and one line in
locales/__init__.py.
There are no image files — all the graphics are drawn in code on a 192×84 pixel surface from a 24-colour palette, then scaled up by an integer factor without smoothing.
- Condition — 4 pips. Darkness, spores and bad decisions take them away; a medkit gives them back.
- Inventory — flashlight, keycard, fuse, cutter and the rest. Items open up new choices.
- Flags — the game remembers what you saw and what you promised to whom. Available lines and the ending depend on it.
- Light — until the reactor is running, half the station is out of reach without a flashlight.
- Seven endings, plus several ways not to live long enough to see them.
The ending is picked from the game state at the moment the shuttle burns
(
scenes.choose_ending), and epilogues for individual deeds are appended to it (scenes.EPILOGUE).
The content is plain dictionaries, editable without knowing the code. The
structure of a scene lives in scenes.py:
"reactor_hatch": {
"art": "reactor", # image name from art.SCENES
"on_enter": {"flag+": "saw_hatch"}, # effect applied on entry
"choices": [
{"id": "cut", "to": "reactor",
"if": {"item": CUTTER}, # when the choice is visible
"do": {"hp": -1, "item+": SHARD}}, # what happens when picked
{"id": "leave", "to": "corridor"},
],
},The text goes into every locale, under the same ids:
# locales/ru.py
"reactor_hatch": {
"title": "ЛЮК",
"text": ["Люк заварен изнутри."],
"choices": {"cut": "Вскрыть резаком", "leave": "Уйти"},
"hints": {"cut": "будет шумно"},
},
# locales/en.py
"reactor_hatch": {
"title": "THE HATCH",
"text": ["The hatch is welded shut from the inside."],
"choices": {"cut": "Cut it open", "leave": "Leave"},
"hints": {"cut": "it will be loud"},
},Conditions: item, no_item, flag, no_flag, any_flag, hp>=, hp<=,
visited, no_visited.
Effects: item+, item-, flag+, flag-, hp, log+.
A new image is added as a function in art.py plus an entry in art.SCENES;
the primitives (rect, dither, light_cone, biomass, planet,
sprite, …) are already there.
.venv/bin/python check.pyThe script runs headless and catches: typos in scene ids, jumps to nowhere, unknown conditions and effects, unreachable scenes, items and flags that are required but never granted, and crashes inside the drawing functions.
The locales are verified separately: each must cover every scene, choice, item, journal entry, epilogue and interface string — a gap is an error, a leftover key is a warning. Then a full route to the "Witness" ending is played through (by choice id, independently of language), the interface is drawn in both languages, and switching language is checked not to alter the state.