Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 149 additions & 18 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,12 @@ function createInitialGridState() {
// Helper function to create initial game state
function createInitialGameState() {
return {
phase: 'waiting', // waiting, rolling, color-selection, active
phase: 'waiting', // waiting, rolling, color-selection, turn-rolling, active
diceRolls: {},
winner: null,
loser: null
loser: null,
currentTurn: null, // Player index (0 or 1) whose turn it is
turnDiceRolls: {} // Dice rolls for turn determination
};
}

Expand Down Expand Up @@ -368,6 +370,129 @@ function determineDiceWinner(lobbyName) {
});
}

// Start dice roll for turn determination
function startTurnDiceRoll(lobbyName) {
const lobby = lobbies.get(lobbyName);
if (!lobby || lobby.players.length !== MAX_PLAYERS) {
return;
}

lobby.gameState.phase = 'turn-rolling';
lobby.gameState.turnDiceRolls = {};

// Generate dice rolls for both players
lobby.players.forEach((player, index) => {
const roll = Math.floor(Math.random() * 6) + 1;
lobby.gameState.turnDiceRolls[index] = roll;
});

// Broadcast turn dice roll start to both players
lobby.players.forEach((player, index) => {
if (player.ws.readyState === WebSocket.OPEN) {
player.ws.send(JSON.stringify({
type: 'turnDiceRollStart',
playerIndex: index,
roll: lobby.gameState.turnDiceRolls[index]
}));
}
});

// After animation delay, determine winner
setTimeout(() => {
determineTurnDiceWinner(lobbyName);
}, 3000); // 3 second delay for animation
}

// Determine who goes first from turn dice rolls
function determineTurnDiceWinner(lobbyName) {
const lobby = lobbies.get(lobbyName);
if (!lobby) {
return;
}

const roll1 = lobby.gameState.turnDiceRolls[0];
const roll2 = lobby.gameState.turnDiceRolls[1];

// Check for tie
if (roll1 === roll2) {
// Broadcast tie, then restart roll
lobby.players.forEach((player, index) => {
if (player.ws.readyState === WebSocket.OPEN) {
player.ws.send(JSON.stringify({
type: 'turnDiceRollTie',
message: 'It\'s a tie! Rolling again...'
}));
}
});

// Restart roll after delay
setTimeout(() => {
startTurnDiceRoll(lobbyName);
}, 2000);
return;
}

// Determine who goes first
const firstPlayerIndex = roll1 > roll2 ? 0 : 1;

lobby.gameState.currentTurn = firstPlayerIndex;
lobby.gameState.phase = 'active';

// Notify both players of result and start the game
lobby.players.forEach((player, index) => {
if (player.ws.readyState === WebSocket.OPEN) {
player.ws.send(JSON.stringify({
type: 'turnDiceRollWinner',
isFirst: index === firstPlayerIndex,
firstPlayerIndex: firstPlayerIndex,
roll1: roll1,
roll2: roll2,
playerIndex: index
}));
}
});

// Broadcast game status as active
broadcastGameStatus(lobbyName);

// Send turn notification to the first player
setTimeout(() => {
sendTurnNotification(lobbyName, firstPlayerIndex);
}, 2000);
}

// Send turn notification to current player
function sendTurnNotification(lobbyName, playerIndex) {
const lobby = lobbies.get(lobbyName);
if (!lobby) {
return;
}

lobby.players.forEach((player, index) => {
if (player.ws.readyState === WebSocket.OPEN) {
player.ws.send(JSON.stringify({
type: 'turnChanged',
currentTurn: playerIndex,
isYourTurn: index === playerIndex
}));
}
});
}

// Switch turn to the other player
function switchTurn(lobbyName) {
const lobby = lobbies.get(lobbyName);
if (!lobby || lobby.gameState.phase !== 'active') {
return;
}

// Switch to the other player
lobby.gameState.currentTurn = lobby.gameState.currentTurn === 0 ? 1 : 0;

// Notify both players
sendTurnNotification(lobbyName, lobby.gameState.currentTurn);
}

// Handle color selection from winner
function handleColorSelection(lobbyName, color) {
const lobby = lobbies.get(lobbyName);
Expand All @@ -383,9 +508,6 @@ function handleColorSelection(lobbyName, color) {
winnerPlayer.color = color;
loserPlayer.color = loserColor;

// Update game state to active
lobby.gameState.phase = 'active';

// Notify both players of their final color assignments
if (winnerPlayer.ws.readyState === WebSocket.OPEN) {
winnerPlayer.ws.send(JSON.stringify({
Expand All @@ -403,19 +525,10 @@ function handleColorSelection(lobbyName, color) {
}));
}

// Broadcast game status as active
broadcastGameStatus(lobbyName);

// Send game start to both players
lobby.players.forEach((player) => {
if (player.ws.readyState === WebSocket.OPEN) {
player.ws.send(JSON.stringify({
type: 'gameStart',
message: 'Welcome to the game!',
yourColor: player.color
}));
}
});
// Start turn determination dice roll after a delay
setTimeout(() => {
startTurnDiceRoll(lobbyName);
}, 1000);
}

// Broadcast chat message to lobby
Expand Down Expand Up @@ -689,6 +802,21 @@ wss.on('connection', (ws, req) => {

// Handle grid toggle
if (message.type === 'toggleSquare') {
// Validate it's the player's turn
if (lobby.gameState.phase !== 'active') {
console.log('Game is not in active phase');
return;
}

if (lobby.gameState.currentTurn !== playerIndex) {
console.log(`Not player ${playerIndex}'s turn (current turn: ${lobby.gameState.currentTurn})`);
ws.send(JSON.stringify({
type: 'error',
message: 'It\'s not your turn!'
}));
return;
}

// Get player data
const playerData = lobby.players.find(p => p.ws === ws);
if (!playerData || !playerData.color) {
Expand Down Expand Up @@ -721,6 +849,9 @@ wss.on('connection', (ws, req) => {
}));
}
});

// Switch turn to the other player
switchTurn(currentLobbyName);
}

// Handle chat messages
Expand Down
Loading