add super powers to this game
no errors full code modern no bugs and add full superpowers system and also make leaderboard use sqlite database andsave points and add login system using discord
use flask for webui and add client html into it please make sure user logged in to make game modern ui

add these super powers
game.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Online Tic Tac Toe</title>
    <style>
        :root {
            --bg-color: #1e1e2f;
            --board-bg: #2e2e3e;
            --cell-color: #ffffff;
            --x-color: #ff4757;
            --o-color: #1e90ff;
            --modal-bg: rgba(0, 0, 0, 0.8);
            --font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            --transition-speed: 0.3s;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: var(--font-family);
        }

        body {
            background-color: var(--bg-color);
            color: var(--cell-color);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
        }

        h1 {
            margin-bottom: 20px;
            font-size: 2.5rem;
            text-transform: uppercase;
            letter-spacing: 2px;
        }

        .game-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            animation: fadeIn 1s ease-in-out;
        }

        .pre-game {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-bottom: 20px;
        }

        .pre-game input {
            padding: 10px;
            margin: 5px;
            font-size: 1rem;
            border: none;
            border-radius: 5px;
            width: 200px;
        }

        .pre-game button {
            padding: 10px 20px;
            margin: 5px;
            background-color: var(--x-color);
            border: none;
            border-radius: 5px;
            color: var(--cell-color);
            font-size: 1rem;
            cursor: pointer;
            transition: background-color var(--transition-speed) ease;
        }

        .pre-game button:hover {
            background-color: #ff6b81;
        }

        .board {
            display: none;
            grid-template-columns: repeat(3, 100px);
            grid-template-rows: repeat(3, 100px);
            gap: 15px;
            background-color: var(--board-bg);
            padding: 15px;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
            margin-bottom: 20px;
        }

        .cell {
            background-color: var(--bg-color);
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 2.5rem;
            cursor: pointer;
            position: relative;
            transition: transform var(--transition-speed) ease;
        }

        .cell:hover {
            transform: scale(1.05);
            background-color: #3e3e50;
        }

        .cell.disabled {
            cursor: not-allowed;
            opacity: 0.7;
        }

        .x::before,
        .o::before {
            content: '';
            position: absolute;
            width: 80%;
            height: 80%;
            border-radius: 50%;
            animation: popIn 0.3s ease forwards;
        }

        .x::before {
            border: 5px solid var(--x-color);
            transform: rotate(45deg);
        }

        .o::before {
            border: 5px solid var(--o-color);
        }

        .x::after {
            content: '';
            position: absolute;
            width: 80%;
            height: 5px;
            background-color: var(--x-color);
            transform: rotate(45deg);
            animation: drawX 0.3s ease forwards;
        }

        .x::after {
            content: '';
            position: absolute;
            width: 80%;
            height: 5px;
            background-color: var(--x-color);
            transform: rotate(-45deg);
            animation: drawX 0.3s ease forwards;
        }

        .o::before {
            border: 5px solid var(--o-color);
            animation: drawO 0.5s ease forwards;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: scale(0.95); }
            to { opacity: 1; transform: scale(1); }
        }

        @keyframes popIn {
            from { transform: scale(0); }
            to { transform: scale(1); }
        }

        @keyframes drawX {
            from { width: 0; }
            to { width: 80%; }
        }

        @keyframes drawO {
            from { transform: scale(0); }
            to { transform: scale(1); }
        }

        .status {
            margin-bottom: 20px;
            font-size: 1.2rem;
        }

        .room-code {
            margin-top: 10px;
            font-size: 1rem;
        }

        .restart-btn {
            margin-top: 20px;
            padding: 10px 20px;
            background-color: var(--o-color);
            border: none;
            border-radius: 5px;
            color: var(--cell-color);
            font-size: 1rem;
            cursor: pointer;
            transition: background-color var(--transition-speed) ease;
        }

        .restart-btn:hover {
            background-color: #1e90ff;
        }

        @media (max-width: 500px) {
            .board {
                grid-template-columns: repeat(3, 80px);
                grid-template-rows: repeat(3, 80px);
                gap: 10px;
                padding: 10px;
            }

            .cell {
                font-size: 2rem;
            }

            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>Tic Tac Toe</h1>
        <div class="pre-game">
            <button id="create-game-btn">Create Game</button>
            <input type="text" id="room-code-input" placeholder="Enter Room Code">
            <button id="join-game-btn">Join Game</button>
        </div>
        <div class="status" id="status"></div>
        <div class="room-code" id="room-code"></div>
        <div class="board" id="board">
            <div class="cell" data-index="0"></div>
            <div class="cell" data-index="1"></div>
            <div class="cell" data-index="2"></div>
            <div class="cell" data-index="3"></div>
            <div class="cell" data-index="4"></div>
            <div class="cell" data-index="5"></div>
            <div class="cell" data-index="6"></div>
            <div class="cell" data-index="7"></div>
            <div class="cell" data-index="8"></div>
        </div>
        <button class="restart-btn" id="restart-btn" style="display:none;">Restart Game</button>
    </div>
    <script>
        const createGameBtn = document.getElementById('create-game-btn');
        const joinGameBtn = document.getElementById('join-game-btn');
        const roomCodeInput = document.getElementById('room-code-input');
        const statusDiv = document.getElementById('status');
        const roomCodeDiv = document.getElementById('room-code');
        const boardDiv = document.getElementById('board');
        const cells = document.querySelectorAll('.cell');
        const restartBtn = document.getElementById('restart-btn');

        let websocket = null;
        let playerSymbol = '';
        let roomCode = '';
        let yourTurn = false;

        // Replace with your server's address and port
        const serverAddress = 'ws://localhost:6789';

        createGameBtn.addEventListener('click', () => {
            websocket = new WebSocket(serverAddress);
            websocket.onopen = () => {
                websocket.send(JSON.stringify({ type: 'create' }));
            };
            setupWebSocket();
        });

        joinGameBtn.addEventListener('click', () => {
            const code = roomCodeInput.value.trim();
            if (code === '') {
                alert('Please enter a valid room code.');
                return;
            }
            websocket = new WebSocket(serverAddress);
            websocket.onopen = () => {
                websocket.send(JSON.stringify({ type: 'join', room: code }));
            };
            setupWebSocket();
        });

        function setupWebSocket() {
            websocket.onmessage = (event) => {
                const data = JSON.parse(event.data);
                if (data.type === 'created') {
                    roomCode = data.room;
                    roomCodeDiv.textContent = 'Room Code: ' + roomCode;
                    statusDiv.textContent = 'Waiting for an opponent to join...';
                } else if (data.type === 'start') {
                    playerSymbol = data.symbol;
                    roomCode = data.room;
                    roomCodeDiv.textContent = 'Room Code: ' + roomCode;
                    statusDiv.textContent = 'Game started! You are ' + playerSymbol;
                    boardDiv.style.display = 'grid';
                    document.querySelector('.pre-game').style.display = 'none';
                } else if (data.type === 'turn') {
                    yourTurn = data.symbol === playerSymbol;
                    if (yourTurn) {
                        statusDiv.textContent = 'Your turn (' + playerSymbol + ')';
                    } else {
                        statusDiv.textContent = 'Opponent\'s turn';
                    }
                } else if (data.type === 'move') {
                    const index = data.index;
                    const symbol = data.symbol;
                    const cell = document.querySelector(`.cell[data-index="${index}"]`);
                    cell.classList.add(symbol.toLowerCase());
                    cell.classList.add('disabled');
                } else if (data.type === 'end') {
                    statusDiv.textContent = data.result;
                    yourTurn = false;
                    restartBtn.style.display = 'block';
                } else if (data.type === 'reset') {
                    cells.forEach(cell => {
                        cell.classList.remove('x', 'o', 'disabled');
                        cell.style.backgroundColor = 'var(--bg-color)';
                    });
                    statusDiv.textContent = 'Game reset! You are ' + playerSymbol;
                    restartBtn.style.display = 'none';
                } else if (data.type === 'error') {
                    alert(data.message);
                }
            };

            websocket.onclose = () => {
                statusDiv.textContent = 'Connection closed.';
            }
        }

        cells.forEach(cell => {
            cell.addEventListener('click', () => {
                if (!yourTurn || cell.classList.contains('disabled')) {
                    return;
                }
                const index = cell.getAttribute('data-index');
                websocket.send(JSON.stringify({ type: 'move', index: parseInt(index), room: roomCode }));
            });
        });

        restartBtn.addEventListener('click', () => {
            websocket.send(JSON.stringify({ type: 'reset', room: roomCode }));
            restartBtn.style.display = 'none';
        });
    </script>
</body>
</html>



server.py
import asyncio
import websockets
import json
import string
import random

PORT = 6789

# Dictionary to manage all active rooms
rooms = {}

def generate_room_code(length=6):
    """Generate a unique room code."""
    while True:
        code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=length))
        if code not in rooms:
            return code

