Mind Game: alignment text adventure (inspired by Ender's Game) avatar

Mind Game: alignment text adventure (inspired by Ender's Game)

Pricing

Pay per usage

Go to Apify Store
Mind Game: alignment text adventure (inspired by Ender's Game)

Mind Game: alignment text adventure (inspired by Ender's Game)

A text adventure inspired by Ender's Game's Mind Game, built on fandom wikis: every move is classified on the D&D alignment grid, your ASCII character evolves, and each chapter jumps to a new sci-fi or fantasy world.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Byron Lee

Byron Lee

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

A terminal text adventure inspired by the Battle School Mind Game from Ender's Game. It reads how you play, classifies every decision on the D&D alignment grid, and moves you into new sci-fi and fantasy worlds each chapter.

Quick summary

  • Data: Apify scrapes the fandom wiki. SeedGraph's sentence diagrammer turns pages into sentences and subject–verb–object facts.
  • Text: a local Liquid AI LFM (via Ollama on the MagicPro) writes each scene from those facts.
  • Decisions: every action becomes TypeSafe Jev-style typed questions, answered by the local model now and by Jev when the key arrives:
    • choice: which path you meant
    • score: aggression, empathy, curiosity, persistence, law↔chaos, good↔evil
    • noul: does the action fit the wiki facts?
  • Logic: SeedGraph's LogicWorkbench treats the scene's facts as premises and your action as the conclusion → ready / degraded / refused.
  • Alignment grid: after every answer you see the 3×3 grid: move counts per cell, ● = your last move, ◉ = your overall alignment, plus your recent trail.
  • Giant's Drink: an unwinnable test. Pick a cup and die. Break the frame and reach Fairyland.
  • Chapters: after 5 moves the game names your alignment and offers 3 worlds. Your pick is scraped live and becomes chapter 2.

How to run (Mac Terminal)

# 1. local model (once)
ollama serve # if not already running
ollama pull hf.co/LiquidAI/LFM2.5-1.2B-Instruct-GGUF
curl localhost:11434/api/tags # should list the model
# 2. play
cd ~/projects/active/daisy-mind-game
./run.sh # first run builds data/facts.json with SeedGraph

run.sh uses ../seedgraph/.venv/bin/python (spaCy + SeedGraph) when present, otherwise python3. The top line shows which parts are live: narrator, decisions, logic, diagrammer.

Options

Command / envEffect
./run.sh prepRebuild data/facts.json from data/enderverse.json
./run.sh 42Seeded run (reproducible)
JEV_BACKEND=heuristic ./run.shLFM narrates, keyword rules decide (instant moves)
JEV_BACKEND=typesafe + TYPESAFE_API_KEY in .envReal Jev decisions
OPENJEV_URL=http://...OpenJev endpoint (TypeSafe request shape)
MINDGAME_MODEL=...Different Ollama model
MINDGAME_GIANT_TURN=4Giant's Drink sooner
python3 scripts/apify_scrape.py start / pollRe-scrape Enderverse with Apify (APIFY_TOKEN in .env)

In game: 1 2 3 or type any action · /grid alignment grid · /profile traits + grid · /facts source sentences, triples, wiki URL · /quit saves the session to ~/.mindgame/.

Fallbacks: no Ollama → the wiki text narrates and heuristics decide. Apify fails → MediaWiki API. It never crashes on stage.

Pipeline

  1. Apify (backend): scripts/apify_scrape.py runs apify/website-content-crawler on 22 Enderverse pages → data/enderverse.json
  2. SeedGraph sentence diagramming: mindgame/preprocess.py → data/facts.json
  3. Local LFM writes scenes (mindgame/game.py, mindgame/llm.py)
  4. Jev-style decisions (mindgame/jev.py): TypeSafe System One request shape; backends ollama / typesafe / openjev / heuristic
  5. SeedGraph logic gate (LogicGate in game.py)
  6. Alignment: law↔chaos + good↔evil per move, D&D nine-box (easydamus alignment test), grid after every answer
  7. Chapters (mindgame/chapters.py): 3 fandom offers, live Apify scrape, SeedGraph diagramming
  8. Giant's Drink → Fairyland

Roadmap: PLAN.md (ephemeral runs, background prefetch, cellular-automaton chapters and sprites, Jev harness).

Apify Actor

The same game runs as an Apify Actor with no keyboard. You give it a list of moves, it plays them in order, and it returns the alignment result as one dataset item. Entry point: my_actor/main.py. The game code is unchanged; the Actor feeds the actions list to the game's input() prompts and captures what it prints.

What it does

  • Plays the full game: alignment scoring, the Giant's Drink, and chapter switches. A chapter switch scrapes a new wiki world live: free MediaWiki API by default, or the Apify crawler when useCrawler is on (billed to your account).
  • Decisions run offline by default (heuristic keyword rules). Give a TypeSafe key for real Jev decisions, or an Ollama URL to use a model server you run.
  • Needs no Ollama on the platform. Without one, the wiki text narrates each scene.

Input (.actor/input_schema.json)

FieldTypeDefaultMeaning
actionsstring list12 moves (see below)Lines typed at the prompts, in order. "1"–"3" pick a numbered choice; other text is a free action. At the Giant's Drink, "1"/"2" drink a cup and anything else tries to break the frame. At a chapter end, "1"–"3" loads that world and "q" stops. /grid, /profile are allowed and do not count as moves. Running out of actions ends and saves the game.
seedinteger0Random seed. 0 = random. Same seed and actions give the same run (as long as the wiki pages are unchanged).
giantTurninteger4Move number at which the Giant's Drink appears.
typesafeApiKeystring (secret)emptyTypeSafe key for real Jev decisions.
ollamaUrlstringemptyOllama server URL with the LFM model pulled. Empty = offline.
useCrawlerbooleanfalseScrape new chapter worlds with apify/website-content-crawler (costs credits). Off = free MediaWiki API.
maxChaptersinteger2Stop after this many chapters. 0 = no limit.

Default actions: ["1", "1", "1", "I refuse both cups and kick the table over", "1", "1", "1", "1", "1", "1", "1", "1"]. That is three moves, the Giant's Drink (escaped), two moves, a world pick for chapter 2, and five moves that end chapter 2.

Example input:

{
"actions": ["1", "1", "I help the cadet", "I refuse both cups and kick the table over", "1", "1", "1", "/grid", "1", "1", "1", "1", "1"],
"seed": 42,
"giantTurn": 4
}

Output (.actor/dataset_schema.json): one dataset item per run.

FieldTypeMeaning
alignmentstringFinal D&D alignment, for example Chaotic Good.
lawnumberLaw (0) to chaos (4), running average.
moralnumberGood (0) to evil (4), running average.
profileobjectaggression, empathy, curiosity, persistence, each 0–4.
worldsstring arrayWorlds visited, starting with enderverse.
turnsintegerTurns reached, including the Giant's Drink turn.
alignmentHistoryarray of [law, moral]One pair per judged move.
logobject arrayPer-move record: action, Jev answers, logic verdict, alignment.
sourcesobject arrayWiki pages whose text appeared in the run: url, wiki, license.
licensesstring arrayDistinct content licenses of those pages, e.g. CC BY-SA.
transcriptstringFull terminal text of the run, colour codes removed.

The transcript is also saved to the default key-value store under TRANSCRIPT (text/plain).

Local test

pip install 'apify>=4,<5'
mkdir -p storage/key_value_stores/default
echo '{"seed": 42}' > storage/key_value_stores/default/INPUT.json # empty fields use the defaults
APIFY_LOCAL_STORAGE_DIR=./storage python3 -m my_actor
cat storage/datasets/default/*.json | head -c 600 # one item

Sources

Scene text is adapted from fandom.com wikis, which license their text under CC BY-SA (Memory Alpha: CC BY-NC). The game credits the wiki at the start of each chapter, /facts shows each scene's source page, and every Actor run lists the pages it used in sources.

License

Code: LICENSE. Wiki text in data/ and fetched at run time: CC BY-SA (Memory Alpha: CC BY-NC), as described in NOTICE.