def get(self, game_id, player_id): seedlines = [] lines = paramVal(self, "seed").split(",") game = Game.with_id(game_id) hist = Cache.getHist(game_id) if not hist: Cache.setHist(game_id, player_id, []) Cache.setPos(game_id, player_id, 189, -210) if not game: flags = lines[0].split("|") mode_opt = [f[5:] for f in flags if f.lower().startswith("mode=")] shared_opt = [ f[7:].split(" ") for f in flags if f.lower().startswith("shared=") ] mode = MultiplayerGameType.mk(mode_opt[0]) if mode_opt else None shared = shared_opt[0] if shared_opt else None game = Game.new(_mode=mode, _shared=shared, id=game_id) game.put() else: game.sanity_check() # cheap if game is short! for l in lines[1:]: line = l.split("|") if len(line) < 3: log.error("malformed seed line %s, skipping" % l) else: seedlines.append("%s:%s" % (line[0], Pickup.name(line[1], line[2]))) player = game.player(player_id) player.seed = "\n".join(seedlines) player.put() self.response.headers['Content-Type'] = 'text/plain' self.response.status = 200 self.response.out.write("ok")
def from_json(json): opts = MultiplayerOptions() opts.enabled = json.get("players", 1) > 1 opts.teams = json.get("teams", {}) if opts.enabled: opts.mode = MultiplayerGameType(json.get("coopGameMode", "None")) opts.cloned = json.get("coopGenMode") != "disjoint" if opts.cloned: opts.teams = {1: range(1, json.get("players", 1) + 1)} opts.dedup = bool(json.get("dedupShared", False)) opts.hints = bool(opts.cloned and json.get("syncHints")) opts.shared = enums_from_strlist(ShareType, json.get("syncShared", [])) return opts
def from_url(qparams): opts = MultiplayerOptions() opts.enabled = int(qparams.get("players", 1)) > 1 if opts.enabled: opts.mode = MultiplayerGameType(qparams.get("sync_mode", "None")) opts.cloned = qparams.get("sync_gen") != "disjoint" opts.hints = bool(opts.cloned and qparams.get("sync_hints")) opts.shared = enums_from_strlist(ShareType, qparams.getall("sync_shared")) teamsRaw = qparams.get("teams") if teamsRaw and opts.mode == MultiplayerGameType.SHARED and opts.cloned: cnt = 1 teams = {} for teamRaw in teamsRaw.split("|"): teams[cnt] = [int(p) for p in teamRaw.split(",")] cnt += 1 opts.teams = teams return opts
def get(self, game_id=101): game_id = int(game_id) if not debug: return redirect("/") game = Game.with_id(game_id) if game: game.clean_up() seedlines = [] seed = "mode=Shared|shared=Keys+Skills+Teleporters,-280256|EC|1|Glades,-1680104|EX|100|Grove,-12320248|EX|100|Forlorn,-10440008|EX|100|Misty,799776|EV|5|Glades,-120208|EC|1|Glades,1519708|SH|@Skill For Player 1@|Blackroot,1799708|KS|1|Blackroot,1959768|RB|9|Blackroot,-1560272|KS|1|Glades,-600244|EX|46|Glades,-3160308|HC|1|Glades,-2840236|EX|15|Glades,-3360288|MS|1|Glades,-2480208|EX|6|Glades,-2400212|AC|1|Glades,-1840228|HC|1|Glades,919772|KS|1|Glades,-2200184|KS|1|Glades,-1800156|KS|1|Glades,24|KS|1|Mapstone,2919744|KS|1|Blackroot,-1840196|SK|2|Glades,-800192|AC|1|Glades,-2080116|SK|14|Valley,-560160|EX|32|Grove,1479880|AC|1|Grove,599844|KS|1|Grove,2999904|RB|1|Grove,6999916|KS|1|Swamp,6159900|HC|1|Swamp,3639880|EX|27|Grove,5119584|MS|1|Grotto,6199596|MS|1|Grotto,5719620|HC|1|Grotto,5879616|KS|1|Grotto,6279880|KS|1|Swamp,5119900|EX|67|Swamp,39804|EX|9|Glades,28|EV|5|Mapstone,7839588|EX|51|Grotto,2999808|EC|1|Grove,3039696|SK|50|Blackroot,3119768|EX|33|Blackroot,-2200148|HC|1|Glades,-2240084|EX|53|Valley,4199828|EX|15|Grotto,32|AC|1|Mapstone,3439744|EX|44|Blackroot,-160096|EC|1|Grove,4239780|SK|5|Grotto,-480168|RB|13|Glades,-1560188|KS|1|Glades,-2160176|EX|50|Glades,3319936|KS|1|Grove,4759860|KS|1|Grotto,4319892|EX|82|Grotto,3639888|EC|1|Grove,5799932|EX|114|Swamp,4479832|EX|77|Grotto,5439640|EC|1|Grotto,5639752|EX|56|Grotto,0|EX|62|Grotto,4039612|AC|1|Grotto,3919624|EX|27|Grotto,4959628|EV|5|Grotto,4639628|EX|97|Grotto,4479568|EC|1|Grotto,7559600|EX|30|Grotto,3919688|EX|10|Blackroot,5399780|EX|32|Grotto,5119556|MS|1|Grotto,4439632|EX|40|Grotto,4359656|EX|52|Grotto,4919600|EX|97|Grotto,-1800088|EX|66|Valley,639888|EX|97|Grove,36|EV|5|Mapstone,2559800|EX|83|Glades,-2480280|EX|44|Glades,3199820|EC|1|Grove,1719892|RB|15|Grove,2599880|HC|1|Grove,4079964|EX|30|Swamp,4999892|KS|1|Swamp,5399808|KS|1|Grotto,5519856|EV|5|Grotto,3399820|EX|63|Grove,3279644|MS|1|Grotto,7199904|EV|5|Swamp,8599904|RB|0|Swamp,40|EX|99|Mapstone,799804|EX|22|Glades,6359836|EX|103|Swamp,4479704|EX|82|Grotto,5200140|AC|1|Ginso,5280264|KS|1|Ginso,5080304|MS|1|Ginso,5280296|EX|175|Ginso,5400100|EX|92|Ginso,6639952|KS|1|Swamp,2719900|EV|5|Grove,5320328|AC|1|Ginso,5320488|AC|1|Ginso,5080496|KS|1|Ginso,5400276|EC|1|Ginso,2759624|EV|5|Blackroot,959960|AC|1|Grove,6399872|EX|156|Swamp,4319860|EX|40|Grotto,4319676|AC|1|Blackroot,7679852|RB|0|Swamp,5359824|EX|148|Grotto,8839900|KS|1|Swamp,5160384|EX|118|Ginso,5280404|EX|153|Ginso,5360432|KS|1|Ginso,3879576|AC|1|Blackroot,3359580|KS|1|Blackroot,719620|KS|1|Blackroot,1759964|EX|125|Grove,2239640|AC|1|Blackroot,1240020|HC|1|Grove,559720|KS|1|Glades,39756|EX|73|Glades,-400240|RB|0|Glades,-3559936|EX|49|Valley,-4199936|HC|1|Valley,-3600088|AC|1|Valley,1839836|KS|1|Grove,3519820|KS|1|Grove,5919864|KS|1|Swamp,4199724|EX|171|Grotto,3559792|KS|1|Grotto,3359784|AC|1|Grove,-3200164|EX|155|Valley,3959588|KS|1|Grotto,7599824|KS|1|Swamp,6839792|EX|183|Swamp,7959788|HC|1|Swamp,8719856|EX|61|Swamp,4599508|KS|1|Blackroot,3039472|EV|5|Blackroot,5239456|EC|1|Blackroot,-4600020|MS|1|Valley,-5479948|EX|121|Sorrow,-6800032|KS|1|Misty,-8240012|EX|265|Misty,-2919980|AC|1|Valley,-5719844|EX|62|Sorrow,-5119796|EX|267|Sorrow,-4879680|EX|35|Sorrow,-5039728|RB|1|Sorrow,-5159700|MS|1|Sorrow,-5959772|KS|1|Sorrow,-9799980|EX|86|Misty,-10760004|RB|11|Misty,-10120036|EX|48|Misty,-10759968|HC|1|Misty,-4600188|EX|147|Valley,-4160080|EX|25|Valley,-4680068|RB|6|Valley,-3520100|KS|1|Valley,-5640092|EX|152|Valley,-6119704|EX|1|Sorrow,-4359680|EC|1|Sorrow,-8400124|EX|315|Misty,-7960144|EX|94|Misty,-9120036|EX|315|Misty,-7680144|AC|1|Misty,-11040068|AC|1|Misty,1720000|EC|1|Grove,2519668|EX|253|Blackroot,4560564|EC|1|Ginso,-6719712|EX|178|Sorrow,-6079672|EC|1|Sorrow,-6119656|RB|1|Sorrow,-6039640|EX|140|Sorrow,-6159632|EX|297|Sorrow,-6279608|EX|14|Sorrow,8|EX|9|Misty,44|AC|1|Mapstone,48|EV|5|Mapstone,-7040392|EX|62|Forlorn,-8440352|KS|1|Forlorn,-8920328|MS|1|Forlorn,-8880252|EX|256|Forlorn,-8720256|EX|154|Forlorn,5320660|EX|291|Ginso,5360732|AC|1|Ginso,5320824|AC|1|Ginso,5160864|KS|1|Ginso,4|EX|135|Ginso,6080608|AC|1|Ginso,-6799732|AC|1|Sorrow,-6319752|AC|1|Sorrow,-8160268|AC|1|Forlorn,-5160280|AC|1|Valley,-5400236|EX|236|Valley,-10839992|EX|284|Misty,7639816|AC|1|Swamp,-4559584|RB|6|Sorrow,-4159572|RB|13|Sorrow,-5479592|EX|382|Sorrow,-5919556|KS|1|Sorrow,-6280316|EV|5|Forlorn,12|EX|277|Forlorn,52|MS|1|Mapstone,1920384|KS|1|Horu,1480360|MS|1|Horu,2480400|EX|291|Horu,-6080316|AC|1|Forlorn,1880164|RB|12|Horu,2520192|AC|1|Horu,1600136|KS|1|Horu,-1919808|AC|1|Horu,-319852|AC|1|Horu,120164|EX|128|Horu,1280164|EX|115|Horu,960128|HC|1|Horu,3160244|EX|235|Horu,20|EC|1|Horu,1040112|AC|1|Horu,-8600356|AC|1|Forlorn,-6959592|EX|15|Sorrow,-6479528|HC|1|Sorrow,-4799416|EX|382|Sorrow,4680612|EV|5|Ginso,56|EX|322|Mapstone,-5159576|AC|1|Sorrow,16|EV|5|Sorrow,5040476|RB|21|Ginso,4559492|RB|19|Blackroot,399844|RB|19|Grove,-1680140|EV|5|Glades,9119928|EV|5|Swamp,2079568|EV|1|Blackroot,3279920|RB|17|Grove,-4600256|RB|21|Valley,-4440152|RB|21|Valley,919908|RB|17|Grove,1599920|RB|17|Grove,-11880100|RB|21|Misty,-5400104|EV|5|Valley,-6720040|RB|19|Misty,5039560|RB|17|Grotto,5280500|EV|5|Ginso,5160336|EV|5|Ginso" lines = seed.split(",") flags = lines[0].split("|") mode_opt = [f[5:] for f in flags if f.lower().startswith("mode=")] shared_opt = [ f[7:].split("+") for f in flags if f.lower().startswith("shared=") ] mode = MultiplayerGameType(mode_opt[0]) if mode_opt else None shared = shared_opt[0] if shared_opt else None for l in lines[1:]: line = l.split("|") if len(line) < 3: log.error("malformed seed line %s, skipping" % l) else: seedlines.append("%s:%s" % (line[0], Pickup.name(line[1], line[2]))) game = Game.new(_mode=mode, _shared=shared, id=game_id) game.put() for player_id in [1, 2, 3]: game = Game.with_id(game_id) hist = Cache.getHist(game_id) if not hist: Cache.setHist(game_id, player_id, []) Cache.setPos(game_id, player_id, 189, -210) player = game.player(player_id) player.seed = "\n".join(seedlines) player.put() url = uri_for("map-render", game_id=game_id, from_test=1) return redirect(url)
def get_mode(self): return MultiplayerGameType.mk( self.str_mode) or MultiplayerGameType.SIMUSOLO
def get_mode(self): return MultiplayerGameType.from_ndb(self.ndb_mode) def set_mode(self, mode): self.ndb_mode = mode.to_ndb()
def from_cli(self): parser = argparse.ArgumentParser() parser.add_argument("--output-dir", help="directory to put the seeds in", type=str, default=".") parser.add_argument( "--preset", help="Choose a preset group of paths for the generator to use") parser.add_argument( "--custom-logic", help= "Customize paths that the generator will use, comma-separated: %s" % ", ".join(vals(LogicPath))) parser.add_argument("--seed", help="Seed value (default 'test')", type=str, default="test") parser.add_argument( "--keymode", help= """Changes how the dungeon keys (The Water Vein, Gumon Seal, and Sunstone) are handled: Default: The dungeon keys are placed without any special consideration. Clues: For each 3 trees visited, the zone of a random dungeon key will be revealed Shards: The dungeon keys will be awarded after 3/5 shards are found LimitKeys: The Water Vein, Gumon Seal, and Sunstone will only appear at skill trees or event sources Free: The dungeon keys are given to the player upon picking up the first Energy Cell. """, type=str) # variations parser.add_argument("--hard", help="Enable hard mode", action="store_true") parser.add_argument("--ohko", help="Enable one-hit-ko mode", action="store_true") parser.add_argument("--zeroxp", help="Enable 0xp mode", action="store_true") parser.add_argument( "--starved", help= "Reduces the rate at which skills will appear when not required to advance", action="store_true") parser.add_argument( "--tp-starved", help= "Reduces the rate at which teleporters will appear early game when not required to advance", action="store_true") parser.add_argument( "--wall-starved", help= "Reduces the rate at which WallJump and Climb will appear early game when not required to advance", action="store_true") parser.add_argument( "--non-progressive-mapstones", help= "Map Stones will retain their behaviour from before v1.2, having their own unique drops", action="store_true") parser.add_argument( "--force-trees", help= "Prevent Ori from entering the final escape room until all skill trees have been visited", action="store_true") parser.add_argument( "--force-mapstones", help= "Prevent Ori from entering the final escape room until all mapstone altars have been activated", action="store_true") parser.add_argument("--entrance", help="Randomize entrances", action="store_true") parser.add_argument("--closed-dungeons", help="deactivate open mode within dungeons", action="store_true") parser.add_argument("--open-world", help="Activate open mode on the world map", action="store_true") parser.add_argument( "--bonus-pickups", help= "Adds some extra bonus pickups not balanced for competitive play", action="store_true") parser.add_argument( "--easy", help= "Add an extra copy of double jump, bash, stomp, glide, charge jump, dash, grenade, water, and wind", action="store_true") parser.add_argument( "--strict-mapstones", help= "Require a mapstone to be placed when a map monument becomes accessible", action="store_true") parser.add_argument( "--world-tour", help= "Prevent Ori from entering the final escape until collecting one relic from each of the zones in the world. Recommended default: 8", type=int) parser.add_argument( "--warmth-frags", help= "Prevent Ori from entering the final escape until collecting some number of warmth fragments. Recommended default: 40", type=int) # misc parser.add_argument( "--verbose-paths", help="print every logic path in the flagline for debug purposes", action="store_true") parser.add_argument("--exp-pool", help="Size of the experience pool (default 10000)", type=int, default=10000) parser.add_argument( "--extra-frags", help= """Sets the number of extra warmth fragments. Total frag number is still the value passed to --warmth-frags; --warmth-frags 40 --extra-frags 10 will place 40 total frags, 30 of which will be required to finish""", type=int, default=10) parser.add_argument( "--prefer-path-difficulty", help= "Increase the chances of putting items in more convenient (easy) or less convenient (hard) locations", choices=["easy", "hard"]) parser.add_argument( "--balanced", help= "Reduce the value of newly discovered locations for progression placements", action="store_true") parser.add_argument( "--force-cells", help= "Force health and energy cells to appear every N pickups, if they don't randomly", type=int, default=256) # anal TODO: IMPL parser.add_argument( "--analysis", help="Report stats on the skill order for all seeds generated", action="store_true") parser.add_argument( "--loc-analysis", help="Report stats on where skills are placed over multiple seeds", action="store_true") parser.add_argument("--count", help="Number of seeds to generate (default 1)", type=int, default=1) # sync parser.add_argument("--players", help="Player count for paired randomizer", type=int, default=1) parser.add_argument( "--tracking", help="Place a sync ID in a seed for tracking purposes", action="store_true") parser.add_argument( "--sync-id", help="Team identifier number for paired randomizer", type=int) parser.add_argument( "--shared-items", help= "What will be shared by sync, comma-separated: skills,worldevents,misc,teleporters,upgrades", default="skills,worldevents") parser.add_argument( "--share-mode", help= "How the server will handle shared pickups, one of: shared,swap,split,none", default="shared") parser.add_argument( "--cloned", help="Make a split cloned seed instead of seperate seeds", action="store_true") parser.add_argument( "--teams", help= "Cloned seeds only: define teams. Format: 1|2,3,4|5,6. Each player must appear once", type=str) parser.add_argument( "--hints", help= "Cloned seeds only: display a hint with the item category on a shared location instead of 'Warmth Returned'", action="store_true") parser.add_argument( "--do-reachability-analysis", help= "Analyze how many locations are opened by various progression items in various inventory states", action="store_true") args = parser.parse_args() """ path_diff = property(get_pathdiff, set_pathdiff) exp_pool = ndb.IntegerProperty(default=10000) balanced = ndb.BooleanProperty(default=True) tracking = ndb.BooleanProperty(default=True) players = ndb.IntegerProperty(default=1) sync = ndb.LocalStructuredProperty(MultiplayerOptions) frag_count = ndb.IntegerProperty(default=40) frag_extra = ndb.IntegerProperty(default=10) cell_freq = ndb.IntegerProperty(default=256) """ self.seed = args.seed if args.preset: self.logic_paths = presets[args.preset.capitalize()] elif args.custom_logic: self.logic_paths = enums_from_strlist(LogicPath, args.custom_logic.split(",")) else: self.logic_paths = presets["Standard"] self.key_mode = KeyMode.mk(args.keymode) or KeyMode.NONE # variations (help) varMap = { "zeroxp": "0XP", "non_progressive_mapstones": "NonProgressMapStones", "ohko": "OHKO", "force_trees": "ForceTrees", "starved": "Starved", "force_mapstones": "ForceMapStones", "entrance": "Entrance", "open_world": "OpenWorld", "easy": "DoubleSkills", "strict_mapstones": "StrictMapstones", "warmth_frags": "WarmthFrags", "world_tour": "WorldTour", "closed_dungeons": "ClosedDungeons", "tp_starved": "TPStarved", "wall_starved": "WallStarved" } self.variations = [] for argName, flagStr in varMap.iteritems(): if getattr(args, argName, False): v = Variation.mk(flagStr) if v: self.variations.append(v) else: log.warning("Failed to make a Variation from %s" % flagStr) if Variation.WORLD_TOUR in self.variations: self.relic_count = args.world_tour if Variation.WARMTH_FRAGMENTS in self.variations: self.frag_count = args.warmth_frags self.frag_extra = args.extra_frags #misc self.exp_pool = args.exp_pool if args.prefer_path_difficulty: if args.prefer_path_difficulty == "easy": self.path_diff = PathDifficulty.EASY else: self.path_diff = PathDifficulty.HARD else: self.path_diff = PathDifficulty.NORMAL self.balanced = args.balanced or False self.cell_freq = args.force_cells self.players = args.players self.tracking = args.tracking or False self.sync = CLIMultiOptions() if Variation.EXTRA_BONUS_PICKUPS in self.variations: self.pool_preset = "Extra Bonus" self.item_pool = { "TP|Grove": [1], "TP|Swamp": [1], "TP|Grotto": [1], "TP|Valley": [1], "TP|Sorrow": [1], "TP|Ginso": [1], "TP|Horu": [1], "TP|Forlorn": [1], "HC|1": [12], "EC|1": [14], "AC|1": [33], "RB|0": [3], "RB|1": [3], "RB|6": [5], "RB|9": [1], "RB|10": [1], "RB|11": [1], "RB|12": [5], "RB|13": [3], "RB|15": [3], "RB|31": [1], "RB|32": [1], "RB|33": [3], "BS|*": [4], "WP|*": [4, 8], } else: self.pool_preset = "Standard" self.item_pool = { "TP|Grove": [1], "TP|Swamp": [1], "TP|Grotto": [1], "TP|Valley": [1], "TP|Sorrow": [1], "TP|Ginso": [1], "TP|Horu": [1], "TP|Forlorn": [1], "HC|1": [12], "EC|1": [14], "AC|1": [33], "RB|0": [3], "RB|1": [3], "RB|6": [3], "RB|9": [1], "RB|10": [1], "RB|11": [1], "RB|12": [1], "RB|13": [3], "RB|15": [3], } if self.players > 1 or self.tracking: self.sync_id = args.sync_id or int(time.time() * 1000 % 1073741824) if self.players > 1: self.sync.enabled = True self.sync.mode = MultiplayerGameType.mk( args.share_mode) or MultiplayerGameType.SIMUSOLO self.sync.shared = enums_from_strlist(ShareType, args.shared_items.split(",")) self.sync.cloned = args.cloned or False if self.sync.cloned: self.sync.hints = args.hints or False if args.teams: cnt = 1 self.sync.teams = {} for team in args.teams.split("|"): self.sync.teams[cnt] = [ int(p) for p in team.split(",") ] cnt += 1 # todo: respect these LMAO self.do_analysis = args.analysis self.do_loc_analysis = args.loc_analysis self.repeat_count = args.count base_seed = self.seed[:] if self.do_analysis: key_items = [ "WallJump", "ChargeFlame", "DoubleJump", "Bash", "Stomp", "Glide", "Climb", "ChargeJump", "Dash", "Grenade", "GinsoKey", "ForlornKey", "HoruKey", "Water", "Wind", "TPForlorn", "TPGrotto", "TPSorrow", "TPGrove", "TPSwamp", "TPValley", "TPGinso", "TPHoru" ] info_by_group = defaultdict(defaultgroup) if self.do_loc_analysis: self.locationAnalysis = {} self.itemsToAnalyze = { "WallJump": 0, "ChargeFlame": 0, "DoubleJump": 0, "Bash": 0, "Stomp": 0, "Glide": 0, "Climb": 0, "ChargeJump": 0, "Dash": 0, "Grenade": 0, "GinsoKey": 0, "ForlornKey": 0, "HoruKey": 0, "Water": 0, "Wind": 0, "WaterVeinShard": 0, "GumonSealShard": 0, "SunstoneShard": 0, "TPForlorn": 0, "TPGrotto": 0, "TPSorrow": 0, "TPGrove": 0, "TPSwamp": 0, "TPValley": 0, "TPGinso": 0, "TPHoru": 0, "Relic": 0 } for i in range(1, 10): self.locationAnalysis["MapStone " + str(i)] = self.itemsToAnalyze.copy() self.locationAnalysis["MapStone " + str(i)]["Zone"] = "MapStone" for count in range(0, self.repeat_count): if self.repeat_count > 1: self.seed = "%s_%s" % (base_seed, count) if self.do_loc_analysis: print(self.seed) sg = SeedGenerator() if args.do_reachability_analysis: sg.do_reachability_analysis(self) return raw = sg.setSeedAndPlaceItems(self, preplaced={}) seeds = [] spoilers = [] if not raw: log.error("Couldn't build seed!") if self.do_loc_analysis: continue return player = 0 for player_raw in raw: player += 1 seed, spoiler = tuple(player_raw) if self.tracking: seed = "Sync%s.%s," % (self.sync_id, player) + seed seedfile = "randomizer_%s.dat" % player spoilerfile = "spoiler_%s.txt" % player if self.players == 1: seedfile = "randomizer" + str(count) + ".dat" spoilerfile = "spoiler" + str(count) + ".txt" if not self.do_analysis and not self.do_loc_analysis: with open(args.output_dir + "/" + seedfile, 'w') as f: f.write(seed) with open(args.output_dir + "/" + spoilerfile, 'w') as f: f.write(spoiler) if self.do_analysis: i = 0 for spoiler_line in spoiler.split("\n"): fl = first_line_pattern.match(spoiler_line) if fl: raw_group, raw_locs = fl.group(1, 2) i = int(raw_group) info_by_group[i]["seeds"] += 1 info_by_group[i]["locs"] += raw_locs.count(",") + 1 continue fp = forced_pickup_pattern.match(spoiler_line) if fp: info_by_group[i]["force"] += 1 for raw in fp.group(1).split(","): info_by_group[i]["forced"][raw.strip( " '")] += 1 continue nl = normal_line_pattern.match(spoiler_line) if nl: item = nl.group(1) if item in key_items: info_by_group[i]["items"][item] += 1 if self.do_analysis: # output = open("analysis.csv", 'w') # output.write("Location,Zone,WallJump,ChargeFlame,DoubleJump,Bash,Stomp,Glide,Climb,ChargeJump,Dash,Grenade,GinsoKey,ForlornKey,HoruKey,Water,Wind,WaterVeinShard,GumonSealShard,SunstoneShard,TPGrove,TPGrotto,TPSwamp,TPValley,TPSorrow,TPGinso,TPForlorn,TPHoru,Relic\n") for i, group in info_by_group.items(): seeds = float(group["seeds"]) print "%d (%d): " % (i, int(seeds)) print "\tkey items: [", for item, count in group["items"].items(): print '%s: %02.2f%%,' % (item, 100 * float(count) / seeds), print "]\n\tforced: [", for item, count in group["forced"].items(): print '%s: %02.2f%%,' % (item, 100 * float(count) / float(group["force"])), print "]\n\taverage locs", float(group['locs']) / seeds with open("anal.pickle", 'w') as out_file: pickle.dump(info_by_group, out_file) with open("analysis.csv", 'w') as out_file: out_file.write( "Group,Seeds,Forced,Locs,WallJump,ChargeFlame,DoubleJump,Bash,Stomp,Glide,Climb,ChargeJump,Dash,Grenade,GinsoKey,ForlornKey,HoruKey,Water,Wind,TPGrove,TPGrotto,TPSwamp,TPValley,TPSorrow,TPGinso,TPForlorn,TPHoru,WallJump,ChargeFlame,DoubleJump,Bash,Stomp,Glide,Climb,ChargeJump,Dash,Grenade,GinsoKey,ForlornKey,HoruKey,Water,Wind,TPGrove,TPGrotto,TPSwamp,TPValley,TPSorrow,TPGinso,TPForlorn,TPHoru,KS,EC,HC,MS,AC\n" ) for i, group in info_by_group.items(): seeds = float(group["seeds"]) line = [ i, int(seeds), int(group["force"]), "%02.2f" % (float(group["locs"]) / seeds) ] for key_item in [ "WallJump", "ChargeFlame", "DoubleJump", "Bash", "Stomp", "Glide", "Climb", "ChargeJump", "Dash", "Grenade", "GinsoKey", "ForlornKey", "HoruKey", "Water", "Wind", "TPGrove", "TPGrotto", "TPSwamp", "TPValley", "TPSorrow", "TPGinso", "TPForlorn", "TPHoru" ]: line.append( "%02.2f%%" % (100 * float(group["items"][key_item]) / seeds)) for forced_prog in [ "WallJump", "ChargeFlame", "DoubleJump", "Bash", "Stomp", "Glide", "Climb", "ChargeJump", "Dash", "Grenade", "GinsoKey", "ForlornKey", "HoruKey", "Water", "Wind", "TPGrove", "TPGrotto", "TPSwamp", "TPValley", "TPSorrow", "TPGinso", "TPForlorn", "TPHoru", "KS", "EC", "HC", "MS", "AC" ]: line.append( "%02.2f%%" % (100 * float(group["forced"][forced_prog]) / float(group["force"]) if group["forced"][forced_prog] else 0)) out_file.write(",".join([str(x) for x in line]) + '\n') if self.do_loc_analysis: output = open("analysis.csv", 'w') output.write( "Group,WallJump,ChargeFlame,DoubleJump,Bash,Stomp,Glide,Climb,ChargeJump,Dash,Grenade,Water,Wind,WaterVeinShard,GumonSealShard,SunstoneShard,TPGrove,TPGrotto,TPSwamp,TPValley,TPSorrow,TPGinso,TPForlorn,TPHoru,\n" ) for key in self.locationAnalysis.keys(): line = key + "," line += str(self.locationAnalysis[key]["Zone"]) + "," line += str(self.locationAnalysis[key]["WallJump"]) + "," line += str(self.locationAnalysis[key]["ChargeFlame"]) + "," line += str(self.locationAnalysis[key]["DoubleJump"]) + "," line += str(self.locationAnalysis[key]["Bash"]) + "," line += str(self.locationAnalysis[key]["Stomp"]) + "," line += str(self.locationAnalysis[key]["Glide"]) + "," line += str(self.locationAnalysis[key]["Climb"]) + "," line += str(self.locationAnalysis[key]["ChargeJump"]) + "," line += str(self.locationAnalysis[key]["Dash"]) + "," line += str(self.locationAnalysis[key]["Grenade"]) + "," line += str(self.locationAnalysis[key]["GinsoKey"]) + "," line += str(self.locationAnalysis[key]["ForlornKey"]) + "," line += str(self.locationAnalysis[key]["HoruKey"]) + "," line += str(self.locationAnalysis[key]["Water"]) + "," line += str(self.locationAnalysis[key]["Wind"]) + "," line += str(self.locationAnalysis[key]["WaterVeinShard"]) + "," line += str(self.locationAnalysis[key]["GumonSealShard"]) + "," line += str(self.locationAnalysis[key]["SunstoneShard"]) + "," line += str(self.locationAnalysis[key]["TPGrove"]) + "," line += str(self.locationAnalysis[key]["TPGrotto"]) + "," line += str(self.locationAnalysis[key]["TPSwamp"]) + "," line += str(self.locationAnalysis[key]["TPValley"]) + "," line += str(self.locationAnalysis[key]["TPSorrow"]) + "," line += str(self.locationAnalysis[key]["TPGinso"]) + "," line += str(self.locationAnalysis[key]["TPForlorn"]) + "," line += str(self.locationAnalysis[key]["TPHoru"]) + "," line += str(self.locationAnalysis[key]["Relic"]) output.write(line + "\n")