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 start(): args = parse_arguments(None) if is_bundled() and len(sys.argv) == 1: # for the bundled builds, if we have no arguments, the user # probably wants the gui. Users of the bundled build who want the command line # interface shouuld specify at least one option, possibly setting a value to a # default if they like all the defaults from Gui import guiMain close_console() guiMain() sys.exit(0) # ToDo: Validate files further than mere existance if not os.path.isfile(args.rom): input( 'Could not find valid base rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom) sys.exit(1) if any([ sprite is not None and not os.path.isfile(sprite) and not Sprite.get_sprite_from_name(sprite) for sprite in args.sprite.values() ]): input( 'Could not find link sprite sheet at given location. \nPress Enter to exit.' ) sys.exit(1) # set up logger loglevel = { 'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG }[args.loglevel] logging.basicConfig(format='%(message)s', level=loglevel) if args.gui: from Gui import guiMain guiMain(args) elif args.count is not None: seed = args.seed for _ in range(args.count): main(seed=seed, args=args) seed = get_seed() else: main(seed=args.seed, args=args)
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, callback=ERmain): 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}" ) if args.race: random.seed() # reset to time-based random source 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} >> " f"{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} >> " f"{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.create_diff = args.create_diff erargs.glitch_triforce = args.glitch_triforce 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] if args.log_output_path: 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 = '' 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, args.plando) 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 name_counter = Counter() 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], args.plando) if settings.sprite and not os.path.isfile( settings.sprite) and not Sprite.get_sprite_from_name( settings.sprite): logging.warning( f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist." ) if args.pre_roll: import yaml if path == args.weights: settings.name = f"Player{player}" elif not settings.name: settings.name = os.path.splitext( os.path.split(path)[-1])[0] if "-" not in settings.shuffle and settings.shuffle != "vanilla": settings.shuffle += f"-{random.randint(0, 2 ** 64)}" pre_rolled = dict() pre_rolled["original_seed_number"] = seed pre_rolled["original_seed_name"] = seedname pre_rolled["pre_rolled"] = vars(settings).copy() if "plando_items" in pre_rolled["pre_rolled"]: pre_rolled["pre_rolled"]["plando_items"] = [ item.to_dict() for item in pre_rolled["pre_rolled"] ["plando_items"] ] if "plando_connections" in pre_rolled["pre_rolled"]: pre_rolled["pre_rolled"]["plando_connections"] = [ connection.to_dict() for connection in pre_rolled["pre_rolled"]["plando_connections"] ] with open( os.path.join( args.outputpath if args.outputpath else ".", f"{os.path.split(path)[-1].split('.')[0]}_pre_rolled.yaml" ), "wt") as f: yaml.dump(pre_rolled, f) 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 path == args.weights: # if name came from the weights file, just use base player name erargs.name[player] = f"Player{player}" elif not erargs.name[ player]: # if name was not specified, generate it from filename erargs.name[player] = os.path.splitext(os.path.split(path)[-1])[0] erargs.name[player] = handle_name(erargs.name[player], player, name_counter) logging.info(erargs.name[player]) 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 all( type(value) != list for value in player_settings.values()): if len(player_settings.values()) > 1: important[option] = { player: value for player, value in player_settings.items() if player <= args.yaml_output } elif len(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) callback(erargs, seed)