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..7c708f98 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,5 +1,5 @@ PROJECT_NAME = Zappy -INPUT = server gui +INPUT = server gui ai 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/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b 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..231ff725 --- /dev/null +++ b/docs/ai/jobs.rst @@ -0,0 +1,141 @@ +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: + +.. 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 +-------------------- + +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..c42f770f --- /dev/null +++ b/docs/ai/message_cipher.rst @@ -0,0 +1,224 @@ +Message Ciphering +================== + +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 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 + + def derive_team_key(team_name: str) -> bytes: + return pbkdf2_hmac( + 'sha256', team_name.encode(), b'3301', 10000, 2048 + ) + +- 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. 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 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 the string. +2. Unpack the header. +3. Validate the checksum. +4. XOR-decrypt using rotation. +5. Parse the content as ASCII. + +Header Format +-------------- + +.. code-block:: python + + def build_header(bot_id, counter, rotation, timestamp, checksum, length): + 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 +--------------- + +We use a custom 16-character LUT to map binary data into text: + +:: + + AIOU aiou qpdb QPDB + +- 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. + diff --git a/docs/ai/protocol.rst b/docs/ai/protocol.rst new file mode 100644 index 00000000..e8be442f --- /dev/null +++ b/docs/ai/protocol.rst @@ -0,0 +1,116 @@ +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 +-------------------------- + +.. 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 +------ + +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..dee9239b --- /dev/null +++ b/docs/ai/strategies.rst @@ -0,0 +1,200 @@ +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/assets/.gitkeep b/docs/assets/.gitkeep new file mode 100644 index 00000000..e69de29b 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/developer/build.rst b/docs/developer/build.rst new file mode 100644 index 00000000..563d09f8 --- /dev/null +++ b/docs/developer/build.rst @@ -0,0 +1,223 @@ +======================= +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. 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 1fc1af99..52453f27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,11 +5,14 @@ :maxdepth: 2 :caption: Contents: -api/api +code/code +ai/ai developer/architecture -developer/systems +developer/build developer/contribution +developer/systems developer/usage_ai -protocol/protocol +developer/runner modules +protocol/protocol ```