187 lines
5.1 KiB
C#
187 lines
5.1 KiB
C#
namespace Koogle.Application.Games.DeathBox;
|
|
|
|
/// <summary>
|
|
/// Game model for DeathBox (Totenkisten) game type.
|
|
/// Players collect marks (Striche) and are eliminated when their coffin is full.
|
|
/// Last player standing wins.
|
|
/// </summary>
|
|
public record DeathBoxGameModel : IGameModel
|
|
{
|
|
/// <summary>
|
|
/// Coffin size (6-12 marks). When a player reaches this many marks, they're eliminated.
|
|
/// </summary>
|
|
public int CoffinSize { get; init; } = 12;
|
|
|
|
/// <summary>
|
|
/// State for each player (marks, X's, eggs, eliminated status).
|
|
/// </summary>
|
|
public Dictionary<Guid, DeathBoxPlayerState> PlayerStates { get; init; } = new();
|
|
|
|
/// <summary>
|
|
/// Fixed player order (randomized at game start).
|
|
/// </summary>
|
|
public Guid[] PlayerOrder { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// Current player index in PlayerOrder.
|
|
/// </summary>
|
|
public int CurrentPlayerIndex { get; set; }
|
|
|
|
/// <summary>
|
|
/// ID of the previous player who threw (for "cleared pins" penalty).
|
|
/// </summary>
|
|
public Guid? PreviousPlayerId { get; set; }
|
|
|
|
/// <summary>
|
|
/// List of eliminated player IDs in elimination order.
|
|
/// </summary>
|
|
public List<Guid> EliminatedPlayers { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// ID of the winner (last player standing).
|
|
/// </summary>
|
|
public Guid? WinnerId { get; set; }
|
|
|
|
/// <summary>
|
|
/// Whether the game has ended.
|
|
/// </summary>
|
|
public bool IsGameOver { get; set; }
|
|
|
|
/// <summary>
|
|
/// Last throw info for display.
|
|
/// </summary>
|
|
public DeathBoxLastThrow? LastThrow { get; set; }
|
|
|
|
/// <summary>
|
|
/// Pending game events that require UI notification.
|
|
/// </summary>
|
|
public List<GameEvent> PendingGameEvents { get; init; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// State for a single player in DeathBox.
|
|
/// </summary>
|
|
public record DeathBoxPlayerState
|
|
{
|
|
/// <summary>
|
|
/// Current marks (Striche). Player is eliminated when this reaches CoffinSize.
|
|
/// </summary>
|
|
public int Marks { get; set; }
|
|
|
|
/// <summary>
|
|
/// Current X count. 3 X's = +1 mark + reset X's.
|
|
/// </summary>
|
|
public int XCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// Current egg count. 3 eggs = -1 mark (if possible) + reset eggs.
|
|
/// </summary>
|
|
public int EggCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// Whether this player is eliminated.
|
|
/// </summary>
|
|
public bool IsEliminated { get; set; }
|
|
|
|
/// <summary>
|
|
/// Total throws made by this player.
|
|
/// </summary>
|
|
public int ThrowCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// Total pins knocked down.
|
|
/// </summary>
|
|
public int TotalPins { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Info about the last throw for UI display.
|
|
/// </summary>
|
|
public record DeathBoxLastThrow
|
|
{
|
|
/// <summary>
|
|
/// Player who made the throw.
|
|
/// </summary>
|
|
public Guid PlayerId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Number of pins knocked down.
|
|
/// </summary>
|
|
public int PinsKnocked { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether this was a new round (all 9 pins were standing).
|
|
/// </summary>
|
|
public bool IsNewRound { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether a penalty was applied for <3 pins on new round.
|
|
/// </summary>
|
|
public bool WasPenalty { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the throw was a gutter.
|
|
/// </summary>
|
|
public bool WasGutter { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the throw was "no wood" (0 pins but not gutter).
|
|
/// </summary>
|
|
public bool WasNoWood { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether all remaining pins were cleared.
|
|
/// </summary>
|
|
public bool WasCleared { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether player earned an X (always on new round).
|
|
/// </summary>
|
|
public bool EarnedX { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether player earned an egg (on clearing).
|
|
/// </summary>
|
|
public bool EarnedEgg { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether 3 X's were converted to 1 mark.
|
|
/// </summary>
|
|
public bool ConvertedXsToMark { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether 3 eggs were converted to remove 1 mark.
|
|
/// </summary>
|
|
public bool ConvertedEggsToRemoveMark { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the next player got a mark (cleared penalty).
|
|
/// </summary>
|
|
public bool NextPlayerGotMark { get; init; }
|
|
|
|
/// <summary>
|
|
/// ID of next player who got a mark (if any).
|
|
/// </summary>
|
|
public Guid? NextPlayerPenalizedId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the previous player got a mark (cleared penalty).
|
|
/// </summary>
|
|
public bool PreviousPlayerGotMark { get; init; }
|
|
|
|
/// <summary>
|
|
/// ID of previous player who got a mark (if any).
|
|
/// </summary>
|
|
public Guid? PreviousPlayerPenalizedId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the current player was eliminated this throw.
|
|
/// </summary>
|
|
public bool PlayerEliminated { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether the previous player was eliminated due to cleared penalty.
|
|
/// </summary>
|
|
public bool PreviousPlayerEliminated { get; init; }
|
|
}
|