create html game online wiht python server and points system and name system have 8 colums and 6 row each box have the game have play 2 players blue and red make it draw circle player by player the player who make 4 circles in horzintal win a point and reset the game,  the player can put circle if there is ciracle under it, modern style, client static html , server in python, no flask, server like minecraft spreated


index.html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Connect Four Online</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #2c3e50;
            color: #ecf0f1;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding-top: 50px;
        }
        #game {
            display: grid;
            grid-template-columns: repeat(8, 60px);
            grid-template-rows: repeat(6, 60px);
            gap: 5px;
            background-color: #34495e;
            padding: 10px;
            border-radius: 10px;
        }
        .cell {
            width: 60px;
            height: 60px;
            background-color: #ecf0f1;
            border-radius: 50%;
            position: relative;
            cursor: pointer;
        }
        .red {
            background-color: red;
        }
        .blue {
            background-color: blue;
        }
        #status {
            margin-top: 20px;
        }
        #join {
            margin-bottom: 20px;
        }
        #points {
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div id="join">
        <input type="text" id="name" placeholder="Enter your name">
        <button onclick="joinGame()">Join Game</button>
    </div>
    <div id="game"></div>
    <div id="status"></div>
    <div id="points"></div>

    <script>
        const gameDiv = document.getElementById('game');
        const statusDiv = document.getElementById('status');
        const pointsDiv = document.getElementById('points');
        let socket;
        let playerColor = null;

        function joinGame() {
            const name = document.getElementById('name').value;
            if (!name) {
                alert("Please enter your name.");
                return;
            }
            socket = new WebSocket('ws://localhost:6789');

            socket.onopen = () => {
                socket.send(JSON.stringify({ type: 'join', name }));
                document.getElementById('join').style.display = 'none';
            };

            socket.onmessage = (event) => {
                const data = JSON.parse(event.data);
                if (data.type === 'error') {
                    alert(data.message);
                } else if (data.type === 'update') {
                    updateGame(data);
                }
            };

            socket.onclose = () => {
                statusDiv.innerText = "Connection closed.";
            };
        }

        function updateGame(data) {
            // Update board
            gameDiv.innerHTML = '';
            for (let row = 0; row < 6; row++) {
                for (let col = 0; col < 8; col++) {
                    const cell = document.createElement('div');
                    cell.classList.add('cell');
                    if (data.board[row][col]) {
                        cell.classList.add(data.board[row][col]);
                    }
                    cell.dataset.column = col;
                    cell.onclick = () => makeMove(col);
                    gameDiv.appendChild(cell);
                }
            }

            // Update current turn
            statusDiv.innerText = `Current Turn: ${capitalize(data.current_turn)}`;

            // Update player info
            pointsDiv.innerHTML = '';
            for (const [color, info] of Object.entries(data.players)) {
                if (playerColor === null && socket.readyState === WebSocket.OPEN) {
                    // Assign player color
                    playerColor = color;
                }
                pointsDiv.innerHTML += `<p>${capitalize(color)} Player: ${info.name} | Points: ${info.points}</p>`;
            }
        }

        function makeMove(column) {
            if (!socket || socket.readyState !== WebSocket.OPEN) return;
            socket.send(JSON.stringify({ type: 'move', column }));
        }

        function capitalize(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
        }
    </script>
</body>
</html>


server.py
# server.py
import asyncio
import websockets
import json

# Game state
GAME_ROWS = 6
GAME_COLS = 8

class Game:
    def __init__(self):
        self.reset_game()
        self.players = {}  # websocket: { 'name': str, 'color': 'red'/'blue', 'points': int }

    def reset_game(self):
        self.board = [[None for _ in range(GAME_COLS)] for _ in range(GAME_ROWS)]
        self.current_turn = 'red'  # red starts
        self.game_over = False

    def add_player(self, websocket, name):
        if len(self.players) >= 2:
            return False  # Game full
        color = 'red' if not any(p['color'] == 'red' for p in self.players.values()) else 'blue'
        self.players[websocket] = {'name': name, 'color': color, 'points': 0}
        return True

    def remove_player(self, websocket):
        if websocket in self.players:
            del self.players[websocket]

    def make_move(self, column, color):
        if self.game_over or color != self.current_turn:
            return False, "Not your turn or game over."

        # Place the piece in the column
        for row in reversed(range(GAME_ROWS)):
            if self.board[row][column] is None:
                self.board[row][column] = color
                if self.check_winner(row, column, color):
                    self.game_over = True
                    return True, "win"
                self.current_turn = 'blue' if self.current_turn == 'red' else 'red'
                return True, "success"
        return False, "Column full."

    def check_winner(self, row, col, color):
        # Check horizontal
        count = 0
        for c in range(GAME_COLS):
            if self.board[row][c] == color:
                count += 1
                if count == 4:
                    return True
            else:
                count = 0
        # You can add vertical and diagonal checks similarly
        return False

    def to_json(self):
        return json.dumps({
            'type': 'update',
            'board': self.board,
            'current_turn': self.current_turn,
            'players': {p['color']: {'name': p['name'], 'points': p['points']} for p in self.players.values()}
        })

game = Game()

async def handler(websocket, path):
    # Register player
    try:
        async for message in websocket:
            data = json.loads(message)
            if data['type'] == 'join':
                name = data['name']
                success = game.add_player(websocket, name)
                if not success:
                    await websocket.send(json.dumps({'type': 'error', 'message': 'Game is full.'}))
                    continue
                # Send initial game state
                await websocket.send(game.to_json())
                # Notify others
                for ws in game.players:
                    if ws != websocket:
                        await ws.send(game.to_json())
            elif data['type'] == 'move':
                column = data['column']
                color = game.players[websocket]['color']
                success, status = game.make_move(column, color)
                if not success:
                    await websocket.send(json.dumps({'type': 'error', 'message': status}))
                    continue
                if status == "win":
                    # Update points
                    for p_ws, p in game.players.items():
                        if p['color'] == color:
                            p['points'] += 1
                    # Notify all players
                    await asyncio.wait([ws.send(game.to_json()) for ws in game.players])
                    game.reset_game()
                else:
                    # Notify all players
                    await asyncio.wait([ws.send(game.to_json()) for ws in game.players])
    except websockets.exceptions.ConnectionClosed:
        pass
    finally:
        game.remove_player(websocket)
        # Optionally notify others about the player leaving

start_server = websockets.serve(handler, "0.0.0.0", 6789)

print("Server started on ws://0.0.0.0:6789")
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()


add roms system