Merge pull request #4103 from LmeSzinc/dev

Bug fix
This commit is contained in:
LmeSzinc 2024-08-20 02:34:45 +08:00 committed by GitHub
commit aa8d990fc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 112 additions and 50 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -12,7 +12,7 @@ class Config:
# Disabled because having errors
MAP_SWIPE_PREDICT_WITH_SEA_GRIDS = False
# Ambushes can be avoid by having more DDs.
MAP_WALK_OPTIMIZE = False
MAP_WALK_TURNING_OPTIMIZE = False
class CampaignBase(CampaignBase_):

View File

@ -13,7 +13,7 @@ MASK_MAP_UI_W15 = Mask(file='./assets/mask/MASK_MAP_UI_W15.png')
class Config:
# Ambushes can be avoid by having more DDs.
MAP_WALK_OPTIMIZE = False
MAP_WALK_TURNING_OPTIMIZE = False
MAP_HAS_MYSTERY = False
MAP_ENEMY_TEMPLATE = ['Light', 'Main', 'Carrier', 'CarrierSpecial']
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {

View File

@ -81,6 +81,7 @@ class Config:
}
HOMO_EDGE_COLOR_RANGE = (0, 33)
HOMO_EDGE_HOUGHLINES_THRESHOLD = 300
MAP_ENSURE_EDGE_INSIGHT_CORNER = 'bottom'
MAP_IS_ONE_TIME_STAGE = True
MAP_SWIPE_MULTIPLY = (1.063, 1.083)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.028, 1.047)

View File

@ -331,28 +331,33 @@ class CampaignOcr(ModuleBase):
logger.warning(f'get_chapter_index: WITHDRAW appears')
raise CampaignNameError
def get_chapter_index(self, image):
def get_chapter_index(self, skip_first_screenshot=True):
"""
A tricky method for ui_ensure_index
Args:
image: Screenshot
skip_first_screenshot:
Returns:
int: Chapter index.
"""
timeout = Timer(2, count=4).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if timeout.reached():
raise CampaignNameError
if self.handle_get_chapter_additional():
continue
image = self.device.image
try:
self._get_stage_name(image)
break
except (IndexError, CampaignNameError):
self.device.screenshot()
image = self.device.image
pass
if self.handle_get_chapter_additional():
continue
return self._campaign_get_chapter_index(self.campaign_chapter)

View File

@ -49,7 +49,7 @@ class CampaignUI(MapOperation, CampaignEvent, CampaignOcr):
if self.handle_chapter_additional():
continue
current = self.get_chapter_index(self.device.image)
current = self.get_chapter_index()
logger.attr("Index", current)
diff = index - current
@ -227,19 +227,35 @@ class CampaignUI(MapOperation, CampaignEvent, CampaignOcr):
return True
return False
def ensure_campaign_ui(self, name, mode='normal'):
for n in range(20):
def ensure_campaign_ui(self, name, mode='normal', skip_first_screenshot=True):
"""
Args:
name (str): Campaign name, such as '7-2', 'd3', 'sp3'.
mode (str): 'normal' or 'hard'.
skip_first_screenshot:
Raises:
ScriptEnd: If failed to switch after retries
"""
timeout = Timer(5, count=20).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if timeout.reached():
break
try:
self.campaign_set_chapter(name, mode)
self.ENTRANCE = self.campaign_get_entrance(name=name)
return True
except CampaignNameError:
pass
if self.handle_campaign_ui_additional():
continue
self.device.screenshot()
logger.warning('Campaign name error')
raise ScriptEnd('Campaign name error')

View File

@ -182,7 +182,7 @@ class ManualConfig:
# Use the green arrow on current fleet to decide if fleet arrived a certain grid
MAP_WALK_USE_CURRENT_FLEET = False
# Optimize walk path, reducing ambushes
MAP_WALK_OPTIMIZE = True
MAP_WALK_TURNING_OPTIMIZE = True
# Optimize swipe path, reducing swipes turn info clicks.
MAP_SWIPE_OPTIMIZE = True
# Swipe after boss appear. Could avoid map detection error when camera is on edge.

View File

@ -299,10 +299,18 @@ class Emulator(EmulatorBase):
for folder in self.list_folder('../vms', is_dir=True):
for file in iter_folder(folder, ext='.nemu'):
serial = Emulator.vbox_file_to_serial(file)
name = os.path.basename(folder)
if serial:
yield EmulatorInstance(
serial=serial,
name=os.path.basename(folder),
name=name,
path=self.path,
)
# Fix for MuMu12 v4.0.4, default instance of which has no forward record in vbox config
elif name == 'MuMuPlayer-12.0-0':
yield EmulatorInstance(
serial='127.0.0.1:16384',
name=name,
path=self.path,
)
elif self == Emulator.MEmuPlayer:

