/// <summary>Part of a shuffle process.</summary> /// <param name="group">The group being shuffled.</param> /// <param name="card">An array containing the CardIdentity ids to shuffle.</param> public void Shuffle(Group group, int[] card) { // Array to hold the new aliases (sent to CreateAlias) ulong[] aliases = new ulong[card.Length]; // Intialize the group shuffle group.filledShuffleSlots = 0; group.hasReceivedFirstShuffledMessage = false; group.myShufflePos = new short[card.Length]; // Check if we received enough cards if (Player.Count <= 1) return; if (card.Length < group.Count / (Player.Count - 1)) Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "[Shuffle] Too few cards received."); // Do the shuffling Random rnd = new Random(); for (int i = card.Length - 1; i >= 0; i--) { int r = rnd.Next(i); int tc = card[r]; card[r] = card[i]; // Create a new alias, if the card is not face up CardIdentity ci = CardIdentity.Find(tc); if (group.FindByCardIdentity(ci) != null) { card[i] = tc; aliases[i] = ulong.MaxValue; ci.visible = true; } else { ci = new CardIdentity(Program.Game.GenerateCardId()); ci.mySecret = ci.alias = true; ci.key = ((ulong)Crypto.PositiveRandom()) << 32 | (uint)tc; card[i] = ci.id; aliases[i] = Crypto.ModExp(ci.key); ci.visible = false; } // Give a random position to the card // TODO: I don't think this shuffling algorithm generates all possibilities equiprobably group.myShufflePos[i] = (short)Crypto.Random(group.Count); } // Send the results Program.Client.Rpc.CreateAlias(card, aliases); Program.Client.Rpc.Shuffled(group, card, group.myShufflePos); }