Sistema de IA Híbrido
Desafío: Crear enemigos inteligentes que sean desafiantes pero predecibles.
Solución de IA: Sistema híbrido que combina lógica basada en reglas con validación Q-Learning.
def barrel_movement(self, platforms, player_rect=None): """IA Híbrida: Decisiones primarias basadas en reglas con validación Q-Learning""" if not player_rect or not platforms: self.velocity_x = self.speed * self.direction return # PASO 1: Decisión primaria basada en reglas dx = player_rect.centerx - self.rect.centerx dy = player_rect.centery - self.rect.centery primary_action = self.decide_primary_action(dx, dy, current_platform, player_platform) # PASO 2: Validación y mejora con Q-Learning if hasattr(self, 'ai_agent'): state = self.get_state(player_rect) q_action = self.ai_agent.choose_action(state) # Anular solo en situaciones específicas if self.should_override_action(primary_action, q_action, dx, dy): primary_action = q_action # Aprender de la acción tomada reward = self.calculate_reward(player_rect) next_state = self.get_state(player_rect) self.ai_agent.learn(state, primary_action, reward, next_state, not self.active) # PASO 3: Ejecutar la acción decidida self.execute_action_decision(primary_action, current_platform, dx)
Por qué esto es Innovador:
- Lo mejor de ambos mundos: Comportamiento base predecible con mejoras adaptativas
- Aprendizaje contextual: Q-Learning solo anula cuando tiene alta confianza
- Experiencia del jugador: Mantiene la sensación del juego mientras agrega inteligencia
- Amigable para debugging: El núcleo basado en reglas es fácil de entender y modificar
Carga Dinámica de Assets
Desafío: Assets que no cargan en ejecutables empaquetados debido a diferencias de rutas.
Solución de IA: Resolución dinámica de rutas que funciona tanto en desarrollo como en producción.
def load_sprites(self): """Carga dinámica de assets para desarrollo y ejecutables empaquetados""" sprites = {'idle': [], 'jump': []} # PASO 1: Determinar la ruta base correcta if hasattr(sys, '_MEIPASS'): # Ejecutable empaquetado con PyInstaller base_path = sys._MEIPASS print("Cargando assets desde ejecutable empaquetado") else: # Entorno de desarrollo base_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) print("Cargando assets desde directorio de desarrollo") # PASO 2: Cargar sprites con manejo comprensivo de errores for i in range(1, 12): sprite_path = os.path.join(base_path, 'assets', 'player', f'sprite_{i:02d}.png') if os.path.exists(sprite_path): try: sprite = pygame.image.load(sprite_path) sprite = pygame.transform.scale(sprite, (self.rect.width, self.rect.height)) sprites['jump'].append(sprite) print(f"✓ Sprite cargado: sprite_{i:02d}.png") except Exception as e: print(f"✗ Error cargando sprite {sprite_path}: {e}") # Continuar cargando otros sprites else: print(f"⚠ Sprite no encontrado: {sprite_path}") return sprites if any(sprites.values()) else None def load_asset_safely(self, asset_path, default_size=(32, 32)): """Carga segura de assets con fallback""" try: if os.path.exists(asset_path): asset = pygame.image.load(asset_path) return pygame.transform.scale(asset, default_size) except Exception as e: print(f"Falló la carga de asset para {asset_path}: {e}") # Retornar rectángulo coloreado como fallback surface = pygame.Surface(default_size) surface.fill((255, 0, 255)) # Magenta para assets faltantes return surface
Por qué esto es Innovador:
- Compatibilidad universal: Funciona en desarrollo y ejecutables empaquetados
- Degradación elegante: Continúa funcionando incluso con assets faltantes
- Logging detallado: Proporciona retroalimentación clara sobre el estado de carga de assets
- Sistema de fallback: Nunca crashea debido a assets faltantes
Spawn Inteligente de Enemigos
Desafío: Equilibrar la dificultad de enemigos sin abrumar al jugador.
Solución de IA: Sistema de spawn adaptativo que escala con el tiempo y rendimiento del jugador.
def spawn_entities(self): """Spawn inteligente de entidades con dificultad adaptativa""" self.spawn_timer += 1 # SPAWN ADAPTATIVO DE BARRILES self.spawn_barrels_adaptively() # SPAWN GRADUAL DE MONSTRUOS self.spawn_monsters_gradually() def spawn_barrels_adaptively(self): """Spawn de barriles con dificultad creciente en el tiempo""" barrel_count = len([e for e in self.enemies if e.enemy_type == "barrel"]) # Calcular máximo de barriles basado en tiempo jugado time_factor = self.spawn_timer // 3600 # Cada 60 segundos max_barrels = min(1 + time_factor, 3) # Máximo 3 barriles # Calcular tasa de spawn (aumenta con el tiempo) current_spawn_rate = min( self.base_spawn_rate + (time_factor * self.spawn_rate_increase), self.max_spawn_rate ) # Spawn si está bajo el límite y pasa la verificación de probabilidad if barrel_count < max_barrels and random.random() < current_spawn_rate: self.spawn_barrel() print(f"Barril spawneado (Tasa: {current_spawn_rate:.3f}, Cantidad: {barrel_count + 1}/{max_barrels})")
Por qué esto es Innovador:
- Dificultad adaptativa: La tasa de spawn aumenta con el tiempo jugado
- Posicionamiento estratégico: Los enemigos aparecen lejos del jugador para mejor desafío
- Progresión equilibrada: El aumento gradual previene abrumar
- Monitoreo de rendimiento: Estadísticas integradas para ajustes
Q-Learning sin NumPy
Desafío: Conflictos de PyInstaller con NumPy causando errores de empaquetado.
Solución de IA: Implementación de Q-Learning usando solo Python estándar.
class SimpleArray: """Reemplazo simple de NumPy para empaquetado""" def __init__(self, data): self.data = data if isinstance(data, list) else [data] def argmax(self): """Encuentra el índice del valor máximo""" if not self.data: return 0 max_val = max(self.data) return self.data.index(max_val) def zeros(self, shape): """Crea array de ceros""" if isinstance(shape, int): return [0.0] * shape return [[0.0] * shape[1] for _ in range(shape[0])] class QLearningAgent: def __init__(self, state_size, action_size, learning_rate=0.1): self.state_size = state_size self.action_size = action_size self.learning_rate = learning_rate self.discount_factor = 0.95 self.epsilon = 0.1 self.q_table = {} def choose_action(self, state): """Selección de acción epsilon-greedy sin NumPy""" state_key = self.get_state_key(state) if random.random() < self.epsilon: return random.randint(0, self.action_size - 1) if state_key not in self.q_table: self.q_table[state_key] = [0.0] * self.action_size # Usar implementación manual de argmax q_values = self.q_table[state_key] max_value = max(q_values) return q_values.index(max_value)
Por qué esto es Innovador:
- Solución de compatibilidad: Elimina conflictos de dependencias de PyInstaller
- Rendimiento mantenido: Funcionalidad completa sin bibliotecas externas
- Simplicidad: Más fácil de debuggear y entender
- Portabilidad: Funciona en cualquier instalación de Python
Conclusión
Estos ejemplos demuestran cómo la IA puede generar código sofisticado y listo para producción que maneja la complejidad del mundo real y casos edge de manera efectiva. Las soluciones van más allá de la funcionalidad básica para incluir:
- Manejo robusto de errores
- Degradación elegante
- Adaptabilidad inteligente
- Compatibilidad multiplataforma
- Experiencia de usuario optimizada
La clave está en proporcionar contexto rico y requerimientos específicos a la IA, permitiéndole generar soluciones que no solo funcionan, sino que son mantenibles, extensibles y profesionales.