Files
FaraonCardGame/Faraon.Core/Engine/GameEngine.cs
T
2026-09-04 11:31:52 +02:00

891 lines
31 KiB
C#

namespace Faraon.Core.Engine;
using Faraon.Core.Models;
public class GameEngine
{
private readonly Deck _deckManager;
public GameState State { get; }
public event Action<GameEvent>? OnGameEvent;
public GameEngine(int? seed = null)
{
_deckManager = new Deck(seed);
State = new GameState();
}
public void StartGame(List<Player> players, RuleOptions rules)
{
if (players.Count < 2 || players.Count > 4)
{
throw new ArgumentException("Hra Faraón vyžaduje 2 až 4 hráčov.", nameof(players));
}
State.Players = players;
State.Rules = rules;
State.IsGameOver = false;
State.IsMatchOver = false;
State.IsRoundOver = false;
State.MatchWinner = null;
State.RoundLoser = null;
State.RoundNumber = 1;
State.LastFinishedPlayer = null;
State.ReviveTurnsRemaining = 0;
State.ReviveRoundsRemaining = 0;
State.ReviveWindowInitialTurns = 0;
State.TurnCount = 1;
State.PendingDrawCount = 0;
State.PendingSkip = false;
State.ActiveSuit = null;
State.PendingHornikPlayer = null;
State.TurnState = TurnState.Playing;
foreach (var player in State.Players)
{
player.OlympicCardsCount = State.Rules.InitialCardCount;
player.Reset();
}
// Vytvorenie a zamiešanie balíčka
State.DrawDeck = _deckManager.CreateShuffledDeck();
State.DiscardPile.Clear();
// Rozdanie kariet každému aktívnemu hráčovi podľa jeho OlympicCardsCount
foreach (var player in State.ActiveTournamentPlayers)
{
for (int i = 0; i < player.OlympicCardsCount; i++)
{
if (State.DrawDeck.Count > 0)
{
var card = State.DrawDeck[0];
State.DrawDeck.RemoveAt(0);
player.Hand.Add(card);
}
}
}
// Otočenie prvej karty na odhadzovaciu kôpku
var startCard = State.DrawDeck[0];
State.DrawDeck.RemoveAt(0);
State.DiscardPile.Add(startCard);
State.CurrentPlayerIndex = 0;
EmitEvent(new GameEvent(
GameEventType.GameStarted,
State.CurrentPlayer,
Card: startCard,
Message: "Hra sa začala!"
));
}
public bool CanPlayCard(Player player, Card card)
{
if (State.IsGameOver || State.TurnState != TurnState.Playing) return false;
if (player != State.CurrentPlayer) return false;
if (!player.Hand.Contains(card)) return false;
return ActionValidator.CanPlayCard(
card,
State.TopCard,
State.ActiveSuit,
State.PendingDrawCount,
State.PendingSkip,
State.Rules
);
}
public bool CanBurnCards(Player player, List<Card> cards)
{
if (State.IsGameOver || State.TurnState != TurnState.Playing) return false;
if (player != State.CurrentPlayer) return false;
if (cards.Any(c => !player.Hand.Contains(c))) return false;
return ActionValidator.CanBurnCards(
cards,
State.PendingDrawCount,
State.PendingSkip,
State.Rules
);
}
public bool CanPlayCards(Player player, List<Card> cards)
{
if (State.IsGameOver || State.TurnState != TurnState.Playing) return false;
if (player != State.CurrentPlayer) return false;
if (cards == null || cards.Count == 0) return false;
if (cards.Any(c => !player.Hand.Contains(c))) return false;
return ActionValidator.CanPlayCards(
cards,
State.TopCard,
State.ActiveSuit,
State.PendingDrawCount,
State.PendingSkip,
State.Rules
);
}
public bool PlayCards(Player player, List<Card> cards, Suit? chosenSuit = null)
{
if (!CanPlayCards(player, cards)) return false;
if (cards.Count == 1)
{
return PlayCard(player, cards[0], chosenSuit);
}
// 4 rovnaké karty pri pravidle spálenia
if (cards.Count == 4 && State.Rules.FourOfAKindBurns && State.PendingDrawCount == 0 && !State.PendingSkip)
{
return BurnCards(player, cards);
}
// Zoradíme karty tak, aby prvá vyložená karta legálne sadla na stôl a posledná ostala na vrchu
List<Card> orderedCards;
if (ActionValidator.CanPlayCard(cards[0], State.TopCard, State.ActiveSuit, State.PendingDrawCount, State.PendingSkip, State.Rules))
{
// Prvá karta zvolená hráčom priamo sedí na stôl -> zachováme presné poradie hráča
orderedCards = new List<Card>(cards);
}
else
{
// Nájdeme kartu, ktorá legálne viaže combo na stôl, a dáme ju na začiatok
var matching = cards.FirstOrDefault(c => ActionValidator.CanPlayCard(
c, State.TopCard, State.ActiveSuit, State.PendingDrawCount, State.PendingSkip, State.Rules)) ?? cards[0];
orderedCards = new List<Card> { matching };
foreach (var c in cards)
{
if (c != matching)
{
orderedCards.Add(c);
}
}
}
foreach (var c in orderedCards)
{
player.Hand.Remove(c);
State.DiscardPile.Add(c);
}
var firstRank = cards[0].Rank;
State.ActiveSuit = null;
// Efekt Horníkov
if (firstRank == Rank.OverKnave)
{
if (chosenSuit.HasValue)
{
State.ActiveSuit = chosenSuit.Value;
EmitEvent(new GameEvent(
GameEventType.SuitChanged,
player,
Cards: cards,
ChosenSuit: chosenSuit.Value,
Message: $"{player.Name} zahral {cards.Count}x Horníka a zmenil farbu!"
));
}
else
{
State.TurnState = TurnState.SelectingSuit;
State.PendingHornikPlayer = player;
EmitEvent(new GameEvent(
GameEventType.CardPlayed,
player,
Cards: cards,
Message: $"{player.Name} zahral {cards.Count}x Horníka a vyberá farbu..."
));
return true;
}
}
// Efekt Sediem
else if (firstRank == Rank.Seven)
{
int addedPenalty = cards.Count * 3;
State.PendingDrawCount += addedPenalty;
var redSeven = cards.FirstOrDefault(c => c.IsRedSeven);
if (redSeven != null && State.Rules.RedSevenRevives && State.LastFinishedPlayer != null && State.LastFinishedPlayer != player && State.ReviveTurnsRemaining > 0)
{
var revived = State.LastFinishedPlayer;
revived.FinishedPosition = null;
State.LastFinishedPlayer = null;
State.ReviveTurnsRemaining = 0;
State.ReviveRoundsRemaining = 0;
DrawCardsForPlayer(revived, 3);
EmitEvent(new GameEvent(
GameEventType.PlayerRevived,
player,
TargetPlayer: revived,
Cards: cards,
ExtraData: 3,
Message: $"🔥 {player.Name} zahral combo {cards.Count}x Sedma a vrátil hráča {revived.Name} späť do hry!"
));
}
else
{
EmitEvent(new GameEvent(
GameEventType.SevenStacked,
player,
Cards: cards,
ExtraData: State.PendingDrawCount,
Message: $"⚡ COMBO {cards.Count}x Sedma! Trest stúpol na {State.PendingDrawCount} kariet!"
));
}
}
// Efekt Es
else if (firstRank == Rank.Ace)
{
bool wasPending = State.PendingSkip;
State.PendingSkip = true;
if (wasPending)
{
EmitEvent(new GameEvent(
GameEventType.AceCountered,
player,
Cards: cards,
Message: $"❄️ {player.Name} prebil Eso {cards.Count}x Esom!"
));
}
else
{
EmitEvent(new GameEvent(
GameEventType.AceSkipped,
player,
Cards: cards,
Message: $"❄️ COMBO {cards.Count}x Eso! Ďalší hráč stojí."
));
}
}
// Efekt Zeleného dolníka (rušenie sediem)
else if (firstRank == Rank.UnderKnave && cards.Any(c => c.IsGreenUnderKnave) && State.Rules.GreenUnderKnaveCancelsSevens && State.PendingDrawCount > 0)
{
int canceled = State.PendingDrawCount;
State.PendingDrawCount = 0;
EmitEvent(new GameEvent(
GameEventType.SevenCanceled,
player,
Cards: cards,
ExtraData: canceled,
Message: $"🍃 {player.Name} zahral Zeleného dolníka a ZRUŠIL trest {canceled} kariet!"
));
}
// Ostatné karty
else
{
EmitEvent(new GameEvent(
GameEventType.CardPlayed,
player,
Cards: cards,
Message: $"{player.Name} zahral combo {cards.Count}x {cards[0].RankName}!"
));
}
CheckPlayerFinish(player);
AdvanceTurn();
return true;
}
public bool PlayCard(Player player, Card card, Suit? chosenSuit = null)
{
if (!CanPlayCard(player, card)) return false;
// Odstránenie z ruky
player.Hand.Remove(card);
State.DiscardPile.Add(card);
// Ak bola predtým zmenená farba, zrušíme ju (alebo prepíšeme novým horníkom)
State.ActiveSuit = null;
// Efekt Horníka
if (card.IsHornik)
{
if (chosenSuit.HasValue)
{
State.ActiveSuit = chosenSuit.Value;
EmitEvent(new GameEvent(
GameEventType.SuitChanged,
player,
Card: card,
ChosenSuit: chosenSuit.Value,
Message: $"{player.Name} zahral Horníka a zmenil farbu na {card.SuitName}!"
));
}
else
{
// Čakáme na výber farby
State.TurnState = TurnState.SelectingSuit;
State.PendingHornikPlayer = player;
EmitEvent(new GameEvent(
GameEventType.CardPlayed,
player,
Card: card,
Message: $"{player.Name} zahral Horníka a vyberá farbu..."
));
return true;
}
}
else
{
EmitEvent(new GameEvent(
GameEventType.CardPlayed,
player,
Card: card,
Message: $"{player.Name} zahral {card.Name}."
));
}
// Efekt Sedmy
if (card.IsSeven)
{
State.PendingDrawCount += 3;
// Červená sedma vracia do hry
if (card.IsRedSeven && State.Rules.RedSevenRevives && State.LastFinishedPlayer != null && State.LastFinishedPlayer != player && State.ReviveTurnsRemaining > 0)
{
var revived = State.LastFinishedPlayer;
revived.FinishedPosition = null;
State.LastFinishedPlayer = null;
State.ReviveTurnsRemaining = 0;
State.ReviveRoundsRemaining = 0;
// Doberie 3 karty
DrawCardsForPlayer(revived, 3);
EmitEvent(new GameEvent(
GameEventType.PlayerRevived,
player,
TargetPlayer: revived,
Card: card,
ExtraData: 3,
Message: $"🔥 {player.Name} zahral Červenú sedmu a vrátil hráča {revived.Name} späť do hry!"
));
}
else
{
EmitEvent(new GameEvent(
GameEventType.SevenStacked,
player,
Card: card,
ExtraData: State.PendingDrawCount,
Message: $"⚡ Sedma! Ďalší hráč berie {State.PendingDrawCount} {(State.PendingDrawCount < 5 ? "karty" : "kariet")}."
));
}
}
// Efekt Esa
if (card.IsAce)
{
if (State.PendingSkip)
{
EmitEvent(new GameEvent(
GameEventType.AceCountered,
player,
Card: card,
Message: $"❄️ {player.Name} prebil Eso vlastným Esom!"
));
}
else
{
EmitEvent(new GameEvent(
GameEventType.AceSkipped,
player,
Card: card,
Message: $"❄️ Eso! Ďalší hráč jedno kolo stojí."
));
}
State.PendingSkip = true;
}
// Efekt Zeleného dolníka (rušenie sediem)
if (card.IsGreenUnderKnave && State.Rules.GreenUnderKnaveCancelsSevens && State.PendingDrawCount > 0)
{
int canceled = State.PendingDrawCount;
State.PendingDrawCount = 0;
EmitEvent(new GameEvent(
GameEventType.SevenCanceled,
player,
Card: card,
ExtraData: canceled,
Message: $"🍃 {player.Name} zahral Zeleného dolníka a ZRUŠIL trest {canceled} kariet!"
));
}
// Kontrola, či hráč vyhral / skončil
CheckPlayerFinish(player);
// Posun na ďalšieho hráča
AdvanceTurn();
return true;
}
public bool ChooseSuit(Player player, Suit suit)
{
if (State.TurnState != TurnState.SelectingSuit || State.PendingHornikPlayer != player)
{
return false;
}
State.ActiveSuit = suit;
State.TurnState = TurnState.Playing;
State.PendingHornikPlayer = null;
var dummyCard = new Card(suit, Rank.OverKnave);
EmitEvent(new GameEvent(
GameEventType.SuitChanged,
player,
ChosenSuit: suit,
Message: $"{player.Name} zmenil farbu na {dummyCard.SuitName} ({dummyCard.SuitSymbol})!"
));
// Kontrola, či hráč vyhodením Horníka skončil
CheckPlayerFinish(player);
AdvanceTurn();
return true;
}
public bool BurnCards(Player player, List<Card> cards)
{
if (!CanBurnCards(player, cards)) return false;
var rank = cards[0].Rank;
foreach (var c in cards)
{
player.Hand.Remove(c);
State.DiscardPile.Add(c);
}
State.ActiveSuit = null;
EmitEvent(new GameEvent(
GameEventType.CardsBurned,
player,
Cards: cards,
Message: $"💥 SPÁLENIE! {player.Name} spálil 4x {cards[0].RankName} a hrá znova!"
));
CheckPlayerFinish(player);
// Pri spálení hráč pokračuje vo svojom ťahu (nevolá sa AdvanceTurn)
return true;
}
public void DrawOrAcknowledge(Player player)
{
if (State.IsGameOver || State.TurnState != TurnState.Playing) return;
if (player != State.CurrentPlayer) return;
if (State.PendingDrawCount > 0)
{
int count = State.PendingDrawCount;
State.PendingDrawCount = 0;
DrawCardsForPlayer(player, count);
EmitEvent(new GameEvent(
GameEventType.CardDrawn,
player,
ExtraData: count,
Message: $"{player.Name} si potiahol {count} trestné karty zo sedmy."
));
AdvanceTurn();
}
else if (State.PendingSkip)
{
State.PendingSkip = false;
EmitEvent(new GameEvent(
GameEventType.AceSkipped,
player,
Message: $"{player.Name} stojí toto kolo kvôli Esu."
));
AdvanceTurn();
}
else
{
// Bežné potiahnutie 1 karty
DrawCardsForPlayer(player, 1);
EmitEvent(new GameEvent(
GameEventType.CardDrawn,
player,
ExtraData: 1,
Message: $"{player.Name} si potiahol kartu z balíčka."
));
AdvanceTurn();
}
}
public void ContinueFromPassScreen()
{
if (State.TurnState == TurnState.PassScreen)
{
State.TurnState = TurnState.Playing;
}
}
private void DrawCardsForPlayer(Player player, int count)
{
for (int i = 0; i < count; i++)
{
EnsureDrawDeckHasCards();
if (State.DrawDeck.Count > 0)
{
var card = State.DrawDeck[0];
State.DrawDeck.RemoveAt(0);
player.Hand.Add(card);
}
}
}
private void EnsureDrawDeckHasCards()
{
if (State.DrawDeck.Count > 0) return;
// Ak je balíček prázdny, vezmeme odhadzovaciu kôpku okrem vrchnej karty
if (State.DiscardPile.Count > 1)
{
var topCard = State.DiscardPile[^1];
var cardsToRecycle = State.DiscardPile.Take(State.DiscardPile.Count - 1).ToList();
State.DiscardPile.Clear();
State.DiscardPile.Add(topCard);
_deckManager.Shuffle(cardsToRecycle);
State.DrawDeck.AddRange(cardsToRecycle);
EmitEvent(new GameEvent(
GameEventType.DeckReshuffled,
null,
Message: "Lízací balíček bol premiešaný z odhadzovacej kôpky."
));
}
}
private void CheckPlayerFinish(Player player)
{
if (player.Hand.Count == 0 && !player.HasFinished)
{
int nextPos = State.Players.Count(p => p.HasFinished) + 1;
player.FinishedPosition = nextPos;
if (State.Rules.RedSevenRevives)
{
State.LastFinishedPlayer = player;
int maxRounds = State.Rules.RedSevenMode == RedSevenMode.ColorOrSevenThreeRounds ? 3 : 1;
int activeCount = Math.Max(1, State.ActivePlayersCount);
State.ReviveRoundsRemaining = maxRounds;
State.ReviveTurnsRemaining = maxRounds * activeCount;
State.ReviveWindowInitialTurns = State.ReviveTurnsRemaining;
}
else
{
State.LastFinishedPlayer = null;
State.ReviveRoundsRemaining = 0;
State.ReviveTurnsRemaining = 0;
}
EmitEvent(new GameEvent(
GameEventType.PlayerFinished,
player,
ExtraData: nextPos,
Message: $"🏆 {player.Name} sa zbavil všetkých kariet a obsadil {nextPos}. miesto!"
));
CheckGameOver();
}
}
private void CheckGameOver()
{
int remaining = State.ActivePlayersCount;
if (remaining <= 1)
{
// Zostávajúci hráč, ktorému ostali karty (porazený tohto kola)
var lastPlayer = State.ActiveTournamentPlayers.FirstOrDefault(p => !p.HasFinished);
if (lastPlayer != null)
{
lastPlayer.FinishedPosition = State.ActiveTournamentPlayers.Count;
State.RoundLoser = lastPlayer;
}
if (State.Rules.OlympicMode)
{
if (lastPlayer != null)
{
lastPlayer.OlympicCardsCount--;
if (lastPlayer.IsEliminated)
{
EmitEvent(new GameEvent(
GameEventType.PlayerEliminated,
lastPlayer,
Message: $"☠️ {lastPlayer.Name} stratil všetky karty a vypadáva z Olympijského turnaja!"
));
}
}
var remainingTournamentPlayers = State.ActiveTournamentPlayers;
if (remainingTournamentPlayers.Count <= 1)
{
// Koniec turnaja! Zostal iba 1 víťaz
State.IsGameOver = true;
State.IsMatchOver = true;
State.MatchWinner = remainingTournamentPlayers.FirstOrDefault() ?? lastPlayer;
State.TurnState = TurnState.GameOver;
EmitEvent(new GameEvent(
GameEventType.MatchWon,
State.MatchWinner,
Message: $"🥇 {State.MatchWinner?.Name} sa stal celkovým OLYMPIJSKÝM ŠAMPIÓNOM!"
));
}
else
{
// Koniec jedného kola, nasleduje ďalšie
State.IsRoundOver = true;
State.TurnState = TurnState.RoundOver;
EmitEvent(new GameEvent(
GameEventType.RoundOver,
lastPlayer,
ExtraData: State.RoundNumber,
Message: $"🏅 Kolo #{State.RoundNumber} sa skončilo! {lastPlayer?.Name} bude mať v ďalšom kole {lastPlayer?.OlympicCardsCount} kariet."
));
}
}
else
{
// Bežná jednoduchá hra
State.IsGameOver = true;
State.TurnState = TurnState.GameOver;
EmitEvent(new GameEvent(
GameEventType.GameOver,
null,
Message: "Koniec hry! Všetky pozície sú určené."
));
}
}
}
public void StartNextRound()
{
if (!State.Rules.OlympicMode || State.IsMatchOver) return;
State.RoundNumber++;
State.IsRoundOver = false;
State.IsGameOver = false;
State.RoundLoser = null;
State.TurnState = TurnState.Playing;
State.TurnCount = 1;
State.PendingDrawCount = 0;
State.PendingSkip = false;
State.ActiveSuit = null;
State.PendingHornikPlayer = null;
foreach (var p in State.Players)
{
p.Reset();
}
// Vytvorenie a zamiešanie nového balíčka
State.DrawDeck = _deckManager.CreateShuffledDeck();
State.DiscardPile.Clear();
// Rozdanie kariet len aktívnym (nevyradeným) hráčom podľa ich OlympicCardsCount
foreach (var player in State.ActiveTournamentPlayers)
{
for (int i = 0; i < player.OlympicCardsCount; i++)
{
if (State.DrawDeck.Count > 0)
{
var card = State.DrawDeck[0];
State.DrawDeck.RemoveAt(0);
player.Hand.Add(card);
}
}
}
// Otočenie prvej karty na odhadzovaciu kôpku
var startCard = State.DrawDeck[0];
State.DrawDeck.RemoveAt(0);
State.DiscardPile.Add(startCard);
// Nastavíme prvého hráča na prvého aktívneho
var firstActiveIndex = State.Players.FindIndex(p => !p.IsEliminated);
State.CurrentPlayerIndex = firstActiveIndex >= 0 ? firstActiveIndex : 0;
EmitEvent(new GameEvent(
GameEventType.GameStarted,
State.CurrentPlayer,
Card: startCard,
Message: $"🏅 Začalo sa Kolo #{State.RoundNumber} Olympijského Faraóna!"
));
}
private void AdvanceTurn()
{
if (State.IsGameOver || State.IsRoundOver) return;
// Odpočet lehoty na oživenie
if (State.LastFinishedPlayer != null && State.ReviveTurnsRemaining > 0)
{
State.ReviveTurnsRemaining--;
int activeCount = Math.Max(1, State.ActivePlayersCount);
State.ReviveRoundsRemaining = (int)Math.Ceiling((double)State.ReviveTurnsRemaining / activeCount);
if (State.ReviveTurnsRemaining <= 0)
{
State.LastFinishedPlayer = null;
State.ReviveRoundsRemaining = 0;
}
}
int attempts = 0;
do
{
State.CurrentPlayerIndex = (State.CurrentPlayerIndex + 1) % State.Players.Count;
attempts++;
}
while ((State.CurrentPlayer.HasFinished || State.CurrentPlayer.IsEliminated) && attempts <= State.Players.Count * 2);
State.TurnCount++;
// Ak hráme Pass & Play a nasledujúci hráč je človek a je zapnutá súkromná clona
if (State.Rules.PassAndPlayPrivacyScreen && State.CurrentPlayer.Type == PlayerType.Human && State.ActiveTournamentPlayers.Count(p => p.Type == PlayerType.Human) > 1)
{
State.TurnState = TurnState.PassScreen;
}
else
{
State.TurnState = TurnState.Playing;
}
}
private void EmitEvent(GameEvent e)
{
RecordStatsAndLog(e);
OnGameEvent?.Invoke(e);
}
private void RecordStatsAndLog(GameEvent e)
{
State.Stats.TotalTurns = State.TurnCount;
switch (e.Type)
{
case GameEventType.GameStarted:
AddLogItem(new GameLogItem("🎮", "Hra sa začala!", null, DateTime.UtcNow));
break;
case GameEventType.CardPlayed:
if (e.SourcePlayer != null)
{
State.Stats.RecordCardPlayed(e.SourcePlayer, e.Cards?.Count ?? 1);
if (e.Card?.Rank == Rank.Ace || (e.Cards != null && e.Cards.Any(c => c.Rank == Rank.Ace)))
{
State.Stats.TotalAcesPlayed++;
}
if (e.Card?.Rank == Rank.Seven || (e.Cards != null && e.Cards.Any(c => c.Rank == Rank.Seven)))
{
State.Stats.TotalSevensPlayed++;
}
string cardDesc = e.Cards != null && e.Cards.Count > 1
? $"{e.Cards.Count}x {e.Cards[0].RankName}"
: (e.Card != null ? $"{e.Card.RankName} {e.Card.SuitSymbol}" : "karta");
AddLogItem(new GameLogItem("🎴", $"{e.SourcePlayer.Name} zahral {cardDesc}", null, DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar));
}
break;
case GameEventType.CardDrawn:
if (e.SourcePlayer != null)
{
int count = e.ExtraData > 0 ? e.ExtraData : 1;
State.Stats.RecordCardDrawn(e.SourcePlayer, count);
string countText = count > 1 ? $"{count} kariet" : "z balíčka";
string? sub = count > 1 ? "Trest za sedmy" : null;
string? accent = count > 1 ? "#f59e0b" : null;
AddLogItem(new GameLogItem("📥", $"{e.SourcePlayer.Name} potiahol {countText}", sub, DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, accent));
}
break;
case GameEventType.SevenStacked:
if (e.TargetPlayer != null)
{
State.Stats.RecordCardDrawn(e.TargetPlayer, e.ExtraData);
AddLogItem(new GameLogItem("🎒", $"{e.TargetPlayer.Name} musel potiahnuť +{e.ExtraData} kariet!", "Trest zo sediem", DateTime.UtcNow, e.TargetPlayer.Name, e.TargetPlayer.Avatar, "#f59e0b"));
}
break;
case GameEventType.SevenCanceled:
if (e.SourcePlayer != null)
{
AddLogItem(new GameLogItem("🛡️", $"{e.SourcePlayer.Name} zrušil sedmy Zeleným dolníkom!", "Štít úspešný", DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#10b981"));
}
break;
case GameEventType.AceSkipped:
if (e.SourcePlayer != null)
{
AddLogItem(new GameLogItem("❄️", $"{e.SourcePlayer.Name} stojí toto kolo", "Zmrazený Esom", DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#06b6d4"));
}
break;
case GameEventType.AceCountered:
if (e.SourcePlayer != null)
{
AddLogItem(new GameLogItem("⚡", $"{e.SourcePlayer.Name} prebil Eso vlastným Esom!", "Protiútok", DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#3b82f6"));
}
break;
case GameEventType.CardsBurned:
if (e.SourcePlayer != null)
{
State.Stats.RecordBurn(e.SourcePlayer);
AddLogItem(new GameLogItem("🔥", $"{e.SourcePlayer.Name} SPÁLIL 4 KARTY!", "Hrá znova", DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#ef4444"));
}
break;
case GameEventType.SuitChanged:
if (e.SourcePlayer != null && e.ChosenSuit.HasValue)
{
AddLogItem(new GameLogItem("👑", $"{e.SourcePlayer.Name} zmenil farbu na {GetSuitName(e.ChosenSuit.Value)}", null, DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#eab308"));
}
break;
case GameEventType.PlayerRevived:
if (e.TargetPlayer != null)
{
AddLogItem(new GameLogItem("❤️", $"{e.TargetPlayer.Name} VSTAL Z MŔTVYCH!", "Červená sedma", DateTime.UtcNow, e.TargetPlayer.Name, e.TargetPlayer.Avatar, "#ec4899"));
}
break;
case GameEventType.PlayerFinished:
if (e.SourcePlayer != null)
{
AddLogItem(new GameLogItem("🏆", $"{e.SourcePlayer.Name} skončil na {e.ExtraData}. mieste!", "Vyprázdnil ruku", DateTime.UtcNow, e.SourcePlayer.Name, e.SourcePlayer.Avatar, "#ffd700"));
}
break;
case GameEventType.GameOver:
case GameEventType.MatchWon:
State.Stats.EndTime = DateTime.UtcNow;
break;
}
}
private void AddLogItem(GameLogItem item)
{
State.MoveLog.Add(item);
if (State.MoveLog.Count > 30)
{
State.MoveLog.RemoveAt(0);
}
}
private static string GetSuitName(Suit suit) => suit switch
{
Suit.Hearts => "Červeň ❤️",
Suit.Leaves => "Zeleň 🍃",
Suit.Acorns => "Žaluď 🌰",
Suit.Bells => "Guľu 🔔",
_ => suit.ToString()
};
}