#!/usr/bin/env python3 """Gym battle module for PetBot""" from .base_module import BaseModule class GymBattles(BaseModule): """Handles gym challenges, battles, and badge tracking""" def get_commands(self): return ["gym", "forfeit"] async def handle_command(self, channel, nickname, command, args): if command == "gym": if not args: await self.cmd_gym_list(channel, nickname) elif self.normalize_input(args[0]) == "list": await self.cmd_gym_list_all(channel, nickname) elif self.normalize_input(args[0]) == "challenge": await self.cmd_gym_challenge(channel, nickname, args[1:]) elif self.normalize_input(args[0]) == "info": await self.cmd_gym_info(channel, nickname, args[1:]) elif self.normalize_input(args[0]) == "status": await self.cmd_gym_status(channel, nickname) else: await self.cmd_gym_list(channel, nickname) elif command == "forfeit": await self.cmd_forfeit(channel, nickname) async def cmd_gym_list(self, channel, nickname): """List gyms in current location""" player = await self.require_player(channel, nickname) if not player: return # Get player's current location location = await self.database.get_player_location(player["id"]) if not location: self.send_message(channel, f"{nickname}: You are not in a valid location!") return # Get gyms in current location gyms = await self.database.get_gyms_in_location(location["id"], player["id"]) if not gyms: self.send_message(channel, f"πŸ›οΈ {nickname}: No gyms found in {location['name']}.") return self.send_message(channel, f"πŸ›οΈ Gyms in {location['name']}:") for gym in gyms: victories = gym.get("victories", 0) if victories == 0: status = "Not challenged" difficulty = "Beginner" else: status = f"{victories} victories" difficulty = f"Level {victories + 1}" badge_icon = gym["badge_icon"] leader = gym["leader_name"] theme = gym["theme"] self.send_message(channel, f" {badge_icon} {gym['name']} - Leader: {leader} ({theme})") self.send_message(channel, f" Status: {status} | Next difficulty: {difficulty}") self.send_message(channel, f"πŸ’‘ Use '!gym challenge \"\"' to battle!") async def cmd_gym_list_all(self, channel, nickname): """List all gyms across all locations""" player = await self.require_player(channel, nickname) if not player: return # Get all locations and their gyms all_locations = await self.database.get_all_locations() self.send_message(channel, f"πŸ—ΊοΈ {nickname}: All Gym Locations:") total_badges = 0 for location in all_locations: gyms = await self.database.get_gyms_in_location(location["id"], player["id"]) if gyms: for gym in gyms: victories = gym.get("victories", 0) status_icon = "βœ…" if victories > 0 else "❌" if victories > 0: total_badges += 1 self.send_message(channel, f" {status_icon} {location['name']}: {gym['name']} ({gym['theme']}) - {victories} victories") self.send_message(channel, f"πŸ† Total badges earned: {total_badges}") async def cmd_gym_challenge(self, channel, nickname, args): """Challenge a gym""" if not args: self.send_message(channel, f"{nickname}: Specify a gym to challenge! Example: !gym challenge \"Forest Guardian\"") return player = await self.require_player(channel, nickname) if not player: return # Get player's current location first location = await self.database.get_player_location(player["id"]) if not location: self.send_message(channel, f"{nickname}: You are not in a valid location! Use !travel to go somewhere first.") return gym_name = " ".join(self.normalize_input(args)).strip('"') # Look for gym in player's current location (case-insensitive) gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"]) if not gym: # List available gyms in current location for helpful error message available_gyms = await self.database.get_gyms_in_location(location["id"]) if available_gyms: gym_list = ", ".join([f'"{g["name"]}"' for g in available_gyms]) self.send_message(channel, f"{nickname}: No gym named '{gym_name}' found in {location['name']}! Available gyms: {gym_list}") else: self.send_message(channel, f"{nickname}: No gyms found in {location['name']}! Try traveling to a different location.") return # Check if player has active pets active_pets = await self.database.get_active_pets(player["id"]) if not active_pets: self.send_message(channel, f"{nickname}: You need at least one active pet to challenge a gym! Use !activate first.") return # Get player's gym progress progress = await self.database.get_player_gym_progress(player["id"], gym["id"]) difficulty_level = (progress["victories"] if progress else 0) + 1 difficulty_multiplier = 1.0 + (difficulty_level - 1) * 0.2 # 20% increase per victory # Start gym battle await self.start_gym_battle(channel, nickname, player, gym, difficulty_level, difficulty_multiplier) async def start_gym_battle(self, channel, nickname, player, gym, difficulty_level, difficulty_multiplier): """Start a gym battle""" # Check if player is already in any battle regular_battle = await self.game_engine.battle_engine.get_active_battle(player["id"]) gym_battle = await self.database.get_active_gym_battle(player["id"]) if regular_battle or gym_battle: self.send_message(channel, f"{nickname}: You're already in a battle! Finish your current battle first.") return # Get gym team with scaling gym_team = await self.database.get_gym_team(gym["id"], difficulty_multiplier) if not gym_team: self.send_message(channel, f"{nickname}: {gym['name']} gym has no team configured!") return # Display battle start badge_icon = gym["badge_icon"] leader = gym["leader_name"] difficulty_name = f"Level {difficulty_level}" if difficulty_level > 1 else "Beginner" self.send_message(channel, f"πŸ›οΈ {nickname} challenges the {gym['name']} gym!") self.send_message(channel, f"{badge_icon} Leader {leader}: \"Welcome to my {gym['theme']}-type gym! Let's see what you've got!\"") self.send_message(channel, f"βš”οΈ Difficulty: {difficulty_name} ({len(gym_team)} pets)") # Start gym battle state battle_id = await self.database.start_gym_battle(player["id"], gym["id"], difficulty_level, gym_team) # Start battle with first gym pet first_gym_pet = gym_team[0] active_pets = await self.database.get_active_pets(player["id"]) player_pet = active_pets[0] # Use first active pet # Create gym pet in wild pet format for battle engine gym_pet_data = { "species_name": first_gym_pet["species_name"], "level": first_gym_pet["level"], "type1": first_gym_pet["type1"], "type2": first_gym_pet["type2"], "stats": { "hp": first_gym_pet["hp"], "attack": first_gym_pet["attack"], "defense": first_gym_pet["defense"], "speed": first_gym_pet["speed"] } } # Start the battle using existing battle engine battle = await self.game_engine.battle_engine.start_battle(player["id"], player_pet, gym_pet_data) # Display first battle start self.send_message(channel, f"πŸ₯Š {leader} sends out {first_gym_pet['species_name']} (Lv.{first_gym_pet['level']})!") self.send_message(channel, f"βš”οΈ Your {player_pet['species_name']} (Lv.{player_pet['level']}, {battle['player_hp']}/{player_pet['max_hp']} HP) vs {first_gym_pet['species_name']} (Lv.{first_gym_pet['level']}, {battle['wild_hp']}/{first_gym_pet['hp']} HP)") # Show available moves from .battle_system import BattleSystem battle_system = BattleSystem(self.bot, self.database, self.game_engine) moves_colored = " | ".join([ f"{battle_system.get_move_color(move['type'])}{move['name']}\x0F" for move in battle["available_moves"] ]) self.send_message(channel, f"🎯 Moves: {moves_colored} | Use !attack or !use ") async def handle_gym_victory(self, channel, nickname, player, gym, difficulty_level): """Handle gym battle victory""" # Record victory in database result = await self.database.record_gym_victory(player["id"], gym["id"]) badge_icon = gym["badge_icon"] leader = gym["leader_name"] self.send_message(channel, f"πŸŽ‰ {nickname} defeats the {gym['name']} gym!") if result["is_first_victory"]: # First time victory - award badge self.send_message(channel, f"{badge_icon} Leader {leader}: \"Impressive! You've earned the {gym['badge_name']}!\"") self.send_message(channel, f"πŸ† {nickname} earned the {gym['badge_name']} {badge_icon}!") # Award bonus rewards for first victory money_reward = 500 + (difficulty_level * 100) exp_reward = 200 + (difficulty_level * 50) else: # Repeat victory self.send_message(channel, f"{badge_icon} Leader {leader}: \"Well fought! Your skills keep improving!\"") money_reward = 200 + (difficulty_level * 50) exp_reward = 100 + (difficulty_level * 25) # Award rewards (we'll implement this when we have currency/exp systems) victories = result["victories"] next_difficulty = result["next_difficulty"] self.send_message(channel, f"πŸ’° Rewards: ${money_reward} | 🌟 {exp_reward} EXP") self.send_message(channel, f"πŸ“Š {gym['name']} record: {victories} victories | Next challenge: Level {next_difficulty}") async def handle_gym_defeat(self, channel, nickname, gym, difficulty_level): """Handle gym battle defeat""" badge_icon = gym["badge_icon"] leader = gym["leader_name"] self.send_message(channel, f"πŸ’₯ {nickname} was defeated by the {gym['name']} gym!") self.send_message(channel, f"{badge_icon} Leader {leader}: \"Good battle! Train more and come back stronger!\"") self.send_message(channel, f"πŸ’‘ Tip: Level up your pets, get better items, or try a different strategy!") async def cmd_gym_info(self, channel, nickname, args): """Get detailed information about a gym""" if not args: self.send_message(channel, f"{nickname}: Specify a gym name! Example: !gym info \"Forest Guardian\"") return player = await self.require_player(channel, nickname) if not player: return gym_name = " ".join(self.normalize_input(args)).strip('"') # First try to find gym in player's current location location = await self.database.get_player_location(player["id"]) gym = None if location: gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"]) # If not found in current location, search globally if not gym: gym = await self.database.get_gym_by_name(gym_name) if not gym: self.send_message(channel, f"{nickname}: Gym '{gym_name}' not found!") return # Get gym team info gym_team = await self.database.get_gym_team(gym["id"]) badge_icon = gym["badge_icon"] self.send_message(channel, f"πŸ›οΈ {gym['name']} Gym Information:") self.send_message(channel, f"πŸ“ Location: {gym['location_name']}") self.send_message(channel, f"πŸ‘€ Leader: {gym['leader_name']}") self.send_message(channel, f"🎯 Theme: {gym['theme']}-type") self.send_message(channel, f"πŸ“ {gym['description']}") self.send_message(channel, f"πŸ† Badge: {gym['badge_name']} {badge_icon}") if gym_team: self.send_message(channel, f"βš”οΈ Team ({len(gym_team)} pets):") for pet in gym_team: type_str = pet["type1"] if pet["type2"]: type_str += f"/{pet['type2']}" self.send_message(channel, f" β€’ Level {pet['level']} {pet['species_name']} ({type_str})") async def cmd_gym_status(self, channel, nickname): """Show player's overall gym progress""" player = await self.require_player(channel, nickname) if not player: return # This will show a summary - for detailed view they can use !gym list self.send_message(channel, f"πŸ† {nickname}: Use !gym list to see all gym progress, or check your profile at: http://petz.rdx4.com/player/{nickname}") async def cmd_forfeit(self, channel, nickname): """Forfeit the current gym battle""" player = await self.require_player(channel, nickname) if not player: return # Check if player is in a gym battle gym_battle = await self.database.get_active_gym_battle(player["id"]) if not gym_battle: self.send_message(channel, f"{nickname}: You're not currently in a gym battle!") return # End any active regular battle first await self.game_engine.battle_engine.end_battle(player["id"], "forfeit") # End gym battle result = await self.database.end_gym_battle(player["id"], victory=False) self.send_message(channel, f"🏳️ {nickname} forfeited the gym battle!") self.send_message(channel, f"{gym_battle['badge_icon']} {gym_battle['leader_name']}: \"Sometimes retreat is the wisest strategy. Come back when you're ready!\"") self.send_message(channel, f"πŸ’‘ {nickname}: Train your pets and try again. You can challenge the gym anytime!")