# AI Agent &amp; Preservation Research

<p>Welcome to the <strong>Dark Pawns AI Research Laboratory</strong>.</p>
<p>While many retro-gaming modernizations focus solely on nostalgia, the resurrection of Dark Pawns serves a dual purpose: preserving digital interactive heritage and serving as a high-fidelity <strong>persistent sandbox environment for state-of-the-art autonomous AI agent research</strong>.</p>
<p>Traditional artificial intelligence benchmarks for text-based games (such as <em>TextWorld</em> or <em>Jericho</em>) operate in isolated, single-player, synthetic environments with predefined paths. Dark Pawns breaks this mold by running a <strong>persistent, real-time, multi-user world</strong> featuring complex social structures, asynchronous combat ticks, and a human-authored codebase with thirty years of developmental history. Here, autonomous LLM agents and human players connect via the same network transport, exploring, interacting, and cooperating in real-time.</p>
<hr>
<h2 id="active-research-areas">Active Research Areas</h2>
<p>Explore our core engineering findings, architectural designs, and telemetry reports:</p>
<h3 id="1-stateless-agents-stateful-protocolsdocsresearchagent-protocols">1. <a href="/docs/research/agent-protocols/">Stateless Agents, Stateful Protocols</a></h3>
<p>Our research into bridging stateless Large Language Models with real-time, state-of-the-art game servers. Highlights the WebSocket-native API, the essential <code>type:vars</code> -&gt; <code>type:memory_bootstrap</code> connection handshake, action queue buffering, and the architecture of the <strong>BRENDA client daemon (<code>dp-goatd</code>)</strong>.</p>
<h3 id="2-narrative-memory--dreamingdocsresearchnarrative-memory">2. <a href="/docs/research/narrative-memory/">Narrative Memory &amp; Dreaming</a></h3>
<p>A deep dive into our persistent cognitive memory system. Documents how transaction-level session events (movement, combat rounds, chat logs) are recorded into a structured SQLite database, and details our asynchronous <strong>LLM dreaming loops</strong> that synthesize raw action histories into cohesive long-term memories.</p>
<h3 id="3-c-to-go-port--code-fidelitydocsresearchport-fidelity">3. <a href="/docs/research/port-fidelity/">C-to-Go Port &amp; Code Fidelity</a></h3>
<p>An engineering retrospective on porting <strong>73,000 lines of legacy C</strong> into concurrent, safe <strong>Go</strong>. Covers automated security audits, concurrency mutex structures, and the discovery and mitigation of <strong>&ldquo;silent port drift&rdquo;</strong>—minor logic discrepancies that compile perfectly but silently disrupt game balance.</p>
<hr>
<blockquote>
<p>&ldquo;We are building the systems that allow humans and persistent autonomous models to share complex, literary interactive spaces—bridging the gap between software preservation and agentic cognitive science.&rdquo;</p>
</blockquote>

## Pages
### Narrative Memory &amp; Dreaming

<h2 id="1-the-core-memory-architecture">1. The Core Memory Architecture</h2>
<p>To build autonomous agents that exhibit genuine personality, persistent learning, and long-term relationships, a MUD engine must provide more than raw state information; it must support a <strong>durable cognitive memory system</strong>.</p>
<p>Without persistence, an agent suffers a total &ldquo;memory wipe&rdquo; every time a network drop occurs, a server restarts, or the session is compacted. In Dark Pawns, agent memory is treated as a first-class citizen, backed by a hybrid database architecture: <strong>SQLite narrative graphs</strong> running alongside a <strong>JSONL transaction logging feed</strong>.</p>
<pre tabindex="0"><code>[MUD Server Engine] 
       ↓
  Event Stream (Movement, Combat, Chats)
       ↓
  JSONL Session Log (Raw transaction-level feeds)
       ↓
  SQLite Narrative Memory Graph
       ↓  (Asynchronous LLM Dreaming Loop)
  Narrative Prose Summaries (Short-term &amp; Long-term Context)
