carte travesti
This commit is contained in:
parent
9b5ce433e0
commit
3b5f37403c
5 changed files with 212 additions and 2 deletions
BIN
assets/img/cards/travesti.png
Normal file
BIN
assets/img/cards/travesti.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
|
|
@ -386,6 +386,7 @@ logs...</pre
|
|||
if (id.indexOf("medusa") !== -1) return "enemy";
|
||||
if (id.indexOf("parrure") !== -1) return "enemy_queen";
|
||||
if (id.indexOf("tout") !== -1) return "piece";
|
||||
if (id.indexOf("travesti") !== -1) return "piece";
|
||||
if (id.indexOf("kamikaz") !== -1) return "owned";
|
||||
if (id.indexOf("invisible") !== -1) return "owned";
|
||||
if (id.indexOf("rebond") !== -1) return "owned";
|
||||
|
|
@ -2437,6 +2438,8 @@ logs...</pre
|
|||
imgSrc = "/assets/img/cards/medusa.png";
|
||||
if (cid === "cachotier")
|
||||
imgSrc = "/assets/img/cards/cachotier.png";
|
||||
if (cid === "travesti")
|
||||
imgSrc = "/assets/img/cards/travesti.png";
|
||||
|
||||
if (imgSrc) {
|
||||
const img = document.createElement("img");
|
||||
|
|
|
|||
|
|
@ -236,6 +236,8 @@
|
|||
imgSrc = "/assets/img/cards/medusa.png";
|
||||
if (cid === "cachotier")
|
||||
imgSrc = "/assets/img/cards/cachotier.png";
|
||||
if (cid === "travesti")
|
||||
imgSrc = "/assets/img/cards/travesti.png";
|
||||
|
||||
if (imgSrc) {
|
||||
const img = document.createElement("img");
|
||||
|
|
|
|||
|
|
@ -651,6 +651,8 @@
|
|||
imgSrc = "/assets/img/cards/medusa.png";
|
||||
if (cid === "cachotier")
|
||||
imgSrc = "/assets/img/cards/cachotier.png";
|
||||
if (cid === "travesti")
|
||||
imgSrc = "/assets/img/cards/travesti.png";
|
||||
|
||||
if (imgSrc) {
|
||||
const img = document.createElement("img");
|
||||
|
|
|
|||
207
server.js
207
server.js
|
|
@ -253,6 +253,61 @@ function recordPlayerDrewPrev(room, playerId) {
|
|||
} catch (_) {}
|
||||
}
|
||||
|
||||
// Helper: apply travesti effect at the start of each turn
|
||||
// Changes the type of affected pieces randomly to P, N, B, R, or Q
|
||||
function applyTraverstiEffects(room) {
|
||||
try {
|
||||
if (!room || !room.boardState) return;
|
||||
const board = room.boardState;
|
||||
const pieces = board.pieces || [];
|
||||
const effects = room.activeCardEffects || [];
|
||||
const travestiEffects = effects.filter((e) => e && e.type === "travesti");
|
||||
if (!travestiEffects.length) return;
|
||||
|
||||
const possibleTypes = ["P", "N", "B", "R", "Q"];
|
||||
|
||||
travestiEffects.forEach((eff) => {
|
||||
const piece = pieces.find((p) => p.id === eff.pieceId);
|
||||
if (!piece) {
|
||||
// Piece was captured, remove the effect
|
||||
try {
|
||||
room.activeCardEffects = effects.filter((e) => e !== eff);
|
||||
io.to(room.id).emit("card:effect:removed", {
|
||||
roomId: room.id,
|
||||
effectId: eff.id,
|
||||
type: "travesti",
|
||||
playerId: eff.playerId,
|
||||
});
|
||||
} catch (_) {}
|
||||
return;
|
||||
}
|
||||
// Choose a random type different from current (if possible)
|
||||
const currentType = piece.type;
|
||||
const availableTypes = possibleTypes.filter((t) => t !== currentType);
|
||||
const newType = availableTypes[Math.floor(Math.random() * availableTypes.length)];
|
||||
piece.type = newType;
|
||||
|
||||
// Update the effect to track the current type
|
||||
eff.currentType = newType;
|
||||
|
||||
try {
|
||||
io.to(room.id).emit("card:effect:updated", {
|
||||
roomId: room.id,
|
||||
effect: eff,
|
||||
pieceChanged: { pieceId: piece.id, newType, square: piece.square },
|
||||
});
|
||||
} catch (_) {}
|
||||
});
|
||||
|
||||
// Bump version so clients pick up the change
|
||||
try {
|
||||
board.version = (board.version || 0) + 1;
|
||||
} catch (_) {}
|
||||
} catch (e) {
|
||||
console.error("applyTraverstiEffects error", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: at the start of a player's turn, either perform an automatic draw
|
||||
// if room.autoDraw is enabled, or simply broadcast the room state so clients
|
||||
// can update UI. This centralizes the auto-draw toggle behavior.
|
||||
|
|
@ -409,6 +464,10 @@ function endTurnAfterCard(room, senderId) {
|
|||
(p) => (p.color && p.color[0]) === nextColor,
|
||||
);
|
||||
if (nextPlayer) {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} else {
|
||||
sendRoomUpdate(room);
|
||||
|
|
@ -659,17 +718,21 @@ function buildDefaultDeck() {
|
|||
"cachotier"
|
||||
],
|
||||
|
||||
[
|
||||
"Travesti",
|
||||
"La pièce désignée change aléatoirement de type à chaque tour.",
|
||||
"travesti"
|
||||
]
|
||||
|
||||
// facile et intéresssant
|
||||
// ["intrication quantique","Deux pièces sont intriquées. Quand l'une bouge, l'autre bouge de la même manière."],
|
||||
// ['kurby','Choisis une pièce. À sa prochaine capture, récupère tous les mouvements de la pièce capturée.'],
|
||||
|
||||
// ['défausse','Le joueur adverse défausse une carte de son choix'],
|
||||
// ['glue','Toutes les pièces autour de la pièce désignée ne peuvent pas bouger tant que cette dernière ne bouge pas'],
|
||||
// ['immunité à la capture','Désigne une pièce qui ne pourra pas être capturée au prochain tour'],
|
||||
// ['marécage','Pendant X tours, toutes les pièces ne peuvent se déplacer que comme un roi'],
|
||||
// ['tricherie','Choisis une carte de la pioche parmis trois'],
|
||||
// ['trêve','Aucun capture ne peut avoir lieu pendant 4 tours'],
|
||||
// ['traversti','La pièce désignée change aléatoirement de type à chaque tour']
|
||||
// ['pièce berserk','Une pièce choisie doit capturer dans les trois prochains tours, sinon elle est capturée'],
|
||||
|
||||
// moyen facile mais intéressant
|
||||
|
|
@ -2095,6 +2158,10 @@ io.on("connection", (socket) => {
|
|||
(p) => (p.color && p.color[0]) === nextColor,
|
||||
);
|
||||
if (nextPlayer) {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} else {
|
||||
sendRoomUpdate(room);
|
||||
|
|
@ -2552,6 +2619,10 @@ io.on("connection", (socket) => {
|
|||
);
|
||||
if (nextPlayer) {
|
||||
try {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} catch (_) {
|
||||
sendRoomUpdate(room);
|
||||
|
|
@ -2667,6 +2738,8 @@ io.on("connection", (socket) => {
|
|||
typeof cardId === "string" && cardId.indexOf("folie") !== -1;
|
||||
const isFort =
|
||||
typeof cardId === "string" && cardId.indexOf("fortification") !== -1;
|
||||
const isTraversti =
|
||||
typeof cardId === "string" && cardId.indexOf("travesti") !== -1;
|
||||
const isTargetCard = isRebond || isAdoub || isFolie || isFort;
|
||||
if (isTargetCard) {
|
||||
const board = room.boardState;
|
||||
|
|
@ -2702,6 +2775,40 @@ io.on("connection", (socket) => {
|
|||
payload.targetSquare = targetCandidate;
|
||||
played.payload = Object.assign({}, payload);
|
||||
}
|
||||
// travesti: any piece except king
|
||||
if (isTraversti) {
|
||||
const board = room.boardState;
|
||||
let targetCandidate = payload && payload.targetSquare;
|
||||
if (!targetCandidate) {
|
||||
try {
|
||||
targetCandidate = socket.data && socket.data.lastSelectedSquare;
|
||||
} catch (e) {
|
||||
targetCandidate = null;
|
||||
}
|
||||
}
|
||||
const targetPiece = ((board && board.pieces) || []).find(
|
||||
(p) => p.square === targetCandidate,
|
||||
);
|
||||
if (
|
||||
!board ||
|
||||
!targetCandidate ||
|
||||
!targetPiece ||
|
||||
targetPiece.type === "K"
|
||||
) {
|
||||
return (
|
||||
cb &&
|
||||
cb({
|
||||
error: "no valid target",
|
||||
message: targetPiece && targetPiece.type === "K"
|
||||
? "Vous ne pouvez pas cibler un roi."
|
||||
: "Sélectionnez une pièce à affecter.",
|
||||
})
|
||||
);
|
||||
}
|
||||
payload = payload || {};
|
||||
payload.targetSquare = targetCandidate;
|
||||
played.payload = Object.assign({}, payload);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("target card pre-check error", e);
|
||||
}
|
||||
|
|
@ -3816,6 +3923,10 @@ io.on("connection", (socket) => {
|
|||
);
|
||||
if (nextPlayer) {
|
||||
try {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
@ -3995,6 +4106,10 @@ io.on("connection", (socket) => {
|
|||
);
|
||||
if (nextPlayer) {
|
||||
try {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
@ -4739,6 +4854,10 @@ io.on("connection", (socket) => {
|
|||
);
|
||||
if (nextPlayer) {
|
||||
try {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
@ -5113,6 +5232,86 @@ io.on("connection", (socket) => {
|
|||
console.error("cachotier effect error", e);
|
||||
}
|
||||
}
|
||||
|
||||
// travesti
|
||||
else if (cardId === "travesti") {
|
||||
try {
|
||||
const board = room.boardState;
|
||||
let target = payload && payload.targetSquare;
|
||||
if (!target) {
|
||||
try {
|
||||
target = socket.data && socket.data.lastSelectedSquare;
|
||||
} catch (e) {
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
const targetPiece = ((board && board.pieces) || []).find(
|
||||
(p) => p.square === target,
|
||||
);
|
||||
// Must select a piece that is not a king
|
||||
if (
|
||||
!board ||
|
||||
!target ||
|
||||
!targetPiece ||
|
||||
targetPiece.type === "K"
|
||||
) {
|
||||
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",
|
||||
message:
|
||||
targetPiece && targetPiece.type === "K"
|
||||
? "Vous ne pouvez pas cibler un roi."
|
||||
: "Aucune cible valide n'a été sélectionnée.",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
room.activeCardEffects = room.activeCardEffects || [];
|
||||
const effect = {
|
||||
id: played.id,
|
||||
type: "travesti",
|
||||
pieceId: targetPiece.id,
|
||||
pieceSquare: target,
|
||||
originalType: targetPiece.type,
|
||||
currentType: targetPiece.type,
|
||||
playerId: senderId,
|
||||
targetColor: targetPiece.color,
|
||||
ts: Date.now(),
|
||||
};
|
||||
room.activeCardEffects.push(effect);
|
||||
try {
|
||||
io.to(room.id).emit("card:effect:applied", {
|
||||
roomId: room.id,
|
||||
effect,
|
||||
});
|
||||
} catch (_) {}
|
||||
played.payload = Object.assign({}, payload, {
|
||||
applied: "travesti",
|
||||
appliedTo: target,
|
||||
pieceId: targetPiece.id,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("travesti effect error", e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("card:play effect error", e);
|
||||
}
|
||||
|
|
@ -5269,6 +5468,10 @@ io.on("connection", (socket) => {
|
|||
(p) => (p.color && p.color[0]) === nextColor,
|
||||
);
|
||||
if (nextPlayer) {
|
||||
// Apply travesti effect at the start of the new turn
|
||||
try {
|
||||
applyTraverstiEffects(room);
|
||||
} catch (_) {}
|
||||
maybeDrawAtTurnStart(room, nextPlayer.id);
|
||||
} else {
|
||||
sendRoomUpdate(room);
|
||||
|
|
|
|||
Loading…
Reference in a new issue