--- title: Hallway 8 emoji: 🚪 colorFrom: gray colorTo: indigo sdk: docker app_port: 7860 pinned: false --- # Hallway 8 [![Deploy to Hugging Face Spaces](https://huggingface.co/datasets/huggingface/badges/resolve/main/deploy-to-spaces-md.svg)](https://huggingface.co/new-space?sdk=docker) A small browser game about memory and doubt. You move through a place that should be identical every time. If anything differs from what you remember, **turn back**. If nothing has changed, **go on**. Reach the eighth loop without contradicting your own memory. Get it wrong and you start over. The trick is that the place is never described the same way twice. Only a handful of its details are mentioned each loop, and each is phrased from a pool of interchangeable sentences — so you can't compare two loops word-for-word. You're forced to remember *meaning*, not wording. Somewhere in that fog, one detail occasionally changes for real. ## Scenarios (arcs) The game ships with several **arcs** — each its own backstory, vocabulary, and visual skin, all sharing the one mechanic. You pick one from the opening screen. - **Hallway 8** — locked in after hours, you follow a sign to the fire exit and walk corridor after identical corridor toward the eighth fire door. - **Stairway 8** — the elevator is out of order, so you descend eight flights on foot, checking each landing before you keep going down to the ground floor. - **Coach 8** — the conductor sent you forward to coach 8, but the night train never seems to reach it; you walk carriage after identical carriage. Every arc carries more than physical changes: each has an **NPC** who is usually passive but can become the anomaly (turning to face you, moving, vanishing) — including a loop-aware twist where they *acknowledge you* — and a psychological `sense` layer where the wrongness is in perception, not objects (a corridor that feels too long, a calm that shouldn't be there). Arcs live as self-contained JSON files in `data/arcs/`. Adding a new one is just dropping in another file (see *Adding an arc* below) — no code changes needed. The design rules and the queue of future arcs are kept in [`docs/ARCS.md`](docs/ARCS.md). ## What makes it unsettling - **Partial description.** Each corridor has eight properties (lighting, sound, the man down the hall, the exit sign, a door, a camera, the floor, a poster), but only four to six are ever mentioned per loop. - **Rotating prose.** Every detail is drawn from several equivalent sentences, so the wording drifts even when nothing has actually changed. - **A single quiet mutation.** When a corridor *is* different, exactly one property has shifted to a plausible variant — nothing screams "look here." - **Confidence as a mechanic.** Before you commit, you rate how sure you are. - **A corridor that notices you.** Linger on one detail across loops and the narration begins to react to your habits. - **Presentation drift.** Heading, pacing, font weight, letter spacing, and the background shift a fraction each loop — felt more than seen. --- ## Run it locally You need **Python 3.9+** (any recent Python 3 works). **1. Get the code** ```bash git clone https://github.com/alvations/hallway8.git cd hallway8 ``` **2. (Optional but recommended) create a virtual environment** ```bash python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate ``` **3. Install the dependencies** ```bash pip install -r requirements.txt ``` **4. Start the server** ```bash python app.py ``` You'll see something like `Running on http://127.0.0.1:5000`. **5. Open the game in your browser** Go to **** and press **Begin**. To stop the server, press `Ctrl+C` in the terminal. ### Options | Variable | Default | What it does | |--------------|-------------|---------------------------------------------------------| | `PORT` | `5000` | Port the server listens on. | | `HOST` | `127.0.0.1` | Interface to bind. Use `0.0.0.0` to expose on a network.| | `SECRET_KEY` | random | Set a fixed value to keep sessions stable across restarts. | Example: `PORT=8000 python app.py` then open . --- ## Host it on Hugging Face Spaces This repo is ready to run as a **Docker Space**. The included `Dockerfile` serves the app on port `7860`, and the metadata block at the very top of this README is the Space card Hugging Face reads — so there's nothing extra to configure. **Prerequisites:** a free Hugging Face account (). For the git and CLI methods you'll also need a **write access token** from . ### Step 1 — create the Space Click the **Deploy to Spaces** badge at the top of this README, or go to and: 1. **Owner / Space name** — e.g. `hallway8`. 2. **SDK** — choose **Docker**, then the **Blank** template. 3. **Hardware** — the free **CPU basic** tier is plenty. 4. **Visibility** — Public or Private, your call. Create the Space. You now have an empty Space at `https://huggingface.co/spaces//hallway8`. ### Step 2 — get the code into the Space Pick whichever is easiest. All three upload the same files; the Space rebuilds on every change. **Option A — drag and drop (no tools needed)** In the Space's **Files** tab, click **Add file → Upload files** and upload the whole project. Make sure these are all present at the Space root: `Dockerfile`, `app.py`, `hallway.py`, `anomalies.py`, `memory.py`, `requirements.txt`, `README.md`, and the `data/`, `templates/`, and `static/` folders. **Option B — push with git** A Space is a git repo. Add it as a remote and push: ```bash git remote add space https://huggingface.co/spaces//hallway8 git push space main ``` When prompted, enter your **Hugging Face username** and paste your **access token** as the password. (To avoid the prompt, run `pip install -U huggingface_hub` then `hf auth login` once — it installs a git credential helper.) > If the Space was created with its own starter `README.md`, your first push may > be rejected as out of date. Either `git pull space main --rebase` first, or > `git push space main --force` to overwrite the starter files with this repo. **Option C — upload with the Hugging Face CLI** ```bash pip install -U huggingface_hub hf auth login # paste your write token once hf upload /hallway8 . . --repo-type=space ``` ### Step 3 — watch it build and play Open the Space's **Logs** (or **App**) tab. Hugging Face builds the Docker image and starts the container; the first build takes a couple of minutes. Once the status turns **Running**, the game plays right there in the browser at `https://huggingface.co/spaces//hallway8`. ### Recommended settings - In **Settings → Variables and secrets**, add a secret named `SECRET_KEY` with any long random string. This keeps player sessions valid across Space restarts. (Without it a fresh key is generated on each boot, which simply resets any in-progress runs.) - The free tier **sleeps after a period of inactivity** and wakes on the next visit — normal, and fine for a game like this. > **Why the Dockerfile pins a single worker:** the game keeps each corridor's > answer in server memory so the page can't be inspected to cheat. That state > lives in one process, so the app must run with a single worker (the Dockerfile > already does this). Don't scale it to multiple workers/replicas. ### Add your own "Open in Spaces" badge Once your Space is live, you can point people straight at it by adding this near the top of the README (swap in your username): ```markdown [![Open in Spaces](https://huggingface.co/datasets/huggingface/badges/resolve/main/open-in-hf-spaces-md.svg)](https://huggingface.co/spaces//hallway8) ``` ### Other hosts The same `Dockerfile` runs anywhere that takes a container — Fly.io, Render, Railway, Google Cloud Run, etc. Point the platform at the image (or use `gunicorn -w 1 --threads 8 -b 0.0.0.0:$PORT app:app`) and keep it to a single worker for the reason above. --- ## Layout ``` app.py Flask server; owns all game state, arc selection, and answers hallway.py loads an arc, builds and describes a loop anomalies.py anomaly selection + wording/heading drift memory.py tracks the player's habits across loops data/arcs/*.json one file per arc: meta/skin, properties, sentence pools, story templates/ the page static/ style (skins) + client logic (rendering, pacing, drift) Dockerfile container image for Hugging Face Spaces and other hosts ``` The browser only ever receives a description — never whether a place has changed — so you can't read the page source to cheat. ### Adding an arc Copy an existing file in `data/arcs/` and edit it. Each arc is fully self-contained: - **`meta`** — `id`, `title`, `tagline`, a `skin` name, the two action labels (`go_on` / `turn_back`), a `progress` HUD template (placeholders `{level}`, `{goal}`, `{floor}`, `{remaining}`), and friendly `labels` per property. - **`properties`** — each with a `baseline` value, a pool of interchangeable `values` sentences, and `anomalies` (each an alternate value with its own sentence pool). Only these ever change between loops. - **`title_variants`**, **`anchor_order`**, **`adaptive`**, and **`framing`** (the intro and win text). To give the arc its own colours, add a `body[data-skin=""]` block in `static/style.css`. The new arc appears automatically on the opening screen — no code changes required.