public void Update(long playerId, databaseCache currentCache) { if (maintainRecentCacheHistory) { lock (updateQueue) updateQueue.Enqueue(new UpdateItem(currentCache)); } else { //We need to guarantee the table is in the cacheTracker for the winRatio provider before this method returns lock (locker) { if (tableCaches.ContainsKey(currentCache.TableId)) { tableCaches[currentCache.TableId].Refresh(); } else { tableCaches.Add(currentCache.TableId, new tableCache(currentCache.TableId, currentCache)); } } lock (updateQueue) updateQueue.Enqueue(new UpdateItem(currentCache.getSatInPlayerIds(), currentCache.TableId, currentCache.getCurrentHandId())); } }
protected static void LogPAPError(Exception ex, databaseCache cache) { //Save the cache for later checking and try again string fileName = LogError.Log(ex, "AIError_PAP"); cache.SaveToDisk("", fileName); }
public CacheMonitor(databaseCache genericCache, bool showNonBotPlayerCardsOnly) { InitializeComponent(); this.testMode = false; this.showNonBotPlayerCardsOnly = showNonBotPlayerCardsOnly; InitialiseMonitor(genericCache); }
/// <summary> /// Creates a new update item and creates a NEW COPY of the passed cache /// Can we quite slow ~ 1ms. /// </summary> /// <param name="cache"></param> public UpdateItem(databaseCache cache) { currentHandId = cache.getCurrentHandId(); playerIds = cache.getSatInPlayerIds(); tableId = cache.TableId; cache = databaseCache.DeSerialise(cache.Serialise()); }
private void PreDecisionErrorChecking(long playerId, databaseCache genericGameCache) { if (runInSafeMode) { #region Basic Error Checking if (!(genericGameCache.getCurrentHandId() > 0)) { throw new Exception("getCurrentHandId() returns an invalid value."); } byte[] positionsLeftToAct = genericGameCache.getActivePositionsLeftToAct(); if (positionsLeftToAct.Length == 0) { throw new Exception("Positions left to act contains no elements."); } if (positionsLeftToAct[0] != genericGameCache.getPlayerPosition(playerId)) { throw new Exception("First position left to act should always be the specified player - otherwise why are we trying to determine an action yet."); } if (!genericGameCache.getPlayerDetails(playerId).isBot) { throw new Exception("Decision requested for player who is not marked as a bot."); } if (genericGameCache.TableId == 0) { throw new Exception("Cache Table Id is 0 which cannot be correct!"); } #endregion } }
public static void LogAIError(Exception ex, databaseCache cache) { //Save the cache for later checking and try again WebLogging.AddLog("GPA", WebLogging.LogCategory.AIError, "AI error logged - " + ex.ToString()); string errorFileName = "pokerAIError " + DateTime.Now.Hour.ToString() + "." + DateTime.Now.Minute.ToString() + "." + DateTime.Now.Second.ToString() + "." + DateTime.Now.Millisecond.ToString() + " " + DateTime.Now.ToString("dd-MM-yyyy"); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(errorFileName + ".log", false)) { sw.WriteLine("Hand Id: " + cache.getCurrentHandId().ToString() + " Player Id: " + cache.getPlayerId(cache.getCurrentActiveTablePosition()).ToString()); if (ex.GetBaseException() != null) { sw.WriteLine("Base Exception Type: " + ex.GetBaseException().ToString()); } if (ex.InnerException != null) { sw.WriteLine("Inner Exception Type: " + ex.InnerException.ToString()); } if (ex.StackTrace != null) { sw.WriteLine(""); sw.WriteLine("Stack Trace: " + ex.StackTrace.ToString()); } File.WriteAllBytes(errorFileName + ".FBPcache", cache.Serialise()); sw.Close(); } }
/// <summary> /// Creates a new update item but only using playerIds and tableId. Cache reference remains null /// </summary> /// <param name="playerIds"></param> /// <param name="tableId"></param> public UpdateItem(long[] playerIds, long tableId, long handId) { this.currentHandId = handId; this.playerIds = playerIds; this.tableId = tableId; this.cache = null; }
public DecisionRequest(long playerId, databaseCache cache, AIGeneration serverType, string aiConfigStr, bool aiManagerInSafeMode) { this.playerId = playerId; this.cache = cache; this.serverType = serverType; this.aiConfigStr = aiConfigStr; this.aiManagerInSafeMode = aiManagerInSafeMode; this.decisionSignal = new ManualResetEvent(false); }
public CacheMonitor(databaseCache genericCache, bool testMode, bool showActivePlayerCardsOnly) { InitializeComponent(); this.Icon = global::PokerBot.CacheMonitor.Properties.Resources.chip; this.showActivePlayerCardsOnly = showActivePlayerCardsOnly; this.testMode = testMode; if (testMode) { timer.Interval = 2000; } InitialiseMonitor(genericCache); }
/// <summary> /// Trigger an update of all info providers in 1st instance /// </summary> /// <returns></returns> private void UpdateInfoStore(long playerId, databaseCache currentCache, InfoCollection localInfoStore, List <InfoProviderBase> localInfoProviders) { //Update the shared cache tracker for the current cache cacheTracker.Update(playerId, currentCache); //Reset all update flags to false localInfoStore.ResetAllUpdateFlags(); foreach (var provider in localInfoProviders) { provider.TriggerUpdateInfo(playerId, currentCache, cacheTracker); } foreach (var provider in localInfoProviders) { provider.UpdateFinished(providersTimeOutMilliSeconds); } }
public TableModel(databaseCache cache, WinRatioProvider wrProv, bool useAllPlayersCards) { this.tableId = cache.TableId; this.numPlayers = cache.NumSeats; this.wrProv = wrProv; //playersOld = new Dictionary<long, PlayerModel>(numPlayers); playersNew = new Dictionary <long, PlayerModelFixed>(numPlayers); var satDownPositions = cache.getSatDownPositions(); for (byte i = 0; i < numPlayers; i++) { if (satDownPositions.Contains(i)) { //playersOld.Add(cache.getPlayerId(i), new PlayerModel(tableId, cache.getCurrentHandId(), cache.getPlayerId(i), wrProv)); playersNew.Add(cache.getPlayerId(i), new PlayerModelFixed(tableId, cache.BigBlind, cache.getCurrentHandId(), cache.getPlayerId(i), wrProv)); } } }
public void InitialiseMonitor(databaseCache genericCache, long playerIdCards) { this.genericCache = genericCache; playerControls = new Control[10, 7] { { player0Name, player0Stack, player0Card1, player0Card2, player0Action, pos0Sitout, pos0Disabled }, { player1Name, player1Stack, player1Card1, player1Card2, player1Action, pos1Sitout, pos1Disabled }, { player2Name, player2Stack, player2Card1, player2Card2, player2Action, pos2Sitout, pos2Disabled }, { player3Name, player3Stack, player3Card1, player3Card2, player3Action, pos3Sitout, pos3Disabled }, { player4Name, player4Stack, player4Card1, player4Card2, player4Action, pos4Sitout, pos4Disabled }, { player5Name, player5Stack, player5Card1, player5Card2, player5Action, pos5Sitout, pos5Disabled }, { player6Name, player6Stack, player6Card1, player6Card2, player6Action, pos6Sitout, pos6Disabled }, { player7Name, player7Stack, player7Card1, player7Card2, player7Action, pos7Sitout, pos7Disabled }, { player8Name, player8Stack, player8Card1, player8Card2, player8Action, pos8Sitout, pos8Disabled }, { player9Name, player9Stack, player9Card1, player9Card2, player9Action, pos9Sitout, pos9Disabled }, }; //By default we hide the manual buttons. showHideManualButtons(false); echoHoleCards = 0; onlyShowCardsForPlayerId = playerIdCards; updateTableUI(); }
//public double GetProbAnyPlayerHasBetterHandOld(databaseCache cache, long playerId, ushort winPercentage) //{ // //return 0; // double prob = 1.0; // var playerCards = cache.getPlayerHoleCards(playerId); // //for each player that isn't us find out probability that we have better cards than them and multiply together // foreach (var player in playersOld) // { // if (player.Key != playerId) // prob *= (1.0 - player.Value.GetProbHaveBetterWinPercentageThan(winPercentage, (Card)playerCards.holeCard1, (Card)playerCards.holeCard2)); // } // //return 1 - prob that we have better cards than all players // prob = Math.Round(1.0 - prob, 4); // if (prob >= 0 && prob <= 1) // return prob; // if (prob > 1.0 && Math.Round(prob, 4) == 1) // return 1; // if (prob < 0 && Math.Round(prob, 4) == 0) // return 0; // throw new Exception("Cannot have probability that gets us here!!!"); //} public double GetProbAnyPlayerHasBetterHandNew(databaseCache cache, long playerId, ushort winPercentage) { //return 0; double prob = 1.0; var playerCards = cache.getPlayerHoleCards(playerId); //for each player that isn't us find out probability that we have better cards than them and multiply together foreach (var player in playersNew) { if (player.Key != playerId) { prob *= (1.0 - player.Value.GetProbHaveBetterWinPercentageThan(winPercentage, (Card)playerCards.holeCard1, (Card)playerCards.holeCard2)); } } //return 1 - prob that we have better cards than all players prob = Math.Round(1.0 - prob, 4); if (prob >= 0 && prob <= 1) { return(prob); } if (prob > 1.0 && Math.Round(prob, 4) == 1) { return(1); } if (prob < 0 && Math.Round(prob, 4) == 0) { return(0); } throw new Exception("Cannot have probability that gets us here!!!"); }
public tableCache(long tableId, databaseCache cache) { this.tableId = tableId; this.cache = cache; lastRefresh = DateTime.Now; }
public void UpdateCache(databaseCache cache) { this.cache = cache; lastRefresh = DateTime.Now; }
public CacheMonitor(databaseCache genericCache) { InitializeComponent(); this.testMode = false; InitialiseMonitor(genericCache); }
/// <summary> /// Validates the AI action. /// Prevents raises when only calls are possible. /// Prevents raising more than allowed. /// Prevent raising less than allowed. /// </summary> /// <param name="aiAction">The AI action to be validated.</param> /// <returns>The validated decision.</returns> public static Play ValidatePlayerDecision(Play oldAiAction, databaseCache cache) { //PlayerId passed through because "cache.getCurrentActiveTablePosition()" is a slow method. //long playerId = cache.getPlayerId(cache.getCurrentActiveTablePosition()); long playerId = oldAiAction.PlayerId; decimal minCallAmount = cache.getMinimumPlayAmount(); decimal currentRoundBetAmount = cache.getPlayerCurrentRoundBetAmount(playerId); decimal playerRemaningStack = cache.getPlayerStack(playerId); //if (oldAiAction.PlayerId != playerId) // throw new Exception("Current active table position does not correspond with bot player position."); //Copy the action here so that we can still see the old one for debugging reasons. //Once we know this is stable we can get rid of this line. Play aiAction = new Play(oldAiAction.Serialise()); //We need to make sure a raise is possible byte[] activePositions = cache.getActivePositions(); byte numPlayersAllIn = (byte)cache.getAllInPositions().Length; //We need to ensure the bot is not calling dead, i.e. if the winPercentage is less than 5% we should not be calling after the river if (aiAction.Action == PokerAction.Fold) { //Check for the free check if (minCallAmount - currentRoundBetAmount == 0) { aiAction.Action = PokerAction.Check; } } else if (aiAction.Action == PokerAction.Call) { //We must call atleast the minimum amount if (minCallAmount - currentRoundBetAmount > aiAction.Amount) { aiAction.Amount = minCallAmount; } //We cannot call 0, it should be a check if (minCallAmount - currentRoundBetAmount == 0) { aiAction.Action = PokerAction.Check; aiAction.Amount = 0; } else if (minCallAmount - currentRoundBetAmount > playerRemaningStack) { //We cannot call more than the stack amount aiAction.Amount = playerRemaningStack; } //Never call a 0 amount!!! if (aiAction.Amount == 0 && aiAction.Action == PokerAction.Call) { aiAction.Action = PokerAction.Check; } } else if (aiAction.Action == PokerAction.Raise) { //If the raiseToAmount is less than the minimum allowable raise then raise the minimum. decimal lastAdditionalRaiseAmount = cache.getCurrentRoundLastRaiseAmount(); decimal minimumRaiseToAmount = (minCallAmount - lastAdditionalRaiseAmount) + (lastAdditionalRaiseAmount * 2); if (aiAction.Amount < minimumRaiseToAmount) { aiAction.Amount = minimumRaiseToAmount; } //if (aiAction.Amount > (cache.getCurrentHandDetails().potValue * 2)) // aiAction.Amount = cache.getCurrentHandDetails().potValue * 2; //If the raiseToAmount is more than we are able to raise then raise the maximum amount possible. if (aiAction.Amount > currentRoundBetAmount + playerRemaningStack) { aiAction.Amount = currentRoundBetAmount + playerRemaningStack; } if (minCallAmount - currentRoundBetAmount >= playerRemaningStack) { //If we are trying to raise but we cannot even meet the minimum call then call stack aiAction.Action = PokerAction.Call; aiAction.Amount = playerRemaningStack; } else if (numPlayersAllIn + 1 == activePositions.Length) { //If everyone else is all in then calling is our only option aiAction.Action = PokerAction.Call; aiAction.Amount = minCallAmount - currentRoundBetAmount; //If we already have the right amount in the pot we can only check if (aiAction.Amount == 0) { aiAction.Action = PokerAction.Check; } } } //If we are still trying to call a 0 amounts somthing else has gone very wrong if (aiAction.Amount == 0 && aiAction.Action == PokerAction.Call) { throw new Exception("Critical validation error - trying to call 0 amount."); } /* * if (oldAiAction.Amount != aiAction.Amount || oldAiAction.Action != aiAction.Action) * throw new Exception("Validation Error"); */ return(aiAction); }
public void GetRaiseCallStealAmounts(databaseCache cache, long playerId, out decimal call, out decimal steel, out double probStealSuccess, out double probCallSuccess) { var playersInHand = cache.getActivePlayerIds(); call = decimal.MinValue; steel = decimal.MinValue; decimal callTemp, stealTemp; double stealProbTemp, callProbTemp; probStealSuccess = 0; probCallSuccess = 0; HandState stage; var details = cache.getCurrentHandDetails(); if (details.tableCard1 == 0) { stage = HandState.PreFlop; } else if (details.tableCard4 == 0) { stage = HandState.Flop; } else if (details.tableCard5 == 0) { stage = HandState.Turn; } else { stage = HandState.River; } var playerCards = cache.getPlayerHoleCards(playerId); decimal minExtraRaise = (cache.getCurrentRoundLastRaiseAmount() == 0 ? cache.BigBlind : cache.getCurrentRoundLastRaiseAmount()); decimal maxExtraRaise = cache.getPlayerStack(playerId) - cache.getMinimumPlayAmount() + cache.getPlayerCurrentRoundBetAmount(playerId); double numberOpponents = cache.getActivePositions().Length - cache.getAllInPositions().Length - 1; if (playersInHand.Length > cache.getAllInPositions().Length + 1 && maxExtraRaise > 0) { foreach (var player in playersNew) { if (player.Key != playerId && playersInHand.Contains(player.Key)) { if (cache.getAllInPositions().Contains(cache.getPlayerPosition(player.Key))) { continue; } var dd = (cache.getActivePlayerDistanceToDealer(player.Key) - 1.0) / (cache.getActivePositions().Length - 1.0); player.Value.GetRaiseCallSteal(stage, (Card)playerCards.holeCard1, (Card)playerCards.holeCard2, dd < 0.5, details.potValue, minExtraRaise, maxExtraRaise, Math.Pow(0.5, 1.0 / numberOpponents), Math.Pow(0.75, 1.0 / numberOpponents), out callTemp, out stealTemp, out stealProbTemp, out callProbTemp); if (callTemp > call) { call = callTemp; probCallSuccess = callProbTemp; } if (stealTemp > steel) { steel = stealTemp; probStealSuccess = stealProbTemp; } } } probStealSuccess = Math.Pow(probStealSuccess, numberOpponents); probCallSuccess = Math.Pow(probCallSuccess, numberOpponents); } else { call = minExtraRaise; steel = minExtraRaise; probStealSuccess = 0; probCallSuccess = 0; } decimal currentMinPlayAmount = cache.getMinimumPlayAmount(); decimal minRaise = minExtraRaise + currentMinPlayAmount; decimal maxRaise = maxExtraRaise + currentMinPlayAmount; call += currentMinPlayAmount; steel += currentMinPlayAmount; decimal callChange = call * 0.2m * (decimal)(wrProv.randomGen.NextDouble() - 0.5); decimal stealChange = steel * 0.2m * (decimal)(wrProv.randomGen.NextDouble() - 0.5); if (Math.Abs(callChange) < cache.LittleBlind) { callChange = cache.LittleBlind * callChange / Math.Abs(callChange); } if (Math.Abs(stealChange) < cache.LittleBlind) { stealChange = cache.LittleBlind * stealChange / Math.Abs(stealChange); } call += callChange; call = Math.Round(call / cache.LittleBlind, 0, MidpointRounding.AwayFromZero) * cache.LittleBlind; if (call < minRaise) { call = minRaise; } if (call > maxRaise) { call = maxRaise; } steel += stealChange; steel = Math.Round(steel / cache.LittleBlind, 0, MidpointRounding.AwayFromZero) * cache.LittleBlind; if (steel < minRaise) { steel = minRaise; } if (steel > maxRaise) { steel = maxRaise; } }
/// <summary> /// Initiaties a decision but overrides the player config using the specified serverType and configStr /// </summary> /// <param name="handId"></param> /// <param name="playerId"></param> /// <param name="genericGameCache"></param> /// <returns></returns> public Play GetDecision(long playerId, databaseCache genericGameCache, AIGeneration serverType, string aiConfigStr) { try { //AIGeneration serverType; //string aiConfigStr; int selectedInstanceIndex; //Check for any simple errors PreDecisionErrorChecking(playerId, genericGameCache); //Determine which instance to use selectedInstanceIndex = DetermineAvailableInstance(); //Enter the correct lock lock (instanceLocks[selectedInstanceIndex]) { //Update the infostore //If anything in the InfoStore throws any error it will be caught by the catch //in this method, and thus logged correctly. UpdateInfoStore(playerId, genericGameCache, infoStoreCollection[selectedInstanceIndex], infoProviderCollection[selectedInstanceIndex]); //Get the correct AI version and configuration for this player if (serverType == AIGeneration.Undefined || aiConfigStr == null) { cacheTracker.playerAiConfig(playerId, genericGameCache.TableId, out serverType, out aiConfigStr); } //Pick that aiServer from the available list var aiServer = from server in aiCollection[selectedInstanceIndex] where server.AiType == serverType select server; if (aiServer.Count() != 1) { throw new Exception("Unable to select correct AI from those avaialble."); } //Get the ai decision Play aiAction = aiServer.First().GetDecision(playerId, aiConfigStr, genericGameCache, infoStoreCollection[selectedInstanceIndex]); aiAction = SetDecisionTime(ValidatePlayerDecision(aiAction, genericGameCache)); //Signal this decision as finished and let another one through. lock (idlelocker) { instancesIdle = instancesIdle | (1 << selectedInstanceIndex); //aiAvailableEvent.Set(); } return(aiAction); } } catch (Exception ex) { //Reset idle instances (the locks will protected and potential multithreading problems). instancesIdle = 0; for (int i = 0; i < numInstances; i++) { instancesIdle = instancesIdle | (1 << i); } genericGameCache.readLockCounter = 0; LogAIError(ex, genericGameCache); return(new Play(PokerAction.GeneralAIError, 0, 0, genericGameCache.getCurrentHandId(), playerId, ex.ToString(), 3)); } throw new Exception("Should never get here!"); }
public void UpdatePlayerModels(databaseCache cache) { //First get hand details var handDetails = cache.getCurrentHandDetails(); //If hand id has changed since last time then some reseting is needed if (cache.getCurrentHandId() != lastHandIdConsidered) { //reset variables lastHandIdConsidered = cache.getCurrentHandId(); wasRaisedPot = false; wasHandState = HandState.PreFlop; lastActionIdConsidered = -1; //get keys in players dictionary and players in cache who are sat in //long[] keys = playersOld.Keys.ToArray(); long[] satInPlayerIds = cache.getSatInPlayerIds(); lastNumberActivePlayers = cache.PlayerIdsStartedHand().Length; //Remove from players all items that don't correspond to sat in players //long[] toRemove = keys.Except(satInPlayerIds).ToArray(); //for (byte i = 0; i < toRemove.Length; i++) // playersOld.Remove(toRemove[i]); //Go through each seat //for (int i = 0; i < satInPlayerIds.Length; i++) //{ // //Get player id for person in seat // long pid = satInPlayerIds[i]; // //and the player is not in dictionary add them, otherwise reset their entry // if (!playersOld.ContainsKey(pid)) // playersOld.Add(pid, new PlayerModel(tableId, lastHandIdConsidered, pid, wrProv)); // else // playersOld[pid].ResetProbsToDefault(lastHandIdConsidered); // playersOld[pid].UpdateCardsWinPercentages(new Card[] { }, lastNumberActivePlayers); //} //get keys in players dictionary and players in cache who are sat in long[] keys = playersNew.Keys.ToArray(); //Remove from players all items that don't correspond to sat in players long[] toRemove = keys.Except(satInPlayerIds).ToArray(); for (byte i = 0; i < toRemove.Length; i++) { playersNew.Remove(toRemove[i]); } //Go through each seat for (int i = 0; i < satInPlayerIds.Length; i++) { //Get player id for person in seat long pid = satInPlayerIds[i]; //and the player is not in dictionary add them, otherwise reset their entry if (!playersNew.ContainsKey(pid)) { playersNew.Add(pid, new PlayerModelFixed(tableId, cache.BigBlind, lastHandIdConsidered, pid, wrProv)); } else { playersNew[pid].ResetProbsToDefault(lastHandIdConsidered); } playersNew[pid].UpdateCardsWinPercentages(new Card[] { }, lastNumberActivePlayers); } } //Setup cards array based on cards that were present at end of last update Card[] cards = new Card[0]; switch (wasHandState) { case HandState.Flop: cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3) }; break; case HandState.Turn: cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3), (Card)(handDetails.tableCard4) }; break; case HandState.River: cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3), (Card)(handDetails.tableCard4), (Card)(handDetails.tableCard5) }; break; } //Get all dealer and betting actions since last update var handActions = cache.getHandActions(lastHandIdConsidered); handActions = (from a in handActions where a.localIndex > lastActionIdConsidered && (a.actionType == PokerAction.Check || a.actionType == PokerAction.Call || a.actionType == PokerAction.Raise || a.actionType == PokerAction.Fold || a.actionType == PokerAction.DealFlop || a.actionType == PokerAction.DealTurn || a.actionType == PokerAction.DealRiver) orderby a.localIndex select a).ToArray(); //Get a list of active players by the end of the hand actions above var activePlayers = cache.getActivePlayerIds(); //Now go through each new hand action foreach (var handAction in handActions) { //if the action is a dealer action then update hand state, change raised pot flag and for each active player update card probs change after deal if (handAction.actionType == PokerAction.DealFlop) { wasHandState = HandState.Flop; wasRaisedPot = false; cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3) }; foreach (var player in activePlayers) { //playersOld[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard1)); //playersOld[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard2)); //playersOld[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard3)); playersNew[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard1)); playersNew[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard2)); playersNew[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard3)); } continue; } else if (handAction.actionType == PokerAction.DealTurn) { wasHandState = HandState.Turn; wasRaisedPot = false; cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3), (Card)(handDetails.tableCard4) }; foreach (var player in activePlayers) { //playersOld[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard4)); playersNew[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard4)); } continue; } else if (handAction.actionType == PokerAction.DealRiver) { wasHandState = HandState.River; wasRaisedPot = false; cards = new Card[] { (Card)(handDetails.tableCard1), (Card)(handDetails.tableCard2), (Card)(handDetails.tableCard3), (Card)(handDetails.tableCard4), (Card)(handDetails.tableCard5) }; foreach (var player in activePlayers) { //playersOld[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard5)); playersNew[player].UpdateProbsAfterCardDealt((Card)(handDetails.tableCard5)); } continue; } else if (handAction.actionType == PokerAction.Fold) { //if a player has folded set all their probabilities of having cards to zero and reduce number of active players //if (playersOld.ContainsKey(handAction.playerId)) // playersOld[handAction.playerId].SetAllProbsToZeroOnFold(); if (playersNew.ContainsKey(handAction.playerId)) { playersNew[handAction.playerId].SetAllProbsToZeroOnFold(); } lastNumberActivePlayers--; continue; } //otherwise we're dealing with a betting action so they should be in active players if (activePlayers.Contains(handAction.playerId)) { //Update win percentages and indices in player model and update card probs based on action //playersOld[handAction.playerId].UpdateCardsWinPercentages(cards, lastNumberActivePlayers); playersNew[handAction.playerId].UpdateCardsWinPercentages(cards, lastNumberActivePlayers); decimal ra = 0, ca = 0, pa = 0; double dd; if (handAction.actionType == PokerAction.Raise) { ra = cache.getCurrentRoundLastRaiseAmount(handAction.localIndex + 1L); } if (wasRaisedPot) { ca = cache.getMinimumPlayAmount(handAction.localIndex) - cache.getPlayerCurrentRoundBetAmount(handAction.playerId, handAction.localIndex); } pa = cache.getPotUpToActionId(handAction.localIndex); dd = (cache.getActivePlayerDistanceToDealer(handAction.playerId, handAction.localIndex) - 1.0) / (cache.getActivePositions(handAction.localIndex).Length - 1.0); //playersOld[handAction.playerId].UpdateCardProbsBasedOnAction(handAction.actionType, wasHandState, ca, ra, pa, wasRaisedPot, dd < 0.5); playersNew[handAction.playerId].UpdateCardProbsBasedOnAction(handAction.actionType, wasHandState, ca, ra, pa, wasRaisedPot, dd < 0.5); } //Finally if the action was a raise we now have a raised pot if (handAction.actionType == PokerAction.Raise) { wasRaisedPot = true; } } //for (int i = 0; i < activePlayers.Length; i++) // playersOld[activePlayers[i]].UpdateCardsWinPercentages(cards, activePlayers.Length); for (int i = 0; i < activePlayers.Length; i++) { playersNew[activePlayers[i]].UpdateCardsWinPercentages(cards, activePlayers.Length); } //finally update last action considered and last number players if (handActions.Count() > 0) { lastActionIdConsidered = handActions.Last().localIndex; } lastNumberActivePlayers = activePlayers.Length; }
public void InitialiseMonitor(databaseCache genericCache) { InitialiseMonitor(genericCache, -1); }
/// <summary> /// Default GetDecision which gets the correct player config from the database. /// </summary> /// <param name="playerId"></param> /// <param name="genericGameCache"></param> /// <returns></returns> public Play GetDecision(long playerId, databaseCache genericGameCache) { return(GetDecision(playerId, genericGameCache, AIGeneration.Undefined, null)); }
/// <summary> /// Initiaties a decision but overrides the player config using the specified serverType and configStr /// </summary> /// <param name="handId"></param> /// <param name="playerId"></param> /// <param name="genericGameCache"></param> /// <returns></returns> public Play GetDecision(long playerId, databaseCache genericGameCache, AIGeneration serverType, string aiConfigStr) { try { //Sort out the cacheTracker CacheTracker.Instance.Update(playerId, genericGameCache); if (serverType == AIGeneration.Undefined || aiConfigStr == null) { CacheTracker.Instance.PlayerAiConfig(playerId, genericGameCache.TableId, out serverType, out aiConfigStr); } DecisionRequest newRequest = new DecisionRequest(playerId, genericGameCache, serverType, aiConfigStr, AIManager.RunInSafeMode); PreDecisionErrorChecking(newRequest.PlayerId, newRequest.Cache); //For now we will just use the old method //Determine an available AIInstance int selectedInstanceIndex = DetermineAvailableInstance(newRequest); //This could be done in a seperate thread if (selectedInstanceIndex == -1) { //There were no available instances so we join the queue and wait newRequest.WaitForDecision(); } else { if (ConcurrencyMode.Concurrency == ConcurrencyMode.ConcurencyModel.MultiCore) { Task t = Task.Factory.StartNew(aiInstanceList[selectedInstanceIndex].HandleDecisionRequest, newRequest); t.Wait(); } else { aiInstanceList[selectedInstanceIndex].HandleDecisionRequest(newRequest); } } Play aiAction = newRequest.DecisionPlay; aiAction = SetDecisionTime(ValidatePlayerDecision(aiAction, newRequest.Cache)); return(aiAction); } catch (Exception ex) { instanceSelector.instancesIdle = 0; for (int i = 0; i < aiInstanceList.Count; i++) { instanceSelector.instancesIdle = instanceSelector.instancesIdle | (1 << i); } genericGameCache.readLockCounter = 0; string fileName = LogError.Log(ex, "PokerAIError"); genericGameCache.SaveToDisk("", fileName); return(new Play(PokerAction.GeneralAIError, 0, 0, genericGameCache.getCurrentHandId(), playerId, ex.ToString(), 3)); } throw new Exception("This point should never be reached."); }