From 5d330a57fd8fd9172d1a544f2b513ff05778c487 Mon Sep 17 00:00:00 2001 From: Didictateur Date: Sat, 22 Nov 2025 21:01:33 +0100 Subject: [PATCH] repenser les actions --- assets/img/bomb.jpg | Bin 0 -> 95300 bytes public/game.html | 143 +++++++++++++++++++++++++++++++++++++++- public/styles/style.css | 42 ++++++++++++ server.js | 63 +++++++++++++++++- 4 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 assets/img/bomb.jpg diff --git a/assets/img/bomb.jpg b/assets/img/bomb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..12770c659edee68521301102615ea07f854f85ff GIT binary patch literal 95300 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 C>YfMy literal 0 HcmV?d00001 diff --git a/public/game.html b/public/game.html index 61eda5b..7dbaf94 100644 --- a/public/game.html +++ b/public/game.html @@ -53,6 +53,8 @@ const remoteMoves = {}; // current boardState cached locally let currentBoardState = null; + let myMines = []; + let pendingCard = null; // when set, next square click is used as card target // safe logger: prefer on-page log if present, otherwise console function log(...args){ @@ -66,6 +68,18 @@ } } + // helper: decide if a card requires a target selected after clicking 'Jouer' + function cardRequiresTarget(cardId){ + if(!cardId) return null; + const id = String(cardId).toLowerCase(); + if(id.indexOf('mine') !== -1) return 'empty'; + if(id.indexOf('rebond') !== -1) return 'owned'; + if(id.indexOf('adoub') !== -1) return 'owned'; + if(id.indexOf('folie') !== -1 || id.indexOf('fou') !== -1) return 'owned'; + if(id.indexOf('fortif') !== -1 || id.indexOf('fortification') !== -1) return 'owned'; + return null; + } + if(!roomId){ alert('roomId manquant dans l\'URL'); } function connectAndJoin(){ @@ -95,6 +109,10 @@ renderBoardFromState(data.boardState); updateTurnBanner(data.boardState); } + // store mines owned by this client (private) + try{ myMines = data.minesOwn || []; }catch(e){ myMines = []; } + // after rendering the board, render mines for owner + try{ renderMines(); }catch(e){ } // render hands: prefer new private `handsOwn` + `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){ @@ -353,6 +371,28 @@ const square = sqEl.getAttribute('data-square'); if(!square) return; + // If we're in a pending card-targeting mode, handle target selection and do NOT attempt moves + if(pendingCard){ + const req = pendingCard.requireType; // 'empty' or 'owned' + if(req === 'empty'){ + const occupied = currentBoardState && Array.isArray(currentBoardState.pieces) && currentBoardState.pieces.find(p => p.square === square); + if(occupied){ log('square not empty for mine placement'); return; } + } else if(req === 'owned'){ + const piece = currentBoardState && Array.isArray(currentBoardState.pieces) && currentBoardState.pieces.find(p => p.square === square); + const myShort = (myColor && myColor[0]) || ''; + if(!piece || piece.color !== myShort){ log('select one of your pieces'); return; } + } + // send card:play with targetSquare + socket.emit('card:play', { roomId, playerId: myPlayerId, cardId: pendingCard.cardId, payload: { targetSquare: square } }, (resp)=>{ + if(resp && resp.error){ log('card:play error', resp); alert(resp.error); } + else { log('card played with target', resp); } + }); + // clear pending state and highlights + pendingCard = null; + clearTargetHighlights(); + return; + } + // If this square contains a move-marker (either clicked marker or square area), attempt the move. // Prefer the actual clicked marker if present, otherwise look for a marker element inside the square. const clickedMarker = ev.target.closest && ev.target.closest('.move-marker'); @@ -381,8 +421,12 @@ return; } - // default: clicked empty square -> clear selection - clearSelection(); + // default: clicked empty square -> select it (toggle) + if(selectedSquare === square){ + clearSelection(); + } else { + setSelection(square); + } }); } @@ -428,6 +472,89 @@ Object.entries(remoteMoves).forEach(([pid, moves]) => { if(Array.isArray(moves) && moves.length) showRemoteLegalMoves(pid, moves); }); + // render any mines owned by this player + try{ renderMines(); }catch(e){ } + } + + // draw mine icons on squares for mines owned by this client + function renderMines(){ + if(!boardEl) return; + // remove old mine markers + // remove old mine markers (either image or dot) + const prev = boardEl.querySelectorAll('.mine-dot, .mine-img'); + prev.forEach(p=>p.remove()); + (myMines || []).forEach(sq => { + const el = boardEl.querySelector(`.square[data-square="${sq}"]`); + if(!el) return; + // create an image element so the mine has a transparent background and crisp edges + const img = document.createElement('img'); + img.className = 'mine-img'; + // use a project asset (SVG) that has a transparent background + img.src = '/assets/img/bomb.jpg'; + img.draggable = false; + // ensure container is positioned so absolute centering works + if(!el.style.position) el.style.position = 'relative'; + el.appendChild(img); + }); + } + + // target highlighting helpers + function clearTargetHighlights(){ + if(!boardEl) return; + const prev = boardEl.querySelectorAll('.square.targetable'); + prev.forEach(p=>p.classList.remove('targetable')); + const note = document.getElementById('pendingNote'); if(note) note.remove(); + } + function highlightTargets(type){ + if(!boardEl || !currentBoardState) return; + clearTargetHighlights(); + const myShort = (myColor && myColor[0]) || ''; + Array.from(boardEl.querySelectorAll('.square')).forEach(sqEl => { + const sq = sqEl.getAttribute('data-square'); + if(!sq) return; + if(type === 'empty'){ + const occ = (currentBoardState.pieces||[]).find(p=>p.square===sq); + if(!occ) sqEl.classList.add('targetable'); + } else if(type === 'owned'){ + const occ = (currentBoardState.pieces||[]).find(p=>p.square===sq); + if(occ && occ.color === myShort) sqEl.classList.add('targetable'); + } + }); + // add a small note near hands + try{ + const handsEl = document.getElementById('hands'); + if(handsEl){ + const note = document.createElement('div'); + note.id = 'pendingNote'; + note.style.marginTop = '8px'; + note.style.display = 'flex'; + note.style.alignItems = 'center'; + note.style.gap = '8px'; + const txt = document.createElement('span'); + txt.textContent = 'Sélectionnez la case cible pour la carte...'; + txt.style.fontWeight = '700'; + note.appendChild(txt); + const cancelBtn = document.createElement('button'); + cancelBtn.type = 'button'; + cancelBtn.id = 'pendingCancelBtn'; + cancelBtn.textContent = 'Annuler'; + // use a dedicated class to ensure good contrast against the hands background + cancelBtn.className = 'btn-cancel'; + cancelBtn.addEventListener('click', (ev)=>{ ev.stopPropagation(); cancelPendingCard(); }); + note.appendChild(cancelBtn); + handsEl.prepend(note); + } + }catch(e){} + } + + // cancel a pending card selection (client-only) + function cancelPendingCard(){ + if(!pendingCard) return; + pendingCard = null; + clearTargetHighlights(); + log('Pending card selection annulée'); + // remove pendingNote if present + const note = document.getElementById('pendingNote'); if(note) note.remove(); } // build grid with independent square elements and data-square attributes @@ -503,7 +630,17 @@ function emitPlay(){ if(!socket) return; const cid = cardEl.dataset.cardId; - socket.emit('card:play', { roomId, playerId: myPlayerId, cardId: cid, payload: {} }, (resp)=>{ + const requireType = cardRequiresTarget(cid); + if(requireType){ + // enter pending target mode: next square click will send the card with payload.targetSquare + pendingCard = { cardId: cid, cardUuid: cardEl.dataset.cardUuid || '', requireType }; + highlightTargets(requireType); + log('Pending card selection for', cid, '-> select target'); + return; + } + // immediate-play card (no target required) + const payload = {}; + socket.emit('card:play', { roomId, playerId: myPlayerId, cardId: cid, payload }, (resp)=>{ if(resp && resp.error){ log('card:play error', resp); alert(resp.error); } else { log('card played', resp); } }); diff --git a/public/styles/style.css b/public/styles/style.css index 364ed12..b5063cc 100644 --- a/public/styles/style.css +++ b/public/styles/style.css @@ -63,6 +63,36 @@ a:hover{text-decoration:underline} } .square .move-marker:hover{ transform:translate(-50%,-50%) scale(1.12); opacity:0.95 } +/* square highlight when selecting a target for a card: a small hollow ring strictly inside the square */ +.square.targetable{ outline: none; box-shadow: none; } +.square.targetable::after{ + content: ''; + position: absolute; + left: 50%; top: 50%; transform: translate(-50%, -50%); + width: 36%; height: 36%; border-radius: 50%; + border: 2px solid rgba(234,88,12,0.95); + box-shadow: 0 2px 6px rgba(234,88,12,0.12) inset; + pointer-events: none; z-index: 3; +} + +/* small circular mine marker strictly inside the square */ +.square .mine-dot{ + position:absolute; + left:50%; top:50%; transform:translate(-50%,-50%); + width:36%; height:36%; border-radius:50%; + background: radial-gradient(circle at 30% 30%, #ffdfe0 0%, #ff6b6b 30%, #b91c1c 100%); + box-shadow: inset 0 2px 6px rgba(255,255,255,0.25), 0 2px 6px rgba(0,0,0,0.25); + pointer-events:none; z-index:2; +} + +/* image-based mine: prefer SVG with transparent background for crisp edges */ +.square .mine-img{ + position:absolute; + left:50%; top:50%; transform:translate(-50%,-50%); + width:40%; height:auto; max-height:42%; + pointer-events:none; z-index:2; image-rendering: -webkit-optimize-contrast; +} + /* highlighted/selected square when a player selects a piece */ .square.selected{ outline: 3px solid rgba(245,158,11,0.95); /* amber */ @@ -112,6 +142,18 @@ a:hover{text-decoration:underline} .btn-ghost{background:transparent;border:1px solid rgba(11,18,32,0.06);padding:8px 10px;border-radius:8px;color:inherit} .btn-cta{background:linear-gradient(90deg,#3b82f6,#60a5fa);box-shadow:0 8px 20px rgba(59,130,246,0.18)} +/* cancel button shown during pending card selection: white background, red text for clear contrast */ +.btn-cancel{ + background: #ffffff; + color: #b91c1c; /* red */ + border: 1px solid rgba(185,28,28,0.14); + padding: 6px 8px; + border-radius: 6px; + cursor: pointer; + font-weight: 700; +} +.btn-cancel:hover{ background: #fff5f5; } + /* floating small piece icons */ .floating-piece{position:absolute;opacity:0.06;width:160px;height:160px;pointer-events:none;transform:translate(-10%,-10%);} diff --git a/server.js b/server.js index f5a7855..43d5bc9 100644 --- a/server.js +++ b/server.js @@ -43,6 +43,11 @@ function sendRoomUpdate(room){ // attach visible squares for this recipient (fog of war) try{ payload.visibleSquares = Array.from(visibleSquaresForPlayer(room, p.id) || []); + // attach any mines owned by this recipient (mines are hidden from other players) + try{ + const mines = (room.activeCardEffects || []).filter(e => e.type === 'mine' && e.playerId === p.id).map(e => e.square); + payload.minesOwn = mines; + }catch(_){ payload.minesOwn = []; } }catch(e){ payload.visibleSquares = []; } if(p.socketId){ io.to(p.socketId).emit('room:update', payload); @@ -101,7 +106,7 @@ function buildDefaultDeck(){ // ['trou de ver','Deux cases du plateau deviennent maintenant la même'], ['jouer deux fois','Le joueur peut déplacer deux pièces'], // ['annulation d une carte','Annule l effet d une carte qui est jouée par l adversaire'], - // ['placement de mines','Le joueur place une mine sur une case vide sans la révéler au joueur adverse. Une pièce qui se pose dessus explose et est capturée par le joueur ayant placé la mine'], + ['placement de mines','Le joueur place une mine sur une case vide sans la révéler au joueur adverse. Une pièce qui se pose dessus explose et est capturée par le joueur ayant placé la mine'], // ['vole d une pièce','Désigne une pièce non roi qui change de camp'], // ['promotion','Un pion au choix est promu reine'], // ['vole d une carte','Vole une carte aléatoirement au joueur adverse'], @@ -687,6 +692,32 @@ io.on('connection', (socket) => { } }catch(e){ console.error('consuming card effects error', e); } + // Check for hidden mines at the destination square. If a mine belonging to another player + // is present, detonate it: remove the moving piece and consume the mine. The mine location + // is kept private (only the owner sees it in their `minesOwn`), but detonations are public. + try{ + room.activeCardEffects = room.activeCardEffects || []; + for(let i = room.activeCardEffects.length - 1; i >= 0; i--){ + const e = room.activeCardEffects[i]; + if(e && e.type === 'mine' && e.square === to){ + // owner is immune to their own mine (assumption). Only detonate for other players. + if(e.playerId !== senderId){ + // remove the moving piece from the board + const rmIdx = pieces.findIndex(p => p.id === moving.id); + if(rmIdx >= 0){ pieces.splice(rmIdx, 1); } + // consume the mine + try{ room.activeCardEffects.splice(i,1); }catch(_){ } + // broadcast detonation to the room (informational) + try{ io.to(roomId).emit('mine:detonated', { roomId: room.id, ownerId: e.playerId, detonatorId: senderId, square: to, piece: moving }); }catch(_){ } + // privately inform the owner as well with effect id and piece details + try{ const owner = (room.players||[]).find(p => p.id === e.playerId); if(owner && owner.socketId) io.to(owner.socketId).emit('mine:detonated:private', { roomId: room.id, effectId: e.id, square: to, piece: moving }); }catch(_){ } + } + // a mine was found/handled; break (only one mine per square expected) + break; + } + } + }catch(err){ console.error('mine detonation error', err); } + // advance board version board.version = (board.version || 0) + 1; @@ -1127,6 +1158,36 @@ io.on('connection', (socket) => { played.payload = Object.assign({}, payload, { applied: 'anneau' }); }catch(e){ console.error('anneau effect error', e); } } + // placement de mines: place a hidden mine on an empty square (hidden from other players) + else if((typeof cardId === 'string' && cardId.indexOf('mine') !== -1)){ + try{ + const board = room.boardState; + let target = payload && payload.targetSquare; + if(!target){ try{ target = socket.data && socket.data.lastSelectedSquare; }catch(e){ target = null; } } + // validate board and empty target + const targetOccupied = (board && board.pieces || []).find(p => p.square === target); + if(!board || !target || targetOccupied){ + // Invalid target: the card is still consumed (player loses the card as requested). + // We do not restore the removed card to the player's hand. Record in played payload that the placement failed. + played.payload = Object.assign({}, payload, { applied: 'mine_failed', attemptedTo: target }); + // Notify only the owner that the card was used but the mine was not placed + try{ const owner = (room.players || []).find(p => p.id === senderId); if(owner && owner.socketId) io.to(owner.socketId).emit('card:effect:applied', { roomId: room.id, effect: { id: played.id, type: 'mine_failed', playerId: senderId, square: target, ts: Date.now() } }); }catch(_){ } + // continue without creating a mine + } else { + // record mine effect scoped to the player; do NOT broadcast location to other players + room.activeCardEffects = room.activeCardEffects || []; + const effect = { id: played.id, type: 'mine', playerId: senderId, square: target, ts: Date.now() }; + room.activeCardEffects.push(effect); + // notify only the owner about the mine placement (keep it hidden from opponents) + try{ + const owner = (room.players || []).find(p => p.id === senderId); + if(owner && owner.socketId) io.to(owner.socketId).emit('card:effect:applied', { roomId: room.id, effect }); + }catch(_){ } + // for the public played record we mark the card as used without revealing the square + played.payload = Object.assign({}, payload, { applied: 'mine' }); + } + }catch(e){ console.error('mine placement error', e); } + } // jouer deux fois: grant the playing player one extra move this turn (does not allow another card play) else if(cardId === 'jouer_deux_fois' || (typeof cardId === 'string' && cardId.indexOf('jouer') !== -1 && cardId.indexOf('deux') !== -1)){ try{