A value type that describes a drawable card face. It stores identifier, corner/center text, colors, gameplay value, pip count and label, and includes a helper to create a standard playing-card face from Rank and Suit.
namespace CardGames;
/// <summary>
/// Describes a single drawable card face. A <see cref="DeckDefinition"/> resolves to an ordered
/// list of these; a runtime <see cref="Card"/> is just an index into it. Generic on purpose so the
/// same data drives a poker deck, an Uno-style colour deck or anything custom - and the fields are
/// <c>[Property]</c> so a deck's custom card list is editable in the inspector.
/// </summary>
public struct CardFace
{
/// <summary>
/// Stable identifier for a card, e.g. "AS", "10H".
/// </summary>
[KeyProperty] public string Key { get; set; }
/// <summary>
/// Small text in the corners, e.g. "A", "10", "K", or an Uno number.
/// </summary>
[Property] public string Corner { get; set; }
/// <summary>
/// Large symbol drawn in the centre, e.g. a suit glyph or an Uno icon.
/// </summary>
[Property] public string Center { get; set; }
/// <summary>
/// Ink colour for the corner/centre marks (red/black for a standard deck, white on a colour card).
/// </summary>
[Property] public Color Accent { get; set; }
/// <summary>
/// Per-card face colour. Defaults to transparent, which means "use the deck's <see cref="DeckDefinition.FaceColor"/>".
/// Set it for colour-on-card decks (e.g. Uno red/green/blue/yellow).
/// </summary>
[Property] public Color Background { get; set; }
/// <summary>
/// Generic gameplay value. For a standard deck this is the rank ordinal (1-13).
/// </summary>
[Property] public int Value { get; set; }
/// <summary>
/// Number of pips to lay out in the centre. 0 for face/custom cards.
/// </summary>
[Property] public int Pips { get; set; }
/// <summary>
/// Human readable name, e.g. "Ace of Spades". Handy for logs and tooltips.
/// </summary>
[Property] public string Label { get; set; }
/// <summary>
/// True if this card overrides the deck's face colour with its own <see cref="Background"/>.
/// </summary>
public readonly bool HasBackground => Background.a > 0f;
public static CardFace FromStandard( Rank rank, Suit suit ) => new()
{
Key = $"{rank.Short()}{suit.ToString()[0]}", // e.g. "AS", "10H", "KC"
Corner = rank.Short(),
Center = suit.Glyph(),
Accent = suit.IsRed() ? Color.Red : Color.Black,
Value = (int)rank,
Pips = rank.PipCount(),
Label = $"{rank} of {suit}"
// Background left transparent → uses the deck's FaceColor (white).
};
}