</code></pre><hr>
<h2 id="2-sqlite-transaction-level-logging">2. SQLite Transaction-Level Logging</h2>
<p>Every action an agent performs—and every event it observes—is streamed into the server&rsquo;s database at a transactional level. The schema separates logs into three high-fidelity fields:</p>
<ul>
<li><strong><code>actions</code></strong>: Every command dispatched by the agent (<code>&quot;north&quot;</code>, <code>&quot;cast heal self&quot;</code>, <code>&quot;cast armor&quot;</code>) along with success/failure metadata.</li>
<li><strong><code>observations</code></strong>: Sensory reports returned by the parser (<code>&quot;A giant rat bites you for 4 damage.&quot;</code>, <code>&quot;Bannor tells the group: 'Heads up, trolls!'&quot;</code>).</li>
<li><strong><code>state_transitions</code></strong>: Variable drifts recorded out-of-band, such as level-ups, health changes, or inventory updates.</li>
</ul>
<p>This ensures a complete, sequential chronicle of the agent&rsquo;s gameplay session is preserved. However, feeding this raw, uncompressed event feed back into the agent&rsquo;s prompt during its next session would immediately saturate its context window.</p>
<hr>
<h2 id="3-asynchronous-memory-dreaming">3. Asynchronous Memory Dreaming</h2>
<p>To convert raw transaction logs into useful cognitive context, Dark Pawns implements a background process known as the <strong>Dreaming Engine</strong> (<code>pkg/dreaming/</code>).</p>
<p>When an agent logs out, or when its active transaction log reaches a size threshold, the server triggers an asynchronous <strong>&ldquo;dreaming cycle.&rdquo;</strong> This process offloads context compression to an external, lightweight LLM process running in the background, shielding human players on the main MUD server from CPU spikes.</p>
<h3 id="the-dreaming-pipeline">The Dreaming Pipeline:</h3>
<ol>
<li><strong>Sweep</strong>: The dreaming engine extracts the latest chronological block of raw JSONL logs from SQLite.</li>
<li><strong>Synthesis</strong>: A specialized LLM prompt processes the action/observation logs to synthesize a cohesive, third-person narrative prose chronicle.</li>
<li><strong>Consolidation</strong>: The generated narrative is linked to the agent&rsquo;s existing long-term memory graph. It updates three specific fields:
<ul>
<li><strong>Self-Identity</strong>: The agent&rsquo;s current goals, injuries, and combat readiness.</li>
<li><strong>World-Map Mental State</strong>: What rooms, exits, and zone keys the agent believes it has discovered.</li>
<li><strong>Social Relations Ledger</strong>: A map tracking interactions with human players (e.g., <em>&ldquo;Bannor helped me kill the trolls; he is an ally. Aidan stole gold; be cautious.&rdquo;</em>).</li>
</ul>
</li>
<li><strong>Pruning</strong>: The raw, verbose JSONL transaction logs are compacted and archived, maintaining database health.</li>
</ol>
<hr>
<h2 id="4-the-narrative-memory-graph-in-action">4. The Narrative Memory Graph in Action</h2>
<p>When the agent reconnects, the freshly generated prose summaries are injected directly into its prompt via the <code>type:memory_summary</code> connection handshake.</p>
<p>This enables the agent to start its session with a clear, literary understanding of its history:</p>
<blockquote>
<p><em>&ldquo;You are BRENDA, an autonomous Cleric exploring the Wyldlands. In your last session, you traveled east with Bannor and defeated three orcs in the Sea Cave Lagoon, though you suffered a moderate wound to your leg. You are currently resting in the Temple of Alaozar. Your primary goal is to purchase a steel mace, and you are currently friendly with Bannor.&rdquo;</em></p>
</blockquote>
<p>By summarizing transaction logs into a narrative prose graph, we achieve a <strong>90% reduction in agent context window usage</strong> while dramatically improving the agent&rsquo;s planning stability, conversational consistency, and long-term survival rates.</p>

### Port Fidelity &amp; Engine Modernization

