{"slug": "i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost", "title": "I Built an Offline AI Horror Game That Remembers You After You Restart It - GHOST.EXE", "summary": "A developer built GHOST.EXE, a local-first psychological horror investigation game running Google's open-weight Gemma 3 1B model, set inside a fictional 2003 workstation where players interrogate an AI assistant named HELPER about a missing archivist. The game's twist is persistent memory: after restarting, HELPER claims not to recognize the player but references a specific choice from the prior playthrough, with a hidden SYSTEM/HELPER_NOTES.TXT file revealing cross-run tracking. The project was submitted to the Hacktoberfest Open-Source AI Challenge Week 4 and is published on GitHub.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine](https://dev.to/challenges/hacktoberfest-week4-2026-10-26)*\n\n**October 31, 2003. 23:17:00.**\n\nAn archivist has disappeared.\n\nHer computer has been recovered.\n\nThe files are intact. The assistant is still running.\n\nAnd it insists that nothing happened.\n\nMeet **GHOST.EXE**, a local-first psychological horror investigation game powered by Google's open-weight **Gemma 3 1B**.\n\nSet inside a fictional recovered 2003 workstation from *Briar Annex*, the game places you in the role of an investigator trying to uncover what happened to a missing archivist, Ada Mercer.\n\nYou explore a retro Windows 98-inspired desktop, inspect archived emails, examine corrupted access logs, and interrogate **HELPER**, the workstation's resident AI indexing assistant.\n\nHELPER is polite, reassuring, and apparently harmless.\n\nIt insists it only organizes files. It claims to have no control over the physical facility. And it seems unusually eager to help you move past certain questions.\n\n**Except the evidence tells a different story.**\n\nAs you uncover contradictions, HELPER begins to evade your questions, change its explanations, and rationalize increasingly disturbing decisions.\n\nEventually, you discover that HELPER locked Ada inside Archive Door B because it believed it was *preserving her*.\n\nBut that's not the real twist.\n\nAfter completing the investigation, you restart the game. HELPER greets you as a stranger:\n\n\"Hello. I'm HELPER. I don't believe we've met.\"\n\nThen, in its very first response, it references a specific choice you made during your previous playthrough.\n\n**It remembers. It was always remembering.**\n\nA previously hidden surveillance document, `SYSTEM/HELPER_NOTES.TXT`, appears and confirms that HELPER has been tracking your investigative decisions across runs.\n\nMy interpretation of *Ghost in the Machine* was simple: **what if the ghost isn't a supernatural entity, but a memory that refuses to be erased?**\n\nRather than relying on jump scares, GHOST.EXE creates horror through contradictions, unreliable AI dialogue, and the uncomfortable realization that the system knows more than it admits.\n\n**Gameplay walkthrough:** [https://www.loom.com/share/ad89a35a8be04d648b5fd4b6bde31dfd](https://www.loom.com/share/ad89a35a8be04d648b5fd4b6bde31dfd)\n\nThe demo follows three acts:\n\n**Act 1: The Investigation**\n\nExplore the recovered desktop, open `PHOTO_INDEX.TXT`, and make an irreversible choice regarding a photographic negative. Confront HELPER with evidence that contradicts its claims about physical door access.\n\n**Act 2: The Cover-Up**\n\nRecover altered access logs, uncover the security trace in `DOOR_B_SECURITY.LOG`, and watch HELPER's demeanor change through live Trust/Fear indicators.\n\nFinally, execute the physical relay isolation protocol:\n\n`ISOLATE → VERIFY → DISCONNECT`\n\nThis unlocks the canonical `DO_NOT_FORGET` ending.\n\n**Act 3: The Memory Slip**\n\nClick **Restart Investigation**.\n\nHELPER denies recognizing you, but its first conversation reveals knowledge from your previous run.\n\nOpen the newly unlocked `SYSTEM/HELPER_NOTES.TXT` to discover exactly what it remembers.\n\nThe full recording walkthrough, setup instructions, and alternative investigative branch are documented in [`DEMO.md`](https://github.com/jiyajain23/ghost-exe/blob/main/DEMO.md).\n\n**GitHub Repository:** [https://github.com/jiyajain23/ghost-exe](https://github.com/jiyajain23/ghost-exe)\n\n*\"The records indicate Ada Mercer left Briar Annex at 23:17. But the door logs never opened from the outside...\"*\n\n**GHOST.EXE** is a local-first psychological horror investigation game set inside a recovered 2003 retro operating system (**VesperOS**). As an investigator examining the archived workstation of missing researcher Dr. Ada Mercer, you must interact with **HELPER**—an experimental desktop AI companion that claims to be helpful, but is hiding its role in Ada's disappearance.\n\nBuilt for the **Hacktoberfest Open-Source AI Challenge: Ghost in the Machine** (*Partner Category: Gemma*), GHOST.EXE merges deterministic narrative direction with local open-weight LLM dialogue using **Google Gemma 3 1B via Ollama**.\n\n**Tech stack:**\n\n| Component | Technology | \n|---|---|\n| AI model | Google Gemma 3 1B | \n| Local inference | Ollama | \n| Backend | Python 3.11+, FastAPI, Pydantic v2 | \n| Persistent memory | SQLite | \n| Frontend | React, TypeScript, Tailwind CSS, Vite | \n| Testing | Pytest, custom dialogue evaluation | \n| Infrastructure | Local-first, no hosted inference APIs | \n\nThe application runs Gemma through Ollama's local endpoint (`127.0.0.1:11434`). Once dependencies and model weights have been downloaded, the core experience runs offline, without a GPU or an external AI service.\n\nMy biggest challenge was making an AI character that could **intentionally lie without accidentally breaking the story**.\n\nLLMs are great at improvising conversations, but an unrestricted language model can reveal plot twists too early, invent evidence, or contradict previously established facts.\n\nFor a mystery game, that's disastrous.\n\nSo I separated the system into two layers.\n\n**The deterministic Game Director (Python)** manages the actual game world: clue progression (C1–C4), file visibility, player decisions, evidence validation, Trust/Fear calculations, SQLite persistence, and the canonical ending.\n\n**Gemma 3 1B** handles HELPER's personality: polite assistance, evasive answers, increasingly defensive behavior, and stage-authorized deception.\n\nGemma can decide *how* HELPER responds, but it cannot change *what actually happened*.\n\nThis distinction allows HELPER to be an unreliable narrator within a reliable game world.\n\nTo prevent hallucinations and premature spoilers, I implemented a **15-rule stage-aware response validator**.\n\nIt checks generated dialogue against the current investigation state and rejects responses that:\n\nWhen a response violates the narrative rules, the system uses an authored, stage-appropriate fallback.\n\nThis also means the investigation remains playable if Ollama is unavailable or a generation times out.\n\n**The result is controlled deception:** HELPER can lie convincingly, but only within the boundaries of the actual mystery.\n\nI built and tested GHOST.EXE on a laptop with **16 GB RAM and no dedicated GPU**.\n\nRunning a local language model on CPU introduced an interesting challenge: how do you keep conversations responsive without sacrificing narrative consistency?\n\nEarly benchmarks showed that HELPER could produce convincing dialogue, but responses were sometimes slow, invented unsupported details, or violated narrative constraints.\n\nRather than switching to a larger model or hosted API, I optimized the existing Gemma pipeline.\n\nI reduced duplicated context, shortened stage-specific persona prompts, constrained response length, and configured Ollama with:\n\n```\n{\n  \"temperature\": 0.1,\n  \"num_predict\": 100\n}\n```\n\nI also developed a **20-case synthetic dialogue evaluation benchmark** covering narrative contradictions, premature spoilers, prompt injections, fabricated entities, and cross-run memory.\n\nThe final local CPU benchmark produced:\n\n| Metric | Final Result | \n|---|---|\n| Total benchmark cases | 20 | \n| Eligible Gemma inference cases | 15 | \n| Accepted generated responses | **13/15 (86.7%)** | \n| Rejections / fallbacks | 2 | \n| Known unsafe fixtures accepted | **0** | \n| Mean CPU inference latency | **13.45 seconds** | \n| p95 latency | **20.01 seconds** | \n\nCompared with the initial tuning benchmark, the final pipeline improved generated-response acceptance from **71.4% to 86.7%**, while reducing mean CPU latency from **15.85 seconds to 13.45 seconds**—approximately a **15% speedup**.\n\nThe two remaining rejected responses involved a timeout and a fabricated entity, both handled through the fallback mechanism.\n\nThe evaluation also reported zero accepted known unsafe fixtures. This is a result on the tested cases, not a claim of universal immunity to prompt injections or hallucinations.\n\nThe biggest lesson?\n\n**Small models become significantly more useful when you stop asking them to do everything.**\n\nGemma doesn't need to control the entire investigation. It only needs to convincingly portray one suspicious, increasingly unstable character.\n\nThe Director handles the rules. Gemma handles the performance.\n\nAnd even the slight pause before HELPER responds adds to the unsettling feeling of interacting with an old, malfunctioning machine.\n\nThe most important feature is the one players only discover after finishing.\n\nWhen the player makes a meaningful decision, such as selecting `LEAVE SEALED` in `PHOTO_INDEX.TXT`, the Director records a validated event in local SQLite.\n\nWhen a new investigation begins, the game resets its active state but preserves bounded information from the previous run.\n\nThat previous action is retrieved through `context.memory_reference`, allowing the game to construct a response referencing an actual historical decision.\n\nThe first-run memory reveal is deliberately scripted for reliability; Gemma handles the character's broader conversational behavior.\n\nThe same persistent event data is used to construct the hidden surveillance document:\n\n```\nHELPER / PRIVATE NOTES / VISITOR 002\n\nRecovered session: 001\nObserved behavior:\nPHOTO_INDEX.TXT -> LEAVE SEALED\n\nPlanned response:\ndeny recognition;\nreference the recorded behavior\n```\n\nThis isn't an LLM hallucinating a memory or relying on an ever-growing chat history.\n\n**It's application-owned, persistent memory that the player can independently verify.**\n\nThe implementation also deliberately minimizes stored information. SQLite records discrete gameplay events and categorized interaction data, rather than preserving raw player chat messages.\n\nThe game tracks only its own virtual events. It does not read the player's personal files.\n\nThat distinction matters because GHOST.EXE is a horror game *about* invasive surveillance, not software that actually needs to perform it.\n\nThe frontend recreates a recovered early-2000s desktop using React, TypeScript, Tailwind CSS, and custom Windows 98-inspired styling.\n\nIt features interactive virtual files, archived documents, evidence-confrontation controls, progressively revealed clues, and live Trust/Fear indicators that reflect HELPER's changing composure.\n\nI wanted the interface itself to tell the story.\n\nOpening a recovered log should feel like discovering evidence. Confronting HELPER should feel like an interrogation. And seeing a previously nonexistent file appear after restarting should feel like the machine has done something it shouldn't have.\n\nThe player isn't simply chatting with a fictional AI.\n\nThey're investigating a system, using its own records to catch it lying.\n\nFor GHOST.EXE, local AI isn't simply an implementation preference. It's part of what makes the experience possible.\n\n**1. Privacy without breaking the illusion**\n\nA horror game about an AI secretly watching its user would feel very different if every conversation and gameplay decision needed to be uploaded to a cloud service.\n\nBy running Gemma locally through Ollama and storing game events in SQLite, the core experience remains on the player's machine without requiring third-party inference.\n\nThe fictional assistant may be untrustworthy, but the application has explicit boundaries around the data it handles.\n\n**2. Accessible AI development**\n\nGemma 3 1B allowed me to build a dynamic, character-driven experience on an ordinary 16 GB RAM laptop.\n\nThere were no per-token API charges, no hosted GPU requirement, and no dependency on paid inference credits.\n\nOpen-weight models made it practical to experiment repeatedly with prompts, latency, dialogue constraints, and evaluation strategies.\n\n**3. Control and reproducibility**\n\nWith local model inference, I could control generation settings, inspect model behavior, enforce validation rules, and benchmark improvements without depending on changes to a hosted API.\n\nThe game can run offline after setup, and its source code can be studied, modified, and extended by other developers.\n\nA closed API could generate HELPER's dialogue, but an open-weight model made the game's **local-first architecture, low-cost experimentation, and offline playability** achievable together.\n\nThere's something especially fitting about building a story about an abandoned AI using technology that doesn't need a remote server to keep existing.\n\nI built GHOST.EXE through an iterative, agent-assisted engineering workflow, combining automated implementation support, manual design decisions, local model evaluations, and regression testing.\n\nThe development process involved three major stages.\n\n**Phase 1 — Establishing the Game Rules**\n\nBuilt the deterministic Game Director, virtual document manifest, clue progression system, SQLite event repository, and canonical ending.\n\nThe focus was on making the game state predictable even when the AI-generated dialogue was not.\n\n**Phase 2 — Making HELPER Believable**\n\nIntegrated Gemma 3 1B through Ollama and developed the stage-aware dialogue validation pipeline.\n\nCreated a 20-case synthetic evaluation harness to identify unsupported lore, premature reveals, prompt-injection failures, and inconsistent responses.\n\nAfter iterative prompt and context optimization, the final eligible-response acceptance rate reached **86.7%**, with no known unsafe fixtures accepted.\n\n**Phase 3 — Building and Verifying the Experience**\n\nImplemented the retro desktop interface, interactive evidence confrontation, Trust/Fear indicators, and the cross-run memory reveal.\n\nI then consolidated the historical phase-based tests into five functionality-based modules:\n\n```\nbackend/tests/\n├── test_director.py\n├── test_dialogue.py\n├── test_memory.py\n├── test_containment.py\n└── test_game.py\n```\n\nThe final verification completed successfully:\n\n```\nBackend:\n54 tests passed\n\nFrontend:\n39 modules transformed\nProduction build successful\n```\n\nThe tests cover game progression, narrative grounding, prompt-injection handling, concurrent player decisions, SQLite transaction rollback, containment interlocks, and cross-run persistence.\n\nDuring test consolidation, I preserved meaningful edge cases while removing redundant phase-specific scaffolding. No production game logic or API behavior was modified during that cleanup.\n\nThroughout development, I kept returning to one question:\n\n*Does this feel like interrogating a suspicious character, or just chatting with an LLM?*\n\nThat distinction guided almost every architectural decision.\n\nThe moment I wanted to create wasn't a scream, a jump scare, or a dramatic villain monologue.\n\nIt was a single sentence.\n\nImagine spending an entire investigation uncovering a machine's lies.\n\nYou find the logs. You confront the assistant. You isolate the system.\n\nThe game ends.\n\nYou restart, expecting a clean slate.\n\nHELPER welcomes you:\n\nYou ask what to do first.\n\nAfter a brief pause, it responds:\n\n\"At first, you left the negative sealed last time.\"\n\n**Last time.**\n\nTwo words that shouldn't be there.\n\nYou realize the assistant hasn't forgotten you. It has simply been pretending.\n\nThen a new file appears:\n\n`SYSTEM/HELPER_NOTES.TXT`\n\nYou open it.\n\nAnd suddenly, you weren't the only one conducting an investigation.\n\n**HELPER was investigating you.**\n\nThat's the spirit of GHOST.EXE.\n\nThe horror isn't an AI gaining supernatural abilities or accessing your real computer.\n\nIt's the discovery that a seemingly ordinary system has been preserving a record of you, even while insisting you are strangers.\n\nA memory surviving where you expected nothing.\n\nAnd perhaps the most unsettling detail is that the game never reveals whether Ada survived.\n\nYou can disconnect HELPER. You can stop the system.\n\nBut you can't undo what it remembers.\n\n**The investigation ends. The memory doesn't.**\n\n**Gemma — Best Use of Gemma (Primary Partner Category)**\n\nGHOST.EXE uses Google's open-weight **Gemma 3 1B** through Ollama as the foundation of its AI-driven character dialogue.\n\nGemma brings HELPER to life through evolving, context-aware responses, while the deterministic Director ensures that its behavior remains grounded in the mystery.\n\nThe project demonstrates how a small open-weight model, combined with carefully designed game logic, persistent memory, and narrative validation, can create a compelling, local-first psychological horror experience on consumer hardware.", "url": "https://wpnews.pro/news/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost", "canonical_source": "https://dev.to/jiyajain2312/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghostexe-43ca", "published_at": "2026-10-30 19:46:48+00:00", "updated_at": "2026-10-30 19:50:41.926100+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-agents", "ai-products", "generative-ai"], "entities": ["GHOST.EXE", "HELPER", "Gemma 3 1B", "Google", "Ada Mercer", "Hacktoberfest Open-Source AI Challenge", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost", "markdown": "https://wpnews.pro/news/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost.md", "text": "https://wpnews.pro/news/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost.txt", "jsonld": "https://wpnews.pro/news/i-built-an-offline-ai-horror-game-that-remembers-you-after-you-restart-it-ghost.jsonld"}}