IA (Python) — Vue d'ensemble¶
Le client IA de Zappy est un drone autonome écrit en Python (3.11+). Il se connecte au serveur de jeu par une socket TCP, observe son environnement, décide seul de ses actions et tente de faire monter son équipe en niveau via les incantations.
Aucune dépendance externe
Le projet n'utilise que la bibliothèque standard : pyproject.toml
déclare dependencies = [] et requires-python >= 3.11. Pas de framework
réseau, pas de selectors, pas de asyncio — uniquement socket,
select, argparse, dataclasses, etc. (ai/pyproject.toml).
Lancement¶
Le client s'invoque via le lanceur zappy_ai, qui insère src/ dans le
sys.path puis appelle main() :
| Option | Rôle | Défaut |
|---|---|---|
-p/--port |
Port TCP du serveur | aucun |
-n/--name |
Nom de l'équipe (handshake) | aucun |
-h/--host |
Adresse de la machine serveur | 127.0.0.1 |
--debug |
Active les logs de débogage | désactivé |
Arguments « requis » non contraints
Le sujet décrit -p et -n comme obligatoires, mais parse_args
(ai/src/main.py:45-57) ne pose pas required=True : leur valeur par
défaut est None. De même, config.DEFAULT_HOST = "localhost"
(ai/src/config.py:106) n'est pas utilisé — le défaut effectif est
127.0.0.1. Voir Limitations connues.
Architecture en couches¶
Le code est organisé en couches nettes, du plus bas niveau (octets sur le réseau) au plus haut niveau (décisions stratégiques).
flowchart TD
main["main.py<br/>(point d'entrée, boucle)"]
subgraph strategy["strategy/ — décision"]
fsm["FSM"]
states["states/<br/>survive, rally, collect,<br/>explore, incant_prep, incant…"]
path["pathfinding<br/>incantation"]
end
subgraph state["state/ — état interne"]
drone["DroneState"]
wmap["WorldMap"]
inv["inventory / vision"]
end
subgraph protocol["protocol/ — sérialisation"]
parser["parser"]
commands["commands"]
messages["messages"]
update["update"]
end
subgraph network["network/ — transport"]
client["Client"]
conn["Connection"]
cq["CommandQueue"]
buf["InputBuffer / OutputBuffer"]
end
team["team/ — coordination<br/>(crypto, protocol, decoy)"]
utils["utils/ — logger"]
main --> strategy
main --> network
strategy --> state
strategy --> protocol
state --> protocol
protocol --> messages
network --> protocol
network --> conn
network --> cq
network --> buf
strategy -.->|prévu, non câblé| team
main --> utils
La couche team/ n'est pas câblée
Le paquet team/ (chiffrement, protocole inter-drones, leurres) est
entièrement implémenté mais jamais appelé par le réseau ou la
stratégie. Voir Coordination d'équipe et
Limitations connues.
Arborescence des sources¶
ai/
├── zappy_ai # lanceur exécutable (insère src/ dans sys.path)
├── pyproject.toml # zappy_ai, requires-python >=3.11, deps=[]
└── src/
├── main.py # parse_args, run() : boucle principale
├── config.py # constantes du sujet (coûts, prérequis, seuils)
├── network/
│ ├── connection.py # socket TCP + handshake
│ ├── client.py # orchestration envoi/réception
│ ├── command_queue.py # file des 10 commandes en vol (FIFO)
│ └── buffers.py # découpage du flux en lignes
├── protocol/
│ ├── parser.py # lignes serveur -> messages typés
│ ├── commands.py # constructeurs de commandes (chaînes pures)
│ ├── messages.py # dataclasses des messages
│ └── update.py # callbacks de mise à jour de l'état
├── state/
│ ├── drone.py # DroneState (niveau, food, position…)
│ ├── inventory.py # helpers d'inventaire
│ ├── vision.py # géométrie du champ de vision
│ └── world_map.py # carte mentale torique
├── strategy/
│ ├── fsm.py # machine à états + pilotage des commandes
│ ├── incantation.py # prérequis d'élévation
│ ├── pathfinding.py # distances/déplacements toriques
│ └── states/ # 8 états concrets de la FSM
├── team/ # crypto.py, protocol.py, decoy.py (non câblés)
└── utils/
└── logger.py
Déroulé du démarrage¶
La fonction run(args) (ai/src/main.py:83) enchaîne :
sequenceDiagram
participant M as main.run
participant C as Client
participant Cx as Connection
participant D as DroneState
participant F as FSM
M->>C: setup_connection(host, port, name)
C->>Cx: connect() puis do_handshake()
Cx-->>C: (nb_per_team, (W, H))
C-->>M: (nb_per_team, (W, H))
M->>D: DroneState(nb_per_team, (W,H), client)
Note over D: envoie immédiatement<br/>Inventory + Look
M->>F: FSM(drone, client)
M->>F: transition_to("survive")
loop tant que vivant
M->>C: receive() (lit, route vers les callbacks)
loop tant que command_queue.can_send()
M->>F: decide_next_command()
end
end
- Connexion & handshake —
Client.setup_connectionouvre laConnection, déroule le handshake (WELCOME, envoi du nom d'équipe, lecture duCLIENT-NUMpuisX Y) et renvoie(nb_per_team, (largeur, hauteur)). - État initial —
DroneState(nb_per_team, world_size, client)place le drone au centre de la carte, oriente auN, construit laWorldMap, et envoie d'embléeInventoryetLookpour amorcer l'état (ai/src/state/drone.py:76-86). - FSM —
FSM(drone, client)enregistre les états et démarre sur l'étatsurvive(ai/src/main.py:124-125).
État initial survive, pas explore
Le README et certains schémas décrivent un démarrage en explore. Le code
démarre en réalité sur survive. Voir Limitations connues.
Boucle principale¶
while 1:
client.receive() # lit le réseau, route les réponses
while client.command_queue.can_send(): # tant qu'il reste des slots
if not fsm.decide_next_command(): # demande une action à la FSM
break
if drone.is_dead() and config.INIT: # famine confirmée
break
La boucle (ai/src/main.py:127-144) reçoit d'abord (les réponses serveur
mettent à jour l'état via les callbacks), puis demande des commandes à la
FSM tant que la file de commandes en vol n'est pas pleine (plafond de 10).
Boucle active, pas de multiplexage selectors
Malgré les docstrings, il n'y a pas de boucle selectors sans attente
active : c'est un while 1 qui appelle select.select(..., 0.1) (poll de
100 ms). Voir Limitations connues.
Pour aller plus loin¶
- Réseau & file de commandes — transport TCP, handshake, FIFO des commandes en vol.
- Couche protocole — parsing des lignes serveur, constructeurs de commandes, messages typés.
- État interne —
DroneState, inventaire, vision, carte torique. - Stratégie (FSM) — machine à états et état local optimiste.
- Coordination d'équipe — chiffrement et protocole inter-drones.
- Boucle de décision — du paquet réseau à l'action.