def missing_predict(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0, mode='normal'): if self.poor_map_data: return False may, missing = self.missing_get(battle_count, mystery_count, siren_count, carrier_count, mode) # predict for upper in self.map_covered: for attr in ['enemy', 'mystery', 'siren', 'boss']: if upper.__getattribute__('may_' + attr) and missing[ attr] > 0 and missing[attr] == may[attr]: logger.info('Predict %s to be %s' % (location2node(upper.location), attr)) upper.__setattr__('is_' + attr, True) if carrier_count: if upper.may_carrier and missing['carrier'] > 0 and missing[ 'carrier'] == may['carrier']: logger.info('Predict %s to be enemy' % location2node(upper.location)) upper.__setattr__('is_enemy', True)
def find_path(self, location, step=0): location = location_ensure(location) path = self._find_path(location) if path is None or not len(path): logger.warning('No path found. Return destination.') return [location] logger.info('Full path: %s' % '[' + ', '.join([location2node(grid) for grid in path]) + ']') portal_path = [] index = [0] for i, loca in enumerate(zip(path[:-1], path[1:])): if self[loca[0]].is_portal and self[ loca[0]].portal_link == loca[1]: index += [i, i + 1] index.append(len(path)) for start, end in zip(index[:-1], index[1:]): 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) portal_path += local_path logger.info('Path: %s' % '[' + ', '.join([location2node(grid) for grid in local_path]) + ']') path = portal_path return path
def find_path(self, location, step=0): location = location_ensure(location) path = self._find_path(location) if path is None or not len(path): logger.warning('No path found. Return destination.') return [location] logger.info('Path: %s' % '[' + ', '.join([location2node(grid) for grid in path]) + ']') path = self._find_route_node(path, step=step) logger.info('Path: %s' % '[' + ', '.join([location2node(grid) for grid in path]) + ']') return path
def _load_map_data(self, text): if not len(self.grids.keys()): grids = np.array([loca for loca, _ in self._parse_text(text)]) self.shape = location2node(tuple(np.max(grids, axis=0))) for loca, data in self._parse_text(text): self.grids[loca].decode(data)
def show_connection(self): logger.info(' ' + ' '.join([' ' + chr(x + 64 + 1) for x in range(self.shape[0] + 1)])) for y in range(self.shape[1] + 1): text = str(y + 1).rjust(2) + ' ' + ' '.join( [location2node(self[(x, y)].connection) if (x, y) in self and self[(x, y)].connection else ' ' for x in range(self.shape[0] + 1)]) logger.info(text)
def get_file_lines(self): """ Returns: list(str): Python code in map file. """ header = """ from module.campaign.campaign_base import CampaignBase from module.map.map_base import CampaignMap from module.map.map_grids import SelectedGrids, RoadGrids from module.logger import logger """ lines = [] # Import for head in header.strip().split('\n'): lines.append(head.strip()) lines.append('') lines.append('') # Map lines.append(f'MAP = CampaignMap(\'{self.chapter_name}\')') lines.append(f'MAP.shape = \'{location2node(self.shape)}\'') lines.append( f'MAP.camera_data = {[location2node(loca) for loca in camera_2d(self.shape, sight=(-3, -1, 3, 2))]}') lines.append(f'MAP.camera_data_spawn_point = []') lines.append('MAP.map_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join([self.map_data[(x, y)] for x in range(self.shape[0] + 1)])) lines.append('\"\"\"') lines.append('MAP.weight_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join(['10'] * (self.shape[0] + 1))) lines.append('\"\"\"') lines.append('MAP.spawn_data = [') for battle in self.spawn_data: lines.append(' ' + str(battle) + ',') lines.append(']') for y in range(self.shape[1] + 1): lines.append(', '.join([location2node((x, y)) for x in range(self.shape[0] + 1)]) + ', \\') lines.append(' = MAP.flatten()') lines.append('') lines.append('') # Config lines.append('class Config:') lines.append(' pass') lines.append('') lines.append('') # Campaign lines.append('class Campaign(CampaignBase):') lines.append(' MAP = MAP') lines.append('') lines.append(' def battle_0(self):') lines.append(' return self.battle_default()') lines.append('') lines.append(f' def battle_{self.data["boss_refresh"]}(self):') lines.append(' return self.fleet_boss.clear_boss()') return lines
def extract_map_size(self, server='zh-CN'): LOADER.server = server data = LOADER.load('sharecfgdata/world_chapter_template.lua') out = {} for full_index, chapter in data.items(): if not full_index // 1000000 == 1 or not chapter['map_sight']: continue index = (full_index % 1000000) // 1000 if index < 10: index -= 1 shape = self.parse_map_data(chapter['grids']) out[index] = location2node(shape) return out
def shape(self, scale): self._shape = node2location(scale.upper()) for y in range(self._shape[1] + 1): for x in range(self._shape[0] + 1): grid = GridInfo() grid.location = (x, y) self.grids[(x, y)] = grid # camera_data can be generate automatically, but it's better to set it manually. self.camera_data = [location2node(loca) for loca in camera_2d((0, 0, *self._shape), sight=self.camera_sight)] self.camera_data_spawn_point = [] # weight_data set to 10. for grid in self: grid.weight = 10.
def extract_map_size(self, server='zh-CN'): folder = os.path.join(self.folder, server, 'sharecfg') data = load_lua_by_function(folder, 'world_chapter_template.lua') out = {} for full_index, chapter in data.items(): if not full_index // 1000000 == 1 or not chapter['map_sight']: continue index = (full_index % 1000000) // 1000 if index < 10: index -= 1 shape = self.parse_map_data(chapter['grids']) out[index] = location2node(shape) return out
def missing_predict(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0): if self.poor_map_data: return False may, missing = self.missing_get(battle_count, mystery_count, siren_count, carrier_count) # predict for grid in self: if not grid.is_fleet and not grid.is_mystery: continue cover = [(0, -1)] if grid.is_current_fleet: cover.append((0, -2)) for upper in cover: upper = tuple(np.array(grid.location) + upper) if upper in self: upper = self[upper] for attr in ['enemy', 'mystery', 'siren', 'boss']: if upper.__getattribute__('may_' + attr) and missing[ attr] > 0 and missing[attr] == may[attr]: logger.info('Predict %s to be %s' % (location2node(upper.location), attr)) upper.__setattr__('is_' + attr, True) if carrier_count: if upper.may_carrier and missing[ 'carrier'] > 0 and missing['carrier'] == may[ 'carrier']: logger.info('Predict %s to be enemy' % location2node(upper.location)) upper.__setattr__('is_enemy', True)
def shape(self, scale): self._shape = node2location(scale.upper()) for y in range(self._shape[1] + 1): for x in range(self._shape[0] + 1): grid = GridInfo() grid.location = (x, y) self.grids[(x, y)] = grid # camera_data can be generate automatically, but it's better to set it manually. self.camera_data = [ location2node(loca) for loca in camera_2d(self._shape, sight=self.camera_sight) ] # weight_data set to 10. for grid in self: grid.weight = 10. # Initialize grid connection. self.grid_connection_initial()
def get_file_lines(self, has_modified_campaign_base): """ Args: has_modified_campaign_base (bool): If target folder has modified campaign_base.py Returns: list(str): Python code in map file. """ if IS_WAR_ARCHIVES: base_import = 'from ..campaign_war_archives.campaign_base import CampaignBase' elif has_modified_campaign_base: base_import = 'from .campaign_base import CampaignBase' else: base_import = 'from module.campaign.campaign_base import CampaignBase' header = f""" {base_import} from module.map.map_base import CampaignMap from module.map.map_grids import SelectedGrids, RoadGrids from module.logger import logger """ lines = [] # Import for head in header.strip().split('\n'): lines.append(head.strip()) if self.chapter_name[-1].isdigit(): chap, stage = self.chapter_name[:-1], self.chapter_name[-1] if stage != '1': lines.append( f'from .{chap.lower()}1 import Config as ConfigBase') lines.append('') # Map lines.append(f'MAP = CampaignMap(\'{self.chapter_name}\')') lines.append(f'MAP.shape = \'{location2node(self.shape)}\'') camera_data = camera_2d(get_map_active_area(self.map_data), sight=(-3, -1, 3, 2)) lines.append( f'MAP.camera_data = {[location2node(loca) for loca in camera_data]}' ) camera_sp = camera_spawn_point( camera_data, sp_list=[k for k, v in self.map_data.items() if v == 'SP']) lines.append( f'MAP.camera_data_spawn_point = {[location2node(loca) for loca in camera_sp]}' ) if self.MAP_HAS_PORTAL: lines.append(f'MAP.portal_data = {self.portal}') lines.append('MAP.map_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join( [self.map_data[(x, y)] for x in range(self.shape[0] + 1)])) lines.append('\"\"\"') if self.map_data_loop is not None: lines.append('MAP.map_data_loop = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join([ self.map_data_loop[(x, y)] for x in range(self.shape[0] + 1) ])) lines.append('\"\"\"') lines.append('MAP.weight_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join(['50'] * (self.shape[0] + 1))) lines.append('\"\"\"') if self.MAP_HAS_LAND_BASED: lines.append(f'MAP.land_based_data = {self.land_based}') lines.append('MAP.spawn_data = [') for battle in self.spawn_data: lines.append(' ' + str(battle) + ',') lines.append(']') if self.spawn_data_loop is not None: lines.append('MAP.spawn_data_loop = [') for battle in self.spawn_data_loop: lines.append(' ' + str(battle) + ',') lines.append(']') for y in range(self.shape[1] + 1): lines.append(', '.join( [location2node((x, y)) for x in range(self.shape[0] + 1)]) + ', \\') lines.append(' = MAP.flatten()') lines.append('') lines.append('') # Config if self.chapter_name[-1].isdigit(): chap, stage = self.chapter_name[:-1], self.chapter_name[-1] if stage != '1': lines.append('class Config(ConfigBase):') else: lines.append('class Config:') else: lines.append('class Config:') lines.append(' # ===== Start of generated config =====') if len(self.MAP_SIREN_TEMPLATE): lines.append(f' MAP_SIREN_TEMPLATE = {self.MAP_SIREN_TEMPLATE}') lines.append( f' MOVABLE_ENEMY_TURN = {tuple(self.MOVABLE_ENEMY_TURN)}') lines.append(f' MAP_HAS_SIREN = True') lines.append( f' MAP_HAS_MOVABLE_ENEMY = {self.MAP_HAS_MOVABLE_ENEMY}') lines.append(f' MAP_HAS_MAP_STORY = {self.MAP_HAS_MAP_STORY}') lines.append(f' MAP_HAS_FLEET_STEP = {self.MAP_HAS_FLEET_STEP}') lines.append(f' MAP_HAS_AMBUSH = {self.MAP_HAS_AMBUSH}') if self.MAP_HAS_PORTAL: lines.append(f' MAP_HAS_PORTAL = {self.MAP_HAS_PORTAL}') if self.MAP_HAS_LAND_BASED: lines.append(f' MAP_HAS_LAND_BASED = {self.MAP_HAS_LAND_BASED}') for n in range(1, 4): if self.__getattribute__(f'STAR_REQUIRE_{n}') != n: lines.append(f' STAR_REQUIRE_{n} = 0') lines.append(' # ===== End of generated config =====') lines.append('') lines.append('') # Campaign lines.append('class Campaign(CampaignBase):') lines.append(' MAP = MAP') lines.append('') lines.append(' def battle_0(self):') if len(self.MAP_SIREN_TEMPLATE): lines.append(' if self.clear_siren():') lines.append(' return True') lines.append('') lines.append(' return self.battle_default()') lines.append('') lines.append(f' def battle_{self.data["boss_refresh"]}(self):') if self.data["boss_refresh"] >= 5: lines.append(' return self.fleet_boss.clear_boss()') else: lines.append(' return self.clear_boss()') return lines
def __init__(self, data, data_loop): self.data = data self.data_loop = data_loop self.chapter_name = data['chapter_name'].replace('–', '-') self.name = data['name'] self.profiles = data['profiles'] self.map_id = data['id'] try: self.spawn_data = self.parse_spawn_data(data) if data_loop is not None: self.spawn_data_loop = self.parse_spawn_data(data_loop) if len(self.spawn_data) == len(self.spawn_data_loop) \ and all([s1 == s2 for s1, s2 in zip(self.spawn_data, self.spawn_data_loop)]): self.spawn_data_loop = None else: self.spawn_data_loop = None # map_data # {0: {0: 6, 1: 8, 2: False, 3: 0}, ...} self.map_data = self.parse_map_data(data['grids']) self.shape = tuple(np.max(list(self.map_data.keys()), axis=0)) if self.data_loop is not None: self.map_data_loop = self.parse_map_data(data_loop['grids']) if all([ d1 == d2 for d1, d2 in zip(self.map_data.values(), self.map_data_loop.values()) ]): self.map_data_loop = None else: self.map_data_loop = None # portal self.portal = [] if self.map_id in MAP_EVENT_LIST: for event_id in MAP_EVENT_LIST[ self.map_id]['event_list'].values(): event = MAP_EVENT_TEMPLATE[event_id] for effect in event['effect'].values(): if effect[0] == 'jump': address = event['address'] address = location2node((address[1], address[0])) target = location2node((effect[2], effect[1])) self.portal.append((address, target)) # land_based # land_based = {{6, 7, 1}, ...} # Format: {y, x, rotation} land_based_rotation_dict = { 1: 'up', 2: 'down', 3: 'left', 4: 'right' } self.land_based = [] if isinstance(data['land_based'], dict): for lb in data['land_based'].values(): y, x, r = lb.values() if r not in land_based_rotation_dict: continue self.land_based.append( [location2node((x, y)), land_based_rotation_dict[r]]) # config self.MAP_SIREN_TEMPLATE = [] self.MOVABLE_ENEMY_TURN = set() for siren_id in data['ai_expedition_list'].values(): if siren_id == 1: continue exped_data = EXPECTATION_DATA[siren_id] name = exped_data['icon'] name = DIC_SIREN_NAME_CHI_TO_ENG.get(name, name) if name not in self.MAP_SIREN_TEMPLATE: self.MAP_SIREN_TEMPLATE.append(name) self.MOVABLE_ENEMY_TURN.add(int(exped_data['ai_mov'])) self.MAP_HAS_MOVABLE_ENEMY = bool(len(self.MOVABLE_ENEMY_TURN)) self.MAP_HAS_MAP_STORY = len(data['story_refresh_boss']) > 0 self.MAP_HAS_FLEET_STEP = bool(data['is_limit_move']) self.MAP_HAS_AMBUSH = bool(data['is_ambush']) or bool( data['is_air_attack']) self.MAP_HAS_PORTAL = bool(len(self.portal)) self.MAP_HAS_LAND_BASED = bool(len(self.land_based)) for n in range(1, 4): self.__setattr__(f'STAR_REQUIRE_{n}', data[f'star_require_{n}']) except Exception as e: for k, v in data.items(): print(f'{k} = {v}') raise e
def __str__(self): return location2node(self.location)
def get_file_lines(self): """ Returns: list(str): Python code in map file. """ header = """ from module.campaign.campaign_base import CampaignBase from module.map.map_base import CampaignMap from module.map.map_grids import SelectedGrids, RoadGrids from module.logger import logger """ lines = [] # Import for head in header.strip().split('\n'): lines.append(head.strip()) if self.chapter_name[-1].isdigit(): chap, stage = self.chapter_name[:-1], self.chapter_name[-1] if stage != '1': lines.append( f'from .{chap.lower()}1 import Config as ConfigBase') lines.append('') # Map lines.append(f'MAP = CampaignMap(\'{self.chapter_name}\')') lines.append(f'MAP.shape = \'{location2node(self.shape)}\'') lines.append( f'MAP.camera_data = {[location2node(loca) for loca in camera_2d(self.shape, sight=(-3, -1, 3, 2))]}' ) lines.append(f'MAP.camera_data_spawn_point = []') lines.append('MAP.map_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join( [self.map_data[(x, y)] for x in range(self.shape[0] + 1)])) lines.append('\"\"\"') lines.append('MAP.weight_data = \"\"\"') for y in range(self.shape[1] + 1): lines.append(' ' + ' '.join(['50'] * (self.shape[0] + 1))) lines.append('\"\"\"') lines.append('MAP.spawn_data = [') for battle in self.spawn_data: lines.append(' ' + str(battle) + ',') lines.append(']') for y in range(self.shape[1] + 1): lines.append(', '.join( [location2node((x, y)) for x in range(self.shape[0] + 1)]) + ', \\') lines.append(' = MAP.flatten()') lines.append('') lines.append('') # Config if self.chapter_name[-1].isdigit(): chap, stage = self.chapter_name[:-1], self.chapter_name[-1] if stage != '1': lines.append('class Config(ConfigBase):') else: lines.append('class Config:') else: lines.append('class Config:') # lines.append(' pass') if len(self.MAP_SIREN_TEMPLATE): lines.append(f' MAP_SIREN_TEMPLATE = {self.MAP_SIREN_TEMPLATE}') lines.append( f' MOVABLE_ENEMY_TURN = {tuple(self.MOVABLE_ENEMY_TURN)}') lines.append(f' MAP_HAS_SIREN = True') lines.append(f' MAP_HAS_MAP_STORY = {self.MAP_HAS_MAP_STORY}') lines.append(f' MAP_HAS_FLEET_STEP = {self.MAP_HAS_FLEET_STEP}') lines.append('') lines.append('') # Campaign lines.append('class Campaign(CampaignBase):') lines.append(' MAP = MAP') lines.append('') lines.append(' def battle_0(self):') if len(self.MAP_SIREN_TEMPLATE): lines.append(' if self.clear_siren():') lines.append(' return True') lines.append('') lines.append(' return self.battle_default()') lines.append('') lines.append(f' def battle_{self.data["boss_refresh"]}(self):') if self.data["boss_refresh"] >= 5: lines.append(' return self.fleet_boss.clear_boss()') else: lines.append(' return self.clear_boss()') return lines
def __init__(self, data, data_loop): self.data = data self.data_loop = data_loop self.chapter_name = data['chapter_name'].replace('–', '-') self.name = data['name'] self.profiles = data['profiles'] self.map_id = data['id'] try: battle_count = max(data['boss_refresh'], max(data['enemy_refresh'].keys())) except ValueError: battle_count = 0 self.spawn_data = [{ 'battle': index } for index in range(battle_count + 1)] try: # spawn_data for index, count in data['enemy_refresh'].items(): if count: spawn = self.spawn_data[index] spawn['enemy'] = spawn.get('enemy', 0) + count if ''.join([str(item) for item in data['elite_refresh'].values() ]) != '100': # Some data is incorrect for index, count in data['elite_refresh'].items(): if count: spawn = self.spawn_data[index] spawn['enemy'] = spawn.get('enemy', 0) + count for index, count in data['ai_refresh'].items(): if count: spawn = self.spawn_data[index] spawn['siren'] = spawn.get('siren', 0) + count for index, count in data['box_refresh'].items(): if count: spawn = self.spawn_data[index] spawn['mystery'] = spawn.get('mystery', 0) + count try: self.spawn_data[data['boss_refresh']]['boss'] = 1 except IndexError: pass # map_data # {0: {0: 6, 1: 8, 2: False, 3: 0}, ...} self.map_data = self.parse_map_data(data['grids']) self.shape = tuple(np.max(list(self.map_data.keys()), axis=0)) if self.data_loop is not None: self.map_data_loop = self.parse_map_data(data_loop['grids']) if all([ d1 == d2 for d1, d2 in zip(self.map_data.values(), self.map_data_loop.values()) ]): self.map_data_loop = None else: self.map_data_loop = None # portal self.portal = [] if self.map_id in MAP_EVENT_LIST: for event_id in MAP_EVENT_LIST[ self.map_id]['event_list'].values(): event = MAP_EVENT_TEMPLATE[event_id] for effect in event['effect'].values(): if effect[0] == 'jump': address = event['address'] address = location2node((address[1], address[0])) target = location2node((effect[2], effect[1])) self.portal.append((address, target)) # config self.MAP_SIREN_TEMPLATE = [] self.MOVABLE_ENEMY_TURN = set() for siren_id in data['ai_expedition_list'].values(): if siren_id == 1: continue exped_data = EXPECTATION_DATA[siren_id] name = exped_data['icon'] name = DIC_SIREN_NAME_CHI_TO_ENG.get(name, name) self.MAP_SIREN_TEMPLATE.append(name) self.MOVABLE_ENEMY_TURN.add(int(exped_data['ai_mov'])) self.MAP_HAS_MOVABLE_ENEMY = bool(len(self.MOVABLE_ENEMY_TURN)) self.MAP_HAS_MAP_STORY = len(data['story_refresh_boss']) > 0 self.MAP_HAS_FLEET_STEP = bool(data['is_limit_move']) self.MAP_HAS_AMBUSH = bool(data['is_ambush']) or bool( data['is_air_attack']) self.MAP_HAS_PORTAL = bool(len(self.portal)) for n in range(1, 4): self.__setattr__(f'STAR_REQUIRE_{n}', data[f'star_require_{n}']) except Exception as e: for k, v in data.items(): print(f'{k} = {v}') raise e