コード例 #1
0
        /// <summary>
        /// Returns a players additional raise amounts in a binned format between 0 and 1 using the provided binWidth. Anything greater than 1 will be added to an additional bin at the end.
        /// </summary>
        /// <param name="playerId"></param>
        /// <param name="binWidth"></param>
        /// <returns></returns>
        public static void PlayerAdditionalRaiseAmountsBinned(long playerId, decimal binWidth, out int[] preFlopBinsSmall, out int[] flopBinsSmall, out int[] turnBinsSmall, out int[] riverBinsSmall,
                                                              out int[] preFlopBinsBig, out int[] flopBinsBig, out int[] turnBinsBig, out int[] riverBinsBig)
        {
            PlayerAverageAdditionalRaiseAmountResult[] playerData = PlayerAdditionalRaiseAmountsRaw(playerId);

            //Setup bins
            int numBins = (int)(1.0m / binWidth) + 1;

            preFlopBinsSmall = new int[numBins];
            flopBinsSmall    = new int[numBins];
            turnBinsSmall    = new int[numBins];
            riverBinsSmall   = new int[numBins];

            preFlopBinsBig = new int[numBins];
            flopBinsBig    = new int[numBins];
            turnBinsBig    = new int[numBins];
            riverBinsBig   = new int[numBins];

            //Fill bins
            for (int i = 0; i < playerData.Length; i++)
            {
                //Calculate the info we need to know about the scaled amount
                double scaledRaiseAmount = RaiseAmountsHelper.ScaleAdditionalRaiseAmount(playerData[i].currentPotAmount, playerData[i].bigBlind, playerData[i].minAdditionalRaiseAmount, playerData[i].maxAdditionalRaiseAmount, playerData[i].additionalRaiseAmountToScale);
                bool   smallPot          = playerData[i].currentPotAmount <= RaiseAmountsHelper.SmallPotBBMultiplierLimit * playerData[i].bigBlind;
                int    binIndex          = (int)(scaledRaiseAmount / (double)binWidth);

                //Anything larger than the last bin just gets put there
                if (binIndex > numBins - 1)
                {
                    binIndex = numBins - 1;
                }

                if (smallPot)
                {
                    if (playerData[i].gameStage == 0)
                    {
                        preFlopBinsSmall[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 1)
                    {
                        flopBinsSmall[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 2)
                    {
                        turnBinsSmall[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 3)
                    {
                        riverBinsSmall[binIndex]++;
                    }
                    else
                    {
                        throw new Exception("Impossible gameStage provided.");
                    }
                }
                else
                {
                    if (playerData[i].gameStage == 0)
                    {
                        preFlopBinsBig[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 1)
                    {
                        flopBinsBig[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 2)
                    {
                        turnBinsBig[binIndex]++;
                    }
                    else if (playerData[i].gameStage == 3)
                    {
                        riverBinsBig[binIndex]++;
                    }
                    else
                    {
                        throw new Exception("Impossible gameStage provided.");
                    }
                }
            }
        }
コード例 #2
0
        protected override Play GetDecision()
        {
            Dictionary <string, decimal> networkInputs = new Dictionary <string, decimal>();

            //Some values need to be moved the top because they are used in multiple places
            decimal currentRoundMinPlayCallAmount = currentDecision.Cache.getMinimumPlayAmount();
            decimal additionalCallAmount          = currentRoundMinPlayCallAmount - infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

            //Determine the minimumRaiseToAmount
            decimal lastAdditionalRaiseAmount = currentDecision.Cache.getCurrentRoundLastRaiseAmount();
            decimal minimumRaiseToAmount      = (currentRoundMinPlayCallAmount - lastAdditionalRaiseAmount) + (lastAdditionalRaiseAmount * 2);

            decimal currentPotAmount     = infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal);
            decimal remainingPlayerStack = currentDecision.Cache.getPlayerStack(currentDecision.PlayerId);

            long[] activePlayerIds = currentDecision.Cache.getActivePlayerIds();

            //Current Round Actions
            List <PokerAction> currentRoundPlayerActions = (from current in currentDecision.Cache.getPlayerCurrentRoundActions(currentDecision.PlayerId)
                                                            where current == PokerAction.Check ||
                                                            current == PokerAction.Call ||
                                                            current == PokerAction.Raise
                                                            select current).ToList();

            #region RaiseAmounts
            decimal raiseToCallAmountNew, raiseToStealAmountNew;

            //If we are preflop we calculate the raise amounts in a slightly more fixed fashion
            if (currentDecision.Cache.getBettingRound() == 0)
            {
                double randomNumber = randomGen.NextDouble();

                //If the pot is unraised
                if (infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal) == currentDecision.Cache.BigBlind)
                {
                    if (randomNumber > 0.8)
                    {
                        raiseToCallAmountNew = 4m * currentDecision.Cache.BigBlind;
                    }
                    else if (randomNumber > 0.4)
                    {
                        raiseToCallAmountNew = 3.5m * currentDecision.Cache.BigBlind;
                    }
                    else
                    {
                        raiseToCallAmountNew = 3.0m * currentDecision.Cache.BigBlind;
                    }
                }
                else
                {
                    //decimal currentRoundLastRaiseAmount = infoStore.GetInfoValue(InfoType.BP_LastAdditionalRaiseAmount);
                    decimal additionalNewRaiseAmount;

                    if (randomNumber > 0.9)
                    {
                        additionalNewRaiseAmount = 2 * lastAdditionalRaiseAmount;
                    }
                    else if (randomNumber > 0.45)
                    {
                        additionalNewRaiseAmount = 1.5m * lastAdditionalRaiseAmount;
                    }
                    else
                    {
                        additionalNewRaiseAmount = 1 * lastAdditionalRaiseAmount;
                    }

                    raiseToCallAmountNew = additionalNewRaiseAmount + infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal);
                }

                raiseToStealAmountNew = 1.5m * raiseToCallAmountNew;

                //We will only scale the raiseToCallAmount if it is not a bigblind multiple
                if (((int)(raiseToCallAmountNew / currentDecision.Cache.BigBlind)) * currentDecision.Cache.BigBlind != raiseToCallAmountNew)
                {
                    //Round the raiseToCallAmount
                    decimal raiseToCallAmountBlindMultiple = raiseToCallAmountNew / currentDecision.Cache.LittleBlind;
                    raiseToCallAmountNew = Math.Round(raiseToCallAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * currentDecision.Cache.LittleBlind;
                }

                //Round the raiseToStealAmount
                decimal raiseToStealAmountBlindMultiple = raiseToStealAmountNew / currentDecision.Cache.LittleBlind;
                raiseToStealAmountNew = Math.Round(raiseToStealAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * currentDecision.Cache.LittleBlind;
            }
            else
            {
                raiseToCallAmountNew  = (decimal)infoStore.GetInfoValue(InfoType.WR_RaiseToCallAmount);
                raiseToStealAmountNew = (decimal)infoStore.GetInfoValue(InfoType.WR_RaiseToStealAmount);
            }

            //Some raise validation
            //Validate we can actually raise the selected amounts
            decimal maximumRaiseAmount = remainingPlayerStack + infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

            //if (raiseToCallAmount > maximumRaiseAmount) raiseToCallAmount = maximumRaiseAmount;
            //if (raiseToStealAmount > maximumRaiseAmount) raiseToStealAmount = maximumRaiseAmount;

            //Check for a big raise amount which would be best as going all in
            if (raiseToCallAmountNew > 0.8m * maximumRaiseAmount)
            {
                raiseToCallAmountNew = maximumRaiseAmount;
            }
            if (raiseToStealAmountNew > 0.8m * maximumRaiseAmount)
            {
                raiseToStealAmountNew = maximumRaiseAmount;
            }

            //If we have already raised twice this round all amounts are set to all in
            bool raisedTwiceOrGreaterCurrentRound = currentRoundPlayerActions.Count(entry => entry == PokerAction.Raise) >= 2;
            if (raisedTwiceOrGreaterCurrentRound)
            {
                raiseToCallAmountNew  = maximumRaiseAmount;
                raiseToStealAmountNew = maximumRaiseAmount;
            }
            #endregion RaiseAmounts

            /////////////////////////////////////////
            ///////////ALL NON BOOLEAN INPUTS BETWEEN 0.9 and 0.1
            /////////////////////////////////////////

            #region neuralInputs

            #region gameStage

            decimal gameStagePreFlop = 0;
            decimal gameStageFlop    = 0;
            decimal gameStageTurn    = 0;
            decimal gameStageRiver   = 0;

            decimal currentGameStage = infoStore.GetInfoValue(InfoType.GP_GameStage_Byte);

            if (currentGameStage == 0)
            {
                gameStagePreFlop = 1;
            }
            else if (currentGameStage == 1)
            {
                gameStageFlop = 1;
            }
            else if (currentGameStage == 2)
            {
                gameStageTurn = 1;
            }
            else if (currentGameStage == 3)
            {
                gameStageRiver = 1;
            }
            else
            {
                throw new Exception("What sort of game stage do you call this??");
            }

            networkInputs.Add("GameStagePreFlop", gameStagePreFlop);
            networkInputs.Add("GameStageFlop", gameStageFlop);
            networkInputs.Add("GameStageTurn", gameStageTurn);
            networkInputs.Add("GameStageRiver", gameStageRiver);

            #endregion gameStage
            //4 inputs

            #region preFlop HoleCards
            if (gameStagePreFlop == 1)
            {
                //Card info types
                networkInputs.Add("HoleCardsAAPair", infoStore.GetInfoValue(InfoType.CP_HoleCardsAAPair_Bool));
                networkInputs.Add("HoleCardsKKPair", infoStore.GetInfoValue(InfoType.CP_HoleCardsKKPair_Bool));
                networkInputs.Add("HoleCardsAKPair", infoStore.GetInfoValue(InfoType.CP_HoleCardsAK_Bool));
                networkInputs.Add("HoleCardsOtherHighPair", infoStore.GetInfoValue(InfoType.CP_HoleCardsOtherHighPair_Bool));
                networkInputs.Add("HoleCardsOtherLowPair", infoStore.GetInfoValue(InfoType.CP_HoleCardsOtherLowPair_Bool));
                networkInputs.Add("HoleCardsTroubleHand", infoStore.GetInfoValue(InfoType.CP_HoleCardsTroubleHand_Bool));
                networkInputs.Add("HoleCardsMidConnector", infoStore.GetInfoValue(InfoType.CP_HoleCardsMidConnector_Bool));
                networkInputs.Add("HoleCardsLowConnector", infoStore.GetInfoValue(InfoType.CP_HoleCardsLowConnector_Bool));
                networkInputs.Add("HoleCardsSuited", infoStore.GetInfoValue(InfoType.CP_HoleCardsSuited_Bool));
            }
            else
            {
                networkInputs.Add("HoleCardsAAPair", 0);
                networkInputs.Add("HoleCardsKKPair", 0);
                networkInputs.Add("HoleCardsAKPair", 0);
                networkInputs.Add("HoleCardsOtherHighPair", 0);
                networkInputs.Add("HoleCardsOtherLowPair", 0);
                networkInputs.Add("HoleCardsTroubleHand", 0);
                networkInputs.Add("HoleCardsMidConnector", 0);
                networkInputs.Add("HoleCardsLowConnector", 0);
                networkInputs.Add("HoleCardsSuited", 0);
            }
            #endregion
            //9 inputs

            #region playerPosition and numPlayers
            decimal dealerDistance     = ((infoStore.GetInfoValue(InfoType.GP_DealerDistance_Byte) - 1) / (infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) - 1));
            decimal tablePositionEarly = 0;
            decimal tablePositionMid   = 0;
            decimal tablePositionLate  = 0;

            if (dealerDistance < (1.0m / 3.0m) && dealerDistance >= 0)
            {
                tablePositionEarly = 1;
            }
            else if (dealerDistance < (2.0m / 3.0m) && dealerDistance >= 0)
            {
                tablePositionMid = 1;
            }
            else if (dealerDistance <= 1.0m && dealerDistance >= 0)
            {
                tablePositionLate = 1;
            }
            else
            {
                throw new Exception("Dealer distance must be between 0 and 1.");
            }

            networkInputs.Add("TablePositionEarly", tablePositionEarly);
            networkInputs.Add("TablePositionMid", tablePositionMid);
            networkInputs.Add("TablePositionLate", tablePositionLate);

            networkInputs.Add("NumActivePlayers4Plus", (infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) >= 4 ? 1 : 0));
            networkInputs.Add("NumActivePlayers3", (infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) == 3 ? 1 : 0));
            networkInputs.Add("NumActivePlayers2", (infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) == 2 ? 1 : 0));

            networkInputs.Add("LastToAct", (infoStore.GetInfoValue(InfoType.GP_NumUnactedPlayers_Byte) == 1 ? 1 : 0));
            #endregion playerPosition and numPlayers
            //7 inputs

            #region potCommitment and liability
            decimal potCommitted = 0;
            if (infoStore.GetInfoValue(InfoType.BP_PlayerMoneyInPot_Decimal) > infoStore.GetInfoValue(InfoType.BP_PlayerHandStartingStackAmount_Decimal) * 0.75m)
            {
                potCommitted = 1;
            }

            networkInputs.Add("PotCommitted", potCommitted);

            //The maximum liability in our current hand, i.e.
            decimal   maximumLiability = 0;
            decimal[] allPlayerStacks  = new decimal[activePlayerIds.Length];

            //Determine if anyone has a larger stack than us
            bool stackLargerThanOurs = false;
            for (int i = 0; i < activePlayerIds.Length; i++)
            {
                allPlayerStacks[i] = currentDecision.Cache.getPlayerStack(activePlayerIds[i]);

                if (activePlayerIds[i] != currentDecision.PlayerId && allPlayerStacks[i] > remainingPlayerStack)
                {
                    stackLargerThanOurs = true;
                    break;
                }
            }

            if (!stackLargerThanOurs)
            {
                //Find the nearest largest stack
                decimal nearestLargestStack = 0;
                for (int i = 0; i < activePlayerIds.Length; i++)
                {
                    if (activePlayerIds[i] != currentDecision.PlayerId && allPlayerStacks[i] > nearestLargestStack)
                    {
                        nearestLargestStack = allPlayerStacks[i];
                    }
                }

                maximumLiability = ScaleContInput(nearestLargestStack / currentDecision.Cache.MaxStack);
            }
            else
            {
                maximumLiability = ScaleContInput(remainingPlayerStack / currentDecision.Cache.MaxStack);
            }

            networkInputs.Add("MaximumLiability", maximumLiability);
            #endregion
            //2 inputs

            #region Hand and Action History
            List <PokerAction> allPlayerActionsCurrentHand = currentDecision.Cache.getPlayerActionsCurrentHand(currentDecision.PlayerId);
            decimal            callCount  = (decimal)allPlayerActionsCurrentHand.Count(entry => entry == PokerAction.Call);
            decimal            checkCount = (decimal)allPlayerActionsCurrentHand.Count(entry => entry == PokerAction.Check);
            decimal            raiseCount = (decimal)allPlayerActionsCurrentHand.Count(entry => entry == PokerAction.Raise);

            decimal currentHandOurAggression = 0;

            currentHandOurAggression = raiseCount - (callCount + checkCount);
            if (currentHandOurAggression < -6)
            {
                currentHandOurAggression = -6;
            }
            else if (currentHandOurAggression > 6)
            {
                currentHandOurAggression = 6;
            }

            networkInputs.Add("CurrentHandOurAggression", currentHandOurAggression / 6.0m);

            networkInputs.Add("CurrentRoundFirstAction", (currentRoundPlayerActions.Count == 0 ? 1 : 0));
            networkInputs.Add("CurrentRoundSecondAction", (currentRoundPlayerActions.Count == 1 ? 1 : 0));
            networkInputs.Add("CurrentRoundThirdPlusAction", (currentRoundPlayerActions.Count >= 2 ? 1 : 0));
            #endregion Hand and Round Actions
            //4 inputs

            #region WinRatio
            decimal probWin = 1.0m - infoStore.GetInfoValue(InfoType.WR_ProbOpponentHasBetterWRFIXED);
            networkInputs.Add("WRProbWin", ScaleContInput(probWin));
            #endregion
            //1 inputs

            #region EV, RaiseAmounts and CheckPossibilitiy

            decimal bigBlindEVScaleAmount = 20;

            #region CallEV
            //The following EV assumes we can actually call the additionaCallAmount
            //We could cap the additionalCallAmount but we would then also not be able to win the total pot amount ;( again a minor error
            decimal actualCallCheckEV = (currentPotAmount * probWin) - ((1.0m - probWin) * additionalCallAmount);
            decimal scaledCallCheckEV = (actualCallCheckEV / currentDecision.Cache.BigBlind) / bigBlindEVScaleAmount;
            if (scaledCallCheckEV > 1)
            {
                networkInputs.Add("ScaledCallCheckEV", 1);
            }
            else if (scaledCallCheckEV < -1)
            {
                networkInputs.Add("ScaledCallCheckEV", -1);
            }
            else
            {
                networkInputs.Add("ScaledCallCheckEV", scaledCallCheckEV);
            }
            #endregion

            //Current scaled raise amounts
            //Aditional = MaximumRaiseTo - CurrentCallAmount
            decimal maximumAdditionalRaiseAmount = (infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal) + remainingPlayerStack) - (currentRoundMinPlayCallAmount);
            bool    raisePossible = false;

            if (maximumAdditionalRaiseAmount > 0)
            {
                raisePossible = true;
                if (lastAdditionalRaiseAmount > maximumAdditionalRaiseAmount)
                {
                    lastAdditionalRaiseAmount = maximumAdditionalRaiseAmount;
                }

                decimal additionalRaiseToCallAmount  = raiseToCallAmountNew - currentRoundMinPlayCallAmount;  // -infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);
                decimal additionalRaiseToStealAmount = raiseToStealAmountNew - currentRoundMinPlayCallAmount; // -infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

                if (additionalRaiseToCallAmount > maximumAdditionalRaiseAmount)
                {
                    additionalRaiseToCallAmount = maximumAdditionalRaiseAmount;
                }
                else if (additionalRaiseToCallAmount < currentDecision.Cache.BigBlind)
                {
                    additionalRaiseToCallAmount = currentDecision.Cache.BigBlind;
                }

                if (additionalRaiseToStealAmount > maximumAdditionalRaiseAmount)
                {
                    additionalRaiseToStealAmount = maximumAdditionalRaiseAmount;
                }
                else if (additionalRaiseToStealAmount < currentDecision.Cache.BigBlind)
                {
                    additionalRaiseToStealAmount = currentDecision.Cache.BigBlind;
                }

                networkInputs.Add("ScaledAdditionalRaiseToCallAmount", ScaleContInput((decimal)RaiseAmountsHelper.ScaleAdditionalRaiseAmount(currentPotAmount, currentDecision.Cache.BigBlind, lastAdditionalRaiseAmount, maximumAdditionalRaiseAmount, additionalRaiseToCallAmount)));
                networkInputs.Add("ScaledAdditionalRaiseToStealAmount", ScaleContInput((decimal)RaiseAmountsHelper.ScaleAdditionalRaiseAmount(currentPotAmount, currentDecision.Cache.BigBlind, lastAdditionalRaiseAmount, maximumAdditionalRaiseAmount, additionalRaiseToStealAmount)));
            }
            else
            {
                //No raise possible, just use defaults
                networkInputs.Add("ScaledAdditionalRaiseToCallAmount", ScaleContInput(0));
                networkInputs.Add("ScaledAdditionalRaiseToStealAmount", ScaleContInput(0));
            }

            decimal probAllOpponentFoldRaiseToCall  = infoStore.GetInfoValue(InfoType.WR_RaiseToCallStealSuccessProb);
            decimal probAllOpponentFoldRaiseToSteal = (gameStagePreFlop == 1 ? 0 : infoStore.GetInfoValue(InfoType.WR_RaiseToStealSuccessProb));

            #region RaiseToCallEV
            if (raisePossible)
            {
                decimal potAmountAssumingAllCall = currentPotAmount;

                //If we are preflop then it would be unrealistic to expect everyone to call
                //For Call we assume that if there are 8 players to act after the raise we get 2 calls
                //If there are 4 players to act after the raise we get 1 call
                //This is the same as dividing the number of activePlayers by 4
                if (gameStagePreFlop == 1)
                {
                    //We assume anyone who has already called or raised will call again
                    long[] calledRaisedPlayerIds = (from current in currentDecision.Cache.getAllHandActions()
                                                    where current.actionType == PokerAction.Call || current.actionType == PokerAction.Raise
                                                    where current.playerId != currentDecision.PlayerId
                                                    select current.playerId).ToArray();

                    for (int i = 0; i < calledRaisedPlayerIds.Length; i++)
                    {
                        potAmountAssumingAllCall += raiseToCallAmountNew - currentDecision.Cache.getPlayerCurrentRoundBetAmount(calledRaisedPlayerIds[i]);
                    }

                    potAmountAssumingAllCall += ((decimal)(activePlayerIds.Length - 1 - calledRaisedPlayerIds.Length) / 4) * raiseToCallAmountNew;
                }
                else
                {
                    for (int i = 0; i < activePlayerIds.Length; i++)
                    {
                        if (activePlayerIds[i] != currentDecision.PlayerId)
                        {
                            potAmountAssumingAllCall += raiseToCallAmountNew - currentDecision.Cache.getPlayerCurrentRoundBetAmount(activePlayerIds[i]);
                        }
                    }
                }

                decimal extraDollarRiskAmount = raiseToCallAmountNew - infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

                decimal actualRaiseToCallEV = (currentPotAmount * probAllOpponentFoldRaiseToCall) + (probWin * potAmountAssumingAllCall * (1.0m - probAllOpponentFoldRaiseToCall)) - ((1.0m - probWin) * extraDollarRiskAmount * (1.0m - probAllOpponentFoldRaiseToCall));

                decimal scaledRaiseToCallEV = (actualRaiseToCallEV / currentDecision.Cache.BigBlind) / bigBlindEVScaleAmount;
                if (scaledRaiseToCallEV > 1)
                {
                    networkInputs.Add("ScaledRaiseToCallEV", 1);
                }
                else if (scaledRaiseToCallEV < -1)
                {
                    networkInputs.Add("ScaledRaiseToCallEV", -1);
                }
                else
                {
                    networkInputs.Add("ScaledRaiseToCallEV", scaledRaiseToCallEV);
                }
            }
            else
            {
                networkInputs.Add("ScaledRaiseToCallEV", networkInputs["ScaledCallCheckEV"]);
            }
            #endregion

            #region RaiseToStealEV
            if (raisePossible)
            {
                decimal potAmountAssumingAllCall = currentPotAmount;

                //If we are preflop then it would be unrealistic to expect everyone to call
                //For steal we assume that if there are 8 players to act after the raise we get 1 call
                //If there are 4 players to act after the raise we get 0.5 call
                //This is the same as dividing the number of activePlayers by 8
                if (gameStagePreFlop == 1)
                {
                    //We assume anyone who has already raised will call again
                    long[] raisedPlayerIds = (from current in currentDecision.Cache.getAllHandActions()
                                              where current.actionType == PokerAction.Raise
                                              where current.playerId != currentDecision.PlayerId
                                              select current.playerId).ToArray();

                    for (int i = 0; i < raisedPlayerIds.Length; i++)
                    {
                        potAmountAssumingAllCall += raiseToStealAmountNew - currentDecision.Cache.getPlayerCurrentRoundBetAmount(raisedPlayerIds[i]);
                    }

                    potAmountAssumingAllCall += ((decimal)(activePlayerIds.Length - 1 - raisedPlayerIds.Length) / 8) * raiseToStealAmountNew;
                }
                else
                {
                    for (int i = 0; i < activePlayerIds.Length; i++)
                    {
                        if (activePlayerIds[i] != currentDecision.PlayerId)
                        {
                            potAmountAssumingAllCall += raiseToStealAmountNew - currentDecision.Cache.getPlayerCurrentRoundBetAmount(activePlayerIds[i]);
                        }
                    }
                }

                decimal extraDollarRiskAmount = raiseToStealAmountNew - infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

                decimal actualRaiseToStealEV = (currentPotAmount * probAllOpponentFoldRaiseToSteal) + (probWin * potAmountAssumingAllCall * (1.0m - probAllOpponentFoldRaiseToSteal)) - ((1.0m - probWin) * extraDollarRiskAmount * (1.0m - probAllOpponentFoldRaiseToSteal));
                decimal scaledRaiseToStealEV = (actualRaiseToStealEV / currentDecision.Cache.BigBlind) / bigBlindEVScaleAmount;
                if (scaledRaiseToStealEV > 1)
                {
                    networkInputs.Add("ScaledRaiseToStealEV", 1);
                }
                else if (scaledRaiseToStealEV < -1)
                {
                    networkInputs.Add("ScaledRaiseToStealEV", -1);
                }
                else
                {
                    networkInputs.Add("ScaledRaiseToStealEV", scaledRaiseToStealEV);
                }
            }
            else
            {
                networkInputs.Add("ScaledRaiseToStealEV", networkInputs["ScaledCallCheckEV"]);
            }
            #endregion

            bool checkPossible = (infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal) == infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal));
            networkInputs.Add("CheckPossible", Convert.ToDecimal(checkPossible));

            networkInputs.Add("CallAmount1BBOrLess", !checkPossible && ((decimal)infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal) - (decimal)infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal)) <= currentDecision.Cache.BigBlind ? 1 : 0);
            #endregion
            //7 inputs

            #region PAP
            networkInputs.Add("ProbRaiseToStealSuccess", ScaleContInput(probAllOpponentFoldRaiseToSteal));
            #endregion
            //1 inputs

            #region PlayerAggression
            networkInputs.Add("AvgLiveOppPreFlopPlayFreq", ScaleContInput(infoStore.GetInfoValue(InfoType.AP_AvgLiveOppPreFlopPlayFreq_Double)));
            networkInputs.Add("AvgLiveOppPostFlopPlayFreq", ScaleContInput(infoStore.GetInfoValue(InfoType.AP_AvgLiveOppPostFlopPlayFreq_Double)));
            networkInputs.Add("AvgLiveOppCurrentRoundAggr", ScaleContInput(infoStore.GetInfoValue(InfoType.AP_AvgLiveOppCurrentRoundAggr_Double)));
            networkInputs.Add("AvgLiveOppCurrentRoundAggrAcc", ScaleContInput(infoStore.GetInfoValue(InfoType.AP_AvgLiveOppCurrentRoundAggrAcc_Double)));
            #endregion
            //4 inputs

            #region BigOrSmallPot
            byte isBigPot = 0;
            if (currentPotAmount > RaiseAmountsHelper.SmallPotBBMultiplierLimit * currentDecision.Cache.BigBlind)
            {
                isBigPot = 1;
            }
            networkInputs.Add("BigPot", ScaleContInput(isBigPot));
            #endregion
            //1 input

            #region RandomInputs
            //We have 2 random inputs with different periods, per hand and per decision

            //Check the randomNumbers are not -1
            if (currentDecision.Cache.CurrentHandRandomNumber() < 0)
            {
                throw new Exception("currentDecision.Cache.CurrentHandRandomNumber() should not be less than 0");
            }

            //We disable these random numbers for the ailwyn blank network
            if (currentDecision.Cache.PokerClientId == (short)PokerClients.GeneticPokerPlayer_PlaySimpleAI_1a_FixedStart || currentDecision.Cache.PokerClientId == (short)PokerClients.GeneticPokerPlayer_PlayerSimpleAI_1b_RandomInitialisation || currentDecision.Cache.PokerClientId == (short)PokerClients.GeneticPokerPlay_PlaySimpleAI_2a || (currentDecision.AiConfigStr.StartsWith("F") && currentDecision.AiConfigStr == "FixedNeuralPlayers\\neuralV7_Ailwyn_NoRandomInput.eNN"))
            {
                networkInputs.Add("HandRandomNumber", 0);
                networkInputs.Add("DecisionRandomNumber", 0);
            }
            else
            {
                networkInputs.Add("HandRandomNumber", ScaleContInput((decimal)currentDecision.Cache.CurrentHandRandomNumber() / (decimal)int.MaxValue));
                networkInputs.Add("DecisionRandomNumber", ScaleContInput((decimal)randomGen.NextDouble()));
            }
            #endregion
            //2 inputs

            #endregion neuralInputs

            NNDataSource aiDecisionData = new NNDataSource(networkInputs.Values.ToArray(), NeuralAINNModelV7.Input_Neurons, true);

            if (true)
            {
                //Get the network outputs
                double[] networkInputsArray = null;
                aiDecisionData.returnInput(ref networkInputsArray);
                double[] networkOutput = getPlayerNetworkPrediction(currentDecision.AiConfigStr, networkInputsArray);

                //Blank the non possible actions
                if (checkPossible)
                {
                    //Blank fold
                    networkOutput[0] = 0;
                    //Blank call
                    networkOutput[2] = 0;
                }
                else
                {
                    //Blank check
                    networkOutput[1] = 0;
                }

                //Get the bot decision
                NeuralAiDecisionNeuralv7 decision = new NeuralAiDecisionNeuralv7(networkOutput, !Convert.ToBoolean(gameStageRiver), randomGen.NextDouble());

                Debug.Print("Decision");

                //Can now check the fold decision for aces
                //if (decision.BotAction == 0 && networkInputs["HoleCardsAAPair"] == 1 && gameStagePreFlop == 1 && currentDecision.AiConfigStr.StartsWith("GeneticPokerPlayers"))
                //{
                //    currentDecision.Cache.SaveToDisk("", currentDecision.PlayerId + "-" + InfoProviderBase.CurrentJob.JobId + "-" + currentDecision.Cache.getCurrentHandId() + "-" + currentDecision.Cache.getMostRecentLocalIndex()[1]);
                //}

                if (decision.BotAction == 0)
                {
                    return(new Play(PokerAction.Fold, 0, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
                }
                else if (decision.BotAction == 1)
                {
                    return(new Play(PokerAction.Check, 0, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
                }
                else if (decision.BotAction == 2)
                {
                    return(new Play(PokerAction.Call, additionalCallAmount, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
                }
                else if (decision.BotAction == 3)
                {
                    bool isSmallPot = currentPotAmount < RaiseAmountsHelper.SmallPotBBMultiplierLimit * currentDecision.Cache.BigBlind * ((decimal)(randomGen.NextDouble() * 0.2) + 0.80m);

                    //////////////////////////////////////////////////////////
                    ///////////////// START VANAHEIM FIX /////////////////////
                    //////////////////////////////////////////////////////////

                    //We add a temporary fix here for vanaheim which is playing mid pocket pairs a little strongly
                    //If we have pocket pair lower than (not including KK) have already raised and are trying to raise again we fold
                    //if (currentDecision.AiConfigStr.StartsWith("F") && !isSmallPot && gameStagePreFlop == 1 && currentDecision.AiConfigStr == "FixedNeuralPlayers\\neuralV7_Vanaheim.eNN")
                    //{
                    //    bool highPair = infoStore.GetInfoValue(InfoType.CP_HoleCardsOtherHighPair_Bool) == 1.0m;
                    //    bool midPair = infoStore.GetInfoValue(InfoType.CP_HoleCardsOtherLowPair_Bool) == 1.0m;
                    //    if (highPair || midPair)
                    //    {
                    //        if (currentRoundPlayerActions.Count(entry => entry == PokerAction.Raise) >= 1)
                    //        {
                    //            if (actualCallCheckEV > 0 && (tablePositionLate == 1 || tablePositionMid == 1) && currentRoundPlayerActions.Count(entry => entry == PokerAction.Call) == 0)
                    //                return new Play(PokerAction.Call, additionalCallAmount, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0);
                    //            else
                    //                return new Play(PokerAction.Fold, 0, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0);
                    //        }
                    //    }
                    //}

                    ////////////////////////////////////////////////////////////////////
                    /////////////////// END VANAHEIM FIX /////////////////////
                    ////////////////////////////////////////////////////////////////////

                    //Make sure raiseAmount is multiple of small blind
                    if (raisePossible)
                    {
                        decimal raiseToAmount, raiseAmountBlindMultiple;
                        /////////////////////
                        //GENETIC OR VANAHEIM 2 PLAYER FIX
                        ////////////////////
                        if (raisedTwiceOrGreaterCurrentRound && gameStagePreFlop == 1 && (currentDecision.AiConfigStr.StartsWith("G") || currentDecision.AiConfigStr == "FixedNeuralPlayers\\neuralV7_Vanaheim.eNN"))
                        {
                            //Genetic players will now go all in on their third raise preflop
                            raiseToAmount = maximumRaiseAmount;
                        }
                        else
                        {
                            decimal additionalRaiseAmount = RaiseAmountsHelper.UnscaleAdditionalRaiseAmount(currentPotAmount, currentDecision.Cache.BigBlind, lastAdditionalRaiseAmount, maximumAdditionalRaiseAmount, decision.ScaledAdditionalRaiseAmount);

                            //If the pot is currently small we raise in increments of big blind instead of little blind
                            //We add a little randomness into this limit so that it's not always exact, random number is between 0.8 and 1.0
                            if (isSmallPot)
                            {
                                ///////////////////////////////////////
                                ///// START VANAHEIM FIX //////////////
                                ///////////////////////////////////////
                                //If we are preflop with a small pot playing as vanaheim
                                //And we do not have AA or KK we can only raise to a set maximum
                                //if (currentDecision.AiConfigStr.StartsWith("F") && gameStagePreFlop == 1 && currentDecision.AiConfigStr == "FixedNeuralPlayers\\neuralV7_Vanaheim.eNN")
                                //{
                                //    bool AAPair = infoStore.GetInfoValue(InfoType.CP_HoleCardsAAPair_Bool) == 1.0m;
                                //    bool KKPair = infoStore.GetInfoValue(InfoType.CP_HoleCardsKKPair_Bool) == 1.0m;

                                //    decimal maxDesiredRaise = RaiseAmountsHelper.SmallPotBBMultiplierLimit * currentDecision.Cache.BigBlind;
                                //    if (!(AAPair || KKPair) && additionalRaiseAmount > maxDesiredRaise)
                                //        additionalRaiseAmount = maxDesiredRaise;
                                //}
                                ///////////////////////////////////////
                                ///// START VANAHEIM FIX //////////////
                                ///////////////////////////////////////

                                raiseAmountBlindMultiple = (currentRoundMinPlayCallAmount + additionalRaiseAmount) / currentDecision.Cache.BigBlind;
                                raiseToAmount            = Math.Round(raiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * currentDecision.Cache.BigBlind;
                            }
                            else
                            {
                                raiseAmountBlindMultiple = (currentRoundMinPlayCallAmount + additionalRaiseAmount) / currentDecision.Cache.LittleBlind;
                                raiseToAmount            = Math.Round(raiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * currentDecision.Cache.LittleBlind;
                            }

                            //If we are going to raise almost maximum then it might as well be max
                            if (raiseToAmount > maximumRaiseAmount * 0.9m)
                            {
                                raiseToAmount = maximumRaiseAmount;
                            }
                        }

                        return(new Play(PokerAction.Raise, raiseToAmount, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
                    }
                    else
                    {
                        return(new Play(PokerAction.Call, additionalCallAmount, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
                    }
                }
                else
                {
                    throw new Exception("Something has gone wery wong!");
                }
            }

            decisionLogStr = aiDecisionData.ToStringAdv(true);
            return(new Play(PokerAction.Fold, 0, 0, currentDecision.Cache.getCurrentHandId(), currentDecision.PlayerId, decisionLogStr, 0));
        }