pioche d'une carte

This commit is contained in:
Didictateur 2025-11-22 16:26:18 +01:00
parent 3b983b5227
commit 82dc0c4222
2 changed files with 38 additions and 26 deletions

View file

@ -98,8 +98,17 @@
renderBoardFromState(data.boardState); renderBoardFromState(data.boardState);
updateTurnBanner(data.boardState); updateTurnBanner(data.boardState);
} }
// render hands: server now sends private hands as `handsOwn` and public counts as `handCounts` // render hands: prefer new private `handsOwn` + `handCounts`.
if(data.handsOwn || data.handCounts) renderHands(data.handsOwn || [], data.handCounts || {}); // If server (or older code) mistakenly sends a full `hands` object, only show the current player's own hand and public counts — never reveal other players' cards.
if(data.hands){
// legacy: full hands object mapping playerId -> array
const own = (data.hands && data.hands[myPlayerId]) ? data.hands[myPlayerId] : [];
const counts = {};
Object.entries(data.hands || {}).forEach(([pid, arr])=>{ counts[pid] = (arr && arr.length) || 0; });
renderHands(own, counts);
} else if(data.handsOwn || data.handCounts){
renderHands(data.handsOwn || [], data.handCounts || {});
}
}); });
socket.on('game:over', (data)=>{ log('game:over', data); if(data.boardState){ renderBoardFromState(data.boardState); updateTurnBanner(data.boardState); } }); socket.on('game:over', (data)=>{ log('game:over', data); if(data.boardState){ renderBoardFromState(data.boardState); updateTurnBanner(data.boardState); } });
socket.on('game:started', (data)=>{ log('game:started', data); if(data.boardState){ renderBoardFromState(data.boardState); updateTurnBanner(data.boardState); } }); socket.on('game:started', (data)=>{ log('game:started', data); if(data.boardState){ renderBoardFromState(data.boardState); updateTurnBanner(data.boardState); } });
@ -457,19 +466,6 @@
}); });
wrap.appendChild(list); wrap.appendChild(list);
handsEl.appendChild(wrap); handsEl.appendChild(wrap);
// show counts for other players
Object.entries(handCounts || {}).forEach(([pid, count]) => {
if(pid === myPlayerId) return;
const other = document.createElement('div');
other.className = 'player-hand';
const t = document.createElement('div');
t.style.fontWeight = '700';
t.style.marginBottom = '6px';
t.textContent = `Main de ${pid} — ${count} carte(s)`;
other.appendChild(t);
handsEl.appendChild(other);
});
} }
function showCardDrawnNotification(evt){ function showCardDrawnNotification(evt){

View file

@ -99,7 +99,12 @@ function buildDefaultDeck(){
// ['doppelganger','Choisis une pièce. À partir de maintenant, devient chacune des pièces qu elle capture.'], // ['doppelganger','Choisis une pièce. À partir de maintenant, devient chacune des pièces qu elle capture.'],
// ['kurby','Choisis une pièce. À sa prochaine capture, récupère les mouvements de la pièce capturée.'] // ['kurby','Choisis une pièce. À sa prochaine capture, récupère les mouvements de la pièce capturée.']
]; ];
return cards.map(([title,desc])=>({ id: uuidv4().slice(0,8), cardId: title.replace(/[^a-z0-9]+/gi,'_').toLowerCase(), title: title, description: desc })); function cap(s){ if(!s) return s; s = String(s).trim(); return s.charAt(0).toUpperCase() + s.slice(1); }
return cards.map(([title,desc])=>{
const normalized = (title||'').toString().trim();
const cardId = normalized.replace(/[^a-z0-9]+/gi,'_').toLowerCase();
return { id: uuidv4().slice(0,8), cardId, title: cap(normalized), description: desc };
});
} }
// draw a random card from room.deck and assign to player hand (respect max hand size 5) // draw a random card from room.deck and assign to player hand (respect max hand size 5)
@ -122,6 +127,11 @@ function drawCardForPlayer(room, playerId){
// pick random index // pick random index
const idx = Math.floor(Math.random() * room.deck.length); const idx = Math.floor(Math.random() * room.deck.length);
const card = room.deck.splice(idx,1)[0]; const card = room.deck.splice(idx,1)[0];
// normalize title capitalization just in case this deck was created earlier with inconsistent casing
if(card && card.title){
card.title = String(card.title).trim();
card.title = card.title.charAt(0).toUpperCase() + card.title.slice(1);
}
room.hands[playerId] = room.hands[playerId] || []; room.hands[playerId] = room.hands[playerId] || [];
room.hands[playerId].push(card); room.hands[playerId].push(card);
if(boardVersion !== null) room._lastDrawForPlayer[playerId] = boardVersion; if(boardVersion !== null) room._lastDrawForPlayer[playerId] = boardVersion;
@ -356,11 +366,14 @@ io.on('connection', (socket) => {
sendRoomUpdate(room); sendRoomUpdate(room);
// If the game is already playing and it's this player's turn, attempt to draw (useful on reconnect) // If the game is already playing and it's this player's turn, attempt to draw (useful on reconnect)
// Only draw if the player's hand is currently empty to avoid double-drawing (e.g. initial granted cards)
try{ try{
if(room.status === 'playing' && room.boardState && room.boardState.turn){ if(room.status === 'playing' && room.boardState && room.boardState.turn){
const myShort = (room.players.find(p => p.id === assignedId).color || '')[0]; const myPlayer = room.players.find(p => p.id === assignedId);
const myShort = (myPlayer && myPlayer.color || '')[0];
if(myShort === room.boardState.turn){ if(myShort === room.boardState.turn){
drawCardForPlayer(room, assignedId); const hasHand = room.hands && room.hands[assignedId] && room.hands[assignedId].length > 0;
if(!hasHand) drawCardForPlayer(room, assignedId);
} }
} }
}catch(e){ console.error('post-join draw error', e); } }catch(e){ console.error('post-join draw error', e); }
@ -411,25 +424,26 @@ io.on('connection', (socket) => {
board.version = (board.version || 0) + 1; board.version = (board.version || 0) + 1;
board.turn = (board.turn === 'w') ? 'b' : 'w'; board.turn = (board.turn === 'w') ? 'b' : 'w';
// broadcast move and new board state // at this point the board has been updated and the turn flipped
// determine next player and perform their draw BEFORE broadcasting the move, so the draw happens at the start of their turn
const moved = { playerId: senderId, from, to, boardState: board }; const moved = { playerId: senderId, from, to, boardState: board };
io.to(roomId).emit('move:moved', moved);
// after flipping turn, draw a card for the next player (beginning of their turn)
try{ try{
const nextColor = board.turn; // 'w' or 'b' const nextColor = board.turn; // 'w' or 'b'
const nextPlayer = room.players.find(p => (p.color && p.color[0]) === nextColor); const nextPlayer = room.players.find(p => (p.color && p.color[0]) === nextColor);
if(nextPlayer){ if(nextPlayer){
// attempt to draw a card for them; drawCardForPlayer will emit updated room state if a card was drawn // draw for next player (this will emit card:drawn privately and send personalized room:update)
drawCardForPlayer(room, nextPlayer.id); drawCardForPlayer(room, nextPlayer.id);
} else { } else {
// still emit updated room state (no draw occurred) // ensure room state is broadcast
sendRoomUpdate(room); sendRoomUpdate(room);
} }
}catch(e){ }catch(e){
console.error('draw after move error', e); console.error('draw-at-start-of-turn error', e);
} }
// now broadcast the move to all clients (move event separate from room:update)
io.to(roomId).emit('move:moved', moved);
return cb && cb({ ok: true, moved }); return cb && cb({ ok: true, moved });
}catch(err){ }catch(err){
console.error('game:move error', err); console.error('game:move error', err);
@ -454,12 +468,14 @@ io.on('connection', (socket) => {
sendRoomUpdate(room); sendRoomUpdate(room);
// draw initial card for the player to move (beginning of their turn) // draw initial card for the player to move (beginning of their turn)
// If the player already has a card (for instance the special starter card), skip the automatic draw
try{ try{
if(room.boardState && room.boardState.turn){ if(room.boardState && room.boardState.turn){
const firstColor = room.boardState.turn; // 'w' or 'b' const firstColor = room.boardState.turn; // 'w' or 'b'
const firstPlayer = room.players.find(p => (p.color && p.color[0]) === firstColor); const firstPlayer = room.players.find(p => (p.color && p.color[0]) === firstColor);
if(firstPlayer){ if(firstPlayer){
drawCardForPlayer(room, firstPlayer.id); const hasHand = room.hands && room.hands[firstPlayer.id] && room.hands[firstPlayer.id].length > 0;
if(!hasHand) drawCardForPlayer(room, firstPlayer.id);
} }
} }
}catch(e){ }catch(e){