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