using OECS; namespace Game.Blackjack; /// /// 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). /// public class DeckSetupSystem : ISystem { public void RunImpl(World world) { var state = world.ReadSingleton(); if (state.Phase != GamePhase.Dealing) return; // Only create deck entities if they don't exist yet. bool hasDeck = false; using (var iter = world.Select()) { hasDeck = iter.MoveNext(); } if (!hasDeck) { // Create deck entity. var deckEntity = world.CreateEntity(); world.AddComponent(deckEntity, new Deck()); // Create all 52 cards. foreach (Suit suit in Enum.GetValues()) { foreach (Rank rank in Enum.GetValues()) { var cardEntity = world.CreateEntity(); world.AddComponent(cardEntity, new Card { Suit = suit, Rank = rank }); world.AddComponent(cardEntity, new InDeck { Target = deckEntity }); } } // 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(); var deckEntity2 = world.FindEntity(); var cards = world.GetSources(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); // Swap the InDeck relationship targets (cards are always in the deck, // so there's nothing to swap except the cards themselves — but we // shuffle the card order conceptually by removing and re-adding // InDeck components in shuffled order). Actually, since InDeck // is just a tag, we just re-shuffle the order in the source collection. // The simplest approach: no need to swap component data; we just // need to ensure the cards are iterated in shuffled order. // We'll swap the card entities in the array. (cardEntities[i], cardEntities[j]) = (cardEntities[j], cardEntities[i]); } // Now remove all InDeck and re-add in shuffled order so GetSources // returns them in shuffled order. for (int i = cardEntities.Length - 1; i >= 0; i--) { world.RemoveComponent(cardEntities[i]); } for (int i = 0; i < cardEntities.Length; i++) { world.AddComponent(cardEntities[i], new InDeck { Target = deckEntity }); } } }