This commit is contained in:
Pavel Flegr 2026-05-07 19:18:47 +02:00
commit 572cfedd56
2 changed files with 23 additions and 10 deletions

View file

@ -71,6 +71,7 @@ The script MUST export these functions (no classes, no imports):
pendingChoices object[] pending choice queue (each has targetPlayerIndex,prompt,options) pendingChoices object[] pending choice queue (each has targetPlayerIndex,prompt,options)
card/topCard suit values: "hearts" | "diamonds" | "spades" | "clubs" card/topCard suit values: "hearts" | "diamonds" | "spades" | "clubs"
user-facing suit naming in this app: hearts=červený, diamonds=zelený, spades=kule, clubs=žaludy
card/topCard value values: "7" | "8" | "9" | "10" | "under" | "upper" | "king" | "ace" card/topCard value values: "7" | "8" | "9" | "10" | "under" | "upper" | "king" | "ace"
onPlayed(cards, state) { onPlayed(cards, state) {
@ -116,6 +117,7 @@ Rules about rules:
- If you need an extra discard, use discardIndex in onPlayed instead of cards.length > 1. - If you need an extra discard, use discardIndex in onPlayed instead of cards.length > 1.
- For advanced custom mechanics you may mutate state directly with playerHands/discardPile/deck/currentPlayerIndex. - For advanced custom mechanics you may mutate state directly with playerHands/discardPile/deck/currentPlayerIndex.
- You may use state.hand, state.handCounts, state.playerCount for hand-inspection rules. - You may use state.hand, state.handCounts, state.playerCount for hand-inspection rules.
- Prefer Czech wording in "description" and use suit names červený/zelený/kule/žaludy in user-facing text.
- Do NOT include markdown fences, comments outside the functions, or any code other than function definitions. - Do NOT include markdown fences, comments outside the functions, or any code other than function definitions.
- Return ONLY valid JSON no prose before or after.` - Return ONLY valid JSON no prose before or after.`

View file

@ -1115,10 +1115,10 @@
<div class="suit-picker"> <div class="suit-picker">
<h2>Vyber barvu</h2> <h2>Vyber barvu</h2>
<div class="suit-grid"> <div class="suit-grid">
<button class="suit-btn red-suit" onclick="pickSuit('hearts')"><span>Srdce</span></button> <button class="suit-btn red-suit" onclick="pickSuit('hearts')"><span>Červený</span></button>
<button class="suit-btn red-suit" onclick="pickSuit('diamonds')"><span>Kára</span></button> <button class="suit-btn black-suit" onclick="pickSuit('diamonds')">🍃<span>Zelený</span></button>
<button class="suit-btn black-suit" onclick="pickSuit('spades')"><span>Piky</span></button> <button class="suit-btn black-suit" onclick="pickSuit('spades')">🔔<span>Kule</span></button>
<button class="suit-btn black-suit" onclick="pickSuit('clubs')"><span>Kříže</span></button> <button class="suit-btn black-suit" onclick="pickSuit('clubs')">🌰<span>Žaludy</span></button>
</div> </div>
</div> </div>
</div> </div>
@ -1205,10 +1205,10 @@ let tableVisible = false;
let currentScriptOpen = false; let currentScriptOpen = false;
let lobbyPollTimer = null; let lobbyPollTimer = null;
const SUIT_ICONS = { hearts:'♥', diamonds:'♦', spades:'♠', clubs:'♣' }; const SUIT_ICONS = { hearts:'♥', diamonds:'🍃', spades:'🔔', clubs:'🌰' };
const SUIT_NAMES = { hearts:'Srdce', diamonds:'Kára', spades:'Piky', clubs:'Kříže' }; const SUIT_NAMES = { hearts:'Červený', diamonds:'Zelený', spades:'Kule', clubs:'Žaludy' };
const SUIT_COLOR = { hearts:'red', diamonds:'red', spades:'black', clubs:'black' }; const SUIT_COLOR = { hearts:'red', diamonds:'black', spades:'black', clubs:'black' };
const VALUE_LABEL = { '7':'7','8':'8','9':'9','10':'10', under:'J', upper:'Q', king:'K', ace:'A' }; const VALUE_LABEL = { '7':'VII','8':'VIII','9':'IX','10':'X', under:'Sp', upper:'Sv', king:'Kr', ace:'Eso' };
// ── WebSocket ────────────────────────────────────────────────────────── // ── WebSocket ──────────────────────────────────────────────────────────
function connect() { function connect() {
@ -1765,15 +1765,26 @@ function renderMyHand() {
} }
const mine = pending.player_id === myId; const mine = pending.player_id === myId;
if (!mine) {
const chooser = gameState.players[pending.player_index || 0];
const chooserName = chooser ? chooser.name : 'soupeře';
zone.innerHTML = `
<div style="margin-top:10px; display:flex; flex-direction:column; gap:6px; align-items:center;">
<div style="font-size:.82rem; color:rgba(255,255,255,.7)">Čeká se na volbu hráče: ${escHtml(chooserName)}</div>
</div>
`;
return;
}
const options = (pending.options || []).map((o) => { const options = (pending.options || []).map((o) => {
const safe = String(o || '').replace(/'/g, "\\'"); const safe = String(o || '').replace(/'/g, "\\'");
return `<button class="btn btn-primary" style="width:auto;min-width:110px;" ${mine ? '' : 'disabled'} onclick="sendChoice('${safe}')">${escHtml(o)}</button>`; return `<button class="btn btn-primary" style="width:auto;min-width:110px;" onclick="sendChoice('${safe}')">${escHtml(o)}</button>`;
}).join(''); }).join('');
zone.innerHTML = ` zone.innerHTML = `
<div style="margin-top:10px; display:flex; flex-direction:column; gap:10px; align-items:center;"> <div style="margin-top:10px; display:flex; flex-direction:column; gap:10px; align-items:center;">
<div style="font-size:.85rem; color:rgba(255,255,255,.85)">${escHtml(pending.prompt || 'Vyber možnost')}</div> <div style="font-size:.85rem; color:rgba(255,255,255,.85)">${escHtml(pending.prompt || 'Vyber možnost')}</div>
<div style="display:flex; gap:8px; flex-wrap:wrap; justify-content:center;">${options}</div> <div style="display:flex; gap:8px; flex-wrap:wrap; justify-content:center;">${options}</div>
<div style="font-size:.75rem; color:rgba(255,255,255,.55)">${mine ? 'Vyber jednu možnost.' : 'Čeká se na volbu soupeře…'}</div> <div style="font-size:.75rem; color:rgba(255,255,255,.55)">Vyber jednu možnost.</div>
</div> </div>
`; `;
} }