public static bool Verify(ActionTree at, ChanceTree ct, StrategyTree[] strategies, double epsilon, out string message) { message = ""; // No need to check preconditions, GameValue does it GameValue gv = new GameValue { ActionTree = at, ChanceTree = ct, Strategies = strategies }; gv.Solve(); for (int p = 0; p < at.PlayersCount; ++p) { StrategyTree[] strategiesCopy = (StrategyTree[])strategies.Clone(); Br br = new Br { ActionTree = at, ChanceTree = ct, Strategies = strategiesCopy, HeroPosition = p }; br.Solve(); if (!FloatingPoint.AreEqual(gv.Values[p], br.Value, epsilon)) { message = String.Format("Unequal values for pos {0}: eq: {1}, br: {2}, eps: {3}", p, gv.Values[p], br.Value, epsilon); return(false); } } return(true); }
static void Verify(int oppCount, double[] cardProbabs, double[,] pm) { if (oppCount <= 0) { throw new ApplicationException("Player count must be > 0"); } int n = cardProbabs.GetLength(0); if (n != pm.GetLength(0) || n != pm.GetLength(1)) { throw new ApplicationException("Array size mismatch"); } double sum = 0; for (int i = 0; i < n; ++i) { sum += cardProbabs[i]; } if (!FloatingPoint.AreEqual(1, sum, 1e-5)) { throw new ApplicationException(String.Format("Wrong sum of card probabilities: {0}, expected 1.", sum)); } for (int i = 0; i < n; ++i) { for (int j = 0; j <= i; ++j) { if (pm[i, j] < 0 || pm[i, j] > 1 || pm[j, i] < 0 || pm[j, i] > 1 || !FloatingPoint.AreEqual(pm[i, j] + pm[j, i], 1, 1e-5)) { throw new ApplicationException(String.Format("Prefernce matrix wrong at ({0}, {1}).", i, j)); } } } }
public virtual void OnGameBegin(string gameString) { _gameRecord = new GameRecord(gameString); _pos = _gameRecord.FindPositionByName(_name); if (_checkBlinds) { for (int p = 0; p < _gameRecord.Players.Count; ++p) { _curStrNodeIdx = p + 1; StrategyTreeNode stNode = new StrategyTreeNode(); _strategies[_pos].GetNode(p + 1, &stNode); double strBlind = stNode.Amount; double grBlind = _gameRecord.Players[p].Blind; if (!FloatingPoint.AreEqual(grBlind, strBlind, AMOUNT_EPSILON)) { throw new ApplicationException( String.Format("{0}: blind size mismatch: game: {1}, strategy: {2}", GetBotStateDiagText(), grBlind, strBlind)); } } } if (_gameRecord.Actions.Count != 0) { throw new ApplicationException( String.Format("{0}: action count must be zero in OnGameBegin, game string '{1}'", GetBotStateDiagText(), gameString)); } _curStrNodeIdx = _gameRecord.Players.Count; _processedActionsCount = 0; _lastAbsStrProbab = 1.0; _gameState = new GameState(_gameRecord, null); log.InfoFormat("{0} OnGameBegin() pos {1}", _name, _pos); }
public static float[] Calculate(int[] hand, int handLength, int sdRound) { VerifyParameters(handLength, sdRound); float[] hssd = new float[2]; hssd[0] = HandStrength.CalculateFast(hand, handLength); if (handLength == 7) { // Nothing more to do on the river. return(hssd); } int sdHandLength = HeHelper.RoundToHandSize[sdRound]; CardSet cs = StdDeck.Descriptor.GetCardSet(hand, 0, handLength); Params p = new Params { Hand = new int[sdHandLength] }; for (int i = 0; i < handLength; ++i) { p.Hand[i] = hand[i]; } p.Hs = hssd[0]; CardEnum.Combin <Params>(StdDeck.Descriptor, sdHandLength - handLength, p.Hand, handLength, p.Hand, handLength, OnDeal, p); Debug.Assert(FloatingPoint.AreEqual(p.Hs, p.SumHs / p.Count, 0.00001)); hssd[1] = (float)Math.Sqrt(p.SumDiff / p.Count); return(hssd); }
public void SetPotShare(ushort activePlayers, double[] potShare) { int bitCount = CountBits.Count(activePlayers); // Now implement for heads-up only. if (bitCount < 1 || bitCount > 3) { throw new ApplicationException(String.Format("Wrong active player mask {0}, players count must be in range [1..2]", activePlayers)); } if (bitCount == 1) { return; } _potShare0 = potShare[0]; Debug.Assert(FloatingPoint.AreEqual(1.0, _potShare0 + potShare[1], 1e-12)); }
void OnNodeEnd(ChanceTree tree, Context[] stack, int depth) { Context context = stack[depth]; Int64 n = context.NodeIdx; if (!context.IsLeaf) { if (!FloatingPoint.AreEqual(tree.Nodes[context.NodeIdx].Probab, context.SumProbabsOfChildren, Epsilon)) { throw new ApplicationException(String.Format( "Node {0}: sum of chance probability of children {1} != chance probability of the paren {2}", context.NodeIdx, context.SumProbabsOfChildren, tree.Nodes[context.NodeIdx].Probab)); ; } } }
protected override void OnNodeEndFunc(StrategyTree tree, Context[] stack, int depth) { if (stack[depth].IsVerificationNeeded) { Context context = stack[depth]; if (!NonZeroSumsOnly || context.SumProbabilityOfChildren != 0) { if (!FloatingPoint.AreEqual(context.SumProbabilityOfChildren, context.Probability, Epsilon)) { throw new VerificationException { Text = string.Format("Node {0}, depth {1}: sum of childen {2} differs from expected {3} (epsilon {4}).", context.NodeIdx, depth, context.SumProbabilityOfChildren, context.Probability, Epsilon) }; } } } }
public double Solve(double a, double b, double epsilon, bool verifyFunctionShape) { if (a > b) { ShortSequence.Swap(ref a, ref b); } double x1 = b - (b - a) / GR; double x2 = a + (b - a) / GR; double f1 = F(x1); double f2 = F(x2); double fStart = 0, fEnd = 0; if (verifyFunctionShape) { fStart = F(a); fEnd = F(b); if (!IsShapeCorrect(fStart, fEnd, f1) || !IsShapeCorrect(fStart, fEnd, f2)) { throw new ApplicationException("Wrong function shape"); } } for (;;) { if (b - a <= epsilon) { return((b + a) * 0.5); } if (f1 > f2) { // Replace a a = x1; x1 = x2; f1 = f2; x2 = a + (b - a) / GR; f2 = F(x2); if (verifyFunctionShape) { if (!IsShapeCorrect(fStart, fEnd, f2)) { throw new ApplicationException("Wrong function shape"); } } } else { // Replace b b = x2; x2 = x1; f2 = f1; x1 = b - (b - a) / GR; f1 = F(x1); if (verifyFunctionShape) { if (!IsShapeCorrect(fStart, fEnd, f1)) { throw new ApplicationException("Wrong function shape"); } } } Debug.Assert(FloatingPoint.AreEqual((b - a) / (x2 - a), GR, 1e-10)); Debug.Assert(FloatingPoint.AreEqual((b - a) / (b - x1), GR, 1e-10)); } }
/// <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; }