namespace RuleEngine.Core;
///
/// Per-game wildcard configuration — replaces the old static HashSet approach.
/// Each MahjongGameState owns its own registry so different game variants
/// don't leak wildcard state between tests or concurrent games.
///
public class WildcardRegistry
{
private readonly HashSet _wildcards = new();
/// Base wildcard encoding range (50-59) for extra tiles added to deck.
public const int WildcardBase = 50;
/// Non-extra wildcard tiles — normal tiles (e.g. 红中=35) that ALSO act as wildcards.
public IReadOnlySet ConfiguredWildcards => _wildcards;
public void Clear() => _wildcards.Clear();
public void Add(int tile) => _wildcards.Add(tile);
public void AddRange(IEnumerable tiles)
{
foreach (var t in tiles) _wildcards.Add(t);
}
/// Is this tile a wildcard? Checks encoding range AND configured set.
public bool IsWildcard(int tile) =>
(tile >= WildcardBase && tile <= WildcardBase + 9) || _wildcards.Contains(tile);
/// Count how many tiles in a list are wildcards.
public int CountWildcards(IReadOnlyList tiles) =>
tiles.Count(t => IsWildcard(t));
/// Parse wildcard tile names from DSL into encodings.
public static int? NameToEncoding(string name) => name switch
{
"红中" => 35,
"发财" => 36,
"白板" => 37,
_ => null
};
public WildcardRegistry Clone()
{
var r = new WildcardRegistry();
r.AddRange(_wildcards);
return r;
}
}