public InformationSet GetFullInformationSet(string code) { InformationSet result = new InformationSet(); Core.Functions client = new Core.Functions(); result = client.GetFullInformationSet(code); return result; }
public static string GetPathFromInformationSet(InformationSet infoSet) { switch (infoSet) { case InformationSet.WorldInformation: return(GameInfo.WorldDataPath); case InformationSet.LevelInformation: return(GameInfo.LevelDataPath); case InformationSet.RoomInformation: return(GameInfo.RoomDataPath); case InformationSet.InteractableInformation: return(GameInfo.InteractableDataPath); case InformationSet.ObstacleInformation: return(GameInfo.ObstacleDataPath); case InformationSet.ItemInformation: return(GameInfo.ItemDataPath); case InformationSet.MessageInformation: return(GameInfo.MessageDataPath); } return(""); }
public PlayerNode(string playerName, string charName, InformationSet infoSet) { this.playerName = playerName; this.charName = charName; this.InfoSet = infoSet; playerDead = false; character = CharacterAbstractFactory.CreatePlayer(charName); }
public static string LoadGameFile(InformationSet informationSet) { string path = GetPathFromInformationSet(informationSet); if (File.Exists(path)) { return(File.ReadAllText(path)); } return(""); }
public void TrainedOneHandTest() { // this number highly depends on abstraction (i.e. stack size, bet size, hand strength and actions) int numberOfStatesPerBucket = 15908; Assert.AreEqual(numberOfStatesPerBucket, trainer.GameNodes.Count); //check if information sets are complete var infoSet = new InformationSet <ActionBucket>() { CardBucket = (int)StartHandBucket.Best, ActionHistory = new List <ActionBucket>() }; //check if some nodes has been added to the dictionary var gameNode = trainer.GameNodes[infoSet.GetHashCode()]; Assert.IsNotNull(gameNode); infoSet = new InformationSet <ActionBucket>() { CardBucket = (int)StartHandBucket.Best, ActionHistory = new List <ActionBucket>() { ActionBucket.Call, ActionBucket.LowBet } }; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; Assert.IsNotNull(gameNode); infoSet = new InformationSet <ActionBucket>() { CardBucket = (int)StartHandBucket.Best, ActionHistory = new List <ActionBucket>() { ActionBucket.LowBet, ActionBucket.LowBet, ActionBucket.LowBet, ActionBucket.LowBet } }; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; Assert.IsNotNull(gameNode); infoSet = new InformationSet <ActionBucket>() { CardBucket = (int)StartHandBucket.Worst, ActionHistory = new List <ActionBucket>() { ActionBucket.LowBet, ActionBucket.LowBet, ActionBucket.LowBet } }; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; Assert.IsNotNull(gameNode); }
private List <float> getOptimalStrategy(byte handBucket, List <ActionBucket> actions) { var infoSet = new InformationSet <ActionBucket>() { CardBucket = handBucket, ActionHistory = actions }; var gameNode = trainedTree[infoSet.GetHashCode()]; Assert.IsNotNull(gameNode); return(gameNode.calculateAverageStrategy()); }
public void NashEquilibriumPlayer1Test() { // get information set (jack and first action) var infoSet = new InformationSet <GameAction>() { CardBucket = (int)CardValue.Jack, ActionHistory = new List <GameAction>() // No actions => first turn }; var gameNode = trainer.GameNodes[infoSet.GetHashCode()]; var averageStrategy = gameNode.calculateAverageStrategy(); // Jack's bet probability (alpha) must lie within 0 and 1/3 to be in nash equilibrium var alpha = averageStrategy[(int)GameAction.Bet]; float alphaMax = 1f / 3f; float alphaMin = 0f; Assert.IsTrue(alpha < (alphaMax + tolerance)); Assert.IsTrue(alpha > (alphaMin - tolerance)); // sum of bet and pass probability should be approximately one, since there are only two actions in Kuhn Poker var sum = averageStrategy[(int)GameAction.Pass] + averageStrategy[(int)GameAction.Bet]; Assert.IsTrue(sum < 1 + tolerance && sum > 1 - tolerance); // alpha value is further used to evaluate nash equilibrium of player 1 infoSet.CardBucket = (int)CardValue.King; // 3 = King gameNode = trainer.GameNodes[infoSet.GetHashCode()]; averageStrategy = gameNode.calculateAverageStrategy(); // King bet probability should be 3 * alpha var betProbability = averageStrategy[(int)GameAction.Bet]; var betProbabilityExpected = (3 * alpha); Assert.IsTrue(Math.Abs(betProbability - betProbabilityExpected) < tolerance); infoSet.CardBucket = (int)CardValue.Queen; // player 1 checked first turn, Player 2 bet second turn. infoSet.ActionHistory = new List <GameAction>() { GameAction.Pass, GameAction.Bet }; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; averageStrategy = gameNode.calculateAverageStrategy(); // Queen should call (bet) with a probability of alpha + 1/3 betProbability = averageStrategy[(int)GameAction.Bet]; betProbabilityExpected = (alpha + 1f / 3f); Assert.IsTrue(Math.Abs(betProbability - betProbabilityExpected) < tolerance); }
public InformationSet GetFullInformationSet(string code) { InformationSet result = new InformationSet(); if (false) //WebAPI { // To do : problème } else //DLL { Core.Functions client = new Core.Functions(); result = client.GetFullInformationSet(code); } return(result); }
/// <summary> /// Dropdown has changed - Update Information. /// </summary> public void InformationSetChanged() { MessageUI.text = ""; string value = InformationSetType.options[InformationSetType.value].text; _currentInformationSet = (InformationSet)Enum.Parse(typeof(InformationSet), value); if (_currentInformationSet == InformationSet.NameGeneration) { ShowNameGenerationEditor(); PopulateNameGenerationFromFile(); } else { ShowDataEditor(); PopulateFromJson(); } }
public void NashEquilibriumPlayer2Test() { // Get information set (jack and first action) var infoSet = new InformationSet <GameAction>() { CardBucket = (int)CardValue.Jack, ActionHistory = new List <GameAction>() { GameAction.Bet } // No actions => first turn }; var gameNode = trainer.GameNodes[infoSet.GetHashCode()]; var averageStrategy = gameNode.calculateAverageStrategy(); // Jack should never bet (i.e. call) after player 1 bet var betProbability = averageStrategy[(int)GameAction.Bet]; var betProbabilityExpected = 0f; Assert.IsTrue(Math.Abs(betProbability - betProbabilityExpected) < tolerance); // Queen should bet (i.e. call) 1/3 after player 1 bet infoSet.CardBucket = (int)CardValue.Queen; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; averageStrategy = gameNode.calculateAverageStrategy(); betProbability = averageStrategy[(int)GameAction.Bet]; betProbabilityExpected = (1f / 3f); Assert.IsTrue(Math.Abs(betProbability - betProbabilityExpected) < tolerance); // Jack should bet 1/3 of the time after being passed (i.e. checked) to infoSet.CardBucket = (int)CardValue.Jack; infoSet.ActionHistory = new List <GameAction> { GameAction.Pass }; gameNode = trainer.GameNodes[infoSet.GetHashCode()]; averageStrategy = gameNode.calculateAverageStrategy(); betProbability = averageStrategy[(int)GameAction.Bet]; betProbabilityExpected = (1f / 3f); Assert.IsTrue(Math.Abs(betProbability - betProbabilityExpected) < tolerance); }
public InformationSet GetFullInformationSet(string code) { if (true) //WebAPI { RunAsync(code).Wait(); } else //DLL { Functions client = new Functions(); try { result = client.GetFullInformationSet(code); } catch (Exception e) { result.executeResult = -1; result.AdditionalInformation = e.Message; } } return(result); }
static async Task RunAsync(string code) { using (var client = new HttpClient()) { string baseAddress = ConfigurationManager.AppSettings["baseAddress"]; client.BaseAddress = new Uri(baseAddress); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = new HttpResponseMessage(); string responseResult = ""; // GetFullInformationSet string urlEncode = WebUtility.UrlEncode(code); response = await client.GetAsync("api/ParserIO/GetFullInformationSet?code=" + urlEncode); if (response.IsSuccessStatusCode) { responseResult = await response.Content.ReadAsStringAsync(); JavaScriptSerializer JSserializer = new JavaScriptSerializer(); result = JSserializer.Deserialize <InformationSet>(responseResult); } } }
public static Type GetTypeFromInformationSet(InformationSet infoSet) { switch (infoSet) { case InformationSet.WorldInformation: return(typeof(WorldData)); case InformationSet.LevelInformation: return(typeof(LevelArray)); case InformationSet.RoomInformation: return(typeof(RoomArray)); case InformationSet.InteractableInformation: return(typeof(InteractableArray)); case InformationSet.ObstacleInformation: return(typeof(ObstacleArray)); case InformationSet.ItemInformation: return(typeof(ItemArray)); } return(null); }
public RuleBasedNode(string playerName, string charName, InformationSet infoSet, bool playerdead) : base(playerName, charName, infoSet, playerdead) { }
public int Parse_1(string Barcode, out string ACL, //1 out string ADDITIONALID, //2 out string BESTBEFORE, //3 out string CIP, //4 out string Company, //5 out bool containsOrMayContainId, out string CONTENT, //6 out string COUNT, //7 out string EAN, out string Expiry, //8 out string Family, //9 out string GTIN, //10 out string LIC, //11 out string Lot, //12 out string LPP, //13 out string NaS7, //14 out string NormalizedBESTBEFORE, //15 out string NormalizedExpiry, //16 out string NormalizedPRODDATE, //17 out string PCN, //18 out string PRODDATE, //19 out string Product, //20 out string Quantity, //21 out string Reference, //22 out string NaSIdParamName, out string Serial, //23 out string SSCC, //24 out string SubType, //25 out string SymbologyID, out string Type, //26 out string UDI, out string UoM, //28 out string UPN, out string VARCOUNT, //29 out string VARIANT, //30 out string Errors) { int executeResult = 0; ACL = ""; //1 ADDITIONALID = ""; //2 BESTBEFORE = ""; //3 CIP = ""; //4 Company = ""; //5 containsOrMayContainId = false; //31 CONTENT = ""; //6 COUNT = ""; //7 EAN = ""; Expiry = ""; //8 Family = ""; //9 GTIN = ""; //10 LIC = ""; //11 Lot = ""; //12 LPP = ""; //13 NaS7 = ""; //14 NormalizedBESTBEFORE = ""; //15 NormalizedExpiry = ""; //16 NormalizedPRODDATE = ""; //17 PCN = ""; //18 PRODDATE = ""; //19 Product = ""; //20 Quantity = ""; //21 Reference = ""; //22 NaSIdParamName = ""; Serial = ""; //23 SSCC = ""; //24 SubType = ""; //25 SymbologyID = ""; Type = ""; //26 UDI = ""; UoM = ""; //28 UPN = ""; VARCOUNT = ""; //29 VARIANT = ""; //30 Errors = ""; try { InformationSet result = new InformationSet(); Core.Functions client = new Core.Functions(); result = client.GetFullInformationSet(Barcode); executeResult = result.executeResult; Type = result.Type; SubType = result.SubType; ACL = result.ACL; ADDITIONALID = result.ADDITIONALID; BESTBEFORE = result.BESTBEFORE; CIP = result.CIP; //4 Company = ""; // result.Company; //5 Obsolete containsOrMayContainId = result.ContainsOrMayContainId; CONTENT = result.CONTENT; //6 COUNT = result.COUNT; //7 EAN = result.EAN; Expiry = result.Expiry; //8 Family = result.Family; //9 GTIN = result.GTIN; //10 LIC = result.LIC; //11 Lot = result.Lot; //12 LPP = result.LPP; //13 NaS7 = result.NaS7; //14 NormalizedBESTBEFORE = result.NormalizedBESTBEFORE; //15 NormalizedExpiry = result.NormalizedExpiry; //16 NormalizedPRODDATE = result.NormalizedPRODDATE; //17 PCN = result.PCN; //18 PRODDATE = result.PRODDATE; //19 Product = ""; // result.Product; //20 //Obsolete Quantity = result.Quantity; //21 Reference = result.Reference; //22 NaSIdParamName = result.NaSIdParamName; Serial = result.Serial; //23 SSCC = result.SSCC; //24 SymbologyID = result.SymbologyID; UDI = result.UDI; UoM = result.UoM; //28 UPN = result.UPN; VARCOUNT = result.VARCOUNT; //29 VARIANT = result.VARIANT; //30 Errors = result.AdditionalInformation; } catch (Exception e) { Errors = Errors + e.Message; } return(executeResult); }
public static bool SaveGameFile(string json, InformationSet informationSet) { string path = GetPathFromInformationSet(informationSet); return(SaveFile(json, path)); }
public RuleBasedNode(string playerName, string charName, InformationSet infoSet) : base(playerName, charName, infoSet) { }
/// <summary> /// Recursively implements the Counterfactual Regret Minimization algorithm /// /// </summary> /// <param name="cards">Hand cards of player 1 and 2</param> /// <param name="actions">Action History</param> /// <param name="probability0">Accumulated action probability of player 1</param> /// <param name="probability1">Accumulated action probability of player 2</param> /// <returns></returns> private float CalculateCounterFactualRegret(int[] cards, List <GameAction> actions, float probability0, float probability1) { int plays = actions.Count; int player = plays % 2; int opponent = 1 - player; if (plays > 1) { bool isLastActionPass = (actions.Last() == GameAction.Pass); bool isSecondLastActionPass = (actions[actions.Count - 2] == GameAction.Pass); bool isPlayerCardHigher = cards[player] > cards[opponent]; bool isDoubleBet = !isLastActionPass && !isSecondLastActionPass; bool isDoublePass = isLastActionPass && isSecondLastActionPass; if (isLastActionPass) { if (isDoublePass) { return(isPlayerCardHigher ? 1 : -1); } else { return(1); } } else if (isDoubleBet) { return(isPlayerCardHigher ? 2 : -2); } } var infoSet = new InformationSet <GameAction>() { CardBucket = cards[player], ActionHistory = actions }; RegretGameNode <GameAction> node = null; var hash = infoSet.GetHashCode(); if (!GameNodes.TryGetValue(hash, out node)) { node = new RegretGameNode <GameAction>(Settings.NumberOfActions); node.InfoSet = infoSet; GameNodes.Add(hash, node); } var strategy = node.calculateStrategy(player == 0 ? probability0 : probability1); var utilities = new List <float>(Settings.NumberOfActions) { 0, 0 }; float nodeUtility = 0; for (int i = 0; i < Settings.NumberOfActions; i++) { var nextAction = (i == 0) ? GameAction.Pass : GameAction.Bet; var nextHistory = new List <GameAction>(actions); nextHistory.Add(nextAction); utilities[i] = player == 0 ? -CalculateCounterFactualRegret(cards, nextHistory, probability0 * strategy[i], probability1) : -CalculateCounterFactualRegret(cards, nextHistory, probability0, probability1 * strategy[i]); nodeUtility += strategy[i] * utilities[i]; } for (int i = 0; i < Settings.NumberOfActions; i++) { float regret = utilities[i] - nodeUtility; node.RegretSum[i] += (player == 0 ? probability1 : probability0) * regret; } return(nodeUtility); }
public override Task <GameActionEntity> GetAction(List <ActionType> possibleActions, int amountToCall) { var infoSet = new InformationSet <ActionBucket>(); infoSet.ActionHistory = actionHistory; infoSet.CardBucket = handBucket; RegretGameNode <ActionBucket> gameNode; trainedTree.TryGetValue(infoSet.GetLongHashCode(), out gameNode); if (gameNode == null) { // this should never occur randomBot.ChipStack = this.ChipStack; return(randomBot.GetAction(possibleActions, amountToCall)); } else { var optimalStrategy = gameNode.calculateAverageStrategy(); var rand = new Random(); double randomValue = rand.NextDouble(); bool isCallActionEnabled = (optimalStrategy.Count == 5); int index = 0; double sumPercent = 0; ActionBucket selectedActionBucket = ActionBucket.None; foreach (ActionBucket action in Enum.GetValues(typeof(ActionBucket))) { if (action == ActionBucket.None) { continue; } if (action == ActionBucket.Call && !isCallActionEnabled) { continue; } double newSumPercent = sumPercent + optimalStrategy[index]; if (randomValue >= sumPercent && randomValue <= newSumPercent) { selectedActionBucket = action; break; } sumPercent = newSumPercent; index++; } ActionType selectedAction = ActionAbstracter.MapToAction(selectedActionBucket, amountToCall); int betSize = 0; switch (selectedAction) { case ActionType.Bet: case ActionType.Raise: betSize = ActionAbstracter.GetBetSize(selectedActionBucket, amountToCall, currentGame.PotSize); break; case ActionType.Call: betSize = amountToCall; break; } if (!possibleActions.Contains(selectedAction)) { // in all-in scenarios actions from bot may differ from possible actions switch (selectedAction) { case ActionType.Bet: case ActionType.Raise: case ActionType.Check: if (possibleActions.Contains(ActionType.Call)) { selectedAction = ActionType.Call; } break; default: throw new Exception("Selected action is illegal!"); } } if (ChipStack < betSize) { betSize = this.ChipStack; } return(Task.FromResult <GameActionEntity>(new GameActionEntity { ActionType = selectedAction, Amount = betSize, PlayerId = this.Id })); } }
/// <summary> /// Traverses the sub tree of the passed hand buckets recursively. Calculates and then backpropagates the counter factual regret for each node. /// </summary> /// <param name="gameState"></param> /// <param name="handBuckets"></param> /// <param name="actions"></param> /// <param name="probabilityPlayer1">probability of player 1 to reach this node</param> /// <param name="probabilityPlayer2">probability of player 2 to reach this node</param> /// <returns></returns> private float CalculateCounterFactualRegret(HeadsUpGameState gameState, byte[] handBuckets, List <ActionBucket> actions, float probabilityPlayer1, float probabilityPlayer2) { int plays = actions.Count; int playerIndex = plays % 2; var newState = gameState.GetCopy(); ActionBucket lastAction = ActionBucket.None; if (actions.Count > 0) { lastAction = actions[plays - 1]; } ActionBucket secondLastAction = ActionBucket.None; if (actions.Count > 1) { secondLastAction = actions[plays - 2]; } bool nextActionCallEnabled = true; bool phaseChanged = false; //the last actions determine whether the next phase has to be set or whether the game (i.e. the recursion) ends switch (lastAction) { case ActionBucket.Pass: if (secondLastAction == ActionBucket.LowBet || secondLastAction == ActionBucket.HighBet || secondLastAction == ActionBucket.MediumBet) { int payoff = (newState.PotSize - newState.AmountToCall) / 2; return((playerIndex == 0) ? payoff : -payoff); } switch (secondLastAction) { case ActionBucket.None: return((playerIndex == 0) ? HeadsupGame.SmallBlindSize : -HeadsupGame.SmallBlindSize); case ActionBucket.Call: newState.SetNextPhase(newState.Phase); phaseChanged = true; break; case ActionBucket.Pass: //check if last pass count is dividable by 2 (then it's a new phase) int lastActionPassCount = 0; for (int i = actions.Count - 1; i >= 0; i--) { if (actions[i] == ActionBucket.Pass) { lastActionPassCount++; } else { //special case: if it's first round, call pass results in ending the round if ((actions[i] == ActionBucket.Call && i == 0) && actions.Count > 2 && actions[i + 1] == ActionBucket.Pass) { lastActionPassCount--; } break; } } if (lastActionPassCount % 2 == 0) { newState.SetNextPhase(newState.Phase); phaseChanged = true; } break; } nextActionCallEnabled = false; break; case ActionBucket.Call: newState.PotSize += newState.AmountToCall; newState.AmountToCall = 0; //special case for first round: big blind needs to check or bet if (actions.Count == 1) { nextActionCallEnabled = false; } else { newState.SetNextPhase(newState.Phase); phaseChanged = true; } break; case ActionBucket.HighBet: case ActionBucket.MediumBet: case ActionBucket.LowBet: int betSize = 0; if (newState.AmountToCall > 0 && newState.AmountToCall == HeadsupGame.SmallBlindSize) { //exception: first round newState.PotSize += HeadsupGame.SmallBlindSize; } int lastActionLowBetCount = 0; for (int i = actions.Count - 1; i >= 0; i--) { if (actions[i] == ActionBucket.LowBet) { lastActionLowBetCount++; } else { break; } } betSize = ActionAbstracter.GetBetSize(lastAction, newState.AmountToCall, newState.PotSize); if (betSize > 0) { newState.AmountToCall = betSize; newState.PotSize += betSize; if (newState.PotSize >= HeadsupGame.StackSize * 2) { phaseChanged = true; newState.Phase = GamePhase.Showdown; } } else { phaseChanged = true; newState.Phase = GamePhase.Showdown; } break; } //if the phase has changed, the next event has to occur (e.g. adding a card to the current board) if (phaseChanged) { if (newState.Phase == GamePhase.Showdown) { int payoff = newState.PotSize / 2; var handComparison = HandComparer.Compare(newState.Player1HoleCards, newState.Player2HoleCards, newState.Board); switch (handComparison) { case HandComparison.None: return(0); case HandComparison.Player1Won: return((playerIndex == 0) ? payoff : -payoff); case HandComparison.Player2Won: return((playerIndex == 0) ? -payoff : payoff); } } else { nextActionCallEnabled = false; List <Card> currentBoard = null; switch (newState.Phase) { case GamePhase.Flop: currentBoard = gameState.Board.Take(3).ToList(); break; case GamePhase.Turn: currentBoard = gameState.Board.Take(4).ToList(); break; case GamePhase.River: currentBoard = gameState.Board; break; } //evaluate new hand buckets byte bucket1 = (byte)HandStrengthAbstracter.MapToBucket(currentBoard, newState.Player1HoleCards); byte bucket2 = (byte)HandStrengthAbstracter.MapToBucket(currentBoard, newState.Player2HoleCards); handBuckets = new byte[] { bucket1, bucket2 }; } } var infoSet = new InformationSet <ActionBucket>() { CardBucket = handBuckets[playerIndex], ActionHistory = actions }; int numberOfActions = Settings.NumberOfActions; if (!nextActionCallEnabled) { numberOfActions = Settings.NumberOfActions - 1; } RegretGameNode <ActionBucket> node = null; long hash = infoSet.GetLongHashCode(); //checks if the current information set already exists in O(1) if (!GameNodes.TryGetValue(hash, out node)) { node = new RegretGameNode <ActionBucket>(numberOfActions); node.InfoSet = infoSet; GameNodes.Add(hash, node); } //gets the strategy of the current player var strategy = node.calculateStrategy(playerIndex == 0 ? probabilityPlayer1 : probabilityPlayer2); // initialise utilities with zeros var utilities = new List <float>(numberOfActions); for (int i = 0; i < numberOfActions; i++) { utilities.Add(0); } float nodeUtility = 0; int index = 0; // traverse the tree further down with a breadth first search foreach (ActionBucket nextAction in Enum.GetValues(typeof(ActionBucket))) { //skip illegal actions if (nextAction == ActionBucket.None) { continue; } if (nextAction == ActionBucket.Call && !nextActionCallEnabled) { continue; } var nextHistory = new List <ActionBucket>(); nextHistory.AddRange(actions.ToArray()); nextHistory.Add(nextAction); utilities[index] = playerIndex == 0 ? -CalculateCounterFactualRegret(newState, handBuckets, nextHistory, probabilityPlayer1 * strategy[index], probabilityPlayer2) : -CalculateCounterFactualRegret(newState, handBuckets, nextHistory, probabilityPlayer1, probabilityPlayer2 * strategy[index]); //accumulate the utility of the sub branches nodeUtility += strategy[index] * utilities[index]; index++; } for (int i = 0; i < numberOfActions; i++) { //calculate the regret float regret = utilities[i] - nodeUtility; //calculate the regret sum based on the current player node.RegretSum[i] += (playerIndex == 0 ? probabilityPlayer2 : probabilityPlayer1) * regret; } return(nodeUtility); }