File size: 3,888 Bytes
ee29c8c
d7b7cac
 
ee29c8c
d7b7cac
ee29c8c
 
d7b7cac
ee29c8c
 
d7b7cac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
---
title: NoExit
emoji: πŸšͺ
colorFrom: gray
colorTo: red
sdk: static
pinned: false
license: mit
---

# NoExit

A real-time, text-driven 2D game built in Unity where the player is locked in a room with two AI-generated characters who remember everything you tell them.

Inspired by Sartre's *Huis Clos* β€” there is no exit.

---

## Gameplay

Type freely to converse with two characters whose names, backstories, and personalities are generated at runtime. Every piece of personal information the player reveals is silently extracted and stored β€” and the characters will bring it up again.

- Type text to talk; press **Enter** to submit
- Press **Enter** again to dismiss a dialogue box
- Arrow keys move the player character
- Point and click movement


---

## Technical Architecture

### Engine & Rendering
- **Unity 2D** (Universal Render Pipeline)
- **TextMeshPro** for all UI text
- **Light2D** for atmosphere and reactive flicker effects
- WebGL build served via Hugging Face Spaces

---

### AI Pipeline

All AI calls route through Hugging Face Spaces β€” no API keys are exposed to the client.

#### Dialogue Model
**Endpoint:** `jejunepixels-noexit-proxy.hf.space/chat`

A proxy Space that forwards chat completion requests. Includes automatic retry logic (up to 2 retries, 10s delay) to handle cold starts.

#### Personal Information Extractor
Scans every line of dialogue β€” from both the player and the characters β€” for personally identifying information using a small LLM. Two switchable backends:

| Backend | Endpoint | Model |
|---|---|---|
| Custom FastAPI | `jejunepixels-qwen3-4B-info-extractor-fastapi.hf.space/extract` | Qwen3 4B |
| HF Gradio Space | `jejunepixels-qwen3-0-6b-info-extractor-api.hf.space/extract` | Qwen3 0.6B |

Returns extracted information as a string, or `"none"` if nothing personal was found.

---

### Character Generation

At game start, two characters are generated procedurally via sequential LLM calls: first a name, then a full backstory and personality description using that name. The resulting description becomes each character's permanent system prompt for all future dialogue.

---

### Addressing System

Once a character has accumulated personal information about the player, an LLM routing call (capped at 10 tokens) decides which character should respond to the next player message β€” Character 1, Character 2, or both. Falls back to both responding after 3 failed attempts.

---

### Reactive Events

A timer-based event system fires unprompted questions at the player during pauses in conversation. If the player has revealed personal information, the question targets a specific piece of what was shared. Otherwise it asks a generic get-to-know-you question. Each fired event schedules the next one randomly.

---

### Dialogue Display

- Words reveal one by one with a typewriter effect
- Up to 3 dialogue boxes can be active simultaneously
- AABB overlap detection repositions boxes to prevent collisions
- Player input is locked while any dialogue is displaying
- When personal information is detected, the scene lighting flickers

---

### Data Logging

Every AI interaction is logged locally in JSONL format using `system / user / assistant` triplet structure, across four separate files for dialogue, info extraction, addressing decisions, and character generation. Intended for fine-tuning and analysis.

---

## Configurable Parameters

| Parameter | Description |
|---|---|
| Dialogue model | Model ID used for character dialogue and addressing |
| Info model | Model ID used for information extraction |
| Temperature | Separate values for dialogue and character generation |
| Max dialogue tokens | Token cap per character response (default: 150) |
| Max addressing tokens | Token cap for routing decisions (default: 10) |
| Info extractor backend | Toggle between Qwen3 4B (FastAPI) and 0.6B (Gradio) |