mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-08 13:07:33 +08:00
Fix: Map swipe optimize should use local map view to generate blacklist
- Opt: Take less screenshots during swipe, reuse local view object as possible - Refactor: handle_boss_appear_refocus() - Fix: Update swipe box area in map, avoid clicking auto search
This commit is contained in:
parent
153c9fb491
commit
7a0c566a9e
@ -85,10 +85,6 @@ class Campaign(CampaignBase):
|
||||
return True
|
||||
|
||||
return self.fleet_2.clear_boss()
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
for data in self.map.spawn_data:
|
||||
if data.get('battle') == self.battle_count and data.get('boss', 0):
|
||||
self.map_swipe((-3, -2))
|
||||
|
||||
return super().handle_boss_appear_refocus()
|
||||
def handle_boss_appear_refocus(self, preset=(-3, -2)):
|
||||
return super().handle_boss_appear_refocus(preset)
|
||||
|
@ -45,8 +45,5 @@ class Campaign(CampaignBase):
|
||||
def battle_1(self):
|
||||
return self.clear_boss()
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
for data in self.map.spawn_data:
|
||||
if data.get('battle') == self.battle_count and data.get('boss', 0):
|
||||
self.map_swipe((-3, 0))
|
||||
return super().handle_boss_appear_refocus()
|
||||
def handle_boss_appear_refocus(self, preset=(-3, 0)):
|
||||
return super().handle_boss_appear_refocus(preset)
|
||||
|
@ -68,8 +68,5 @@ class Campaign(CampaignBase):
|
||||
|
||||
return self.fleet_boss.clear_boss()
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
for data in self.map.spawn_data:
|
||||
if data.get('battle') == self.battle_count and data.get('boss', 0):
|
||||
self.map_swipe((0, -2))
|
||||
return super().handle_boss_appear_refocus()
|
||||
def handle_boss_appear_refocus(self, preset=(0, -2)):
|
||||
return super().handle_boss_appear_refocus(preset)
|
||||
|
@ -68,8 +68,5 @@ class Campaign(CampaignBase):
|
||||
|
||||
return self.fleet_2.brute_clear_boss()
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
for data in self.map.spawn_data:
|
||||
if data.get('battle') == self.battle_count and data.get('boss', 0):
|
||||
self.map_swipe((-3, -2))
|
||||
return super().handle_boss_appear_refocus()
|
||||
def handle_boss_appear_refocus(self, preset=(-3, -2)):
|
||||
return super().handle_boss_appear_refocus(preset)
|
||||
|
@ -49,8 +49,5 @@ class Config:
|
||||
class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
if self.battle_count == 4:
|
||||
self.map_swipe((-3, -2))
|
||||
|
||||
return super().handle_boss_appear_refocus()
|
||||
def handle_boss_appear_refocus(self, preset=(-3, -2)):
|
||||
return super().handle_boss_appear_refocus(preset)
|
||||
|
@ -86,19 +86,32 @@ def random_rectangle_vector_opted(
|
||||
half_vector = np.round(vector / 2).astype(np.int)
|
||||
box = np.array(box) + np.append(np.abs(half_vector) + padding, -np.abs(half_vector) - padding)
|
||||
box = area_offset(box, half_vector)
|
||||
segment = int(np.linalg.norm(vector) // 70) + 1
|
||||
|
||||
def in_blacklist(end):
|
||||
if not blacklist_area:
|
||||
return False
|
||||
for x in range(segment + 1):
|
||||
point = - vector * x / segment + end
|
||||
for area in blacklist_area:
|
||||
if point_in_area(point, area, threshold=0):
|
||||
return True
|
||||
return False
|
||||
|
||||
if whitelist_area:
|
||||
for area in whitelist_area:
|
||||
area = area_limit(area, box)
|
||||
if sum(area_size(area)) > 0:
|
||||
end_point = random_rectangle_point(area)
|
||||
return tuple(end_point - vector), tuple(end_point)
|
||||
for _ in range(10):
|
||||
if in_blacklist(end_point):
|
||||
continue
|
||||
return tuple(end_point - vector), tuple(end_point)
|
||||
|
||||
for n in range(100):
|
||||
for _ in range(100):
|
||||
end_point = random_rectangle_point(box)
|
||||
if blacklist_area:
|
||||
if any([point_in_area(end_point, area, threshold=0) for area in blacklist_area]):
|
||||
continue
|
||||
if in_blacklist(end_point):
|
||||
continue
|
||||
return tuple(end_point - vector), tuple(end_point)
|
||||
|
||||
end_point = random_rectangle_point(box)
|
||||
|
@ -115,6 +115,8 @@ class ManualConfig:
|
||||
MAP_WALK_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.
|
||||
MAP_BOSS_APPEAR_REFOCUS_SWIPE = (0, 0)
|
||||
|
||||
"""
|
||||
module.map_detection
|
||||
|
@ -112,7 +112,7 @@ class Control(MiniTouch):
|
||||
)
|
||||
self.device.long_click(x, y, duration=duration)
|
||||
|
||||
def swipe(self, vector, box=(123, 159, 1193, 628), random_range=(0, 0, 0, 0), padding=15, duration=(0.1, 0.2),
|
||||
def swipe(self, vector, box=(123, 159, 1175, 628), random_range=(0, 0, 0, 0), padding=15, duration=(0.1, 0.2),
|
||||
whitelist_area=None, blacklist_area=None, name='SWIPE'):
|
||||
"""Method to swipe.
|
||||
|
||||
|
@ -20,11 +20,10 @@ class Camera(MapOperation):
|
||||
map: CampaignMap
|
||||
camera = (0, 0)
|
||||
grid_class = Grid
|
||||
_correct_camera = False
|
||||
_prev_view = None
|
||||
_prev_swipe = None
|
||||
|
||||
def _map_swipe(self, vector, box=(123, 159, 1193, 628)):
|
||||
def _map_swipe(self, vector, box=(123, 159, 1175, 628)):
|
||||
"""
|
||||
Args:
|
||||
vector (tuple, np.ndarray): float
|
||||
@ -53,7 +52,9 @@ class Camera(MapOperation):
|
||||
self.device.sleep(0.3)
|
||||
self.update()
|
||||
else:
|
||||
self.update(camera=False)
|
||||
# Drop swipe
|
||||
# self.update(camera=False)
|
||||
pass
|
||||
|
||||
def map_swipe(self, vector):
|
||||
"""
|
||||
@ -109,7 +110,7 @@ class Camera(MapOperation):
|
||||
self._view_init()
|
||||
try:
|
||||
self.view.load(self.device.image)
|
||||
except (MapDetectionError, AttributeError) as e:
|
||||
except MapDetectionError as e:
|
||||
if self.info_bar_count():
|
||||
logger.info('Perspective error cause by info bar. Waiting.')
|
||||
self.handle_info_bar()
|
||||
@ -151,9 +152,6 @@ class Camera(MapOperation):
|
||||
self._prev_swipe = None
|
||||
self.show_camera()
|
||||
|
||||
if not self._correct_camera:
|
||||
self.show_camera()
|
||||
return False
|
||||
# Set camera position
|
||||
if self.view.left_edge:
|
||||
x = 0 + self.view.center_loca[0]
|
||||
@ -173,14 +171,16 @@ class Camera(MapOperation):
|
||||
self.camera = (x, y)
|
||||
self.show_camera()
|
||||
|
||||
def predict(self, mode='normal'):
|
||||
self.predict()
|
||||
|
||||
def predict(self):
|
||||
self.view.predict()
|
||||
self.map.update(grids=self.view, camera=self.camera, mode=mode)
|
||||
self.view.show()
|
||||
|
||||
def show_camera(self):
|
||||
logger.attr_align('Camera', location2node(self.camera))
|
||||
|
||||
def ensure_edge_insight(self, reverse=False, preset=None, swipe_limit=(3, 2)):
|
||||
def ensure_edge_insight(self, reverse=False, preset=None, swipe_limit=(3, 2), skip_first_update=True):
|
||||
"""
|
||||
Swipe to bottom left until two edges insight.
|
||||
Edges are used to locate camera.
|
||||
@ -189,18 +189,19 @@ class Camera(MapOperation):
|
||||
reverse (bool): Reverse swipes.
|
||||
preset (tuple(int)): Set in map swipe manually.
|
||||
swipe_limit (tuple): (x, y). Limit swipe in (-x, -y, x, y).
|
||||
skip_first_update (bool): Usually to be True. Use False if you are calling ensure_edge_insight manually.
|
||||
|
||||
Returns:
|
||||
list[tuple]: Swipe record.
|
||||
"""
|
||||
logger.info(f'Ensure edge in sight.')
|
||||
record = []
|
||||
self._correct_camera = True
|
||||
x_swipe, y_swipe = np.multiply(swipe_limit, random_direction(self.config.MAP_ENSURE_EDGE_INSIGHT_CORNER))
|
||||
|
||||
while 1:
|
||||
if len(record) == 0:
|
||||
self.update()
|
||||
if not skip_first_update:
|
||||
self.update()
|
||||
if preset is not None:
|
||||
self.map_swipe(preset)
|
||||
record.append(preset)
|
||||
@ -217,8 +218,6 @@ class Camera(MapOperation):
|
||||
if x == 0 and y == 0:
|
||||
break
|
||||
|
||||
# self._correct_camera = False
|
||||
|
||||
if reverse:
|
||||
logger.info('Reverse swipes.')
|
||||
for vector in record[::-1]:
|
||||
@ -279,10 +278,9 @@ class Camera(MapOperation):
|
||||
queue = queue.sort_by_camera_distance(self.camera)
|
||||
self.focus_to(queue[0])
|
||||
self.focus_to_grid_center(0.25)
|
||||
self.view.predict()
|
||||
success = self.map.update(grids=self.view, camera=self.camera, mode=mode)
|
||||
if not success:
|
||||
self.ensure_edge_insight()
|
||||
self.ensure_edge_insight(skip_first_update=False)
|
||||
continue
|
||||
|
||||
queue = queue[1:]
|
||||
@ -405,30 +403,36 @@ class Camera(MapOperation):
|
||||
"""
|
||||
map_vector = np.array(map_vector)
|
||||
|
||||
def filter_grids(globe_grids, pad=0):
|
||||
def local_to_area(local_grid, pad=0):
|
||||
result = []
|
||||
for local in local_grid:
|
||||
# Predict the position of grid after swipe.
|
||||
# Swipe should ends there, to prevent treating swipe as click.
|
||||
area = area_offset((0, 0, 1, 1), offset=-map_vector)
|
||||
corner = local.grid2screen(area2corner(area))
|
||||
area = trapezoid2area(corner, pad=pad)
|
||||
result.append(area)
|
||||
return result
|
||||
|
||||
def globe_to_local(globe_grids):
|
||||
result = []
|
||||
for globe in globe_grids:
|
||||
location = tuple(np.array(globe.location) - self.camera + self.view.center_loca)
|
||||
if location in self.view:
|
||||
# Predict the position of grid after swipe.
|
||||
# Swipe should ends there, to prevent treating swipe as click.
|
||||
local = self.view[location]
|
||||
area = area_offset((0, 0, 1, 1), offset=-map_vector)
|
||||
corner = local.grid2screen(area2corner(area))
|
||||
area = trapezoid2area(corner, pad=pad)
|
||||
result.append(area)
|
||||
result.append(local)
|
||||
return result
|
||||
|
||||
whitelist = self.map.select(is_land=True) \
|
||||
.add(self.map.select(is_current_fleet=True)) \
|
||||
.sort_by_camera_distance(self.camera)
|
||||
blacklist = self.map.select(is_sea=False) \
|
||||
.delete(self.map.select(is_land=True)) \
|
||||
.add(self.map.select(is_fleet=True, is_current_fleet=False)) \
|
||||
.add(self.map.select(is_mystery=True)) \
|
||||
.sort_by_camera_distance(self.camera)
|
||||
blacklist = self.view.select(is_enemy=True) \
|
||||
.add(self.view.select(is_siren=True)) \
|
||||
.add(self.view.select(is_mystery=True)) \
|
||||
.add(self.view.select(is_fleet=True, is_current_fleet=False))
|
||||
|
||||
whitelist = filter_grids(whitelist, pad=25)
|
||||
blacklist = filter_grids(blacklist, pad=-5)
|
||||
# self.view.show()
|
||||
whitelist = local_to_area(globe_to_local(whitelist), pad=25)
|
||||
blacklist = [grid.outer for grid in blacklist] + local_to_area(blacklist, pad=-5)
|
||||
|
||||
return whitelist, blacklist
|
||||
|
@ -1,7 +1,9 @@
|
||||
import itertools
|
||||
|
||||
import numpy as np
|
||||
|
||||
from module.base.timer import Timer
|
||||
from module.exception import MapWalkError, MapEnemyMoved
|
||||
from module.exception import MapWalkError, MapEnemyMoved, MapDetectionError
|
||||
from module.handler.ambush import AmbushHandler
|
||||
from module.logger import logger
|
||||
from module.map.camera import Camera
|
||||
@ -298,7 +300,8 @@ class Fleet(Camera, AmbushHandler):
|
||||
elif self.map[location].may_enemy:
|
||||
self.map[location].is_cleared = True
|
||||
|
||||
self.handle_boss_appear_refocus()
|
||||
if self.catch_boss_appear():
|
||||
self.handle_boss_appear_refocus()
|
||||
if self.config.MAP_FOCUS_ENEMY_AFTER_BATTLE:
|
||||
self.camera = location
|
||||
self.update()
|
||||
@ -364,6 +367,7 @@ class Fleet(Camera, AmbushHandler):
|
||||
break
|
||||
if walk_timeout.reached():
|
||||
logger.warning('Walk timeout. Retrying.')
|
||||
self.predict()
|
||||
self.ensure_edge_insight()
|
||||
break
|
||||
|
||||
@ -382,8 +386,11 @@ class Fleet(Camera, AmbushHandler):
|
||||
self.full_scan_carrier()
|
||||
if result == 'combat':
|
||||
self.round_battle()
|
||||
self.predict()
|
||||
self.round_next()
|
||||
if self.round_is_new:
|
||||
if result != 'combat':
|
||||
self.predict()
|
||||
self.full_scan_movable(enemy_cleared=result == 'combat')
|
||||
self.find_path_initial()
|
||||
raise MapEnemyMoved
|
||||
@ -422,6 +429,7 @@ class Fleet(Camera, AmbushHandler):
|
||||
self._goto(node, expected=expected if node == nodes[-1] else '')
|
||||
except MapWalkError:
|
||||
logger.warning('Map walk error.')
|
||||
self.predict()
|
||||
self.ensure_edge_insight()
|
||||
nodes_ = self.map.find_path(node, step=1)
|
||||
for node_ in nodes_:
|
||||
@ -845,7 +853,7 @@ class Fleet(Camera, AmbushHandler):
|
||||
|
||||
logger.warning('Enemy roadblock try exhausted.')
|
||||
|
||||
def handle_boss_appear_refocus(self):
|
||||
def catch_boss_appear(self):
|
||||
"""
|
||||
|
||||
"""
|
||||
@ -868,14 +876,33 @@ class Fleet(Camera, AmbushHandler):
|
||||
# g.wipe_out()
|
||||
# break
|
||||
|
||||
if appear:
|
||||
camera = self.camera
|
||||
return appear
|
||||
|
||||
def handle_boss_appear_refocus(self, preset=None):
|
||||
"""
|
||||
Refocus to previous camera position after boss appear.
|
||||
|
||||
Args:
|
||||
preset (tuple): (x, y).
|
||||
"""
|
||||
camera = self.camera
|
||||
if preset is None:
|
||||
preset = self.config.MAP_BOSS_APPEAR_REFOCUS_SWIPE
|
||||
|
||||
if preset is not None and np.linalg.norm(preset) > 0:
|
||||
try:
|
||||
self.update()
|
||||
except MapDetectionError:
|
||||
logger.info(f'MapDetectionError occurs after boss appear, trying swipe preset {preset}')
|
||||
# Swipe optimize here may not be accurate.
|
||||
self.map_swipe(preset)
|
||||
self.ensure_edge_insight()
|
||||
logger.info('Refocus to previous camera position.')
|
||||
self.focus_to(camera)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
self.update()
|
||||
self.ensure_edge_insight()
|
||||
|
||||
logger.info('Refocus to previous camera position.')
|
||||
self.focus_to(camera)
|
||||
|
||||
def fleet_checked_reset(self):
|
||||
self.map_fleet_checked = False
|
||||
|
@ -294,7 +294,7 @@ class CampaignMap:
|
||||
mode (str): Scan mode, such as 'normal', 'carrier', 'movable'
|
||||
"""
|
||||
offset = np.array(camera) - np.array(grids.center_loca)
|
||||
grids.show()
|
||||
# grids.show()
|
||||
|
||||
failed_count = 0
|
||||
for grid in grids.grids.values():
|
||||
|
@ -112,6 +112,10 @@ class Perspective:
|
||||
edge_v = edge_v.delete(inner_v, threshold=self.config.TRUST_EDGE_LINES_THRESHOLD)
|
||||
self.horizontal = horizontal
|
||||
self.vertical = vertical
|
||||
if not self.horizontal:
|
||||
raise MapDetectionError('No horizontal line detected')
|
||||
if not self.vertical:
|
||||
raise MapDetectionError('No vertical line detected')
|
||||
|
||||
# Calculate perspective
|
||||
self.crossings = self.horizontal.cross(self.vertical)
|
||||
|
@ -17,6 +17,10 @@ class Assets:
|
||||
def ui_mask(self):
|
||||
return UI_MASK.image
|
||||
|
||||
@cached_property
|
||||
def ui_mask_os(self):
|
||||
return UI_MASK_OS.image
|
||||
|
||||
@cached_property
|
||||
def ui_mask_stroke(self):
|
||||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
||||
@ -33,7 +37,7 @@ class Assets:
|
||||
def ui_mask_os_in_map(self):
|
||||
area = np.append(np.subtract(0, DETECTING_AREA[:2]), self.ui_mask.shape[::-1])
|
||||
# area = (-123, -55, 1157, 665)
|
||||
return crop(UI_MASK_OS.image, area)
|
||||
return crop(self.ui_mask_os, area)
|
||||
|
||||
@cached_property
|
||||
def tile_center_image(self):
|
||||
|
@ -36,7 +36,7 @@ class OSFleet(OSCamera, Combat, Fleet, OSAsh):
|
||||
Remove non-exist things like strategy, round.
|
||||
"""
|
||||
# self.handle_strategy(index=1 if not self.fleets_reversed() else 2)
|
||||
# self.update()
|
||||
self.update()
|
||||
# if self.handle_fleet_reverse():
|
||||
# self.handle_strategy(index=1)
|
||||
self.hp_reset()
|
||||
|
Loading…
Reference in New Issue
Block a user