示例#1
0
        public void Go3()
        {
            Console.WriteLine("Let's get this show on the road!!");

            long[] allPlayerIds = new long[0];

            //Todo - Add players to allPlayerIds

            //Get all of the playerActions
            Console.WriteLine("Testing new network accuracy for {0} players.", allPlayerIds.Length);

            for (int i = 0; i < allPlayerIds.Length; i++)
            {
                try
                {
                    PokerPlayerNNModelv1 playerPrediction = new PokerPlayerNNModelv1();

                    playerPrediction.populatePlayActions(allPlayerIds[i], 10000, 0);
                    playerPrediction.SuffleDataSource();

                    //playerPrediction.createNetwork();
                    //playerPrediction.createTrainingSets();
                    //playerPrediction.trainNetwork();
                    playerPrediction.Network = NNLoadSave.loadNetwork("generalPlayer.eNN", "");

                    Console.WriteLine("... data loaded for player index {0} ({1}). {2} actions added.", i, allPlayerIds[i], playerPrediction.NeuralNetDataSource.Count);
                    //playerPrediction.SaveNNDataSource("allPlayerPAPData.csv");

                    playerPrediction.createTestingSets();
                    decimal accuracy = playerPrediction.getNetworkAccuracy();
                    Console.WriteLine("PlayerId:{0} Predicted {1}% Of Actions Correctly.", allPlayerIds[i], Math.Round(accuracy, 1));

                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter("accuracy.csv", true))
                        sw.WriteLine(allPlayerIds[i] + ", " + Math.Round(accuracy, 1));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Meh - Error on playerId {0}.", allPlayerIds[i]);
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter("errors.txt", true))
                        sw.WriteLine(ex.ToString());
                }
            }

            //NNLoadSave.saveNetwork(playerPrediction.Network, "generalPlayer.eNN", "");
            Console.WriteLine("... completed.");
            Console.ReadKey();
        }
        private void CalculateRaiseToBotCheck()
        {
            byte[] positionsLeftToAct           = tempLocalHandCache.positionsLeftToAct;
            PokerPlayerNNModelv1 playerActionNN = new PokerPlayerNNModelv1();

            decimal totalProbRequiredRaisersAchieved = 0;

            decimal numActivePlayers  = infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte);
            decimal numUnactedPlayers = infoStore.GetInfoValue(InfoType.GP_NumUnactedPlayers_Byte);
            decimal betsToCall        = infoStore.GetInfoValue(InfoType.BP_BetsToCall_Byte);
            decimal minimumCallAmount = infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal);
            decimal totalNumCalls     = infoStore.GetInfoValue(InfoType.BP_TotalNumCalls_Byte);
            decimal totalNumRaises    = infoStore.GetInfoValue(InfoType.BP_TotalNumRaises_Byte);
            decimal totalPotAmount    = infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal);

            if (positionsLeftToAct.Count() > 1 && betsToCall == 0)
            {
                TraverseActionProbTree(ref totalProbRequiredRaisersAchieved, 1, decisionRequest.Cache.getCurrentHandId(), positionsLeftToAct,
                                       1, PokerAction.Raise, 1, 0, (byte)numActivePlayers, (byte)(numUnactedPlayers - 1), new List <byte> {
                }, (byte)betsToCall, minimumCallAmount,
                                       (byte)totalNumCalls, (byte)totalNumRaises, totalPotAmount, playerActionNN);

                raiseToBotCheckProb = totalProbRequiredRaisersAchieved;
            }
            else
            {
                raiseToBotCheckProb = 0; //If we are last to act the prob that someone will raise our call is 0 - i.e. they never get the opportunity too.
            }
            //Need to handle possible crazy values and possible arithmetic overflows.
            if (raiseToBotCheckProb > 1 || raiseToBotCheckProb < 0)
            {
                if (raiseToBotCheckProb > 1 && Math.Round(raiseToBotCheckProb, 4) == 1)
                {
                    raiseToBotCheckProb = 1;
                }
                else if (raiseToBotCheckProb < 0 && Math.Round(raiseToBotCheckProb, 4) == 0)
                {
                    raiseToBotCheckProb = 0;
                }
                else
                {
                    throw new Exception("raiseToBotCheckProb must be between 0 and 1.");
                }
            }
        }
        /// <summary>
        /// Trains a new player network based on available database data and returns the most accurate network, previous or new.
        /// </summary>
        /// <param name="playerId"></param>
        /// <param name="currentHandId"></param>
        /// <param name="currentNetwork"></param>
        /// <returns></returns>
        protected PAPNetworkContainer trainPlayerNetwork(long playerId, long currentHandId, PAPNetworkContainer previousNetwork, long startingHandId, int maxTrainingActions)
        {
            DateTime startTime = DateTime.Now;

            PAPNetworkContainer  returnNetworkContainer;
            PokerPlayerNNModelv1 playerPredictionNNModel = new PokerPlayerNNModelv1();

            playerPredictionNNModel.populatePlayActions(playerId, maxTrainingActions, startingHandId);
            playerPredictionNNModel.SuffleDataSource();

            if (playerPredictionNNModel.DataSourceCount < minActionsRequiredForNetwork)
            {
                return(previousNetwork);
            }

            playerPredictionNNModel.createNetwork();
            playerPredictionNNModel.createTrainingSets();
            playerPredictionNNModel.trainNetwork();
            playerPredictionNNModel.createTestingSets();

            BasicNetwork newPlayerNetwork   = playerPredictionNNModel.Network;
            decimal      newNetworkAccuracy = playerPredictionNNModel.getNetworkAccuracy();

            //We need to get the accuracy of the previous network on the new data so that it is a fair comparison
            playerPredictionNNModel.Network = previousNetwork.PlayerNetworkPool.BaseNetwork;
            decimal previousNetworkAccuracy = playerPredictionNNModel.getNetworkAccuracy();

            if (newNetworkAccuracy > previousNetworkAccuracy)
            {
                previousNetwork.UpdateNetwork(newPlayerNetwork, newNetworkAccuracy, playerPredictionNNModel.DataSourceCount, currentHandId);
            }
            else
            {
                //Regardless of whether we replace network/accuracy, we reset the trainingActions and mostRecentHandId
                previousNetwork.UpdateNetwork(previousNetwork.PlayerNetworkPool.BaseNetwork, previousNetworkAccuracy, playerPredictionNNModel.DataSourceCount, currentHandId);
            }

            returnNetworkContainer = previousNetwork;

            //SerializeObject.Save(PAP_STORE + playerId.ToString() + ".PAPdat", returnNetworkContainer);
            returnNetworkContainer.SavePAPContainer(PAP_STORE, playerId.ToString());
            return(returnNetworkContainer);
        }
