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: (x40+20, y40+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_SIZE2) โ”‚ โ”‚ โŒ 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_SIZE3 โ”‚ โ”‚ โœ… 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." ๐Ÿšœ๐Ÿ’ฐ