View File

@ -467,23 +467,27 @@ class Fleet(Camera, AmbushHandler):
if result == 'nothing' and expected == 'combat':
raise MapEnemyMoved
def goto(self, location, optimize=None, expected=''):
def goto(self, location, expected='', step_optimize=None, turning_optimize=None):
"""
Args:
location (tuple, str, GridInfo): Destination.
optimize (bool): Optimize walk path, reducing ambushes.
If None, loads MAP_WALK_OPTIMIZE
expected (str): Expected result on destination grid, such as 'combat', 'combat_siren', 'mystery'.
Will give a waring if arrive with unexpected result.
step_optimize (bool): True to walk in fleet step
turning_optimize (bool): True to optimize route to reduce ambushes
"""
location = location_ensure(location)
if optimize is None:
optimize = self.config.MAP_WALK_OPTIMIZE
if step_optimize is None:
step_optimize = self.config.MAP_HAS_FLEET_STEP
if self.config.MAP_HAS_PORTAL or self.config.MAP_HAS_MAZE:
step_optimize = True
if turning_optimize is None:
turning_optimize = self.config.MAP_HAS_AMBUSH
# self.device.sleep(1000)
if optimize and (self.config.MAP_HAS_AMBUSH or self.config.MAP_HAS_FLEET_STEP or self.config.MAP_HAS_PORTAL
or self.config.MAP_HAS_MAZE):
nodes = self.map.find_path(location, step=self.fleet_step)
if step_optimize or turning_optimize:
step = self.fleet_step if step_optimize else 0
nodes = self.map.find_path(location, step=step, turning_optimize=turning_optimize)
for node in nodes:
if self.maze_active_on(node):
logger.info(f'Maze is active on {location2node(node)}, bouncing to wait')
@ -499,7 +503,7 @@ class Fleet(Camera, AmbushHandler):
logger.warning('Map walk error.')
self.predict()
self.ensure_edge_insight()
nodes_ = self.map.find_path(node, step=1)
nodes_ = self.map.find_path(node, step=1, turning_optimize=False)
for node_ in nodes_:
self._goto(node_, expected=expected if node == nodes[-1] else '')
else:

View File

@ -653,8 +653,8 @@ class Map(Fleet):
def clear_filter_enemy(self, string, preserve=0):
"""
if EnemyPriority_EnemyScaleBalanceWeight != default_mode
Filter will be covered
If EnemyPriority_EnemyScaleBalanceWeight != default_mode, enemy filter is ignored
If MAP_HAS_MOVABLE_NORMAL_ENEMY, enemy filter is ignored
Args:
string (str): Filter to select enemies, from easy to hard
@ -664,6 +664,11 @@ class Map(Fleet):
Returns:
bool: If clear an enemy.
"""
if self.config.MAP_HAS_MOVABLE_NORMAL_ENEMY:
if self.clear_any_enemy(sort=('cost_2',)):
return True
return False
if self.config.EnemyPriority_EnemyScaleBalanceWeight == 'S3_enemy_first':
string = '3L > 3M > 3E > 3C > 2L > 2M > 2E > 2C > 1L > 1M > 1E > 1C'
preserve = 0

View File

