Esempio n. 1
0
    def load_distribution(self):
        if self.enable_distribution_file:
            if self.distribution_file:
                try:
                    self.distribution = Distribution.from_file(
                        self, self.distribution_file)
                except FileNotFoundError:
                    logging.getLogger('').warning(
                        "Distribution file not found at %s" %
                        (self.distribution_file))
                    self.enable_distribution_file = False
            else:
                logging.getLogger('').warning(
                    "Plandomizer enabled, but no distribution file provided.")
                self.enable_distribution_file = False
        elif self.distribution_file:
            logging.getLogger('').warning(
                "Distribution file provided, but using it not enabled. "
                "Did you mean to set enable_distribution_file?")
        else:
            self.distribution = Distribution(self)

        self.reset_distribution()

        self.numeric_seed = self.get_numeric_seed()
Esempio n. 2
0
    def load_distribution(self):
        if self.enable_distribution_file:
            if self.distribution_file:
                try:
                    self.distribution = Distribution.from_file(
                        self, self.distribution_file)
                    self.using_distribution_file = True
                except FileNotFoundError:
                    logging.getLogger('').warning(
                        "Distribution file not found at %s" %
                        (self.distribution_file))
            else:
                logging.getLogger('').warning(
                    "Plandomizer enabled, but no distribution file provided.")
        elif self.distribution_file:
            logging.getLogger('').warning(
                "Distribution file provided, but using it not enabled. "
                "Did you mean to set enable_distribution_file?")
        else:
            self.distribution = Distribution(self)

        for location in self.disabled_locations:
            self.distribution.add_location(location, '#Junk')

        self.numeric_seed = self.get_numeric_seed()
 def load_distribution(self):
     if self.distribution_file is not None and self.distribution_file != '':
         try:
             self.distribution = Distribution.from_file(
                 self, self.distribution_file)
         except FileNotFoundError:
             logging.getLogger('').warning(
                 "Distribution file not found at %s" %
                 (self.distribution_file))
     else:
         self.distribution = Distribution(self)
     self.numeric_seed = self.get_numeric_seed()
Esempio n. 4
0
    def load_distribution(self):
        if self.enable_distribution_file and self.distribution_file is not None and self.distribution_file != '':
            try:
                self.distribution = Distribution.from_file(self, self.distribution_file)
            except FileNotFoundError:
                logging.getLogger('').warning("Distribution file not found at %s" % (self.distribution_file))
        else:
            self.distribution = Distribution(self)

        for location in self.disabled_locations:
            self.distribution.add_location(location, '#Junk')

        self.numeric_seed = self.get_numeric_seed()
Esempio n. 5
0
    def __init__(self, settings_dict):
        self.__dict__.update(settings_dict)
        for info in setting_infos:
            if info.name not in self.__dict__:
                self.__dict__[info.name] = info.default

        if self.world_count < 1:
            self.world_count = 1
        if self.world_count > 255:
            self.world_count = 255

        self.settings_string = self.get_settings_string()
        self.distribution = Distribution(self)
        self.update_seed(self.seed)
    def __init__(self, settings_dict):
        self.__dict__.update(settings_dict)
        for info in setting_infos:
            if info.name not in self.__dict__:
                self.__dict__[info.name] = info.default

        self.settings_string = self.get_settings_string()
        self.distribution = Distribution(self)
        self.update_seed(self.seed)
