rts-commander / docs /HARVESTER_LOGIC_EXPLAINED.md
Luigi's picture
deploy(web): full clean snapshot with app code and assets
12d64f8
|
raw
history blame
36.2 kB
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ ๐Ÿ“š HARVESTER LOGIC EXPLAINED - GUIDE COMPLET ๐Ÿ“š โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ“… Date: 3 Octobre 2025
๐ŸŽฎ Game: RTS Web - Red Alert Style
๐Ÿšœ Subject: Harvester, Refinery & Resource System
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐ŸŽฏ PROBLรˆME RAPPORTร‰
"Harvester didn't go collect resource"
Le Harvester ne collecte pas automatiquement les ressources.
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ“‹ SYSTรˆME DE RESSOURCES - VUE D'ENSEMBLE
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CYCLE COMPLET DU HARVESTER โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
1. SPAWN (Crรฉation)
โ””โ”€> Harvester produit depuis HQ (pas Refinery!)
Coรปt: 200 crรฉdits
2. IDLE (Repos)
โ””โ”€> Cherche automatiquement le minerai le plus proche
Variables: gathering=False, ore_target=None
3. SEARCHING (Recherche)
โ””โ”€> find_nearest_ore() trouve ORE ou GEM
Variables: gathering=True, ore_target=Position(x, y)
4. MOVING TO ORE (Dรฉplacement vers minerai)
โ””โ”€> Se dรฉplace vers ore_target
Vitesse: 1.0 tiles/tick
5. HARVESTING (Rรฉcolte)
โ””โ”€> ร€ proximitรฉ du minerai (< TILE_SIZE/2)
ORE: +50 crรฉdits par tile
GEM: +100 crรฉdits par tile
Tile devient GRASS aprรจs rรฉcolte
6. CARGO CHECK (Vรฉrification cargaison)
โ””โ”€> Si cargo >= 180 (90% de 200)
โ†’ Variables: returning=True
7. RETURNING (Retour base)
โ””โ”€> find_nearest_depot() trouve Refinery ou HQ
Se dรฉplace vers le dรฉpรดt
8. DEPOSITING (Dรฉpรดt)
โ””โ”€> ร€ proximitรฉ du dรฉpรดt (< TILE_SIZE*2)
player.credits += unit.cargo
cargo = 0
Variables: returning=False, gathering=False
9. REPEAT (Recommence)
โ””โ”€> Retour ร  l'รฉtape 2 (IDLE)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ”ง CONSTANTES SYSTรˆME
HARVESTER_CAPACITY = 200 # Capacitรฉ max cargo
HARVEST_AMOUNT_PER_ORE = 50 # Crรฉdits par tile ORE
HARVEST_AMOUNT_PER_GEM = 100 # Crรฉdits par tile GEM
TILE_SIZE = 40 # Taille d'une tile en pixels
MAP_WIDTH = 96 # Largeur carte en tiles
MAP_HEIGHT = 72 # Hauteur carte en tiles
Production:
โ”œโ”€ Coรปt: 200 crรฉdits
โ”œโ”€ Bรขtiment requis: HQ (pas Refinery!)
โ”œโ”€ Santรฉ: 150 HP
โ”œโ”€ Vitesse: 1.0
โ”œโ”€ Dรฉgรขts: 0 (sans arme)
โ””โ”€ Portรฉe: 0
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ—๏ธ Bร‚TIMENTS IMPLIQUร‰S
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 1. HQ (Headquarters / Quartier Gรฉnรฉral) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Rรดle: โ”‚
โ”‚ โ€ข PRODUIT les Harvesters (pas le Refinery!) โ”‚
โ”‚ โ€ข Sert de Dร‰Pร”T pour dรฉposer les ressources โ”‚
โ”‚ โ€ข Prรฉsent au dรฉmarrage du jeu โ”‚
โ”‚ โ”‚
โ”‚ Code: โ”‚
โ”‚ PRODUCTION_REQUIREMENTS = { โ”‚
โ”‚ UnitType.HARVESTER: BuildingType.HQ # โ† Important! โ”‚
โ”‚ } โ”‚
โ”‚ โ”‚
โ”‚ Fonction dรฉpรดt: โ”‚
โ”‚ find_nearest_depot() retourne HQ OU Refinery โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ 2. REFINERY (Raffinerie) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Rรดle: โ”‚
โ”‚ โ€ข NE PRODUIT PAS de Harvesters โ”‚
โ”‚ โ€ข Sert de Dร‰Pร”T pour dรฉposer les ressources โ”‚
โ”‚ โ€ข Optionnel (HQ suffit) โ”‚
โ”‚ โ€ข Coรปt construction: 600 crรฉdits โ”‚
โ”‚ โ”‚
โ”‚ Avantages: โ”‚
โ”‚ โ€ข Peut รชtre construit prรจs des champs de minerai โ”‚
โ”‚ โ€ข Rรฉduit le temps de trajet des Harvesters โ”‚
โ”‚ โ€ข Optimise l'รฉconomie โ”‚
โ”‚ โ”‚
โ”‚ Fonction dรฉpรดt: โ”‚
โ”‚ find_nearest_depot() retourne HQ OU Refinery โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐ŸŒ TYPES DE TERRAIN
TerrainType.GRASS ๐ŸŸฉ Herbe (normal, traversable)
TerrainType.ORE ๐ŸŸจ Minerai (50 crรฉdits, devient GRASS aprรจs)
TerrainType.GEM ๐Ÿ’Ž Gemme (100 crรฉdits, devient GRASS aprรจs)
TerrainType.WATER ๐ŸŸฆ Eau (obstacle, non traversable)
Gรฉnรฉration carte (init_map):
โ”œโ”€ 15 patches d'ORE (5x5 tiles chacun, ~70% densitรฉ)
โ”œโ”€ 5 patches de GEM (3x3 tiles chacun, ~50% densitรฉ)
โ””โ”€ 8 corps d'eau (7x7 tiles chacun)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ”„ LOGIQUE HARVESTER - CODE Dร‰TAILLร‰
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ update_harvester(unit: Unit) โ”‚
โ”‚ Appelรฉ chaque tick (50ms) pour chaque Harvester โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
def update_harvester(self, unit: Unit):
"""RED ALERT: Harvester AI - auto-collect resources!"""
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ร‰TAT 1: RETURNING (Retour au dรฉpรดt avec cargaison)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
if unit.returning:
# Trouver le dรฉpรดt le plus proche (Refinery ou HQ)
depot = self.find_nearest_depot(unit.player_id, unit.position)
if depot:
distance = unit.position.distance_to(depot.position)
# Arrivรฉ au dรฉpรดt?
if distance < TILE_SIZE * 2: # < 80 pixels
# โœ… Dร‰POSER LA CARGAISON
self.game_state.players[unit.player_id].credits += unit.cargo
unit.cargo = 0
unit.returning = False
unit.gathering = False
unit.ore_target = None
# โ†’ Retour ร  l'รฉtat IDLE (cherchera du minerai)
else:
# ๐Ÿšถ SE Dร‰PLACER VERS LE Dร‰Pร”T
unit.target = Position(depot.position.x, depot.position.y)
else:
# โŒ PAS DE Dร‰Pร”T (HQ dรฉtruit?)
unit.returning = False
return # โ† Sortie de la fonction
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ร‰TAT 2: AT ORE PATCH (Au minerai, en train de rรฉcolter)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
if unit.ore_target:
distance = ((unit.position.x - unit.ore_target.x) ** 2 +
(unit.position.y - unit.ore_target.y) ** 2) ** 0.5
# Arrivรฉ au minerai?
if distance < TILE_SIZE / 2: # < 20 pixels
# Convertir position en coordonnรฉes de tile
tile_x = int(unit.ore_target.x / TILE_SIZE)
tile_y = int(unit.ore_target.y / TILE_SIZE)
# Vรฉrifier limites carte
if (0 <= tile_x < MAP_WIDTH and 0 <= tile_y < MAP_HEIGHT):
terrain = self.game_state.terrain[tile_y][tile_x]
# โ›๏ธ Rร‰COLTER LE MINERAI
if terrain == TerrainType.ORE:
unit.cargo = min(HARVESTER_CAPACITY,
unit.cargo + HARVEST_AMOUNT_PER_ORE)
# Tile devient herbe
self.game_state.terrain[tile_y][tile_x] = TerrainType.GRASS
elif terrain == TerrainType.GEM:
unit.cargo = min(HARVESTER_CAPACITY,
unit.cargo + HARVEST_AMOUNT_PER_GEM)
# Tile devient herbe
self.game_state.terrain[tile_y][tile_x] = TerrainType.GRASS
# Rรฉinitialiser รฉtat
unit.ore_target = None
unit.gathering = False
# ๐Ÿ“ฆ CARGAISON PLEINE?
if unit.cargo >= HARVESTER_CAPACITY * 0.9: # โ‰ฅ 180
unit.returning = True # โ†’ Retour au dรฉpรดt
unit.target = None
else:
# ๐Ÿšถ SE Dร‰PLACER VERS LE MINERAI
unit.target = unit.ore_target
return # โ† Sortie de la fonction
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ร‰TAT 3: IDLE (Chercher du minerai)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
if not unit.gathering and not unit.target:
# ๐Ÿ” CHERCHER LE MINERAI LE PLUS PROCHE
nearest_ore = self.find_nearest_ore(unit.position)
if nearest_ore:
unit.ore_target = nearest_ore
unit.gathering = True
unit.target = nearest_ore
# โ†’ Passera ร  l'รฉtat AT ORE PATCH au prochain tick
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ” FONCTIONS AUXILIAIRES
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ find_nearest_depot(player_id, position) โ†’ Building | None โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Trouve le dรฉpรดt le plus proche (Refinery OU HQ) du joueur โ”‚
โ”‚ โ”‚
โ”‚ Logique: โ”‚
โ”‚ 1. Parcourt tous les bรขtiments โ”‚
โ”‚ 2. Filtre par player_id โ”‚
โ”‚ 3. Filtre par type: REFINERY ou HQ โ”‚
โ”‚ 4. Calcule distance euclidienne โ”‚
โ”‚ 5. Retourne le plus proche โ”‚
โ”‚ โ”‚
โ”‚ Retour: โ”‚
โ”‚ โ€ข Building si trouvรฉ โ”‚
โ”‚ โ€ข None si aucun dรฉpรดt (HQ dรฉtruit et pas de Refinery) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ find_nearest_ore(position) โ†’ Position | None โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Trouve le minerai (ORE ou GEM) le plus proche โ”‚
โ”‚ โ”‚
โ”‚ Logique: โ”‚
โ”‚ 1. Parcourt toutes les tiles de la carte (96ร—72 = 6,912 tiles) โ”‚
โ”‚ 2. Filtre par terrain: ORE ou GEM โ”‚
โ”‚ 3. Calcule position centre tile: (x*40+20, y*40+20) โ”‚
โ”‚ 4. Calcule distance euclidienne โ”‚
โ”‚ 5. Retourne position du plus proche โ”‚
โ”‚ โ”‚
โ”‚ Retour: โ”‚
โ”‚ โ€ข Position(x, y) si minerai trouvรฉ โ”‚
โ”‚ โ€ข None si tout le minerai รฉpuisรฉ โ”‚
โ”‚ โ”‚
โ”‚ Performance: โ”‚
โ”‚ โ€ข O(nยฒ) oรน n = taille carte โ”‚
โ”‚ โ€ข Appelรฉ une fois quand Harvester devient idle โ”‚
โ”‚ โ€ข Pas de cache (minerai change dynamiquement) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ› PROBLรˆMES POSSIBLES & SOLUTIONS
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PROBLรˆME 1: Harvester ne bouge pas du tout โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Causes possibles: โ”‚
โ”‚ โŒ Harvester pas produit depuis HQ โ”‚
โ”‚ โŒ update_harvester() pas appelรฉ dans game loop โ”‚
โ”‚ โŒ Tout le minerai dรฉjร  รฉpuisรฉ โ”‚
โ”‚ โŒ Variables Unit pas initialisรฉes (gathering, returning, etc.) โ”‚
โ”‚ โ”‚
โ”‚ Solutions: โ”‚
โ”‚ โœ… Vรฉrifier: UnitType.HARVESTER: BuildingType.HQ โ”‚
โ”‚ โœ… Vรฉrifier: if unit.type == UnitType.HARVESTER: โ”‚
โ”‚ โœ… Vรฉrifier terrain: print(self.game_state.terrain) โ”‚
โ”‚ โœ… Vรฉrifier init Unit: cargo=0, gathering=False, returning=False โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PROBLรˆME 2: Harvester va au minerai mais ne rรฉcolte pas โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Causes possibles: โ”‚
โ”‚ โŒ Distance check trop strict (< TILE_SIZE/2) โ”‚
โ”‚ โŒ Coordonnรฉes tile mal calculรฉes (int conversion) โ”‚
โ”‚ โŒ Terrain dรฉjร  GRASS (autre Harvester a pris) โ”‚
โ”‚ โŒ Limites carte mal vรฉrifiรฉes โ”‚
โ”‚ โ”‚
โ”‚ Solutions: โ”‚
โ”‚ โœ… Augmenter distance: if distance < TILE_SIZE โ”‚
โ”‚ โœ… Debug: print(f"At ore: {tile_x},{tile_y} = {terrain}") โ”‚
โ”‚ โœ… Vรฉrifier race condition entre Harvesters โ”‚
โ”‚ โœ… Vรฉrifier: 0 <= tile_x < MAP_WIDTH โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PROBLรˆME 3: Harvester ne retourne pas au dรฉpรดt โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Causes possibles: โ”‚
โ”‚ โŒ Pas de Refinery ni HQ (dรฉtruit?) โ”‚
โ”‚ โŒ Cargo pas incrรฉmentรฉ (reste ร  0) โ”‚
โ”‚ โŒ Check cargo >= 180 jamais atteint โ”‚
โ”‚ โŒ Variable returning pas setรฉe โ”‚
โ”‚ โ”‚
โ”‚ Solutions: โ”‚
โ”‚ โœ… Vรฉrifier HQ existe: buildings[id].type == BuildingType.HQ โ”‚
โ”‚ โœ… Debug: print(f"Cargo: {unit.cargo}/200") โ”‚
โ”‚ โœ… Test manuel: unit.returning = True โ”‚
โ”‚ โœ… Construire Refinery prรจs du minerai โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PROBLรˆME 4: Harvester au dรฉpรดt mais ne dรฉpose pas โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Causes possibles: โ”‚
โ”‚ โŒ Distance check trop strict (< TILE_SIZE*2) โ”‚
โ”‚ โŒ Position dรฉpรดt mal calculรฉe โ”‚
โ”‚ โŒ Credits pas incrรฉmentรฉs cรดtรฉ player โ”‚
โ”‚ โŒ Variables pas rรฉinitialisรฉes aprรจs dรฉpรดt โ”‚
โ”‚ โ”‚
โ”‚ Solutions: โ”‚
โ”‚ โœ… Augmenter distance: if distance < TILE_SIZE*3 โ”‚
โ”‚ โœ… Debug: print(f"At depot: distance={distance}") โ”‚
โ”‚ โœ… Vรฉrifier: player.credits += unit.cargo โ”‚
โ”‚ โœ… Vรฉrifier: cargo=0, returning=False aprรจs dรฉpรดt โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PROBLรˆME 5: Frontend ne montre pas le Harvester โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Causes possibles: โ”‚
โ”‚ โŒ WebSocket state pas broadcast โ”‚
โ”‚ โŒ game.js ne render pas type "harvester" โ”‚
โ”‚ โŒ Harvester hors viewport (carte 96ร—72) โ”‚
โ”‚ โŒ Cache cรดtรฉ client โ”‚
โ”‚ โ”‚
โ”‚ Solutions: โ”‚
โ”‚ โœ… Vรฉrifier broadcast: state_dict['units'] โ”‚
โ”‚ โœ… Vรฉrifier game.js: case 'harvester': ... โ”‚
โ”‚ โœ… Tester via curl /health (units count) โ”‚
โ”‚ โœ… F5 refresh browser โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿงช TESTS & DEBUGGING
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TEST 1: Vรฉrifier crรฉation Harvester โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ curl http://localhost:7860/health โ”‚
โ”‚ โ”‚
โ”‚ Rรฉsultat attendu: โ”‚
โ”‚ { โ”‚
โ”‚ "status": "healthy", โ”‚
โ”‚ "units": 8, โ† Devrait augmenter aprรจs production Harvester โ”‚
โ”‚ ... โ”‚
โ”‚ } โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TEST 2: Vรฉrifier minerai sur la carte โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Ajouter dans app.py: โ”‚
โ”‚ โ”‚
โ”‚ ore_count = sum(1 for row in self.terrain โ”‚
โ”‚ for tile in row โ”‚
โ”‚ if tile in [TerrainType.ORE, TerrainType.GEM]) โ”‚
โ”‚ print(f"Ore tiles remaining: {ore_count}") โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TEST 3: Debug รฉtat Harvester โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Ajouter dans update_harvester(): โ”‚
โ”‚ โ”‚
โ”‚ print(f"Harvester {unit.id[:8]}:") โ”‚
โ”‚ print(f" Position: ({unit.position.x:.0f}, {unit.position.y:.0f}")โ”‚
โ”‚ print(f" Cargo: {unit.cargo}/200") โ”‚
โ”‚ print(f" Gathering: {unit.gathering}") โ”‚
โ”‚ print(f" Returning: {unit.returning}") โ”‚
โ”‚ print(f" Ore target: {unit.ore_target}") โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TEST 4: Vรฉrifier dรฉpรดts disponibles โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Ajouter dans find_nearest_depot(): โ”‚
โ”‚ โ”‚
โ”‚ depots = [b for b in self.game_state.buildings.values() โ”‚
โ”‚ if b.player_id == player_id โ”‚
โ”‚ and b.type in [BuildingType.REFINERY, BuildingType.HQ]] โ”‚
โ”‚ print(f"Available depots for player {player_id}: {len(depots)}") โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
โœ… CHECKLIST FONCTIONNEMENT HARVESTER
Pour que le Harvester fonctionne correctement, vรฉrifier:
โ–ก 1. PRODUCTION
โœ“ HQ existe et appartient au joueur
โœ“ PRODUCTION_REQUIREMENTS: HARVESTER โ†’ HQ
โœ“ Player a โ‰ฅ200 crรฉdits
โœ“ Commande WebSocket "build_unit" avec type="harvester"
โ–ก 2. CRร‰ATION UNITร‰
โœ“ create_unit(UnitType.HARVESTER, player_id, position)
โœ“ Unit.cargo = 0
โœ“ Unit.gathering = False
โœ“ Unit.returning = False
โœ“ Unit.ore_target = None
โ–ก 3. GAME LOOP
โœ“ update_game_state() appelle update_harvester(unit)
โœ“ Tick rate: 50ms (20 ticks/sec)
โœ“ Broadcast state inclut units
โ–ก 4. TERRAIN
โœ“ init_map() gรฉnรจre ORE et GEM
โœ“ โ‰ฅ15 patches d'ORE sur la carte
โœ“ Tiles accessibles (pas entourรฉes d'eau)
โ–ก 5. MOUVEMENT
โœ“ unit.target settรฉ correctement
โœ“ unit.speed = 1.0
โœ“ Position mise ร  jour chaque tick
โœ“ Distance calculรฉe correctement
โ–ก 6. Rร‰COLTE
โœ“ Distance < TILE_SIZE/2 pour rรฉcolter
โœ“ tile_x, tile_y calculรฉs correctement
โœ“ Terrain type vรฉrifiรฉ (ORE ou GEM)
โœ“ Cargo incrรฉmentรฉ
โœ“ Tile devient GRASS
โ–ก 7. RETOUR Dร‰Pร”T
โœ“ cargo >= 180 โ†’ returning = True
โœ“ find_nearest_depot() trouve HQ ou Refinery
โœ“ Distance < TILE_SIZE*2 pour dรฉposer
โœ“ player.credits += cargo
โœ“ cargo reset ร  0
โ–ก 8. FRONTEND
โœ“ WebSocket connectรฉ
โœ“ game.js render type "harvester"
โœ“ Couleur/sprite dรฉfini
โœ“ Broadcast state reรงu
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ“Š Mร‰TRIQUES PERFORMANCE
Harvester optimal (temps pour 1 cycle):
โ”œโ”€ Recherche minerai: ~1 sec (instant si proche)
โ”œโ”€ Trajet vers minerai: Variable (dรฉpend distance)
โ”œโ”€ Rรฉcolte 4 tiles: ~4 ticks = 0.2 sec
โ”œโ”€ Trajet vers dรฉpรดt: Variable (dรฉpend distance)
โ”œโ”€ Dรฉpรดt: ~1 tick = 0.05 sec
โ””โ”€ Total: ~10-30 sec par cycle
Revenus par Harvester:
โ”œโ”€ Cargo max: 200 crรฉdits
โ”œโ”€ ORE: 4 tiles = 200 crรฉdits
โ”œโ”€ GEM: 2 tiles = 200 crรฉdits
โ””โ”€ Cycles/min: 2-6 (selon distance)
ROI (Return on Investment):
โ”œโ”€ Coรปt: 200 crรฉdits
โ”œโ”€ Premier cycle: Break-even
โ”œโ”€ Profit net: Tous cycles suivants
โ””โ”€ Recommandรฉ: 2-3 Harvesters minimum
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ“– EXEMPLE SCร‰NARIO COMPLET
Tick 0: Player construit HQ
Tick 100: Player a 5000 crรฉdits
Tick 101: Player envoie commande: build_unit("harvester")
Tick 102: Check: HQ existe? โœ… Credits โ‰ฅ200? โœ…
Tick 103: Credits: 5000 - 200 = 4800
Tick 104: Harvester crรฉรฉ ร  position (HQ.x+80, HQ.y+80)
Tick 105: update_harvester() appelรฉ
ร‰tat: IDLE (gathering=False, ore_target=None)
Tick 106: find_nearest_ore() cherche minerai
โ†’ Trouve ORE ร  (1200, 800)
ร‰tat: ore_target=(1200,800), gathering=True
Tick 107-200: Se dรฉplace vers (1200, 800)
Vitesse: 1.0 pixel/tick
Tick 201: Arrivรฉ au minerai (distance < 20)
tile_x=30, tile_y=20
terrain[20][30] = ORE
Tick 202: Rรฉcolte: cargo += 50 โ†’ cargo=50
terrain[20][30] = GRASS
ร‰tat: ore_target=None, gathering=False
Tick 203: Cherche nouveau minerai proche
โ†’ Trouve ORE adjacent ร  (1240, 800)
Tick 204-220: Se dรฉplace et rรฉcolte 3 autres tiles ORE
cargo: 50 โ†’ 100 โ†’ 150 โ†’ 200
Tick 221: cargo=200 โ‰ฅ 180 โ†’ returning=True
Tick 222: find_nearest_depot() โ†’ Trouve HQ ร  (200, 200)
Tick 223-350: Se dรฉplace vers HQ
Tick 351: Arrivรฉ au HQ (distance < 80)
Tick 352: Dรฉpรดt: player.credits += 200 โ†’ 5000
cargo=0, returning=False
Tick 353: ร‰tat: IDLE โ†’ Cherche nouveau minerai
Tick 354: Cycle recommence...
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Date: 3 Octobre 2025
Status: โœ… DOCUMENTATION COMPLรˆTE
"The Harvester must flow." ๐Ÿšœ๐Ÿ’ฐ