コード例 #1
0
 // Use custom implementation for optitmization reasons.
 protected void ProcessChildren(ActionTreeNode node)
 {
     for (int c = 0; c < node.Children.Count; ++c)
     {
         node.Children[c].StrategyFactor = node.StrategyFactor;
         TraverseSubtree(node.Children[c], node);
     }
 }
コード例 #2
0
        protected bool OnNodeBegin(ActionTreeNode node, ActionTreeNode parent)
        {
            if (node.ActionKind == Ak.s)
            {
                Debug.Assert(node.State.LastActor == -1);

                // This is a point where a bucket is transformed to the next round's buckets.
                // Here we do not have know the probability of transformation from
                // mc[r].bucket -> mc[r+1].bucket, because this probability i
                // is inherently taken into account by Monte-Carlo method.
            }
            else if (parent != null && parent.State.CurrentActor == 1 - _ourPos && !parent.State.IsDealerActing)
            {
                // Opponent have acted - apply strategic probability.
                Debug.Assert(node.State.Round == parent.State.Round);
                int bucket     = _mc[node.State.Round].bucket;
                int parentFreq = parent.OppBuckets.Counts[bucket];
                int nodeFreq   = node.OppBuckets.Counts[bucket];
                if (parentFreq != 0)
                {
                    node.StrategyFactor *= (double)nodeFreq / parentFreq;
                }
                else
                {
                    Debug.Assert(nodeFreq == 0);
                    node.StrategyFactor = 0;
                }
            }

            if (node.Children.Count == 0)
            {
                // Terminal node.
                Debug.Assert(node.State.IsGameOver);

                double value;

                if (node.State.IsShowdownRequired)
                {
                    // Noone folded - do showdown.
                    value = node.State.Pot / 2 * _showdownValue;
                }
                else if (node.State.Players[_ourPos].IsFolded)
                {
                    // We folded
                    value = -node.State.Players[_ourPos].InPot;
                }
                else
                {
                    // Opponent folded
                    Debug.Assert(node.State.Players[1 - _ourPos].IsFolded);
                    value = node.State.Players[1 - _ourPos].InPot;
                }
                value      *= node.StrategyFactor;
                node.Value += value;
            }
            return(node.StrategyFactor > 0);
        }
コード例 #3
0
 protected bool TraverseSubtree(ActionTreeNode node, ActionTreeNode parent)
 {
     if (!OnNodeBegin(node, parent))
     {
         return(false);
     }
     ProcessChildren(node);
     return(true);
 }
コード例 #4
0
 public void ApplyData(ActionTreeNode root, MonteCarloData [] mc, int ourPos,
                       int showdownValue, double strategyFactor)
 {
     _mc                 = mc;
     _ourPos             = ourPos;
     _showdownValue      = showdownValue;
     root.StrategyFactor = strategyFactor;
     TraverseSubtree(root, null);
 }
コード例 #5
0
 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);
 }
コード例 #6
0
 public ActionTree(GameDefinition gameDef, Bucketizer bucketizer)
 {
     Version    = new BdsVersion(Assembly.GetExecutingAssembly());
     GameDef    = gameDef;
     Bucketizer = bucketizer;
     Positions  = new ActionTreeNode[GameDef.MinPlayers];
     for (int p = 0; p < Positions.Length; ++p)
     {
         Positions[p]       = new ActionTreeNode();
         Positions[p].State = new GameState(gameDef, gameDef.MinPlayers);
     }
 }
コード例 #7
0
 private void ProcessPlayerActions()
 {
     for (int a = _strategyPath.Count - 1; a < _gameRecord.Actions.Count; ++a)
     {
         PokerAction pa = _gameRecord.Actions[a];
         log.InfoFormat("{0} process {1} of pos {2}", _name, pa.Kind, pa.Position);
         ActionTreeNode nextNode = CurStrategyNode.FindChildByAction(pa.Kind);
         Debug.Assert(nextNode.State.LastActor == pa.Position);
         _strategyPath.Add(nextNode);
         if (pa.Kind == Ak.d && pa.Position == _pos)
         {
             OnDeal(pa.Cards);
         }
     }
 }
コード例 #8
0
        private PokerAction GetBestAction(GameState CurGameState)
        {
            Debug.Assert(CurStrategyNode.State.CurrentActor == _pos);
            double         maxVal   = double.MinValue;
            ActionTreeNode bestNode = null;

            foreach (ActionTreeNode child in CurStrategyNode.Children)
            {
                double childValue = CurGameState.Round == 0 ? child.PreflopValues[(int)_pocketKind] : child.Value;
                if (childValue > maxVal)
                {
                    bestNode = child;
                    maxVal   = childValue;
                }
                else if (childValue == maxVal)
                {
                    if (ActionPreference(child.ActionKind) > ActionPreference(bestNode.ActionKind))
                    {
                        bestNode = child;
                    }
                }
            }

            PokerAction result;

            if (bestNode != null)
            {
                result = new PokerAction {
                    Kind = bestNode.ActionKind
                };
            }
            else
            {
                Debug.Assert(CurStrategyNode.Children.Count > 0);
                // We have never been here - just call
                result = PokerAction.c(0);
            }
            return(result);
        }
コード例 #9
0
        protected override bool OnNodeBeginFunc(GenTree tree, GenNode node, List <ActionTreeBuilderContext> stack, int depth)
        {
            base.OnNodeBeginFunc(tree, node, stack, depth);
            ActionTreeNode atNode;

            if (depth == 0)
            {
                atNode = _atTree.Positions[_pos];
            }
            else
            {
                atNode = new ActionTreeNode();
                stack[depth - 1].AtNode.Children.Add(atNode);
            }
            stack[depth].AtNode = atNode;
            atNode.State        = node.State;
            atNode.ActionKind   = node.Action.Kind;
            atNode.Id           = NodesCount;
            NodesCount++;

            GameState gs = atNode.State;

            if (gs.IsGameOver)
            {
                if (gs.Players[1 - _pos].IsFolded)
                {
                    atNode.OppBuckets = new Buckets(0, 0); // If we fold, it is never used
                }
                else
                {
                    atNode.OppBuckets = new Buckets(_atTree.Bucketizer.BucketCount[gs.Round], 0);
                }
                return(false);
            }
            atNode.OppBuckets = new Buckets(depth > 0 ? _atTree.Bucketizer.BucketCount[gs.Round] : 0, 0);
            return(true);
        }
コード例 #10
0
        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);
        }