def resolve_random_settings(self): # evaluate settings (important for logic, nice for spoiler) self.randomized_list = [] if self.randomize_settings: setting_info = get_setting_info('randomize_settings') self.randomized_list.extend(setting_info.disable[True]['settings']) for section in setting_info.disable[True]['sections']: self.randomized_list.extend(get_settings_from_section(section)) if self.big_poe_count_random: self.big_poe_count = random.randint(1, 10) self.randomized_list.append('big_poe_count') if self.starting_tod == 'random': setting_info = get_setting_info('starting_tod') choices = [ ch for ch in setting_info.choices if ch not in ['default', 'random'] ] self.starting_tod = random.choice(choices) self.randomized_list.append('starting_tod') if self.starting_age == 'random': self.starting_age = random.choice(['child', 'adult']) self.randomized_list.append('starting_age') if self.chicken_count_random: self.chicken_count = random.randint(0, 7) self.randomized_list.append('chicken_count') # Determine Ganon Trials trial_pool = list(self.skipped_trials) dist_chosen = self.distribution.configure_trials(trial_pool) dist_num_chosen = len(dist_chosen) if self.trials_random: self.trials = dist_num_chosen + random.randint(0, len(trial_pool)) self.randomized_list.append('trials') num_trials = int(self.trials) choosen_trials = random.sample(trial_pool, num_trials - dist_num_chosen) for trial in self.skipped_trials: if trial not in choosen_trials and trial not in dist_chosen: self.skipped_trials[trial] = True # Determine MQ Dungeons dungeon_pool = list(self.dungeon_mq) dist_num_mq = self.distribution.configure_dungeons(self, dungeon_pool) if self.mq_dungeons_random: for dungeon in dungeon_pool: self.dungeon_mq[dungeon] = random.choice([True, False]) self.mq_dungeons = list(self.dungeon_mq.values()).count(True) self.randomized_list.append('mq_dungeons') else: mqd_picks = random.sample(dungeon_pool, self.mq_dungeons - dist_num_mq) for dung in mqd_picks: self.dungeon_mq[dung] = True self.distribution.configure_randomized_settings(self)
def get_dependency(self, setting_name, check_random=True): info = get_setting_info(setting_name) if check_random and 'randomize_key' in info.gui_params and self.__dict__[info.gui_params['randomize_key']]: return info.disabled_default elif info.dependency != None: return info.disabled_default if info.dependency(self) else None else: return None
def get_dependency(self, setting_name, check_random=True): info = get_setting_info(setting_name) not_in_dist = '_settings' not in self.distribution.src_dict or info.name not in self.distribution.src_dict[ '_settings'].keys() if check_random and 'randomize_key' in info.gui_params and self.__dict__[ info.gui_params['randomize_key']] and not_in_dist: return info.disabled_default elif info.dependency != None: return info.disabled_default if info.dependency( self) and not_in_dist else None else: return None
def generate_balanced_weights(fname='default_weights.json'): """ Generate a file with even weights for each setting. """ settings_to_randomize = list(get_settings_from_tab('main_tab'))[1:] + \ list(get_settings_from_tab('detailed_tab')) + \ list(get_settings_from_tab('other_tab')) + \ list(get_settings_from_tab('starting_tab')) exclude_from_weights = [ 'bridge_tokens', 'lacs_tokens', 'triforce_goal_per_world', 'disabled_locations', 'allowed_tricks', 'starting_equipment', 'starting_items', 'starting_songs' ] weight_dict = {} for name in settings_to_randomize: if name not in exclude_from_weights: opts = list(get_setting_info(name).choices.keys()) optsdict = {o: 100. / len(opts) for o in opts} weight_dict[name] = optsdict if fname is not None: with open(fname, 'w') as fp: json.dump(weight_dict, fp, indent=4) return weight_dict
def GetSettingJson(setting, web_version, as_array=False): try: setting_info = get_setting_info(setting) except KeyError: if as_array: return {'name': setting} else: return {} if setting_info.gui_text is None: return None settingJson = { 'options': [], 'default': setting_info.default, 'text': setting_info.gui_text, 'tooltip': RemoveTrailingLines('<br>'.join( line.strip() for line in setting_info.gui_tooltip.split('\n'))), 'type': setting_info.gui_type, 'shared': setting_info.shared, } if as_array: settingJson['name'] = setting_info.name else: settingJson['current_value'] = setting_info.default setting_disable = {} if setting_info.disable != None: setting_disable = copy.deepcopy(setting_info.disable) for key, value in setting_info.gui_params.items(): if key.startswith('web:'): if web_version: key = key[4:] else: continue if key.startswith('electron:'): if not web_version: key = key[9:] else: continue if key in setting_keys: settingJson[key] = value if key == 'disable': for option, types in value.items(): for s in types.get('settings', []): if get_setting_info(s).shared: raise ValueError( f'Cannot disable setting {s}. Disabling "shared" settings in the gui_params is forbidden. Use the non gui_param version of disable instead.' ) for section in types.get('sections', []): for s in get_settings_from_section(section): if get_setting_info(s).shared: raise ValueError( f'Cannot disable setting {s} in {section}. Disabling "shared" settings in the gui_params is forbidden. Use the non gui_param version of disable instead.' ) for tab in types.get('tabs', []): for s in get_settings_from_tab(tab): if get_setting_info(s).shared: raise ValueError( f'Cannot disable setting {s} in {tab}. Disabling "shared" settings in the gui_params is forbidden. Use the non gui_param version of disable instead.' ) deep_update(setting_disable, value) if settingJson['type'] in types_with_options: if as_array: settingJson['options'] = [] else: settingJson['options'] = {} tags_list = [] for option_name in setting_info.choice_list: if option_name in settingJson.get('option_remove', []): continue if as_array: optionJson = { 'name': option_name, 'text': setting_info.choices[option_name], } else: optionJson = { 'text': setting_info.choices[option_name], } if option_name in setting_disable: add_disable_option_to_json(setting_disable[option_name], optionJson) option_tooltip = setting_info.gui_params.get('choice_tooltip', {}).get( option_name, None) if option_tooltip != None: optionJson['tooltip'] = RemoveTrailingLines('<br>'.join( line.strip() for line in option_tooltip.split('\n'))) option_filter = setting_info.gui_params.get('filterdata', {}).get( option_name, None) if option_filter != None: optionJson['tags'] = option_filter for tag in option_filter: if tag not in tags_list: tags_list.append(tag) if as_array: settingJson['options'].append(optionJson) else: settingJson['options'][option_name] = optionJson # For disables with '!', add disable settings to all options other than the one marked. for option_name in setting_disable: if isinstance(option_name, str) and option_name[0] == '!': if as_array: for option in settingJson['options']: if option['name'] != option_name[1:]: add_disable_option_to_json( setting_disable[option_name], option) else: for name, option in settingJson['options'].items(): if name != option_name[1:]: add_disable_option_to_json( setting_disable[option_name], option) if tags_list: tags_list.sort() settingJson['tags'] = ['(all)'] + tags_list settingJson['filter_by_tag'] = True return settingJson
def __init__(self, settings): self.shuffle = 'vanilla' self.dungeons = [] self.regions = [] self.itempool = [] self.state = State(self) self._cached_locations = None self._entrance_cache = {} self._region_cache = {} self._location_cache = {} self.required_locations = [] self.shop_prices = {} self.scrub_prices = {} self.light_arrow_location = None # dump settings directly into world's namespace # this gives the world an attribute for every setting listed in Settings.py self.settings = settings self.__dict__.update(settings.__dict__) self.distribution = None # evaluate settings (important for logic, nice for spoiler) if self.big_poe_count_random: self.big_poe_count = random.randint(1, 10) if self.starting_tod == 'random': setting_info = get_setting_info('starting_tod') choices = [ ch for ch in setting_info.choices if ch not in ['default', 'random'] ] self.starting_tod = random.choice(choices) if self.starting_age == 'random': self.starting_age = random.choice(['child', 'adult']) # rename a few attributes... self.keysanity = self.shuffle_smallkeys != 'dungeon' self.check_beatable_only = not self.all_reachable self.shuffle_dungeon_entrances = self.entrance_shuffle != 'off' self.shuffle_grotto_entrances = self.entrance_shuffle in [ 'simple-indoors', 'all-indoors', 'all' ] self.shuffle_interior_entrances = self.entrance_shuffle in [ 'simple-indoors', 'all-indoors', 'all' ] self.shuffle_special_interior_entrances = self.entrance_shuffle in [ 'all-indoors', 'all' ] self.shuffle_overworld_entrances = self.entrance_shuffle == 'all' # trials that can be skipped will be decided later self.skipped_trials = { 'Forest': False, 'Fire': False, 'Water': False, 'Spirit': False, 'Shadow': False, 'Light': False } # dungeon forms will be decided later self.dungeon_mq = { 'Deku Tree': False, 'Dodongos Cavern': False, 'Jabu Jabus Belly': False, 'Bottom of the Well': False, 'Ice Cavern': False, 'Gerudo Training Grounds': False, 'Forest Temple': False, 'Fire Temple': False, 'Water Temple': False, 'Spirit Temple': False, 'Shadow Temple': False, 'Ganons Castle': False } self.can_take_damage = True
def GetSettingJson(setting, web_version, as_array=False): try: setting_info = get_setting_info(setting) except KeyError: if as_array: return {'name': setting} else: return {} if setting_info.gui_text is None: return None settingJson = { 'options': [], 'default': setting_info.default, 'text': setting_info.gui_text, 'tooltip': RemoveTrailingLines('<br>'.join( line.strip() for line in setting_info.gui_tooltip.split('\n'))), 'type': setting_info.gui_type, } if as_array: settingJson['name'] = setting_info.name else: settingJson['current_value'] = setting_info.default for key, value in setting_info.gui_params.items(): if key in setting_keys: settingJson[key] = value if key.startswith('web:') and web_version: settingJson[key[4:]] = value if key.startswith('electron:') and not web_version: settingJson[key[9:]] = value if settingJson['type'] in types_with_options: if as_array: settingJson['options'] = [] else: settingJson['options'] = {} tags_list = [] for option_name in setting_info.choice_list: if as_array: optionJson = { 'name': option_name, 'text': setting_info.choices[option_name], } else: optionJson = { 'text': setting_info.choices[option_name], } if setting_info.disable != None and option_name in setting_info.disable: disable_option = setting_info.disable[option_name] if disable_option.get('settings') != None: optionJson['controls_visibility_setting'] = ','.join( disable_option['settings']) if disable_option.get('sections') != None: optionJson['controls_visibility_section'] = ','.join( disable_option['sections']) if disable_option.get('tabs') != None: optionJson['controls_visibility_tab'] = ','.join( disable_option['tabs']) option_tooltip = setting_info.gui_params.get('choice_tooltip', {}).get( option_name, None) if option_tooltip != None: optionJson['tooltip'] = RemoveTrailingLines('<br>'.join( line.strip() for line in option_tooltip.split('\n'))) option_filter = setting_info.gui_params.get('filterdata', {}).get( option_name, None) if option_filter != None: optionJson['tags'] = option_filter for tag in option_filter: if tag not in tags_list: tags_list.append(tag) if as_array: settingJson['options'].append(optionJson) else: settingJson['options'][option_name] = optionJson if tags_list: tags_list.sort() settingJson['tags'] = ['(all)'] + tags_list settingJson['filter_by_tag'] = True return settingJson
def check_dependency(self, setting_name): info = get_setting_info(setting_name) if info.gui_params is not None and 'dependency' in info.gui_params: return info.gui_params['dependency'](self) == None else: return True
def check_dependency(self, setting_name): info = get_setting_info(setting_name) if info.dependency != None: return info.dependency(self) == None else: return True
def resolve_random_settings(self): # evaluate settings (important for logic, nice for spoiler) self.randomized_list = [] dist_keys = [] if '_settings' in self.distribution.distribution.src_dict: dist_keys = self.distribution.distribution.src_dict[ '_settings'].keys() if self.settings.randomize_settings: setting_info = get_setting_info('randomize_settings') self.randomized_list.extend(setting_info.disable[True]['settings']) for section in setting_info.disable[True]['sections']: self.randomized_list.extend(get_settings_from_section(section)) # Remove settings specified in the distribution self.randomized_list = [ x for x in self.randomized_list if x not in dist_keys ] for setting in list(self.randomized_list): if (setting == 'bridge_medallions' and self.settings.bridge != 'medallions') \ or (setting == 'bridge_stones' and self.settings.bridge != 'stones') \ or (setting == 'bridge_rewards' and self.settings.bridge != 'dungeons') \ or (setting == 'bridge_tokens' and self.settings.bridge != 'tokens') \ or (setting == 'lacs_medallions' and self.settings.lacs_condition != 'medallions') \ or (setting == 'lacs_stones' and self.settings.lacs_condition != 'stones') \ or (setting == 'lacs_rewards' and self.settings.lacs_condition != 'dungeons') \ or (setting == 'lacs_tokens' and self.settings.lacs_condition != 'tokens'): self.randomized_list.remove(setting) if self.settings.big_poe_count_random and 'big_poe_count' not in dist_keys: self.settings.big_poe_count = random.randint(1, 10) self.randomized_list.append('big_poe_count') if self.settings.starting_tod == 'random' and 'starting_tod' not in dist_keys: setting_info = get_setting_info('starting_tod') choices = [ ch for ch in setting_info.choices if ch not in ['default', 'random'] ] self.settings.starting_tod = random.choice(choices) self.randomized_list.append('starting_tod') if self.settings.starting_age == 'random' and 'starting_age' not in dist_keys: if self.settings.open_forest == 'closed': # adult is not compatible self.settings.starting_age = 'child' else: self.settings.starting_age = random.choice(['child', 'adult']) self.randomized_list.append('starting_age') if self.settings.chicken_count_random and 'chicken_count' not in dist_keys: self.settings.chicken_count = random.randint(0, 7) self.randomized_list.append('chicken_count') # Handle random Rainbow Bridge condition if self.settings.bridge == 'random': possible_bridge_requirements = [ "open", "medallions", "dungeons", "stones", "vanilla" ] self.settings.bridge = random.choice(possible_bridge_requirements) self.set_random_bridge_values() self.randomized_list.append('bridge') # Determine Ganon Trials trial_pool = list(self.skipped_trials) dist_chosen = self.distribution.configure_trials(trial_pool) dist_num_chosen = len(dist_chosen) if self.settings.trials_random and 'trials' not in dist_keys: self.settings.trials = dist_num_chosen + random.randint( 0, len(trial_pool)) self.randomized_list.append('trials') num_trials = int(self.settings.trials) choosen_trials = random.sample(trial_pool, num_trials - dist_num_chosen) for trial in self.skipped_trials: if trial not in choosen_trials and trial not in dist_chosen: self.skipped_trials[trial] = True # Determine MQ Dungeons dungeon_pool = list(self.dungeon_mq) dist_num_mq = self.distribution.configure_dungeons(self, dungeon_pool) if self.settings.mq_dungeons_random and 'mq_dungeons' not in dist_keys: for dungeon in dungeon_pool: self.dungeon_mq[dungeon] = random.choice([True, False]) self.settings.mq_dungeons = list( self.dungeon_mq.values()).count(True) self.randomized_list.append('mq_dungeons') else: mqd_picks = random.sample(dungeon_pool, self.settings.mq_dungeons - dist_num_mq) for dung in mqd_picks: self.dungeon_mq[dung] = True self.distribution.configure_randomized_settings(self)