private ChanceTree CreateCt(HePocketKind[] sbCards, HePocketKind[] bbCards) { int nodeCount = 1 + sbCards.Length + sbCards.Length * bbCards.Length; ChanceTree ct = new ChanceTree(nodeCount); ct.PlayersCount = 2; ct.Nodes[0].Probab = 1; ct.SetDepth(0, 0); int totalCombSB = 0; foreach (HePocketKind p in sbCards) { totalCombSB += HePocket.KindToRange(p).Length; } for (int c0 = 0; c0 < sbCards.Length; ++c0) { int sbNode = 1 + c0 * (bbCards.Length + 1); HePocketKind sbPocket = sbCards[c0]; ct.SetDepth(sbNode, 1); ct.Nodes[sbNode].Position = 0; ct.Nodes[sbNode].Probab = (double)HePocket.KindToRange(sbPocket).Length / totalCombSB; ct.Nodes[sbNode].Card = c0; double[] oppDealProbabCond = PocketHelper.GetProbabDistr(bbCards, HePocket.KindToCardSet(sbPocket)); for (int c1 = 0; c1 < bbCards.Length; ++c1) { int bbNode = sbNode + 1 + c1; ct.SetDepth(bbNode, 2); ct.Nodes[bbNode].Position = 1; ct.Nodes[bbNode].Probab = ct.Nodes[sbNode].Probab * oppDealProbabCond[c1]; ct.Nodes[bbNode].Card = c1; PocketEquity.Result pe = PocketEquity.CalculateFast(sbPocket, bbCards[c1]); var potShare = new double[] { pe.Equity, 1 - pe.Equity }; ct.Nodes[bbNode].SetPotShare(3, potShare); } } VerifyChanceTree.VerifyS(ct, 1e-5); return(ct); }
public static ChanceTree CreateCt(HePocketKind [] pockets, double [] oppCardProbab) { int n = pockets.Count(); double[] dealProbab = PocketHelper.GetProbabDistr(pockets); int nodeCount = 1 + n + n * n; ChanceTree ct = new ChanceTree(nodeCount); ct.PlayersCount = 2; ct.Nodes[0].Probab = 1; ct.SetDepth(0, 0); for (int c0 = 0; c0 < n; ++c0) { int heroNode = 1 + c0 * (n + 1); ct.SetDepth(heroNode, 1); ct.Nodes[heroNode].Position = 0; ct.Nodes[heroNode].Probab = dealProbab[c0]; ct.Nodes[heroNode].Card = c0; double[] corrOppProbab = CorrectOpponentProbab(pockets, c0, dealProbab, oppCardProbab); for (int c1 = 0; c1 < n; ++c1) { int oppNode = heroNode + 1 + c1; ct.SetDepth(oppNode, 2); ct.Nodes[oppNode].Position = 1; ct.Nodes[oppNode].Probab = ct.Nodes[heroNode].Probab * corrOppProbab[c1]; ct.Nodes[oppNode].Card = c1; PocketEquity.Result pe = PocketEquity.CalculateFast(pockets[c0], pockets[c1]); var potShare = new double[] { pe.Equity, 1 - pe.Equity }; ct.Nodes[oppNode].SetPotShare(3, potShare); } } VerifyChanceTree.VerifyS(ct, 1e-5); return(ct); }
void CopyFromTemp(ChanceTree newTree, TempNode tempNode, int depth) { newTree.SetDepth(_nodeCount, (byte)depth); newTree.Nodes[_nodeCount].Card = tempNode.Card; newTree.Nodes[_nodeCount].Probab = tempNode.Probab; newTree.Nodes[_nodeCount].Position = 0; _nodeCount++; List <int> cards = new List <int>(tempNode.Children.Keys.ToArray()); cards.Sort(); foreach (int card in cards) { CopyFromTemp(newTree, tempNode.Children[card], depth + 1); } }
bool SyncNodes(Node uniTree, object uniNode, byte uniDepth, int uniIt, UFTree ufTree, Int64 ufNode, object userData) { ChanceTree ct = (ChanceTree)ufTree; ct.SetDepth(ufNode, uniDepth); ct.Nodes[ufNode].Card = uniDepth == 0 ? 0 : uniIt - 1; ct.Nodes[ufNode].Position = (uniDepth - 1) % PlayersCount; if (uniNode is LeafT) { // This is a leaf LeafT leaf = (LeafT)uniNode; ct.Nodes[ufNode].Probab = (double)leaf.Count / SamplesCount; double [] potShares = new double[2]; potShares[0] = 0.5 * leaf.Result / leaf.Count; potShares[1] = 1 - potShares[0]; ct.Nodes[ufNode].SetPotShare(0x11, potShares); } else { ct.Nodes[ufNode].Probab = 0; } return(true); }
public static ChanceTree FromTxt(TextReader r) { int ln = 0; int serializationFormat = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "SeralizationFormat")); if (serializationFormat > SERIALIZATION_FORMAT) { throw new ApplicationException(String.Format("Line {0}: serialization format {1} is not supported by this version, max supported {2}", ln, serializationFormat, SERIALIZATION_FORMAT)); } string value; value = TextDumpHelper.ReadTag(r, ref ln, "Version"); StringReader sr = new StringReader(value); BdsVersion v; XmlSerializerExt.Deserialize(out v, sr); Int64 nodesCount = Int64.Parse(TextDumpHelper.ReadTag(r, ref ln, "NodesCount")); int roundsCount = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "RoundsCount")); ChanceTree t = new ChanceTree(nodesCount); t.SetNodesMemory(0); // Clear memory to ensure zeros at unused fields t.Version.CopyFrom(v); char [] separators = new char[] { ' ', '\t' }; for (Int64 n = 0; n < nodesCount; ++n) { Int64 id = Int64.Parse(TextDumpHelper.ReadTag(r, ref ln, "Id")); if (id != n) { throw new ApplicationException(String.Format("Line {0}: wrong node id '{1}', expected '{2}'", ln, id, n)); } byte depth = byte.Parse(TextDumpHelper.ReadTag(r, ref ln, "D")); t.SetDepth(n, depth); t.Nodes[n].Position = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "P")); t.Nodes[n].Card = int.Parse(TextDumpHelper.ReadTag(r, ref ln, "C")); t.Nodes[n].Probab = TextDumpHelper.BinStringToDouble(TextDumpHelper.ReadTag(r, ref ln, "Pr")); if (depth == t.PlayersCount * roundsCount) { double[] potShare = new double[t.PlayersCount]; UInt16[] activePlayerMasks = ActivePlayers.Get(t.PlayersCount, 2, t.PlayersCount); for (int a = 0; a < activePlayerMasks.Length; ++a) { value = TextDumpHelper.ReadTag(r, ref ln, "Ps"); string[] parts = value.Split(separators, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != t.PlayersCount + 1) { throw new ApplicationException( String.Format("Line {0}: wrong number of values: '{1}', expected '{2}'", ln, parts.Length, t.PlayersCount + 1)); } UInt16 activePlayers = UInt16.Parse(parts[0], NumberStyles.AllowHexSpecifier); for (int i = 1; i < parts.Length; ++i) { potShare[i - 1] = TextDumpHelper.BinStringToDouble(parts[i]); } t.Nodes[n].SetPotShare(activePlayers, potShare); } } } return(t); }
private static void ProcessGameContext(GameContext context) { int nodeId = context.Global.NodeId++; GameDefinition gd = context.Global.GameDef; ChanceTree tree = context.Global.Tree; while (!context.GameState.IsGameOver && !context.GameState.IsDealerActing) { context.GameState.UpdateByAction(PokerAction.c(context.GameState.CurrentActor), gd); } if (tree != null) { tree.SetDepth(nodeId, (byte)context.Depth); int position = context.GameState.LastActor; if (context.Deal != null && context.Deal.SharedCardsPlayer != -1) { position = context.Deal.SharedCardsPlayer; } if (nodeId == 0) { position = gd.MinPlayers; } tree.Nodes[nodeId].Position = position; if (context.Deal == null) { tree.Nodes[nodeId].Card = -1; } else { // This double-conversion assures that for decks with duplicates // the same index int stableCardIdx = gd.DeckDescr.GetIndex(gd.DeckDescr.CardNames[context.Deal.CardIdx]); tree.Nodes[nodeId].Card = stableCardIdx; } } if (context.GameState.IsGameOver) { context.CombCountOfLeaves = context.DealCount; if (tree != null) { tree.Nodes[nodeId].Probab = (double)context.CombCountOfLeaves / context.Global.TotalCombCountOfLeaves; int playersCount = gd.MinPlayers; uint[] ranks = new uint[playersCount]; int[][] hands = new int[playersCount][]; for (int p = 0; p < playersCount; ++p) { hands[p] = gd.DeckDescr.GetIndexes(context.GameState.Players[p].Hand); } gd.GameRules.Showdown(gd, hands, ranks); context.GameState.UpdateByShowdown(ranks, gd); double[] potShares = new double[gd.MinPlayers]; for (int p = 0; p < playersCount; ++p) { potShares[p] = (context.GameState.Players[p].Result + context.GameState.Players[p].InPot) / context.GameState.Pot; } tree.Nodes[nodeId].SetPotShare(context.GameState.GetActivePlayers(), potShares); } return; } // Deal next cards. List <DealT> deals = DealCards(context); foreach (DealT d in deals) { GameContext childContext = new GameContext(context); childContext.Depth++; childContext.DealtCards.UnionWith(gd.DeckDescr.CardSets[d.CardIdx]); if (d.SharedCardsPlayer == -1) { // Non-shared deal - update game state and deal count PokerAction a = PokerAction.d(context.GameState.CurrentActor, d.CardName); childContext.GameState.UpdateByAction(a, gd); childContext.DealCount *= d.Count; } else if (d.SharedCardsPlayer == gd.MinPlayers - 1) { // Shared deal for last player - update game state and deal count once for all. PokerAction a = PokerAction.d(-1, context.Deal.CardName); childContext.GameState.UpdateByAction(a, gd); childContext.DealCount *= d.Count; } childContext.Deal = d; ProcessGameContext(childContext); context.CombCountOfLeaves += childContext.CombCountOfLeaves; context.ChildCount += childContext.ChildCount + 1; } if (tree != null) { tree.Nodes[nodeId].Probab = (double)context.CombCountOfLeaves / context.Global.TotalCombCountOfLeaves; } }