Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Test du comportement IA du Harvester | |
| Vérifie que le Harvester cherche automatiquement les ressources après spawn | |
| """ | |
| import sys | |
| import json | |
| import time | |
| import requests | |
| API_URL = "http://localhost:7860" | |
| def test_harvester_auto_collect(): | |
| """Test que le Harvester commence automatiquement à collecter""" | |
| print("\n" + "="*80) | |
| print("🧪 TEST: Harvester Auto-Collection AI") | |
| print("="*80) | |
| # 1. Get initial state | |
| print("\n📊 1. État initial...") | |
| resp = requests.get(f"{API_URL}/health") | |
| if resp.status_code != 200: | |
| print("❌ Serveur non accessible") | |
| return False | |
| data = resp.json() | |
| initial_units = len(data.get('units', [])) | |
| initial_credits_p0 = data.get('players', [{}])[0].get('credits', 0) | |
| print(f" Units initiaux: {initial_units}") | |
| print(f" Crédits Joueur 0: {initial_credits_p0}") | |
| # 2. Build a Harvester from HQ | |
| print("\n🏗️ 2. Construction d'un Harvester depuis HQ...") | |
| # Assuming player 0 has HQ at position (5*40, 5*40) = (200, 200) | |
| build_resp = requests.post(f"{API_URL}/ws", json={ | |
| "action": "build_unit", | |
| "player_id": 0, | |
| "unit_type": "harvester" | |
| }) | |
| # Wait for production (assume instant for test) | |
| time.sleep(2) | |
| # 3. Check Harvester created | |
| print("\n🔍 3. Vérification du Harvester créé...") | |
| resp = requests.get(f"{API_URL}/health") | |
| data = resp.json() | |
| current_units = len(data.get('units', [])) | |
| harvesters = [u for u in data.get('units', []) if u.get('type') == 'harvester'] | |
| print(f" Units actuels: {current_units}") | |
| print(f" Harvesters trouvés: {len(harvesters)}") | |
| if len(harvesters) == 0: | |
| print("❌ Aucun Harvester trouvé") | |
| print(" Vérifiez que le HQ peut produire des Harvesters") | |
| print(" Vérifiez que vous avez ≥200 crédits") | |
| return False | |
| # 4. Monitor Harvester behavior for 10 seconds | |
| print("\n👀 4. Surveillance du comportement (10 secondes)...") | |
| harvester = harvesters[0] | |
| harvester_id = harvester.get('id') | |
| initial_pos = harvester.get('position', {}) | |
| print(f" Harvester ID: {harvester_id}") | |
| print(f" Position initiale: ({initial_pos.get('x', 0):.1f}, {initial_pos.get('y', 0):.1f})") | |
| print(f" État: gathering={harvester.get('gathering')}, returning={harvester.get('returning')}, cargo={harvester.get('cargo')}") | |
| movements = [] | |
| for i in range(10): | |
| time.sleep(1) | |
| resp = requests.get(f"{API_URL}/health") | |
| data = resp.json() | |
| harvesters = [u for u in data.get('units', []) if u.get('id') == harvester_id] | |
| if not harvesters: | |
| print(f"\n ❌ Tick {i+1}: Harvester disparu!") | |
| return False | |
| h = harvesters[0] | |
| pos = h.get('position', {}) | |
| target = h.get('target') | |
| ore_target = h.get('ore_target') | |
| gathering = h.get('gathering') | |
| returning = h.get('returning') | |
| cargo = h.get('cargo') | |
| # Calculate distance moved | |
| dist = ((pos.get('x', 0) - initial_pos.get('x', 0))**2 + | |
| (pos.get('y', 0) - initial_pos.get('y', 0))**2)**0.5 | |
| movements.append({ | |
| 'tick': i+1, | |
| 'position': pos, | |
| 'distance': dist, | |
| 'target': target, | |
| 'ore_target': ore_target, | |
| 'gathering': gathering, | |
| 'returning': returning, | |
| 'cargo': cargo | |
| }) | |
| status = f" 📍 Tick {i+1}: pos=({pos.get('x', 0):.1f},{pos.get('y', 0):.1f}) dist={dist:.1f}px" | |
| if gathering: | |
| status += " 🔍GATHERING" | |
| if ore_target: | |
| status += f" 🎯ORE_TARGET=({ore_target.get('x', 0):.0f},{ore_target.get('y', 0):.0f})" | |
| if returning: | |
| status += " 🔙RETURNING" | |
| if cargo > 0: | |
| status += f" 💰cargo={cargo}" | |
| if target: | |
| status += f" ➡️target=({target.get('x', 0):.0f},{target.get('y', 0):.0f})" | |
| print(status) | |
| # 5. Analysis | |
| print("\n📊 5. Analyse du comportement...") | |
| # Check if moved | |
| final_dist = movements[-1]['distance'] | |
| if final_dist < 10: | |
| print(f" ❌ ÉCHEC: Harvester n'a pas bougé (distance={final_dist:.1f}px)") | |
| print(" 🐛 Problème: L'IA ne démarre pas automatiquement") | |
| return False | |
| else: | |
| print(f" ✅ Harvester a bougé: {final_dist:.1f}px") | |
| # Check if gathering flag set | |
| gathering_ticks = sum(1 for m in movements if m['gathering']) | |
| if gathering_ticks > 0: | |
| print(f" ✅ Mode GATHERING activé ({gathering_ticks}/10 ticks)") | |
| else: | |
| print(f" ⚠️ Mode GATHERING jamais activé") | |
| # Check if ore target found | |
| ore_target_ticks = sum(1 for m in movements if m['ore_target']) | |
| if ore_target_ticks > 0: | |
| print(f" ✅ ORE_TARGET trouvé ({ore_target_ticks}/10 ticks)") | |
| else: | |
| print(f" ❌ ORE_TARGET jamais trouvé") | |
| print(" 🐛 Problème: find_nearest_ore() ne trouve rien ou n'est pas appelé") | |
| return False | |
| # Check if moving toward target | |
| target_ticks = sum(1 for m in movements if m['target']) | |
| if target_ticks > 0: | |
| print(f" ✅ TARGET assigné ({target_ticks}/10 ticks)") | |
| else: | |
| print(f" ⚠️ TARGET jamais assigné") | |
| # Success criteria: moved AND found ore target | |
| if final_dist > 10 and ore_target_ticks > 0: | |
| print("\n✅ TEST RÉUSSI: Harvester cherche automatiquement les ressources!") | |
| return True | |
| else: | |
| print("\n❌ TEST ÉCHOUÉ: Harvester ne fonctionne pas correctement") | |
| return False | |
| def show_terrain_info(): | |
| """Affiche les informations du terrain""" | |
| print("\n" + "="*80) | |
| print("🌍 TERRAIN: Vérification des ressources disponibles") | |
| print("="*80) | |
| resp = requests.get(f"{API_URL}/health") | |
| if resp.status_code != 200: | |
| print("❌ Serveur non accessible") | |
| return | |
| data = resp.json() | |
| terrain = data.get('terrain', []) | |
| if not terrain: | |
| print("❌ Pas de données terrain") | |
| return | |
| # Count terrain types | |
| ore_count = 0 | |
| gem_count = 0 | |
| water_count = 0 | |
| grass_count = 0 | |
| ore_positions = [] | |
| gem_positions = [] | |
| for y, row in enumerate(terrain): | |
| for x, cell in enumerate(row): | |
| if cell == 'ore': | |
| ore_count += 1 | |
| ore_positions.append((x, y)) | |
| elif cell == 'gem': | |
| gem_count += 1 | |
| gem_positions.append((x, y)) | |
| elif cell == 'water': | |
| water_count += 1 | |
| elif cell == 'grass': | |
| grass_count += 1 | |
| print(f"\n📊 Statistiques terrain:") | |
| print(f" 🟩 GRASS: {grass_count} tiles") | |
| print(f" 🟨 ORE: {ore_count} tiles") | |
| print(f" 💎 GEM: {gem_count} tiles") | |
| print(f" 🟦 WATER: {water_count} tiles") | |
| print(f" 📏 Total: {len(terrain) * len(terrain[0])} tiles") | |
| if ore_count + gem_count == 0: | |
| print("\n❌ PROBLÈME CRITIQUE: Aucune ressource sur la carte!") | |
| print(" Le Harvester ne peut rien collecter.") | |
| return | |
| print(f"\n✅ {ore_count + gem_count} ressources disponibles") | |
| # Show first 5 ore positions | |
| if ore_positions: | |
| print(f"\n🟨 Premiers patches ORE (max 5):") | |
| for i, (x, y) in enumerate(ore_positions[:5]): | |
| px = x * 40 + 20 | |
| py = y * 40 + 20 | |
| print(f" {i+1}. Tile ({x},{y}) → Position ({px},{py})px") | |
| if gem_positions: | |
| print(f"\n💎 Premiers patches GEM (max 5):") | |
| for i, (x, y) in enumerate(gem_positions[:5]): | |
| px = x * 40 + 20 | |
| py = y * 40 + 20 | |
| print(f" {i+1}. Tile ({x},{y}) → Position ({px},{py})px") | |
| if __name__ == "__main__": | |
| print("\n" + "="*80) | |
| print("🚜 HARVESTER AI TEST SUITE") | |
| print("="*80) | |
| print("\n⚠️ Assurez-vous que le serveur tourne sur http://localhost:7860") | |
| print(" (docker run ou python web/app.py)") | |
| input("\nAppuyez sur Entrée pour continuer...") | |
| # First check terrain | |
| show_terrain_info() | |
| # Then test Harvester AI | |
| print("\n") | |
| input("Appuyez sur Entrée pour lancer le test Harvester...") | |
| success = test_harvester_auto_collect() | |
| print("\n" + "="*80) | |
| if success: | |
| print("✅ TOUS LES TESTS RÉUSSIS") | |
| print("="*80) | |
| sys.exit(0) | |
| else: | |
| print("❌ TESTS ÉCHOUÉS") | |
| print("="*80) | |
| sys.exit(1) | |