public override void CopyFrom(PocketData Source)
        {
            RaiseCallFoldData _Source = Source as RaiseCallFoldData;

            for (int i = 0; i < Pocket.N; i++)
            {
                Raise[i] = _Source.Raise[i];
                Call[i]  = _Source.Call[i];
            }
        }
        public number ChanceToActWithExclusion(PocketData pdf, PocketData chance, int ExcludedPocketIndex)
        {
            var pocket = Pocket.Pockets[ExcludedPocketIndex];
            int c1 = pocket.Cards[0], c2 = pocket.Cards[1];

            number Chance =
            TotalChance -
                TotalChance_OneCardFixed[c1] -
                TotalChance_OneCardFixed[c2] +
                    pdf[ExcludedPocketIndex] * chance[ExcludedPocketIndex];

            number Mass =
            TotalMass -
                TotalMass_OneCardFixed[c1] -
                TotalMass_OneCardFixed[c2] +
                    pdf[ExcludedPocketIndex];

            if (Mass < Tools.eps) return 0;
            else return Chance / Mass;
        }
        public void ChanceToActPrecomputation(PocketData pdf, PocketData chance, CommunityNode community)
        {
            ResetTotal();

            number val, mass;
            Pocket pocket;
            for (int p = 0; p < Pocket.N; p++)
            {
                if (!community.AvailablePocket[p]) continue;

                mass = pdf[p];
                val = mass * chance[p];
                TotalChance += val;
                TotalMass += mass;

                pocket = Pocket.Pockets[p];
                int c1 = pocket.Cards[0], c2 = pocket.Cards[1];
                TotalChance_OneCardFixed[c1] += val;
                TotalChance_OneCardFixed[c2] += val;
                TotalMass_OneCardFixed[c1] += mass;
                TotalMass_OneCardFixed[c2] += mass;
            }
        }
 public virtual void CopyFrom(PocketData Source)
 {
     for (int i = 0; i < Pocket.N; i++)
         data[i] = Source[i];
 }
 public virtual void SwitchWith(PocketData other)
 {
     for (int i = 0; i < Pocket.N; i++)
     {
         number temp = other[i];
         other[i] = data[i];
         data[i] = temp;
     }
 }
        public virtual void MultiLinear(int n, int pocket, double[] weight, PocketData[] data)
        {
            number result = 0;
            for (int i = 0; i < n; i++)
                result += (number)weight[i] * data[i][pocket];

            this[pocket] = result;
        }
 public virtual void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2, number t3, PocketData data3)
 {
     this[pocket] = t1 * data1[pocket] + t2 * data2[pocket] + t3 * data3[pocket];
 }
 public virtual void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2)
 {
     //t1 = .5 * (t1 + Node.__t);
     //t2 = .5 * (t2 + (1 - Node.__t));
     this[pocket] = t1 * data1[pocket] + t2 * data2[pocket];
 }
        void CalculateBestAgainst_Naive(Player Opponent)
        {
            // First decide strategy for children nodes.
            RecursiveBest(Opponent);

            // For each pocket we might have, calculate what we should do.
            PocketData UpdatedP = new PocketData();
            for (int p1 = 0; p1 < Pocket.N; p1++)
            {
                if (!MyCommunity.AvailablePocket[p1]) continue;

                // Update the opponent's pocket PDF using the new information,
                // (which is that we now know which pocket we have).
                UpdateOnExclusion(PocketP, UpdatedP, p1);

                // Calculate the EV assuming we proceed to a branch.
                // Loop through each possible opponent pocket and then each possible branch,
                // summing up the EV of each branch times the probability of arriving there.
                number TotalWeight = 0, BranchEV = 0;
                number[] BranchPDF = new number[Branches.Count];
                for (int p2 = 0; p2 < Pocket.N; p2++)
                {
                    if (!MyCommunity.AvailablePocket[p2]) continue;

                    // All branches not overlapping our pocket or the opponent's pocket are equally likely.
                    int BranchIndex = 0;
                    foreach (Node Branch in Branches)
                    {
                        BranchIndex++;
                        if (!Branch.MyCommunity.AvailablePocket[p1] || !Branch.MyCommunity.AvailablePocket[p2]) continue;

                        number Weight = Branch.Weight;
                        BranchEV += UpdatedP[p2] * Weight * Branch.EV[p1];
                        TotalWeight += UpdatedP[p2] * Weight;
                        BranchPDF[BranchIndex - 1] += UpdatedP[p2] * Weight;
                    }
                }
                Assert.ZeroOrOne(BranchPDF.Sum());
                Assert.ZeroOrOne(TotalWeight);
                Assert.That(BranchEV >= -DerivedSetup.MaxPot - Tools.eps && BranchEV <= DerivedSetup.MaxPot + Tools.eps);

                EV[p1] = BranchEV;
                Assert.IsNum(EV[p1]);
            }
        }
        protected override void Initialize()
        {
            S = new PocketData();
            B = new PocketData();
            if (MakeHold) Hold = new PocketData();

            CreateBranches();
        }
 public RaiseCallFoldData()
 {
     this.Raise = this;
     this.Call = new PocketData();
 }
 public override void Linear(int pocket, number t1, PocketData data1, number t2, PocketData data2, number t3, PocketData data3)
 {
     base.Linear(pocket, t1, data1, t2, data2, t3, data3);
     Call.Linear(pocket, t1, ((RaiseCallFoldData)data1).Call, t2, ((RaiseCallFoldData)data2).Call, t3, ((RaiseCallFoldData)data3).Call);
 }
        public void ProbabilityPrecomputation(PocketData pdf, CommunityNode community)
        {
            ResetMass();

            number mass;
            Pocket pocket;
            for (int p = 0; p < Pocket.N; p++)
            {
                if (!community.AvailablePocket[p]) continue;

                mass = pdf[p];
                TotalMass += mass;

                pocket = Pocket.Pockets[p];
                int c1 = pocket.Cards[0], c2 = pocket.Cards[1];
                TotalMass_OneCardFixed[c1] += mass;
                TotalMass_OneCardFixed[c2] += mass;
            }
        }
        /// <summary>
        /// Takes in a pocket PDF and updates it based on new information,
        /// the new information being that a particular pocket should be excluded.
        /// </summary>
        /// <param name="P">The prior PDF</param>
        /// <param name="UpdatedP">The posterior PDF</param>
        /// <param name="ExcludePocketIndex">The index of the excluded pocket.</param>
        public void UpdateOnExclusion(PocketData P, PocketData UpdatedP, int ExcludePocketIndex)
        {
            number TotalWeight = 0;
            for (int p = 0; p < Pocket.N; p++)
            {
                if (!MyCommunity.AvailablePocket[p]) continue;

                // If this pocket overlaps with the excluded pocket,
                // then the probability of seeing it is 0.
                if (PocketPocketOverlap(p, ExcludePocketIndex))
                {
                    UpdatedP[p] = 0;
                    continue;
                }

                UpdatedP[p] = P[p];
                TotalWeight += P[p];
            }

            if (TotalWeight == 0) return;

            for (int p = 0; p < Pocket.N; p++)
                UpdatedP[p] /= TotalWeight;
        }
        public void Update(PocketData PreviousPDF, PocketData Strategy, PocketData Destination)
        {
            number ChanceToProceed = 0;
            for (int p = 0; p < Pocket.N; p++)
            {
                if (MyCommunity.AvailablePocket[p])
                    ChanceToProceed += PreviousPDF[p] * Strategy[p];
            }

            Assert.AlmostPos(ChanceToProceed);
            if (ChanceToProceed <= 0) ChanceToProceed = 1;

            // Calculate the Pocket PDF assuming opponent proceeded.
            for (int p = 0; p < Pocket.N; p++)
                Destination[p] = PreviousPDF[p] * Strategy[p] / ChanceToProceed;
        }
        /// <summary>
        /// Given a strategy to act or not act for each pocket,
        /// and assuming we know the PDF of the pockets, calculate
        /// the chance action is taken.
        /// </summary>
        /// <param name="pdf">The PDF of pockets.</param>
        /// <param name="chance">The chance to act for each pocket.</param>
        /// <param name="ExcludePocketIndex">Index of a pre-existing pocket. Exclude all pockets overlapping this pocket.</param>
        /// <returns>The overall chance to act.</returns>
        public number TotalChance(PocketData pdf, PocketData chance, int ExcludePocketIndex)
        {
            number RaiseChance = 0;
            number weight = 0;
            for (int p = 0; p < Pocket.N; p++)
            {
                if (!MyCommunity.AvailablePocket[p]) continue;
                if (PocketPocketOverlap(p, ExcludePocketIndex)) continue;

                weight += pdf[p];
                RaiseChance += pdf[p] * chance[p];
            }

            if (weight == 0)
            {
                Assert.That(RaiseChance == 0);
                return 0;
            }

            return RaiseChance / weight;
        }
        /// <summary>
        /// Given a strategy to act or not act for each pocket,
        /// and assuming we know the PDF of the pockets, calculate
        /// the chance action is taken.
        /// </summary>
        /// <param name="pdf">The PDF of pockets.</param>
        /// <param name="chance">The chance to act for each pocket.</param>
        /// <returns>The overall chance to act.</returns>
        public number TotalChance(PocketData pdf, PocketData chance)
        {
            number RaiseChance = 0;
            for (int p = 0; p < Pocket.N; p++)
                RaiseChance += pdf[p] * chance[p];

            return RaiseChance;
        }
        //static number[] IntersectP = new number[Card.N];
        void CalculateBestAgainst_SingleCardOptimized(Player Opponent)
        {
            RecursiveBest(Opponent);

            // Calculate P(Opponent pocket intersects a given card)
            for (int c = 0; c < Card.N; c++)
            {
                if (BranchesByIndex[c] == null) continue;

                IntersectP[c] = 0;
                for (int c2 = 0; c2 < Card.N; c2++)
                {
                    if (c == c2) continue;

                    int p = Game.PocketLookup[c, c2];
                    if (!MyCommunity.AvailablePocket[p]) continue;

                    IntersectP[c] += PocketP[p];
                }
            }

            Data.ProbabilityPrecomputation(PocketP, MyCommunity);

            // For each pocket we might have, calculate what we should do.
            PocketData UpdatedP = new PocketData();
            for (int p1 = 0; p1 < Pocket.N; p1++)
            {
                if (!MyCommunity.AvailablePocket[p1]) continue;

                number BranchEV = 0;
                for (int c = 0; c < Card.N; c++)
                {
                    Node Branch = BranchesByIndex[c];
                    if (Branch == null) continue;
                    if (!Branch.MyCommunity.AvailablePocket[p1]) continue;

                    // Find opponent pockets that intersect our pocket and the community card c
                    var Pocket1 = Pocket.Pockets[p1];
                    int p2_1 = Game.PocketLookup[Pocket1.Cards[0], c];
                    int p2_2 = Game.PocketLookup[Pocket1.Cards[1], c];

                    number Correction = Data.MassAfterExclusion(PocketP, p1);
                    number Pr = Correction - IntersectP[c] + PocketP[p2_1] + PocketP[p2_2];
                    if (Pr <= Tools.eps) continue;
                    Assert.That(Correction > Tools.eps);
                    Pr /= Correction;

                    Assert.AlmostProbability(Pr);
                    Assert.That(Branch.Weight > 0);
                    Assert.IsNum(Pr);
                    Pr = Tools.Restrict(Pr);
                    BranchEV += Branch.EV[p1] * Pr * Branch.Weight;
                }

                EV[p1] = BranchEV;
                Assert.IsNum(EV[p1]);
            }
        }
        public override void SwitchWith(PocketData other)
        {
            RaiseCallFoldData _other = other as RaiseCallFoldData;
            Assert.That(_other != null);

            base.SwitchWith(other);
            Call.SwitchWith(_other.Call);
        }
        public number MassAfterExclusion(PocketData pdf, int ExcludedPocketIndex)
        {
            var pocket = Pocket.Pockets[ExcludedPocketIndex];
            int c1 = pocket.Cards[0], c2 = pocket.Cards[1];

            number Mass =
            TotalMass -
                TotalMass_OneCardFixed[c1] -
                TotalMass_OneCardFixed[c2] +
                    pdf[ExcludedPocketIndex];

            return Mass;
        }
        public void MakeScratchSpace()
        {
            if (Phase == BettingPhase.PreFlop || Phase == BettingPhase.Flop)
            {
                // Initialize HoldEV and HoldPocketP, both arrays of PocketDatas
                int NumData = MaxDepth + Flop.N + Card.N + Card.N;
                HoldEV = new PocketData[NumData];
                HoldPocketP = new PocketData[NumData];

                for (int i = 0; i < NumData; i++)
                {
                    HoldEV[i] = new PocketData();
                    HoldPocketP[i] = new PocketData();
                }

                // Initialize rest of scratch space
                Data = new Optimize();
                Data2 = new Optimize();
                NotS = new PocketData();
                IntersectP = new number[Card.N];
            }
            else
            {
                // Copy scratch space from parent community node
                HoldEV = Parent.HoldEV;
                HoldPocketP = Parent.HoldPocketP;
                Data = Parent.Data;
                Data2 = Parent.Data2;
                NotS = Parent.NotS;
                IntersectP = Parent.IntersectP;
            }
        }
 public virtual void InverseOf(PocketData Source)
 {
     for (int i = 0; i < Pocket.N; i++)
         data[i] = ((number)1) - Source[i];
 }
        public override void CalculateBestAgainst(Player Opponent)
        {
            /* Naive implementation. O(N^4) */
            if (DerivedSetup.Naive)
            {
                // For each pocket we might have, calculate EV.
                PocketData UpdatedP = new PocketData();
                uint PocketValue1, PocketValue2;
                for (int p1 = 0; p1 < Pocket.N; p1++)
                {
                    if (!MyCommunity.AvailablePocket[p1]) continue;
                    PocketValue1 = PocketValue[p1];
                    Assert.That(PocketValue1 < uint.MaxValue);

                    // Update the opponent's pocket PDF using the new information,
                    // (which is that we now know which pocket we have).
                    UpdateOnExclusion(PocketP, UpdatedP, p1);
                    OpCount++;

                    number ShowdownEV = 0;
                    for (int p2 = 0; p2 < Pocket.N; p2++)
                    {
                        if (!MyCommunity.AvailablePocket[p2]) continue;
                        PocketValue2 = PocketValue[p2];
                        Assert.That(PocketValue2 < uint.MaxValue);

                        if (PocketValue1 == PocketValue2) continue;
                        else if (PocketValue1 > PocketValue2)
                            ShowdownEV += UpdatedP[p2] * Pot;
                        else
                            ShowdownEV -= UpdatedP[p2] * Pot;
                    }

                    EV[p1] = ShowdownEV;
                    Assert.IsNum(EV[p1]);
                }
            }
            else /* Asymptotically optimal implementation. O(N^2) */
            {
                RiverCommunity River = (RiverCommunity)MyCommunity;
                Data.ProbabilityPrecomputation(PocketP, MyCommunity);
                number Correction;
                int _p1;

                // For each pocket we might have, calculate the chance to win.
                Data.ResetSummed();

                _p1 = 0;
                while (_p1 < Pocket.N)
                {
                    int p1 = River.SortedPockets[_p1];
                    if (!MyCommunity.AvailablePocket[p1]) { _p1++; continue; }

                    // Find next highest pocket
                    int NextHighest = _p1 + 1;
                    uint CurrentPocketValue = River.PocketValue[p1];
                    while (NextHighest < Pocket.N && River.SortedPocketValue[NextHighest] == CurrentPocketValue)
                        NextHighest++;

                    // For all pockets of equal value, calculate the chance to win
                    for (int EqualValuedPocket = _p1; EqualValuedPocket < NextHighest; EqualValuedPocket++)
                    {
                        int p = River.SortedPockets[EqualValuedPocket];
                        if (!MyCommunity.AvailablePocket[p]) continue;

                        var pocket1 = Pocket.Pockets[p];
                        int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1];

                        number ChanceToWin =
                        Data.SummedChance -
                            Data.SummedChance_OneCardFixed[c1] -
                            Data.SummedChance_OneCardFixed[c2];

                        Correction = Data.MassAfterExclusion(PocketP, p);
                        if (Correction < Tools.eps)
                        {
                            ChanceToWin = 0;
                        }
                        else
                        {
                            ChanceToWin /= Correction;
                        }

                        EV[p] = ChanceToWin * Pot;
                        Assert.IsNum(EV[p]);
                    }

                    // Total the probability mass of our opponent having a hand with equal value
                    for (int EqualValuedPocket = _p1; EqualValuedPocket < NextHighest; EqualValuedPocket++)
                    {
                        int p = River.SortedPockets[EqualValuedPocket];
                        if (!MyCommunity.AvailablePocket[p]) continue;

                        var pocket1 = Pocket.Pockets[p];
                        int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1];

                        number P = PocketP[p];

                        Data.SummedChance += P;
                        Data.SummedChance_OneCardFixed[c1] += P;
                        Data.SummedChance_OneCardFixed[c2] += P;
                    }

                    _p1 = NextHighest;
                }

                // For each pocket we might have, calculate the chance to lose.
                Data.ResetSummed();

                _p1 = Pocket.N - 1;
                while (_p1 > 0)
                {
                    int p1 = River.SortedPockets[_p1];
                    if (!MyCommunity.AvailablePocket[p1]) { _p1--; continue; }

                    // Find next highest pocket
                    int NextLowest = _p1 - 1;
                    uint CurrentPocketValue = River.PocketValue[p1];
                    while (NextLowest >= 0 && River.SortedPocketValue[NextLowest] == CurrentPocketValue)
                        NextLowest--;

                    // For all pockets of equal value, calculate the chance to win
                    for (int EqualValuedPocket = _p1; EqualValuedPocket > NextLowest; EqualValuedPocket--)
                    {
                        int p = River.SortedPockets[EqualValuedPocket];
                        if (!MyCommunity.AvailablePocket[p]) continue;

                        var pocket1 = Pocket.Pockets[p];
                        int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1];

                        number ChanceToLose =
                        Data.SummedChance -
                            Data.SummedChance_OneCardFixed[c1] -
                            Data.SummedChance_OneCardFixed[c2];

                        Correction = Data.MassAfterExclusion(PocketP, p);
                        if (Correction < Tools.eps)
                            ChanceToLose = 0;
                        else
                            ChanceToLose /= Correction;

                        EV[p] -= ChanceToLose * Pot;
                        Assert.IsNum(EV[p]);
                    }

                    // Total the probability mass of our opponent having a hand with equal value
                    for (int EqualValuedPocket = _p1; EqualValuedPocket > NextLowest; EqualValuedPocket--)
                    {
                        int p = River.SortedPockets[EqualValuedPocket];
                        if (!MyCommunity.AvailablePocket[p]) continue;

                        var pocket1 = Pocket.Pockets[p];
                        int c1 = pocket1.Cards[0], c2 = pocket1.Cards[1];

                        number P = PocketP[p];

                        Data.SummedChance += P;
                        Data.SummedChance_OneCardFixed[c1] += P;
                        Data.SummedChance_OneCardFixed[c2] += P;
                    }

                    _p1 = NextLowest;
                }
            }
        }
        void CalculateBestAgainst_FlopSuitReduced(Player Opponent)
        {
            System.Threading.Tasks.Parallel.ForEach(Branches, node => node.CalculateBestAgainst(Opponent));

            //foreach (Node node in Branches)
            //    node.CalculateBestAgainst(Opponent);

            // For each pocket we might have, calculate what we should do.
            PocketData UpdatedP = new PocketData();
            for (int p1 = 0; p1 < Pocket.N; p1++)
            {
                if (!MyCommunity.AvailablePocket[p1]) continue;

                // Update the opponent's pocket PDF using the new information,
                // (which is that we now know which pocket we have).
                UpdateOnExclusion(PocketP, UpdatedP, p1);

                // Calculate the EV assuming we proceed to a branch.
                // Loop through each possible opponent pocket and then each possible branch,
                // summing up the EV of each branch times the probability of arriving there.
                number TotalWeight = 0, BranchEV = 0;
                number[] BranchPDF = new number[Branches.Count];
                for (int p2 = 0; p2 < Pocket.N; p2++)
                {
                    if (!MyCommunity.AvailablePocket[p2]) continue;

                    // All branches not overlapping our pocket or the opponent's pocket are equally likely.
                    // However, because we have grouped some branches together we weight representative branches more heavily.
                    int b = 0;
                    foreach (Node Branch in Branches)
                    {
                        b++;
                        if (Branch.MyCommunity.NewCollision(p1) || Branch.MyCommunity.NewCollision(p2)) continue;

                        FlopRoot FlopBranch = (FlopRoot)Branch;
                        FlopRoot _Branch = FlopBranch.Representative;
                        int _p1 = FlopBranch.MyFlop.PocketMap[p1];

                        //Assert.AlmostEqual(Branch.EV[p1], _Branch.EV[_p1], .05);

                        number Weight = _Branch.Weight;
                        BranchEV += UpdatedP[p2] * Weight * _Branch.EV[_p1];
                        TotalWeight += UpdatedP[p2] * Weight;
                        BranchPDF[b - 1] += UpdatedP[p2] * Weight;
                    }
                }
                Assert.ZeroOrOne(BranchPDF.Sum());
                Assert.ZeroOrOne(TotalWeight);
                Assert.That(BranchEV >= -DerivedSetup.MaxPot - Tools.eps && BranchEV <= DerivedSetup.MaxPot + Tools.eps);

                EV[p1] = BranchEV;
                Assert.IsNum(EV[p1]);
            }
        }