public static bool TreeGetChild(ActionTree tree, ActionTreeNode n, ref int i, out ActionTreeNode child) { if (i < n.Children.Count) { child = n.Children[i++]; return(true); } child = null; return(false); }
/// <summary> /// Build a tree for position pos. /// </summary> public void Build(ActionTree atTree, int pos) { //GetChild = (GenTree t, DeckGenNode n, ref int i, out DeckGenNode c) => // { // GenNode c1; // GenTree.TreeGetChild(t, n, ref i, out c) // }; _pos = pos; _atTree = atTree; _atTree.Positions[pos] = new ActionTreeNode(); GenTree genTree = new GenTree { GameDef = _atTree.GameDef, Kind = GenTree.TreeKind.ActionTree }; DeckGenNode genRoot = new DeckGenNode(genTree, 2); NodesCount = 0; Walk(genTree, genRoot); }
public static void DoMonteCarlo( ActionTree tree, int ourPos, CardSet pocket, int round, string sharedCardsAsString, List <ActionTreeNode> strategyPath, int repetitionsCount) { string[] sharedCards = sharedCardsAsString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); ActionTreeNode curStrategyNode = strategyPath[strategyPath.Count - 1]; // Here we sometimes use the knowledge about the game definition. _clearValues.Walk(tree, curStrategyNode); MonteCarloData[] mc = new MonteCarloData[tree.GameDef.RoundsCount]; for (int r = 0; r < mc.Length; ++r) { mc[r] = new MonteCarloData(); } // Fill known public data. for (int r = 1; r <= round; ++r) { int sharedCount = tree.GameDef.SharedCardsCount[r]; mc[r].boardSize = mc[r - 1].boardSize + sharedCount; mc[r].shared = StdDeck.Descriptor.GetCardSet(sharedCards, mc[r - 1].boardSize, sharedCount); mc[r].board = mc[r - 1].board | mc[r].shared; Debug.Assert(mc[r].shared.CountCards() == sharedCount); Debug.Assert(mc[r].board.CountCards() == mc[r].boardSize); } Debug.Assert(mc[round].boardSize == sharedCards.Length); MonteCarloDealer mcDealer = new MonteCarloDealer(); ApplyMonteCarloData applyMc = new ApplyMonteCarloData(); mcDealer.Initialize(pocket | mc[round].board); Debug.Assert(mcDealer.Cards.Length + pocket.CountCards() + mc[round].boardSize == 52); for (int repetition = 0; repetition < repetitionsCount * 10; ++repetition) { mcDealer.Shuffle(7); // 2 for opponent, up to 5 for the board CardSet mcPocket = StdDeck.Descriptor.GetCardSet(mcDealer.Cards, 0, 2); Debug.Assert(mc[0].board.IsEmpty()); int sharedDealt = 0; for (int r = 0; r < tree.GameDef.RoundsCount; ++r) { if (r > round) { mc[r].boardSize = mc[r - 1].boardSize + tree.GameDef.SharedCardsCount[r]; mc[r].shared = StdDeck.Descriptor.GetCardSet(mcDealer.Cards, 2 + sharedDealt, tree.GameDef.SharedCardsCount[r]); sharedDealt += tree.GameDef.SharedCardsCount[r]; Debug.Assert(!mc[r - 1].board.Contains(mc[r].shared)); Debug.Assert(!mcPocket.Contains(mc[r].shared)); mc[r].board = mc[r - 1].board | mc[r].shared; } mc[r].bucket = tree.Bucketizer.GetBucket(mcPocket, mc[r].board, r); } double strategyFactor = 1; // Go through the strategy path, skip the b-node Debug.Assert(strategyPath[0].ActionKind == Ak.b); // Start from pos. 2 to skip deals (where OppBuckets always contains 0s if ourPos == 0). for (int pathIndex = 2; pathIndex < strategyPath.Count; pathIndex++) { ActionTreeNode pathNode = strategyPath[pathIndex]; Debug.Assert(pathNode.ActionKind != Ak.b); // Take nodes where opponent acts. if (pathNode.State.CurrentActor == 1 - ourPos) { // nextNode always exists because this function is called when we act ActionTreeNode nextNode = strategyPath[pathIndex + 1]; Debug.Assert(pathNode.State.Round == nextNode.State.Round); int freq = pathNode.OppBuckets.Counts[mc[pathNode.State.Round].bucket]; int nextFreq = nextNode.OppBuckets.Counts[mc[pathNode.State.Round].bucket]; double coef = freq == 0 ? 0 : (double)nextFreq / freq; strategyFactor *= coef; } } if (strategyFactor > 0) { int showdownValue = Showdown(pocket, mcPocket, mc[tree.GameDef.RoundsCount - 1].board, mc[tree.GameDef.RoundsCount - 1].boardSize + 2); applyMc.ApplyData(curStrategyNode, mc, ourPos, showdownValue, strategyFactor); repetition += 9; } } FinalizeMonteCarloData finalizer = new FinalizeMonteCarloData(); finalizer.Finalize(tree, curStrategyNode, ourPos); }