class Game:
    def __init__(self, room_code, player1, player2):
        self.room_code = room_code
        self.players = [player1, player2]
        self.symbols = {player1: 'X', player2: 'O'}
        self.board = [''] * 9
        self.current_turn = player1
        self.active = True

    async def start(self):
        """Notify players that the game has started and assign symbols."""
        start_msg_p1 = {'type': 'start', 'symbol': self.symbols[self.players[0]], 'room': self.room_code}
        start_msg_p2 = {'type': 'start', 'symbol': self.symbols[self.players[1]], 'room': self.room_code}
        await asyncio.gather(
            self.players[0].send(json.dumps(start_msg_p1)),
            self.players[1].send(json.dumps(start_msg_p2))
        )
        await self.notify_turn()

    async def notify_turn(self):
        """Notify players whose turn it is."""
        if not self.active:
            return
        current_symbol = self.symbols[self.current_turn]
        turn_msg = {'type': 'turn', 'symbol': current_symbol}
        await asyncio.gather(
            self.players[0].send(json.dumps(turn_msg)),
            self.players[1].send(json.dumps(turn_msg))
        )

    def check_winner(self):
        """Check if there's a winner or a draw."""
        winning_combinations = [
            [0,1,2], [3,4,5], [6,7,8],  # rows
            [0,3,6], [1,4,7], [2,5,8],  # columns
            [0,4,8], [2,4,6]            # diagonals
        ]
        for combo in winning_combinations:
            a, b, c = combo
            if self.board[a] and self.board[a] == self.board[b] == self.board[c]:
                return self.board[a]
        if all(cell != '' for cell in self.board):
            return 'Draw'
        return None

    async def handle_move(self, player, index):
        """Process a player's move."""
        if player != self.current_turn or not self.active:
            await player.send(json.dumps({'type': 'error', 'message': 'Not your turn.'}))
            return
        if self.board[index] != '':
            await player.send(json.dumps({'type': 'error', 'message': 'Cell already occupied.'}))
            return
        symbol = self.symbols[player]
        self.board[index] = symbol
        move_msg = {'type': 'move', 'index': index, 'symbol': symbol}
        await asyncio.gather(
            self.players[0].send(json.dumps(move_msg)),
            self.players[1].send(json.dumps(move_msg))
        )
        # Check for winner
        result = self.check_winner()
        if result:
            self.active = False
            if result == 'Draw':
                end_msg = {'type': 'end', 'result': 'It\'s a draw!'}
            else:
                end_msg = {'type': 'end', 'result': f'{result} wins!'}
            await asyncio.gather(
                self.players[0].send(json.dumps(end_msg)),
                self.players[1].send(json.dumps(end_msg))
            )
        else:
            # Switch turn
            self.current_turn = self.players[1] if self.current_turn == self.players[0] else self.players[0]
            await self.notify_turn()

    async def handle_reset(self, player):
        """Handle game reset requests."""
        if not self.active:
            # Reset the game
            self.board = [''] * 9
            self.active = True
            await asyncio.gather(
                self.players[0].send(json.dumps({'type': 'reset'})),
                self.players[1].send(json.dumps({'type': 'reset'}))
            )
            # Decide who starts (player1 starts)
            self.current_turn = self.players[0]
            await self.start()
        else:
            # If game is active, do not allow reset
            await player.send(json.dumps({'type': 'error', 'message': 'Cannot reset during an active game.'}))

    async def handle_disconnect(self, player):
        """Handle player disconnections."""
        opponent = self.players[1] if self.players[0] == player else self.players[0]
        if self.active:
            end_msg = {'type': 'end', 'result': 'Opponent disconnected.'}
            await opponent.send(json.dumps(end_msg))
        # Clean up room
        del rooms[self.room_code]
        await asyncio.gather(
            opponent.close(),
            player.close()
        )

