la parrure

This commit is contained in:
Didictateur 2025-11-23 13:00:49 +01:00
parent 95bef7ea51
commit 72d096f0e5
2 changed files with 42 additions and 1 deletions

View file

@ -96,6 +96,8 @@
if(id.indexOf('mine') !== -1) return 'empty';
// 'toucher c'est jouer' : require selecting an enemy piece as the card target
if(id.indexOf('toucher') !== -1) return 'enemy';
// la parrure: select an enemy queen to downgrade to a pawn
if(id.indexOf('parrure') !== -1) return 'enemy_queen';
// kamikaz targets one of your pieces (play card, then choose a piece)
if(id.indexOf('kamikaz') !== -1) return 'owned';
if(id.indexOf('invis') !== -1 || id.indexOf('invisible') !== -1) return 'owned';
@ -533,6 +535,17 @@
// keep pendingCard until server response processed (client will call setSelection on success)
pendingCard = null; clearTargetHighlights(); return;
}
else if(req === 'enemy_queen'){
const occ = currentBoardState && Array.isArray(currentBoardState.pieces) && currentBoardState.pieces.find(p => p.square === square);
if(!occ || occ.color === myShort || !occ.type || occ.type.toLowerCase() !== 'q'){ log('select an enemy queen'); return; }
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);
try{ setSelection(square); }catch(_){ }
}
});
pendingCard = null; clearTargetHighlights(); return;
}
}
// If this square contains a move-marker (either clicked marker or square area), attempt the move.
@ -715,6 +728,9 @@
} else if(type === 'owned_pawn'){
const occ = (currentBoardState.pieces||[]).find(p=>p.square===sq);
if(occ && occ.color === myShort && occ.type && occ.type.toLowerCase() === 'p') sqEl.classList.add('targetable');
} else if(type === 'enemy_queen'){
const occ = (currentBoardState.pieces||[]).find(p=>p.square===sq);
if(occ && occ.color && occ.color !== myShort && occ.type && occ.type.toLowerCase() === 'q') sqEl.classList.add('targetable');
} else if(type === 'enemy'){
const occ = (currentBoardState.pieces||[]).find(p=>p.square===sq);
if(occ && occ.color && occ.color !== myShort) sqEl.classList.add('targetable');

View file

@ -182,7 +182,7 @@ function buildDefaultDeck(){
// ['cluster','Désigne 4 pions formant un rectangle. Tant que ces pions ne bougent pas, aucune pièce ne peut sortir ou rentrer dans ce rectangle.'],
// ['vacances','Choisie une pièce qui sort du plateau pendant deux tours. Ce après quoi elle tente de revenir: si la case est occupée, alors la pièce vacancière est capturée par la pièce occupant la case.'],
['mélange','La position de toutes les pièces sont échangées aléatoirement.'],
// ['la parrure','Une reine est dégradée en pion'],
['la parrure','Une reine est dégradée en pion'],
// ['tricherie','Choisis une carte de la pioche parmis trois'],
// ['tout ou rien','Une pièce choisie ne peut maintenant se déplacer que si elle capture.'],
// ['tous les mêmes','Au yeux de l ennemie, toutes les pièces se ressemblent pendant 2 tours.'],
@ -1388,6 +1388,31 @@ io.on('connection', (socket) => {
try{ io.to(room.id).emit('card:effect:applied', { roomId: room.id, effect }); }catch(_){ }
}catch(e){ console.error('toucher effect error', e); }
}
// la parrure: downgrade an enemy queen to a pawn (selected target must be an enemy queen)
else if((typeof cardId === 'string' && cardId.indexOf('parrure') !== -1) || cardId === 'la_parrure'){
try{
const board = room.boardState;
let target = payload && payload.targetSquare;
if(!target){ try{ target = socket.data && socket.data.lastSelectedSquare; }catch(e){ target = null; } }
const roomPlayer = room.players.find(p => p.id === senderId);
const playerColorShort = (roomPlayer && roomPlayer.color && roomPlayer.color[0]) || null;
const targetPiece = (board && board.pieces || []).find(p => p.square === target);
// validate target exists and belongs to the opponent and is a queen
if(!board || !target || !targetPiece || targetPiece.color === playerColorShort || !targetPiece.type || targetPiece.type.toLowerCase() !== 'q'){
// invalid target: do NOT restore the removed card (card is consumed). Return error but card remains in discard.
return cb && cb({ error: 'no valid target' });
}
// perform downgrade: change piece type to pawn
try{
targetPiece.type = 'p';
if(targetPiece.promoted) delete targetPiece.promoted;
// bump board version so clients react to the board mutation
try{ board.version = (board.version || 0) + 1; }catch(_){ }
played.payload = Object.assign({}, payload, { applied: 'parrure', appliedTo: target });
try{ io.to(room.id).emit('card:effect:applied', { roomId: room.id, effect: { id: played.id, type: 'parrure', pieceId: targetPiece.id, pieceSquare: targetPiece.square, playerId: senderId } }); }catch(_){ }
}catch(e){ console.error('parrure apply error', e); }
}catch(e){ console.error('parrure effect error', e); }
}
// teleportation: allow the selected piece to move to any empty square for one turn
else if((typeof cardId === 'string' && (cardId.indexOf('teleport') !== -1 || cardId.indexOf('t_l_portation') !== -1 || cardId.indexOf('t_lportation') !== -1)) || cardId === 'teleport'){
try{