diff --git a/ai_decision.py b/ai_decision.py index 38f26d1..6a0e9b7 100644 --- a/ai_decision.py +++ b/ai_decision.py @@ -1,202 +1,102 @@ - - -import random - -from typing import List, Dict - - - -class AIDecision: - - def __init__(self, difficulty: str = "medium"): - - self.difficulty = difficulty - - self.last_decision_time = 0 - - self.decision_cooldown = self._get_decision_cooldown() - - - - def decide(self, snapshot: Dict, dt: float) -> List[Dict]: - - self.last_decision_time += dt - - if self.last_decision_time < self.decision_cooldown: - - return [] - - - - commands = [] - - commands.extend(self.plan_expand(snapshot)) - - commands.extend(self.plan_attack(snapshot)) - - commands.extend(self.plan_build(snapshot)) - - - - self.last_decision_time = 0 - - return commands - - - - def plan_expand(self, snapshot: Dict) -> List[Dict]: - - commands = [] - - resources = snapshot.get('resources', {}) - - minerals = resources.get('minerals', 0) - - - - if minerals >= 400 and random.random() < 0.3: - - commands.append({ - - 'type': 'create_entity', - - 'entity_type': 'supply_depot', - - 'position': self._find_expansion_position(snapshot) - - }) - - - - return commands - - - - def plan_attack(self, snapshot: Dict) -> List[Dict]: - - commands = [] - - entities = snapshot.get('entities', []) - - ai_units = [e for e in entities if e.get('owner') == 'ai'] - - player_units = [e for e in entities if e.get('owner') == 'player'] - - - - if len(ai_units) >= 5 and player_units and random.random() < 0.4: - - target_unit = random.choice(player_units) - - for unit in ai_units: - - if unit.get('type') == 'unit' and unit.get('state') == 'idle': - - commands.append({ - - 'type': 'attack', - - 'entity_id': unit['id'], - - 'target_id': target_unit['id'] - - }) - - - - return commands - - - - def plan_build(self, snapshot: Dict) -> List[Dict]: - - commands = [] - - resources = snapshot.get('resources', {}) - - minerals = resources.get('minerals', 0) - - entities = snapshot.get('entities', []) - - ai_units = [e for e in entities if e.get('owner') == 'ai'] - - - - if minerals >= 150 and len(ai_units) < 8 and random.random() < 0.5: - - commands.append({ - - 'type': 'create_entity', - - 'entity_type': 'worker', - - 'position': self._find_build_position(snapshot) - - }) - - - - if minerals >= 300 and random.random() < 0.2: - - commands.append({ - - 'type': 'create_entity', - - 'entity_type': 'barracks', - - 'position': self._find_build_position(snapshot) - - }) - - - - return commands - - - - def _find_expansion_position(self, snapshot: Dict) -> tuple: - - base_x = snapshot.get('ai_base_x', 100) - - base_y = snapshot.get('ai_base_y', 100) - - offset_x = random.randint(-200, 200) - - offset_y = random.randint(-200, 200) - - return (base_x + offset_x, base_y + offset_y) - - - - def _find_build_position(self, snapshot: Dict) -> tuple: - - base_x = snapshot.get('ai_base_x', 100) - - base_y = snapshot.get('ai_base_y', 100) - - offset_x = random.randint(-50, 50) - - offset_y = random.randint(-50, 50) - - return (base_x + offset_x, base_y + offset_y) - - - - def _get_decision_cooldown(self) -> float: - - if self.difficulty == "easy": - - return 3.0 - - elif self.difficulty == "medium": - - return 2.0 - - elif self.difficulty == "hard": - - return 1.0 - - else: - - return 2.0 - + +import random +from typing import List, Dict + + +class AIDecision: + def __init__(self, difficulty: str = "medium"): + self.difficulty = difficulty + self.last_decision_time = 0 + self.decision_cooldown = self._get_decision_cooldown() + + def decide(self, game_state, dt: float) -> List[Dict]: + self.last_decision_time += dt + if self.last_decision_time < self.decision_cooldown: + return [] + + commands = [] + commands.extend(self.plan_expand(game_state)) + commands.extend(self.plan_attack(game_state)) + commands.extend(self.plan_build(game_state)) + + self.last_decision_time = 0 + return commands + + def plan_expand(self, game_state) -> List[Dict]: + commands = [] + resources = getattr(game_state, 'resources', {}) + minerals = getattr(resources, 'minerals', 0) if hasattr(resources, 'minerals') else 0 + + if minerals >= 400 and random.random() < 0.3: + commands.append({ + 'type': 'create_entity', + 'entity_type': 'supply_depot', + 'position': self._find_expansion_position(game_state) + }) + + return commands + + def plan_attack(self, game_state) -> List[Dict]: + commands = [] + entities = getattr(game_state, 'entities', []) + ai_units = [e for e in entities if getattr(e, 'owner', None) == 'ai'] + player_units = [e for e in entities if getattr(e, 'owner', None) == 'player'] + + if len(ai_units) >= 5 and player_units and random.random() < 0.4: + target_unit = random.choice(player_units) + for unit in ai_units: + if getattr(unit, 'type', None) == 'unit' and getattr(unit, 'state', None) == 'idle': + commands.append({ + 'type': 'attack', + 'entity_id': getattr(unit, 'id', None), + 'target_id': getattr(target_unit, 'id', None) + }) + + return commands + + def plan_build(self, game_state) -> List[Dict]: + commands = [] + resources = getattr(game_state, 'resources', {}) + minerals = getattr(resources, 'minerals', 0) if hasattr(resources, 'minerals') else 0 + entities = getattr(game_state, 'entities', []) + ai_units = [e for e in entities if getattr(e, 'owner', None) == 'ai'] + + if minerals >= 150 and len(ai_units) < 8 and random.random() < 0.5: + commands.append({ + 'type': 'create_entity', + 'entity_type': 'worker', + 'position': self._find_build_position(game_state) + }) + + if minerals >= 300 and random.random() < 0.2: + commands.append({ + 'type': 'create_entity', + 'entity_type': 'barracks', + 'position': self._find_build_position(game_state) + }) + + return commands + + def _find_expansion_position(self, game_state) -> tuple: + base_x = getattr(game_state, 'ai_base_x', 100) + base_y = getattr(game_state, 'ai_base_y', 100) + offset_x = random.randint(-200, 200) + offset_y = random.randint(-200, 200) + return (base_x + offset_x, base_y + offset_y) + + def _find_build_position(self, game_state) -> tuple: + base_x = getattr(game_state, 'ai_base_x', 100) + base_y = getattr(game_state, 'ai_base_y', 100) + offset_x = random.randint(-50, 50) + offset_y = random.randint(-50, 50) + return (base_x + offset_x, base_y + offset_y) + + def _get_decision_cooldown(self) -> float: + if self.difficulty == "easy": + return 3.0 + elif self.difficulty == "medium": + return 2.0 + elif self.difficulty == "hard": + return 1.0 + else: + return 2.0 diff --git a/input_commands.py b/input_commands.py index 43aea9e..b3a509f 100644 --- a/input_commands.py +++ b/input_commands.py @@ -1,92 +1,48 @@ - - -from typing import List, Dict, Tuple - - - -class InputCommands: - - def __init__(self): - - pass - - - - def generate_commands(self, events: List, snapshot: Dict) -> List[Dict]: - - commands = [] - - camera = snapshot.get('camera', {}) - - - - for event in events: - - command = self._process_event(event, camera) - - if command: - - commands.append(command) - - - - return commands - - - - def _process_event(self, event, camera: Dict) -> Dict: - - if event.type == event.MOUSEBUTTONDOWN: - - if event.button == 1: # Left click - - world_x, world_y = self.screen_to_world(event.pos[0], event.pos[1], camera) - - return {'type': 'select', 'world_pos': (world_x, world_y)} - - elif event.button == 3: # Right click - - world_x, world_y = self.screen_to_world(event.pos[0], event.pos[1], camera) - - return {'type': 'move', 'world_pos': (world_x, world_y)} - - - - elif event.type == event.KEYDOWN: - - if event.key == event.K_b: - - return {'type': 'build', 'building_type': 'barracks'} - - elif event.key == event.K_s: - - return {'type': 'build', 'building_type': 'supply_depot'} - - elif event.key == event.K_g: - - return {'type': 'gather'} - - - - return None - - - - def screen_to_world(self, x: int, y: int, camera: Dict) -> Tuple[float, float]: - - camera_x = camera.get('x', 0) - - camera_y = camera.get('y', 0) - - zoom = camera.get('zoom', 1.0) - - - - world_x = (x / zoom) + camera_x - - world_y = (y / zoom) + camera_y - - - - return world_x, world_y - + +from typing import List, Dict, Tuple +import pygame + + +class InputCommands: + def __init__(self): + pass + + def generate_commands(self, events: List, game_state) -> List[Dict]: + commands = [] + camera = getattr(game_state, 'camera', {}) + + for event in events: + command = self._process_event(event, camera) + if command: + commands.append(command) + + return commands + + def _process_event(self, event, camera: Dict) -> Dict: + if event.type == pygame.MOUSEBUTTONDOWN: + if event.button == 1: # Left click + world_x, world_y = self.screen_to_world(event.pos[0], event.pos[1], camera) + return {'type': 'select', 'world_pos': (world_x, world_y)} + elif event.button == 3: # Right click + world_x, world_y = self.screen_to_world(event.pos[0], event.pos[1], camera) + return {'type': 'move', 'world_pos': (world_x, world_y)} + + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_b: + return {'type': 'build', 'building_type': 'barracks'} + elif event.key == pygame.K_s: + return {'type': 'build', 'building_type': 'supply_depot'} + elif event.key == pygame.K_g: + return {'type': 'gather'} + + return None + + def screen_to_world(self, x: int, y: int, camera: Dict) -> Tuple[float, float]: + camera_x = camera.get('x', 0) + camera_y = camera.get('y', 0) + zoom = camera.get('zoom', 1.0) + + world_x = (x / zoom) + camera_x + world_y = (y / zoom) + camera_y + + return world_x, world_y