From 5b579758958bfe7a51ea25d792c329e1f4d1bf47 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 16:06:35 +0200 Subject: [PATCH 1/7] Add a more complete documentation for that IA --- docs/ai/ai.rst | 20 ++++ docs/ai/jobs.rst | 84 ++++++++++++++++ docs/ai/message_cipher.rst | 80 +++++++++++++++ docs/ai/protocol.rst | 86 ++++++++++++++++ docs/ai/strategies.rst | 194 +++++++++++++++++++++++++++++++++++++ docs/ai/triangulation.rst | 36 +++++++ docs/index.md | 5 +- 7 files changed, 503 insertions(+), 2 deletions(-) create mode 100644 docs/ai/ai.rst create mode 100644 docs/ai/jobs.rst create mode 100644 docs/ai/message_cipher.rst create mode 100644 docs/ai/protocol.rst create mode 100644 docs/ai/strategies.rst create mode 100644 docs/ai/triangulation.rst diff --git a/docs/ai/ai.rst b/docs/ai/ai.rst new file mode 100644 index 00000000..38129901 --- /dev/null +++ b/docs/ai/ai.rst @@ -0,0 +1,20 @@ +================= +AI Documentation +================= + +This section describes the AI client implementation and internal design: + +- Communication protocol +- Triangulation strategies +- Message ciphering +- Job system +- Overall AI strategies + +.. toctree:: + :maxdepth: 2 + + protocol + triangulation + message_cipher + jobs + strategies diff --git a/docs/ai/jobs.rst b/docs/ai/jobs.rst new file mode 100644 index 00000000..cbe8e435 --- /dev/null +++ b/docs/ai/jobs.rst @@ -0,0 +1,84 @@ +AI Job System +============== + +This page explains the *Legacy AI Behavior* we experimented with for the project. + +Our unfinished AI design used well-defined behavioral roles called **Jobs**. Each job had its own file in `ai/behavior/`, implementing the abstract `JobTemplate` class. This class provided a shared structure for all specialized behaviors. + +Overview +-------- + +- **Newcomer** + - Default job for any freshly spawned player. + - Waits to be assigned a role by the existing *Elder*. + - If no Elder broadcast is heard for 50 ticks, promotes itself to Elder. + +- **Elder** + - A single Elder exists per civilization. + - Acts as the central coordinator: + - Chooses a "home tile" near civilization center. + - Receives stones, food, and players for incantations. + - Assigns jobs to newcomers. + - Tracks the roles and locations of all known players. + - Garblers are a partial exception: they are not tracked as precisely, and assignment is rarer to avoid confusion. + +- **Basic** + - Default worker role. + - Randomly paths around the map, collecting any stones in its way. + - Broadcasts when it has enough resources to evolve. + +- **Collector** + - Focuses on gathering specific stones. + - Delivers resources to the Elder's designated home tile. + +- **Garbler** + - Leaves the civilization to embed itself in an enemy team. + - Goal is to disrupt enemy communication. + - For every message it sends, it cycles modes: + - **50%** Raven: emits nonsense (including invalid encodings like `\feff`). + - **40%** Mimicry: repeats verbatim any intercepted enemy message. + - **10%** Parrot: repeats messages with heavy modification. + +Job Assignment System +---------------------- + +The Elder assigns jobs dynamically, using our team's broadcast protocol. Each player listens for instructions and responds appropriately. + +Communication Protocol +----------------------- + +All inter-player instructions passed through team broadcasts during the game are defined below: + ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +| **Job** | **Instruction (Recv)** | **Instruction (Send)** | **Effect** | **Args / Type** | ++============+===================================+===============================================+==========================================================+=========================================+ +| Basic | `assign_job ` | `evolution_ready ` | Elder-directed reassignment; immediate job transition | id: `int`, job: `str` | +| | `evolution_call ` | `evolution_response ` | Respond to Elder's group evolution call | id: `int` | +| | `status_report_request` | `basic_status level: needs: food:` | Periodic status update to Elder | level: `int`, needs: `int`, food: `int` | +| | `resource_request ` | `resource_available ` | Reply if the player holds excess resources | resource: `str`, amt: `int` | ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +| Elder | `newcomer_seeking_assignment` | `assign_job ` | Assigns job to a newcomer | id: `int`, job: `str` | +| | `resource_delivery ` | `status_report_request` | Updates depot stock from Collector; asks for reports | resource: `str`, amt: `int` | +| | | `elder_location ` | Announces Elder's tile location | x: `int`, y: `int` | ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +| Newcomer | `elder_announce ` | `newcomer_seeking_assignment ` | Announces presence and level; awaits Elder assignment | id: `int`, level: `int` | +| | `assign_job ` | `newcomer_joined` | Confirms receiving role assignment | id: `int`, job: `str` | ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +| Collector | | `resource_delivery ` | Delivers collected resources to the Elder | resource: `str`, amt: `int` | ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +| Garbler | | *variable garbage* | Disrupts enemies with random unreadable text | `str` | +| | | *intercepted_message (mimicry/parrot)* | Mimic or distort intercepted enemy messages | `str` | +| | *any enemy message* | | Stores for mimicry/parrot modes | `str` | ++------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ + +Behavior Philosophy +-------------------- + +This system was designed to: + +- Decentralize coordination via broadcast-based communication. +- Have a single Elder coordinate overall strategy. +- Allow role reassignment and adaptability during play. +- Disrupt enemy teams by embedding Garblers who mimic or garble enemy messages. + +Although unfinished, this "Job System" represents an ambitious attempt to create complex AI behaviors resembling a true in-game society. diff --git a/docs/ai/message_cipher.rst b/docs/ai/message_cipher.rst new file mode 100644 index 00000000..d75c384e --- /dev/null +++ b/docs/ai/message_cipher.rst @@ -0,0 +1,80 @@ +Message Ciphering +================== + +Our AI agents can encode/decode messages for secure communication within the team. + +Overview +-------- + +We use a symmetric cipher with XOR + rotation and PBKDF2-derived team keys. + +Key Derivation +-------------- + +.. code-block:: python + + from hashlib import pbkdf2_hmac + + def derive_team_key(team_name: str) -> bytes: + return pbkdf2_hmac( + 'sha256', team_name.encode(), b'3301', 10000, 2048 + ) + +- Salt: 3301 +- Iterations: 10,000 +- Output length: 2048 bytes + +Encryption Process +------------------- + +1. Derive key from team name. +2. Choose rotation = counter % len(key). +3. XOR content with rotated key. +4. FNV-1a checksum over encrypted content. +5. Pack header: + +:: + + bot_id | counter | rotation | timestamp | checksum | length + +6. Concatenate header + encrypted payload. +7. Nibble-encode: + +:: + + LUT = "AIOU aiou qpdb QPDB" + +Decoding Process +----------------- + +1. Nibble-decode string. +2. Unpack header. +3. Validate checksum. +4. XOR-decrypt using rotation. +5. Parse content. + +Code Example +------------ + +.. literalinclude:: ../path/to/your/code.py + :language: python + +Alternatively, show excerpts explaining the header format and nibble encoding: + +.. code-block:: python + + def build_header(bot_id, counter, rotation, timestamp, checksum, length): + return struct.pack(">HBBI2sH", ...) + +Nibble Encoding +--------------- + +Uses a 16-character LUT: + +:: + + AIOU aiou qpdb QPDB + +- Maps high/low nibbles to characters. +- Enables safe transmission over text channels. + diff --git a/docs/ai/protocol.rst b/docs/ai/protocol.rst new file mode 100644 index 00000000..0cc923c1 --- /dev/null +++ b/docs/ai/protocol.rst @@ -0,0 +1,86 @@ +AI Protocol +=========== + +This page explains the communication protocol between the AI client and the server, as defined in the project specification. + +Overview +-------- + +The AI connects to the server via TCP and exchanges text commands. The server responds in plain text. The basic handshake: + +:: + + <-- WELCOME\n + --> TEAM team_name\n + <-- CLIENT_NUM\n + <-- X Y\n + +Where: + +- `CLIENT_NUM` is the number of available slots for the team. +- `X`, `Y` are the map dimensions. + +Command/Response Examples +-------------------------- + ++-----------------+-------------------------+------------------------------+ +| Command | Time (1/f) | Response | ++=================+=========================+==============================+ +| Forward | 7/f | ok | +| Right | 7/f | ok | +| Left | 7/f | ok | +| Look | 7/f | [tile1, tile2, ...] | +| Inventory | 1/f | [object count, ...] | +| Broadcast text | 7/f | ok | +| Connect_nbr | - | number of remaining slots | +| Fork | 42/f | ok | +| Eject | 7/f | ok / ko | +| Take object | 7/f | ok / ko | +| Set object | 7/f | ok / ko | +| Incantation | 300/f | Elevation underway / ko | ++-----------------+-------------------------+------------------------------+ + +Vision +------ + +The "look" command returns a list of visible tiles. Vision grows with level: + +- Level 1: 1 unit +- Level 2: 2 units, etc. + +Example server response for "look": + +:: + + [player, linemate,, food] + +Sound/Broadcast +---------------- + +Players can broadcast messages. The server responds: + +:: + + message K, text + +Where K indicates direction relative to the receiver. Directions are determined by the tile layout around the player, choosing the shortest wraparound path on the toroidal map. + +Reproduction +------------ + +Players can fork to create an egg: + +- `Fork` command reserves a new slot for a teammate. +- When a new client joins, it hatches an egg and spawns. + +Time +---- + +All actions have duration: + +:: + + duration = action_time / f + +where `f` is the frequency set in server arguments. + diff --git a/docs/ai/strategies.rst b/docs/ai/strategies.rst new file mode 100644 index 00000000..2d355deb --- /dev/null +++ b/docs/ai/strategies.rst @@ -0,0 +1,194 @@ +AI Strategies +============= + +This page describes several strategies we considered (and partly implemented or designed) for coordinating our AI players. Each approach balances complexity, coordination overhead, and robustness to adversarial teams. + +Our goal was to provide flexibility to assign strategies dynamically depending on the game context. + +1. Elder-Centric Hub Strategy +------------------------------ + +**Description:** + +- Designate a single Elder as the "home base." +- Elder stays on a chosen central tile. +- All other players report status, deliver resources there, and await assignments. +- Elder decides when and where to launch incantations, assigns roles dynamically. + +**Pros:** + +- Centralized control enables fine-grained planning. +- Makes it easy to stockpile stones on one tile. +- Elder can optimize group formation for incantation. + +**Cons:** + +- Single point of failure (if Elder dies, assignment collapses). +- Requires all players to stay in communication range. +- Easy for enemies to locate and disrupt the hub. + +**Best Use:** + +- Large, coordinated team with stable communication. +- When enemy interference is minimal. + +--- + +2. Opportunistic Evolution +--------------------------- + +**Description:** + +- No Elder. +- Each player roams the map collecting stones independently. +- When a player has all stones for next level, it broadcasts a "call" for all same-level teammates nearby. +- Players move to the caller to attempt evolution. + +**Pros:** + +- Fully decentralized; no single leader. +- Resistant to Elder assassination or communication jams. +- Scales well with many players. + +**Cons:** + +- Harder to synchronize multiple players of same level. +- Players may fail to converge in time. +- Resource waste due to duplication (multiple players carry same stones). + +**Best Use:** + +- When the map is sparse or enemy interference breaks centralized planning. +- Small teams with limited coordination. + +--- + +3. GPS / Triangulation Network +------------------------------- + +**Description:** + +- Assign specific players to act as "beacons" or "GPS nodes." +- Each beacon broadcasts its location regularly. +- Other players can triangulate their own positions by comparing signal directions. +- Enables distributed coordination: players can navigate to any rendezvous point reliably. + +**Pros:** + +- Map-wide navigation aid for all team members. +- Supports sophisticated positioning strategies (e.g. flanking, resource delivery). +- Works even on large maps with wraparound. + +**Cons:** + +- Requires dedicated players reducing effective workforce. +- Beacons must stay alive and avoid enemy ejection. +- Communication can be jammed or mimicked by enemies. + +**Best Use:** + +- Large teams wanting precise coordination. +- Maps with complex topology or high wraparound confusion. + +--- + +4. Raider/Disruptor Cells +-------------------------- + +**Description:** + +- Divide the team into small semi-autonomous cells. +- Assign a few players as Raiders or Disruptors. +- Raiders move toward enemy hubs to eject, steal, or confuse. +- Remaining players continue resource gathering and elevation. + +**Pros:** + +- Harasses enemy coordination (e.g. ejecting their Elder). +- Can disrupt enemy incantations. +- Forces enemies to spend resources defending. + +**Cons:** + +- Raiders often die or get stranded. +- Reduces overall resource-gathering capacity. +- Risk of friendly communication noise. + +**Best Use:** + +- When enemy teams are tightly coordinated. +- To delay enemy elevation while your team advances. + +--- + +5. Resource Grid Delivery +-------------------------- + +**Description:** + +- Players spread out in a grid to maximize map coverage. +- When stones are found, players broadcast availability. +- Nearest Collector or Basic player comes to fetch and deliver to the hub. +- Elder (or distributed leader) decides where incantations occur. + +**Pros:** + +- Efficient map-wide resource exploitation. +- Minimizes redundant searching. +- Adaptive to dynamic spawns. + +**Cons:** + +- High communication overhead. +- Needs strong coordination logic to avoid conflict over resources. +- Vulnerable to broadcast jamming. + +**Best Use:** + +- Medium to large teams. +- When resource density is low or scattered. + +--- + +6. Egg Farming & Fast-Fork Expansion +------------------------------------ + +**Description:** + +- Focus on forking early and often. +- Maintain a steady supply of eggs to keep slots full. +- Assign newcomers rapidly to resource or collector roles. +- Prioritize food gathering to sustain population. + +**Pros:** + +- Maximizes team population quickly. +- Provides backup even if some players die. +- Can overwhelm enemy teams via numbers. + +**Cons:** + +- Needs careful food management. +- Coordination becomes harder as numbers grow. +- Slower to reach higher elevations if stone stockpiles are neglected. + +**Best Use:** + +- On large maps with abundant food. +- Against teams that can't coordinate their expansions. + +--- + +Choosing a Strategy +-------------------- + +In practice, the AI system was designed to switch between these strategies depending on: + +- Number of connected players. +- Current resource stockpiles. +- Enemy activity (e.g. presence of Garblers). +- Map size and density. + +By mixing these approaches, we hoped to create a robust and adaptable AI civilization capable of winning under varied conditions. + +This flexibility allows the AI to respond dynamically to the evolving game state, maximizing its chances of success against both human and AI opponents. diff --git a/docs/ai/triangulation.rst b/docs/ai/triangulation.rst new file mode 100644 index 00000000..7ca8d534 --- /dev/null +++ b/docs/ai/triangulation.rst @@ -0,0 +1,36 @@ +Triangulation Strategy +======================= + +Sound propagation in Zappy is toroidal. The map wraps horizontally and vertically. + +When a message is broadcast, all players receive: + +:: + + message K, text + +Where K is the tile direction relative to the receiver. + +Strategy +-------- + +- Build a lookup of relative positions vs. directions. +- Use map width/height to compute shortest wraparound. +- When multiple paths exist, choose the shortest. + +Diagram +------- + +.. figure:: /_static/sound_diagram.png + :alt: Sound direction example + :align: center + + Example of tile numbering and shortest path for sound. + +Implementation Idea +-------------------- + +- On receiving message, compare possible paths. +- Simulate wraparound to find the shortest path to sender. +- Store recent directions for source estimation over time. + diff --git a/docs/index.md b/docs/index.md index 1fc1af99..37ac0158 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,10 +6,11 @@ :caption: Contents: api/api +ai/ai developer/architecture -developer/systems developer/contribution +developer/systems developer/usage_ai -protocol/protocol modules +protocol/protocol ``` From f2a1190a0268bd54b712e4049c5a43ada5a992e8 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 16:56:54 +0200 Subject: [PATCH 2/7] Enhance the cipher process documentation --- docs/ai/message_cipher.rst | 190 ++++++++++++++++++++++++++++++++----- 1 file changed, 167 insertions(+), 23 deletions(-) diff --git a/docs/ai/message_cipher.rst b/docs/ai/message_cipher.rst index d75c384e..c42f770f 100644 --- a/docs/ai/message_cipher.rst +++ b/docs/ai/message_cipher.rst @@ -1,16 +1,35 @@ Message Ciphering ================== -Our AI agents can encode/decode messages for secure communication within the team. +Our AI agents implement a custom encoding/decoding scheme to allow secure +communication among teammates. This page explains the chosen design in detail, +as well as other models and improvements we considered. Overview -------- -We use a symmetric cipher with XOR + rotation and PBKDF2-derived team keys. +We use multiple components to ensure secure communication: + +- PBKDF2-derived team keys: generates a shared, team-specific secret from the +team name using a password-based key derivation function, ensuring all +teammates have the same base key without exchanging it in-game. +- XOR with rotation offset: performs lightweight symmetric encryption by +combining the message with the derived key at an offset, obfuscating the +content from opponents. +- FNV-1a checksumming: computes a short hash of the encrypted payload to +detect tampering or corruption during transmission. +- Custom nibble-encoding: converts binary data into safe text-only messages +using a 16-character lookup table, ensuring compatibility with the game's +line-based, text-only protocol. + +This design balances simplicity, speed, and the severe constraints of +the game's communication system (small, plain-text messages with no binary). Key Derivation -------------- +We derive a team-wide symmetric key from the team name using PBKDF2: + .. code-block:: python from hashlib import pbkdf2_hmac @@ -20,61 +39,186 @@ Key Derivation 'sha256', team_name.encode(), b'3301', 10000, 2048 ) -- Salt: 3301 +- Salt: `b"3301"` - Iterations: 10,000 - Output length: 2048 bytes +✅ Pros: +- Each team automatically gets a unique key from its name. +- Harder for opponents to brute-force without knowing the team name. + +✅ Cons: +- All team members share the same key (no per-player secrecy). + Encryption Process ------------------- 1. Derive key from team name. -2. Choose rotation = counter % len(key). -3. XOR content with rotated key. -4. FNV-1a checksum over encrypted content. -5. Pack header: +2. Compute `rotation = counter % len(key)`. +3. XOR the plaintext content with the key, offset by rotation. +4. Compute FNV-1a checksum over the encrypted content. +5. Pack a header: :: bot_id | counter | rotation | timestamp | checksum | length 6. Concatenate header + encrypted payload. -7. Nibble-encode: +7. Nibble-encode the result: :: LUT = "AIOU aiou qpdb QPDB" +✅ Pros: +- Very fast encryption/decryption (suitable for real-time bot). +- Obfuscates content enough to confuse naive interceptors. +- Includes integrity check (checksum) to detect tampering. + +✅ Cons: +- Relatively weak cryptography if opponent knows the team name. +- No perfect secrecy if rotation/counter reused. + Decoding Process ----------------- -1. Nibble-decode string. -2. Unpack header. -3. Validate checksum. +1. Nibble-decode the string. +2. Unpack the header. +3. Validate the checksum. 4. XOR-decrypt using rotation. -5. Parse content. - -Code Example ------------- - -.. literalinclude:: ../path/to/your/code.py - :language: python +5. Parse the content as ASCII. -Alternatively, show excerpts explaining the header format and nibble encoding: +Header Format +-------------- .. code-block:: python def build_header(bot_id, counter, rotation, timestamp, checksum, length): - return struct.pack(">HBBI2sH", ...) + return struct.pack(">HBBI2sH", bot_id, counter, rotation, timestamp, checksum, length) + +- `bot_id`: Unique player ID. +- `counter`: Monotonic message counter. +- `rotation`: For XOR offset. +- `timestamp`: Unix time at message creation. +- `checksum`: FNV-1a checksum over ciphertext. +- `length`: Encrypted payload length. Nibble Encoding --------------- -Uses a 16-character LUT: +We use a custom 16-character LUT to map binary data into text: :: AIOU aiou qpdb QPDB -- Maps high/low nibbles to characters. -- Enables safe transmission over text channels. +- Each byte is split into two nibbles (4 bits). +- Each nibble maps to a single LUT character. +- Guarantees safe transmission through text-only channels. + +✅ Pros: +- Avoids forbidden binary characters in communication. +- Lightweight and easy to decode. + +✅ Cons: +- Doubles message length. + +Code Example +------------ + +.. literalinclude:: ../path/to/your/code.py + :language: python + +Alternative Models Considered +----------------------------- + +During design, we evaluated other encoding/encryption models: + +**1. Full Symmetric Encryption (AES, ChaCha20)** +- Pros: + - Strong cryptographic security. + - Widely available, well-studied algorithms. +- Cons: + - Requires binary-safe channels (the game only accepts plain text). + - Much slower on low-powered bots. + - Not feasible within the text-based, line-delimited protocol. + +**2. Per-Player Individual Keys** +- Pros: + - Better secrecy (messages can be addressed to a single bot). + - Prevents compromised teammate from leaking all keys. +- Cons: + - Requires key-exchange in-game (forbidden by project spec). + - Team-based communication makes single-player keys impractical. + - Harder to coordinate multiple bots for incantation. + +**3. Asymmetric Cryptography (RSA, ECC)** +- Pros: + - Strongest security. + - Supports signatures for message authenticity. +- Cons: + - Far too slow for real-time usage on many bots. + - Requires large message sizes, incompatible with nibble encoding. + - Overkill given the adversary model (mostly meant to confuse, not + for military-grade secrecy). + +**4. Simple Substitution or Caesar Cipher** +- Pros: + - Very easy to implement. + - Minimal overhead. +- Cons: + - Breakable by any opponent listening to multiple messages. + - Not robust even against random guessing. + - Fails to meet our minimum obfuscation requirement. + +Security Improvements Considered +-------------------------------- + +We also thought about ways to make our existing scheme safer: + +**A. Self-validation Using Previous Messages** +- Idea: + - Include hashes of previous messages in the new one to form a chain. +- Pros: + - Detects replay attacks. + - Ensures message sequence integrity. +- Cons: + - Longer messages, less room for content. + - Complicated state-tracking across many independent bots. + - Difficult to resynchronize after disconnects. + +**B. Individual Counters Per Bot** +- Idea: + - Each bot tracks its own counter for rotation. +- Pros: + - Reduces risk of key rotation reuse across bots. + - Slightly harder to guess. +- Cons: + - Requires reliable synchronization of counters. + - Risk of drift if bots miss messages or reconnect. + - Added complexity for small security gain. + +**C. Full Key Cipher Instead of XOR** +- Idea: + - Encrypt entire payload with AES or ChaCha20. +- Pros: + - High security. +- Cons: + - Computationally expensive. + - Large binary outputs unsuitable for nibble encoding. + - Exceeds game's communication limits (plain-text line-based protocol). + +Why We Didn't Use Them +----------------------- + +We chose our design for being: + +- Lightweight enough for many AI clients to run simultaneously. +- Compatible with the game's text-based, line-delimited communication protocol. +- Sufficiently obfuscating to confuse other teams without over-engineering. +- Fast to encode/decode in Python even on limited hardware. + +Ultimately, given the game's constraints (no binary, limited bandwidth, +no out-of-band key exchange), we accepted the trade-off of using a shared +team key with modest obfuscation over unbreakable cryptography. From dc8d5bf7cad3a5db38e5def4434e6611591e0485 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 17:34:27 +0200 Subject: [PATCH 3/7] Add doc for the zappy runner --- docs/_static/.gitkeep | 0 docs/assets/.gitkeep | 0 docs/developer/runner.rst | 216 ++++++++++++++++++++++++++++++++++++++ docs/index.md | 1 + 4 files changed, 217 insertions(+) create mode 100644 docs/_static/.gitkeep create mode 100644 docs/assets/.gitkeep create mode 100644 docs/developer/runner.rst diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/assets/.gitkeep b/docs/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/developer/runner.rst b/docs/developer/runner.rst new file mode 100644 index 00000000..2e80b13b --- /dev/null +++ b/docs/developer/runner.rst @@ -0,0 +1,216 @@ +================ +Zappy Runner +================ + +The **Zappy Runner** is a command-line orchestrator that builds and launches the full Zappy server/AI/GUI suite for development or testing. It uses `nix` (or `nom`) to build binaries (from local or remote sources) and spawns the server, multiple AIs, and the GUI with consistent configuration. + +It is designed to simplify: + +- Building derivations with custom settings (branches, local sources, debug modes) +- Managing multiple team AI clients +- Logging output for debugging +- Coordinating the launch of all components + +This document explains how to use the runner, its options, and how it works internally. + +---------------- +Running the tool +---------------- + +You can invoke the runner via Nix: + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner -- --help + +Or to launch a full local game with defaults: + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner + +---------------- +Basic Usage +---------------- + +By default, this will: + +- Build the Zappy server, AI, and GUI derivations +- Launch the server on port 4242 with a 10x10 map +- Start 2 AI clients per team (3 teams) +- Start the GUI +- Connect all clients automatically + +You can customize almost every parameter with CLI flags. + +---------------- +Example invocations +---------------- + +Use local server and GUI sources (without pulling from GitHub): + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner -- --local-server --local-gui + +Pin server and GUI to specific branches: + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner -- --branch-server fix-map-bug --branch-gui new-theme + +Run with debug server build: + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner -- --debug-server + +---------------- +Full CLI reference +---------------- + +These are all available command-line options: + +.. list-table:: + :header-rows: 1 + + * - Option + - Description + - Default + * - ``--map-width`` + - Map width in tiles + - 10 + * - ``--map-height`` + - Map height in tiles + - 10 + * - ``--team-count`` + - Number of teams + - 3 + * - ``--team-init-count`` + - Number of AI clients per team + - 2 + * - ``--team-init-cap`` + - Initial capacity of players per team on the server + - 200 + * - ``--freq`` + - Server frequency (game ticks per second) + - 100 + * - ``--port`` + - Server port + - 4242 + * - ``--host`` + - Server host address for AI and GUI connections + - 0.0.0.0 + * - ``--ref-gui`` + - Force using reference GUI derivation + - - + * - ``--ref-server`` + - Force using reference server derivation + - - + * - ``--nom`` + - Use ``nom`` instead of ``nix`` for building + - - + * - ``--respective-branches`` + - Build GUI, server, and AI from independent branches + - - + * - ``--branch-gui`` + - Override GUI branch + - None + * - ``--branch-server`` + - Override server branch + - None + * - ``--branch-ai`` + - Override AI branch + - None + * - ``--local-ai`` + - Use local source for AI + - - + * - ``--local-gui`` + - Use local source for GUI + - - + * - ``--local-server`` + - Use local source for server + - - + * - ``--debug-server`` + - Use server build with debug instrumentation + - - + * - ``--basic-team-names`` + - Use simple team names like team1, team2, team3 instead of generated names + - - + * - ``--no-server`` + - Don't launch the server process + - - + * - ``--no-gui`` + - Don't launch the GUI process + - - + * - ``--no-ai`` + - Don't launch any AI clients + - - + * - ``--split-logs`` + - Write separate log files in ``logs/`` directory + - - + * - ``--pause-before-connections`` + - Wait for Enter before starting AI and GUI + - - + +---------------- +Log files +---------------- + +If you use ``--split-logs``, the runner will create a ``logs/`` directory and save separate log files for: + +- Server output +- Each AI client +- GUI + +It also writes a ``.gitignore`` to exclude logs from version control. + +---------------- +Team names +---------------- + +By default, the runner generates unique, random, pronounceable team names (like *Zavria* or *Plouvenek*). Use ``--basic-team-names`` to get deterministic names: ``team1``, ``team2``, etc. + +---------------- +Branches and Sources +---------------- + +You can control precisely which code is built: + +- By default, all components build from the ``zappy-runner`` flake input (same branch). +- ``--respective-branches`` lets you specify different branches for server, GUI, AI. +- You can also force use of local sources (no branch) or official reference derivations. + +---------------- +How it works +---------------- + +When you run the runner: + +1. It parses CLI options and computes build settings (bitmask flags). +2. It resolves source derivations (with branches, local overrides, or reference builds). +3. It runs ``nix build`` or ``nom build`` for the required derivations. +4. It extracts the binaries from the Nix build outputs. +5. It launches: + - The server process (if not disabled) + - Multiple AI processes (per team and init count) + - The GUI process (if not disabled) +6. It manages their lifecycles and shuts them down cleanly on interrupt. + +---------------- +Nix Build System +---------------- + +All building is done via Nix (or Nom if specified). The runner supports: + +- Selecting branches (for testing specific changes) +- Local development builds (no GitHub fetch) +- Reference derivations (stable baseline) + +This ensures reproducible builds and simplifies testing multiple configurations. + +---------------- +Interrupt Handling +---------------- + +If you interrupt the runner (Ctrl+C), it gracefully terminates all subprocesses to avoid zombie processes. diff --git a/docs/index.md b/docs/index.md index 37ac0158..15d6e03f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,6 +11,7 @@ developer/architecture developer/contribution developer/systems developer/usage_ai +developer/runner modules protocol/protocol ``` From ae34003e6d10c5480e157b548ed1c9d172e189e5 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 18:40:16 +0200 Subject: [PATCH 4/7] Add documentation for the building process --- docs/developer/build.rst | 222 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 docs/developer/build.rst diff --git a/docs/developer/build.rst b/docs/developer/build.rst new file mode 100644 index 00000000..2febab9a --- /dev/null +++ b/docs/developer/build.rst @@ -0,0 +1,222 @@ +======================= +How to Build Zappy +======================= + +This page explains everything you need to install to build and run the +Zappy project. It is structured into sections for: + +- Minimal delivery (AI / Server / GUI) +- Runner +- Documentation +- Development (extra) + +Where possible, two approaches are described: + +- **Using Nix** (recommended for reproducibility) +- **Traditional/manual** install (for portability) + +------------------------ +Minimal delivery (AI / Server / GUI) +------------------------ + +These are the core components needed to *run* or *develop* the server, AI, +and GUI separately. + +**Using Nix (recommended)** + +If you have Nix installed: + +.. code-block:: bash + + nix develop + +This will enter a shell with all dependencies available for building the server, +AI, and GUI. + +**Traditional (manual) install** + +You'll need to install these system packages yourself: + +* **Common build tools**: + - bash + - coreutils + - gnugrep + - findutils + - GNU Make + - pkg-config + +* **Server**: + - gcc + - glibc (with math libraries) + +* **AI**: + - Python 3.13 (or compatible) with pip + - virtualenv or Python's built-in venv module + - pip packages: + - setuptools + - hatching + +* **GUI**: + - g++ (with libstdc++) + - SDL2 + - SDL2_image + - glew + - GL, GLU + - glm + - mesa + +* **Optional**: + - ncurses (for pretty Makefile logs) + +------------------------ +Runner +------------------------ + +The **runner** tool (to coordinate AI, server, GUI in one command) requires: + +**Using Nix (recommended)** + +Nix is the only requirement: + +.. code-block:: bash + + nix run github:Sigmapitech/zappy/zappy-runner + +This will handle all other builds and dependencies automatically. + +**Traditional (manual) install** + +There is no non-Nix delivery for the runner. If you want to avoid Nix entirely, +you'll have to run the server, AI, and GUI manually in separate terminals, +using the minimal delivery setup above. + +------------------------ +Documentation +------------------------ + +To build the Sphinx documentation: + +**Using Nix** + +All packages are included in the dev shell: + +.. code-block:: bash + + nix develop + make -C docs html + +**Traditional install** + +You’ll need: + +* **System** + - doxygen + - libxml + +* **Python packages (install via pip)** + - sphinx + - furo + - breathe + - exhale + - beautifulsoup4 + - six + - linkify-it-py + - myst-parser + - sphinx-copybutton + - sphinx-design + - sphinx-notfound-page + - sphinx-sitemap + +Example: + +.. code-block:: bash + + pip install sphinx furo breathe exhale beautifulsoup4 six linkify-it-py myst-parser \ + sphinx-copybutton sphinx-design sphinx-notfound-page sphinx-sitemap + +Then: + +.. code-block:: bash + + doxygen + make -C docs html + +------------------------ +Development (extra) +------------------------ + +Additional tools recommended for testing, coverage, linting, and advanced debugging. + +**Using Nix** + +These are included in the dev shell: + +.. code-block:: bash + + nix develop + +**Traditional install** + +You can install these manually via your system package manager or pip. + +* **Testing and coverage** + - gcovr + - libcoverage + - pytest + +* **Static analysis and formatting** + - compiledb + - clang-tools + - black + - mypy + - isort + - vulture + +* **Logging & profiling** + - hl-log-viewer + - valgrind + - kcachegrind + - graphviz + +------------------------ +Recommended approach +------------------------ + +We strongly recommend using Nix for development: + +.. code-block:: bash + + nix develop + +This ensures: + +- Reproducible builds +- All dependencies present +- Correct versions matched to the project + +You can build/run each package from their nix derivation, following the flake schema: + +... code-block:: bash + + └───packages + └───x86_64-linux + ├───ai: package 'python3.13-zappy-ai' + ├───bleach: package 'bleach-0.0.1' + ├───cpp-fmt: package 'cpp-fmt' + ├───default: package 'zappy' + ├───doc: package 'doc' + ├───exhale: package 'python3.13-exhale-0.3.7' + ├───gui: package 'zappy-gui-0.0.1' + ├───ref: package 'ref' + ├───ref-gui: package 'ref-gui-3.0.0' + ├───ref-server: package 'ref-server-3.0.1' + ├───runner: package 'python3.13-zappy' + ├───server: package 'zappy-server-0.0.1' + └───server-debug: package 'zappy-server-0.0.1' + +Note: it is recommended to derectly build/run the final derivation (default), +that contains our delivery and reference binaries, alongside the zappy-runner ... +see instructions on how to use the zappy-runner + +If you prefer manual installs, make sure to match the versions in your package +manager as closely as possible to avoid compatibility issues. From 529401ede58dc880db21f19f6663948547af88dd Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 18:40:49 +0200 Subject: [PATCH 5/7] Rename "API documentation" into "Code documentation" --- .gitignore | 1 + Doxyfile | 2 +- docs/.gitignore | 2 +- docs/conf.py | 6 +++--- docs/index.md | 3 ++- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 8c3e7e27..7ef4e707 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ docs/source/api # Logs logs *.log +docs/code/* diff --git a/Doxyfile b/Doxyfile index 681a0116..b9a5dc3c 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,5 +1,5 @@ PROJECT_NAME = Zappy -INPUT = server gui +INPUT = server gui ia FILE_PATTERNS = *.c *.cpp *.h *.hpp RECURSIVE = YES diff --git a/docs/.gitignore b/docs/.gitignore index eedd89b4..1be39564 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1 @@ -api +code/* diff --git a/docs/conf.py b/docs/conf.py index af3c1728..a4ac2e22 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,9 +31,9 @@ } exhale_args = { - "containmentFolder": "./api", - "rootFileName": "api.rst", - "rootFileTitle": "API Documentation", + "containmentFolder": "./code", + "rootFileName": "code.rst", + "rootFileTitle": "Code Documentation", "doxygenStripFromPath": "..", "createTreeView": True, } diff --git a/docs/index.md b/docs/index.md index 15d6e03f..52453f27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,9 +5,10 @@ :maxdepth: 2 :caption: Contents: -api/api +code/code ai/ai developer/architecture +developer/build developer/contribution developer/systems developer/usage_ai From 28f9b076524bc27d19e148b83848d942b43a60b3 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 20:25:51 +0200 Subject: [PATCH 6/7] Fix some documentation issue --- Doxyfile | 2 +- docs/ai/jobs.rst | 10 ++++-- docs/ai/protocol.rst | 68 +++++++++++++++++++++++++++++----------- docs/ai/strategies.rst | 16 +++++++--- docs/developer/build.rst | 5 +-- 5 files changed, 71 insertions(+), 30 deletions(-) diff --git a/Doxyfile b/Doxyfile index b9a5dc3c..7c708f98 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,5 +1,5 @@ PROJECT_NAME = Zappy -INPUT = server gui ia +INPUT = server gui ai FILE_PATTERNS = *.c *.cpp *.h *.hpp RECURSIVE = YES diff --git a/docs/ai/jobs.rst b/docs/ai/jobs.rst index cbe8e435..fec0c883 100644 --- a/docs/ai/jobs.rst +++ b/docs/ai/jobs.rst @@ -3,7 +3,9 @@ AI Job System This page explains the *Legacy AI Behavior* we experimented with for the project. -Our unfinished AI design used well-defined behavioral roles called **Jobs**. Each job had its own file in `ai/behavior/`, implementing the abstract `JobTemplate` class. This class provided a shared structure for all specialized behaviors. +Our unfinished AI design used well-defined behavioral roles called **Jobs**. +Each job had its own file in `ai/behavior/`, implementing the abstract `JobTemplate` class. +This class provided a shared structure for all specialized behaviors. Overview -------- @@ -42,7 +44,8 @@ Overview Job Assignment System ---------------------- -The Elder assigns jobs dynamically, using our team's broadcast protocol. Each player listens for instructions and responds appropriately. +The Elder assigns jobs dynamically, using our team's broadcast protocol. +Each player listens for instructions and responds appropriately. Communication Protocol ----------------------- @@ -81,4 +84,5 @@ This system was designed to: - Allow role reassignment and adaptability during play. - Disrupt enemy teams by embedding Garblers who mimic or garble enemy messages. -Although unfinished, this "Job System" represents an ambitious attempt to create complex AI behaviors resembling a true in-game society. +Although unfinished, this "Job System" represents an ambitious attempt to create +complex AI behaviors resembling a true in-game society. diff --git a/docs/ai/protocol.rst b/docs/ai/protocol.rst index 0cc923c1..e8be442f 100644 --- a/docs/ai/protocol.rst +++ b/docs/ai/protocol.rst @@ -1,12 +1,14 @@ AI Protocol =========== -This page explains the communication protocol between the AI client and the server, as defined in the project specification. +This page explains the communication protocol between the AI client and the server, +as defined in the project specification. Overview -------- -The AI connects to the server via TCP and exchanges text commands. The server responds in plain text. The basic handshake: +The AI connects to the server via TCP and exchanges text commands. The server +responds in plain text. The basic handshake: :: @@ -23,22 +25,48 @@ Where: Command/Response Examples -------------------------- -+-----------------+-------------------------+------------------------------+ -| Command | Time (1/f) | Response | -+=================+=========================+==============================+ -| Forward | 7/f | ok | -| Right | 7/f | ok | -| Left | 7/f | ok | -| Look | 7/f | [tile1, tile2, ...] | -| Inventory | 1/f | [object count, ...] | -| Broadcast text | 7/f | ok | -| Connect_nbr | - | number of remaining slots | -| Fork | 42/f | ok | -| Eject | 7/f | ok / ko | -| Take object | 7/f | ok / ko | -| Set object | 7/f | ok / ko | -| Incantation | 300/f | Elevation underway / ko | -+-----------------+-------------------------+------------------------------+ +.. list-table:: Player Commands + :header-rows: 1 + + * - Command + - Time (1/f) + - Response + * - Forward + - 7/f + - ok + * - Right + - 7/f + - ok + * - Left + - 7/f + - ok + * - Look + - 7/f + - [tile1, tile2, ...] + * - Inventory + - 1/f + - [object count, ...] + * - Broadcast text + - 7/f + - ok + * - Connect_nbr + - - + - number of remaining slots + * - Fork + - 42/f + - ok + * - Eject + - 7/f + - ok / ko + * - Take object + - 7/f + - ok / ko + * - Set object + - 7/f + - ok / ko + * - Incantation + - 300/f + - Elevation underway / ko Vision ------ @@ -63,7 +91,9 @@ Players can broadcast messages. The server responds: message K, text -Where K indicates direction relative to the receiver. Directions are determined by the tile layout around the player, choosing the shortest wraparound path on the toroidal map. +Where K indicates direction relative to the receiver. Directions are determined +by the tile layout around the player, choosing the shortest wraparound path on +the toroidal map. Reproduction ------------ diff --git a/docs/ai/strategies.rst b/docs/ai/strategies.rst index 2d355deb..dee9239b 100644 --- a/docs/ai/strategies.rst +++ b/docs/ai/strategies.rst @@ -1,9 +1,12 @@ AI Strategies ============= -This page describes several strategies we considered (and partly implemented or designed) for coordinating our AI players. Each approach balances complexity, coordination overhead, and robustness to adversarial teams. +This page describes several strategies we considered (and partly implemented or +designed) for coordinating our AI players. Each approach balances complexity, +coordination overhead, and robustness to adversarial teams. -Our goal was to provide flexibility to assign strategies dynamically depending on the game context. +Our goal was to provide flexibility to assign strategies dynamically depending +on the game context. 1. Elder-Centric Hub Strategy ------------------------------ @@ -41,7 +44,8 @@ Our goal was to provide flexibility to assign strategies dynamically depending o - No Elder. - Each player roams the map collecting stones independently. -- When a player has all stones for next level, it broadcasts a "call" for all same-level teammates nearby. +- When a player has all stones for next level, it broadcasts a "call" for all +same-level teammates nearby. - Players move to the caller to attempt evolution. **Pros:** @@ -189,6 +193,8 @@ In practice, the AI system was designed to switch between these strategies depen - Enemy activity (e.g. presence of Garblers). - Map size and density. -By mixing these approaches, we hoped to create a robust and adaptable AI civilization capable of winning under varied conditions. +By mixing these approaches, we hoped to create a robust and adaptable AI +civilization capable of winning under varied conditions. -This flexibility allows the AI to respond dynamically to the evolving game state, maximizing its chances of success against both human and AI opponents. +This flexibility allows the AI to respond dynamically to the evolving game state, +maximizing its chances of success against both human and AI opponents. diff --git a/docs/developer/build.rst b/docs/developer/build.rst index 2febab9a..563d09f8 100644 --- a/docs/developer/build.rst +++ b/docs/developer/build.rst @@ -196,9 +196,9 @@ This ensures: You can build/run each package from their nix derivation, following the flake schema: -... code-block:: bash +.. code-block:: bash - └───packages + └───packages └───x86_64-linux ├───ai: package 'python3.13-zappy-ai' ├───bleach: package 'bleach-0.0.1' @@ -214,6 +214,7 @@ You can build/run each package from their nix derivation, following the flake sc ├───server: package 'zappy-server-0.0.1' └───server-debug: package 'zappy-server-0.0.1' + Note: it is recommended to derectly build/run the final derivation (default), that contains our delivery and reference binaries, alongside the zappy-runner ... see instructions on how to use the zappy-runner From 7afd05c502e33ce651397cbcc93d3eee801b84c8 Mon Sep 17 00:00:00 2001 From: Fenriir42 Date: Sun, 29 Jun 2025 20:48:43 +0200 Subject: [PATCH 7/7] Fix the job's list-table --- docs/ai/jobs.rst | 95 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/docs/ai/jobs.rst b/docs/ai/jobs.rst index fec0c883..231ff725 100644 --- a/docs/ai/jobs.rst +++ b/docs/ai/jobs.rst @@ -52,27 +52,80 @@ Communication Protocol All inter-player instructions passed through team broadcasts during the game are defined below: -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ -| **Job** | **Instruction (Recv)** | **Instruction (Send)** | **Effect** | **Args / Type** | -+============+===================================+===============================================+==========================================================+=========================================+ -| Basic | `assign_job ` | `evolution_ready ` | Elder-directed reassignment; immediate job transition | id: `int`, job: `str` | -| | `evolution_call ` | `evolution_response ` | Respond to Elder's group evolution call | id: `int` | -| | `status_report_request` | `basic_status level: needs: food:` | Periodic status update to Elder | level: `int`, needs: `int`, food: `int` | -| | `resource_request ` | `resource_available ` | Reply if the player holds excess resources | resource: `str`, amt: `int` | -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ -| Elder | `newcomer_seeking_assignment` | `assign_job ` | Assigns job to a newcomer | id: `int`, job: `str` | -| | `resource_delivery ` | `status_report_request` | Updates depot stock from Collector; asks for reports | resource: `str`, amt: `int` | -| | | `elder_location ` | Announces Elder's tile location | x: `int`, y: `int` | -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ -| Newcomer | `elder_announce ` | `newcomer_seeking_assignment ` | Announces presence and level; awaits Elder assignment | id: `int`, level: `int` | -| | `assign_job ` | `newcomer_joined` | Confirms receiving role assignment | id: `int`, job: `str` | -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ -| Collector | | `resource_delivery ` | Delivers collected resources to the Elder | resource: `str`, amt: `int` | -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ -| Garbler | | *variable garbage* | Disrupts enemies with random unreadable text | `str` | -| | | *intercepted_message (mimicry/parrot)* | Mimic or distort intercepted enemy messages | `str` | -| | *any enemy message* | | Stores for mimicry/parrot modes | `str` | -+------------+-----------------------------------+-----------------------------------------------+----------------------------------------------------------+-----------------------------------------+ +.. list-table:: Job Protocol + :header-rows: 1 + :widths: 10 25 25 25 15 + + * - Job + - Instruction (Recv) + - Instruction (Send) + - Effect + - Args / Type + * - Basic + - ``assign_job `` + - ``evolution_ready `` + - Elder-directed reassignment; immediate job transition + - id: ``int``, job: ``str`` + * - + - ``evolution_call `` + - ``evolution_response `` + - Respond to group evolution call + - id: ``int`` + * - + - ``status_report_request`` + - ``basic_status level: needs: food:`` + - Periodic status update to elder + - level: ``int``, needs: ``int``, food: ``int`` + * - + - ``resource_request `` + - ``resource_available `` + - Respond if excess resource is held + - resource: ``str``, amt: ``int`` + * - Elder + - ``newcomer_seeking_assignment`` + - ``assign_job `` + - Assigns newcomer to job + - id: ``int``, job: ``str`` + * - + - ``resource_delivery `` + - ``status_report_request`` + - Update depot stock from collector; ask for reports + - resource: ``str``, amt: ``int`` + * - + - + - ``elder_location `` + - Updates elder position for everyone + - x: ``int``, y: ``int`` + * - Newcomer + - ``elder_announce `` + - ``newcomer_seeking_assignment `` + - Announces presence and level; awaits elder reply + - id: ``int``, level: ``int`` + * - + - ``assign_job `` + - ``newcomer_joined`` + - Elder assigns role; confirms join + - id: ``int``, job: ``str`` + * - Collector + - + - ``resource_delivery `` + - Dispose of the collected stones on the Elder's tile + - resource: ``str``, amt: ``int`` + * - Garbler + - + - *variable garbage* + - Disruption: random unreadable text + - ``str`` + * - + - + - *intercepted_message (mimicry/parrot)* + - Disruption: repeated or modified enemy message + - ``str`` + * - + - *any enemy message* + - + - Stores for mimicry or parrot use + - ``str`` Behavior Philosophy --------------------