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); }
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(); }
/// <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)); } }
/// <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."); } } }
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(); }