private StrategyTree CreateValidStrategy(GameDefinition gd) { StrategyTree st = TreeHelper.CreateStrategyTree(gd, _heroPos); _childrenCount = new int[st.NodesCount]; WalkUFTreePP <StrategyTree, Context> wt = new WalkUFTreePP <StrategyTree, Context>(); wt.OnNodeBegin = OnNodeBegin; _run = 0; wt.Walk(st); _run = 1; wt.Walk(st); return(st); }
public ChanceTree Extract(ChanceTree ct, int position) { if (position >= ct.PlayersCount) { throw new ArgumentOutOfRangeException( string.Format("Position {0} is out of range (players count: {1})", position, ct.PlayersCount)); } _position = position; WalkUFTreePP <ChanceTree, Context> wt = new WalkUFTreePP <ChanceTree, Context>(); wt.OnNodeBegin = OnNodeBegin; _nodeCount = 0; _tempRoot = new TempNode { Card = -1, Probab = 1 }; wt.Walk(ct); ChanceTree newTree = new ChanceTree(_nodeCount + 1); // Reset memory to clear results. newTree.SetNodesMemory(0); _nodeCount = 0; CopyFromTemp(newTree, _tempRoot, 0); // Overwrite root position newTree.Nodes[0].Position = 1; newTree.Version.Description = String.Format("Player {0} chance tree from {1}", position, ct.Version.Description); return(newTree); }
double [,] FlattenStrategy(StrategyTree st, int pos, int cardCount, Dictionary <string, int> actionLabelToId) { double[,] result = new double[cardCount, actionLabelToId.Count]; var wt = new WalkUFTreePP <StrategyTree, FlattenStrategyContext>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; if (d > 0) { s[d].ActionLabel = s[d - 1].ActionLabel; s[d].Probab = s[d - 1].Probab; s[d].Card = s[d - 1].Card; if (t.Nodes[n].IsDealerAction) { s[d].Card = t.Nodes[n].Card; } else if (d > 2) // Skip blinds { s[d].ActionLabel = s[d].ActionLabel + "/" + String.Format("{0}p{1}", t.Nodes[n].Position, t.Nodes[n].Amount); if (t.Nodes[n].IsPlayerAction(pos)) { s[d].Probab = t.Nodes[n].Probab; double pr = s[d - 1].Probab == 0 ? 0 : s[d].Probab / s[d - 1].Probab; result[s[d].Card, actionLabelToId[s[d].ActionLabel]] = pr; } } } }; wt.Walk(st); return(result); }
private void Calculate() { WalkUFTreePP <ActionTree, CalculateActionContext> wt = new WalkUFTreePP <ActionTree, CalculateActionContext>(); wt.OnNodeBegin = Calculate_Action_OnNodeBegin; wt.Walk(ActionTree); }
private void VerifyWalk(TestTree tree, UFToUniAdapter adapter) { List <int> expectedPre = new List <int>(); List <int> expectedPost = new List <int>(); WalkUFTreePP <TestTree, WalkUFTreePPContext> wft = new WalkUFTreePP <TestTree, WalkUFTreePPContext>(); wft.OnNodeBegin = (t, s, d) => expectedPre.Add(tree.Nodes[s[d].NodeIdx].Value); wft.OnNodeEnd = (t, s, d) => expectedPost.Add(tree.Nodes[s[d].NodeIdx].Value); wft.Walk(tree); List <int> actualPre = new List <int>(); List <int> actualPost = new List <int>(); WalkTreePP <UFToUniAdapter, int, int, AdapterContext> wt = new WalkTreePP <UFToUniAdapter, int, int, AdapterContext>(); wt.OnNodeBegin = (t, n, s, d) => { actualPre.Add(tree.Nodes[n].Value); return(true); }; wt.OnNodeEnd = (t, n, s, d) => actualPost.Add(tree.Nodes[n].Value); wt.Walk(adapter, 0); Assert.AreEqual(expectedPre, actualPre); Assert.AreEqual(expectedPost, actualPost); int bi, cnt; adapter.GetChildrenBeginIdxAndCount(0, out bi, out cnt); Assert.AreEqual(4, cnt); }
public ChanceTree Create(GameDefinition gd, IChanceAbstraction [] abstractions) { _abstractions = abstractions; _gameDef = gd; _hands = new int[gd.MinPlayers][].Fill(i => new int[gd.RoundsCount]); _activePlayersOne = ActivePlayers.Get(gd.MinPlayers, 1, 1); _activePlayersAll = ActivePlayers.Get(gd.MinPlayers, 1, gd.MinPlayers); _maxDepth = gd.RoundsCount * gd.MinPlayers; ChanceTree gdChanceTree = CreateChanceTreeByGameDef.Create(gd); WalkUFTreePP <ChanceTree, CreateIntermediateTreeContext> wt1 = new WalkUFTreePP <ChanceTree, CreateIntermediateTreeContext>(); wt1.OnNodeBegin = CreateIntermediateTree_OnNodeBegin; wt1.OnNodeEnd = CreateIntermediateTree_OnNodeEnd; _nodesCount = 0; wt1.Walk(gdChanceTree); _abstChanceTree = new ChanceTree(_nodesCount + 1); WalkTreePP <IntermediateNode, IntermediateNode, int, CopyTreeContext> wt2 = new WalkTreePP <IntermediateNode, IntermediateNode, int, CopyTreeContext>(); wt2.OnNodeBegin = CopyTree_OnNodeBegin; _nodesCount = 0; wt2.Walk(_intRoot, _intRoot); _abstChanceTree.Version.Description = String.Format("Chance tree (gamedef: {0}", gd.Name); for (int p = 0; p < gd.MinPlayers; ++p) { _abstChanceTree.Version.Description += String.Format(", {0}", abstractions[p].Name); } _abstChanceTree.Version.Description += ")"; return(_abstChanceTree); }
void Calculate_Action_OnNodeBegin(ActionTree tree, CalculateActionContext[] stack, int depth) { CalculateActionContext context = stack[depth]; Int64 n = context.NodeIdx; if (depth == 0) { context.State = new StrategicState(_playersCount); } else { context.State = stack[depth - 1].State.GetNextState(tree.Nodes[n]); } if (_actionTreeIndex.GetChildrenCount(n) != 0) { return; } // This is a leaf int round = ActionTree.Nodes[n].Round; _chanceDepth = (byte)(_playersCount * (round + 1)); _strategicState = context.State; _actionTreeNodeIdx = n; WalkUFTreePP <ChanceTree, CalculateChanceContext> wt = new WalkUFTreePP <ChanceTree, CalculateChanceContext>(); wt.OnNodeBegin = Calculate_Chance_OnNodeBegin; wt.Walk(ChanceTree); }
string[] CreateActionLabels(ActionTree at, int pos) { var wt = new WalkUFTreePP <ActionTree, CreateActionLabelsContext>(); List <string> labels = new List <string>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; if (d > 0) { s[d].Label = s[d - 1].Label; // Skip blinds if (d > 2) { s[d].Label = s[d].Label + "/" + String.Format("{0}p{1}", t.Nodes[n].Position, t.Nodes[n].Amount); if (t.Nodes[n].Position == pos) { labels.Add(s[d].Label); } } } }; wt.Walk(at); return(labels.ToArray()); }
public unsafe void Benchmark_Walk() { int depthLimit = 25; int expectedNodesCount = (1 << (depthLimit + 1)) - 1; TestTree tree = new TestTree(expectedNodesCount); int idx = 0; CreateTestTree(tree, idx, ref idx, 0, depthLimit, 2); WalkUFTreePP <TestTree, Context> walker = new WalkUFTreePP <TestTree, Context>(); int nodeCount = 0; walker.OnNodeBegin = (t, s, d) => { nodeCount++; }; DateTime startTime = DateTime.Now; walker.Walk(tree); double time = (DateTime.Now - startTime).TotalSeconds; Assert.AreEqual(expectedNodesCount, nodeCount); Console.WriteLine("Node count {0:###,###,###}, {1} s, {2:###,###,###} n/s", nodeCount, time, nodeCount / time); }
private void CopySolutionToStrategy() { _varH = 0; WalkUFTreePP <StrategyTree, CopySolutionToStrategyContext> wt = new WalkUFTreePP <StrategyTree, CopySolutionToStrategyContext>(); wt.OnNodeBegin = CopySolutionToStrategy_OnNodeBegin; wt.Walk(Strategy, PLAYERS_COUNT); }
private void PrepareOpp() { WalkUFTreePP <StrategyTree, PrepareOppContext> wt = new WalkUFTreePP <StrategyTree, PrepareOppContext>(); wt.OnNodeBegin = PrepareOpp_OnNodeBegin; wt.OnNodeEnd = PrepareOpp_OnNodeEnd; wt.Walk(_oppStrategy, PLAYERS_COUNT); }
void BestResponseFinalize() { int[] heroAbstrCards = HandToAbstractCards(_hands[_heroPos]); var wt = new WalkUFTreePP <StrategyTree, BrFinalizeContext>(); Node[] heroPtExt = _ptExt[_heroPos]; wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; s[d].ChildBrFound = false; if (d > 0) { s[d].DealPath = new List <int>(s[d - 1].DealPath); s[d].ParentBrProbab = s[d - 1].ParentBrProbab; } if (_pt.Nodes[n].IsDealerAction) { s[d].DealPath.Add(_pt.Nodes[n].Card); } for (int r = 0; r < s[d].DealPath.Count; ++r) { if (s[d].DealPath[r] != heroAbstrCards[r]) { // This deal paths is not of interest. return; } } if (n == 0) { return; } long pn = s[d - 1].NodeIdx; if (_pt.Nodes[n].IsPlayerAction(_heroPos) && n > _playersCount) { int br = 0; if (s[d].ParentBrProbab > 0) { if (heroPtExt[pn].GameValue == heroPtExt[n].GameValue && !s[d - 1].ChildBrFound) { // This was the BR br = 1; s[d - 1].ChildBrFound = true; } } double p = _pt.Nodes[n].Probab * (IterationCounts[_heroPos] - 1); p += br; _pt.Nodes[n].Probab = p / IterationCounts[_heroPos]; s[d].ParentBrProbab = br; } }; wt.OnNodeEnd = (t, s, d) => { }; wt.Walk(_pt); }
public void Verify(ChanceTree ct) { _playersCount = ct.Nodes[0].Position; _areAllPosInvalid = true; WalkUFTreePP <ChanceTree, Context> wt = new WalkUFTreePP <ChanceTree, Context>(); wt.OnNodeBegin = OnNodeBegin; wt.OnNodeEnd = OnNodeEnd; wt.Walk(ct); }
/// <summary> /// Set initial strategy. /// </summary> private void SetInitialStrategy(int pos) { IterationCounts[pos]++; WalkUFTreePP <StrategyTree, SetInitialStrategyContext> wt = new WalkUFTreePP <StrategyTree, SetInitialStrategyContext>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; s[d].HeroChildren.Clear(); if (d > 0) { s[d].Probab = s[d - 1].Probab; } if (d > _playersCount) { if (t.Nodes[n].IsPlayerAction(pos)) { s[d - 1].HeroChildren.Add(n); #if false // Pure strategy if (s[d].Probab > 0) { t.Nodes[n].Probab = s[d - 1].ChildrenCount == 1 ? 1 : 0; } s[d].Probab = t.Nodes[n].Probab; #endif } } }; wt.OnNodeEnd = (t, s, d) => { Int64 n = s[d].NodeIdx; if (s[d].HeroChildren.Count > 0) { #if true // Mixed strategy double condProbab = 1.0 / s[d].HeroChildren.Count; foreach (long ch in s[d].HeroChildren) { t.Nodes[ch].Probab = condProbab; } #endif } }; wt.Walk(_pt); ConvertCondToAbs.Convert(_pt, pos); string error; if (!VerifyAbsStrategy.Verify(_pt, pos, out error)) { throw new ApplicationException(String.Format("Initial strategy inconsistent: {0}", error)); } }
private void PrepareHero() { _maxCard = new int[PLAYERS_COUNT][]; _chanceIndexSizes = new int[PLAYERS_COUNT][]; _heroVarsInLeaves = new int[ActionTree.NodesCount][]; _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < PLAYERS_COUNT; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _chanceIndexSizes[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / PLAYERS_COUNT; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < PLAYERS_COUNT; ++p) { _chanceIndexSizes[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _chanceIndexSizes[p][r] = _chanceIndexSizes[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; _heroVarsInLeaves[n] = new int[_chanceIndexSizes[HeroPosition][round]].Fill(-1); } } // Create hero variables WalkUFTreePP <StrategyTree, PrepareHeroVarsContext> wt = new WalkUFTreePP <StrategyTree, PrepareHeroVarsContext>(); wt.OnNodeBegin = PrepareHero_OnNodeBegin; wt.Walk(Strategy, PLAYERS_COUNT); }
public void Analyze() { try { _playersCount = StrategyTree.PlayersCount; _stats = new List <Stats>(10); LeavesCount = 0; ZaspLeavesCount = 0; MovesCount = 0; ZaspMovesCount = 0; var walkTree = new WalkUFTreePP <StrategyTree, AnalyzeContext>(); walkTree.OnNodeBegin = OnNodeBegin; walkTree.OnNodeEnd = OnNodeEnd; walkTree.Walk(StrategyTree); if (IsVerbose) { Output.WriteLine("Analysis of strategy tree: '{0}'", StrategyTree.Version.Description); Output.WriteLine("Players: {0}, nodes: {1:#,#}, leaves: {2:#,#}", StrategyTree.PlayersCount, StrategyTree.NodesCount, LeavesCount); Output.Write("Blinds:"); for (int p = 0; p < _playersCount; ++p) { Output.Write(" {0}", StrategyTree.Nodes[p + 1].Amount); } Output.WriteLine(); Output.WriteLine("Hero position: {0}, moves: {1:#,#}", HeroPosition, MovesCount); Output.WriteLine("Zero str probab moves of hero: total {0} ({1:0.00%}), leaves: {2} ({3:0.00%})", ZaspMovesCount, (double)ZaspMovesCount / MovesCount, ZaspLeavesCount, (double)ZaspLeavesCount / LeavesCount); Output.WriteLine("Action statistics in nodes with non-zero strategic probability:"); for (int r = 0; r < _stats.Count; ++r) { Console.WriteLine("Round {0}: nodes {1,10:#,#}, f: {2:0.00000}, c: {3:0.00000}, r: {4:0.00000}", r, _stats[r].NZaspMovesCount, _stats[r].SumNZaspFold / _stats[r].NZaspMovesCount, _stats[r].SumNZaspCall / _stats[r].NZaspMovesCount, _stats[r].SumNZaspRaise / _stats[r].NZaspMovesCount); } } } finally { } }
private void Calculate() { WalkUFTreePP <StrategyTree, CalculateValuesContext> wt = new WalkUFTreePP <StrategyTree, CalculateValuesContext>(); wt.OnNodeBegin = CalculateValues_OnNodeBegin; wt.OnNodeEnd = CalculateValues_OnNodeEnd; wt.Walk(Strategies[HeroPosition]); Value = Strategies[HeroPosition].Nodes[0].Probab; WalkUFTreePP <StrategyTree, CalculateBrContext> wt1 = new WalkUFTreePP <StrategyTree, CalculateBrContext>(); wt1.OnNodeBegin = CalculateBr_OnNodeBegin; wt1.OnNodeEnd = CalculateBr_OnNodeEnd; wt1.Walk(Strategies[HeroPosition]); }
private void DoVerifyChanceTree(ChanceTree ct) { Assert.AreEqual(ct.PlayersCount, _gd.MinPlayers); try { VerifyChanceTree.VerifyS(ct); } catch (Exception e) { Assert.Fail(e.ToString()); } WalkUFTreePP <ChanceTree, Context> wt = new WalkUFTreePP <ChanceTree, Context>(); wt.OnNodeBegin = OnNodeBegin; wt.OnNodeEnd = OnNodeEnd; wt.Walk(ct); }
public ChanceTree ConvertToChanceTree() { int depth = PlayersCount * RoundsCount; int nodesCount = CountNodes <int> .Count(Root, Root as object); ChanceTree ct = new ChanceTree(nodesCount); ct.SetNodesMemory(0); // To clear results. SyncUniAndUF <int> .Sync(Root, Root as object, ct, SyncNodes); WalkUFTreePP <ChanceTree, WalkUFTreePPContext> wt = new WalkUFTreePP <ChanceTree, WalkUFTreePPContext>(); wt.OnNodeEnd = FinalizeChanceTree_OnNodeEnd; wt.Walk(ct); ct.PlayersCount = PlayersCount; ct.Version.Description = String.Format("Chance tree (MC:{0:0,0}, {1})", SamplesCount, SourceInfo); return(ct); }
void Prepare() { _oppPosition = 1 - HeroPosition; // Create a strategy for each player. We need both because players can use different abstractions. PrepareHeroStrategy(); ChanceTree pct; pct = ExtractPlayerChanceTree.ExtractS(ChanceTree, _oppPosition); _oppStrategy = CreateStrategyTreeByChanceAndActionTrees.CreateS(pct, ActionTree); _variables = new Variables(); _constraintsLE = new List <Constraint>(); _constraintsEQ = new List <Constraint>(); PrepareHero(); // Create index for the chance tree. _chanceTreeNodes = new int[PLAYERS_COUNT][][]; for (int r = 0; r < _roundsCount; ++r) { int oppSize = _chanceIndexSizes[_oppPosition][r]; _chanceTreeNodes[r] = new int[oppSize][]; int heroSize = _chanceIndexSizes[HeroPosition][r]; for (int i = 0; i < oppSize; ++i) { _chanceTreeNodes[r][i] = new int[heroSize]; } } WalkUFTreePP <ChanceTree, PrepareChanceIndexContext> wt1 = new WalkUFTreePP <ChanceTree, PrepareChanceIndexContext>(); wt1.OnNodeBegin = PrepareChanceIndex_OnNodeBegin; wt1.Walk(ChanceTree); // This will be the index of v0 variable, because it will be added next. _v0 = _variables.Count; PrepareOpp(); }
/// <summary> /// Converts a chance tree to a dictionary of leaves. This allows to compare trees with different structure easily. /// Use a string key of two charachters, this is proven to be very fast. // Todo: use new hash. /// </summary> static Dictionary <string, IntPtr> ConvertToDict(ChanceTree ct, int maxDepth) { WalkUFTreePP <ChanceTree, ConvertToDictContext> wt = new WalkUFTreePP <ChanceTree, ConvertToDictContext>(); Dictionary <string, IntPtr> dict = new Dictionary <string, IntPtr>(); StringBuilder sb = new StringBuilder(); wt.OnNodeBegin = (tree, stack, depth) => { Int64 n = stack[depth].NodeIdx; if (depth > 0) { int card = tree.Nodes[n].Card; stack[depth].Key = stack[depth - 1].Key + _cardToString[card]; } if (depth == maxDepth) { dict.Add(stack[depth].Key, new IntPtr(tree.Nodes + n)); } }; wt.Walk(ct); return(dict); }
public void Analyze(ChanceTree ct) { if (!string.IsNullOrEmpty(ZeroNodesLogName)) { _zeroNodesLog = new StreamWriter(ZeroNodesLogName); } try { _playersCount = ct.PlayersCount; int roundsCount = ct.CalculateRoundsCount(); _maxDepth = roundsCount * _playersCount; _seenCards = new bool[roundsCount][][]; for (int r = 0; r < roundsCount; ++r) { _seenCards[r] = new bool[_playersCount][].Fill(i => new bool[0]); } LeavesCount = 0; SumPotShares = new double[_playersCount]; ZeroChanceLeavesCount = ZeroPotSharesCount = 0; WalkUFTreePP <ChanceTree, AnalyzeContext> walkTree = new WalkUFTreePP <ChanceTree, AnalyzeContext>(); walkTree.OnNodeBegin = OnNodeBegin; walkTree.Walk(ct); if (IsVerbose) { Output.WriteLine("Analysis of chance tree: '{0}'", ct.Version.Description); Output.WriteLine("Players: {0}, nodes: {1:#,#}, leaves: {2:#,#}", ct.PlayersCount, ct.NodesCount, LeavesCount); Output.WriteLine("Leaves statistics:"); double totalPotShares = 0; for (int p = 0; p < _playersCount; ++p) { totalPotShares += SumPotShares[p]; Output.WriteLine("Sum pot shares pos {0}: {1:0.000}", p, SumPotShares[p]); } Output.WriteLine("Sum pot shares total: {0:0.000}", totalPotShares); Output.WriteLine("Zero leaves: chance: {0} ({1:0.00%}), pot shares: {2} ({3:0.00%})", ZeroChanceLeavesCount, (double)ZeroChanceLeavesCount / LeavesCount, ZeroPotSharesCount, (double)ZeroPotSharesCount / LeavesCount); Output.WriteLine("Seen cards:"); for (int r = 0; r < roundsCount; ++r) { Output.WriteLine("Round {0}:", r); for (int p = 0; p < _playersCount; ++p) { Output.Write("Pos {0}:", p); int seenCount = 0; for (int c = 0; c < _seenCards[r][p].Length; ++c) { if (_seenCards[r][p][c]) { seenCount++; Output.Write(" {0,2}", c); } } Output.WriteLine(" ({0})", seenCount); } } } } finally { if (_zeroNodesLog != null) { _zeroNodesLog.Close(); _zeroNodesLog = null; } } }
void OnOppDeal(int [] cards, int param) { int oppPos = 1 - _heroPos; uint[] ranks = new uint[_playersCount]; GameDef.GameRules.Showdown(GameDef, _hands, ranks); double oppShowdown = 0; if (ranks[_heroPos] > ranks[oppPos]) { oppShowdown = -1; } else if (ranks[_heroPos] < ranks[oppPos]) { oppShowdown = 1; } int[] oppAbstrCards = HandToAbstractCards(_hands[oppPos]); var wt = new WalkUFTreePP <StrategyTree, CalcOppValuesContext>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; if (d > 0) { s[d].DealPath = new List <int>(s[d - 1].DealPath); s[d].StrProbab = s[d - 1].StrProbab; } if (_pt.Nodes[n].IsDealerAction) { s[d].DealPath.Add(_pt.Nodes[n].Card); } else if (_pt.Nodes[n].IsPlayerAction(oppPos) && n > _playersCount) { s[d].StrProbab = _pt.Nodes[n].Probab; } }; wt.OnNodeEnd = (t, s, d) => { Int64 n = s[d].NodeIdx; if (s[d].ChildrenCount == 0) { // A leaf. for (int r = 0; r < s[d].DealPath.Count; ++r) { if (s[d].DealPath[r] != oppAbstrCards[r]) { // This deal paths is not of interest. return; } } uint atIdx = _ptExt[oppPos][n].AtIdx; UInt16 activePlayers = _at.Nodes[atIdx].ActivePlayers; UInt16 oppMask = (UInt16)(1 << oppPos); double gvPS = _ptExt[oppPos][n].PotFactor * s[d].StrProbab; double gv; if (activePlayers == (activePlayers & (~oppMask))) { // The opp folded and loses its inPot gv = -gvPS; } else if (activePlayers == oppMask) { // The hero. folds: opp wins gv = gvPS; } else { // Showdown (inpots are equal) gv = gvPS * oppShowdown; } _oppGv[atIdx] += gv; } }; wt.Walk(_pt); }
private void CreatePlayerTrees() { //_pt = StrategyTree.Read<StrategyTree>(_curSnapshotInfo.StrategyFile[heroPos]); for (int heroPos = 0; heroPos < _playersCount; ++heroPos) { if (IsVerbose) { Console.WriteLine("Creating player tree for pos {0}", heroPos); } _ptExt[heroPos] = new Node[_pt.NodesCount]; var wt = new WalkUFTreePP <StrategyTree, CreatePlayerTreeContext>(); wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; if (d > 0) { s[d].AtIdx = s[d - 1].AtIdx; s[d - 1].InPot.CopyTo(s[d].InPot, 0); } if (!_pt.Nodes[n].IsDealerAction && n > 0) { s[d].InPot[_pt.Nodes[n].Position] += _pt.Nodes[n].Amount; s[d].AtIdx = FindActionTreeNodeIdx(t, n, s[d].AtIdx, s[d - 1].ChildrenCount - 1); } _ptExt[heroPos][n].AtIdx = s[d].AtIdx; /*if (d == 0) * { * } * else * { * } * _playerTrees[heroPos].SetDepth(n, (byte) d); * if (d > _init.PlayerTreeMaxDepth[heroPos]) * _init.PlayerTreeMaxDepth[heroPos] = d; * if (st.Nodes[n].IsDealerAction) * { * _playerTrees[heroPos].Nodes[n].Position = (byte) _playersCount; * _playerTrees[heroPos].Nodes[n].ChanceId = (UInt32) st.Nodes[n].Card; * } * else if (n > 0) * { * s[d].AtIdx = FindActionTreeNodeIdx(t, n, s[d].AtIdx, * s[d - 1].ChildrenCount - 1); * * _playerTrees[heroPos].Nodes[n].Position = (byte) st.Nodes[n].Position; * if (st.Nodes[n].Position == heroPos) * { * * _playerTrees[heroPos].Nodes[s[d - 1].NodeIdx].IsHeroActing = true; * _playerTrees[heroPos].Nodes[n].SetStrVar(this, st.Nodes[n].Probab); * } * } * _playerTrees[heroPos].Nodes[n].AtIdx = Node.INVALID_AT_IDX; * if (d == _playersCount + 1) * { * // Set up the top tree. Do it at the end when the node is initialized * TopTreeNode ttn = new TopTreeNode(this, heroPos, n); * _topTrees[heroPos].Nodes.Add(ttn); * }*/ }; wt.OnNodeEnd = (t, s, d) => { Int64 n = s[d].NodeIdx; if (s[d].ChildrenCount == 0) { // A leaf Debug.Assert(_playersCount == 2); _ptExt[heroPos][n].PotFactor = Math.Min(s[d].InPot[0], s[d].InPot[1]); } }; wt.Walk(_pt); } }
void BestResponseValuesUp() { int[] heroAbstrCards = HandToAbstractCards(_hands[_heroPos]); var wt = new WalkUFTreePP <StrategyTree, BrValuesUpContext>(); Node[] heroPtExt = _ptExt[_heroPos]; wt.OnNodeBegin = (t, s, d) => { Int64 n = s[d].NodeIdx; s[d].OldGv = heroPtExt[n].GameValue; if (d > 0) { s[d].DealPath = new List <int>(s[d - 1].DealPath); } if (_pt.Nodes[n].IsDealerAction) { s[d].DealPath.Add(_pt.Nodes[n].Card); } }; wt.OnNodeEnd = (t, s, d) => { Int64 n = s[d].NodeIdx; for (int r = 0; r < s[d].DealPath.Count; ++r) { if (s[d].DealPath[r] != heroAbstrCards[r]) { // This deal paths is not of interest. return; } } if (s[d].ChildrenCount == 0) { // A leaf. // Update game value. Overwrite the old one, because we have calculated // a fully correct value for the current opponent strategy and this hero hand. heroPtExt[n].GameValue = -_oppGv[heroPtExt[n].AtIdx]; } // Now we know the game value of this node. if (n == 0) { // Update total game values, counting the fact that actually the update is started from iteration 2. // LastBrValues[_heroPos] = heroPtExt[n].GameValue / (IterationCounts[_heroPos] - 1); LastBrValues[_heroPos] = heroPtExt[n].GameValue; return; } long pn = s[d - 1].NodeIdx; if (_pt.Nodes[n].IsPlayerAction(_heroPos) && n > _playersCount) { // maximize value if (s[d - 1].ChildrenCount == 1) { heroPtExt[pn].GameValue = heroPtExt[n].GameValue; } else { heroPtExt[pn].GameValue = Math.Max(heroPtExt[pn].GameValue, heroPtExt[n].GameValue); } } else { // Sum values by updating. heroPtExt[pn].GameValue -= s[d].OldGv; heroPtExt[pn].GameValue += heroPtExt[n].GameValue; } }; wt.Walk(_pt); }
private void Prepare() { CreateHeroStrategy(); _playersCount = Strategies.Length; _maxCard = new int[_playersCount][]; _chanceIndexSizes = new int[_playersCount][]; _strategicProbabs = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); if (PrepareVis) { _visGameValues = new double[Strategies[HeroPosition].NodesCount]; } else { _visGameValues = null; } _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < _playersCount; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _chanceIndexSizes[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / _playersCount; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < _playersCount; ++p) { _chanceIndexSizes[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _chanceIndexSizes[p][r] = _chanceIndexSizes[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; for (int p = 0; p < _playersCount; ++p) { if (p != HeroPosition) { _strategicProbabs[p][n] = new double[_chanceIndexSizes[p][round]]; } } } } // Fill strategic probability for each player except the hero. for (_curPlayer = 0; _curPlayer < _playersCount; ++_curPlayer) { if (_curPlayer == HeroPosition) { continue; } WalkUFTreePP <StrategyTree, PrepareStrategicProbabsContext> wt = new WalkUFTreePP <StrategyTree, PrepareStrategicProbabsContext>(); wt.OnNodeBegin = PrepareStrategicProbabs_OnNodeBegin; wt.Walk(Strategies[_curPlayer]); } _chanceTreeNodes = new int[_roundsCount][][]; for (int r = 0; r < _roundsCount; ++r) { int oppChanceIndexSize = 1; for (int p = 0; p < _playersCount; ++p) { if (p == HeroPosition) { continue; } oppChanceIndexSize *= _chanceIndexSizes[p][r]; } int size = _chanceIndexSizes[HeroPosition][r]; _chanceTreeNodes[r] = new int[size][]; for (int i = 0; i < size; ++i) { _chanceTreeNodes[r][i] = new int[oppChanceIndexSize]; } } WalkUFTreePP <ChanceTree, PrepareChanceIndexContext> wt1 = new WalkUFTreePP <ChanceTree, PrepareChanceIndexContext>(); wt1.OnNodeBegin = PrepareChanceIndex_OnNodeBegin; wt1.Walk(ChanceTree); }
private void Prepare() { _playersCount = Strategies.Length; _maxCard = new int[_playersCount][]; _spArrayLengths = new int[_playersCount][]; _spArrays = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); if (PrepareVis) { _visLeaveValues = new double[_playersCount][][].Fill(i => new double[ActionTree.NodesCount][]); } _gameValues = new double[_playersCount]; _roundsCount = ChanceTree.CalculateRoundsCount(); for (int p = 0; p < _playersCount; ++p) { _maxCard[p] = new int[_roundsCount].Fill(int.MinValue); _spArrayLengths[p] = new int[_roundsCount].Fill(int.MinValue); } for (Int64 n = 1; n < ChanceTree.NodesCount; ++n) { int round = (ChanceTree.GetDepth(n) - 1) / _playersCount; if (_maxCard[ChanceTree.Nodes[n].Position][round] < ChanceTree.Nodes[n].Card) { _maxCard[ChanceTree.Nodes[n].Position][round] = ChanceTree.Nodes[n].Card; } } for (int p = 0; p < _playersCount; ++p) { _spArrayLengths[p][0] = _maxCard[p][0] + 1; for (int r = 1; r < _roundsCount; ++r) { _spArrayLengths[p][r] = _spArrayLengths[p][r - 1] * (_maxCard[p][r] + 1); } } _actionTreeIndex = new UFTreeChildrenIndex(ActionTree); for (Int64 n = 1; n < ActionTree.NodesCount; ++n) { if (_actionTreeIndex.GetChildrenCount(n) == 0) { // This is a leaf int round = ActionTree.Nodes[n].Round; for (int p = 0; p < _playersCount; ++p) { _spArrays[p][n] = new double[_spArrayLengths[p][round]]; if (PrepareVis) { _visLeaveValues[p][n] = new double[_spArrayLengths[p][round]]; } } } } for (_curPlayer = 0; _curPlayer < _playersCount; ++_curPlayer) { WalkUFTreePP <StrategyTree, PrepareContext> wt = new WalkUFTreePP <StrategyTree, PrepareContext>(); wt.OnNodeBegin = Prepare_OnNodeBegin; wt.Walk(Strategies[_curPlayer]); } }
void DoWalkTest(int startNode, int expectedNodesCount, int depth, int childCount, bool checkPostValue) { int power = 1; int nodesCount = 0; for (int d = 0; d <= depth; ++d) { nodesCount += power; power *= childCount; } TestTree tree = new TestTree(nodesCount); int idx = 0; _postValue = 0; CreateTestTree(tree, idx, ref idx, 0, 3, 4); WalkUFTreePP <TestTree, WalkUFTreePPContext> wt = new WalkUFTreePP <TestTree, WalkUFTreePPContext>(); int treeBeginCount = 0; int treeEndCount = 0; int nodeBeginCount = 0; int nodeEndCount = 0; wt.OnNodeBegin = (t, s, d) => { Assert.AreEqual(1, treeBeginCount); Assert.AreEqual(0, treeEndCount); Assert.AreEqual(0, t.Nodes[s[d].NodeIdx].BeginCallCount); Assert.AreEqual(0, t.Nodes[s[d].NodeIdx].EndCallCount); Assert.AreEqual(nodeBeginCount + startNode, t.Nodes[s[d].NodeIdx].PreValue); Assert.AreEqual(0, s[d].ChildrenCount); if (d > 0) { Assert.IsTrue(s[d - 1].ChildrenCount >= 1); Assert.IsTrue(s[d - 1].ChildrenCount <= 4); } t.Nodes[s[d].NodeIdx].BeginCallCount++; nodeBeginCount++; }; wt.OnNodeEnd = (t, s, d) => { Assert.AreEqual(1, treeBeginCount); Assert.AreEqual(0, treeEndCount); Assert.AreEqual(1, t.Nodes[s[d].NodeIdx].BeginCallCount); Assert.AreEqual(0, t.Nodes[s[d].NodeIdx].EndCallCount); Assert.AreEqual(t.GetDepth(s[d].NodeIdx), d); if (checkPostValue) { Assert.AreEqual(nodeEndCount, t.Nodes[s[d].NodeIdx].PostValue); } int expChildrenCount = d == 3 ? 0 : 4; Assert.AreEqual(expChildrenCount, s[d].ChildrenCount); nodeEndCount++; t.Nodes[s[d].NodeIdx].EndCallCount++; }; wt.OnTreeBegin = (t) => { Assert.AreEqual(0, treeBeginCount); Assert.AreEqual(0, treeEndCount); treeBeginCount++; }; wt.OnTreeEnd = (t) => { Assert.AreEqual(1, treeBeginCount); Assert.AreEqual(0, treeEndCount); treeEndCount++; }; wt.Walk(tree, startNode); Assert.AreEqual(1, treeBeginCount); Assert.AreEqual(1, treeEndCount); Assert.AreEqual(expectedNodesCount, nodeBeginCount); Assert.AreEqual(expectedNodesCount, nodeEndCount); }