async def handler(websocket, path):
    """
    Handle incoming WebSocket connections.
    Expected protocol:
    - Client sends a JSON message to 'create' or 'join' a room.
    - After joining, the game starts when two players are in the room.
    """
    try:
        async for message in websocket:
            data = json.loads(message)
            if data['type'] == 'create':
                # Create a new room
                room_code = generate_room_code()
                rooms[room_code] = {'players': [websocket], 'game': None}
                await websocket.send(json.dumps({'type': 'created', 'room': room_code}))
                print(f"Room {room_code} created by {websocket.remote_address}")
            elif data['type'] == 'join':
                # Join an existing room
                room_code = data.get('room')
                if room_code not in rooms:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Room does not exist.'}))
                elif len(rooms[room_code]['players']) >= 2:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Room is full.'}))
                else:
                    rooms[room_code]['players'].append(websocket)
                    player1, player2 = rooms[room_code]['players']
                    game = Game(room_code, player1, player2)
                    rooms[room_code]['game'] = game
                    await game.start()
                    print(f"Player joined room {room_code} from {websocket.remote_address}")
            elif data['type'] == 'move':
                # Handle a move; ensure the player is part of a game
                room_code = data.get('room')
                game = rooms.get(room_code, {}).get('game')
                if not game:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Game not found.'}))
                    continue
                index = data.get('index')
                if index is not None and 0 <= index < 9:
                    await game.handle_move(websocket, index)
                else:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Invalid move.'}))
            elif data['type'] == 'reset':
                # Handle a reset request
                room_code = data.get('room')
                game = rooms.get(room_code, {}).get('game')
                if not game:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Game not found.'}))
                    continue
                await game.handle_reset(websocket)
            else:
                await websocket.send(json.dumps({'type': 'error', 'message': 'Unknown command.'}))
    except websockets.exceptions.ConnectionClosed:
        print(f"Connection closed: {websocket.remote_address}")
        # Find and handle disconnection
        for room_code, room in list(rooms.items()):
            if websocket in room['players']:
                game = room.get('game')
                if game:
                    await game.handle_disconnect(websocket)
                else:
                    # Room still has only one player
                    room['players'].remove(websocket)
                    del rooms[room_code]
                break

# Start the WebSocket server
start_server = websockets.serve(handler, "0.0.0.0", PORT)

print(f"Server started on port {PORT}")
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()