def gen_game(gen_options, race=False, owner=None, sid=None): try: target = tempfile.TemporaryDirectory() playercount = len(gen_options) seed = get_seed() random.seed(seed) if race: random.seed() # reset to time-based random source seedname = "M" + ( f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits)) erargs = parse_arguments(['--multi', str(playercount)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, playercount + 1) } # only so it can be overwrittin in mystery erargs.create_spoiler = not race erargs.race = race erargs.skip_playthrough = race erargs.outputname = seedname erargs.outputpath = target.name erargs.teams = 1 erargs.progression_balancing = {} erargs.create_diff = True name_counter = Counter() for player, (playerfile, settings) in enumerate(gen_options.items(), 1): for k, v in settings.items(): if v is not None: getattr(erargs, k)[player] = v if not erargs.name[player]: erargs.name[player] = os.path.splitext( os.path.split(playerfile)[-1])[0] erargs.name[player] = handle_name(erargs.name[player], player, name_counter) erargs.names = ",".join(erargs.name[i] for i in range(1, playercount + 1)) del (erargs.name) erargs.skip_progression_balancing = { player: not balanced for player, balanced in erargs.progression_balancing.items() } del (erargs.progression_balancing) ERmain(erargs, seed) return upload_to_db(target.name, owner, sid, race) except BaseException as e: if sid: with db_session: gen = Generation.get(id=sid) if gen is not None: gen.state = STATE_ERROR gen.meta = (e.__class__.__name__ + ": " + str(e)).encode() raise
def gen(gen_options, race=False): target = tempfile.TemporaryDirectory() with target: playercount = len(gen_options) seed = get_seed() random.seed(seed) if race: random.seed() # reset to time-based random source seedname = "M" + ( f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits)) erargs = parse_arguments(['--multi', str(playercount)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, playercount + 1) } # only so it can be overwrittin in mystery erargs.create_spoiler = not race erargs.race = race erargs.skip_playthrough = race erargs.outputname = seedname erargs.outputpath = target.name erargs.teams = 1 erargs.progression_balancing = {} erargs.create_diff = True for player, (playerfile, settings) in enumerate(gen_options.items(), 1): for k, v in vars(settings).items(): if v is not None: getattr(erargs, k)[player] = v if not erargs.name[player]: erargs.name[player] = os.path.split(playerfile)[-1].split( ".")[0] erargs.names = ",".join(erargs.name[i] for i in range(1, playercount + 1)) del (erargs.name) erargs.skip_progression_balancing = { player: not balanced for player, balanced in erargs.progression_balancing.items() } del (erargs.progression_balancing) ERmain(erargs, seed) return upload_to_db(target.name)
def main(args=None): if not args: args = mystery_argparse() seed = get_seed(args.seed) random.seed(seed) seedname = "M" + (f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits)) print(f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}") weights_cache = {} if args.weights: try: weights_cache[args.weights] = get_weights(args.weights) except Exception as e: raise ValueError(f"File {args.weights} is destroyed. Please fix your yaml.") from e print(f"Weights: {args.weights} >> {get_choice('description', weights_cache[args.weights], 'No description specified')}") if args.meta: try: weights_cache[args.meta] = get_weights(args.meta) except Exception as e: raise ValueError(f"File {args.meta} is destroyed. Please fix your yaml.") from e meta_weights = weights_cache[args.meta] print(f"Meta: {args.meta} >> {get_choice('meta_description', meta_weights, 'No description specified')}") if args.samesettings: raise Exception("Cannot mix --samesettings with --meta") for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if path: try: if path not in weights_cache: weights_cache[path] = get_weights(path) print(f"P{player} Weights: {path} >> {get_choice('description', weights_cache[path], 'No description specified')}") except Exception as e: raise ValueError(f"File {path} is destroyed. Please fix your yaml.") from e erargs = parse_arguments(['--multi', str(args.multi)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, args.multi + 1)} # only so it can be overwrittin in mystery erargs.create_spoiler = args.create_spoiler erargs.race = args.race erargs.skip_playthrough = args.skip_playthrough erargs.outputname = seedname erargs.outputpath = args.outputpath erargs.teams = args.teams erargs.progression_balancing = {} # set up logger if args.loglevel: erargs.loglevel = args.loglevel loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[erargs.loglevel] import sys class LoggerWriter(object): def __init__(self, writer): self._writer = writer self._msg = '' def write(self, message): self._msg = self._msg + message while '\n' in self._msg: pos = self._msg.find('\n') self._writer(self._msg[:pos]) self._msg = self._msg[pos + 1:] def flush(self): if self._msg != '': self._writer(self._msg) self._msg = '' if args.log_output_path: log = logging.getLogger("stderr") log.addHandler(logging.StreamHandler()) sys.stderr = LoggerWriter(log.error) os.makedirs(args.log_output_path, exist_ok=True) logging.basicConfig(format='%(message)s', level=loglevel, filename=os.path.join(args.log_output_path, f"{seed}.log")) else: logging.basicConfig(format='%(message)s', level=loglevel) if args.rom: erargs.rom = args.rom if args.enemizercli: erargs.enemizercli = args.enemizercli settings_cache = {k: (roll_settings(v) if args.samesettings else None) for k, v in weights_cache.items()} player_path_cache = {} for player in range(1, args.multi + 1): player_path_cache[player] = getattr(args, f'p{player}') if getattr(args, f'p{player}') else args.weights if args.meta: for player, path in player_path_cache.items(): weights_cache[path].setdefault("meta_ignore", []) meta_weights = weights_cache[args.meta] for key in meta_weights: option = get_choice(key, meta_weights) if option is not None: for player, path in player_path_cache.items(): players_meta = weights_cache[path].get("meta_ignore", []) if key not in players_meta: weights_cache[path][key] = option elif type(players_meta) == dict and players_meta[key] and option not in players_meta[key]: weights_cache[path][key] = option for player in range(1, args.multi + 1): path = player_path_cache[player] if path: try: settings = settings_cache[path] if settings_cache[path] else roll_settings(weights_cache[path]) if settings.sprite is not None and not os.path.isfile(settings.sprite) and not get_sprite_from_name(settings.sprite): logging.warning( f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist.") for k, v in vars(settings).items(): if v is not None: getattr(erargs, k)[player] = v except Exception as e: raise ValueError(f"File {path} is destroyed. Please fix your yaml.") from e else: raise RuntimeError(f'No weights specified for player {player}') if not erargs.name[player]: erargs.name[player] = os.path.split(path)[-1].split(".")[0] if args.weights: erargs.names = "" else: erargs.names = ",".join(erargs.name[i] for i in range(1, args.multi + 1)) del (erargs.name) if args.yaml_output: import yaml important = {} for option, player_settings in vars(erargs).items(): if type(player_settings) == dict: if len(set(player_settings.values())) > 1: important[option] = {player: value for player, value in player_settings.items() if player <= args.yaml_output} elif len(set(player_settings.values())) > 0: important[option] = player_settings[1] else: logging.debug(f"No player settings defined for option '{option}'") else: if player_settings != "": # is not empty name important[option] = player_settings else: logging.debug(f"No player settings defined for option '{option}'") if args.outputpath: os.makedirs(args.outputpath, exist_ok=True) with open(os.path.join(args.outputpath if args.outputpath else ".", f"mystery_result_{seed}.yaml"), "wt") as f: yaml.dump(important, f) erargs.skip_progression_balancing = {player: not balanced for player, balanced in erargs.progression_balancing.items()} del (erargs.progression_balancing) ERmain(erargs, seed)
def gen_game(gen_options, meta: TypeOptional[Dict[str, object]] = None, owner=None, sid=None): if not meta: meta: Dict[str, object] = {} meta.setdefault("hint_cost", 10) race = meta.get("race", False) del (meta["race"]) plando_options = meta.get("plando", {"bosses", "items", "connections", "texts"}) del (meta["plando_options"]) try: target = tempfile.TemporaryDirectory() playercount = len(gen_options) seed = get_seed() random.seed(seed) if race: random.seed() # reset to time-based random source seedname = "W" + ( f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits)) erargs = parse_arguments(['--multi', str(playercount)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, playercount + 1) } # only so it can be overwrittin in mystery erargs.spoiler = 0 if race else 2 erargs.race = race erargs.outputname = seedname erargs.outputpath = target.name erargs.teams = 1 erargs.plando_options = ", ".join(plando_options) name_counter = Counter() for player, (playerfile, settings) in enumerate(gen_options.items(), 1): for k, v in settings.items(): if v is not None: if hasattr(erargs, k): getattr(erargs, k)[player] = v else: setattr(erargs, k, {player: v}) if not erargs.name[player]: erargs.name[player] = os.path.splitext( os.path.split(playerfile)[-1])[0] erargs.name[player] = handle_name(erargs.name[player], player, name_counter) if len(set(erargs.name.values())) != len(erargs.name): raise Exception( f"Names have to be unique. Names: {Counter(erargs.name.values())}" ) ERmain(erargs, seed, baked_server_options=meta) return upload_to_db(target.name, sid, owner, race) except BaseException as e: if sid: with db_session: gen = Generation.get(id=sid) if gen is not None: gen.state = STATE_ERROR meta = json.loads(gen.meta) meta["error"] = (e.__class__.__name__ + ": " + str(e)) gen.meta = json.dumps(meta) commit() raise
def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) multiargs, _ = parser.parse_known_args() parser = argparse.ArgumentParser() parser.add_argument( '--weights', help= 'Path to the weights file to use for rolling game settings, urls are also valid' ) parser.add_argument( '--samesettings', help='Rolls settings per weights file rather than per player', action='store_true') parser.add_argument('--seed', help='Define seed number to generate.', type=int) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--teams', default=1, type=lambda value: max(int(value), 1)) parser.add_argument('--create_spoiler', action='store_true') parser.add_argument('--skip_playthrough', action='store_true') parser.add_argument('--rom') parser.add_argument('--enemizercli') parser.add_argument('--outputpath') parser.add_argument('--race', action='store_true') parser.add_argument('--meta', default=None) parser.add_argument('--log_output_path', help='Path to store output log') parser.add_argument('--loglevel', default='info', help='Sets log level') parser.add_argument( '--yaml_output', default=0, type=lambda value: min(max(int(value), 0), 255), help= 'Output rolled mystery results to yaml up to specified number (made for async multiworld)' ) for player in range(1, multiargs.multi + 1): parser.add_argument(f'--p{player}', help=argparse.SUPPRESS) args = parser.parse_args() if args.seed is None: random.seed(None) seed = random.randint(0, 999999999) else: seed = args.seed random.seed(seed) seedname = "M" + (f"{random.randint(0, 999999999)}".zfill(9)) print( f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}" ) weights_cache = {} if args.weights: try: weights_cache[args.weights] = get_weights(args.weights) except Exception as e: raise ValueError( f"File {args.weights} is destroyed. Please fix your yaml." ) from e print( f"Weights: {args.weights} >> {weights_cache[args.weights]['description']}" ) if args.meta: try: weights_cache[args.meta] = get_weights(args.meta) except Exception as e: raise ValueError( f"File {args.meta} is destroyed. Please fix your yaml.") from e meta_weights = weights_cache[args.meta] print(f"Meta: {args.meta} >> {meta_weights['meta_description']}") if args.samesettings: raise Exception("Cannot mix --samesettings with --meta") for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if path: try: if path not in weights_cache: weights_cache[path] = get_weights(path) print( f"P{player} Weights: {path} >> {weights_cache[path]['description']}" ) except Exception as e: raise ValueError( f"File {path} is destroyed. Please fix your yaml.") from e erargs = parse_arguments(['--multi', str(args.multi)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, args.multi + 1) } # only so it can be overwrittin in mystery erargs.create_spoiler = args.create_spoiler erargs.race = args.race erargs.skip_playthrough = args.skip_playthrough erargs.outputname = seedname erargs.outputpath = args.outputpath erargs.teams = args.teams erargs.progression_balancing = {} # set up logger if args.loglevel: erargs.loglevel = args.loglevel loglevel = { 'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG }[erargs.loglevel] import sys class LoggerWriter(object): def __init__(self, writer): self._writer = writer self._msg = '' def write(self, message): self._msg = self._msg + message while '\n' in self._msg: pos = self._msg.find('\n') self._writer(self._msg[:pos]) self._msg = self._msg[pos + 1:] def flush(self): if self._msg != '': self._writer(self._msg) self._msg = '' if args.log_output_path: log = logging.getLogger("stderr") log.addHandler(logging.StreamHandler()) sys.stderr = LoggerWriter(log.error) os.makedirs(args.log_output_path, exist_ok=True) logging.basicConfig(format='%(message)s', level=loglevel, filename=os.path.join(args.log_output_path, f"{seed}.log")) else: logging.basicConfig(format='%(message)s', level=loglevel) if args.rom: erargs.rom = args.rom if args.enemizercli: erargs.enemizercli = args.enemizercli settings_cache = { k: (roll_settings(v) if args.samesettings else None) for k, v in weights_cache.items() } player_path_cache = {} for player in range(1, args.multi + 1): player_path_cache[player] = getattr(args, f'p{player}') if getattr( args, f'p{player}') else args.weights if args.meta: for player, path in player_path_cache.items(): weights_cache[path].setdefault("meta_ignore", []) meta_weights = weights_cache[args.meta] for key in meta_weights: option = get_choice(key, meta_weights) if option is not None: for player, path in player_path_cache.items(): players_meta = weights_cache[path].get("meta_ignore", []) if key not in players_meta: weights_cache[path][key] = option elif type(players_meta) == dict and players_meta[ key] and option not in players_meta[key]: weights_cache[path][key] = option for player in range(1, args.multi + 1): path = player_path_cache[player] if path: try: settings = settings_cache[path] if settings_cache[ path] else roll_settings(weights_cache[path]) if settings.sprite is not None and not os.path.isfile( settings.sprite) and not get_sprite_from_name( settings.sprite): logging.warning( f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist." ) for k, v in vars(settings).items(): if v is not None: getattr(erargs, k)[player] = v except Exception as e: raise ValueError( f"File {path} is destroyed. Please fix your yaml.") from e else: raise RuntimeError(f'No weights specified for player {player}') if not erargs.name[player]: erargs.name[player] = os.path.split(path)[-1].split(".")[0] if args.weights: erargs.names = "" else: erargs.names = ",".join(erargs.name[i] for i in range(1, args.multi + 1)) del (erargs.name) if args.yaml_output: import yaml important = {} for option, player_settings in vars(erargs).items(): if type(player_settings) == dict: if len(set(player_settings.values())) > 1: important[option] = { player: value for player, value in player_settings.items() if player <= args.yaml_output } elif len(set(player_settings.values())) > 0: important[option] = player_settings[1] else: logging.debug( f"No player settings defined for option '{option}'") else: if player_settings != "": # is not empty name important[option] = player_settings else: logging.debug( f"No player settings defined for option '{option}'") if args.outputpath: os.makedirs(args.outputpath, exist_ok=True) with open( os.path.join(args.outputpath if args.outputpath else ".", f"mystery_result_{seed}.yaml"), "wt") as f: yaml.dump(important, f) erargs.skip_progression_balancing = { player: not balanced for player, balanced in erargs.progression_balancing.items() } del (erargs.progression_balancing) ERmain(erargs, seed)
def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) multiargs, _ = parser.parse_known_args() parser = argparse.ArgumentParser() parser.add_argument('--weights', help='Path to the weights file to use for rolling game settings, urls are also valid') parser.add_argument('--samesettings', help='Rolls settings per weights file rather than per player', action='store_true') parser.add_argument('--seed', help='Define seed number to generate.', type=int) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--teams', default=1, type=lambda value: max(int(value), 1)) parser.add_argument('--create_spoiler', action='store_true') parser.add_argument('--rom') parser.add_argument('--enemizercli') parser.add_argument('--outputpath') parser.add_argument('--race', action='store_true') parser.add_argument('--meta', default=None) for player in range(1, multiargs.multi + 1): parser.add_argument(f'--p{player}', help=argparse.SUPPRESS) args = parser.parse_args() if args.seed is None: random.seed(None) seed = random.randint(0, 999999999) else: seed = args.seed random.seed(seed) seedname = "M"+(f"{random.randint(0, 999999999)}".zfill(9)) print(f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}") weights_cache = {} if args.weights: try: weights_cache[args.weights] = get_weights(args.weights) except Exception as e: raise ValueError(f"File {args.weights} is destroyed. Please fix your yaml.") from e print(f"Weights: {args.weights} >> {weights_cache[args.weights]['description']}") if args.meta: try: weights_cache[args.meta] = get_weights(args.meta) except Exception as e: raise ValueError(f"File {args.meta} is destroyed. Please fix your yaml.") from e print(f"Meta: {args.meta} >> {weights_cache[args.meta]['meta_description']}") if args.samesettings: raise Exception("Cannot mix --samesettings with --meta") for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if path: try: if path not in weights_cache: weights_cache[path] = get_weights(path) print(f"P{player} Weights: {path} >> {weights_cache[path]['description']}") except Exception as e: raise ValueError(f"File {path} is destroyed. Please fix your yaml.") from e erargs = parse_arguments(['--multi', str(args.multi)]) erargs.seed = seed erargs.name = {x: "" for x in range(1, args.multi + 1)} # only so it can be overwrittin in mystery erargs.create_spoiler = args.create_spoiler erargs.race = args.race erargs.outputname = seedname erargs.outputpath = args.outputpath erargs.teams = args.teams # set up logger loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[erargs.loglevel] logging.basicConfig(format='%(message)s', level=loglevel) if args.rom: erargs.rom = args.rom if args.enemizercli: erargs.enemizercli = args.enemizercli settings_cache = {k: (roll_settings(v) if args.samesettings else None) for k, v in weights_cache.items()} player_path_cache = {} for player in range(1, args.multi + 1): player_path_cache[player] = getattr(args, f'p{player}') if getattr(args, f'p{player}') else args.weights if args.meta: for player, path in player_path_cache.items(): weights_cache[path].setdefault("meta_ignore", []) meta_weights = weights_cache[args.meta] for key in meta_weights: option = get_choice(key, meta_weights) if option is not None: for player, path in player_path_cache.items(): players_meta = weights_cache[path]["meta_ignore"] if key not in players_meta: weights_cache[path][key] = option elif type(players_meta) == dict and option not in players_meta[key]: weights_cache[path][key] = option for player in range(1, args.multi + 1): path = player_path_cache[player] if path: try: settings = settings_cache[path] if settings_cache[path] else roll_settings(weights_cache[path]) if settings.sprite is not None and not os.path.isfile(settings.sprite) and not get_sprite_from_name(settings.sprite): logging.warning( f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist.") for k, v in vars(settings).items(): if v is not None: getattr(erargs, k)[player] = v except Exception as e: raise ValueError(f"File {path} is destroyed. Please fix your yaml.") from e else: raise RuntimeError(f'No weights specified for player {player}') if not erargs.name[player]: erargs.name[player] = os.path.split(path)[-1].split(".")[0] if args.samesettings: erargs.names = "" else: erargs.names = ",".join(erargs.name[i] for i in range(1, args.multi + 1)) del (erargs.name) ERmain(erargs, seed)
def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) multiargs, _ = parser.parse_known_args() parser = argparse.ArgumentParser() parser.add_argument( '--weights', help= 'Path to the weights file to use for rolling game settings, urls are also valid' ) parser.add_argument( '--samesettings', help='Rolls settings per weights file rather than per player', action='store_true') parser.add_argument('--seed', help='Define seed number to generate.', type=int) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--names', default='') parser.add_argument('--teams', default=1, type=lambda value: max(int(value), 1)) parser.add_argument('--create_spoiler', action='store_true') parser.add_argument('--rom') parser.add_argument('--enemizercli') parser.add_argument('--outputpath') for player in range(1, multiargs.multi + 1): parser.add_argument(f'--p{player}', help=argparse.SUPPRESS) args = parser.parse_args() if args.seed is None: random.seed(None) seed = random.randint(0, 999999999) else: seed = args.seed random.seed(seed) seedname = f'M{random.randint(0, 999999999)}' print( f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}" ) weights_cache = {} if args.weights: weights_cache[args.weights] = get_weights(args.weights) print( f"Weights: {args.weights} >> {weights_cache[args.weights]['description']}" ) for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if path: if path not in weights_cache: weights_cache[path] = get_weights(path) print( f"P{player} Weights: {path} >> {weights_cache[path]['description']}" ) erargs = parse_arguments(['--multi', str(args.multi)]) erargs.seed = seed erargs.names = args.names erargs.create_spoiler = args.create_spoiler erargs.race = True erargs.outputname = seedname erargs.outputpath = args.outputpath if args.rom: erargs.rom = args.rom if args.enemizercli: erargs.enemizercli = args.enemizercli settings_cache = { k: (roll_settings(v) if args.samesettings else None) for k, v in weights_cache.items() } for player in range(1, args.multi + 1): path = getattr(args, f'p{player}') if getattr( args, f'p{player}') else args.weights if path: settings = settings_cache[path] if settings_cache[ path] else roll_settings(weights_cache[path]) for k, v in vars(settings).items(): if v is not None: getattr(erargs, k)[player] = v else: raise RuntimeError(f'No weights specified for player {player}') # set up logger loglevel = { 'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG }[erargs.loglevel] logging.basicConfig(format='%(message)s', level=loglevel) ERmain(erargs, seed)