from typing import List, Dict, Tuple import math class EntityBehavior: def __init__(self): pass def process_behaviors(self, state, dt: float) -> List[Dict]: actions = [] if not hasattr(state, 'entities'): return actions for entity in state.entities: if entity.get('type') == 'unit': entity_actions = self._process_unit_behavior(state, entity, dt) actions.extend(entity_actions) elif entity.get('type') == 'building': entity_actions = self._process_building_behavior(state, entity, dt) actions.extend(entity_actions) return actions def _process_unit_behavior(self, state, entity: Dict, dt: float) -> List[Dict]: actions = [] current_state = entity.get('state', 'idle') if current_state == 'moving': if self._has_reached_target(entity): actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'}) else: self._continue_movement(entity, dt) elif current_state == 'attacking': target_id = entity.get('target_id') target = self._find_entity_by_id(state, target_id) if not target or target.get('health', 0) <= 0: actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'}) else: if self._is_in_attack_range(entity, target): actions.append({'type': 'deal_damage', 'attacker_id': entity['id'], 'target_id': target_id, 'damage': entity.get('attack_power', 10)}) else: entity['target_x'] = target['x'] entity['target_y'] = target['y'] actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'moving'}) elif current_state == 'gathering': target_id = entity.get('target_id') target = self._find_entity_by_id(state, target_id) if not target or target.get('type') != 'resource': actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'idle'}) else: if self._is_in_gather_range(entity, target): gather_rate = entity.get('gather_rate', 5) actions.append({'type': 'gather_resources', 'gatherer_id': entity['id'], 'resource_id': target_id, 'amount': gather_rate}) else: entity['target_x'] = target['x'] entity['target_y'] = target['y'] actions.append({'type': 'change_state', 'entity_id': entity['id'], 'new_state': 'moving'}) return actions def _process_building_behavior(self, state, entity: Dict, dt: float) -> List[Dict]: actions = [] if not entity.get('completed', False): build_progress = entity.get('build_progress', 0) + dt build_time = entity.get('build_time', 0) if build_progress >= build_time: actions.append({'type': 'building_completed', 'entity_id': entity['id']}) else: actions.append({'type': 'building_progress', 'entity_id': entity['id'], 'progress': build_progress}) return actions def pathfind(self, entity: Dict, target_pos: Tuple[float, float], map_tiles: List[List[Dict]]) -> List[Tuple[float, float]]: start_pos = (entity['x'], entity['y']) path = [start_pos, target_pos] return path def _has_reached_target(self, entity: Dict) -> bool: if 'target_x' not in entity or 'target_y' not in entity: return True dx = entity['target_x'] - entity['x'] dy = entity['target_y'] - entity['y'] distance = math.sqrt(dx*dx + dy*dy) return distance < 5.0 def _continue_movement(self, entity: Dict, dt: float) -> None: if 'target_x' not in entity or 'target_y' not in entity: return dx = entity['target_x'] - entity['x'] dy = entity['target_y'] - entity['y'] distance = math.sqrt(dx*dx + dy*dy) if distance > 0: speed = entity.get('speed', 50.0) move_dist = speed * dt entity['x'] += (dx / distance) * move_dist entity['y'] += (dy / distance) * move_dist def _is_in_attack_range(self, entity: Dict, target: Dict) -> bool: dx = target['x'] - entity['x'] dy = target['y'] - entity['y'] distance = math.sqrt(dx*dx + dy*dy) attack_range = entity.get('attack_range', 50.0) return distance <= attack_range def _is_in_gather_range(self, entity: Dict, target: Dict) -> bool: dx = target['x'] - entity['x'] dy = target['y'] - entity['y'] distance = math.sqrt(dx*dx + dy*dy) gather_range = entity.get('gather_range', 20.0) return distance <= gather_range def _find_entity_by_id(self, state, entity_id: int) -> Dict: if hasattr(state, 'entities'): for entity in state.entities: if entity.get('id') == entity_id: return entity return None