def _goto(self, location, expected=''): """Goto a grid directly and handle ambush, air raid, mystery picked up, combat. Args: location (tuple, str, GridInfo): Destination. """ location = location_ensure(location) result_mystery = '' self.movable_before = self.map.select(is_siren=True) if self.hp_withdraw_triggered(): self.withdraw() is_portal = self.map[location].is_portal while 1: sight = self.map.camera_sight self.in_sight(location, sight=(sight[0], 0, sight[2], sight[3])) self.focus_to_grid_center() grid = self.convert_map_to_grid(location) self.ambush_color_initial() self.enemy_searching_color_initial() grid.__str__ = location result = 'nothing' self.device.click(grid) arrived = False # Wait to confirm fleet arrived. It does't appear immediately if fleet in combat . extra = 4.5 if self.config.SUBMARINE_MODE == 'hunt_only' else 0 arrive_timer = Timer(0.5 + self.round_wait + extra, count=2) arrive_unexpected_timer = Timer(1.5 + self.round_wait + extra, count=6) # Wait after ambushed. ambushed_retry = Timer(0.5) # If nothing happens, click again. walk_timeout = Timer(20) walk_timeout.start() while 1: self.device.screenshot() grid.image = np.array(self.device.image) if is_portal: self.update() grid = self.view[self.view.center_loca] # Combat if self.config.ENABLE_MAP_FLEET_LOCK and not self.is_in_map(): if self.handle_retirement(): self.map_offensive() walk_timeout.reset() if self.handle_combat_low_emotion(): walk_timeout.reset() if self.combat_appear(): self.combat( expected_end=self._expected_combat_end(expected), fleet_index=self.fleet_current_index) self.hp_get() arrived = True if not self.config.MAP_HAS_MOVABLE_ENEMY else False result = 'combat' self.battle_count += 1 self.fleet_ammo -= 1 if 'siren' in expected or ( self.config.MAP_HAS_MOVABLE_ENEMY and not expected): self.siren_count += 1 elif self.map[location].may_enemy: self.map[location].is_cleared = True self.handle_boss_appear_refocus() grid = self.convert_map_to_grid(location) walk_timeout.reset() # Ambush if self.handle_ambush(): self.hp_get() ambushed_retry.start() walk_timeout.reset() # Mystery mystery = self.handle_mystery(button=grid) if mystery: self.mystery_count += 1 result = 'mystery' result_mystery = mystery # Cat attack animation if self.handle_map_cat_attack(): walk_timeout.reset() continue if self.handle_walk_out_of_step(): raise MapWalkError('walk_out_of_step') # Arrive if self.is_in_map() and \ (grid.predict_fleet() or (walk_timeout.reached() and grid.predict_current_fleet())): if not arrive_timer.started(): logger.info(f'Arrive {location2node(location)}') arrive_timer.start() arrive_unexpected_timer.start() if not arrive_timer.reached(): continue if expected and result not in expected: if arrive_unexpected_timer.reached(): logger.warning('Arrive with unexpected result') else: continue if is_portal: location = self.map[location].portal_link self.camera = location logger.info( f'Arrive {location2node(location)} confirm. Result: {result}. Expected: {expected}' ) arrived = True break # Story if expected == 'story': if self.handle_story_skip(): result = 'story' continue # End if ambushed_retry.started() and ambushed_retry.reached(): break if walk_timeout.reached(): logger.warning('Walk timeout. Retrying.') self.ensure_edge_insight() break # End if arrived: # Ammo grid needs to click again, otherwise the next click doesn't work. if self.map[location].may_ammo: self.device.click(grid) break self.map[self.fleet_current].is_fleet = False self.map[location].wipe_out() self.map[location].is_fleet = True self.__setattr__('fleet_%s_location' % self.fleet_current_index, location) if result_mystery == 'get_carrier': self.full_scan_carrier() if result == 'combat': self.round_battle() self.round_next() if self.round_is_new: self.full_scan_movable(enemy_cleared=result == 'combat') self.find_path_initial() raise MapEnemyMoved self.find_path_initial()
def _goto(self, location, expected=''): """Goto a grid directly and handle ambush, air raid, mystery picked up, combat. Args: location (tuple, str, GridInfo): Destination. """ location = location_ensure(location) siren_count = self.map.select(is_siren=True).count result_mystery = '' while 1: sight = self.map.camera_sight self.in_sight(location, sight=(sight[0], 0, sight[2], sight[3])) self.focus_to_grid_center() grid = self.convert_map_to_grid(location) self.ambush_color_initial() self.enemy_searching_color_initial() grid.__str__ = location result = 'nothing' self.device.click(grid) arrived = False # Wait to confirm fleet arrived. It does't appear immediately if fleet in combat . add = self.config.MAP_SIREN_MOVE_WAIT * min(self.config.MAP_SIREN_COUNT, siren_count) \ if self.config.MAP_HAS_MOVABLE_ENEMY and not self.config.ENABLE_FAST_FORWARD else 0 arrive_timer = Timer(0.3 + add) arrive_unexpected_timer = Timer(1.5 + add) # Wait after ambushed. ambushed_retry = Timer(0.5) # If nothing happens, click again. walk_timeout = Timer(20) walk_timeout.start() while 1: self.device.screenshot() grid.image = self.device.image # Ambush if self.handle_ambush(): ambushed_retry.start() # Mystery mystery = self.handle_mystery(button=grid) if mystery: self.mystery_count += 1 result = 'mystery' result_mystery = mystery # Combat if self.config.ENABLE_MAP_FLEET_LOCK and not self.is_in_map(): if self.handle_retirement(): self.map_offensive() walk_timeout.reset() if self.handle_combat_low_emotion(): walk_timeout.reset() if self.combat_appear(): self.combat( expected_end=self._expected_combat_end(expected), fleet_index=self.fleet_current_index) self.hp_get() if self.hp_withdraw_triggered(): self.withdraw() arrived = True if not self.config.MAP_HAS_MOVABLE_ENEMY else False result = 'combat' self.battle_count += 1 self.fleet_ammo -= 1 if 'siren' in expected: self.siren_count += 1 elif self.map[location].may_enemy: self.map[location].is_cleared = True self.handle_boss_appear_refocus() grid = self.convert_map_to_grid(location) walk_timeout.reset() # Cat attack animation if self.handle_map_cat_attack(): walk_timeout.reset() continue if self.handle_walk_out_of_step(): raise MapWalkError('walk_out_of_step') # Arrive if self.is_in_map() and \ (grid.predict_fleet() or (walk_timeout.reached() and grid.predict_current_fleet())): if not arrive_timer.started(): logger.info(f'Arrive {location2node(location)}') arrive_timer.start() arrive_unexpected_timer.start() if not arrive_timer.reached(): continue if expected and result not in expected: if arrive_unexpected_timer.reached(): logger.warning('Arrive with unexpected result') else: continue logger.info( f'Arrive {location2node(location)} confirm. Result: {result}. Expected: {expected}' ) arrived = True break # End if ambushed_retry.started() and ambushed_retry.reached(): break if walk_timeout.reached(): logger.warning('Walk timeout. Retrying.') self.ensure_edge_insight() break # End if arrived: # Ammo grid needs to click again, otherwise the next click doesn't work. if self.map[location].may_ammo: self.device.click(grid) break self.map[self.fleet_current].is_fleet = False self.map[location].wipe_out() self.map[location].is_fleet = True self.__setattr__('fleet_%s_location' % self.fleet_current_index, location) if result_mystery == 'get_carrier': prev_enemy = self.map.select(is_enemy=True) self.full_scan(is_carrier_scan=True) diff = self.map.select(is_enemy=True).delete(prev_enemy) logger.info(f'Carrier spawn: {diff}') self.find_path_initial()
def _goto(self, location, expected=''): """Goto a grid directly and handle ambush, air raid, mystery picked up, combat. Args: location (tuple, str, GridInfo): Destination. expected (str): Expected result on destination grid, such as 'combat', 'combat_siren', 'mystery'. Will give a waring if arrive with unexpected result. """ location = location_ensure(location) result_mystery = '' self.movable_before = self.map.select(is_siren=True) self.movable_before_normal = self.map.select(is_enemy=True) if self.hp_retreat_triggered(): self.withdraw() is_portal = self.map[location].is_portal # The upper grid is submarine, may mess up predict_fleet() may_submarine_icon = self.map.grid_covered(self.map[location], location=[(0, -1)]) may_submarine_icon = may_submarine_icon and self.fleet_submarine_location == may_submarine_icon[ 0].location while 1: self.fleet_ensure(self.fleet_current_index) self.in_sight(location, sight=self._walk_sight) self.focus_to_grid_center() grid = self.convert_global_to_local(location) self.ambush_color_initial() self.enemy_searching_color_initial() grid.__str__ = location result = 'nothing' self.device.click(grid) arrived = False # Wait to confirm fleet arrived. It does't appear immediately if fleet in combat. extra = 0 if self.config.Submarine_Mode == 'hunt_only': extra += 4.5 if self.config.MAP_HAS_LAND_BASED and grid.is_mechanism_trigger: extra += grid.mechanism_wait arrive_timer = Timer(0.5 + self.round_wait + extra, count=2) arrive_unexpected_timer = Timer(1.5 + self.round_wait + extra, count=6) # Wait after ambushed. ambushed_retry = Timer(0.5) # If nothing happens, click again. walk_timeout = Timer(20) walk_timeout.start() while 1: self.device.screenshot() self.view.update(image=self.device.image) if is_portal: self.update(allow_error=True) grid = self.view[self.view.center_loca] # Combat if self.config.Campaign_UseFleetLock and not self.is_in_map(): if self.handle_retirement(): self.map_offensive() walk_timeout.reset() if self.handle_combat_low_emotion(): walk_timeout.reset() if self.combat_appear(): self.combat(expected_end=self._expected_end(expected), fleet_index=self.fleet_show_index, submarine_mode=self._submarine_mode(expected)) self.hp_get() self.lv_get(after_battle=True) arrived = True if not self.config.MAP_HAS_MOVABLE_ENEMY else False result = 'combat' self.battle_count += 1 self.fleet_ammo -= 1 if 'siren' in expected or ( self.config.MAP_HAS_MOVABLE_ENEMY and not expected): self.siren_count += 1 elif self.map[location].may_enemy: self.map[location].is_cleared = True if self.catch_camera_repositioning(self.map[location]): self.handle_boss_appear_refocus() if self.config.MAP_FOCUS_ENEMY_AFTER_BATTLE: self.camera = location self.update() grid = self.convert_global_to_local(location) arrive_timer = Timer(0.5 + extra, count=2) arrive_unexpected_timer = Timer(1.5 + extra, count=6) walk_timeout.reset() if not (grid.predict_fleet() and grid.predict_current_fleet()): ambushed_retry.start() # Ambush if self.handle_ambush(): self.hp_get() self.lv_get(after_battle=True) walk_timeout.reset() self.view.update(image=self.device.image) if not (grid.predict_fleet() and grid.predict_current_fleet()): ambushed_retry.start() # Mystery mystery = self.handle_mystery(button=grid) if mystery: self.mystery_count += 1 result = 'mystery' result_mystery = mystery # Cat attack animation if self.handle_map_cat_attack(): walk_timeout.reset() continue # Guild popup # Usually handled in combat_status, but sometimes delayed until after battle on slow PCs. if self.handle_guild_popup_cancel(): walk_timeout.reset() continue if self.handle_walk_out_of_step(): raise MapWalkError('walk_out_of_step') # Arrive arrive_predict = '' arrive_checker = False if self.is_in_map(): if not may_submarine_icon and grid.predict_fleet(): arrive_predict = '(is_fleet)' arrive_checker = True elif may_submarine_icon and grid.predict_current_fleet(): arrive_predict = '(may_submarine_icon, is_current_fleet)' arrive_checker = True elif self.config.MAP_WALK_USE_CURRENT_FLEET \ and expected != 'combat_boss' \ and not ('combat' in expected and grid.may_boss) \ and (grid.predict_fleet() or grid.predict_current_fleet()): arrive_predict = '(MAP_WALK_USE_CURRENT_FLEET, is_current_fleet)' arrive_checker = True elif walk_timeout.reached() and grid.predict_current_fleet( ): arrive_predict = '(walk_timeout, is_current_fleet)' arrive_checker = True if arrive_checker: if not arrive_timer.started(): logger.info( f'Arrive {location2node(location)} {arrive_predict}' .strip()) arrive_timer.start() arrive_unexpected_timer.start() if result == 'nothing' and not arrive_timer.reached(): continue if expected and result not in expected: if arrive_unexpected_timer.reached(): logger.warning('Arrive with unexpected result') else: continue if is_portal: location = self.map[location].portal_link self.camera = location logger.info( f'Arrive {location2node(location)} confirm. Result: {result}. Expected: {expected}' ) arrived = True break else: if arrive_timer.started(): arrive_timer.reset() if arrive_unexpected_timer.started(): arrive_unexpected_timer.reset() # Story if expected == 'story': if self.handle_story_skip(): result = 'story' continue # End if ambushed_retry.started() and ambushed_retry.reached(): break if walk_timeout.reached(): logger.warning('Walk timeout. Retrying.') self.predict() self.ensure_edge_insight(skip_first_update=False) break # End if arrived: # Ammo grid needs to click again, otherwise the next click doesn't work. if self.map[location].may_ammo: self.device.click(grid) break self.map[self.fleet_current].is_fleet = False self.map[location].wipe_out() self.map[location].is_fleet = True self.__setattr__('fleet_%s_location' % self.fleet_current_index, location) if result_mystery == 'get_carrier': self.full_scan_carrier() if result == 'combat': self.round_battle(after_battle=True) 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 if self.round_maze_changed: self.find_path_initial() raise MapEnemyMoved self.find_path_initial() if self.config.MAP_HAS_DECOY_ENEMY: if result == 'nothing' and expected == 'combat': raise MapEnemyMoved
def wait_until_walk_stable(self, confirm_timer=None, skip_first_screenshot=False, walk_out_of_step=True): """ Wait until homo_loca stabled. DETECTION_BACKEND must be 'homography'. Args: confirm_timer (Timer): skip_first_screenshot (bool): walk_out_of_step (bool): If catch walk_out_of_step error. Default to True, use False in abyssal zones. Raises: MapWalkError: If unable to goto such grid. """ logger.hr('Wait until walk stable') record = None enemy_searching_appear = False self.device.screenshot_interval_set(0.35) if confirm_timer is None: confirm_timer = Timer(0.8, count=2) confirm_timer.reset() while 1: if skip_first_screenshot: skip_first_screenshot = False else: self.device.screenshot() # Map event if self.handle_map_event(): confirm_timer.reset() continue if self.handle_retirement(): confirm_timer.reset() continue if self.handle_walk_out_of_step(): if walk_out_of_step: raise MapWalkError('walk_out_of_step') else: continue # Enemy searching if not enemy_searching_appear and self.enemy_searching_appear(): enemy_searching_appear = True confirm_timer.reset() continue else: if enemy_searching_appear: self.handle_enemy_flashing() self.device.sleep(0.3) logger.info('Enemy searching appeared.') enemy_searching_appear = False if self.is_in_map(): self.enemy_searching_color_initial() # Combat if self.combat_appear(): # Use ui_back() for testing, because there are too few abyssal loggers every month. # self.ui_back(check_button=self.is_in_map) self.combat(expected_end=self.is_in_map, fleet_index=self.fleet_show_index) confirm_timer.reset() continue # Arrive # Check colors, because screen goes black when something is unlocking. if self.is_in_map() and IN_MAP.match_appear_on(self.device.image): self.update_os() current = self.view.backend.homo_loca logger.attr('homo_loca', current) if record is None or (current is not None and np.linalg.norm( np.subtract(current, record)) < 3): if confirm_timer.reached(): break else: confirm_timer.reset() record = current else: confirm_timer.reset() logger.info('Walk stabled') self.device.screenshot_interval_set(0.1)
def wait_until_walk_stable(self, confirm_timer=None, skip_first_screenshot=False, walk_out_of_step=True, drop=None): """ Wait until homo_loca stabled. DETECTION_BACKEND must be 'homography'. Args: confirm_timer (Timer): skip_first_screenshot (bool): walk_out_of_step (bool): If catch walk_out_of_step error. Default to True, use False in abyssal zones. drop (DropImage): Returns: str: Things that fleet met on its way, 'event', 'search', 'akashi', 'combat', or their combinations like 'event_akashi', 'event_combat', or an empty string '' if nothing met. Raises: MapWalkError: If unable to goto such grid. """ logger.hr('Wait until walk stable') record = None enemy_searching_appear = False self.device.screenshot_interval_set(0.35) if confirm_timer is None: confirm_timer = Timer(0.8, count=2) result = set() confirm_timer.reset() while 1: if skip_first_screenshot: skip_first_screenshot = False else: self.device.screenshot() # Map event if self.handle_map_event(drop=drop): confirm_timer.reset() result.add('event') continue if self.handle_retirement(): confirm_timer.reset() continue if self.handle_walk_out_of_step(): if walk_out_of_step: raise MapWalkError('walk_out_of_step') else: continue # Accident click if self.is_in_globe(): self.os_globe_goto_map() confirm_timer.reset() continue if self.is_in_storage(): self.storage_quit() confirm_timer.reset() continue if self.is_in_os_mission(): self.os_mission_quit() confirm_timer.reset() continue if self.handle_os_game_tips(): confirm_timer.reset() continue # Enemy searching if not enemy_searching_appear and self.enemy_searching_appear(): enemy_searching_appear = True confirm_timer.reset() continue else: if enemy_searching_appear: self.handle_enemy_flashing() self.device.sleep(0.3) logger.info('Enemy searching appeared.') enemy_searching_appear = False result.add('search') if self.is_in_map(): self.enemy_searching_color_initial() # Combat if self.combat_appear(): # Use ui_back() for testing, because there are too few abyssal loggers every month. # self.ui_back(check_button=self.is_in_map) self.combat(expected_end=self.is_in_map, fleet_index=self.fleet_show_index, save_get_items=drop) confirm_timer.reset() result.add('event') continue # Akashi shop if self.appear(PORT_SUPPLY_CHECK, offset=(20, 20)): self.interval_clear(PORT_SUPPLY_CHECK) self.handle_akashi_supply_buy(CLICK_SAFE_AREA) confirm_timer.reset() result.add('akashi') continue # Arrive # Check colors, because screen goes black when something is unlocking. if self.is_in_map() and IN_MAP.match_appear_on(self.device.image): self.update_os() current = self.view.backend.homo_loca logger.attr('homo_loca', current) if record is None or (current is not None and np.linalg.norm( np.subtract(current, record)) < 3): if confirm_timer.reached(): break else: confirm_timer.reset() record = current else: confirm_timer.reset() result = '_'.join(result) logger.info(f'Walk stabled, result: {result}') self.device.screenshot_interval_set() return result