add super powers to this game
no erros full code modern


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()