public void Run() { GameDataLists gameDataLists = new GameDataLists(); gameDataLists.Load(@"..\..\..\datasource\export\exd-all\"); bool result = true; result = result && ValidateCardIds(gameDataLists); result = result && ValidateNpcIds(gameDataLists); result = result && gameDataLists.Link(); if (result) { var mapRuleByCodeName = BuildRuleNameMap(); var mapCardTypeByCodeName = BuildCardTypes(); result = result && ExportRuleNames(gameDataLists.rules, mapRuleByCodeName); result = result && ExportCardTypes(gameDataLists.cardTypes, mapCardTypeByCodeName); result = result && UpdateCards(gameDataLists, mapCardTypeByCodeName); result = result && UpdateNpcs(gameDataLists, mapRuleByCodeName); result = result && UpdateTournaments(gameDataLists, mapRuleByCodeName); } if (result) { LocalizationDB.Get().Save(); TriadCardDB.Get().Save(); TriadNpcDB.Get().Save(); TriadTournamentDB.Get().Save(); } Logger.WriteLine(result ? "Done." : "Aborted"); }
public static void RunSolverStressTest() { int numIterations = 1000 * 1000; Logger.WriteLine("Solver testing start, numIterations:" + numIterations); Stopwatch timer = new Stopwatch(); timer.Start(); TriadDeck testDeck = new TriadDeck(new int[] { 10, 20, 30, 40, 50 }); TriadNpc testNpc = TriadNpcDB.Get().Find("Garima"); Random randStream = new Random(); TriadGameSession solver = new TriadGameSession(); solver.modifiers.AddRange(testNpc.Rules); solver.UpdateSpecialRules(); for (int Idx = 0; Idx < numIterations; Idx++) { TriadGameData testData = solver.StartGame(testDeck, testNpc.Deck, ETriadGameState.InProgressBlue); Random sessionRand = new Random(randStream.Next()); solver.SolverPlayRandomGame(testData, sessionRand); } timer.Stop(); Logger.WriteLine("Solver testing finished, time taken:" + timer.ElapsedMilliseconds + "ms"); if (Debugger.IsAttached) { Debugger.Break(); } }
public static void RunSolverStressTest() { #if DEBUG int numIterations = 1000 * 100; Logger.WriteLine("Solver testing start, numIterations:" + numIterations); perfStats = new SolverPerfStats(); Stopwatch timer = new Stopwatch(); timer.Start(); TriadDeck testDeck = new TriadDeck(new int[] { 10, 20, 30, 40, 50 }); TriadNpc testNpc = TriadNpcDB.Get().Find("Garima"); Random randStream = new Random(); TriadGameSession solver = new TriadGameSession(); solver.modifiers.AddRange(testNpc.Rules); solver.UpdateSpecialRules(); for (int Idx = 0; Idx < numIterations; Idx++) { TriadGameData testData = solver.StartGame(testDeck, testNpc.Deck, ETriadGameState.InProgressBlue); Random sessionRand = new Random(randStream.Next()); solver.SolverPlayRandomGame(testData, sessionRand); } timer.Stop(); Logger.WriteLine("Solver testing finished, time taken:" + timer.ElapsedMilliseconds + "ms"); float TicksToMs = 1000.0f / Stopwatch.Frequency; Logger.WriteLine(">> PlayRandomTurn.SelectSpot: " + (perfStats.PlayRandomTurnSelectSpot * TicksToMs) + "ms"); Logger.WriteLine(">> PlayRandomTurn.SelectCard: " + (perfStats.PlayRandomTurnSelectCard * TicksToMs) + "ms"); Logger.WriteLine(">> PlayRandomTurn.PlaceCard: " + (perfStats.PlayRandomTurnPlaceCard * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.OnPlaced: " + (perfStats.PlaceCardOnPlaced * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.OnPlacedMods: " + (perfStats.PlaceCardOnPlacedMods * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.Captures: " + (perfStats.PlaceCardCaptures * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.CapturesCombo: " + (perfStats.PlaceCardCapturesCombo * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.PostCaptures: " + (perfStats.PlaceCardPostCaptures * TicksToMs) + "ms"); Logger.WriteLine(" >> PlaceCard.AllPlaced: " + (perfStats.PlaceCardAllPlaced * TicksToMs) + "ms"); #endif // DEBUG }
private bool UpdateNpcs(GameDataLists gameDataLists, Dictionary <string, TriadGameModifier> mapRuleNames) { Logger.WriteLine("Updating npc list..."); TriadCardDB cardDB = TriadCardDB.Get(); TriadNpcDB npcDB = TriadNpcDB.Get(); var validDeckIds = new List <string>(); foreach (var npcData in gameDataLists.npcs) { if (npcData.LinkedNpcId == null) { continue; } if (npcData.LinkedNpcId.LinkedName == null || npcData.LinkedNpcId.LinkedLocation == null) { continue; } TriadDeck npcDataDeck = new TriadDeck(); foreach (var cardData in npcData.LinkedCardsFixed) { npcDataDeck.knownCards.Add(cardDB.cards[cardData.Id]); } foreach (var cardData in npcData.LinkedCardsVariable) { npcDataDeck.unknownCardPool.Add(cardDB.cards[cardData.Id]); } npcDataDeck.UpdateDeckId(); validDeckIds.Add(npcDataDeck.deckId); // mistakes were made... TriadNpc npcOb = npcDB.FindByDeckId(npcDataDeck.deckId); int npcId = (npcOb == null) ? npcDB.npcs.Count : npcOb.Id; if (npcOb != null) { // ensure decks are the same if (!npcOb.Deck.Equals(npcDataDeck)) { Logger.WriteLine("FAILED npc update, id:{0} name:{1} is not matching cards!", npcId, npcData.LinkedNpcId.LinkedName.Name.GetCodeName()); return(false); } } else { while (npcDB.npcs.Count <= npcId) { npcDB.npcs.Add(null); } var listMods = new List <TriadGameModifier>(); foreach (var ruleData in npcData.LinkedRules) { listMods.Add(mapRuleNames[ruleData.Name.GetCodeName()]); } var listRewards = new List <TriadCard>(); foreach (var rewardData in npcData.LinkedRewards) { listRewards.Add(cardDB.cards[rewardData.LinkedCard.Id]); } npcOb = new TriadNpc(npcId, listMods, listRewards, npcDataDeck); Logger.WriteLine(">> adding new npc: " + npcOb.ToString()); npcDB.npcs[npcId] = npcOb; } var linkedLoc = npcData.LinkedNpcId.LinkedLocation; linkedLoc.LinkedMap.GetCoords(linkedLoc.ScaledPosX, linkedLoc.ScaledPosZ, out npcOb.LocationX, out npcOb.LocationY); npcOb.Name.Text = npcData.LinkedNpcId.LinkedName.Name.Text; npcOb.LocationMap.Text = npcData.LinkedNpcId.LinkedLocation.LinkedMap.LinkedPlace.Name.Text; } for (int idx = 0; idx < npcDB.npcs.Count; idx++) { TriadNpc npcOb = npcDB.npcs[idx]; if (npcOb != null) { if (!validDeckIds.Contains(npcOb.Deck.deckId)) { Logger.WriteLine(">> removing npc: " + npcOb.ToString() + ", deck:" + npcOb.Deck.ToString()); npcDB.npcs[idx] = null; continue; } if (npcOb.Id != idx) { Logger.WriteLine("FAILED npc update, index mismatch for npc[{0}].Id:{1}, Name:{2}", idx, npcOb.Id, npcOb.Name.GetCodeName()); return(false); } } } return(true); }
private bool UpdateNpcs(Dictionary <int, TriadNpc> npcMap) { TriadNpcDB npcDB = TriadNpcDB.Get(); int newNpcId = npcDB.npcs[npcDB.npcs.Count - 1].Id + 1; bool hasChanges = false; foreach (KeyValuePair <int, TriadNpc> kvp in npcMap) { if (kvp.Key >= newNpcId) { kvp.Value.Id = newNpcId; newNpcId++; while (npcDB.npcs.Count < newNpcId) { npcDB.npcs.Add(null); } npcDB.npcs[kvp.Value.Id] = kvp.Value; Logger.WriteLine("Newly added npc: " + kvp.Value.ToString()); hasChanges = true; continue; } TriadNpc npcMatch = npcDB.Find(kvp.Value.Name); if (npcMatch == null) { foreach (TriadNpc testNpc in npcDB.npcs) { if (testNpc != null && HasMatchingRewards(testNpc.Rewards, kvp.Value.Rewards) && HasMatchingRules(testNpc.Rules, kvp.Value.Rules) && testNpc.Deck.Equals(kvp.Value.Deck)) { Logger.WriteLine("Npc name remap: " + testNpc.ToString() + " => " + kvp.Value.Name); npcMatch = testNpc; hasChanges = true; break; } } } if (npcMatch != null) { kvp.Value.Id = npcMatch.Id; npcDB.npcs[kvp.Value.Id] = kvp.Value; } else { Logger.WriteLine("Newly added npc: " + kvp.Value.ToString()); kvp.Value.Id = newNpcId; newNpcId++; hasChanges = true; while (npcDB.npcs.Count < newNpcId) { npcDB.npcs.Add(null); } npcDB.npcs[kvp.Value.Id] = kvp.Value; } } if (hasChanges) { npcDB.Save(); } return(hasChanges); }
public bool LoadFromXmlStream(Stream stream) { TriadCardDB cardDB = TriadCardDB.Get(); TriadNpcDB npcDB = TriadNpcDB.Get(); try { XmlDocument xdoc = new XmlDocument(); xdoc.Load(stream); foreach (XmlNode testNode in xdoc.DocumentElement.ChildNodes) { try { XmlElement testElem = (XmlElement)testNode; if (testElem != null && testElem.Name == "ui") { int autoScanNum = int.Parse(testElem.GetAttribute("autoScan")); useAutoScan = (autoScanNum == 1); } else if (testElem != null && testElem.Name == "cloud") { int useNum = int.Parse(testElem.GetAttribute("use")); useCloudStorage = (useNum == 1); cloudToken = testElem.HasAttribute("token") ? testElem.GetAttribute("token") : null; } else if (testElem != null && testElem.Name == "card") { int cardId = int.Parse(testElem.GetAttribute("id")); ownedCards.Add(cardDB.cards[cardId]); } else if (testElem != null && testElem.Name == "npc") { int npcId = int.Parse(testElem.GetAttribute("id")); completedNpcs.Add(npcDB.npcs[npcId]); } else if (testElem != null && testElem.Name == "deck") { int npcId = int.Parse(testElem.GetAttribute("id")); TriadNpc npc = TriadNpcDB.Get().npcs[npcId]; if (npc != null) { TriadDeck deckCards = new TriadDeck(); foreach (XmlAttribute attr in testElem.Attributes) { if (attr.Name.StartsWith("card")) { string cardNumStr = attr.Name.Substring(4); int cardNum = int.Parse(cardNumStr); while (deckCards.knownCards.Count < (cardNum + 1)) { deckCards.knownCards.Add(null); } int cardId = int.Parse(attr.Value); deckCards.knownCards[cardNum] = TriadCardDB.Get().cards[cardId]; } } lastDeck.Add(npc, deckCards); } } else { ImageHashData customHash = ImageHashDB.Get().LoadHashEntry(testElem); if (customHash != null) { customHashes.Add(customHash); } else { ImagePatternDigit customDigit = ImageHashDB.Get().LoadDigitEntry(testElem); if (customDigit.Value > 0) { customDigits.Add(customDigit); } } } } catch (Exception ex) { Logger.WriteLine("Loading failed! Exception:" + ex); } } } catch (Exception ex) { Logger.WriteLine("Loading failed! Exception:" + ex); } return(ownedCards.Count > 0); }
public bool LoadFromJson(string jsonStr) { TriadCardDB cardDB = TriadCardDB.Get(); TriadNpcDB npcDB = TriadNpcDB.Get(); try { JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(jsonStr); JsonParser.ObjectValue uiOb = (JsonParser.ObjectValue)jsonOb["ui", null]; if (uiOb != null) { useAutoScan = (JsonParser.BoolValue)uiOb["autoScan", JsonParser.BoolValue.Empty]; } JsonParser.ObjectValue cloudOb = (JsonParser.ObjectValue)jsonOb["cloud", null]; if (cloudOb != null) { useCloudStorage = (JsonParser.BoolValue)cloudOb["use", JsonParser.BoolValue.Empty]; cloudToken = (JsonParser.StringValue)cloudOb["token", null]; } JsonParser.ArrayValue cardsArr = (JsonParser.ArrayValue)jsonOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in cardsArr.entries) { int cardId = (JsonParser.IntValue)value; ownedCards.Add(cardDB.cards[cardId]); } JsonParser.ArrayValue npcsArr = (JsonParser.ArrayValue)jsonOb["npcs", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in npcsArr.entries) { int npcId = (JsonParser.IntValue)value; completedNpcs.Add(npcDB.npcs[npcId]); } JsonParser.ArrayValue decksArr = (JsonParser.ArrayValue)jsonOb["decks", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in decksArr.entries) { JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value; int npcId = (JsonParser.IntValue)deckOb["id"]; TriadNpc npc = TriadNpcDB.Get().npcs[npcId]; if (npc != null) { TriadDeck deckCards = new TriadDeck(); cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value cardValue in cardsArr.entries) { int cardId = (JsonParser.IntValue)cardValue; deckCards.knownCards.Add(cardDB.cards[cardId]); } lastDeck.Add(npc, deckCards); } } JsonParser.ArrayValue favDecksArr = (JsonParser.ArrayValue)jsonOb["favDecks", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in favDecksArr.entries) { JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value; TriadDeckNamed deckCards = new TriadDeckNamed(); cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value cardValue in cardsArr.entries) { int cardId = (JsonParser.IntValue)cardValue; deckCards.knownCards.Add(cardDB.cards[cardId]); } if (deckCards.knownCards.Count > 0) { deckCards.Name = deckOb["name", JsonParser.StringValue.Empty]; favDecks.Add(deckCards); } } JsonParser.ObjectValue imageHashesOb = (JsonParser.ObjectValue)jsonOb["images", null]; if (imageHashesOb != null) { customHashes = ImageHashDB.Get().LoadImageHashes(imageHashesOb); } JsonParser.ArrayValue digitHashesArr = (JsonParser.ArrayValue)jsonOb["digits", null]; if (digitHashesArr != null) { customDigits = ImageHashDB.Get().LoadDigitHashes(digitHashesArr); } } catch (Exception ex) { Logger.WriteLine("Loading failed! Exception:" + ex); } return(ownedCards.Count > 0); }
public static void RunTest(string configPath, bool debugMode) { string testName = System.IO.Path.GetFileNameWithoutExtension(configPath); string configText = System.IO.File.ReadAllText(configPath); JsonParser.ObjectValue rootOb = JsonParser.ParseJson(configText); if (rootOb["type"] != "Screen") { return; } ScannerTriad.VerifyConfig configData = new ScannerTriad.VerifyConfig(); configData.Load(rootOb); // setup npc & modifiers TriadNpc testNpc = TriadNpcDB.Get().Find(configData.npc); if (testNpc == null) { string exceptionMsg = string.Format("Test {0} failed! Can't find npc: {1}", testName, configData.npc); throw new Exception(exceptionMsg); } ScannerTriad.GameState screenGame = new ScannerTriad.GameState(); if (mapValidationRules == null) { mapValidationRules = new Dictionary <string, TriadGameModifier>(); foreach (TriadGameModifier mod in ImageHashDB.Get().modObjects) { mapValidationRules.Add(mod.GetCodeName(), mod); } } foreach (string modName in configData.rules) { screenGame.mods.Add(mapValidationRules[modName]); } Func <ScannerTriad.VerifyCard, TriadCard> ConvertToTriadCard = configCard => { if (configCard.state == ScannerTriad.ECardState.None) { return(null); } if (configCard.state == ScannerTriad.ECardState.Hidden) { return(TriadCardDB.Get().hiddenCard); } TriadCard matchingCard = !string.IsNullOrEmpty(configCard.name) ? TriadCardDB.Get().Find(configCard.name) : TriadCardDB.Get().Find(configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]); if (matchingCard == null) { string exceptionMsg = string.Format("Test {0} failed! Can't match validation card: '{1}' [{2},{3},{4},{5}]", testName, configCard.name, configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]); throw new Exception(exceptionMsg); } return(matchingCard); }; bool needsLockedBlue = false; for (int idx = 0; idx < 5; idx++) { screenGame.blueDeck[idx] = ConvertToTriadCard(configData.deckBlue[idx]); screenGame.redDeck[idx] = ConvertToTriadCard(configData.deckRed[idx]); if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Locked) { needsLockedBlue = true; } } if (needsLockedBlue) { for (int idx = 0; idx < 5; idx++) { if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Visible) { screenGame.forcedBlueCard = screenGame.blueDeck[idx]; break; } } } for (int idx = 0; idx < 9; idx++) { screenGame.board[idx] = ConvertToTriadCard(configData.board[idx]); screenGame.boardOwner[idx] = configData.board[idx].state == ScannerTriad.ECardState.PlacedBlue ? ETriadCardOwner.Blue : configData.board[idx].state == ScannerTriad.ECardState.PlacedRed ? ETriadCardOwner.Red : ETriadCardOwner.Unknown; } TriadGameScreenMemory screenMemory = new TriadGameScreenMemory { logScan = false }; screenMemory.OnNewScan(screenGame, testNpc); screenMemory.gameSession.SolverFindBestMove(screenMemory.gameState, out int solverBoardPos, out TriadCard solverTriadCard, out TriadGameResultChance bestChance); if (bestChance.expectedResult == ETriadGameState.BlueLost && bestChance.winChance <= 0.0f && bestChance.drawChance <= 0.0f) { string exceptionMsg = string.Format("Test {0} failed! Can't find move!", testName); throw new Exception(exceptionMsg); } }
public bool LoadFromJson(string jsonStr) { TriadCardDB cardDB = TriadCardDB.Get(); TriadNpcDB npcDB = TriadNpcDB.Get(); ownedCards.Clear(); completedNpcs.Clear(); lastDeck.Clear(); favDecks.Clear(); try { JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(jsonStr); JsonParser.ObjectValue uiOb = (JsonParser.ObjectValue)jsonOb["ui", null]; if (uiOb != null) { JsonParser.Value BoolTrue = new JsonParser.BoolValue(true); JsonParser.Value BoolFalse = new JsonParser.BoolValue(false); useXInput = (JsonParser.BoolValue)uiOb["xInput", BoolTrue]; alwaysOnTop = (JsonParser.BoolValue)uiOb["onTop", BoolFalse]; forcedLanguage = (JsonParser.StringValue)uiOb["lang", null]; TryGettingFloatValue(uiOb, "fontSize", ref fontSize); TryGettingFloatValue(uiOb, "markerCard", ref markerDurationCard); TryGettingFloatValue(uiOb, "markerSwap", ref markerDurationSwap); TryGettingFloatValue(uiOb, "markerCactpot", ref markerDurationCactpot); TryGettingIntValue(uiOb, "lastNpcId", ref lastNpcId); TryGettingFloatValue(uiOb, "lastWidth", ref lastWidth); TryGettingFloatValue(uiOb, "lastHeight", ref lastHeight); fontSize = Math.Min(Math.Max(fontSize, 10), 40); } JsonParser.ObjectValue cloudOb = (JsonParser.ObjectValue)jsonOb["cloud", null]; if (cloudOb != null) { useCloudStorage = (JsonParser.BoolValue)cloudOb["use", JsonParser.BoolValue.Empty]; cloudToken = (JsonParser.StringValue)cloudOb["token", null]; } JsonParser.ArrayValue cardsArr = (JsonParser.ArrayValue)jsonOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in cardsArr.entries) { int cardId = (JsonParser.IntValue)value; ownedCards.Add(cardDB.cards[cardId]); } JsonParser.ArrayValue npcsArr = (JsonParser.ArrayValue)jsonOb["npcs", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in npcsArr.entries) { int npcId = (JsonParser.IntValue)value; completedNpcs.Add(npcDB.npcs[npcId]); } JsonParser.ArrayValue decksArr = (JsonParser.ArrayValue)jsonOb["decks", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in decksArr.entries) { JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value; int npcId = (JsonParser.IntValue)deckOb["id"]; TriadNpc npc = TriadNpcDB.Get().npcs[npcId]; if (npc != null) { TriadDeck deckCards = new TriadDeck(); cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value cardValue in cardsArr.entries) { int cardId = (JsonParser.IntValue)cardValue; deckCards.knownCards.Add(cardDB.cards[cardId]); } lastDeck.Add(npc, deckCards); } } JsonParser.ArrayValue favDecksArr = (JsonParser.ArrayValue)jsonOb["favDecks", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value value in favDecksArr.entries) { JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value; TriadDeckNamed deckCards = new TriadDeckNamed(); cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty]; foreach (JsonParser.Value cardValue in cardsArr.entries) { int cardId = (JsonParser.IntValue)cardValue; deckCards.knownCards.Add(cardDB.cards[cardId]); } if (deckCards.knownCards.Count > 0) { deckCards.Name = deckOb["name", JsonParser.StringValue.Empty]; favDecks.Add(deckCards); } } JsonParser.ObjectValue imageHashesOb = (JsonParser.ObjectValue)jsonOb["images", null]; if (imageHashesOb != null) { customHashes = ImageHashDB.Get().LoadImageHashes(imageHashesOb); ImageHashDB.Get().hashes.AddRange(customHashes); } } catch (Exception ex) { Logger.WriteLine("Loading failed! Exception:" + ex); } Logger.WriteLine("Loaded player cards: " + ownedCards.Count + ", npcs: " + completedNpcs.Count + ", hashes: " + customHashes.Count); return(ownedCards.Count > 0); }