diff --git a/public/index.html b/public/index.html
index ab90475..4ea08eb 100644
--- a/public/index.html
+++ b/public/index.html
@@ -467,7 +467,6 @@
const msg = JSON.parse(e.data);
if (msg.type === "room_list") updateRoomList(msg.rooms);
if (msg.type === "init") {
- myRole = msg.role;
roomId = msg.roomId;
document.getElementById("roomCode").innerText = roomId.toUpperCase();
window.history.replaceState({}, '', `?room=${roomId}`);
diff --git a/server.js b/server.js
index 6a0ece6..a55bef4 100644
--- a/server.js
+++ b/server.js
@@ -199,54 +199,68 @@ wss.on("connection", (ws, req) => {
const room = rooms[roomId];
ws.roomId = roomId;
+ ws.sessionId = sessionId; // Store on socket for easy lookup during close
let player = room.players.find(p => p.sessionId === sessionId);
if (player) {
- // Reconnecting existing player
player.ws = ws;
} else if (room.players.length < 2) {
- // New player joining: logic to pick the opposite role
let role;
if (room.players.length === 1) {
- // Pick the role that isn't taken
- const takenRole = room.players[0].role;
- role = (takenRole === "wolf") ? "sheep" : "wolf";
+ role = (room.players[0].role === "wolf") ? "sheep" : "wolf";
} else {
- // First player in the room defaults to sheep
role = "sheep";
}
-
- player = { ws, role, sessionId };
+ player = { ws, role, sessionId, isBot: false };
room.players.push(player);
}
- // Inform the client of their assigned role
ws.send(JSON.stringify({ type: "init", role: player.role, roomId }));
-
broadcastRoomList();
broadcastState(roomId);
-
- // If a bot is involved, update its state
if (room.players.some(p => p.isBot)) sendBotState(roomId);
+ // --- HANDLE DISCONNECT ---
+ ws.on("close", () => {
+ const currentRoom = rooms[ws.roomId];
+ if (!currentRoom) return;
+
+ // Remove the player from the room array
+ currentRoom.players = currentRoom.players.filter(p => p.sessionId !== ws.sessionId);
+
+ // If the room is now empty (or only contains a bot), delete it
+ const humanRemaining = currentRoom.players.some(p => !p.isBot);
+ if (currentRoom.players.length === 0 || (!humanRemaining && currentRoom.players.some(p => p.isBot))) {
+ // If it was a bot room, close the bot socket before deleting
+ const bot = currentRoom.players.find(p => p.isBot);
+ if (bot && bot.socket) bot.socket.destroy();
+ delete rooms[ws.roomId];
+ } else {
+ // Room still has someone, notify them
+ broadcastState(ws.roomId);
+ }
+
+ broadcastRoomList();
+ });
+
ws.on("message", msg => {
let data = JSON.parse(msg);
+ const playerObj = room.players.find(p => p.sessionId === sessionId);
+ if (!playerObj) return;
+
if (data.type === "restart") {
swapRoles(room);
room.game = { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null, lastMove: null };
-
- // Critical: Re-sync roles for all human clients on restart
room.players.forEach(p => {
if (p.ws && p.ws.readyState === WebSocket.OPEN) {
p.ws.send(JSON.stringify({ type: "init", role: p.role, roomId }));
}
});
-
broadcastState(roomId);
if (room.players.some(p => p.isBot)) sendBotState(roomId);
} else {
- handleMove(roomId, player.role, data);
+ handleMove(roomId, playerObj.role, data);
}
});
});