示例#4
0
        public void Go2()
        {
            Console.WriteLine("Let's get this show on the road!!");

            //Get all of the playerActions
            for (int i = 0; i < 20; i++)
            {
                PokerPlayerNNModelv1 playerPrediction = new PokerPlayerNNModelv1();
                playerPrediction.LoadNNDatasource("allPlayerPAPData.csv", PokerPlayerNNModelv1.Input_Neurons, PokerPlayerNNModelv1.Output_Neurons);

                playerPrediction.SuffleDataSource();
                playerPrediction.createNetwork();
                playerPrediction.createTrainingSets();
                playerPrediction.trainNetwork();
                playerPrediction.createTestingSets();
                decimal accuracy = playerPrediction.getNetworkAccuracy();

                Console.WriteLine("Achieved {0}% accuracy.", accuracy);
                NNLoadSave.saveNetwork(playerPrediction.Network, accuracy.ToString() + "_generalPlayer.eNN", "");
            }

            Console.WriteLine("... completed.");
            Console.ReadKey();
        }
示例#5
0
        /// <summary>
        /// Works through the probability tree of possible player actions and sums the paths where
        /// the number of callers or raisers in that path is equal to or greater than numCallersRequired
        /// </summary>
        /// <param name="numCallersRequired"></param>
        /// <param name="?"></param>
        protected void TraverseActionProbTree(ref decimal totalProbRequiredActionAchieved,
                                              decimal pathProb,
                                              long handId,
                                              byte[] positionsLeftToAct,
                                              byte playerPositionIndex,
                                              PokerAction actionToCount,
                                              byte minActionCountRequired,
                                              byte currentActionCount,
                                              byte numActivePlayers,
                                              byte numUnactedPlayers,
                                              List <byte> simulatedFoldPositions,
                                              byte betsToCall,
                                              decimal callAmount,
                                              byte totalNumCalls,
                                              byte totalNumRaises,
                                              decimal totalPotAmount,
                                              PokerPlayerNNModelv1 playerActionNN)
        {
            decimal tempPathProb;
            PlayerActionPrediction predictedAction;

            long currentPlayerId = decisionRequest.Cache.getPlayerId(positionsLeftToAct[playerPositionIndex]);

            if (!tempLocalPlayerCacheDict.ContainsKey(currentPlayerId))
            {
                throw new Exception("Player information not stored in local cache. Make sure to call BuildTempPlayerCache().");
            }

            //We need to check to see if this player is all in
            //If this player is all in we will just ignore them for now and try to move on
            if (tempLocalPlayerCacheDict[currentPlayerId].playerStack == 0)
            {
                do
                {
                    playerPositionIndex++;

                    if (playerPositionIndex >= positionsLeftToAct.Count())
                    {
                        playerPositionIndex--;
                        break;
                    }

                    currentPlayerId = decisionRequest.Cache.getPlayerId(positionsLeftToAct[playerPositionIndex]);
                    if (!tempLocalPlayerCacheDict.ContainsKey(currentPlayerId))
                    {
                        throw new Exception("Player information not stored in local cache. Make sure to call BuildTempPlayerCache().");
                    }
                } while (tempLocalPlayerCacheDict[currentPlayerId].playerStack == 0);

                //If the last player is all in just return as it wont affect the probabilities at this section of the tree.
                if (tempLocalPlayerCacheDict[currentPlayerId].playerStack == 0)
                {
                    if (currentActionCount >= minActionCountRequired)
                    {
                        totalProbRequiredActionAchieved += pathProb;
                    }

                    return;
                }
            }

            predictedAction = PredictPlayerAction(handId,
                                                  currentPlayerId,
                                                  numActivePlayers,
                                                  numUnactedPlayers,
                                                  simulatedFoldPositions,
                                                  betsToCall,
                                                  callAmount,
                                                  totalNumCalls,
                                                  totalNumRaises,
                                                  totalPotAmount,
                                                  false,
                                                  playerActionNN);

            //If we predict a raise we just return this path now
            if (predictedAction.PredictedAction == PokerAction.Raise)
            {
                if (currentActionCount + 1 >= minActionCountRequired)
                {
                    totalProbRequiredActionAchieved += pathProb * predictedAction.Accuracy;
                }
                else
                {
                    //This line will rarely be used as we will only ever be looking for 1 raiser or more!
                    totalProbRequiredActionAchieved += pathProb * ((1 - predictedAction.Accuracy));
                }

                return;
            }

            //If we have reached the end of the tree
            if (positionsLeftToAct.Count() == playerPositionIndex + 1)
            {
                if (actionToCount == PokerAction.Call)
                {
                    //If we have already achieved the correct number of action counts at this point
                    //We don't care about the current prediction action
                    if (currentActionCount >= minActionCountRequired)
                    {
                        totalProbRequiredActionAchieved += pathProb;
                    }
                    else
                    {
                        //If we predicted a call then increment the current action count.
                        if (predictedAction.PredictedAction == PokerAction.Call)
                        {
                            currentActionCount++;
                        }

                        //Right, have we now hit the necessary minimum??
                        if (currentActionCount >= minActionCountRequired)
                        {
                            totalProbRequiredActionAchieved += pathProb * predictedAction.Accuracy;
                        }
                        else if (positionsLeftToAct.Count() == 1)
                        {
                            //The only exception is if we are predicting for a single player
                            if (predictedAction.PredictedAction == PokerAction.Call)
                            {
                                totalProbRequiredActionAchieved += pathProb * predictedAction.Accuracy;
                            }
                            else
                            {
                                totalProbRequiredActionAchieved += pathProb * (1 - predictedAction.Accuracy);
                            }
                        }
                        else if (currentActionCount + 1 >= minActionCountRequired)
                        {
                            totalProbRequiredActionAchieved += pathProb * (1 - predictedAction.Accuracy);
                        }
                    }
                }
                else if (actionToCount == PokerAction.Raise)
                {
                    //If a raise was predicted it would have been returned above
                    //If we have reached this point we have not predicted a raise anywhere along the line
                    totalProbRequiredActionAchieved += pathProb * (1 - predictedAction.Accuracy);
                }
                else
                {
                    throw new Exception("We should not be counting any other action at the moment.");
                }
            }
            else
            {
                //We are in the middle of the tree and need to get REALLY F*****G FANCY!!!

                //Call down the tree as if this player called
                //If we predicted a call then we modify the pathProb with *= confidence
                //If we predicted a fold then we modify the pathProb with *= 1- confidence
                decimal newPathMultipler;

                if (actionToCount == PokerAction.Raise)
                {
                    newPathMultipler = (1 - predictedAction.Accuracy);
                }
                else
                {
                    newPathMultipler = (predictedAction.PredictedAction == PokerAction.Call ? predictedAction.Accuracy : (1 - predictedAction.Accuracy));
                }

                tempPathProb = pathProb * newPathMultipler;

                TraverseActionProbTree(ref totalProbRequiredActionAchieved,
                                       tempPathProb,
                                       handId,
                                       positionsLeftToAct,
                                       (byte)(playerPositionIndex + 1),
                                       actionToCount,
                                       minActionCountRequired,
                                       (byte)(currentActionCount + 1),
                                       numActivePlayers,
                                       (byte)(numUnactedPlayers - 1),
                                       simulatedFoldPositions,
                                       (byte)(betsToCall + 1),
                                       callAmount,
                                       (byte)(totalNumCalls + 1),
                                       totalNumRaises,
                                       totalPotAmount + callAmount,
                                       playerActionNN);

                newPathMultipler = (predictedAction.PredictedAction == PokerAction.Check ? predictedAction.Accuracy : (1 - predictedAction.Accuracy));
                tempPathProb     = pathProb * newPathMultipler;
                simulatedFoldPositions.Add(positionsLeftToAct.ElementAt(playerPositionIndex));

                //Call down the tree as if this player folded
                TraverseActionProbTree(ref totalProbRequiredActionAchieved,
                                       tempPathProb,
                                       handId,
                                       positionsLeftToAct,
                                       (byte)(playerPositionIndex + 1),
                                       actionToCount,
                                       minActionCountRequired,
                                       currentActionCount,
                                       (byte)(numActivePlayers - 1),
                                       (byte)(numUnactedPlayers - 1),
                                       simulatedFoldPositions,
                                       betsToCall,
                                       callAmount,
                                       totalNumCalls,
                                       totalNumRaises,
                                       totalPotAmount,
                                       playerActionNN);

                simulatedFoldPositions.Remove(positionsLeftToAct.ElementAt(playerPositionIndex));
            }
        }
