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