@ -604,11 +604,12 @@ class CampaignMap:
return res
def _find_route_node(self, route, step=0):
def _find_route_node(self, route, step=0, turning_optimize=False):
"""
Args:
route (list[tuple]): list of grids.
step (int): Fleet step in event map. Default to 0.
turning_optimize: (bool): True to optimize route to reduce ambushes
Returns:
list[tuple]: list of walking node.
@ -617,23 +618,30 @@ class CampaignMap:
MAP_7_2._find_route_node([(2, 2), (3, 2), (4, 2), (5, 2), (6, 2), (6, 1), (7, 1)])
[(6, 2), (7, 1)]
"""
res = []
diff = np.abs(np.diff(route, axis=0))
turning = np.diff(diff, axis=0)[:, 0]
indexes = np.where(turning == -1)[0] + 1
for index in indexes:
if not self[route[index]].is_fleet:
res.append(index)
else:
logger.info(f'Path_node_avoid: {self[route[index]]}')
if (index > 1) and (index - 1 not in indexes):
res.append(index - 1)
if (index < len(route) - 2) and (index + 1 not in indexes):
res.append(index + 1)
res.append(len(route) - 1)
# res = [6, 8]
if step == 0:
return [route[index] for index in res]
if turning_optimize:
res = []
diff = np.abs(np.diff(route, axis=0))
turning = np.diff(diff, axis=0)[:, 0]
indexes = np.where(turning == -1)[0] + 1
for index in indexes:
if not self[route[index]].is_fleet:
res.append(index)
else:
logger.info(f'Path_node_avoid: {self[route[index]]}')
if (index > 1) and (index - 1 not in indexes):
res.append(index - 1)
if (index < len(route) - 2) and (index + 1 not in indexes):
res.append(index + 1)
res.append(len(route) - 1)
# res = [4, 6]
if step == 0:
return [route[index] for index in res]
else:
if step == 0:
return [route[-1]]
# Index of the last node
# res = [6]
res = [max(len(route) - 1, 0)]
res.insert(0, 0)
inserted = []
@ -653,7 +661,7 @@ class CampaignMap:
# res = [3, 6, 8]
return [route[index] for index in res]
def find_path(self, location, step=0):
def find_path(self, location, step=0, turning_optimize=False):
location = location_ensure(location)
path = self._find_path(location)
@ -676,7 +684,7 @@ class CampaignMap:
if end - start == 1 and self[path[start]].is_portal and self[path[start]].portal_link == path[end]:
continue
local_path = path[start:end + 1]
local_path = self._find_route_node(local_path, step=step)
local_path = self._find_route_node(local_path, step=step, turning_optimize=turning_optimize)
portal_path += local_path
logger.info('Path: %s' % '[' + ', ' .join([location2node(grid) for grid in local_path]) + ']')
path = portal_path

View File

@ -105,6 +105,10 @@ class ActionPointHandler(UI, MapEventHandler):
def _is_in_action_point(self):
return self.appear(ACTION_POINT_USE, offset=(20, 20))
def is_current_ap_visible(self):
return self.appear(CURRENT_AP_CHECK, offset=(40, 5)) \
and CURRENT_AP_CHECK.match_appear_on(self.device.image, threshold=15)
def action_point_use(self, skip_first_screenshot=True):
prev = self._action_point_current
self.interval_clear(ACTION_POINT_USE)
@ -144,6 +148,20 @@ class ActionPointHandler(UI, MapEventHandler):
self._action_point_total = total
def action_point_safe_get(self, skip_first_screenshot=True):
timeout = Timer(3, count=6).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.is_current_ap_visible():
break
if timeout.reached():
logger.warning('Get action points timeout, wait is_current_ap_visible timeout')
break
skip_first_screenshot = True
timeout = Timer(1, count=2).start()
while 1:
if skip_first_screenshot:
@ -155,10 +173,6 @@ class ActionPointHandler(UI, MapEventHandler):
logger.warning('Get action points timeout')
break
if self.info_bar_count() >= 2:
timeout.reset()
continue
self.action_point_update()
# Having too many current AP, probably an OCR error

View File

