Skip to content

Handshake

On connection, the server immediately sends WELCOME\n to any new client (PendingClient, server/srcs/network/PendingClient.cpp). The client's first line then determines its type:

  • if it is the reserved keyword GRAPHIC, the client becomes a GUI;
  • otherwise, the line is read as a team name: the client becomes an AI if an egg is still available in that team.

All routing is handled by ClientSessionManager (server/srcs/core/ClientSessionManager.cpp).

AI handshake

sequenceDiagram
    participant AI as zappy_ai
    participant S as Server
    S->>AI: WELCOME
    AI->>S: <team-name>
    Note over S: hatch an egg of the team
    S->>AI: <CLIENT-NUM>   (remaining slots)
    S->>AI: <X> <Y>        (world size)

The client sends its team name. If the team exists and at least one egg is free, the server:

  1. hatches an egg into a new player (Player);
  2. replies <CLIENT-NUM>\n: the number of remaining slots in the team, i.e. the number of eggs still available after hatching;
  3. replies <X> <Y>\n: the width and height of the world.

(ClientSessionManager.cpp:123-127.)

Failure

Unknown team or no available egg

If the team name is unknown or the team has no egg left, the server replies ko\n and closes the connection (ClientSessionManager.cpp).

Example (success)

S -> C : WELCOME
C -> S : team1
S -> C : 5
S -> C : 10 10

Here team team1 had 6 eggs: after hatching, 5 remain, and the world is 10 × 10.

AI side

The AI client waits for the exact string WELCOME, sends the team name, then reads CLIENT-NUM and X Y. The implementation assumes these last two lines arrive in the same packet (splitlines()), which is fragile under TCP fragmentation — see AI connection and Known limitations. Reference: ai/src/network/connection.py (do_handshake).

GUI handshake

sequenceDiagram
    participant GUI as zappy_gui
    participant S as Server
    S->>GUI: WELCOME
    GUI->>S: GRAPHIC
    S->>GUI: msz X Y
    S->>GUI: sgt T
    loop for each team
        S->>GUI: tna <team-name>
    end
    loop for each tile (mct → bct)
        S->>GUI: bct X Y q0 q1 q2 q3 q4 q5 q6
    end
    loop for each player
        S->>GUI: pnw #id X Y O L N
        S->>GUI: plv #id L
        S->>GUI: pin #id X Y q0..q6
    end
    loop for each egg
        S->>GUI: enw #egg #player X Y
    end

As soon as it receives GRAPHIC, the server performs a full initial dump of the world state, in this order (ClientSessionManager.cpp:31-66):

  1. msz X Y — map size;
  2. sgt T — current frequency/time unit;
  3. tna <name> — one message per team;
  4. the whole map: sendMct iterates over all tiles and emits one bct per tile (the GUI therefore never receives an aggregated mct, see the warning below);
  5. for each already-present player: pnw, then plv, then pin;
  6. for each existing egg: enw.

Example (excerpt)

C -> S : GRAPHIC
S -> C : msz 10 10
S -> C : sgt 100
S -> C : tna team1
S -> C : tna team2
S -> C : bct 0 0 1 0 0 0 0 0 0
S -> C : bct 1 0 0 1 0 0 0 0 0
...
S -> C : bct 9 9 0 0 0 0 0 0 0
S -> C : pnw #1 4 5 2 1 team1
S -> C : plv #1 1
S -> C : pin #1 4 5 10 0 0 0 0 0 0
S -> C : enw #3 #-1 7 2

In pnw #1 4 5 2 1 team1, player #1 is at (4,5), oriented 2 (East), level 1, team team1. The detailed format of each event is given in GUI ↔ Server.

mct always expanded into bct

The server never emits a consolidated mct event: it "explodes" it into a series of bct (one per tile). On the GUI side, the onMct handler exists but is deliberately a no-op. See Known limitations.