public virtual PokerAction OnActionRequired(string gameString) { log.InfoFormat("{0} OnActionRequired", _name); _gameRecord = new GameRecord(gameString); ProcessActions(); int chBegin, movesCount; _strIndexes[_pos].GetChildrenBeginIdxAndCount(_curStrNodeIdx, out chBegin, out movesCount); double[] probabs = new double[movesCount]; double sumProbab = 0; for (int c = 0; c < movesCount; ++c) { int stNodeIdx = _strIndexes[_pos].GetChildIdx(chBegin + c); StrategyTreeNode stNode = new StrategyTreeNode(); _strategies[_pos].GetNode(stNodeIdx, &stNode); // Verify we are in the correct position. // This is proven to be very helpful in testing. if (!stNode.IsPlayerAction(_pos)) { throw new ApplicationException(String.Format("{0}: expected strategy child: player action for pos {1}, but was: '{2}'", GetBotStateDiagText(), _pos, stNode.ToStrategicString(null))); } probabs[c] = stNode.Probab; sumProbab += probabs[c]; } try { // Convert to relative probability and ignore if necessary for (int c = 0; c < probabs.Length; ++c) { probabs[c] /= sumProbab; if (probabs[c] < _relProbabIgnoreLevel) { probabs[c] = 0; } } _moveSelector.SetWeights(probabs); } catch (Exception e) { // If there are problems with 0-probablities, add more info to it. throw new ApplicationException(String.Format("{0} : see inner exception", GetBotStateDiagText()), e); } int moveIdx = _moveSelector.Next(); Debug.Assert(probabs[moveIdx] > 0, "0-probabs must not occur"); int nextStrNode = _strIndexes[_pos].GetChildIdx(chBegin + moveIdx); PokerAction move = ConvertStrActionToPokerAction(nextStrNode); log.InfoFormat("{0} OnActionRequired() returns {1}", _name, move); return(move); }
/// <summary> /// Process new poker actions received from the server. /// </summary> private void ProcessActions() { for (int a = _processedActionsCount; a < _gameRecord.Actions.Count; ++a, _processedActionsCount++) { PokerAction pa = _gameRecord.Actions[a]; log.InfoFormat("{0} process {1} of pos {2}", _name, pa.Kind, pa.Position); ProcessAction(pa); StrategyTreeNode stNode = new StrategyTreeNode(); _strategies[_pos].GetNode(_curStrNodeIdx, &stNode); if (stNode.IsPlayerAction(_pos)) { _lastAbsStrProbab = stNode.Probab; } } }
private PokerAction ConvertStrActionToPokerAction(int nextStNodeIdx) { StrategyTreeNode nextStNode = new StrategyTreeNode(); _strategies[_pos].GetNode(nextStNodeIdx, &nextStNode); if (!nextStNode.IsPlayerAction(_pos)) { throw new ApplicationException(String.Format("{0} : wrong move: {1}", GetBotStateDiagText(), nextStNode.ToStrategicString(null))); } double amount = nextStNode.Amount; double raiseAmount = _gameState.Players[_pos].Bet + amount - _gameState.Bet; if (raiseAmount > 0) { return(PokerAction.r(_pos, raiseAmount)); } if (amount == 0 && _gameState.Players[_pos].Bet < _gameState.Bet) { return(PokerAction.f(_pos)); } return(PokerAction.c(_pos)); }
/// <summary> /// Processes each poker action received from the server. /// Updates the game state and moves to the next node in our strategy. /// </summary> /// <param name="pa"></param> void ProcessAction(PokerAction pa) { int chBegin, chCount; _strIndexes[_pos].GetChildrenBeginIdxAndCount(_curStrNodeIdx, out chBegin, out chCount); int nextStrNodeIdx = -1; if (pa.IsDealerAction()) { _gameState.UpdateByAction(pa, null); if (pa.Position >= 0 && pa.Position != _pos) { // This is a deal to an opponent // We can skip it for games without public cards (and it is very unlikely we will have some // in the future). return; } int[] hand = _deckDescr.GetIndexes(_gameState.Players[_pos].Hand); int abstrCard = _chanceAbsrtractions[_pos].GetAbstractCard(hand, hand.Length); for (int c = 0; c < chCount; ++c) { int stNodeIdx = _strIndexes[_pos].GetChildIdx(chBegin + c); StrategyTreeNode stNode = new StrategyTreeNode(); _strategies[_pos].GetNode(stNodeIdx, &stNode); if (!stNode.IsDealerAction) { throw new ApplicationException( String.Format("{0} : expected strategy child: dealer action but was: '{1}'", GetBotStateDiagText(), stNode.ToStrategicString(null))); } if (stNode.Card == abstrCard) { nextStrNodeIdx = stNodeIdx; goto searchFinished; } } } else // Player action { double inPotBefore = _gameState.Players[pa.Position].InPot; _gameState.UpdateByAction(pa, null); double inPotAfter = _gameState.Players[pa.Position].InPot; double actualAmount = inPotAfter - inPotBefore; double bestAmount = double.MinValue; for (int c = 0; c < chCount; ++c) { int stNodeIdx = _strIndexes[_pos].GetChildIdx(chBegin + c); StrategyTreeNode stNode = new StrategyTreeNode(); _strategies[_pos].GetNode(stNodeIdx, &stNode); if (!stNode.IsPlayerAction(pa.Position)) { throw new ApplicationException( String.Format("{0} : expected strategy child: player action pos {1} but was: '{2}'", GetBotStateDiagText(), pa.Position, stNode.ToStrategicString(null))); } double amount = stNode.Amount; switch (_amountSearchMethod) { case AmountSearchMethod.Equal: if (FloatingPoint.AreEqual(amount, actualAmount, AMOUNT_EPSILON)) { nextStrNodeIdx = stNodeIdx; goto searchFinished; } break; case AmountSearchMethod.Closest: if (Math.Abs(amount - actualAmount) < Math.Abs(bestAmount - actualAmount)) { bestAmount = amount; nextStrNodeIdx = stNodeIdx; } break; } } } searchFinished: if (nextStrNodeIdx == -1) { throw new ApplicationException( String.Format("{0} : cannot find strategy action for poker action '{1}'", GetBotStateDiagText(), pa.ToGameString())); } _curStrNodeIdx = nextStrNodeIdx; }