@ -15,6 +15,7 @@ AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED = Button(area={'cn': (1205, 531, 1275, 54
AUTO_SEARCH_OS_MAP_OPTION_ON = Button(area={'cn': (1205, 549, 1275, 566), 'en': (1203, 534, 1274, 544), 'jp': (1205, 573, 1275, 592), 'tw': (1206, 573, 1275, 591)}, color={'cn': (149, 176, 193), 'en': (110, 131, 152), 'jp': (145, 172, 190), 'tw': (123, 148, 169)}, button={'cn': (1205, 549, 1275, 566), 'en': (1203, 534, 1274, 544), 'jp': (1205, 573, 1275, 592), 'tw': (1206, 573, 1275, 591)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'en': './assets/en/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png'})
AUTO_SEARCH_REWARD = Button(area={'cn': (575, 598, 721, 646), 'en': (574, 597, 722, 648), 'jp': (577, 597, 722, 645), 'tw': (576, 598, 720, 647)}, color={'cn': (169, 168, 170), 'en': (168, 171, 174), 'jp': (165, 170, 175), 'tw': (171, 174, 179)}, button={'cn': (575, 598, 721, 646), 'en': (574, 597, 722, 648), 'jp': (577, 597, 722, 645), 'tw': (576, 598, 720, 647)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_REWARD.png', 'en': './assets/en/os_handler/AUTO_SEARCH_REWARD.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_REWARD.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_REWARD.png'})
CLICK_SAFE_AREA = Button(area={'cn': (1104, 169, 1214, 284), 'en': (1104, 169, 1214, 284), 'jp': (1104, 169, 1214, 284), 'tw': (1104, 169, 1214, 284)}, color={'cn': (96, 114, 142), 'en': (96, 114, 142), 'jp': (96, 114, 142), 'tw': (96, 114, 142)}, button={'cn': (1104, 169, 1214, 284), 'en': (1104, 169, 1214, 284), 'jp': (1104, 169, 1214, 284), 'tw': (1104, 169, 1214, 284)}, file={'cn': './assets/cn/os_handler/CLICK_SAFE_AREA.png', 'en': './assets/en/os_handler/CLICK_SAFE_AREA.png', 'jp': './assets/jp/os_handler/CLICK_SAFE_AREA.png', 'tw': './assets/tw/os_handler/CLICK_SAFE_AREA.png'})
CURRENT_AP_CHECK = Button(area={'cn': (837, 228, 867, 252), 'en': (837, 228, 867, 252), 'jp': (837, 228, 867, 252), 'tw': (837, 228, 867, 252)}, color={'cn': (165, 124, 73), 'en': (165, 124, 73), 'jp': (165, 124, 73), 'tw': (165, 124, 73)}, button={'cn': (837, 228, 867, 252), 'en': (837, 228, 867, 252), 'jp': (837, 228, 867, 252), 'tw': (837, 228, 867, 252)}, file={'cn': './assets/cn/os_handler/CURRENT_AP_CHECK.png', 'en': './assets/en/os_handler/CURRENT_AP_CHECK.png', 'jp': './assets/jp/os_handler/CURRENT_AP_CHECK.png', 'tw': './assets/tw/os_handler/CURRENT_AP_CHECK.png'})
EXCHANGE_CHECK = Button(area={'cn': (144, 17, 249, 41), 'en': (143, 16, 240, 37), 'jp': (141, 16, 250, 42), 'tw': (142, 15, 250, 44)}, color={'cn': (153, 170, 209), 'en': (117, 133, 171), 'jp': (86, 98, 127), 'tw': (135, 151, 189)}, button={'cn': (144, 17, 249, 41), 'en': (143, 16, 240, 37), 'jp': (141, 16, 250, 42), 'tw': (142, 15, 250, 44)}, file={'cn': './assets/cn/os_handler/EXCHANGE_CHECK.png', 'en': './assets/en/os_handler/EXCHANGE_CHECK.png', 'jp': './assets/jp/os_handler/EXCHANGE_CHECK.png', 'tw': './assets/tw/os_handler/EXCHANGE_CHECK.png'})
EXCHANGE_ENTER = Button(area={'cn': (195, 629, 344, 693), 'en': (202, 640, 332, 690), 'jp': (195, 629, 345, 693), 'tw': (195, 629, 344, 693)}, color={'cn': (58, 54, 52), 'en': (64, 61, 59), 'jp': (53, 50, 48), 'tw': (59, 55, 54)}, button={'cn': (195, 629, 344, 693), 'en': (202, 640, 332, 690), 'jp': (195, 629, 345, 693), 'tw': (195, 629, 344, 693)}, file={'cn': './assets/cn/os_handler/EXCHANGE_ENTER.png', 'en': './assets/en/os_handler/EXCHANGE_ENTER.png', 'jp': './assets/jp/os_handler/EXCHANGE_ENTER.png', 'tw': './assets/tw/os_handler/EXCHANGE_ENTER.png'})
GET_ADAPTABILITY = Button(area={'cn': (538, 191, 742, 227), 'en': (527, 194, 659, 215), 'jp': (538, 191, 743, 227), 'tw': (539, 191, 741, 227)}, color={'cn': (166, 195, 246), 'en': (198, 207, 230), 'jp': (158, 190, 245), 'tw': (164, 195, 246)}, button={'cn': (538, 191, 742, 227), 'en': (527, 194, 659, 215), 'jp': (538, 191, 743, 227), 'tw': (539, 191, 741, 227)}, file={'cn': './assets/cn/os_handler/GET_ADAPTABILITY.png', 'en': './assets/en/os_handler/GET_ADAPTABILITY.png', 'jp': './assets/jp/os_handler/GET_ADAPTABILITY.png', 'tw': './assets/tw/os_handler/GET_ADAPTABILITY.png'})