From f989169b3a9b6a707be082d689b43f11d588d214 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 25 Oct 2022 01:08:17 -0400 Subject: [PATCH 1/2] Test custom minigame rewards --- .../test_data/test_minigame_reward_chests.dsv | Bin 0 -> 524410 bytes tests/desmume/test_minigame_reward_chests.py | 222 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 tests/desmume/test_data/test_minigame_reward_chests.dsv create mode 100644 tests/desmume/test_minigame_reward_chests.py diff --git a/tests/desmume/test_data/test_minigame_reward_chests.dsv b/tests/desmume/test_data/test_minigame_reward_chests.dsv new file mode 100644 index 0000000000000000000000000000000000000000..5598b7611b2eeff75b0265321df2d423969d4738 GIT binary patch literal 524410 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

M`S~I!J`HBPP~V zG9NZ6Lmkr*$I8N(VK0NJqHrmA*~jExf{bb36lGsh%htfdiY3l@R^L=|Z_{#@2@0at zpY}R@AOm|HHSgug%U#_z9<5_>^2K4z5Oey)@UhB<$JZl3p-uTweRIxkEsuKqzII?^ z>nbdF_aC^h28<^j?_CZJGfJbE?;I4TueNTOHLV<~hwMnSRn5OLCN#p5Pt=tY0`Drn^opxbLzlzasF`nwyqyUsN@4 zzulrVJ+|nc8Cm9K&y_2a<3IQzP`dnKK{MR=)`V~LM;;x!uu2{hdE17!Jgxi6EqT&l zyGimm9{0sF({}c>IQ8pXrS-LUj4119m<$i!T?5P#prlzhc#g1}E8)`I1(L(F>_hgB;C`Ha`E=lNkslG7^UlA-ONdZ!!idtHyuAwRr*3F zdt`;WUHu{KhacXv=ASwg-D{!>#y6B>Km71g#^Gm*d(AJ#)wr{m?S0q0=^Xu-?a_^L zT&m=)s!*y9?$8e4uG0?ybHakap-G_Mu(T#B4ZIEB60kf&`NMf|qxAA*l*AcU?S(7b zt2%y*zeu(rSQ$S7&eCd!quFw{+gT0ns|8*n*B-UPjmUjoZM zdTChuuB!luO?&=(1(?r71}wYe(S1(X(W~nKJtSG;UIZn1Q#;2}*QZZsfSfn$F(3Bw z^qLG%Sf}~-=0W@fA06PUvl|M6Ez1_)N@BUW(P1yOztJ@h*C>qZXZdPJ3h+0l4ZfLY zllMX#h2*DCGJOZvP3m};McsVdX(>o!5A27uE4nPmPb*ifvp|02oF0EKZ@9p?GyyD= zq8wJ|CVGXb+KUu_?`90SU+v`k$Ib)AT)+O`S<#|EKp-Fx5C{ka1OftqYXyOm<`(`x z+%q5|BE@TjF2&O~!aMNl{(ma}TEksP@KKS2)pZO48NaL+neC1TKPfGa%OHU~V%=cmnxK0@50~`Csb^_-@v+?*BTNr9bR;(D?!<-T))Y**AEg{DMP2;kV;6dH5ar(1Ez;tX~(*pl`;lr5QU>9BB$75G#eZC=Sx+<99TM7joVV5~}2*7&NV2kKAL7)4&Uw1Nsv$ zx%$Z}h6J|})2WCh_W@+Z&`s60MdLM2+tdwsq4p~0s<9i)Wd?TJ%7wH|dV7Hdk(u3z zwqm;%Sn@G&r6vahoxoPBN2x)=kPFCZ!iDFPFb#%Ol`jLSqIV%R(J}0~mq5R$sQ~Jr zHsqrZfwfjuR6AJw`2w!6Abs^!4=@eARF9JoIePx1z}7pQ#(HSIyj?tWb97U{q`Y=d zr(EpOnV;ajs^di&v}Zp`jd{Il;F(Vs0vpos!&!)m-5-Fv@U{=3{YAA+X|5HqohZLv z<*K{#XPmB1kx?b5Kz<>y5zES9&%9I)@~RymJ79

%&9s`w5zgXzf4WmvoVobn## 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 S>*5;h8w%7B>=@>%TLS<(L)~lu literal 0 HcmV?d00001 diff --git a/tests/desmume/test_minigame_reward_chests.py b/tests/desmume/test_minigame_reward_chests.py new file mode 100644 index 00000000..774d29dc --- /dev/null +++ b/tests/desmume/test_minigame_reward_chests.py @@ -0,0 +1,222 @@ +from pathlib import Path + +from desmume.emulator import SCREEN_HEIGHT, SCREEN_WIDTH +from ndspy.rom import NintendoDSRom +import pytesseract +import pytest + +from ph_rando.common import ShufflerAuxData +from ph_rando.patcher._items import ITEMS_REVERSED +from ph_rando.patcher._util import GD_MODELS, _patch_minigame_items +from ph_rando.shuffler.aux_models import Item, MinigameRewardChest +from tests.desmume.conftest import GOT_ITEM_TEXT, ITEM_MEMORY_OFFSETS +from tests.desmume.emulator_utils import assert_item_is_picked_up + +from .emulator_utils import AbstractEmulatorWrapper, start_first_file +from .melonds import MelonDSWrapper + + +@pytest.fixture +def minigame_reward_chest_emu( + rom_path: Path, + emulator: AbstractEmulatorWrapper, + request, + aux_data: ShufflerAuxData, +): + if isinstance(emulator, MelonDSWrapper): + pytest.skip('MelonDS not supported for this test yet') + + rom = NintendoDSRom.fromFile(rom_path) + chests = [ + chest + for area in aux_data.areas + for room in area.rooms + for chest in room.chests + if type(chest) is MinigameRewardChest + ] + for chest in chests: + chest.contents = Item(name=ITEMS_REVERSED[request.param], states=set()) + + _patch_minigame_items(aux_data.areas, rom) + + rom.saveToFile(rom_path) + + emulator.open(str(rom_path)) + + return emulator + + +@pytest.mark.parametrize( + 'minigame_reward_chest_emu', + [val for val in ITEM_MEMORY_OFFSETS.keys()], + ids=[f'{hex(val)}-{GD_MODELS[val]}' for val in ITEM_MEMORY_OFFSETS.keys()], + indirect=['minigame_reward_chest_emu'], +) +def test_minigame_reward_chests(minigame_reward_chest_emu: AbstractEmulatorWrapper, request): + item_id: int = request.node.callspec.params['minigame_reward_chest_emu'] + + start_first_file(minigame_reward_chest_emu) + + # Skip "arriving in port" cutscene + minigame_reward_chest_emu.touch_set_and_release((SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2), 1) + + # Walk left from boat + minigame_reward_chest_emu.touch_set_and_release((0, SCREEN_HEIGHT // 2), 160) + + # Walk up + minigame_reward_chest_emu.touch_set_and_release((SCREEN_WIDTH // 2, 0), 50) + + # Walk to goron + minigame_reward_chest_emu.touch_set_and_release((0, SCREEN_HEIGHT // 2), 150) # left + minigame_reward_chest_emu.touch_set_and_release((0, SCREEN_HEIGHT), 20) # left and down + minigame_reward_chest_emu.touch_set_and_release((0, SCREEN_HEIGHT // 2), 20) # left + minigame_reward_chest_emu.touch_set_and_release((SCREEN_WIDTH // 2, 0), 5) # up + minigame_reward_chest_emu.wait(20) + + # Talk to goron + minigame_reward_chest_emu.touch_set_and_release((165, 65), 5) # touch goron + minigame_reward_chest_emu.wait(165) + minigame_reward_chest_emu.touch_set_and_release( + (SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5 + ) # advance dialog + minigame_reward_chest_emu.wait(130) + minigame_reward_chest_emu.touch_set_and_release((206, 90), 5) # click "Yes" to play game + + # advance dialog + for _ in range(6): + minigame_reward_chest_emu.wait(150) + minigame_reward_chest_emu.touch_set_and_release((SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5) + + minigame_reward_chest_emu.wait(20) + minigame_reward_chest_emu.touch_set_and_release((206, 90), 5) # click "Yes" to play game + + # advance dialog + for _ in range(11): + minigame_reward_chest_emu.wait(150) + minigame_reward_chest_emu.touch_set_and_release((SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5) + + minigame_reward_chest_emu.wait(300) + + # Start rolling + for x in range(40): + minigame_reward_chest_emu.touch_set((SCREEN_WIDTH // 2) - x * 2, SCREEN_HEIGHT // 2) + minigame_reward_chest_emu.wait(1) + + minigame_reward_chest_emu.wait(115) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(80) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(30) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(20) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(60) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(30) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(35) + + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(30) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(10) + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(50) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(80) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(190) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(20) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(70) + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(70) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(80) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(55) + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + + minigame_reward_chest_emu.wait(23) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2 + 10) # Right + minigame_reward_chest_emu.wait(45) + + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(35) + + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(50) + + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(60) + minigame_reward_chest_emu.touch_release() + + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(100) + + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + + # # Wait for door to open + minigame_reward_chest_emu.wait(260) + + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(50) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, SCREEN_HEIGHT) # Down + minigame_reward_chest_emu.wait(50) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH, SCREEN_HEIGHT // 2) # Right + minigame_reward_chest_emu.wait(60) + minigame_reward_chest_emu.touch_set(SCREEN_WIDTH // 2, 0) # Up + minigame_reward_chest_emu.wait(40) + minigame_reward_chest_emu.touch_set(0, SCREEN_HEIGHT // 2) # Left + minigame_reward_chest_emu.wait(200) + minigame_reward_chest_emu.touch_release() # End of race + + minigame_reward_chest_emu.wait(80) + minigame_reward_chest_emu.touch_set_and_release( + (SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5 + ) # advance dialog + + minigame_reward_chest_emu.wait(200) + minigame_reward_chest_emu.touch_set_and_release( + (SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5 + ) # advance dialog + minigame_reward_chest_emu.wait(150) + minigame_reward_chest_emu.touch_set_and_release( + (SCREEN_HEIGHT, SCREEN_WIDTH // 2), 5 + ) # advance dialog + minigame_reward_chest_emu.wait(50) + + minigame_reward_chest_emu.touch_set_and_release((SCREEN_WIDTH // 2, SCREEN_HEIGHT), 15) # Down + minigame_reward_chest_emu.touch_set_and_release((SCREEN_WIDTH, SCREEN_HEIGHT // 2), 30) # Right + + with assert_item_is_picked_up(item_id, minigame_reward_chest_emu): + minigame_reward_chest_emu.wait(10) + minigame_reward_chest_emu.touch_set_and_release((107, 67), 2) # Open chest + + # Wait for "Got item" text + minigame_reward_chest_emu.wait(800) + + # Check if the "got item" text is correct + if hasattr(minigame_reward_chest_emu, 'screenshot') and item_id in GOT_ITEM_TEXT: + ocr_text: str = pytesseract.image_to_string( + minigame_reward_chest_emu.screenshot().crop((24, 325, 231, 384)) + ).replace('\u2019', "'") + assert GOT_ITEM_TEXT[item_id] in ocr_text + + minigame_reward_chest_emu.touch_set_and_release((0, 0), 2) + minigame_reward_chest_emu.wait(200) + minigame_reward_chest_emu.touch_set_and_release((0, 0), 2) + minigame_reward_chest_emu.wait(100) + minigame_reward_chest_emu.touch_set_and_release((0, 0), 2) + minigame_reward_chest_emu.wait(100) From 10b02db0f09f751e9cd15278edc38e2b58ed7c88 Mon Sep 17 00:00:00 2001 From: mike8699 Date: Sun, 5 Jan 2025 14:25:17 -0500 Subject: [PATCH 2/2] RF test OCR code into helper function --- tests/desmume/emulator_utils.py | 28 ++++++++++++++++++++ tests/desmume/melonds.py | 3 +++ tests/desmume/test_chest_items.py | 15 ++++++----- tests/desmume/test_minigame_reward_chests.py | 10 +++---- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/tests/desmume/emulator_utils.py b/tests/desmume/emulator_utils.py index 13b8dcb9..3dcbeee2 100644 --- a/tests/desmume/emulator_utils.py +++ b/tests/desmume/emulator_utils.py @@ -1,14 +1,18 @@ from abc import ABC, abstractmethod from collections.abc import Callable, Generator from contextlib import contextmanager +import logging from pathlib import Path import struct from desmume.emulator import SCREEN_HEIGHT, SCREEN_WIDTH +import pytesseract from ph_rando.patcher._items import ITEMS from ph_rando.shuffler.aux_models import Area +logger = logging.getLogger(__name__) + class AbstractEmulatorWrapper(ABC): video = None @@ -109,6 +113,10 @@ def reset(self): def load_battery_file(self, test_name: str, rom_path: Path): raise NotImplementedError + @abstractmethod + def screenshot(self): + raise NotImplementedError + @property def event_flag_base_addr(self) -> int: addr = int.from_bytes(self.read_memory(start=0x27E0F74, stop=0x27E0F78), 'little') @@ -282,3 +290,23 @@ def cancel_spawn(addr: int, size: int): # Clear callback on context manager exit emu_instance.set_exec_breakpoint(0x20C3FE8, None) + + +def assert_text_displayed(emu_instance: AbstractEmulatorWrapper, text: str) -> None: + """ + Asserts that the given text is displayed on the screen. + """ + from .desmume import DeSmuMEWrapper + + if not isinstance(emu_instance, DeSmuMEWrapper): + logger.warning('Text assertion only supported for DeSmuME emulator.') + return + + screenshot = emu_instance.screenshot() + + # Check if the text is correct + ocr_text: str = pytesseract.image_to_string(screenshot.crop((24, 325, 231, 384))).replace( + '\u2019', "'" + ) + + assert text in ocr_text diff --git a/tests/desmume/melonds.py b/tests/desmume/melonds.py index fb633bdf..6c914fb9 100644 --- a/tests/desmume/melonds.py +++ b/tests/desmume/melonds.py @@ -291,3 +291,6 @@ def reset(self): def stop(self): logger.debug('Stopping MelonDS') self.destroy() + + def screenshot(self): + pytest.skip('MelonDSWrapper does not support screenshots') diff --git a/tests/desmume/test_chest_items.py b/tests/desmume/test_chest_items.py index 478677cc..4051bb55 100644 --- a/tests/desmume/test_chest_items.py +++ b/tests/desmume/test_chest_items.py @@ -2,7 +2,6 @@ from desmume.emulator import SCREEN_WIDTH from ndspy.rom import NintendoDSRom -import pytesseract import pytest from ph_rando.common import ShufflerAuxData @@ -11,7 +10,12 @@ from ph_rando.shuffler.aux_models import Chest, Item from .conftest import GOT_ITEM_TEXT, ITEM_MEMORY_OFFSETS -from .emulator_utils import AbstractEmulatorWrapper, assert_item_is_picked_up, start_first_file +from .emulator_utils import ( + AbstractEmulatorWrapper, + assert_item_is_picked_up, + assert_text_displayed, + start_first_file, +) from .melonds import MelonDSWrapper @@ -71,11 +75,8 @@ def test_custom_chest_items( chest_test_emu.wait(800) # Check if the "got item" text is correct - if hasattr(chest_test_emu, 'screenshot') and item_id in GOT_ITEM_TEXT: - ocr_text: str = pytesseract.image_to_string( - chest_test_emu.screenshot().crop((24, 325, 231, 384)) - ).replace('\u2019', "'") - assert GOT_ITEM_TEXT[item_id] in ocr_text + if item_id in GOT_ITEM_TEXT: + assert_text_displayed(chest_test_emu, GOT_ITEM_TEXT[item_id]) chest_test_emu.touch_set_and_release((0, 0), 2) chest_test_emu.wait(200) diff --git a/tests/desmume/test_minigame_reward_chests.py b/tests/desmume/test_minigame_reward_chests.py index 774d29dc..53b8fb37 100644 --- a/tests/desmume/test_minigame_reward_chests.py +++ b/tests/desmume/test_minigame_reward_chests.py @@ -2,7 +2,6 @@ from desmume.emulator import SCREEN_HEIGHT, SCREEN_WIDTH from ndspy.rom import NintendoDSRom -import pytesseract import pytest from ph_rando.common import ShufflerAuxData @@ -12,7 +11,7 @@ from tests.desmume.conftest import GOT_ITEM_TEXT, ITEM_MEMORY_OFFSETS from tests.desmume.emulator_utils import assert_item_is_picked_up -from .emulator_utils import AbstractEmulatorWrapper, start_first_file +from .emulator_utils import AbstractEmulatorWrapper, assert_text_displayed, start_first_file from .melonds import MelonDSWrapper @@ -208,11 +207,8 @@ def test_minigame_reward_chests(minigame_reward_chest_emu: AbstractEmulatorWrapp minigame_reward_chest_emu.wait(800) # Check if the "got item" text is correct - if hasattr(minigame_reward_chest_emu, 'screenshot') and item_id in GOT_ITEM_TEXT: - ocr_text: str = pytesseract.image_to_string( - minigame_reward_chest_emu.screenshot().crop((24, 325, 231, 384)) - ).replace('\u2019', "'") - assert GOT_ITEM_TEXT[item_id] in ocr_text + if item_id in GOT_ITEM_TEXT: + assert_text_displayed(minigame_reward_chest_emu, GOT_ITEM_TEXT[item_id]) minigame_reward_chest_emu.touch_set_and_release((0, 0), 2) minigame_reward_chest_emu.wait(200)