Skip to content

Known limitations

About this page

This page documents the actual state of the code as it exists today: functions left as stubs, mismatches between the code and the historical documentation, and potential bugs found while reviewing the repository. The goal is an honest, precise reference — not a blame list. Each item is framed as a current state, a known limitation or future work, with the file:line when known and the practical impact.

The code is functional for the nominal use case; the items below concern un-wired branches, representation inconsistencies, or features that are announced but not realized end-to-end.


IA (Python)

The AI (ai/) is largely implemented, even though its README still calls it a "skeleton". Several stubs and inconsistencies remain.

Stubs (raise an error if reached)

Unimplemented functions

Item Location Impact
parse_broadcast ai/src/protocol/parser.py:102 Raises NotImplementedError. Inbound message K, text broadcasts are not handled end-to-end: sound-based rally is not realized.
ForkState (4 methods) ai/src/strategy/states/fork.py:27,33,37,41 All methods raise NotImplementedError. FORK is registered in the FSM but no transition leads to it; entering it would crash. The reproduction strategy (Fork/Connect_nbr) is unimplemented.
tile_index_to_relative_coord ai/src/state/vision.py:20 Dead stub: the equivalent geometry is implemented inline in WorldMap.update_from_look. Never called, so no runtime effect.

See IA > Strategy (FSM) and IA > Protocol layer.

Implemented but not wired in

Present and tested, but with no caller

The entire team/ package (crypto.py, protocol.py, decoy.py) is implemented and covered by tests, but is only referenced from within team/ itself: there is no caller in the network or strategy code. Encrypted team comms and decoys are therefore not actually used at runtime. See IA > Team coordination.

Other implemented-but-unused items:

  • pathfinding.bfs_toric — full toric BFS, no caller.
  • pathfinding.direction_from_sound — maps K (0–8) to a direction, unused (tied to the absence of sound-based rally).
  • Client.flush_output — implemented but never called from the main loop.
  • CommandQueue._callbacks — stored by add_callback but never read (effectively dead).
  • ConnectNbrResult — message type never produced (because ForkState is a stub).
  • config.DEFAULT_HOST — unused constant.

Probable bug: food unit comparison

Food thresholds: count vs time units

The food-threshold comparisons compare drone.food (a food count) against FOOD_SURVIVAL_THRESHOLD * LIFE_PER_FOOD (a value in time units, e.g. 5 * 126 = 630). They therefore compare a count (typically a few units) against a value in ticks (hundreds), so some transitions may effectively never fire.

Affected in: survive, collect, incant_prep, incant (ai/src/strategy/states/). See IA > Strategy (FSM).

Handshake fragility

do_handshake assumes a single grouped receive

In ai/src/network/connection.py (do_handshake, ~:65), the code assumes that CLIENT-NUM and the X Y line arrive in a single recv (splitlines()[0] / [1]). With TCP fragmentation, this can raise an IndexError. See IA > Network & command queue.

Code / documentation mismatches

The code does not always match the docstrings/README

  • I/O loop: main uses select-with-timeout polling (select.select([...], [], [], 0.1)), not the selectors module, contrary to the docstrings and the README. The main loop is a non-blocking while 1, not a busy-wait-free event loop.
  • README FSM diagram: the historical diagram (sound-based RALLY, EXPLORE as the default state, a FORK loop) does not match the implementation: RALLY is coordinate-based, the initial state is survive, and FORK is unreachable.

See IA > Decision loop and IA > Strategy (FSM).

Debug leftovers and configuration

Items to clean up

  • Leftover debug print() calls: ai/src/strategy/states/collect.py:50 and :95, ai/src/strategy/states/incant_prep.py:77.
  • pyproject.toml: the wheel target [tool.hatch.build.targets.wheel] references packages=["src/zappy_ai"], a non-existent directory. The wheel build is thus misconfigured — with no impact, since the client is run directly (via ./zappy_ai), not installed.

Server (C++)

Food representation mismatch

The food quantity does not have the same representation depending on the consumer:

  • the AI receives food in the Inventory as units * 126 (server/srcs/commands/CmdInventory.cpp:12);
  • the GUI receives, via pin, the raw unit count (server/srcs/protocol/GUIProtocol.cpp:100).

Furthermore, the Player.hpp comment describes food as 1260 ticks, which does not match the 10-unit model (1 unit consumed every 126 ticks). The total duration is equivalent (10 × 126 = 1260); only the representation differs. See Server > Players, teams & eggs.

Server events / commands

  • smg: the GUI event smg is defined in GUIProtocol but no server call site emits it (appears unused).
  • Connect_nbr: the command returns the count of remaining (unhatched) team eggs rather than a separately tracked count of free connection slots. The approximation is reasonable but is not, strictly speaking, a dedicated free-slot counter.

See Server > Commands & delays.


GUI (C++ / Raylib)

Raylib version not pinned

The Raylib version is pinned nowhere (build files, docs, binary). The build assumes a system-installed libraylib (dynamic link -lraylib -lGL ...) and a GL / GLSL 330-capable driver (the recolor.frag shader targets #version 330). There is no vendoring, find_package, pkg-config or FetchContent. The GUI > Installing Raylib page therefore describes a generic install (distribution package or build-from-source).

Dead code and ignored messages

  • gui/raylib/Window.*: thin wrapper that is not compiled (absent from the Makefile SRCS) and not used — dead/legacy code.
  • mct: the handler is a no-op (the server expands mct into per-tile bct).
  • sst: not handled by the GUI (no handler).
  • The GUI handles only the 21 messages registered in MessageParser. Server-emitted sst / suc / sbp are ignored — which is consistent since the GUI only ever sends GRAPHIC.

Player info panel (PlayerCard) stubbed

The 2D PlayerCard panel is wired in but inoperative: _focusedPlayerId (Renderer3D.hpp:53) is never set (stays -1). The "focused player" branch therefore never runs, and the card is always drawn empty, with the hardcoded name "Salut" (PlayerCard.cpp:20).

Assets and camera shortcuts

  • Assets: many on-disk asset folders are unused; only 13 animation folders plus the shader, the font and the playerCard elements are loaded.
  • Camera: the README key table is partly inconsistent with the actual IsoCamera code. Trust the code and the in-app hint ("W/S height | A/D radius | Q/E orbit").

See GUI > Rendering.


Build / documentation drift

Two AI directories

Two AI directories coexist:

  • ai/ is the live AI (real Python code, zappy_ai, tests, docs);
  • ia/ is legacy / dead (only a shell script and empty directories, no .py).

The root Makefile correctly references ai/. The ia/ directory can be ignored.

CI and docs

  • CI: the Jenkinsfile does not build or test the GUI: it only builds and tests the server (build, cppcheck, doctest, coverage) and runs the AI pytest suite. The only GitHub workflow (.github/workflows/mirror.yml) merely mirrors the repository.
  • Missing doc: gui/README.md references a docs/GUI_protocol.md file that does not exist.