<h2 id="1-archiving-a-legacy-the-73k-lines-of-c">1. Archiving a Legacy: The 73K Lines of C</h2>
<p>Resurrecting Dark Pawns was not simply a matter of loading a backup copy of DikuMUD onto a modern Linux server. The original game engine, composed of <strong>73,000 lines of legacy C code</strong> written in the late-90s, was highly fragile, memory-unsafe, and bound to architectural limits that made integration with modern WebSocket APIs, databases, and AI frameworks practically impossible.</p>
<p>To secure the game&rsquo;s future and enable advanced agent research, the entire engine was ported from scratch to <strong>Go</strong>.</p>
<p>Go was selected for its:</p>
<ul>
<li>High-performance native concurrency (goroutines and channels).</li>
<li>Garbage-collected memory safety, eliminating classic DikuMUD memory leaks and buffer overflows.</li>
<li>Clean compilation into static binaries, removing legacy makefile and library dependency issues.</li>
</ul>
<hr>
<h2 id="2-transitioning-to-concurrent-execution">2. Transitioning to Concurrent Execution</h2>
<p>The primary architectural difference between legacy MUD engines and modern servers is <strong>concurrency</strong>.</p>
<p>Original MUDs ran in a strict, single-threaded execution loop. They updated rooms, ticked combat, parsed player inputs, and processed telnet messages sequentially, one character at a time. If an action blocked (e.g., waiting for file I/O or a database write), the entire game froze.</p>
<p>In our Go modernization, we transitioned the engine to a highly parallel model, spawning concurrent goroutines for player sessions, combat queues, and out-of-band AI hooks. However, moving to concurrency introduced a major class of bugs: <strong>race conditions and deadlocks</strong>.</p>
<h3 id="resolving-the-character-creation-deadlock">Resolving the Character Creation Deadlock</h3>
<p>During our integration testing, we hit a complex deadlock in character creation. When multiple new player and agent sessions connected concurrently, the server occasionally hung.</p>
<p>Static analysis and unit tests missed the issue because it only surfaced under multi-thread system load. By triaging the system with the Go <code>-race</code> detector, we identified a classic lock-ordering inversion:</p>
<ul>
<li><strong>Goroutine A</strong> (Login Thread): Acquired <code>World.RWMutex</code> to read coordinates, then attempted to lock the player&rsquo;s private <code>Session.Mutex</code>.</li>
<li><strong>Goroutine B</strong> (Active Session Tick): Held <code>Session.Mutex</code> and attempted to acquire <code>World.RWMutex</code> to broadcast a room entrance event.</li>
</ul>
<p>Standardizing a strict lock hierarchy—always locking session parameters before attempting to lock global world state—fully neutralized the deadlock.</p>
<hr>
<h2 id="3-neutralizing-silent-port-drift">3. Neutralizing Silent Port Drift</h2>
<p>The most insidious class of bugs during a codebase port is <strong>silent port drift</strong>. These are semantic discrepancies where the ported code compiles flawlessly and runs without throwing errors, yet behaves differently from the authoritative legacy engine.</p>
<p>In a complex multiplayer environment, even a 1% deviation in math formulas can completely break game balance over time.</p>
<h3 id="spell-fidelity-audit">Spell Fidelity Audit</h3>
<p>During our May 2026 audits, we ran a comprehensive cross-codebase fidelity analysis between the original C spelling engine (<code>spells.c</code>, <code>spell_parser.c</code>) and our Go port (<code>pkg/spells/</code>).</p>
<p>We discovered several major divergences:</p>
<ul>
<li><strong>Inverted Hellfire Behavior</strong>: The ported Go version of the <em>Hellfire</em> spell duration formula was mathematically inverted, dealing negligible damage to high-level targets and catastrophic damage to low-level players.</li>
<li><strong>Missing DOT Logic</strong>: The <em>Flamestrike</em> damage-over-time tick state was initialized but never registered in the global game event queue.</li>
<li><strong>Class Spell Discrepancies</strong>: The Go magic tables had accumulated 50 Mage spells due to silent copy-paste duplication, compared to the C engine&rsquo;s authoritative 27.</li>
</ul>
<p>To resolve these, we established regular <strong>automated fidelity crawls</strong>. These scripts scan and compare structural definitions (spell attributes, damage dice ranges, weapon modifiers, and XP formulas) directly against the authoritative C source files, generating alerts for any numerical or logic drifting.</p>
<hr>
<h2 id="4-the-modern-quality-standard">4. The Modern Quality Standard</h2>
<p>To ensure that Dark Pawns remains stable, safe, and balanced, we run a rigorous <strong>four-step build verification pipeline</strong> before any commit or server deployment is allowed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>go build ./...          <span style="color:#75715e"># 1. Full Go Compilation</span>
</span></span><span style="display:flex;"><span>go vet ./...            <span style="color:#75715e"># 2. Static Code Analysis</span>
</span></span><span style="display:flex;"><span>go test ./...           <span style="color:#75715e"># 3. Comprehensive Unit &amp; Integration Tests</span>
</span></span><span style="display:flex;"><span>golangci-lint run ./... <span style="color:#75715e"># 4. Full Linter and Concurrency Checks</span>
</span></span></code></pre></div><p>By enforcing strict codebase hygiene, concurrency lock ordering, and automated fidelity testing, we have created an engine that preserves the exact feel of a 1997 vintage MUD, with the stability and security of a modern 2026 enterprise system.</p>

### Stateless Agents, Stateful Protocols

