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; } }
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; }
/// <summary> /// Refreshes the cache monitor screen ouput with the current state of the cache. /// </summary> public void updateTableUI() { lock (locker) { if (genericCache == null) { //Just clear everything and wait for the cache to be set. resetAllTableElements(); } else { #region updatingNow //Prevent any more changes from happening to the cache while the table is updated genericCache.startRead(); //Update hands played handsPlayed.Text = genericCache.getNumHandsPlayed().ToString(); //It's possible the table tries to update exactly after a hand has finished //In this particular case for now we are just going to exit updateTableUI if (genericCache.currentHandExists()) { currentHandDetails = genericCache.getCurrentHandDetails(); currentPlayerDetails = genericCache.getPlayerDetails(); //Disable unused seats disableUnusedSeats(genericCache.NumSeats); //Get any new actions if (lastLocalIndex[0] == -1) { playActions = genericCache.getAllHandActions(); } else { playActions = genericCache.getHandActionsBasedOnLocalIndex(lastLocalIndex[0], (byte)lastLocalIndex[1]); } //Once we have actions we record the last one we go if (playActions.Length > 0) { lastLocalIndex[0] = playActions.Last().handId; lastLocalIndex[1] = playActions.Last().localIndex; } //Only update hand information if a current hand exists if (currentHandDetails.currentHandExists) { if (currentHandId != currentHandDetails.handId) { currentHandId = currentHandDetails.handId; handHistory.AppendText("\n\nNew Hand Started - HandId " + currentHandId.ToString() + "\n\n"); echoHoleCards = 0; resetAllTableElements(); } moveDealerButton(currentHandDetails.dealerPosition); potValue.Text = currentHandDetails.potValue.ToString(); if (currentHandDetails.tableCard1 != (byte)Card.NoCard) { setCard(currentHandDetails.tableCard1, tableCard1); } if (currentHandDetails.tableCard2 != (byte)Card.NoCard) { setCard(currentHandDetails.tableCard2, tableCard2); } if (currentHandDetails.tableCard3 != (byte)Card.NoCard) { setCard(currentHandDetails.tableCard3, tableCard3); } if (currentHandDetails.tableCard4 != (byte)Card.NoCard) { setCard(currentHandDetails.tableCard4, tableCard4); } if (currentHandDetails.tableCard5 != (byte)Card.NoCard) { setCard(currentHandDetails.tableCard5, tableCard5); } } //Actions which also update the useraction box //Call, Raise & Check //Big & Little Blind //Fold //Wins //Need to update actions //Add all actions in playActions to chat window for (int i = 0; i < playActions.GetLength(0); i++) { actionString = "Player Name: " + genericCache.getPlayerName(playActions.ElementAt(i).playerId) + ", Action: " + playActions.ElementAt(i).actionType.ToString() + ", Action Value: " + playActions.ElementAt(i).actionValue.ToString() + "\n"; #region actionStringSwtich switch (playActions.ElementAt(i).actionType) { case PokerAction.JoinTable: actionString = "[Dealer] " + genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " sits down at the table."; break; case PokerAction.LeaveTable: actionString = "[Dealer] " + genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " leaves the table."; break; case PokerAction.SitOut: sitInOutPlayer(genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), false); actionString = "[Dealer] " + genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " is now sitting out."; break; case PokerAction.SitIn: sitInOutPlayer(genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), true); actionString = "[Dealer] " + genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " is now playing again."; break; case PokerAction.LittleBlind: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " posts the little blind."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "LB - " + genericCache.LittleBlind.ToString(); break; case PokerAction.BigBlind: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " posts the big blind."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "BB - " + genericCache.BigBlind.ToString(); break; case PokerAction.Fold: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " folds."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Fold"; clearCard((PictureBox)playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 2]); clearCard((PictureBox)playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 3]); break; case PokerAction.Check: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " checks."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Check"; break; case PokerAction.Call: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " calls " + playActions.ElementAt(i).actionValue.ToString() + "."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Call - " + playActions.ElementAt(i).actionValue.ToString(); break; case PokerAction.Raise: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " raises to " + playActions.ElementAt(i).actionValue.ToString() + "."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Raise - " + playActions.ElementAt(i).actionValue.ToString(); break; case PokerAction.WinPot: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " wins " + playActions.ElementAt(i).actionValue.ToString() + "."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Wins " + playActions.ElementAt(i).actionValue.ToString(); echoHoleCards = 1; break; case PokerAction.AddStackCash: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " adds " + playActions.ElementAt(i).actionValue.ToString() + " to their stack."; break; case PokerAction.DeadBlind: actionString = genericCache.getPlayerName(playActions.ElementAt(i).playerId) + " posts a dead blind."; playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "DB - " + playActions.ElementAt(i).actionValue.ToString(); break; case PokerAction.ReturnBet: actionString = "Uncalled bet of " + playActions.ElementAt(i).actionValue.ToString() + " returned to " + genericCache.getPlayerName(playActions.ElementAt(i).playerId); playerControls[genericCache.getPlayerPosition(playActions.ElementAt(i).playerId), 4].Text = "Bet Returned - " + playActions.ElementAt(i).actionValue.ToString(); break; case PokerAction.DealFlop: actionString = "[Dealer] Flop Cards Revealed (" + ((Card)genericCache.getCurrentHandDetails().tableCard1).ToString() + "), (" + ((Card)genericCache.getCurrentHandDetails().tableCard2).ToString() + "), (" + ((Card)genericCache.getCurrentHandDetails().tableCard3).ToString() + ")."; newRoundTableRefresh(); break; case PokerAction.DealTurn: actionString = "[Dealer] Turn Card Revealed (" + ((Card)genericCache.getCurrentHandDetails().tableCard4).ToString() + ")."; newRoundTableRefresh(); break; case PokerAction.DealRiver: actionString = "[Dealer] River Card Revealed (" + ((Card)genericCache.getCurrentHandDetails().tableCard5).ToString() + ")."; newRoundTableRefresh(); break; case PokerAction.TableRake: actionString = "[Dealer] Table rake of " + playActions.ElementAt(i).actionValue.ToString("#0.00"); break; } #endregion actionStringSwtich handHistory.AppendText(actionString + "\n"); //lastActionTime = playActions.ElementAt(i).actionTime; } activePositions = genericCache.getActivePositions(); //Only update player details if they exist if (activePositions.Length != 0) { bool endOfHand = false; if (genericCache.getBettingRound() == 3 && genericCache.getActivePositionsLeftToAct().Length == 0) { endOfHand = true; } for (int i = 0; i < currentPlayerDetails.Length; i++) { //{player0Name, player0Stack, player0Card1, player0Card2, player0Action}, playerControls[currentPlayerDetails[i].position, 0].Text = currentPlayerDetails[i].playerName; playerControls[currentPlayerDetails[i].position, 1].Text = currentPlayerDetails[i].stack.ToString(); //If echoHoleCards is set to true then echo out any known hole cards if (echoHoleCards == 1) { if (genericCache.getPlayerHoleCards(currentPlayerDetails[i].playerId).holeCard1 != 0) { actionString = "[Hole Cards] " + currentPlayerDetails[i].playerName + " (" + (Card)genericCache.getPlayerHoleCards(currentPlayerDetails[i].playerId).holeCard1 + ", " + (Card)genericCache.getPlayerHoleCards(currentPlayerDetails[i].playerId).holeCard2 + ")."; handHistory.AppendText(actionString + "\n"); } } var isActive = from ac in activePositions where ac == currentPlayerDetails[i].position select ac; var currentActivePosition = genericCache.getCurrentActiveTablePosition(); if (onlyShowCardsForPlayerId != -1 && currentPlayerDetails[i].playerId == onlyShowCardsForPlayerId) { setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard1, (PictureBox)playerControls[currentPlayerDetails[i].position, 2]); setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard2, (PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } else if (isActive.Count() == 1 && onlyShowCardsForPlayerId != -1 && currentPlayerDetails[i].playerId != onlyShowCardsForPlayerId) { blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 2]); blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } else if ((showNonBotPlayerCardsOnly && isActive.Count() == 1 && !currentPlayerDetails[i].isBot) || (endOfHand && isActive.Count() == 1)) { //We are only showing non bot player cards and we are currently at a non bot position. //It is the end of the hand and this position is still active (it's a showdown folks). setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard1, (PictureBox)playerControls[currentPlayerDetails[i].position, 2]); setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard2, (PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } else if (showNonBotPlayerCardsOnly && isActive.Count() == 1 && currentPlayerDetails[i].isBot) { //We are only showing non bot player cards and we are currently at a bot position. blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 2]); blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } else if ((!showActivePlayerCardsOnly && isActive.Count() == 1) || (showActivePlayerCardsOnly && currentActivePosition == currentPlayerDetails[i].position)) { //show cards if we are showing everyones cards and this current position is active //show cards if we are only showing active positions and we are currently in the active position. setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard1, (PictureBox)playerControls[currentPlayerDetails[i].position, 2]); setCard(genericCache.getPlayerHoleCards((long)currentPlayerDetails[i].playerId).holeCard2, (PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } else if (isActive.Count() == 1) { //If we get here just show the back of the cards blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 2]); blankCard((PictureBox)playerControls[currentPlayerDetails[i].position, 3]); } //Player might be dead if (currentPlayerDetails[i].isDead) { sitInOutPlayer(currentPlayerDetails[i].position, false); } else if (currentActivePosition == currentPlayerDetails[i].position) { setPlayerTurn(currentPlayerDetails[i].position); } else { sitInOutPlayer(currentPlayerDetails[i].position, true); } } echoHoleCards = 2; } } genericCache.endRead(); #endregion } //lastLocalIndex = genericCache.getMostRecentLocalIndex(); //Call garbage collection to keep memory usage under control (without this it will quite happily hit 0.5Gb usage) GC.Collect(); } this.Invalidate(); }