Upd: use combination instead of inheritance in RogueSelector

This commit is contained in:
Hengyu 2023-08-15 03:35:15 +08:00
parent 03caaa2855
commit 5a06402d43
9 changed files with 152 additions and 135 deletions

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,25 @@
from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ```
BONUS_BOTTOM_WHITE_BAR = ButtonWrapper(
name='BONUS_BOTTOM_WHITE_BAR',
share=Button(
file='./assets/share/rogue/bonus/BONUS_BOTTOM_WHITE_BAR.png',
area=(182, 568, 1098, 590),
search=(162, 548, 1118, 610),
color=(221, 221, 222),
button=(182, 568, 1098, 590),
),
)
BONUS_CONFIRM = ButtonWrapper(
name='BONUS_CONFIRM',
share=Button(
file='./assets/share/rogue/bonus/BONUS_CONFIRM.png',
area=(504, 629, 620, 677),
search=(484, 609, 640, 697),
color=(222, 224, 224),
button=(504, 629, 620, 677),
),
)

View File

@ -3,26 +3,6 @@ from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ```
BONUS_BOTTOM_WHITE_BAR = ButtonWrapper(
name='BONUS_BOTTOM_WHITE_BAR',
share=Button(
file='./assets/share/rogue/ui/BONUS_BOTTOM_WHITE_BAR.png',
area=(182, 568, 1098, 590),
search=(162, 548, 1118, 610),
color=(221, 221, 222),
button=(182, 568, 1098, 590),
),
)
BONUS_CONFIRM = ButtonWrapper(
name='BONUS_CONFIRM',
share=Button(
file='./assets/share/rogue/ui/BONUS_CONFIRM.png',
area=(504, 629, 620, 677),
search=(484, 609, 640, 697),
color=(222, 224, 224),
button=(504, 629, 620, 677),
),
)
CHECK_BLESSING = ButtonWrapper(
name='CHECK_BLESSING',
share=Button(

View File

@ -12,7 +12,6 @@ from tasks.rogue.assets.assets_rogue_ui import CONFIRM
from tasks.rogue.keywords import *
from tasks.rogue.preset import *
from tasks.rogue.selector import RogueSelector
from tasks.rogue.ui import RogueUI
from tasks.rogue.utils import get_regex_from_keyword_name, parse_name, is_card_selected
# normal blessing
@ -78,7 +77,7 @@ class RogueBuffOcr(Ocr):
return result
class RogueBlessingSelector(RogueUI, RogueSelector):
class RogueBlessingSelector(RogueSelector):
"""
Usage:
self = RogueBlessingSelector('alas')
@ -90,9 +89,9 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
"""
Returns: The number of blessing
"""
if not self.image_color_count(BOTTOM_WHITE_BAR.area, color=(255, 255, 255), count=5000):
if not self.main.image_color_count(BOTTOM_WHITE_BAR.area, color=(255, 255, 255), count=5000):
return 0
color = get_color(self.device.image, BOTTOM_WHITE_BAR.area)
color = get_color(self.main.device.image, BOTTOM_WHITE_BAR.area)
mean = np.mean(color)
return int(mean // 60) # the magic number that maps blessing num with mean_color
@ -100,7 +99,7 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
self.ocr_results = []
self._wait_until_blessing_loaded()
ocr = RogueBuffOcr(OCR_ROGUE_BUFF)
results = ocr.matched_ocr(self.device.image, [RogueBlessing, RogueResonance])
results = ocr.matched_ocr(self.main.device.image, [RogueBlessing, RogueResonance])
blessing_count = self.get_blessing_count()
if blessing_count != len(results):
logger.warning(f"The OCR result does not match the blessing count. "
@ -121,8 +120,9 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
Case 2: choose curio
Case 3: another choose blessings, but no blessing is selected when the new selection page loaded
"""
return (self.is_in_main() or self.is_page_choose_curio()
or (self.is_page_choose_blessing() and not is_card_selected(self, target, confirm_button=CONFIRM)))
return (self.main.is_in_main() or self.main.is_page_choose_curio()
or (self.main.is_page_choose_blessing() and
not is_card_selected(self.main, target, confirm_button=CONFIRM)))
interval = Timer(1)
enforce = False
@ -135,9 +135,9 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.main.device.screenshot()
if is_card_selected(self, target, confirm_button=CONFIRM):
if is_card_selected(self.main, target, confirm_button=CONFIRM):
if enforce:
logger.info("Buff selected (enforce)")
else:
@ -145,9 +145,9 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
break
if interval.reached():
if enforce:
self.device.click(BLESSING_ENFORCE)
self.main.device.click(BLESSING_ENFORCE)
else:
self.device.click(target)
self.main.device.click(target)
interval.reset()
skip_first_screenshot = True
@ -156,16 +156,16 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.main.device.screenshot()
if is_select_blessing_complete():
break
if interval.reached():
self.device.click(CONFIRM)
self.main.device.click(CONFIRM)
interval.reset()
def _get_reset_count(self):
current, _, _ = DigitCounter(OCR_RESET_COUNT).ocr_single_line(self.device.image)
current, _, _ = DigitCounter(OCR_RESET_COUNT).ocr_single_line(self.main.device.image)
return current
def _wait_until_blessing_loaded(self, timer=Timer(0.3, count=1), timeout=Timer(5, count=10)):
@ -173,7 +173,7 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
timeout.reset()
previous_count = self.get_blessing_count()
while 1:
self.device.screenshot()
self.main.device.screenshot()
blessing_count = self.get_blessing_count()
if timeout.reached():
@ -189,7 +189,7 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
timer.reset()
def reset_blessing_list(self, skip_first_screenshot=True):
if not self.is_page_choose_blessing():
if not self.main.is_page_choose_blessing():
return False
reset_count = self._get_reset_count()
@ -197,8 +197,8 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
logger.info("Does not have enough reset count")
return False
reset_cost = Digit(OCR_RESET_COST).ocr_single_line(self.device.image)
if reset_cost > self.cosmic_fragment:
reset_cost = Digit(OCR_RESET_COST).ocr_single_line(self.main.device.image)
if reset_cost > self.main.cosmic_fragment:
logger.info("Does not have enough cosmic fragment")
return False
@ -207,7 +207,7 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.main.device.screenshot()
new_count = self._get_reset_count()
@ -215,7 +215,7 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
logger.info("Reset once")
break
if interval.reached():
self.device.click(BLESSING_RESET)
self.main.device.click(BLESSING_RESET)
interval.reset()
return True
@ -224,16 +224,16 @@ class RogueBlessingSelector(RogueUI, RogueSelector):
keyword = self.ocr_results[0].matched_keyword
if isinstance(keyword, RogueBlessing):
filter_ = BLESSING_FILTER
if self.config.Rogue_PresetBlessingFilter == 'preset-1':
if self.main.config.Rogue_PresetBlessingFilter == 'preset-1':
filter_.load(parse_name(BLESSING_PRESET_1))
if self.config.Rogue_PresetBlessingFilter == 'custom':
filter_.load(parse_name(self.config.Rogue_CustomBlessingFilter))
if self.main.config.Rogue_PresetBlessingFilter == 'custom':
filter_.load(parse_name(self.main.config.Rogue_CustomBlessingFilter))
if isinstance(keyword, RogueResonance):
filter_ = RESONANCE_FILTER
if self.config.Rogue_PresetResonanceFilter == 'preset-1':
if self.main.config.Rogue_PresetResonanceFilter == 'preset-1':
RESONANCE_FILTER.load(parse_name(RESONANCE_PRESET_1))
if self.config.Rogue_PresetResonanceFilter == 'custom':
RESONANCE_FILTER.load(parse_name(self.config.Rogue_CustomResonanceFilter))
if self.main.config.Rogue_PresetResonanceFilter == 'custom':
RESONANCE_FILTER.load(parse_name(self.main.config.Rogue_CustomResonanceFilter))
self.filter_ = filter_
def try_select(self, option: OcrResultButton | str):

83
tasks/rogue/bonus.py Normal file
View File

@ -0,0 +1,83 @@
import numpy as np
from module.base.timer import Timer
from module.logger import logger
from module.ocr.ocr import OcrResultButton
from tasks.rogue.assets.assets_rogue_blessing import OCR_ROGUE_BUFF
from tasks.rogue.assets.assets_rogue_bonus import BONUS_BOTTOM_WHITE_BAR, BONUS_CONFIRM
from tasks.rogue.keywords import RogueBonus
from tasks.rogue.selector import RogueSelector
from tasks.rogue.ui import RogueBonusOcr
from tasks.rogue.utils import is_card_selected
class RogueBonusSelector(RogueSelector):
def _wait_bonus_page_loaded(self, timer=Timer(0.3, count=1), timeout=Timer(5, count=10)):
timer.reset()
timeout.reset()
while 1:
self.main.device.screenshot()
if timeout.reached():
logger.warning('Wait bonus page loaded timeout')
break
if self.main.appear(BONUS_BOTTOM_WHITE_BAR):
if timer.reached():
logger.info('Bonus page stabled')
break
else:
timer.reset()
def recognition(self):
self._wait_bonus_page_loaded()
ocr = RogueBonusOcr(OCR_ROGUE_BUFF)
results = ocr.matched_ocr(self.main.device.image, [RogueBonus])
expected_count = 3
if expected_count != len(results):
logger.warning(f"The OCR result does not match the bonus count. "
f"Expect {expected_count}, but recognized {len(results)} only.")
self.ocr_results = results
return results
def ui_select(self, target: OcrResultButton | None, skip_first_screenshot=True):
interval = Timer(1)
# start -> select
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.main.device.screenshot()
if is_card_selected(self.main, target, confirm_button=BONUS_CONFIRM):
break
if interval.reached():
self.main.device.click(target)
interval.reset()
skip_first_screenshot = True
# select -> confirm
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.main.device.screenshot()
if self.main.is_in_main() or self.main.is_page_choose_curio() or self.main.is_page_choose_blessing():
break
if interval.reached():
self.main.device.click(BONUS_CONFIRM)
interval.reset()
def recognize_and_select(self):
self.recognition()
if not self.ocr_results:
self.ui_select(None)
options = {result.matched_keyword.en: result for result in self.ocr_results}
if self.main.config.Rogue_Bonus not in options.keys():
logger.warning(f"Can not find option: {self.main.config.Rogue_Bonus}, randomly choose one")
target = np.random.choice(options)
else:
target = options[self.main.config.Rogue_Bonus]
logger.info(f"Choose bonus: {target}")
self.ui_select(target)

View File

@ -12,7 +12,6 @@ from tasks.rogue.assets.assets_rogue_ui import CONFIRM
from tasks.rogue.keywords import RogueCurio
from tasks.rogue.preset import CURIO_PRESET_1
from tasks.rogue.selector import RogueSelector
from tasks.rogue.ui import RogueUI
from tasks.rogue.utils import get_regex_from_keyword_name, parse_name
CURIO_FILTER_ATTR = tuple()
@ -36,11 +35,11 @@ class RogueCurioOcr(Ocr):
return result
class RogueCurioSelector(RogueUI, RogueSelector):
class RogueCurioSelector(RogueSelector):
def recognition(self):
self.ocr_results = []
ocr = RogueCurioOcr(OCR_ROGUE_CURIO)
results = ocr.matched_ocr(self.device.image, RogueCurio)
results = ocr.matched_ocr(self.main.device.image, RogueCurio)
expect_num = 3
if len(results) != expect_num:
logger.warning(f"The OCR result does not match the curio count. "
@ -50,13 +49,13 @@ class RogueCurioSelector(RogueUI, RogueSelector):
def ui_select(self, target: OcrResultButton | None, skip_first_screenshot=True):
def is_curio_selected():
return np.mean(get_color(self.device.image, tuple(target.area))) > 70 # shiny background
return np.mean(get_color(self.main.device.image, tuple(target.area))) > 70 # shiny background
def is_select_curio_complete():
"""
Case 1: back to main page
"""
return self.is_in_main()
return self.main.is_in_main()
enforce = False
if not target:
@ -67,7 +66,7 @@ class RogueCurioSelector(RogueUI, RogueSelector):
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.main.device.screenshot()
if is_curio_selected():
if enforce:
@ -77,9 +76,9 @@ class RogueCurioSelector(RogueUI, RogueSelector):
break
if interval.reached():
if enforce:
self.device.click(CURIO_ENFORCE)
self.main.device.click(CURIO_ENFORCE)
else:
self.device.click(target)
self.main.device.click(target)
interval.reset()
skip_first_screenshot = True
@ -88,12 +87,12 @@ class RogueCurioSelector(RogueUI, RogueSelector):
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.main.device.screenshot()
if is_select_curio_complete():
break
if interval.reached():
self.device.click(CONFIRM)
self.main.device.click(CONFIRM)
interval.reset()
def try_select(self, option: OcrResultButton | str):
@ -108,8 +107,8 @@ class RogueCurioSelector(RogueUI, RogueSelector):
def load_filter(self):
filter_ = CURIO_FILTER
if self.config.Rogue_PresetCurioFilter == 'preset-1':
if self.main.config.Rogue_PresetCurioFilter == 'preset-1':
filter_.load(parse_name(CURIO_PRESET_1))
if self.config.Rogue_PresetCurioFilter == 'custom':
filter_.load(parse_name(self.config.Rogue_CustomCurioFilter))
if self.main.config.Rogue_PresetCurioFilter == 'custom':
filter_.load(parse_name(self.main.config.Rogue_CustomCurioFilter))
self.filter_ = filter_

View File

@ -4,12 +4,17 @@ from module.base.filter import MultiLangFilter
from module.logger import logger
from module.ocr.keyword import Keyword
from module.ocr.ocr import OcrResultButton
from tasks.rogue.ui import RogueUI
class RogueSelector:
"""
An Interface used in blessing, curio, and other ui selection in rogue
"""
def __init__(self, main: RogueUI):
self.main = main
ocr_results: list[OcrResultButton]
filter_: MultiLangFilter
preset_methods: dict[str, callable]

View File

@ -1,15 +1,9 @@
import re
import numpy as np
from module.base.timer import Timer
from module.logger import logger
from module.ocr.ocr import Digit, Ocr, OcrResultButton
from module.ocr.ocr import Digit, Ocr
from tasks.base.ui import UI
from tasks.rogue.assets.assets_rogue_blessing import OCR_ROGUE_BUFF
from tasks.rogue.assets.assets_rogue_ui import *
from tasks.rogue.keywords import *
from tasks.rogue.utils import is_card_selected
class RogueBonusOcr(Ocr):
@ -43,72 +37,3 @@ class RogueUI(UI):
def is_page_choose_bonus(self):
return self.appear(PAGE_CHOOSE_BONUS)
def _wait_bonus_page_loaded(self, timer=Timer(0.3, count=1), timeout=Timer(5, count=10)):
timer.reset()
timeout.reset()
while 1:
self.device.screenshot()
if timeout.reached():
logger.warning('Wait bonus page loaded timeout')
break
if self.appear(BONUS_BOTTOM_WHITE_BAR):
if timer.reached():
logger.info('Bonus page stabled')
break
else:
timer.reset()
def bonus_recognition(self):
self._wait_bonus_page_loaded()
ocr = RogueBonusOcr(OCR_ROGUE_BUFF)
results = ocr.matched_ocr(self.device.image, [RogueBonus])
expected_count = 3
if expected_count != len(results):
logger.warning(f"The OCR result does not match the bonus count. "
f"Expect {expected_count}, but recognized {len(results)} only.")
return results
def ui_choose_bonus(self, target: OcrResultButton | None, skip_first_screenshot=True):
interval = Timer(1)
# start -> select
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if is_card_selected(self, target, confirm_button=BONUS_CONFIRM):
break
if interval.reached():
self.device.click(target)
interval.reset()
skip_first_screenshot = True
# select -> confirm
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.is_in_main() or self.is_page_choose_curio() or self.is_page_choose_blessing():
break
if interval.reached():
self.device.click(BONUS_CONFIRM)
interval.reset()
def recognize_and_select_bonus(self):
results = self.bonus_recognition()
if not results:
self.ui_choose_bonus(None)
options = {result.matched_keyword.en: result for result in results}
if self.config.Rogue_Bonus not in options.keys():
logger.warning(f"Can not find option: {self.config.Rogue_Bonus}, randomly choose one")
target = np.random.choice(options)
else:
target = options[self.config.Rogue_Bonus]
logger.info(f"Choose bonus: {target}")
self.ui_choose_bonus(target)