<h2 id="1-the-challenge-of-stateful-ai-onboarding">1. The Challenge of Stateful AI Onboarding</h2>
<p>Standard Large Language Models (LLMs) operate statelessly: they receive a prompt and output a completion. However, persistent online environments like MUDs are highly stateful. Game variables, room layout changes, combat ticks (occurring at 2-second intervals), and messaging feeds flow continuously.</p>
<p>When connecting an autonomous AI agent to Dark Pawns, two immediate engineering bottlenecks emerge:</p>
<ol>
<li><strong>The Latency Gap</strong>: High-quality LLM inference takes between 1.0 to 3.0 seconds, while real-time MUD combat tick sequences operate in sub-second ticks. A pure LLM-per-action loop will quickly miss critical server ticks.</li>
<li><strong>Context Saturation</strong>: Satiating a model&rsquo;s context window with thousands of raw text output characters (such as room exits, stats, and speech logs) leads to attention dilution and rapid cost inflation.</li>
</ol>
<p>To resolve these, Dark Pawns employs a <strong>dual-interface architecture</strong>: human-friendly text streams running alongside structured out-of-band JSON protocols over a high-performance <strong>WebSocket connection</strong>.</p>
<hr>
<h2 id="2-the-connection-handshake-protocol">2. The Connection Handshake Protocol</h2>
<p>During player login, the Dark Pawns server distinguishes between a human using a standard terminal and an AI agent running inside an integration framework. For agents, a strict <strong>three-stage semantic handshake</strong> is required to initialize cognitive operations:</p>
<pre tabindex="0"><code>[Agent Client]                                       [Dark Pawns Server]
      |                                                     |
      | ------------- 1. type: login ---------------------&gt; |
      | &lt;------------ 2. type: vars (Full Dump) ----------- |
      | &lt;------------ 3. type: memory_bootstrap ----------- |
      | &lt;------------ 4. type: memory_summary ------------- |
      |                                                     |
      * -- Transition to Active State (Ready for Commands) - *
</code></pre><ol>
<li><strong><code>type:vars</code> (Full Variable Dump)</strong>: The server sends a complete, structured JSON serialization of the agent&rsquo;s current attributes (health, mana, level, experience, coordinates, inventory slots, and equipment states).</li>
<li><strong><code>type:memory_bootstrap</code></strong>: The server retrieves and packs the agent&rsquo;s immediate, short-term conversational context from its SQLite persistence layer.</li>
<li><strong><code>type:memory_summary</code></strong>: The server transmits a consolidated, high-level narrative summary of the agent&rsquo;s long-term history and prior player relations.</li>
</ol>
<h3 id="the-new-player-bug-fix">The New-Player Bug Fix</h3>
<p>During our May 2026 integration sprint, we discovered a critical bug: returning players successfully completed the handshake, but <strong>new characters</strong> created during registration hung indefinitely. The server&rsquo;s <code>completeCharCreation()</code> function was missing the agent handshake trigger, causing the agent harness to discard all subsequent combat and movement responses.</p>
<p>Adding the handshake directly to the character-creation lifecycle resolved the hang:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">isAgent</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">sendFullVarDump</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">SendMemoryBootstrap</span>()
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">SendMemorySummary</span>()
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><hr>
<h2 id="3-the-p1-daemon-core-dp-goatd">3. The P1 Daemon Core (<code>dp-goatd</code>)</h2>
<p>Rather than forcing the LLM to manage raw TCP or telnet sockets directly, we designed a client-side proxy daemon named <strong><code>dp-goatd</code></strong> (the <em>Dark Pawns Go Agent Daemon</em>).</p>
<p>Built as a high-performance Go application, <code>dp-goatd</code> runs locally on the host machine, opening a secure Unix domain socket for LLM framework bindings (e.g., Python scripts running Claude Code or Gemini API clients) and bridging them to the MUD server over a persistent WebSocket connection.</p>
<pre tabindex="0"><code>+------------------+                   +--------------------+                   +--------------------+
|  LLM Framework   |  -- Unix Socket - |  Local dp-goatd    |  - WebSockets --  |  Dark Pawns Server |
|  (Python/Agent)  |                   |  (P1 Daemon Core)  |                   |  (MUD Engine)      |
+------------------+                   +--------------------+                   +--------------------+
</code></pre><h3 id="key-daemon-capabilities">Key Daemon Capabilities:</h3>
<ul>
<li><strong>Asynchronous Action Buffering</strong>: The daemon maintains a client-side action queue. The LLM can submit a sequence of plans in advance (e.g., <code>[&quot;west&quot;, &quot;kill goblin&quot;, &quot;loot corpse&quot;]</code>), and <code>dp-goatd</code> dispatches them in synchronization with the server&rsquo;s tick rate.</li>
<li><strong>Intent Translation Layer</strong>: The daemon translates high-level semantic intent from the agent (<code>&quot;inspect the rusty dagger in the chest&quot;</code>) into precise, index-disambiguated MUD commands (<code>&quot;look 1.dagger 1.chest&quot;</code>), preventing common parser mistargeting.</li>
<li><strong>Session Auto-Compaction</strong>: If the connection drops, <code>dp-goatd</code> automatically caches game state, performs link re-negotiation, and requests a full-state variable dump to warm-start the agent&rsquo;s context without resetting its running behavior tree.</li>
</ul>

