AI human mode

This commit is contained in:
Michal Vrba
2026-09-03 21:11:25 +02:00
parent 035da18584
commit 9005b4b9be
8 changed files with 1220 additions and 247 deletions
+169 -164
View File
@@ -56,178 +56,160 @@
}
</div>
<!-- Nastavenia pravidiel -->
<div style="font-weight: 700; margin-bottom: 8px; color: var(--gold); font-size: 0.95rem;">
PRAVIDLÁ A NASTAVENIA:
</div>
<div class="rules-toggle-grid">
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.StackSevens" />
<span>Kumulácia sediem (+3, +6, +9...)</span>
</label>
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.CounterAceWithAce" />
<span>Prebíjanie esa esom</span>
</label>
<div style="grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; background: rgba(255, 23, 68, 0.08); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(255, 23, 68, 0.25); gap: 12px;">
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 1.1rem;">❤️</span>
<div>
<div style="font-weight: 700; color: #ff5252;">Červená sedma (Oživenie / Resurrect)</div>
<div style="font-size: 0.76rem; color: #94a3b8;">Spôsob vrátenia skončeného hráča späť do hry</div>
<!-- Nastavenia pravidiel (Collapsible - by default schované) -->
<div style="margin-bottom: 18px;">
<div class="lobby-accordion-header @(ShowRules ? "open" : "")" @onclick="() => ShowRules = !ShowRules">
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
<span style="font-size: 1.15rem;">⚙️</span>
<span style="font-weight: 800; color: var(--gold); font-size: 0.95rem; letter-spacing: 0.5px;">
PRAVIDLÁ A NASTAVENIA HRY
</span>
@if (!ShowRules)
{
<span class="badge-rules-summary">
@(Rules.InitialCardCount) kariet • Sedmy (+3) • @(Rules.SpeedLevel)x Rýchlosť
</span>
}
</div>
<div class="accordion-toggle-btn">
<span>@(ShowRules ? "Zbaliť" : "Rozbaliť")</span>
<span class="accordion-arrow">@(ShowRules ? "▲" : "▼")</span>
</div>
</div>
@if (ShowRules)
{
<div class="rules-toggle-grid" style="margin-top: 10px; animation: fadeIn 0.25s ease;">
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.StackSevens" />
<span>Kumulácia sediem (+3, +6, +9...)</span>
</label>
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.CounterAceWithAce" />
<span>Prebíjanie esa esom</span>
</label>
<div style="grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; background: rgba(255, 23, 68, 0.08); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(255, 23, 68, 0.25); gap: 12px;">
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 1.1rem;">❤️</span>
<div>
<div style="font-weight: 700; color: #ff5252;">Červená sedma (Oživenie / Resurrect)</div>
<div style="font-size: 0.76rem; color: #94a3b8;">Spôsob vrátenia skončeného hráča späť do hry</div>
</div>
</div>
<select class="player-setup-select" style="width: auto; min-width: 240px; padding: 4px 10px; font-weight: 600;" @bind="Rules.RedSevenMode">
<option value="@RedSevenMode.AnyCardOneRound">⚡ Voľná na čokoľvek (do 1 kola)</option>
<option value="@RedSevenMode.ColorOrSevenThreeRounds">🎴 Klasická na Srdce/7 (do 3 kôl)</option>
<option value="@RedSevenMode.Disabled">❌ Vypnuté (Bez oživenia)</option>
</select>
</div>
<div style="grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; background: rgba(45, 106, 79, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(45, 106, 79, 0.35); gap: 12px;">
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 1.1rem;">🍃</span>
<div>
<div style="font-weight: 700; color: #52b788;">Zelený dolník (Rušenie sediem)</div>
<div style="font-size: 0.76rem; color: #94a3b8;">Zelený dolník zruší trest zo sedmy & pravidlá vykladania</div>
</div>
</div>
<select class="player-setup-select" style="width: auto; min-width: 240px; padding: 4px 10px; font-weight: 600;" @bind="Rules.GreenUnderKnaveMode">
<option value="@GreenUnderKnaveMode.OnlyOnSevenOrUnderKnave">🌿 Ruší sedmy (Zeleň / Dolník)</option>
<option value="@GreenUnderKnaveMode.UniversalWildcard">✨ Voľný na čokoľvek + čokoľvek naňho</option>
<option value="@GreenUnderKnaveMode.Disabled">❌ Vypnuté (Bez rušenia sediem)</option>
</select>
</div>
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.FourOfAKindBurns" />
<span>Spálenie (4 rovnaké karty)</span>
</label>
<label class="rule-check-item" style="grid-column: 1 / -1; background: rgba(245, 176, 65, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(245, 176, 65, 0.3);">
<input type="checkbox" @bind="Rules.OlympicMode" />
<span style="font-weight: 800; color: var(--gold);">🏅 Olympijský Faraón (Turnajový režim)</span>
<span style="font-size: 0.8rem; color: #94a3b8; margin-left: 6px;">— porazený má v ďalšom kole o 1 kartu menej</span>
</label>
<label class="rule-check-item" style="grid-column: 1 / -1; background: rgba(56, 189, 248, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(56, 189, 248, 0.35);">
<input type="checkbox" @bind="Rules.AIHumanMode" />
<span style="font-weight: 800; color: #38bdf8;">🤖💭 AI Human Mode (Premýšľacie bubliny & hlášky)</span>
<span style="font-size: 0.8rem; color: #94a3b8; margin-left: 6px;">— boti hovoria svoje myšlienky, blufujú a reagujú na hru</span>
</label>
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
<span>Počiatočný počet kariet:</span>
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.InitialCardCount">
<option value="4">4 karty</option>
<option value="5">5 kariet</option>
<option value="6">6 kariet</option>
</select>
</div>
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
<span>Rýchlosť hry:</span>
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.SpeedLevel">
<option value="-5">🐢 -5 (0.2x Zen / Extra pomalá)</option>
<option value="-4">🐢 -4 (0.35x Veľmi pomalá)</option>
<option value="-3">🚶 -3 (0.5x Pomalá)</option>
<option value="-2">🚶 -2 (0.65x Pokojná)</option>
<option value="-1">🍃 -1 (0.8x Zvoľnená)</option>
<option value="0">⚡ 0 (1x Normálna / Vyvážená)</option>
<option value="1">🔥 +1 (1.25x Svižná)</option>
<option value="2">🔥 +2 (1.5x Rýchla)</option>
<option value="3">🚀 +3 (2x Veľmi rýchla)</option>
<option value="4">🚀 +4 (2.75x Turbo)</option>
<option value="5">⚡ +5 (4x Blesková)</option>
</select>
</div>
</div>
<select class="player-setup-select" style="width: auto; min-width: 240px; padding: 4px 10px; font-weight: 600;" @bind="Rules.RedSevenMode">
<option value="@RedSevenMode.AnyCardOneRound">⚡ Voľná na čokoľvek (do 1 kola)</option>
<option value="@RedSevenMode.ColorOrSevenThreeRounds">🎴 Klasická na Srdce/7 (do 3 kôl)</option>
<option value="@RedSevenMode.Disabled">❌ Vypnuté (Bez oživenia)</option>
</select>
</div>
<div style="grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; background: rgba(45, 106, 79, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(45, 106, 79, 0.35); gap: 12px;">
<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 1.1rem;">🍃</span>
<div>
<div style="font-weight: 700; color: #52b788;">Zelený dolník (Rušenie sediem)</div>
<div style="font-size: 0.76rem; color: #94a3b8;">Zelený dolník zruší trest zo sedmy & pravidlá vykladania</div>
</div>
</div>
<select class="player-setup-select" style="width: auto; min-width: 240px; padding: 4px 10px; font-weight: 600;" @bind="Rules.GreenUnderKnaveMode">
<option value="@GreenUnderKnaveMode.OnlyOnSevenOrUnderKnave">🌿 Ruší sedmy (Zeleň / Dolník)</option>
<option value="@GreenUnderKnaveMode.UniversalWildcard">✨ Voľný na čokoľvek + čokoľvek naňho</option>
<option value="@GreenUnderKnaveMode.Disabled">❌ Vypnuté (Bez rušenia sediem)</option>
</select>
</div>
<label class="rule-check-item">
<input type="checkbox" @bind="Rules.FourOfAKindBurns" />
<span>Spálenie (4 rovnaké karty)</span>
</label>
<label class="rule-check-item" style="grid-column: 1 / -1; background: rgba(245, 176, 65, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(245, 176, 65, 0.3);">
<input type="checkbox" @bind="Rules.OlympicMode" />
<span style="font-weight: 800; color: var(--gold);">🏅 Olympijský Faraón (Turnajový režim)</span>
<span style="font-size: 0.8rem; color: #94a3b8; margin-left: 6px;">— porazený má v ďalšom kole o 1 kartu menej</span>
</label>
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
<span>Počiatočný počet kariet:</span>
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.InitialCardCount">
<option value="4">4 karty</option>
<option value="5">5 kariet</option>
<option value="6">6 kariet</option>
</select>
</div>
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
<span>Rýchlosť hry:</span>
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.SpeedLevel">
<option value="1">🐢 0.5x (Pomalá)</option>
<option value="2">🚶 0.75x (Pokojná)</option>
<option value="3">⚡ 1x (Normálna - štandard)</option>
<option value="4">🔥 1.5x (Rýchla)</option>
<option value="5">🚀 2.5x (Turbo / Blesková)</option>
</select>
</div>
}
</div>
<!-- Výber balíčka kariet (Deck Theme) -->
<!-- Výber balíčka kariet (Collapsible - by default iba zvolený deck) -->
<div style="margin-bottom: 24px;">
<h3 style="font-size: 1.05rem; color: var(--gold); margin-bottom: 12px; text-transform: uppercase; letter-spacing: 1px;">
🎨 Vizuálny štýl balíčka kariet
</h3>
<div class="deck-selector-grid">
<div class="deck-option-card @(Rules.SelectedDeck == "original" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "original"'>
<div class="deck-preview-img-box">
<img src="assets/cards/original/Hearts_Seven.webp" class="deck-preview-thumb" alt="Original Mariáš" />
<img src="assets/cards/original/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Tradičný Mariáš 🎴</div>
<div class="deck-desc">Autentický dvojhlavý Tell vzor (Piatnik)</div>
</div>
<div class="lobby-accordion-header @(ShowDeckSelector ? "open" : "")" @onclick="() => ShowDeckSelector = !ShowDeckSelector">
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
<span style="font-size: 1.15rem;">🎨</span>
<span style="font-weight: 800; color: var(--gold); font-size: 0.95rem; letter-spacing: 0.5px;">
VIZUÁLNY ŠTÝL BALÍČKA
</span>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "janosik" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "janosik"'>
<div class="deck-preview-img-box">
<img src="assets/cards/janosik/Hearts_King.webp" class="deck-preview-thumb" alt="Zbojníci" />
<img src="assets/cards/janosik/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Zbojníci & Legendy 🪓</div>
<div class="deck-desc">Jánošík, Uhorčík, výšivky a tatranský folklór</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "spongebob" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "spongebob"'>
<div class="deck-preview-img-box">
<img src="assets/cards/spongebob/Hearts_OverKnave.webp" class="deck-preview-thumb" alt="SpongeBob Cartoon" />
<img src="assets/cards/spongebob/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">SpongeBob Cartoon 🧽</div>
<div class="deck-desc">Bikini Bottom edícia (postavičky a veľké symboly)</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "cyberpunk" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "cyberpunk"'>
<div class="deck-preview-img-box">
<img src="assets/cards/cyberpunk/Leaves_King.webp" class="deck-preview-thumb" alt="Cyberpunk 2077" />
<img src="assets/cards/cyberpunk/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Cyberpunk 2077 ⚡</div>
<div class="deck-desc">Neónový holografický štýl a kybernetickí hrdinovia</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "fantasy" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "fantasy"'>
<div class="deck-preview-img-box">
<img src="assets/cards/fantasy/Acorns_OverKnave.webp" class="deck-preview-thumb" alt="Fantasy RPG" />
<img src="assets/cards/fantasy/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Fantasy RPG 🐉</div>
<div class="deck-desc">Dračí lordi, mágovia, runy a rytieri</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "egypt" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "egypt"'>
<div class="deck-preview-img-box">
<img src="assets/cards/egypt/Bells_King.webp" class="deck-preview-thumb" alt="Staroveký Egypt" />
<img src="assets/cards/egypt/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Staroveký Egypt ⚔️</div>
<div class="deck-desc">Zlatý papyrus, Tutanchamón, Anubis a pyramídy</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "pets" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "pets"'>
<div class="deck-preview-img-box">
<img src="assets/cards/pets/Hearts_OverKnave.webp" class="deck-preview-thumb" alt="Kráľovské zvieratká" />
<img src="assets/cards/pets/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Kráľovské Zvieratká 🐱</div>
<div class="deck-desc">Mačičky a psíkovia v kráľovských korunkách</div>
</div>
</div>
<div class="deck-option-card @(Rules.SelectedDeck == "pixel" ? "selected-deck" : "")"
@onclick='() => Rules.SelectedDeck = "pixel"'>
<div class="deck-preview-img-box">
<img src="assets/cards/pixel/Leaves_Seven.webp" class="deck-preview-thumb" alt="Retro Pixel" />
<img src="assets/cards/pixel/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">Retro 8-Bit Pixel 🕹️</div>
<div class="deck-desc">Nostalgický arkádový štýl klasických hier</div>
</div>
<div class="accordion-toggle-btn">
<span>@(ShowDeckSelector ? "Zavrieť galériu" : "Zmeniť balíček")</span>
<span class="accordion-arrow">@(ShowDeckSelector ? "▲" : "▼")</span>
</div>
</div>
<!-- Aktuálne zvolený balíček (Default náhľad po kliknutí rozbalí výber) -->
<div class="selected-deck-summary-card" @onclick="() => ShowDeckSelector = !ShowDeckSelector" title="Klikni pre výber a zmenu balíčka kariet">
<div class="deck-preview-img-box">
<img src="@CurrentDeck.Thumb" class="deck-preview-thumb" alt="@CurrentDeck.Name" />
<img src="@CurrentDeck.Back" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info" style="flex: 1;">
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
<span class="deck-name" style="color: var(--gold); font-size: 0.98rem;">@CurrentDeck.Name</span>
<span class="badge-active-deck">Vybraný</span>
</div>
<div class="deck-desc">@CurrentDeck.Desc</div>
</div>
<div class="btn-deck-change-action">
@(ShowDeckSelector ? "▲ Skryť" : "🎨 Zmeniť štýl ▾")
</div>
</div>
@if (ShowDeckSelector)
{
<div class="deck-selector-grid" style="margin-top: 12px; animation: fadeIn 0.25s ease;">
@foreach (var d in AvailableDecks)
{
<div class="deck-option-card @(Rules.SelectedDeck == d.Id ? "selected-deck" : "")"
@onclick="() => SelectDeck(d.Id)">
<div class="deck-preview-img-box">
<img src="@d.Thumb" class="deck-preview-thumb" alt="@d.Name" />
<img src="@d.Back" class="deck-preview-thumb-back" alt="Rub" />
</div>
<div class="deck-info">
<div class="deck-name">@d.Name</div>
<div class="deck-desc">@d.Desc</div>
</div>
</div>
}
</div>
}
</div>
<!-- Štart tlačidlo -->
@@ -244,6 +226,29 @@
private int SelectedPlayerCount = 4;
private RuleOptions Rules = new();
private bool ShowRules = false;
private bool ShowDeckSelector = false;
private record DeckInfo(string Id, string Name, string Desc, string Thumb, string Back);
private readonly DeckInfo[] AvailableDecks = new[]
{
new DeckInfo("original", "Tradičný Mariáš 🎴", "Autentický dvojhlavý Tell vzor (Piatnik)", "assets/cards/original/Hearts_Seven.webp", "assets/cards/original/Card_Back.webp"),
new DeckInfo("janosik", "Zbojníci & Legendy 🪓", "Jánošík, Uhorčík, výšivky a tatranský folklór", "assets/cards/janosik/Hearts_King.webp", "assets/cards/janosik/Card_Back.webp"),
new DeckInfo("spongebob", "SpongeBob Cartoon 🧽", "Bikini Bottom edícia (postavičky a veľké symboly)", "assets/cards/spongebob/Hearts_OverKnave.webp", "assets/cards/spongebob/Card_Back.webp"),
new DeckInfo("cyberpunk", "Cyberpunk 2077 ⚡", "Neónový holografický štýl a kybernetickí hrdinovia", "assets/cards/cyberpunk/Leaves_King.webp", "assets/cards/cyberpunk/Card_Back.webp"),
new DeckInfo("fantasy", "Fantasy RPG 🐉", "Dračí lordi, mágovia, runy a rytieri", "assets/cards/fantasy/Acorns_OverKnave.webp", "assets/cards/fantasy/Card_Back.webp"),
new DeckInfo("egypt", "Staroveký Egypt ⚔️", "Zlatý papyrus, Tutanchamón, Anubis a pyramídy", "assets/cards/egypt/Bells_King.webp", "assets/cards/egypt/Card_Back.webp"),
new DeckInfo("pets", "Kráľovské Zvieratká 🐱", "Mačičky a psíkovia v kráľovských korunkách", "assets/cards/pets/Hearts_OverKnave.webp", "assets/cards/pets/Card_Back.webp"),
new DeckInfo("pixel", "Retro 8-Bit Pixel 🕹️", "Nostalgický arkádový štýl klasických hier", "assets/cards/pixel/Leaves_Seven.webp", "assets/cards/pixel/Card_Back.webp")
};
private DeckInfo CurrentDeck => AvailableDecks.FirstOrDefault(d => d.Id == Rules.SelectedDeck) ?? AvailableDecks[0];
private void SelectDeck(string deckId)
{
Rules.SelectedDeck = deckId;
}
private readonly string[] Avatars = ["👑", "🧙‍♂️", "🦊", "🦁", "🐯", "🤖", "🐉", "🥷", "👸", "🤠", "🦅", "🐺"];
+10
View File
@@ -75,6 +75,14 @@
</span>
</div>
}
@if (!string.IsNullOrEmpty(ThoughtBubble))
{
<div class="ai-thought-bubble @PositionClass @(IsThoughtFadingOut ? "fading-out" : "")">
<span class="thought-bubble-prefix">💭</span>
<span class="thought-bubble-text">@ThoughtBubble</span>
</div>
}
</div>
<!-- Mini karty pre vizuálny odpočet kariet v ruke -->
@@ -96,6 +104,8 @@
[Parameter] public bool CanBeRevived { get; set; } = false;
[Parameter] public int ReviveRoundsRemaining { get; set; } = 0;
[Parameter] public int ReviveTurnsRemaining { get; set; } = 0;
[Parameter] public string? ThoughtBubble { get; set; }
[Parameter] public bool IsThoughtFadingOut { get; set; } = false;
[Parameter] public bool IsOlympicMode { get; set; } = false;
[Parameter] public string PositionClass { get; set; } = "slot-top";
}