示例#6
0
        /// <summary>
        /// Predict a players next action using the current cache reference.
        /// </summary>
        /// <param name="handId"></param>
        /// <param name="playerId"></param>
        /// <returns></returns>
        protected PlayerActionPrediction PredictPlayerAction(long handId, long predictPlayerId, decimal numActivePlayers,
                                                             decimal numUnactedPlayers, List <byte> simulatedFoldPositions, decimal betsToCall, decimal minCallAmount, decimal totalNumCalls, decimal totalNumRaises, decimal totalPotAmount, bool logNetworkInputs, PokerPlayerNNModelv1 playerActionNN)
        {
            //Load the network.
            decimal networkAccuracy = 0;

            //playerActionNN.Network = networkManager.getPlayerNetwork(predictPlayerId, ref networkAccuracy);

            if (tempLocalHandCache.handId != handId)
            {
                throw new Exception("The tempLocalHandCache has not been updated.");
            }

            Dictionary <string, decimal> networkInputs = new Dictionary <string, decimal>();

            #region compileNetworkInputs
            decimal playerCurrentRoundBetAmount;
            decimal totalPlayerMoneyInPot;
            decimal playerTotalStack;
            bool    playerLastRoundCall;
            bool    playerLastRoundRaise;
            decimal RFreq_PostFlop, CFreq_PostFlop, PreFlopPlayFreq;

            if (tempLocalPlayerCacheDict.Count != 0)
            {
                tempPlayerCache playerDetails;

                if (tempLocalPlayerCacheDict.ContainsKey(predictPlayerId))
                {
                    playerDetails = tempLocalPlayerCacheDict[predictPlayerId];
                }
                else
                {
                    throw new Exception("Played not found - The tempLocalPlayerCache should be built before PredictPlayerAction is called.");
                }

                playerCurrentRoundBetAmount = playerDetails.currentRoundPlayerBetAmount;
                totalPlayerMoneyInPot       = playerDetails.totalPlayerMoneyInPot;
                playerLastRoundCall         = playerDetails.playerLastRoundCall;
                playerLastRoundRaise        = playerDetails.playerLastRoundRaise;
                playerTotalStack            = playerDetails.playerStack;
                RFreq_PostFlop  = playerDetails.RFreq_PostFlop;
                CFreq_PostFlop  = playerDetails.CFreq_PostFlop;
                PreFlopPlayFreq = playerDetails.PreFlopPlayFreq;
            }
            else
            {
                throw new Exception("No entries - The tempLocalPlayerCache should be built before PredictPlayerAction is called.");
            }

            decimal imPotOdds;
            if (minCallAmount > 0)
            {
                //The immediatePotOdds will always be larger than 1 al the way to 10,000 (assuming $100 pot size and a $0.01 call amount)
                //Most immedaitePotOdds seem to fall between 1 and 10 (i.e. if a pot already has $5 in it the minimum expected call will be around $0.50)
                //A @imPotOdds = 1 means the pot odds are very good i.e. better than 10:1
                //A @imPotOdds = 0 means the pot odds are crap i.e. 1:1
                //cache.getPlayerCurrentRoundBetAmount(predictPlayerId, out playerCurrentRounBetAmount);
                decimal useThisCallAmount;
                if (minCallAmount > playerTotalStack + playerCurrentRoundBetAmount)
                {
                    useThisCallAmount = playerTotalStack + playerCurrentRoundBetAmount;
                }
                else
                {
                    useThisCallAmount = minCallAmount;
                }

                imPotOdds = ((totalPotAmount / (useThisCallAmount - playerCurrentRoundBetAmount)) / 10.0m) - 0.1m;
                if (imPotOdds > 1)
                {
                    imPotOdds = 1;
                }
                else if (imPotOdds < 0)
                {
                    throw new Exception("Error in predictPlayerAction. ImmediatePotOdds should never be negative. TotalPot: " + totalPotAmount.ToString() + ", MinCallAmount: " + minCallAmount.ToString() + ", PlayerCurrentRoundBetAmount:" + playerCurrentRoundBetAmount.ToString());
                }
            }
            else
            {
                imPotOdds = 1;
            }

            networkInputs.Add("ImPotOdds", imPotOdds);

            //Compile all inputs
            decimal raiseRatio = 0;
            if (totalNumRaises + totalNumCalls > 0)
            {
                raiseRatio = totalNumRaises / (totalNumRaises + totalNumCalls);
            }

            networkInputs.Add("RaiseRatio", raiseRatio);
            networkInputs.Add("PotRatio", totalPlayerMoneyInPot / totalPotAmount); // Own Money In Pot / Total Amount In Pot

            //Bets to Call
            decimal betsToCall0 = 0, betsToCall1 = 0, betsToCall2Greater = 0;
            if (betsToCall == 0)
            {
                betsToCall0 = 1;
            }
            else if (betsToCall == 1)
            {
                betsToCall1 = 1;
            }
            else if (betsToCall > 1)
            {
                betsToCall2Greater = 1;
            }
            else
            {
                throw new Exception("Meh!");
            }

            networkInputs.Add("BetsToCall0", betsToCall0);
            networkInputs.Add("BetsToCall1", betsToCall1);
            networkInputs.Add("BetsToCall2Greater", betsToCall2Greater);

            //Gamestage
            byte    gameStage = tempLocalHandCache.gameStage;
            decimal gameStage0 = 0, gameStage1 = 0, gameStage2 = 0, gameStage3 = 0;
            if (gameStage == 0)
            {
                gameStage0 = 1;
            }
            else if (gameStage == 1)
            {
                gameStage1 = 1;
            }
            else if (gameStage == 2)
            {
                gameStage2 = 1;
            }
            else if (gameStage == 3)
            {
                gameStage3 = 1;
            }
            else
            {
                throw new Exception("Meh!");
            }

            networkInputs.Add("GameStage0", gameStage0);
            networkInputs.Add("GameStage1", gameStage1);
            networkInputs.Add("GameStage2", gameStage2);
            networkInputs.Add("GameStage3", gameStage3);

            networkInputs.Add("PlayerLastRoundCall", Convert.ToDecimal(playerLastRoundCall));
            networkInputs.Add("PlayerLastRoundRaise", Convert.ToDecimal(playerLastRoundRaise));

            networkInputs.Add("DealtInPlayersRatio", tempLocalHandCache.numPlayersDealtIn / tempLocalHandCache.numTableSeats);
            networkInputs.Add("ActivePlayersRatio", numActivePlayers / tempLocalHandCache.numPlayersDealtIn);
            networkInputs.Add("UnactedPlayersRatio", numUnactedPlayers / numActivePlayers);

            networkInputs.Add("FlushPossible", Convert.ToDecimal(tempLocalHandCache.flushPossible));
            networkInputs.Add("StraightPossible", Convert.ToDecimal(tempLocalHandCache.straightPossible));
            networkInputs.Add("AceOnBoard", Convert.ToDecimal(tempLocalHandCache.aceOnBoard));
            networkInputs.Add("KingOnBoard", Convert.ToDecimal(tempLocalHandCache.kingOnBoard));
            networkInputs.Add("AceKingQueenRatio", tempLocalHandCache.aceKingQueenRatio);

            ////This is wrong and not going to work as we don't know where the simulated folded players sit!!
            //float dealerDistance = (cache.getActivePlayerDistanceToDealer(predictPlayerId) - (float)numSimulatedFoldPlayers) - 1  / ((float)numActivePlayers - 1);
            //Distance to dealer for this player
            networkInputs.Add("DealerDistance", 0);

            //Some aggression information
            networkInputs.Add("PreFlopPlayFreq", PreFlopPlayFreq);
            networkInputs.Add("CFreq_PostFlop", CFreq_PostFlop);
            networkInputs.Add("RFreq_PostFlop", RFreq_PostFlop);

            #endregion

            NNDataSource networkInputSource = new NNDataSource(networkInputs.Values.ToArray(), PokerPlayerNNModelv1.Input_Neurons);

            //Get the network output
            double[] networkInput = null;
            networkInputSource.returnInput(ref networkInput);
            double[] networkOutput = networkManager.getPlayerNetworkPrediction(predictPlayerId, networkInput, ref networkAccuracy);
            PlayerActionPrediction predictedAction = new PlayerActionPrediction(networkOutput[0], networkOutput[1], networkOutput[2], networkAccuracy);

#if logging
            logger.Debug("PPA," + handId + ", " + predictPlayerId + ",, " + networkInputSource.ToString() + ",, " + GenerateMD5(networkManager.GetDefaultNetwork()) + ", ," + networkOutput[0] + ", ," + networkOutput[1] + ", ," + networkOutput[2]);
#endif

            //Return as PlayerActionPrediction struct
            return(predictedAction);
        }
        private void CalculateFoldToBotCall()
        {
            byte[]  positionsLeftToAct          = tempLocalHandCache.positionsLeftToAct;
            decimal minimumCallAmount           = infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal);
            PokerPlayerNNModelv1 playerActionNN = new PokerPlayerNNModelv1();

            if (positionsLeftToAct.Count() > 1 && minimumCallAmount > 0)
            {
                PlayerActionPrediction predictedAction;
                List <byte>            simulatedFoldPositions = new List <byte>();
                decimal probFold = 1;

                decimal trueMinCallAmount = decisionRequest.Cache.getMinimumPlayAmount();
                decimal virtualCallAmount;

                //To make this accuracte we need to have some bet amount.
                if (trueMinCallAmount == 0)
                {
                    virtualCallAmount = decisionRequest.Cache.BigBlind;
                }
                else
                {
                    virtualCallAmount = trueMinCallAmount;
                }


                for (int i = 1; i < positionsLeftToAct.Count(); i++)
                {
                    //If the current trueMinCallAmount = 0, then we simulate a raise our end
                    if (trueMinCallAmount == 0)
                    {
                        predictedAction = PredictPlayerAction(decisionRequest.Cache.getCurrentHandId(), decisionRequest.Cache.getPlayerId(positionsLeftToAct.ElementAt(i)), infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) - i + 1,
                                                              infoStore.GetInfoValue(InfoType.GP_NumUnactedPlayers_Byte) - i, simulatedFoldPositions, infoStore.GetInfoValue(InfoType.BP_BetsToCall_Byte) + 1, virtualCallAmount,
                                                              infoStore.GetInfoValue(InfoType.BP_TotalNumCalls_Byte), infoStore.GetInfoValue(InfoType.BP_TotalNumRaises_Byte) + 1, infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal) + virtualCallAmount, false, playerActionNN);
                    }
                    else
                    {
                        predictedAction = PredictPlayerAction(decisionRequest.Cache.getCurrentHandId(), decisionRequest.Cache.getPlayerId(positionsLeftToAct.ElementAt(i)), infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte) - i + 1,
                                                              infoStore.GetInfoValue(InfoType.GP_NumUnactedPlayers_Byte) - i, simulatedFoldPositions, infoStore.GetInfoValue(InfoType.BP_BetsToCall_Byte) + 1, virtualCallAmount,
                                                              infoStore.GetInfoValue(InfoType.BP_TotalNumCalls_Byte) + 1, infoStore.GetInfoValue(InfoType.BP_TotalNumRaises_Byte), infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal) + virtualCallAmount, false, playerActionNN);
                    }

                    if (predictedAction.PredictedAction == PokerAction.Fold)
                    {
                        probFold *= 1 * predictedAction.Accuracy;
                    }
                    else
                    {
                        probFold *= 1 - (1 * predictedAction.Accuracy);
                    }
                }

                foldToBotCallProb = probFold;
            }
            else
            {
                foldToBotCallProb = 0;
            }

            if (foldToBotCallProb > 1 || foldToBotCallProb < 0)
            {
                if (foldToBotCallProb > 1 && Math.Round(foldToBotCallProb, 4) == 1)
                {
                    foldToBotCallProb = 1;
                }
                else if (foldToBotCallProb < 0 && Math.Round(foldToBotCallProb, 4) == 0)
                {
                    foldToBotCallProb = 0;
                }
                else
                {
                    throw new Exception("foldToBotCallProb must be between 0 and 1.");
                }
            }
        }
        private void CalculateRaiseToCallAmount1Players()
        {
            //byte[] activePositions = cache.getActivePositions(cache.getCurrentHandDetails().dealerPosition);
            byte[] activePositions              = (from local in tempLocalPlayerCacheDict.Values select local.playerPosition).ToArray();
            byte[] positionsLeftToAct           = tempLocalHandCache.positionsLeftToAct;
            PokerPlayerNNModelv1 playerActionNN = new PokerPlayerNNModelv1();

            List <byte> positionsRequiredToActAfterRaise = new List <byte>();

            positionsRequiredToActAfterRaise.AddRange(positionsLeftToAct);
            positionsRequiredToActAfterRaise.AddRange(activePositions.Except(positionsLeftToAct));
            positionsRequiredToActAfterRaise.Remove(decisionRequest.Cache.getPlayerPosition(decisionRequest.PlayerId));

            //Raise To Call Amount
            //What is the maximum the bot can raise to guarantee 1 or more callers
            decimal totalProbRequiredCallersAchieved;

            decimal numActivePlayers  = infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte);
            decimal numUnactedPlayers = positionsRequiredToActAfterRaise.Count();
            decimal betsToCall        = infoStore.GetInfoValue(InfoType.BP_BetsToCall_Byte);
            decimal minimumCallAmount = infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal);
            decimal totalNumCalls     = infoStore.GetInfoValue(InfoType.BP_TotalNumCalls_Byte);
            decimal totalNumRaises    = infoStore.GetInfoValue(InfoType.BP_TotalNumRaises_Byte);
            decimal totalPotAmount    = infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal);
            decimal lastRaiseAmount   = infoStore.GetInfoValue(InfoType.BP_LastAdditionalRaiseAmount);

            decimal bigBlind    = decisionRequest.Cache.BigBlind;
            decimal littleBlind = decisionRequest.Cache.LittleBlind;

            #region MaximumRaiseAmount
            //Initialise the maximum raiseAmount to sensible values
            //These are more of a safety net than anything else.
            decimal maximumRaiseToAmount;
            if (totalPotAmount < bigBlind * 4)
            {
                maximumRaiseToAmount = bigBlind * 8;
            }
            else
            {
                maximumRaiseToAmount = totalPotAmount;
            }

            decimal maxRaiseAmountBlindMultiple = maximumRaiseToAmount / littleBlind;
            maximumRaiseToAmount = Math.Round(maxRaiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * littleBlind;
            #endregion

            #region MinimumRaiseAmount
            decimal minimumRaiseToAmount = (2 * lastRaiseAmount) + (minimumCallAmount - lastRaiseAmount);
            //If the minimumRaiseAmount is less than or equal to 2 blind and the pot is less than 4BB
            if (minimumRaiseToAmount <= 2 * bigBlind && totalPotAmount <= 4 * bigBlind)
            {
                if (randomNumbers[1] > 0.5)
                {
                    minimumRaiseToAmount = 3 * bigBlind;
                }
                else
                {
                    minimumRaiseToAmount = 3.5m * bigBlind;
                }
            }
            else if (minimumRaiseToAmount <= 2 * bigBlind && totalPotAmount > 4 * bigBlind)
            {
                minimumRaiseToAmount = 0.6m * totalPotAmount;
            }

            //Round the minimumRaiseToAmount UP TO (+1) the nearest blind multitple
            decimal minRaiseAmountBlindMultiple = minimumRaiseToAmount / littleBlind;
            minimumRaiseToAmount = (Math.Round(minRaiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) + 1) * littleBlind;
            #endregion

            #region Calculation
            decimal raiseToCallAmount1Callers = minimumRaiseToAmount;
            decimal raiserStackAmount         = decisionRequest.Cache.getPlayerStack(decisionRequest.PlayerId);

            List <decimal> raiseAmountsTried = new List <decimal>();
            bool           nextRaiseAmountGreaterThanPrevious = false;

            do
            {
                totalProbRequiredCallersAchieved = 0;
                raiseToCallAmount1Callers        = NextRaiseAmount(minimumRaiseToAmount, raiseAmountsTried, nextRaiseAmountGreaterThanPrevious);
                raiseAmountsTried.Add(raiseToCallAmount1Callers);

                if (raiseToCallAmount1Callers > raiserStackAmount)
                {
                    raiseToCallAmount1Callers = raiserStackAmount;
                    break;
                }
                else if (raiseToCallAmount1Callers < minimumRaiseToAmount)
                {
                    raiseToCallAmount1Callers = minimumRaiseToAmount;
                    break;
                }

                TraverseActionProbTree(ref totalProbRequiredCallersAchieved, 1, decisionRequest.Cache.getCurrentHandId(), positionsRequiredToActAfterRaise.ToArray(),
                                       0, PokerAction.Call, 1, 0, (byte)numActivePlayers, (byte)numUnactedPlayers, new List <byte> {
                }, (byte)(betsToCall + 1), raiseToCallAmount1Callers,
                                       (byte)totalNumCalls, (byte)(totalNumRaises + 1), totalPotAmount + raiseToCallAmount1Callers, playerActionNN);

                if (totalProbRequiredCallersAchieved > raiseToCallTheshold)
                {
                    nextRaiseAmountGreaterThanPrevious = true;
                }
                else
                {
                    nextRaiseAmountGreaterThanPrevious = false;
                }
            } while (raiseAmountsTried.Count() < 8);

            if (raiseToCallAmount1Callers > maximumRaiseToAmount)
            {
                raiseToCallAmount1Callers = maximumRaiseToAmount;
            }

            if (raiseToCallAmount1Callers < minimumRaiseToAmount)
            {
                raiseToCallAmount1Callers = minimumRaiseToAmount;
            }

            decimal raiseToCallAmountBlindMultiple = raiseToCallAmount1Callers / littleBlind;
            raiseToCallAmount1Callers = Math.Round(raiseToCallAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * littleBlind;

            decimal playerAlreadyBetAmount = infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

            if (raiseToCallAmount1Callers > (raiserStackAmount + playerAlreadyBetAmount) * 0.75m)
            {
                raiseToCallAmount1Callers = raiserStackAmount + playerAlreadyBetAmount;
            }

            raiseToCallAmount1Players = raiseToCallAmount1Callers;

            #endregion
        }
        private void CalculateRaiseToSteal()
        {
            decimal totalProbRequiredCallersAchieved;
            decimal probRaiseToStealSuccess;
            PokerPlayerNNModelv1 playerActionNN = new PokerPlayerNNModelv1();

            //byte[] activePositions = cache.getActivePositions(cache.getCurrentHandDetails().dealerPosition);
            byte[] activePositions    = (from local in tempLocalPlayerCacheDict.Values select local.playerPosition).ToArray();
            byte[] positionsLeftToAct = tempLocalHandCache.positionsLeftToAct;

            decimal raiserStackAmount = decisionRequest.Cache.getPlayerStack(decisionRequest.PlayerId);

            List <byte> positionsRequiredToActAfterRaise = new List <byte>();

            positionsRequiredToActAfterRaise.AddRange(positionsLeftToAct);
            positionsRequiredToActAfterRaise.AddRange(activePositions.Except(positionsLeftToAct));
            positionsRequiredToActAfterRaise.Remove(decisionRequest.Cache.getPlayerPosition(decisionRequest.PlayerId));

            decimal numActivePlayers  = infoStore.GetInfoValue(InfoType.GP_NumActivePlayers_Byte);
            decimal numUnactedPlayers = positionsRequiredToActAfterRaise.Count();
            decimal betsToCall        = infoStore.GetInfoValue(InfoType.BP_BetsToCall_Byte);
            decimal minimumCallAmount = infoStore.GetInfoValue(InfoType.BP_MinimumPlayAmount_Decimal);
            decimal totalNumCalls     = infoStore.GetInfoValue(InfoType.BP_TotalNumCalls_Byte);
            decimal totalNumRaises    = infoStore.GetInfoValue(InfoType.BP_TotalNumRaises_Byte);
            decimal totalPotAmount    = infoStore.GetInfoValue(InfoType.BP_TotalPotAmount_Decimal);
            decimal lastRaiseAmount   = infoStore.GetInfoValue(InfoType.BP_LastAdditionalRaiseAmount);

            decimal bigBlind    = decisionRequest.Cache.BigBlind;
            decimal littleBlind = decisionRequest.Cache.LittleBlind;

            #region MaximumRaiseAmount
            //Initialise the maximum raiseAmount to sensible values
            //These are more of a safety net than anything else.
            decimal maximumRaiseToAmount;
            if (totalPotAmount < bigBlind * 4)
            {
                maximumRaiseToAmount = bigBlind * 8;
            }
            else
            {
                maximumRaiseToAmount = 2 * totalPotAmount;
            }

#if logging
            logger.Debug("maximumRaiseToAmount (PreScale) =" + maximumRaiseToAmount);
#endif

            decimal maxRaiseAmountBlindMultiple = maximumRaiseToAmount / littleBlind;
            maximumRaiseToAmount = Math.Round(maxRaiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * littleBlind;

#if logging
            logger.Debug("maximumRaiseToAmount (PostScale) =" + maximumRaiseToAmount);
#endif

            #endregion

            #region MinimumRaiseAmount
            decimal minimumRaiseToAmount = (2 * lastRaiseAmount) + (minimumCallAmount - lastRaiseAmount);
            //If the minimumRaiseAmount is less than or equal to 2 blind and the pot is less than 4BB
            if (minimumRaiseToAmount <= 2 * bigBlind && totalPotAmount <= 4 * bigBlind)
            {
                if (randomNumbers[0] > 0.5)
                {
                    minimumRaiseToAmount = 3 * bigBlind;
                }
                else
                {
                    minimumRaiseToAmount = 4 * bigBlind;
                }
            }
            else if (minimumRaiseToAmount <= 2 * bigBlind && totalPotAmount > 4 * bigBlind)
            {
                minimumRaiseToAmount = 0.6m * totalPotAmount;
            }

#if logging
            logger.Debug("minimumRaiseToAmount (PreScale) =" + minimumRaiseToAmount);
#endif

            //Round the minimumRaiseToAmount UPTO (+1) the nearest blind multitple
            decimal minRaiseAmountBlindMultiple = minimumRaiseToAmount / littleBlind;
            minimumRaiseToAmount = (Math.Round(minRaiseAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) + 1) * littleBlind;

#if logging
            logger.Debug("minimumRaiseToAmount (PostScale) =" + minimumRaiseToAmount);
#endif

            #endregion

            //Start the raiseToCallAmount off at the calculated minimumRaiseAmount
            decimal        raiseToCallAmount0Callers          = minimumRaiseToAmount;
            List <decimal> raiseAmountsTried                  = new List <decimal>();
            bool           nextRaiseAmountGreaterThanPrevious = false;

            do
            {
                totalProbRequiredCallersAchieved = 0;
                raiseToCallAmount0Callers        = NextRaiseAmount(minimumRaiseToAmount, raiseAmountsTried, nextRaiseAmountGreaterThanPrevious);
                raiseAmountsTried.Add(raiseToCallAmount0Callers);

#if logging
                logger.Debug("Testing raise amount " + raiseToCallAmount0Callers);
#endif

                if (raiseToCallAmount0Callers > raiserStackAmount)
                {
                    raiseToCallAmount0Callers = raiserStackAmount;
                    break;
                }
                else if (raiseToCallAmount0Callers < minimumRaiseToAmount)
                {
                    raiseToCallAmount0Callers = minimumRaiseToAmount;
                    break;
                }

                TraverseActionProbTree(ref totalProbRequiredCallersAchieved, 1, decisionRequest.Cache.getCurrentHandId(), positionsRequiredToActAfterRaise.ToArray(),
                                       0, PokerAction.Call, 1, 0, (byte)numActivePlayers, (byte)numUnactedPlayers, new List <byte> {
                }, (byte)(betsToCall + 1), raiseToCallAmount0Callers,
                                       (byte)totalNumCalls, (byte)(totalNumRaises + 1), totalPotAmount + raiseToCallAmount0Callers, playerActionNN);

#if logging
                logger.Debug("    totalProbRequiredCallersAchieved = " + totalProbRequiredCallersAchieved);
#endif

                if (totalProbRequiredCallersAchieved > raiseToStealThreshold)
                {
                    nextRaiseAmountGreaterThanPrevious = true;
                }
                else
                {
                    nextRaiseAmountGreaterThanPrevious = false;
                }
            } while (raiseAmountsTried.Count() < 8);

            raiseToCallAmount0Callers *= 1.2m;


#if logging
            logger.Debug("Selected raise amount * 1.2 (PreScale) = " + raiseToCallAmount0Callers);
#endif

            //We now want to round up the raiseToStealAmount to nearest blind multiple
            decimal raiseToStealAmountBlindMultiple = raiseToCallAmount0Callers / littleBlind;
            raiseToCallAmount0Callers = Math.Round(raiseToStealAmountBlindMultiple, 0, MidpointRounding.AwayFromZero) * littleBlind;

#if logging
            logger.Debug("Selected raise amount * 1.2 (PostScale) = " + raiseToStealAmountBlindMultiple);
#endif

            if (raiseToCallAmount0Callers > maximumRaiseToAmount)
            {
                raiseToCallAmount0Callers = maximumRaiseToAmount;
            }

            decimal playerAlreadyBetAmount = infoStore.GetInfoValue(InfoType.BP_PlayerBetAmountCurrentRound_Decimal);

            if (raiseToCallAmount0Callers > (decisionRequest.Cache.getPlayerStack(decisionRequest.PlayerId) + playerAlreadyBetAmount) * 0.75m)
            {
                raiseToCallAmount0Callers = decisionRequest.Cache.getPlayerStack(decisionRequest.PlayerId) + playerAlreadyBetAmount;
            }

#if logging
            logger.Debug("Getting final steal success prob using = " + raiseToCallAmount0Callers);
#endif

            //Work out the final probability of having atleast 1 caller
            totalProbRequiredCallersAchieved = 0;
            TraverseActionProbTree(ref totalProbRequiredCallersAchieved, 1, decisionRequest.Cache.getCurrentHandId(), positionsRequiredToActAfterRaise.ToArray(),
                                   0, PokerAction.Call, 1, 0, (byte)numActivePlayers, (byte)numUnactedPlayers, new List <byte> {
            }, (byte)(betsToCall + 1), raiseToCallAmount0Callers,
                                   (byte)totalNumCalls, (byte)(totalNumRaises + 1), totalPotAmount + raiseToCallAmount0Callers, playerActionNN);

            probRaiseToStealSuccess = (1 - totalProbRequiredCallersAchieved);

#if logging
            logger.Debug("probRaiseToStealSuccess = " + probRaiseToStealSuccess + ", raiseToStealAmount = " + raiseToCallAmount0Callers);
#endif

            //Set the output values
            raiseToStealAmount      = raiseToCallAmount0Callers;
            raiseToStealSuccessProb = probRaiseToStealSuccess;

            if (raiseToStealSuccessProb > 1 || raiseToStealSuccessProb < 0)
            {
                if (raiseToStealSuccessProb > 1 && Math.Round(raiseToStealSuccessProb, 4) == 1)
                {
                    raiseToStealSuccessProb = 1;
                }
                else if (raiseToStealSuccessProb < 0 && Math.Round(raiseToStealSuccessProb, 4) == 0)
                {
                    raiseToStealSuccessProb = 0;
                }
                else
                {
                    throw new Exception("raiseToStealSuccessProb must be between 0 and 1.");
                }
            }
        }
示例#10
0
        public void Go()
        {
            double[][] networkPredictedOutputs;

            byte   idealColumn;
            double outputMaxValue1st  = -1;
            byte   outputColumn       = byte.MaxValue;
            int    correctPredictions = 0;

            Console.WriteLine("Let's get this show on the road!!");

            long[] allPlayerIds = new long[0];

            //Todo - Add players to allPlayerIds

            //Before we do PAP we need select specific players based on agression
            //int numHandsCounted=0;
            //double RFreq_PreFlop=0, RFreq_PostFlop=0, CFreq_PreFlop=0, CFreq_PostFlop=0, PreFlopPlayFreq=0;
            //using (System.IO.StreamWriter sw = new System.IO.StreamWriter("playerAggression.csv", false))
            //{
            //    for (int i = 0; i < allPlayerIds.Length; i++)
            //    {
            //        //Break the stats down for the top player to find out what is the needed number of hands for a good answer
            //        //for (int j = 0; j < 353; j++)
            //        //{
            //            numHandsCounted = 0; RFreq_PreFlop = 0; RFreq_PostFlop = 0; CFreq_PreFlop = 0; CFreq_PostFlop = 0; PreFlopPlayFreq = 0;
            //            databaseQueries.PlayerAgressionMetrics(allPlayerIds[i],10000, 1, 1, ref numHandsCounted, ref RFreq_PreFlop, ref RFreq_PostFlop, ref CFreq_PreFlop, ref CFreq_PostFlop, ref PreFlopPlayFreq);
            //            //sw.WriteLine("{0},{1},{2},{3},{4},{5},{6}", allPlayerIds[i], numHandsCounted, RFreq_PreFlop, RFreq_PostFlop, CFreq_PreFlop, CFreq_PostFlop, PreFlopPlayFreq);
            //            sw.WriteLine("{0},{1},{2},{3},{4},{5}", allPlayerIds[i], RFreq_PreFlop, RFreq_PostFlop, CFreq_PreFlop, CFreq_PostFlop, PreFlopPlayFreq);
            //            //Console.WriteLine(j);
            //        //}
            //        sw.Flush();
            //        Console.WriteLine(i);
            //    }
            //}

            //return;
            PokerPlayerNNModelv1 playerPrediction = new PokerPlayerNNModelv1();

            //Get all of the playerActions
            if (true)
            {
                Console.WriteLine("Loading PAP data for {0} players.", allPlayerIds.Length);
                for (int i = 0; i < allPlayerIds.Length; i++)
                {
                    try
                    {
                        playerPrediction.populatePlayActions(allPlayerIds[i], 10000, 0);
                        Console.WriteLine("... data loaded for player index {0} ({1}). {2} actions added.", i, allPlayerIds[i], playerPrediction.NeuralNetDataSource.Count);
                        playerPrediction.SaveNNDataSource("allPlayerPAPData.csv");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Meh - Error on playerId {0}.", allPlayerIds[i]);
                        using (System.IO.StreamWriter sw = new System.IO.StreamWriter("errors.txt", true))
                            sw.WriteLine(ex.ToString());
                    }
                }
            }
            else
            {
                Console.WriteLine("Loading NNData...");
                playerPrediction.LoadNNDatasource("allPlayerPAPData.csv", PokerPlayerNNModelv1.Input_Neurons, PokerPlayerNNModelv1.Output_Neurons);
                Console.WriteLine("... complete.");
            }

            Console.WriteLine("Shuffling NNData...");
            playerPrediction.SuffleDataSource();
            Console.WriteLine("... complete.");

            Console.WriteLine("Initiating training ...");

            //playerPrediction.createNetwork();
            playerPrediction.Network = NNLoadSave.loadNetwork("generalPlayer.eNN", "");
            //neuralPokerAI.getBotAiNN(false);
            playerPrediction.createTrainingSets();
            playerPrediction.trainNetwork();
            playerPrediction.createTestingSets();

            networkPredictedOutputs = new double[playerPrediction.NetworkInput.Length][];
            ;

            //Create the output array
            for (int i = 0; i < networkPredictedOutputs.Length; i++)
            {
                networkPredictedOutputs[i] = new double[PokerPlayerNNModelv1.Output_Neurons];
            }

            Stopwatch timer = new Stopwatch();

            timer.Start();
            playerPrediction.testNetwork(networkPredictedOutputs);
            timer.Stop();

            for (int i = 0; i < networkPredictedOutputs.GetLength(0); i++)
            {
                outputMaxValue1st = -1;

                //Determine if the output match the ideal
                if (playerPrediction.NetworkIdealOutput[i][0] == 1)
                {
                    idealColumn = 0;
                }
                else if (playerPrediction.NetworkIdealOutput[i][1] == 1)
                {
                    idealColumn = 1;
                }
                else if (playerPrediction.NetworkIdealOutput[i][2] == 1)
                {
                    idealColumn = 2;
                }
                else
                {
                    throw new Exception("This should never happen");
                }

                if (networkPredictedOutputs[i][0] > outputMaxValue1st)
                {
                    outputMaxValue1st = networkPredictedOutputs[i][0];
                    outputColumn      = 0;
                }

                if (networkPredictedOutputs[i][1] > outputMaxValue1st)
                {
                    outputMaxValue1st = networkPredictedOutputs[i][1];
                    outputColumn      = 1;
                }

                if (networkPredictedOutputs[i][2] > outputMaxValue1st)
                {
                    outputMaxValue1st = networkPredictedOutputs[i][2];
                    outputColumn      = 2;
                }

                if (outputColumn == byte.MaxValue)
                {
                    throw new Exception("This should not happen!");
                }

                if (outputColumn != idealColumn)
                {
                    Console.WriteLine("****  Actual-{0},Predicted-{1} - [{2}, {3}, {4}]", idealColumn, outputColumn, String.Format("{0:0.00}", networkPredictedOutputs[i][0]), String.Format("{0:0.00}", networkPredictedOutputs[i][1]), String.Format("{0:0.00}", networkPredictedOutputs[i][2]));
                }
                else
                {
                    //if (idealColumn == 4)
                    //Console.WriteLine("Actual-{0}, Predicted-{1} - [{2}, {3}, {4}, {5}, {6}]", idealColumn, outputColumn, String.Format("{0:0.00}", networkPredictedOutputs[i][0]), String.Format("{0:0.00}", networkPredictedOutputs[i][1]), String.Format("{0:0.00}", networkPredictedOutputs[i][2]), String.Format("{0:0.00}", networkPredictedOutputs[i][3]), String.Format("{0:0.00}", networkPredictedOutputs[i][4]));
                    //Console.WriteLine("Actual-{0},Predicted-{1} - [{2}, {3}, {4}]", idealColumn, outputColumn, String.Format("{0:0.00}", networkPredictedOutputs[i][0]), String.Format("{0:0.00}", networkPredictedOutputs[i][1]), String.Format("{0:0.00}", networkPredictedOutputs[i][2]));
                    correctPredictions++;
                }
            }

            Console.WriteLine("Predicted {0}% Of Actions Correctly.", ((double)correctPredictions / (double)(int)(playerPrediction.DataSourceCount - (int)(playerPrediction.DataSourceCount * playerPrediction.Train_Data_Percent))) * 100);
            Console.WriteLine("Per network compute - {0}ms.", (double)timer.ElapsedMilliseconds / ((double)(playerPrediction.DataSourceCount - (int)(playerPrediction.DataSourceCount * playerPrediction.Train_Data_Percent))));
            //Console.WriteLine("Predicted {0}% Of Actions Correctly.", ((double)correctPredictions / (double)(int)(playerPrediction.DataSourceCount)) * 100);

            NNLoadSave.saveNetwork(playerPrediction.Network, "generalPlayerNew.eNN", "");

            Console.ReadKey();
        }