public void UpdateScreenState(ScreenshotAnalyzer screenReader, bool bDebugMode = false) { checkBoxDetails_CheckedChanged(null, null); if (screenReader.GetCurrentState() != ScreenshotAnalyzer.EState.NoErrors) { Logger.WriteLine("Capture failed: " + screenReader.GetCurrentState()); bHasValidMarkerDeck = false; bHasValidMarkerBoard = false; UpdateStatusDescription(); return; } scanId++; labelScanId.Text = "Scan Id: " + scanId; Logger.WriteLine("Capture " + labelScanId.Text); // multi monitor setup: make sure that overlay and game and on the same monitor Rectangle gameWindowRect = screenReader.GetGameWindowRect(); if (gameWindowRect.Width > 0) { Rectangle gameScreenBounds = Screen.GetBounds(gameWindowRect); Point centerPt = new Point((Left + Right) / 2, (Top + Bottom) / 2); if (!gameScreenBounds.Contains(centerPt)) { Location = gameScreenBounds.Location; Size = gameScreenBounds.Size; bCanAdjustSummaryLocation = true; } } TriadGameScreenMemory.EUpdateFlags updateFlags = TriadGameScreenMemory.EUpdateFlags.None; if (screenReader.GetCurrentGameType() == ScreenshotAnalyzer.EGame.TripleTriad) { // update overlay locations if (bCanAdjustSummaryLocation) { Rectangle gridRect = screenReader.GetGridRect(); if ((gridRect.Width > 0) && (gameWindowRect.Width > 0)) { bCanAdjustSummaryLocation = false; screenReader.ConvertToScaledScreen(ref gridRect); UpdateOverlayLocation(gameWindowRect.Left + ((gridRect.Left + gridRect.Right) / 2) - (panelSummary.Width / 2), gameWindowRect.Top + gridRect.Bottom + 50); } } // solver logic updateFlags = screenMemory.OnNewScan(screenReader.currentTriadGame, npc); if (updateFlags != TriadGameScreenMemory.EUpdateFlags.None) { int markerDeckPos = -1; int markerBoardPos = -1; FindNextMove(out markerDeckPos, out markerBoardPos, out TriadGameResultChance bestChance); ETriadGameState expectedResult = bestChance.expectedResult; TriadCard suggestedCard = screenMemory.deckBlue.GetCard(markerDeckPos); Logger.WriteLine(" suggested move: [" + markerBoardPos + "] " + ETriadCardOwner.Blue + " " + (suggestedCard != null ? suggestedCard.Name : "??") + " (expected: " + expectedResult + ")"); bHasValidMarkerDeck = false; bHasValidMarkerBoard = false; if (markerDeckPos >= 0 && markerBoardPos >= 0) { try { Rectangle rectDeckPos = screenReader.GetBlueCardRect(markerDeckPos); Rectangle rectBoardPos = screenReader.GetBoardCardRect(markerBoardPos); rectDeckPos.Offset(gameWindowRect.Location); rectBoardPos.Offset(gameWindowRect.Location); screenReader.ConvertToScaledScreen(ref rectDeckPos); screenReader.ConvertToScaledScreen(ref rectBoardPos); rectDeckPos.Inflate(10, 10); rectBoardPos.Inflate(10, 10); panelMarkerDeck.Bounds = rectDeckPos; panelMarkerBoard.Bounds = rectBoardPos; panelMarkerBoard.BackColor = (expectedResult == ETriadGameState.BlueWins) ? Color.Lime : (expectedResult == ETriadGameState.BlueDraw) ? Color.Gold : Color.Red; bHasValidMarkerDeck = true; bHasValidMarkerBoard = true; } catch (Exception) { } } } } else if (screenReader.GetCurrentGameType() == ScreenshotAnalyzer.EGame.MiniCactpot) { // update overlay locations if (bCanAdjustSummaryLocation) { Rectangle boardRect = screenReader.GetCactpotBoardRect(); if ((boardRect.Width > 0) && (gameWindowRect.Width > 0)) { screenReader.ConvertToScaledScreen(ref boardRect); bCanAdjustSummaryLocation = false; UpdateOverlayLocation(gameWindowRect.Left + ((boardRect.Left + boardRect.Right) / 2) - (panelSummary.Width / 2), gameWindowRect.Top + boardRect.Bottom + 50); } } // solver logic if (screenReader.currentCactpotGame.numRevealed > 3) { bHasValidMarkerBoard = false; CactpotGame.FindBestLine(screenReader.currentCactpotGame.board, out int fromIdx, out int toIdx); Logger.WriteLine(" suggested line: [" + fromIdx + "] -> [" + toIdx + "]"); if (fromIdx >= 0 && toIdx >= 0) { Rectangle fromBox = screenReader.GetCactpotCircleBox(fromIdx); Rectangle toBox = screenReader.GetCactpotCircleBox(toIdx); fromBox.Offset(gameWindowRect.Location); toBox.Offset(gameWindowRect.Location); screenReader.ConvertToScaledScreen(ref fromBox); screenReader.ConvertToScaledScreen(ref toBox); fromBox.Inflate(10, 10); toBox.Inflate(10, 10); ShowCactpotLine(fromBox, toBox); } } else { int markerPos = CactpotGame.FindNextCircle(screenReader.currentCactpotGame.board); Logger.WriteLine(" suggested move: [" + markerPos + "]"); bHasValidMarkerBoard = (markerPos >= 0); if (bHasValidMarkerBoard) { Rectangle rectBoardPos = screenReader.GetCactpotCircleBox(markerPos); rectBoardPos.Offset(gameWindowRect.Location); screenReader.ConvertToScaledScreen(ref rectBoardPos); rectBoardPos.Inflate(10, 10); panelMarkerBoard.Bounds = rectBoardPos; panelMarkerBoard.BackColor = Color.Lime; } } for (int Idx = 0; Idx < screenReader.currentCactpotGame.board.Length; Idx++) { int numInCircle = screenReader.currentCactpotGame.board[Idx]; cactpotBoard[Idx].Text = (numInCircle == 0) ? "" : numInCircle.ToString(); } } // update what's needed if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.Modifiers) != TriadGameScreenMemory.EUpdateFlags.None) { string desc = ""; foreach (TriadGameModifier mod in screenMemory.gameSession.modifiers) { desc += mod.ToString() + ", "; } labelRules.Text = "Rules: " + ((desc.Length > 2) ? desc.Remove(desc.Length - 2, 2) : "unknown"); } if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.BlueDeck) != TriadGameScreenMemory.EUpdateFlags.None) { deckCtrlBlue.SetDeck(screenReader.currentTriadGame.blueDeck); } if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.RedDeck) != TriadGameScreenMemory.EUpdateFlags.None) { deckCtrlRed.SetDeck(screenReader.currentTriadGame.redDeck); UpdateRedDeckDetails(screenMemory.deckRed); } if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.Board) != TriadGameScreenMemory.EUpdateFlags.None) { for (int Idx = 0; Idx < screenMemory.gameState.board.Length; Idx++) { boardControls[Idx].SetCard(screenMemory.gameState.board[Idx]); } } if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.SwapWarning) != TriadGameScreenMemory.EUpdateFlags.None) { Rectangle ruleRect = screenReader.GetRuleBoxRect(); if (gameWindowRect.Width > 0 && ruleRect.Width > 0) { Rectangle warningBounds = new Rectangle(ruleRect.Left, ruleRect.Top - panelSwapWarning.Height - 10, 0, 0); warningBounds.Offset(gameWindowRect.Location); screenReader.ConvertToScaledScreen(ref warningBounds); panelSwapWarning.Location = warningBounds.Location; panelSwapWarning.Visible = true; timerHideSwapWarning.Stop(); timerHideSwapWarning.Start(); } } if ((updateFlags & TriadGameScreenMemory.EUpdateFlags.SwapHints) != TriadGameScreenMemory.EUpdateFlags.None) { Rectangle rectDeckPos = screenReader.GetBlueCardRect(screenMemory.swappedBlueCardIdx); rectDeckPos.Offset(gameWindowRect.Location); screenReader.ConvertToScaledScreen(ref rectDeckPos); rectDeckPos.Inflate(-10, -10); panelMarkerSwap.Bounds = rectDeckPos; panelMarkerSwap.Visible = true; } bCanStopTurnScan = false; bCanAutoCapture = false; timerFadeMarkers.Enabled = bHasValidMarkerDeck || bHasValidMarkerBoard || panelMarkerSwap.Visible || panelMarkerLine.Visible; panelMarkerDeck.Visible = bHasValidMarkerDeck; panelMarkerBoard.Visible = bHasValidMarkerBoard; timerTurnScan.Enabled = true; timerTurnScan_Tick(null, null); }
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); } }