Implement interactive gym battle system with full battle engine integration

**NEW FEATURES:**
- Full 3-pet gym battles with turn-based combat
- Interactive attack selection (\!attack <move>)
- Item usage during gym battles (\!use <item>)
- Progressive battles through gym leader's team
- Proper gym battle state tracking and advancement

**BATTLE MECHANICS:**
- Players fight through all 3 gym pets sequentially
- Can use all battle commands: \!attack, \!moves, \!use
- Cannot flee from gym battles (must \!forfeit instead)
- Battle engine integration maintains all existing combat features
- Automatic progression to next gym pet when one is defeated

**GYM BATTLE FLOW:**
1. \!gym challenge "gym name" - starts battle with first pet
2. Standard turn-based combat using \!attack <move>
3. When gym pet defeated, automatically advance to next pet
4. Complete victory after defeating all 3 gym pets
5. \!forfeit available to quit gym battle with honor

**DATABASE UPDATES:**
- Added active_gym_battles table for state tracking
- Gym battle progression and team management
- Integration with existing player_gym_battles for victory tracking

**COMMANDS ADDED:**
- \!forfeit - quit current gym battle
- Enhanced \!gym challenge with full battle system
- Battle system now handles gym vs wild battle contexts

This creates the proper Pokemon-style gym experience where players strategically
battle through the gym leader's team using their full arsenal of moves and items.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
megaproxy 2025-07-14 13:08:25 +01:00
parent dc49e5f9c9
commit 710ff5ac9c
3 changed files with 298 additions and 24 deletions

View file

@ -256,6 +256,21 @@ class Database:
)
""")
await db.execute("""
CREATE TABLE IF NOT EXISTS active_gym_battles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player_id INTEGER NOT NULL,
gym_id INTEGER NOT NULL,
difficulty_level INTEGER NOT NULL,
current_pet_index INTEGER DEFAULT 0,
gym_team_data TEXT NOT NULL,
battle_status TEXT DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (player_id) REFERENCES players (id),
FOREIGN KEY (gym_id) REFERENCES gyms (id)
)
""")
await db.commit()
async def get_player(self, nickname: str) -> Optional[Dict]:
@ -968,4 +983,117 @@ class Database:
))
await db.commit()
print("Gyms initialized from config")
print("Gyms initialized from config")
async def start_gym_battle(self, player_id: int, gym_id: int, difficulty_level: int, gym_team: List[Dict]) -> int:
"""Start a new gym battle"""
import json
gym_team_json = json.dumps(gym_team)
async with aiosqlite.connect(self.db_path) as db:
# End any existing gym battle for this player
await db.execute("""
UPDATE active_gym_battles
SET battle_status = 'ended'
WHERE player_id = ? AND battle_status = 'active'
""", (player_id,))
# Create new gym battle
cursor = await db.execute("""
INSERT INTO active_gym_battles
(player_id, gym_id, difficulty_level, current_pet_index, gym_team_data)
VALUES (?, ?, ?, 0, ?)
""", (player_id, gym_id, difficulty_level, gym_team_json))
battle_id = cursor.lastrowid
await db.commit()
return battle_id
async def get_active_gym_battle(self, player_id: int) -> Optional[Dict]:
"""Get player's active gym battle"""
async with aiosqlite.connect(self.db_path) as db:
db.row_factory = aiosqlite.Row
cursor = await db.execute("""
SELECT agb.*, g.name as gym_name, g.leader_name, g.badge_icon
FROM active_gym_battles agb
JOIN gyms g ON agb.gym_id = g.id
WHERE agb.player_id = ? AND agb.battle_status = 'active'
ORDER BY agb.id DESC LIMIT 1
""", (player_id,))
row = await cursor.fetchone()
if row:
battle_data = dict(row)
# Parse gym team data
import json
battle_data["gym_team"] = json.loads(battle_data["gym_team_data"])
return battle_data
return None
async def advance_gym_battle(self, player_id: int) -> bool:
"""Advance to next pet in gym battle"""
async with aiosqlite.connect(self.db_path) as db:
# Get current battle
cursor = await db.execute("""
SELECT current_pet_index, gym_team_data
FROM active_gym_battles
WHERE player_id = ? AND battle_status = 'active'
""", (player_id,))
battle = await cursor.fetchone()
if not battle:
return False
import json
gym_team = json.loads(battle[1])
current_index = battle[0]
# Check if there are more pets
if current_index + 1 >= len(gym_team):
return False # No more pets
# Advance to next pet
await db.execute("""
UPDATE active_gym_battles
SET current_pet_index = current_pet_index + 1
WHERE player_id = ? AND battle_status = 'active'
""", (player_id,))
await db.commit()
return True
async def end_gym_battle(self, player_id: int, victory: bool = False) -> Optional[Dict]:
"""End gym battle and return final status"""
async with aiosqlite.connect(self.db_path) as db:
# Get battle info before ending it
cursor = await db.execute("""
SELECT agb.*, g.name as gym_name
FROM active_gym_battles agb
JOIN gyms g ON agb.gym_id = g.id
WHERE agb.player_id = ? AND agb.battle_status = 'active'
""", (player_id,))
battle = await cursor.fetchone()
if not battle:
return None
# End the battle
await db.execute("""
UPDATE active_gym_battles
SET battle_status = 'completed'
WHERE player_id = ? AND battle_status = 'active'
""", (player_id,))
result = {
"gym_id": battle[2],
"gym_name": battle[9],
"difficulty_level": battle[3],
"victory": victory
}
# Record victory if successful
if victory:
await self.record_gym_victory(player_id, battle[2])
await db.commit()
return result