Esempio n. 7
0
class Settings:
    def get_settings_display(self):
        padding = 0
        for setting in filter(lambda s: s.shared, setting_infos):
            padding = max(len(setting.name), padding)
        padding += 2
        output = ''
        for setting in filter(lambda s: s.shared, setting_infos):
            name = setting.name + ': ' + ' ' * (padding - len(setting.name))
            if setting.type == list:
                val = ('\n' + (' ' * (padding + 2))).join(
                    self.__dict__[setting.name])
            else:
                val = str(self.__dict__[setting.name])
            output += name + val + '\n'
        return output

    def get_settings_string(self):
        bits = []
        for setting in filter(lambda s: s.shared and s.bitwidth > 0,
                              setting_infos):
            value = self.__dict__[setting.name]
            i_bits = []
            if setting.type == bool:
                i_bits = [1 if value else 0]
            if setting.type == str:
                try:
                    index = setting.choice_list.index(value)
                except ValueError:
                    index = setting.choice_list.index(setting.default)
                # https://stackoverflow.com/questions/10321978/integer-to-bitfield-as-a-list
                i_bits = [1 if digit == '1' else 0 for digit in bin(index)[2:]]
                i_bits.reverse()
            if setting.type == int:
                value = int(value)
                value = value - (setting.gui_params.get('min', 0))
                value = int(value / (setting.gui_params.get('step', 1)))
                value = min(value, (setting.gui_params.get('max', value)))
                # https://stackoverflow.com/questions/10321978/integer-to-bitfield-as-a-list
                i_bits = [1 if digit == '1' else 0 for digit in bin(value)[2:]]
                i_bits.reverse()
            if setting.type == list:
                if len(value) > len(setting.choice_list) / 2:
                    value = [
                        item for item in setting.choice_list
                        if item not in value
                    ]
                    terminal = [1] * setting.bitwidth
                else:
                    terminal = [0] * setting.bitwidth

                item_indexes = []
                for item in value:
                    try:
                        item_indexes.append(setting.choice_list.index(item))
                    except ValueError:
                        continue
                item_indexes.sort()
                for index in item_indexes:
                    item_bits = [
                        1 if digit == '1' else 0
                        for digit in bin(index + 1)[2:]
                    ]
                    item_bits.reverse()
                    item_bits += [0] * (setting.bitwidth - len(item_bits))
                    i_bits.extend(item_bits)
                i_bits.extend(terminal)

            # pad it
            i_bits += [0] * (setting.bitwidth - len(i_bits))
            bits += i_bits
        return bit_string_to_text(bits)

    def update_with_settings_string(self, text):
        bits = text_to_bit_string(text)

        for setting in filter(lambda s: s.shared and s.bitwidth > 0,
                              setting_infos):
            cur_bits = bits[:setting.bitwidth]
            bits = bits[setting.bitwidth:]
            value = None
            if setting.type == bool:
                value = True if cur_bits[0] == 1 else False
            if setting.type == str:
                index = 0
                for b in range(setting.bitwidth):
                    index |= cur_bits[b] << b
                value = setting.choice_list[index]
            if setting.type == int:
                value = 0
                for b in range(setting.bitwidth):
                    value |= cur_bits[b] << b
                value = value * setting.gui_params.get('step', 1)
                value = value + setting.gui_params.get('min', 0)
            if setting.type == list:
                value = []
                max_index = (1 << setting.bitwidth) - 1
                while True:
                    index = 0
                    for b in range(setting.bitwidth):
                        index |= cur_bits[b] << b

                    if index == 0:
                        break
                    if index == max_index:
                        value = [
                            item for item in setting.choice_list
                            if item not in value
                        ]
                        break

                    value.append(setting.choice_list[index - 1])
                    cur_bits = bits[:setting.bitwidth]
                    bits = bits[setting.bitwidth:]

            self.__dict__[setting.name] = value

        self.settings_string = self.get_settings_string()
        self.numeric_seed = self.get_numeric_seed()

    def get_numeric_seed(self):
        # salt seed with the settings, and hash to get a numeric seed
        distribution = json.dumps(
            self.distribution.to_json(include_output=False), sort_keys=True)
        full_string = self.settings_string + distribution + __version__ + self.seed
        return int(hashlib.sha256(full_string.encode('utf-8')).hexdigest(), 16)

    def sanitize_seed(self):
        # leave only alphanumeric and some punctuation
        self.seed = re.sub(r'[^a-zA-Z0-9_-]', '', self.seed, re.UNICODE)

    def update_seed(self, seed):
        if seed is None or seed == '':
            # https://stackoverflow.com/questions/2257441/random-string-generation-with-upper-case-letters-and-digits-in-python
            self.seed = ''.join(
                random_choices(string.ascii_uppercase + string.digits, k=10))
        else:
            self.seed = seed
        self.sanitize_seed()
        self.numeric_seed = self.get_numeric_seed()

    def update(self):
        self.settings_string = self.get_settings_string()
        self.numeric_seed = self.get_numeric_seed()

    def load_distribution(self):
        if self.enable_distribution_file:
            if self.distribution_file:
                try:
                    self.distribution = Distribution.from_file(
                        self, self.distribution_file)
                except FileNotFoundError:
                    logging.getLogger('').warning(
                        "Distribution file not found at %s" %
                        (self.distribution_file))
                    self.enable_distribution_file = False
            else:
                logging.getLogger('').warning(
                    "Plandomizer enabled, but no distribution file provided.")
                self.enable_distribution_file = False
        elif self.distribution_file:
            logging.getLogger('').warning(
                "Distribution file provided, but using it not enabled. "
                "Did you mean to set enable_distribution_file?")
        else:
            self.distribution = Distribution(self)

        self.reset_distribution()

        self.numeric_seed = self.get_numeric_seed()

    def reset_distribution(self):
        self.distribution.reset()

        for location in self.disabled_locations:
            self.distribution.add_location(location, '#Junk')

    def check_dependency(self, setting_name, check_random=True):
        return self.get_dependency(setting_name, check_random) == None

    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 remove_disabled(self):
        for info in setting_infos:
            if info.dependency != None:
                new_value = self.get_dependency(info.name)
                if new_value != None:
                    self.__dict__[info.name] = new_value
                    self._disabled.add(info.name)

        self.settings_string = self.get_settings_string()
        self.numeric_seed = self.get_numeric_seed()

    def resolve_random_settings(self, cosmetic):
        sorted_infos = list(setting_infos)
        sort_key = lambda info: 0 if info.dependency is None else 1
        sorted_infos.sort(key=sort_key)

        for info in sorted_infos:
            # only randomize cosmetics options or non-cosmetic
            if cosmetic == info.shared:
                continue

            if self.check_dependency(info.name, check_random=True):
                continue

            if 'randomize_key' in info.gui_params and self.__dict__[
                    info.gui_params['randomize_key']]:
                choices, weights = zip(*info.gui_params['distribution'])
                self.__dict__[info.name] = random_choices(choices,
                                                          weights=weights)[0]

    # add the settings as fields, and calculate information based on them
    def __init__(self, settings_dict):
        self.__dict__.update(settings_dict)
        for info in setting_infos:
            if info.name not in self.__dict__:
                self.__dict__[info.name] = info.default

        if self.world_count < 1:
            self.world_count = 1
        if self.world_count > 255:
            self.world_count = 255

        self._disabled = set()
        self.settings_string = self.get_settings_string()
        self.distribution = Distribution(self)
        self.update_seed(self.seed)

    def to_json(self):
        return {
            setting.name: self.__dict__[setting.name]
            for setting in setting_infos
            if setting.shared and setting.name not in self._disabled
        }