2026-07-18 23:26:56 +08:00
|
|
|
using OECS;
|
|
|
|
|
|
2026-07-20 16:41:10 +08:00
|
|
|
namespace Game.Blackjack;
|
2026-07-18 23:26:56 +08:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates the deck (52 cards + deck/hand entities) and shuffles
|
|
|
|
|
/// using mulberry32 with the seed from the GameState singleton.
|
|
|
|
|
/// Runs once at the start of each round (during Dealing phase).
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class DeckSetupSystem : ISystem
|
|
|
|
|
{
|
2026-07-21 13:57:11 +08:00
|
|
|
public void RunImpl(World world)
|
2026-07-18 23:26:56 +08:00
|
|
|
{
|
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
|
|
|
if (state.Phase != GamePhase.Dealing)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Only create deck entities if they don't exist yet.
|
|
|
|
|
bool hasDeck = false;
|
|
|
|
|
using (var iter = world.Select<Deck>())
|
|
|
|
|
{
|
2026-07-21 13:57:11 +08:00
|
|
|
hasDeck = iter.MoveNext();
|
2026-07-18 23:26:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasDeck)
|
|
|
|
|
{
|
|
|
|
|
// Create deck entity.
|
|
|
|
|
var deckEntity = world.CreateEntity();
|
|
|
|
|
world.AddComponent(deckEntity, new Deck());
|
|
|
|
|
|
|
|
|
|
// Create all 52 cards.
|
|
|
|
|
foreach (Suit suit in Enum.GetValues<Suit>())
|
|
|
|
|
{
|
|
|
|
|
foreach (Rank rank in Enum.GetValues<Rank>())
|
|
|
|
|
{
|
|
|
|
|
var cardEntity = world.CreateEntity();
|
|
|
|
|
world.AddComponent(cardEntity, new Card { Suit = suit, Rank = rank });
|
2026-07-20 22:59:27 +08:00
|
|
|
world.AddComponent(cardEntity, new InDeck { Target = deckEntity });
|
2026-07-18 23:26:56 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create hand entities.
|
|
|
|
|
var playerHand = world.CreateEntity();
|
|
|
|
|
world.AddComponent(playerHand, new PlayerHand());
|
|
|
|
|
|
|
|
|
|
var dealerHand = world.CreateEntity();
|
|
|
|
|
world.AddComponent(dealerHand, new DealerHand());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shuffle the deck using mulberry32 with the current seed.
|
|
|
|
|
ref var mutableState = ref world.GetSingleton<GameState>();
|
2026-07-21 13:57:11 +08:00
|
|
|
var deckEntity2 = world.FindEntity<Deck>();
|
2026-07-18 23:26:56 +08:00
|
|
|
var cards = world.GetSources<InDeck>(deckEntity2).ToArray();
|
|
|
|
|
Shuffle(world, deckEntity2, cards, ref mutableState.Seed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void Shuffle(World world, Entity deckEntity, Entity[] cardEntities, ref uint seed)
|
|
|
|
|
{
|
|
|
|
|
// Fisher-Yates shuffle using mulberry32.
|
|
|
|
|
for (int i = cardEntities.Length - 1; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int j = Mulberry32.NextInt(ref seed, 0, i);
|
|
|
|
|
(cardEntities[i], cardEntities[j]) = (cardEntities[j], cardEntities[i]);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 22:46:32 +08:00
|
|
|
// Reorder the source set in-place — no component add/remove needed.
|
|
|
|
|
world.ReorderSources<InDeck>(deckEntity, cardEntities);
|
2026-07-18 23:26:56 +08:00
|
|
|
}
|
|
|
|
|
}
|