def full_scan_movable(self, enemy_cleared=True): """ Call this method if enemy moved. Args: enemy_cleared (bool): True if cleared an enemy and need to scan spawn enemies. False if just a simple walk and only need to scan movable enemies. """ before = self.movable_before for grid in before: grid.wipe_out() self.full_scan(queue=None if enemy_cleared else before, must_scan=before, mode='movable') after = self.map.select(is_siren=True) step = self.config.MOVABLE_ENEMY_FLEET_STEP matched_before, matched_after = match_movable( before=before.location, spawn=self.map.select(may_siren=True).location, after=after.location, fleets=[self.fleet_current] if enemy_cleared else [], fleet_step=step) matched_before = self.map.to_selected(matched_before) matched_after = self.map.to_selected(matched_after) logger.info(f'Movable enemy {before} -> {after}') logger.info(f'Tracked enemy {matched_before} -> {matched_after}') for grid in after.delete(matched_after): if not grid.may_siren: logger.warning(f'Wrong detection: {grid}') grid.wipe_out() diff = before.delete(matched_before) if diff: logger.info(f'Movable enemy tracking lost: {diff}') covered = self.map.grid_covered(self.map[self.fleet_current], location=[(0, -2)]) \ .add(self.map.grid_covered(self.map[self.fleet_1_location], location=[(0, -1)])) \ .add(self.map.grid_covered(self.map[self.fleet_2_location], location=[(0, -1)])) for grid in after: covered = covered.add(self.map.grid_covered(grid)) accessible = SelectedGrids([]) location = [(x, y) for x in range(step) for y in range(step) if abs(x) + abs(y) <= step] for grid in diff: accessible = accessible.add( self.map.grid_covered(grid, location=location)) predict = accessible.intersect(covered).select(is_sea=True) logger.info(f'Movable enemy predict: {predict}') for grid in predict: grid.is_siren = True grid.is_enemy = True for grid in matched_after: if grid.location != self.fleet_current: grid.is_movable = True
def find_submarine(self): if not (self.config.SUBMARINE and self.map.select(is_submarine_spawn_point=True)): return False fleets = self.map.select(is_submarine=True) count = fleets.count if count == 1: self.fleet_submarine = fleets[0].location elif count == 0: logger.info('No submarine found') # Try spawn points spawn_point = self.map.select(is_submarine_spawn_point=True) if spawn_point.count == 1: logger.info( f'Predict the only submarine spawn point {spawn_point[0]} as submarine' ) self.fleet_submarine = spawn_point[0].location else: logger.info( f'Having multiple submarine spawn points: {spawn_point}') # Try covered grids covered = SelectedGrids([]) for grid in spawn_point: covered = covered.add( self.map.grid_covered(grid, location=[(0, 1)])) covered = covered.filter(lambda g: g.is_enemy or g.is_fleet or g.is_siren or g.is_boss) if covered.count == 1: spawn_point = self.map.grid_covered(covered[0], location=[(0, -1)]) logger.info( f'Submarine {spawn_point[0]} covered by {covered[0]}') self.fleet_submarine = spawn_point[0].location else: logger.info( 'Found multiple submarine spawn points being covered') # Give up self.find_all_submarines() else: logger.warning('Too many submarines: %s.' % str(fleets)) self.find_all_submarines() if not len(self.fleet_submarine_location): logger.warning( 'Unable to find submarine, assume it is at map center') shape = self.map.shape center = (shape[0] // 2, shape[1] // 2) self.fleet_submarine = self.map.select( is_land=False).sort_by_camera_distance(center)[0].location self.show_submarine() return self.fleet_submarine_location
def full_scan_movable(self, enemy_cleared=True): """ Call this method if enemy moved. Args: enemy_cleared (bool): True if cleared an enemy and need to scan spawn enemies. False if just a simple walk and only need to scan movable enemies. """ before = self.movable_before for grid in before: grid.wipe_out() self.full_scan(queue=None if enemy_cleared else before, must_scan=before, mode='movable') # Track siren moving after = self.map.select(is_siren=True) step = self.config.MOVABLE_ENEMY_FLEET_STEP matched_before, matched_after = match_movable( before=before.location, spawn=self.map.select(may_siren=True).location, after=after.location, fleets=[self.fleet_current] if enemy_cleared else [], fleet_step=step) matched_before = self.map.to_selected(matched_before) matched_after = self.map.to_selected(matched_after) logger.info(f'Movable enemy {before} -> {after}') logger.info(f'Tracked enemy {matched_before} -> {matched_after}') # Delete wrong prediction for grid in after.delete(matched_after): if not grid.may_siren: logger.warning(f'Wrong detection: {grid}') grid.wipe_out() # Predict missing siren diff = before.delete(matched_before) _, missing = self.map.missing_get(self.battle_count, self.mystery_count, self.siren_count, self.carrier_count, mode='normal') if diff and missing['siren'] != 0: logger.warning(f'Movable enemy tracking lost: {diff}') covered = self.map.grid_covered(self.map[self.fleet_current], location=[(0, -2)]) if self.fleet_1_location: covered = covered.add( self.map.grid_covered(self.map[self.fleet_1_location], location=[(0, -1)])) if self.fleet_2_location: covered = covered.add( self.map.grid_covered(self.map[self.fleet_2_location], location=[(0, -1)])) for grid in after: covered = covered.add(self.map.grid_covered(grid)) logger.attr('enemy_covered', covered) accessible = SelectedGrids([]) for grid in diff: self.map.find_path_initial(grid, has_ambush=False) accessible = accessible.add(self.map.select(cost=0)) \ .add(self.map.select(cost=1)).add(self.map.select(cost=2)) self.map.find_path_initial(self.fleet_current, has_ambush=self.config.MAP_HAS_AMBUSH) logger.attr('enemy_accessible', accessible) predict = accessible.intersect(covered).select(is_sea=True, is_fleet=False) logger.info(f'Movable enemy predict: {predict}') for grid in predict: grid.is_siren = True grid.is_enemy = True elif missing['siren'] == 0: logger.info(f'Movable enemy tracking drop: {diff}') for grid in matched_after: if grid.location != self.fleet_current: grid.is_movable = True