public void Test_GetHandSizes() { string testResourcesPath = UTHelper.GetTestResourceDir(Assembly.GetExecutingAssembly()); GameDefinition gd = XmlSerializerExt.Deserialize <GameDefinition>(Path.Combine(testResourcesPath, "gamedef-test.xml")); int[] handSizes = gd.GetHandSizes(); Assert.AreEqual(new int [] { 2, 5, 6, 7 }, handSizes); }
/// <summary> /// Generate an internal chance tree by MC sampling. /// </summary> /// <param name="chanceAbstractions">An array of chance abstractions</param> /// <param name="areAbstractionsEqual">If the absractions are equal, /// one MC sample will update multiple nodes of the chance tree.</param> /// <param name="samplesCount">Number of samples. If equal absractions are used, /// less MC samples will be actually done to reach the specified numbers of updates.</param> /// <param name="rngSeed">RNG seed.</param> /// <param name="feedback">User feedback callback.</param> /// <returns></returns> public static Tree Generate(GameDefinition gd, IChanceAbstraction[] chanceAbstractions, bool areAbstractionsEqual, long samplesCount, int rngSeed, FeedbackDelegate feedback) { if (chanceAbstractions.Length != 2) { throw new ArgumentOutOfRangeException("Only heads up games are supported now"); } McDealer mcDealer = new McDealer(gd, rngSeed); int [][] hands = new int[chanceAbstractions.Length][].Fill(i => new int[mcDealer.HandSize]); int[] handSizes = gd.GetHandSizes(); Tree tree = new Tree { PlayersCount = chanceAbstractions.Length, RoundsCount = gd.RoundsCount, SourceInfo = GetSourceInfo(gd, chanceAbstractions) }; Node root = tree.Root; byte[] abstrCards = new byte[gd.RoundsCount * chanceAbstractions.Length]; uint[] ranks = new uint[chanceAbstractions.Length]; Int64 samplesDone; int updateCount = areAbstractionsEqual ? 2 : 1; for (samplesDone = 0; samplesDone < samplesCount; samplesDone += updateCount) { if (feedback != null && (samplesDone % FEEDBACK_PERIOD == 0)) { if (!feedback(samplesDone)) { break; } } mcDealer.NextDeal(hands); gd.GameRules.Showdown(gd, hands, ranks); int c = 0; for (int r = 0; r < gd.RoundsCount; ++r) { for (int p = 0; p < chanceAbstractions.Length; ++p) { int abstrCard = chanceAbstractions[p].GetAbstractCard(hands[p], handSizes[r]); if (abstrCard < byte.MinValue || abstrCard > byte.MaxValue) { throw new ApplicationException(string.Format("Abstract card {0} out of byte range", abstrCard)); } abstrCards[c++] = (byte)abstrCard; } } for (int u = 0; ;) { LeafT[] leaves = tree.GetLeavesByCards(abstrCards); int lastCard = abstrCards[abstrCards.Length - 1]; leaves[lastCard].Update(ranks); if (++u == updateCount) { break; } // If the abstractions are equal, we can update another node // by permuting cards and results // Note: implemented for 2 players only for (c = 0; c < abstrCards.Length; c += 2) { ShortSequence.Swap(ref abstrCards[c], ref abstrCards[c + 1]); } ShortSequence.Swap(ref ranks[0], ref ranks[1]); } } tree.SamplesCount = (UInt64)samplesDone; tree.UpdateDescription(); return(tree); }