teleportation

This commit is contained in:
Didictateur 2025-11-23 01:06:18 +01:00
parent 3d2bb42aa6
commit ad00592c33
2 changed files with 54 additions and 1 deletions

View file

@ -485,8 +485,13 @@
if(!occ || occ.color === myShort){ log('select an enemy piece'); 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); }
else { log('card played with target', resp);
// after server applied the card effect, request legal moves for the selected piece so the client
// will receive the updated legal moves (including teleport to empty squares)
try{ setSelection(square); }catch(_){ }
}
});
// keep pendingCard until server response processed (client will call setSelection on success)
pendingCard = null; clearTargetHighlights(); return;
}
}

View file

@ -312,6 +312,25 @@ function computeLegalMoves(room, square){
});
}
}catch(_){ }
// detect teleport effect: allow this piece to move to any empty square (one-turn temporary effect)
try{
const hasTeleport = (room.activeCardEffects || []).some(e => e && e.type === 'teleport' && ((e.pieceId && e.pieceId === piece.id) || e.pieceSquare === square));
if(hasTeleport){
// iterate all board squares and add empty ones as legal non-capturing moves
for(let tx = 0; tx < width; tx++){
for(let ty = 0; ty < height; ty++){
const tsq = coordToSquare(tx, ty);
if(!tsq) continue;
// avoid adding the current square
if(tsq === square) continue;
const occ = getPieceAt(tsq);
if(!occ && !moves.some(m => m.to === tsq)){
moves.push({ from: square, to: tsq });
}
}
}
}
}catch(_){ }
// detect if this specific piece has a permanent adoubement effect (grants knight moves)
// effects may be bound either to the piece's current square or to the piece id (preferred)
const hasAdoubement = (room.activeCardEffects || []).some(e => e.type === 'adoubement' && ((e.pieceId && e.pieceId === piece.id) || e.pieceSquare === square));
@ -1212,6 +1231,35 @@ io.on('connection', (socket) => {
room.activeCardEffects.push({ id: played.id, type: 'fortification', pieceId: targetPiece.id, pieceSquare: target, playerId: senderId });
played.payload = Object.assign({}, payload, { applied: 'fortification', appliedTo: target });
}catch(e){ console.error('fortification 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{
const board = room.boardState;
let target = payload && payload.targetSquare;
if(!target){ try{ target = socket.data && socket.data.lastSelectedSquare; }catch(e){ target = null; } }
// validate target exists and belongs to the player
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);
if(!board || !target || !targetPiece || targetPiece.color !== playerColorShort){
// restore removed card to hand and remove from discard if necessary
try{
room.hands = room.hands || {};
room.hands[senderId] = room.hands[senderId] || [];
if(removed) room.hands[senderId].push(removed);
room.discard = room.discard || [];
for(let i = room.discard.length - 1; i >= 0; i--){ if(room.discard[i] && room.discard[i].id === (removed && removed.id)){ room.discard.splice(i,1); break; } }
}catch(e){ console.error('restore removed card error', e); }
return cb && cb({ error: 'no valid target' });
}
// apply a temporary teleport effect bound to the piece id for one owner turn
room.activeCardEffects = room.activeCardEffects || [];
const effect = { id: played.id, type: 'teleport', pieceId: targetPiece.id, pieceSquare: target, playerId: senderId, remainingTurns: 1, decrementOn: 'owner' };
room.activeCardEffects.push(effect);
played.payload = Object.assign({}, payload, { applied: 'teleport', appliedTo: target });
try{ io.to(room.id).emit('card:effect:applied', { roomId: room.id, effect }); }catch(_){ }
}catch(e){ console.error('teleport effect error', e); }
}
// promotion: promote one of your pawns to a queen
else if(cardId === 'promotion' || cardId === 'promote' || (typeof cardId === 'string' && (cardId.indexOf('promotion') !== -1 || cardId.indexOf('promot') !== -1 || cardId.indexOf('promouvoir') !== -1))){