Ability to play Uno implemented in early stages!
This commit is contained in:
195
bot/commands/uno.py
Normal file
195
bot/commands/uno.py
Normal file
@@ -0,0 +1,195 @@
|
||||
"""
|
||||
UNO Game Commands for Miku
|
||||
Allows Miku to play UNO games via Discord
|
||||
"""
|
||||
import discord
|
||||
import asyncio
|
||||
import requests
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional, Dict, Any
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger('uno')
|
||||
|
||||
# UNO game server configuration (use host IP from container)
|
||||
UNO_SERVER_URL = "http://192.168.1.2:5000"
|
||||
UNO_CLIENT_URL = "http://192.168.1.2:3002"
|
||||
|
||||
# Active games tracking
|
||||
active_uno_games: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
|
||||
async def join_uno_game(message: discord.Message, room_code: str):
|
||||
"""
|
||||
Miku joins an UNO game as Player 2
|
||||
Usage: !uno join <room_code>
|
||||
"""
|
||||
if not room_code:
|
||||
await message.channel.send("🎴 Please provide a room code! Usage: `!uno join <ROOM_CODE>`")
|
||||
return
|
||||
|
||||
room_code = room_code.strip() # Keep exact case - don't convert to uppercase!
|
||||
|
||||
# Check if already in a game
|
||||
if room_code in active_uno_games:
|
||||
await message.channel.send(f"🎴 I'm already playing in room **{room_code}**! Let me finish this game first~ 🎶")
|
||||
return
|
||||
|
||||
await message.channel.send(f"🎤 Joining UNO game **{room_code}** as Player 2! Time to show you how it's done! ✨")
|
||||
|
||||
try:
|
||||
# Import here to avoid circular imports
|
||||
from utils.uno_game import MikuUnoPlayer
|
||||
|
||||
# Define cleanup callback to remove from active games
|
||||
async def cleanup_game(code: str):
|
||||
if code in active_uno_games:
|
||||
logger.info(f"[UNO] Removing room {code} from active games")
|
||||
del active_uno_games[code]
|
||||
|
||||
# Create Miku's player instance with cleanup callback
|
||||
player = MikuUnoPlayer(room_code, message.channel, cleanup_callback=cleanup_game)
|
||||
|
||||
# Join the game (this will open browser and join)
|
||||
success = await player.join_game()
|
||||
|
||||
if success:
|
||||
active_uno_games[room_code] = {
|
||||
'player': player,
|
||||
'channel': message.channel,
|
||||
'started_by': message.author.id
|
||||
}
|
||||
|
||||
await message.channel.send(f"✅ Joined room **{room_code}**! Waiting for Player 1 to start the game... 🎮")
|
||||
|
||||
# Start the game loop
|
||||
asyncio.create_task(player.play_game())
|
||||
else:
|
||||
await message.channel.send(f"❌ Couldn't join room **{room_code}**. Make sure the room exists and has space!")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error joining UNO game: {e}", exc_info=True)
|
||||
await message.channel.send(f"❌ Oops! Something went wrong: {str(e)}")
|
||||
|
||||
|
||||
async def list_uno_games(message: discord.Message):
|
||||
"""
|
||||
List active UNO games Miku is in
|
||||
Usage: !uno list
|
||||
"""
|
||||
if not active_uno_games:
|
||||
await message.channel.send("🎴 I'm not in any UNO games right now! Create a room and use `!uno join <code>` to make me play! 🎤")
|
||||
return
|
||||
|
||||
embed = discord.Embed(
|
||||
title="🎴 Active UNO Games",
|
||||
description="Here are the games I'm currently playing:",
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
|
||||
for room_code, game_info in active_uno_games.items():
|
||||
player = game_info['player']
|
||||
status = "🎮 Playing" if player.is_game_active() else "⏸️ Waiting"
|
||||
embed.add_field(
|
||||
name=f"Room: {room_code}",
|
||||
value=f"Status: {status}\nChannel: <#{game_info['channel'].id}>",
|
||||
inline=False
|
||||
)
|
||||
|
||||
await message.channel.send(embed=embed)
|
||||
|
||||
|
||||
async def quit_uno_game(message: discord.Message, room_code: Optional[str] = None):
|
||||
"""
|
||||
Miku quits an UNO game
|
||||
Usage: !uno quit [room_code]
|
||||
"""
|
||||
if not room_code:
|
||||
# Quit all games
|
||||
if not active_uno_games:
|
||||
await message.channel.send("🎴 I'm not in any games right now!")
|
||||
return
|
||||
|
||||
for code, game_info in list(active_uno_games.items()):
|
||||
await game_info['player'].quit_game()
|
||||
del active_uno_games[code]
|
||||
|
||||
await message.channel.send("👋 I quit all my UNO games! See you next time~ 🎶")
|
||||
return
|
||||
|
||||
room_code = room_code.strip() # Keep exact case
|
||||
|
||||
if room_code not in active_uno_games:
|
||||
await message.channel.send(f"🤔 I'm not in room **{room_code}**!")
|
||||
return
|
||||
|
||||
game_info = active_uno_games[room_code]
|
||||
await game_info['player'].quit_game()
|
||||
del active_uno_games[room_code]
|
||||
|
||||
await message.channel.send(f"👋 I left room **{room_code}**! That was fun~ 🎤")
|
||||
|
||||
|
||||
async def handle_uno_command(message: discord.Message):
|
||||
"""
|
||||
Main UNO command router
|
||||
Usage: !uno <subcommand> [args]
|
||||
|
||||
Subcommands:
|
||||
!uno join <code> - Join an existing game as Player 2
|
||||
!uno list - List active games
|
||||
!uno quit [code] - Quit a game (or all games)
|
||||
!uno help - Show this help
|
||||
"""
|
||||
content = message.content.strip()
|
||||
parts = content.split()
|
||||
|
||||
if len(parts) == 1:
|
||||
# Just !uno
|
||||
await show_uno_help(message)
|
||||
return
|
||||
|
||||
subcommand = parts[1].lower()
|
||||
|
||||
if subcommand == "join":
|
||||
if len(parts) < 3:
|
||||
await message.channel.send("❌ Please provide a room code! Usage: `!uno join <ROOM_CODE>`")
|
||||
return
|
||||
await join_uno_game(message, parts[2])
|
||||
|
||||
elif subcommand == "list":
|
||||
await list_uno_games(message)
|
||||
|
||||
elif subcommand == "quit" or subcommand == "leave":
|
||||
room_code = parts[2] if len(parts) > 2 else None
|
||||
await quit_uno_game(message, room_code)
|
||||
|
||||
elif subcommand == "help":
|
||||
await show_uno_help(message)
|
||||
|
||||
else:
|
||||
await message.channel.send(f"❌ Unknown command: `{subcommand}`. Use `!uno help` to see available commands!")
|
||||
|
||||
|
||||
async def show_uno_help(message: discord.Message):
|
||||
"""Show UNO command help"""
|
||||
embed = discord.Embed(
|
||||
title="🎴 Miku's UNO Commands",
|
||||
description="Play UNO with me! I'll join as Player 2 and use my AI to make strategic moves~ 🎤✨\n\n**How to play:**\n1. Create a room at http://192.168.1.2:3002\n2. Copy the room code\n3. Use `!uno join <CODE>` to make me join!\n4. I'll play automatically and trash talk in chat! 🎶",
|
||||
color=discord.Color.green()
|
||||
)
|
||||
|
||||
commands = [
|
||||
("!uno join <CODE>", "Make me join your UNO game as Player 2"),
|
||||
("!uno list", "List all active games I'm playing"),
|
||||
("!uno quit [CODE]", "Make me quit a game (or all games if no code)"),
|
||||
("!uno help", "Show this help message"),
|
||||
]
|
||||
|
||||
for cmd, desc in commands:
|
||||
embed.add_field(name=cmd, value=desc, inline=False)
|
||||
|
||||
embed.set_footer(text="I'll trash talk and celebrate in chat during games! 🎶")
|
||||
|
||||
await message.channel.send(embed=embed)
|
||||
Reference in New Issue
Block a user