From 4ee6b9ea532baa0bb6cabe3839941a3731314962 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Tue, 19 Mar 2024 13:15:21 -0400 Subject: [PATCH 01/27] Update entrance rando description to discuss seed groups --- worlds/tunic/options.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/worlds/tunic/options.py b/worlds/tunic/options.py index 779e632326db..bf19fce4c9e1 100644 --- a/worlds/tunic/options.py +++ b/worlds/tunic/options.py @@ -105,9 +105,12 @@ class ExtraHexagonPercentage(Range): class EntranceRando(TextChoice): - """Randomize the connections between scenes. - You can choose a custom seed by editing this option. - A small, very lost fox on a big adventure.""" + """ + Randomize the connections between scenes. + If you set this to a value besides true or false, that value will be used as a custom seed. + Every player who uses the same seed will have the same entrances, choosing the most restrictive settings among these players for the purpose of pairing entrances. + A small, very lost fox on a big adventure. + """ internal_name = "entrance_rando" display_name = "Entrance Rando" alias_false = 0 From f6bb6b2f7bcfae03a476d510104e752cda6e6bd0 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Tue, 19 Mar 2024 13:42:23 -0400 Subject: [PATCH 02/27] Starting off, setting up some names --- worlds/tunic/er_scripts.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 291cd7b3310e..050624512c9c 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -188,10 +188,15 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: two_plus: List[Portal] = [] logic_rules = world.options.logic_rules.value player_name = world.multiworld.get_player_name(world.player) + fixed_shop = world.options.fixed_shop + laurels_location = world.options.laurels_location + # check seed group, sync up entrance-altering settings + # for player in world.multiworld.get_players() + shop_scenes: Set[str] = set() shop_count = 6 - if world.options.fixed_shop.value: + if fixed_shop: shop_count = 1 shop_scenes.add("Overworld Redux") @@ -328,7 +333,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: # need to plando fairy cave, or it could end up laurels locked # fix this later to be random after adding some item logic to dependent regions - if world.options.laurels_location == "10_fairies" and not hasattr(world.multiworld, "re_gen_passthrough"): + if laurels_location == "10_fairies" and not hasattr(world.multiworld, "re_gen_passthrough"): portal1 = None portal2 = None for portal in two_plus: @@ -349,7 +354,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: two_plus.remove(portal1) dead_ends.remove(portal2) - if world.options.fixed_shop and not hasattr(world.multiworld, "re_gen_passthrough"): + if fixed_shop and not hasattr(world.multiworld, "re_gen_passthrough"): portal1 = None for portal in two_plus: if portal.scene_destination() == "Overworld Redux, Windmill_": @@ -363,6 +368,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: two_plus.remove(portal1) random_object: Random = world.random + # use the seed given in the options to shuffle the portals if world.options.entrance_rando.value != 1: random_object = Random(world.options.entrance_rando.value) # we want to start by making sure every region is accessible From c626f0054c67641673305f7b3b5163f75d72053c Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Tue, 19 Mar 2024 20:55:17 -0400 Subject: [PATCH 03/27] It lives --- worlds/tunic/__init__.py | 34 ++++++++++++++++++++++++++++++++-- worlds/tunic/er_rules.py | 3 ++- worlds/tunic/er_scripts.py | 14 ++++++++++---- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index c4b1bbec8ea3..9fee5b741fc6 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -1,6 +1,6 @@ -from typing import Dict, List, Any +from typing import Dict, List, Any, Tuple, TypedDict -from BaseClasses import Region, Location, Item, Tutorial, ItemClassification +from BaseClasses import Region, Location, Item, Tutorial, ItemClassification, MultiWorld from .items import item_name_to_id, item_table, item_name_groups, fool_tiers, filler_items, slot_data_item_names from .locations import location_table, location_name_groups, location_name_to_id, hexagon_locations from .rules import set_location_rules, set_region_rules, randomize_ability_unlocks, gold_hexagon @@ -35,6 +35,12 @@ class TunicLocation(Location): game: str = "TUNIC" +class SeedGroup(TypedDict): + logic_rules: int # logic rules value + laurels_at_10_fairies: bool # laurels location value + fixed_shop: bool # fixed shop value + + class TunicWorld(World): """ Explore a land filled with lost legends, ancient powers, and ferocious monsters in TUNIC, an isometric action game @@ -57,6 +63,7 @@ class TunicWorld(World): slot_data_items: List[TunicItem] tunic_portal_pairs: Dict[str, str] er_portal_hints: Dict[int, str] + seed_groups: Dict[str, SeedGroup] = {} def generate_early(self) -> None: # Universal tracker stuff, shouldn't do anything in standard gen @@ -73,6 +80,29 @@ def generate_early(self) -> None: self.options.hexagon_quest.value = passthrough["hexagon_quest"] self.options.entrance_rando.value = passthrough["entrance_rando"] + @classmethod + def stage_generate_early(cls, multiworld: MultiWorld) -> None: + tunc_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") + for tunc in tunc_worlds: + if isinstance(tunc.options.entrance_rando.value, str): + group = tunc.options.entrance_rando.value + # if this is the first world in the group, set the rules equal to its rules + if group not in cls.seed_groups: + cls.seed_groups[group] = SeedGroup(logic_rules=tunc.options.logic_rules.value, + laurels_at_10_fairies=tunc.options.laurels_location == 3, + fixed_shop=bool(tunc.options.fixed_shop)) + else: + # lower value is more restrictive + if tunc.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: + print("restricting logic rules") + cls.seed_groups[group]["logic_rules"] = tunc.options.logic_rules.value + if tunc.options.laurels_location == 3: + print("restricting for laurels location") + cls.seed_groups[group]["laurels_at_10_fairies"] = True + if tunc.options.fixed_shop: + print("restricting for fixed shop") + cls.seed_groups[group]["fixed_shop"] = True + def create_item(self, name: str) -> TunicItem: item_data = item_table[name] return TunicItem(name, item_data.classification, self.item_name_to_id[name], self.player) diff --git a/worlds/tunic/er_rules.py b/worlds/tunic/er_rules.py index fec6635422ac..6fe0e37f0753 100644 --- a/worlds/tunic/er_rules.py +++ b/worlds/tunic/er_rules.py @@ -627,7 +627,8 @@ def set_er_region_rules(world: "TunicWorld", ability_unlocks: Dict[str, int], re # connecting the regions portals are in to other portals you can access via ladder storage # using has_stick instead of can_ladder_storage since it's already checking the logic rules - if options.logic_rules == "unrestricted": + # todo: unfalse this when merging with ladder branch + if options.logic_rules == "unrestricted" and False: def get_paired_region(portal_sd: str) -> str: for portal1, portal2 in portal_pairs.items(): if portal1.scene_destination() == portal_sd: diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 050624512c9c..f8826c5a3cea 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -186,13 +186,16 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: portal_pairs: Dict[Portal, Portal] = {} dead_ends: List[Portal] = [] two_plus: List[Portal] = [] - logic_rules = world.options.logic_rules.value player_name = world.multiworld.get_player_name(world.player) + logic_rules = world.options.logic_rules.value fixed_shop = world.options.fixed_shop laurels_location = world.options.laurels_location - # check seed group, sync up entrance-altering settings - # for player in world.multiworld.get_players() + if isinstance(world.options.entrance_rando.value, str): + seed_group = world.seed_groups[world.options.entrance_rando.value] + logic_rules = seed_group["logic_rules"] + fixed_shop = seed_group["fixed_shop"] + laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True else False shop_scenes: Set[str] = set() shop_count = 6 @@ -202,10 +205,13 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if not logic_rules: dependent_regions = dependent_regions_restricted + print("not logic rules") elif logic_rules == 1: dependent_regions = dependent_regions_nmg + print("logic rules is 1") else: dependent_regions = dependent_regions_ur + print("logic rules is more than 1") # create separate lists for dead ends and non-dead ends if logic_rules: @@ -369,7 +375,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: random_object: Random = world.random # use the seed given in the options to shuffle the portals - if world.options.entrance_rando.value != 1: + if isinstance(world.options.entrance_rando.value, str): random_object = Random(world.options.entrance_rando.value) # we want to start by making sure every region is accessible random_object.shuffle(two_plus) From f3090dd46304af9404dd2fa1aa1fc81a9eda473c Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Wed, 20 Mar 2024 14:18:30 -0400 Subject: [PATCH 04/27] Some preliminary plando connection handling, probably has errors --- worlds/tunic/__init__.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 9fee5b741fc6..eb395274f6ae 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -9,6 +9,7 @@ from .er_scripts import create_er_regions from .options import TunicOptions from worlds.AutoWorld import WebWorld, World +from worlds.generic import PlandoConnection from decimal import Decimal, ROUND_HALF_UP @@ -39,6 +40,7 @@ class SeedGroup(TypedDict): logic_rules: int # logic rules value laurels_at_10_fairies: bool # laurels location value fixed_shop: bool # fixed shop value + plando: List[PlandoConnection] = [] # consolidated list of plando connections for the seed group class TunicWorld(World): @@ -90,18 +92,43 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: if group not in cls.seed_groups: cls.seed_groups[group] = SeedGroup(logic_rules=tunc.options.logic_rules.value, laurels_at_10_fairies=tunc.options.laurels_location == 3, - fixed_shop=bool(tunc.options.fixed_shop)) + fixed_shop=bool(tunc.options.fixed_shop) + plando=multiworld.plando_connections[tunc.player]) else: # lower value is more restrictive if tunc.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: - print("restricting logic rules") + print("restricting logic rules") # debug print, remove later cls.seed_groups[group]["logic_rules"] = tunc.options.logic_rules.value if tunc.options.laurels_location == 3: - print("restricting for laurels location") + print("restricting for laurels location") # debug print, remove later cls.seed_groups[group]["laurels_at_10_fairies"] = True if tunc.options.fixed_shop: - print("restricting for fixed shop") + print("restricting for fixed shop") # debug print, remove later cls.seed_groups[group]["fixed_shop"] = True + if multiworld.plando_connections[tunc.player]: + # loop through the connections in the player's yaml + for cxn in multiworld.plando_conections[tunc.player]: + new_conn = True + # check if either of the entrances in the pair match. If one matches and the other doesn't, error out + for group_cxn in cls.seed_group[group]["plando"]: + # todo: figure out what to do regarding shops + if cxn.entrance == group_cxn.entrance: + new_conn = False + if cxn.exit == group_cxn.exit: + continue + else: + # todo: figure out what to do with shop vs shop portal + raise Exception(f"Conflict between group and plando_connections for {tunc.get_player_name()} for their connection {cxn.entrance} <-> {cxn.exit} and the group's connection {group_cxn.entrance} <-> {group_cxn.exit}") + # if a connection exit matches an entrance in the seed group, check if the entrance matches + if cxn.entrance == group_cxn.exit: + new_conn = False + if cxn.exit == group_cxn.entrance: + continue + else: + raise Exception(f"Conflict between group and plando_connections for {tunc.get_player_name()} for their connection {cxn.entrance} <-> {cxn.exit} and the group's connection {group_cxn.entrance} <-> {group_cxn.exit}") + if new_conn: + cls.seed_groups[group]["plando"].append(cxn) + def create_item(self, name: str) -> TunicItem: item_data = item_table[name] From d8ed4a1fa196c6097a63730e17f57926fbe39aa6 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Wed, 20 Mar 2024 14:21:17 -0400 Subject: [PATCH 05/27] Add missed comma --- worlds/tunic/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index eb395274f6ae..ca30e44def38 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -92,7 +92,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: if group not in cls.seed_groups: cls.seed_groups[group] = SeedGroup(logic_rules=tunc.options.logic_rules.value, laurels_at_10_fairies=tunc.options.laurels_location == 3, - fixed_shop=bool(tunc.options.fixed_shop) + fixed_shop=bool(tunc.options.fixed_shop), plando=multiworld.plando_connections[tunc.player]) else: # lower value is more restrictive From ca4ecaae0d3d5afcc515105338d2fec6459b9cef Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Wed, 20 Mar 2024 15:15:59 -0400 Subject: [PATCH 06/27] if -> elif --- worlds/tunic/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index ca30e44def38..919369ad9b2d 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -120,7 +120,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: # todo: figure out what to do with shop vs shop portal raise Exception(f"Conflict between group and plando_connections for {tunc.get_player_name()} for their connection {cxn.entrance} <-> {cxn.exit} and the group's connection {group_cxn.entrance} <-> {group_cxn.exit}") # if a connection exit matches an entrance in the seed group, check if the entrance matches - if cxn.entrance == group_cxn.exit: + elif cxn.entrance == group_cxn.exit: new_conn = False if cxn.exit == group_cxn.entrance: continue From 58ea87efcdb29171d455ed381ae4cbf76e24fb0e Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Wed, 20 Mar 2024 20:16:04 -0400 Subject: [PATCH 07/27] I think this is working properly to handle plando connections --- worlds/tunic/__init__.py | 35 ++++++++++++++++++++++------------- worlds/tunic/er_scripts.py | 32 +++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 919369ad9b2d..f0a53597d921 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -40,7 +40,7 @@ class SeedGroup(TypedDict): logic_rules: int # logic rules value laurels_at_10_fairies: bool # laurels location value fixed_shop: bool # fixed shop value - plando: List[PlandoConnection] = [] # consolidated list of plando connections for the seed group + plando: List[PlandoConnection] # consolidated list of plando connections for the seed group class TunicWorld(World): @@ -68,6 +68,14 @@ class TunicWorld(World): seed_groups: Dict[str, SeedGroup] = {} def generate_early(self) -> None: + if self.multiworld.plando_connections[self.player]: + for cxn in self.multiworld.plando_connections[self.player]: + # making shops second to simplify other things later + if cxn.entrance.startswith("Shop"): + replacement = PlandoConnection(cxn.exit, "Shop Portal", "both") + self.multiworld.plando_connections[self.player].append(replacement) + self.multiworld.plando_connections[self.player].remove(cxn) + # Universal tracker stuff, shouldn't do anything in standard gen if hasattr(self.multiworld, "re_gen_passthrough"): if "TUNIC" in self.multiworld.re_gen_passthrough: @@ -97,38 +105,39 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: else: # lower value is more restrictive if tunc.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: - print("restricting logic rules") # debug print, remove later cls.seed_groups[group]["logic_rules"] = tunc.options.logic_rules.value if tunc.options.laurels_location == 3: - print("restricting for laurels location") # debug print, remove later cls.seed_groups[group]["laurels_at_10_fairies"] = True if tunc.options.fixed_shop: - print("restricting for fixed shop") # debug print, remove later cls.seed_groups[group]["fixed_shop"] = True + if multiworld.plando_connections[tunc.player]: # loop through the connections in the player's yaml - for cxn in multiworld.plando_conections[tunc.player]: + for cxn in multiworld.plando_connections[tunc.player]: new_conn = True - # check if either of the entrances in the pair match. If one matches and the other doesn't, error out - for group_cxn in cls.seed_group[group]["plando"]: - # todo: figure out what to do regarding shops + # check if either of the entrances in the pair match + for group_cxn in cls.seed_groups[group]["plando"]: if cxn.entrance == group_cxn.entrance: new_conn = False if cxn.exit == group_cxn.exit: continue else: - # todo: figure out what to do with shop vs shop portal - raise Exception(f"Conflict between group and plando_connections for {tunc.get_player_name()} for their connection {cxn.entrance} <-> {cxn.exit} and the group's connection {group_cxn.entrance} <-> {group_cxn.exit}") - # if a connection exit matches an entrance in the seed group, check if the entrance matches + raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " + f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " + f"{tunc.multiworld.get_player_name(tunc.player)}'s plando " + f"connection {cxn.entrance} <-> {cxn.exit}") + # if a connection exit matches an entrance in the seed group, check if entrance matches elif cxn.entrance == group_cxn.exit: new_conn = False if cxn.exit == group_cxn.entrance: continue else: - raise Exception(f"Conflict between group and plando_connections for {tunc.get_player_name()} for their connection {cxn.entrance} <-> {cxn.exit} and the group's connection {group_cxn.entrance} <-> {group_cxn.exit}") + raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " + f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " + f"{tunc.multiworld.get_player_name(tunc.player)}'s plando " + f"connection {cxn.entrance} <-> {cxn.exit}") if new_conn: cls.seed_groups[group]["plando"].append(cxn) - def create_item(self, name: str) -> TunicItem: item_data = item_table[name] diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index f8826c5a3cea..9c046da3a4d9 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -205,13 +205,10 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if not logic_rules: dependent_regions = dependent_regions_restricted - print("not logic rules") elif logic_rules == 1: dependent_regions = dependent_regions_nmg - print("logic rules is 1") else: dependent_regions = dependent_regions_ur - print("logic rules is more than 1") # create separate lists for dead ends and non-dead ends if logic_rules: @@ -232,7 +229,10 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: start_region = "Overworld" connected_regions.update(add_dependent_regions(start_region, logic_rules)) - plando_connections = world.multiworld.plando_connections[world.player] + if isinstance(world.options.entrance_rando.value, str): + plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"] + else: + plando_connections = world.multiworld.plando_connections[world.player] # universal tracker support stuff, don't need to care about region dependency if hasattr(world.multiworld, "re_gen_passthrough"): @@ -266,10 +266,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: for connection in plando_connections: p_entrance = connection.entrance p_exit = connection.exit - - if p_entrance.startswith("Shop"): - p_entrance = p_exit - p_exit = "Shop Portal" + entrance_dead_end = False portal1 = None portal2 = None @@ -290,6 +287,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if not portal1: raise Exception(f"Could not find entrance named {p_entrance} for " f"plando connections in {player_name}'s YAML.") + entrance_dead_end = True dead_ends.remove(portal1) else: two_plus.remove(portal1) @@ -299,7 +297,15 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if p_exit == portal.name: portal2 = portal break - if p_exit in ["Shop Portal", "Shop"]: + if p_exit == "Shop Portal": + # don't pair dead ends to dead ends, that's bad + if entrance_dead_end: + if isinstance(world.options.entrance_rando.value, str): + raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " + "end to a dead end in their plando connections.") + else: + raise Exception(f"{player_name} paired a dead end to a dead end in their " + "plando connections.") portal2 = Portal(name="Shop Portal", region=f"Shop", destination="Previous Region_") shop_count -= 1 @@ -313,6 +319,14 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if not portal2: raise Exception(f"Could not find entrance named {p_exit} for " f"plando connections in {player_name}'s YAML.") + # don't pair dead ends to dead ends, that's bad + if entrance_dead_end: + if isinstance(world.options.entrance_rando.value, str): + raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " + "end to a dead end in their plando connections.") + else: + raise Exception(f"{player_name} paired a dead end to a dead end in their " + "plando connections.") dead_ends.remove(portal2) else: two_plus.remove(portal2) From cd72e386c396cade8a22783196c2215c3d0e9088 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 10:30:41 -0400 Subject: [PATCH 08/27] Update comments --- worlds/tunic/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index f0a53597d921..de7e14fb28e6 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -106,8 +106,10 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: # lower value is more restrictive if tunc.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: cls.seed_groups[group]["logic_rules"] = tunc.options.logic_rules.value + # laurels at 10 fairies changes logic for secret gathering place placement if tunc.options.laurels_location == 3: cls.seed_groups[group]["laurels_at_10_fairies"] = True + # fewer shops, one at windmill if tunc.options.fixed_shop: cls.seed_groups[group]["fixed_shop"] = True @@ -115,7 +117,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: # loop through the connections in the player's yaml for cxn in multiworld.plando_connections[tunc.player]: new_conn = True - # check if either of the entrances in the pair match + # check if either of the entrances in the pair match, then check for conflicts for group_cxn in cls.seed_groups[group]["plando"]: if cxn.entrance == group_cxn.entrance: new_conn = False @@ -126,7 +128,6 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " f"{tunc.multiworld.get_player_name(tunc.player)}'s plando " f"connection {cxn.entrance} <-> {cxn.exit}") - # if a connection exit matches an entrance in the seed group, check if entrance matches elif cxn.entrance == group_cxn.exit: new_conn = False if cxn.exit == group_cxn.entrance: From 2f0e4948d3c1b894745dbca56accf6ab1be19917 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 12:33:19 -0400 Subject: [PATCH 09/27] Fix up shop -> shop portal stuff --- worlds/tunic/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index a59fe958838a..9c8825a78d39 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -69,12 +69,16 @@ class TunicWorld(World): def generate_early(self) -> None: if self.multiworld.plando_connections[self.player]: - for cxn in self.multiworld.plando_connections[self.player]: + for index, cxn in enumerate(self.multiworld.plando_connections[self.player]): # making shops second to simplify other things later if cxn.entrance.startswith("Shop"): replacement = PlandoConnection(cxn.exit, "Shop Portal", "both") - self.multiworld.plando_connections[self.player].append(replacement) self.multiworld.plando_connections[self.player].remove(cxn) + self.multiworld.plando_connections[self.player].insert(index, replacement) + elif cxn.exit.startswith("Shop"): + replacement = PlandoConnection(cxn.entrance, "Shop Portal", "both") + self.multiworld.plando_connections[self.player].remove(cxn) + self.multiworld.plando_connections[self.player].insert(index, replacement) # Universal tracker stuff, shouldn't do anything in standard gen if hasattr(self.multiworld, "re_gen_passthrough"): From 10740ffbb9f76e29b0de00fed23a4ae91dada8a0 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 12:33:51 -0400 Subject: [PATCH 10/27] Add back comma that got removed for no reason in the ladder PR --- worlds/tunic/er_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 9c1813eba0ea..6518f534a8ce 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -69,7 +69,7 @@ def create_er_regions(world: "TunicWorld") -> Dict[Portal, Portal]: "Quarry Fuse": "Quarry", "Ziggurat Fuse": "Rooted Ziggurat Lower Back", "West Garden Fuse": "West Garden", - "Library Fuse": "Library Lab" + "Library Fuse": "Library Lab", } From 6f915cf130554b5733a351a7b20643650b81f082 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 12:45:22 -0400 Subject: [PATCH 11/27] Remove unnecessary if else --- worlds/tunic/er_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 6518f534a8ce..6c406d16f7fd 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -133,7 +133,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: seed_group = world.seed_groups[world.options.entrance_rando.value] logic_rules = seed_group["logic_rules"] fixed_shop = seed_group["fixed_shop"] - laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True else False + laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] shop_scenes: Set[str] = set() shop_count = 6 From a4efc3120f6a872961de8d0de123c8ebe90f3500 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 12:49:21 -0400 Subject: [PATCH 12/27] add back the actually necessary if but not the else --- worlds/tunic/er_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 6c406d16f7fd..c24a14907d88 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -133,7 +133,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: seed_group = world.seed_groups[world.options.entrance_rando.value] logic_rules = seed_group["logic_rules"] fixed_shop = seed_group["fixed_shop"] - laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] + laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True shop_scenes: Set[str] = set() shop_count = 6 From 2b2501776b3fe32641720106b595baf452f96217 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 12:53:18 -0400 Subject: [PATCH 13/27] okay they were both necessary --- worlds/tunic/er_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index c24a14907d88..6518f534a8ce 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -133,7 +133,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: seed_group = world.seed_groups[world.options.entrance_rando.value] logic_rules = seed_group["logic_rules"] fixed_shop = seed_group["fixed_shop"] - laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True + laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True else False shop_scenes: Set[str] = set() shop_count = 6 From 0e0267460b6e9f2dce41736388028613d703d895 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Thu, 21 Mar 2024 14:32:09 -0400 Subject: [PATCH 14/27] Update entrance rando description --- worlds/tunic/options.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/options.py b/worlds/tunic/options.py index 1c5b3bc12aa2..32d881194ab7 100644 --- a/worlds/tunic/options.py +++ b/worlds/tunic/options.py @@ -103,9 +103,10 @@ class ExtraHexagonPercentage(Range): class EntranceRando(TextChoice): """ Randomize the connections between scenes. - If you set this to a value besides true or false, that value will be used as a custom seed. - Every player who uses the same seed will have the same entrances, choosing the most restrictive settings among these players for the purpose of pairing entrances. A small, very lost fox on a big adventure. + + If you set this to a value besides true or false, that value will be used as a custom seed. + Every player who uses the same seed will have the same entrances, choosing the most restrictive settings among these players for the purpose of pairing entrances. """ internal_name = "entrance_rando" display_name = "Entrance Rando" From 7b876c1c29c0a86df4f6b663ff52895015009857 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sun, 24 Mar 2024 11:32:50 -0400 Subject: [PATCH 15/27] blasphemy Co-authored-by: Silent <110704408+silent-destroyer@users.noreply.github.com> --- worlds/tunic/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 9c8825a78d39..d1fa852368e7 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -97,8 +97,8 @@ def generate_early(self) -> None: @classmethod def stage_generate_early(cls, multiworld: MultiWorld) -> None: - tunc_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") - for tunc in tunc_worlds: + tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") + for tunic in tunic_worlds: if isinstance(tunc.options.entrance_rando.value, str): group = tunc.options.entrance_rando.value # if this is the first world in the group, set the rules equal to its rules From 2892409f070ab7aba771f50623add52d17e35e12 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Sun, 24 Mar 2024 11:37:33 -0400 Subject: [PATCH 16/27] Rename other instances of tunc -> tunic --- worlds/tunic/__init__.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index d1fa852368e7..ba4e3ec07921 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -99,28 +99,28 @@ def generate_early(self) -> None: def stage_generate_early(cls, multiworld: MultiWorld) -> None: tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") for tunic in tunic_worlds: - if isinstance(tunc.options.entrance_rando.value, str): - group = tunc.options.entrance_rando.value + if isinstance(tunic.options.entrance_rando.value, str): + group = tunic.options.entrance_rando.value # if this is the first world in the group, set the rules equal to its rules if group not in cls.seed_groups: - cls.seed_groups[group] = SeedGroup(logic_rules=tunc.options.logic_rules.value, - laurels_at_10_fairies=tunc.options.laurels_location == 3, - fixed_shop=bool(tunc.options.fixed_shop), - plando=multiworld.plando_connections[tunc.player]) + cls.seed_groups[group] = SeedGroup(logic_rules=tunic.options.logic_rules.value, + laurels_at_10_fairies=tunic.options.laurels_location == 3, + fixed_shop=bool(tunic.options.fixed_shop), + plando=multiworld.plando_connections[tunic.player]) else: # lower value is more restrictive - if tunc.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: - cls.seed_groups[group]["logic_rules"] = tunc.options.logic_rules.value + if tunic.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: + cls.seed_groups[group]["logic_rules"] = tunic.options.logic_rules.value # laurels at 10 fairies changes logic for secret gathering place placement - if tunc.options.laurels_location == 3: + if tunic.options.laurels_location == 3: cls.seed_groups[group]["laurels_at_10_fairies"] = True # fewer shops, one at windmill - if tunc.options.fixed_shop: + if tunic.options.fixed_shop: cls.seed_groups[group]["fixed_shop"] = True - if multiworld.plando_connections[tunc.player]: + if multiworld.plando_connections[tunic.player]: # loop through the connections in the player's yaml - for cxn in multiworld.plando_connections[tunc.player]: + for cxn in multiworld.plando_connections[tunic.player]: new_conn = True # check if either of the entrances in the pair match, then check for conflicts for group_cxn in cls.seed_groups[group]["plando"]: @@ -131,7 +131,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: else: raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " - f"{tunc.multiworld.get_player_name(tunc.player)}'s plando " + f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " f"connection {cxn.entrance} <-> {cxn.exit}") elif cxn.entrance == group_cxn.exit: new_conn = False @@ -140,7 +140,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: else: raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " - f"{tunc.multiworld.get_player_name(tunc.player)}'s plando " + f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " f"connection {cxn.entrance} <-> {cxn.exit}") if new_conn: cls.seed_groups[group]["plando"].append(cxn) From 59cb87f5a01e39a341058016efec6aee5661840e Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 09:43:44 -0400 Subject: [PATCH 17/27] Update per Vi's review (thank you) --- worlds/tunic/__init__.py | 91 ++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index ba4e3ec07921..676fd79f4c14 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -8,7 +8,7 @@ from .regions import tunic_regions from .er_scripts import create_er_regions from .er_data import portal_mapping -from .options import TunicOptions +from .options import TunicOptions, EntranceRando from worlds.AutoWorld import WebWorld, World from worlds.generic import PlandoConnection from decimal import Decimal, ROUND_HALF_UP @@ -99,51 +99,50 @@ def generate_early(self) -> None: def stage_generate_early(cls, multiworld: MultiWorld) -> None: tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") for tunic in tunic_worlds: - if isinstance(tunic.options.entrance_rando.value, str): - group = tunic.options.entrance_rando.value - # if this is the first world in the group, set the rules equal to its rules - if group not in cls.seed_groups: - cls.seed_groups[group] = SeedGroup(logic_rules=tunic.options.logic_rules.value, - laurels_at_10_fairies=tunic.options.laurels_location == 3, - fixed_shop=bool(tunic.options.fixed_shop), - plando=multiworld.plando_connections[tunic.player]) - else: - # lower value is more restrictive - if tunic.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: - cls.seed_groups[group]["logic_rules"] = tunic.options.logic_rules.value - # laurels at 10 fairies changes logic for secret gathering place placement - if tunic.options.laurels_location == 3: - cls.seed_groups[group]["laurels_at_10_fairies"] = True - # fewer shops, one at windmill - if tunic.options.fixed_shop: - cls.seed_groups[group]["fixed_shop"] = True - - if multiworld.plando_connections[tunic.player]: - # loop through the connections in the player's yaml - for cxn in multiworld.plando_connections[tunic.player]: - new_conn = True - # check if either of the entrances in the pair match, then check for conflicts - for group_cxn in cls.seed_groups[group]["plando"]: - if cxn.entrance == group_cxn.entrance: - new_conn = False - if cxn.exit == group_cxn.exit: - continue - else: - raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " - f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " - f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " - f"connection {cxn.entrance} <-> {cxn.exit}") - elif cxn.entrance == group_cxn.exit: - new_conn = False - if cxn.exit == group_cxn.entrance: - continue - else: - raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " - f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " - f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " - f"connection {cxn.entrance} <-> {cxn.exit}") - if new_conn: - cls.seed_groups[group]["plando"].append(cxn) + if not tunic.options.entrance_rando in EntranceRando.options: + continue + group = tunic.options.entrance_rando.value + # if this is the first world in the group, set the rules equal to its rules + if group not in cls.seed_groups: + cls.seed_groups[group] = SeedGroup(logic_rules=tunic.options.logic_rules.value, + laurels_at_10_fairies=tunic.options.laurels_location == 3, + fixed_shop=bool(tunic.options.fixed_shop), + plando=multiworld.plando_connections[tunic.player]) + continue + + # lower value is more restrictive + if tunic.options.logic_rules.value < cls.seed_groups[group]["logic_rules"]: + cls.seed_groups[group]["logic_rules"] = tunic.options.logic_rules.value + # laurels at 10 fairies changes logic for secret gathering place placement + if tunic.options.laurels_location == 3: + cls.seed_groups[group]["laurels_at_10_fairies"] = True + # fewer shops, one at windmill + if tunic.options.fixed_shop: + cls.seed_groups[group]["fixed_shop"] = True + + if multiworld.plando_connections[tunic.player]: + # loop through the connections in the player's yaml + for cxn in multiworld.plando_connections[tunic.player]: + for group_cxn in cls.seed_groups[group]["plando"]: + + # if neither entrance nor exit match anything in the group, add to group + if not (cxn.entrance == group_cxn.entrance or cxn.entrance == group_cxn.exit + or cxn.exit == group_cxn.entrance or cxn.exit == group_cxn.exit): + cls.seed_groups[group]["plando"].append(cxn) + continue + + # check if this pair is the same as a pair in the group already + is_mismatched = ( + cxn.entrance == group_cxn.entrance and cxn.exit != group_cxn.exit + or cxn.entrance == group_cxn.exit and cxn.exit != group_cxn.entrance + or cxn.exit == group_cxn.entrance and cxn.entrance != group_cxn.exit + or cxn.exit == group_cxn.exit and cxn.entrance != group_cxn.entrance + ) + if is_mismatched: + raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " + f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " + f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " + f"connection {cxn.entrance} <-> {cxn.exit}") def create_item(self, name: str) -> TunicItem: item_data = item_table[name] From bb24e75f612f464c561d20cae8084ead5de9081c Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 09:53:01 -0400 Subject: [PATCH 18/27] Fix a not that shouldn't have been --- worlds/tunic/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 676fd79f4c14..dd106d60239d 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -99,7 +99,8 @@ def generate_early(self) -> None: def stage_generate_early(cls, multiworld: MultiWorld) -> None: tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") for tunic in tunic_worlds: - if not tunic.options.entrance_rando in EntranceRando.options: + # if it's one of the options, then it isn't a custom seed group + if tunic.options.entrance_rando in EntranceRando.options: continue group = tunic.options.entrance_rando.value # if this is the first world in the group, set the rules equal to its rules From 1b3c857d18b7f5a7c104b8fbc96137585cca391d Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 09:58:52 -0400 Subject: [PATCH 19/27] Rearrange, update per Vi's comments (thank you) --- worlds/tunic/er_scripts.py | 48 +++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 1ceed1450e08..868693bae025 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -4,6 +4,7 @@ from .er_data import Portal, tunic_er_regions, portal_mapping, \ dependent_regions_restricted, dependent_regions_nmg, dependent_regions_ur from .er_rules import set_er_region_rules +from .options import EntranceRando from worlds.generic import PlandoConnection from random import Random @@ -127,7 +128,8 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: fixed_shop = world.options.fixed_shop laurels_location = world.options.laurels_location - if isinstance(world.options.entrance_rando.value, str): + # if it's not one of the EntranceRando options, it's a custom seed + if world.options.entrance_rando not in EntranceRando.options: seed_group = world.seed_groups[world.options.entrance_rando.value] logic_rules = seed_group["logic_rules"] fixed_shop = seed_group["fixed_shop"] @@ -202,7 +204,6 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: for connection in plando_connections: p_entrance = connection.entrance p_exit = connection.exit - entrance_dead_end = False portal1 = None portal2 = None @@ -215,7 +216,18 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: portal2 = portal # search dead_ends individually since we can't really remove items from two_plus during the loop - if not portal1: + if portal1: + two_plus.remove(portal1) + else: + # if not both, they're both dead ends + if not portal2: + if world.options.entrance_rando in EntranceRando.options: + raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " + "end to a dead end in their plando connections.") + else: + raise Exception(f"{player_name} paired a dead end to a dead end in their " + "plando connections.") + for portal in dead_ends: if p_entrance == portal.name: portal1 = portal @@ -223,26 +235,19 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if not portal1: raise Exception(f"Could not find entrance named {p_entrance} for " f"plando connections in {player_name}'s YAML.") - entrance_dead_end = True dead_ends.remove(portal1) - else: - two_plus.remove(portal1) - if not portal2: + if portal2: + two_plus.remove(portal2) + else: + # check if portal2 is a dead end for portal in dead_ends: if p_exit == portal.name: portal2 = portal break + # if it's not a dead end, it might be a shop if p_exit == "Shop Portal": - # don't pair dead ends to dead ends, that's bad - if entrance_dead_end: - if isinstance(world.options.entrance_rando.value, str): - raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " - "end to a dead end in their plando connections.") - else: - raise Exception(f"{player_name} paired a dead end to a dead end in their " - "plando connections.") - portal2 = Portal(name="Shop Portal", region=f"Shop", + portal2 = Portal(name="Shop Portal", region="Shop", destination="Previous Region", tag="_") shop_count -= 1 if shop_count < 0: @@ -251,21 +256,12 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: if p.name == p_entrance: shop_scenes.add(p.scene()) break + # and if it's neither shop nor dead end, it just isn't correct else: if not portal2: raise Exception(f"Could not find entrance named {p_exit} for " f"plando connections in {player_name}'s YAML.") - # don't pair dead ends to dead ends, that's bad - if entrance_dead_end: - if isinstance(world.options.entrance_rando.value, str): - raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " - "end to a dead end in their plando connections.") - else: - raise Exception(f"{player_name} paired a dead end to a dead end in their " - "plando connections.") dead_ends.remove(portal2) - else: - two_plus.remove(portal2) portal_pairs[portal1] = portal2 From c69d12142998270604ffe2e644795b7c535f8cef Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 10:01:17 -0400 Subject: [PATCH 20/27] Fix indent --- worlds/tunic/__init__.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index dd106d60239d..5daff6bb97e6 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -126,24 +126,24 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: for cxn in multiworld.plando_connections[tunic.player]: for group_cxn in cls.seed_groups[group]["plando"]: - # if neither entrance nor exit match anything in the group, add to group - if not (cxn.entrance == group_cxn.entrance or cxn.entrance == group_cxn.exit - or cxn.exit == group_cxn.entrance or cxn.exit == group_cxn.exit): - cls.seed_groups[group]["plando"].append(cxn) - continue - - # check if this pair is the same as a pair in the group already - is_mismatched = ( - cxn.entrance == group_cxn.entrance and cxn.exit != group_cxn.exit - or cxn.entrance == group_cxn.exit and cxn.exit != group_cxn.entrance - or cxn.exit == group_cxn.entrance and cxn.entrance != group_cxn.exit - or cxn.exit == group_cxn.exit and cxn.entrance != group_cxn.entrance - ) - if is_mismatched: - raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " - f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " - f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " - f"connection {cxn.entrance} <-> {cxn.exit}") + # if neither entrance nor exit match anything in the group, add to group + if not (cxn.entrance == group_cxn.entrance or cxn.entrance == group_cxn.exit + or cxn.exit == group_cxn.entrance or cxn.exit == group_cxn.exit): + cls.seed_groups[group]["plando"].append(cxn) + continue + + # check if this pair is the same as a pair in the group already + is_mismatched = ( + cxn.entrance == group_cxn.entrance and cxn.exit != group_cxn.exit + or cxn.entrance == group_cxn.exit and cxn.exit != group_cxn.entrance + or cxn.exit == group_cxn.entrance and cxn.entrance != group_cxn.exit + or cxn.exit == group_cxn.exit and cxn.entrance != group_cxn.entrance + ) + if is_mismatched: + raise Exception(f"TUNIC: Conflict between seed group {group}'s plando " + f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " + f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " + f"connection {cxn.entrance} <-> {cxn.exit}") def create_item(self, name: str) -> TunicItem: item_data = item_table[name] From 5afdeda2857587243e41cf10e85a148377947810 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 10:09:54 -0400 Subject: [PATCH 21/27] Add a .value --- worlds/tunic/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 5daff6bb97e6..6a5b7f386bda 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -100,7 +100,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") for tunic in tunic_worlds: # if it's one of the options, then it isn't a custom seed group - if tunic.options.entrance_rando in EntranceRando.options: + if tunic.options.entrance_rando.value in EntranceRando.options: continue group = tunic.options.entrance_rando.value # if this is the first world in the group, set the rules equal to its rules From 35b3fbc88a028aa886bf3a8ee3ca2b2a70dc8559 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 10:10:30 -0400 Subject: [PATCH 22/27] Add .values --- worlds/tunic/er_scripts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 868693bae025..9d9ceac3795a 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -129,7 +129,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: laurels_location = world.options.laurels_location # if it's not one of the EntranceRando options, it's a custom seed - if world.options.entrance_rando not in EntranceRando.options: + if world.options.entrance_rando.value not in EntranceRando.options: seed_group = world.seed_groups[world.options.entrance_rando.value] logic_rules = seed_group["logic_rules"] fixed_shop = seed_group["fixed_shop"] @@ -221,7 +221,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: else: # if not both, they're both dead ends if not portal2: - if world.options.entrance_rando in EntranceRando.options: + if world.options.entrance_rando.value in EntranceRando.options: raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " "end to a dead end in their plando connections.") else: From 11eac122c7a07892f089f2d2ec2661a3c1532ba9 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 14:11:48 -0400 Subject: [PATCH 23/27] Fix bad comparison --- worlds/tunic/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 6a5b7f386bda..8a5268b29f48 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -124,13 +124,13 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: if multiworld.plando_connections[tunic.player]: # loop through the connections in the player's yaml for cxn in multiworld.plando_connections[tunic.player]: + new_cxn = True for group_cxn in cls.seed_groups[group]["plando"]: - # if neither entrance nor exit match anything in the group, add to group - if not (cxn.entrance == group_cxn.entrance or cxn.entrance == group_cxn.exit - or cxn.exit == group_cxn.entrance or cxn.exit == group_cxn.exit): - cls.seed_groups[group]["plando"].append(cxn) - continue + if ((cxn.entrance == group_cxn.entrance and cxn.exit == group_cxn.exit) + or (cxn.exit == group_cxn.entrance and cxn.entrance == group_cxn.exit)): + new_cxn = False + break # check if this pair is the same as a pair in the group already is_mismatched = ( @@ -144,6 +144,8 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: f"connection {group_cxn.entrance} <-> {group_cxn.exit} and " f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " f"connection {cxn.entrance} <-> {cxn.exit}") + if new_cxn: + cls.seed_groups[group]["plando"].append(cxn) def create_item(self, name: str) -> TunicItem: item_data = item_table[name] From 7f9b6cdcf7139682442572d3f03141a0a48b117b Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 14:12:12 -0400 Subject: [PATCH 24/27] Add a not that was supposed to be there --- worlds/tunic/er_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 9d9ceac3795a..769200582ec9 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -221,7 +221,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: else: # if not both, they're both dead ends if not portal2: - if world.options.entrance_rando.value in EntranceRando.options: + if world.options.entrance_rando.value not in EntranceRando.options: raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " "end to a dead end in their plando connections.") else: From d1084464f89157e87f59bcf71d5a9ef55f1d771b Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 29 Mar 2024 18:27:04 -0400 Subject: [PATCH 25/27] Replace another isinstance --- worlds/tunic/__init__.py | 2 +- worlds/tunic/er_scripts.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/__init__.py b/worlds/tunic/__init__.py index 8a5268b29f48..2b4712338557 100644 --- a/worlds/tunic/__init__.py +++ b/worlds/tunic/__init__.py @@ -128,7 +128,7 @@ def stage_generate_early(cls, multiworld: MultiWorld) -> None: for group_cxn in cls.seed_groups[group]["plando"]: # if neither entrance nor exit match anything in the group, add to group if ((cxn.entrance == group_cxn.entrance and cxn.exit == group_cxn.exit) - or (cxn.exit == group_cxn.entrance and cxn.entrance == group_cxn.exit)): + or (cxn.exit == group_cxn.entrance and cxn.entrance == group_cxn.exit)): new_cxn = False break diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 769200582ec9..167f628ca246 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -167,7 +167,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: start_region = "Overworld" connected_regions.update(add_dependent_regions(start_region, logic_rules)) - if isinstance(world.options.entrance_rando.value, str): + if world.options.entrance_rando.value in EntranceRando.options: plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"] else: plando_connections = world.multiworld.plando_connections[world.player] From c73407bdf151d1f923827708ba2191ff76cb24e7 Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Tue, 2 Apr 2024 12:15:48 -0400 Subject: [PATCH 26/27] Revise option description --- worlds/tunic/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/options.py b/worlds/tunic/options.py index 32d881194ab7..9af0a0409c01 100644 --- a/worlds/tunic/options.py +++ b/worlds/tunic/options.py @@ -105,8 +105,8 @@ class EntranceRando(TextChoice): Randomize the connections between scenes. A small, very lost fox on a big adventure. - If you set this to a value besides true or false, that value will be used as a custom seed. - Every player who uses the same seed will have the same entrances, choosing the most restrictive settings among these players for the purpose of pairing entrances. + If you set this option's value to a string, it will be used as a custom seed. + Every player who uses the same custom seed will have the same entrances, choosing the most restrictive settings among these players for the purpose of pairing entrances. """ internal_name = "entrance_rando" display_name = "Entrance Rando" From 190d1bb19c43e9e259cb3bdb2cab1d567c752d9f Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Fri, 19 Apr 2024 18:16:33 -0400 Subject: [PATCH 27/27] Fix per Kaito's comment Co-authored-by: Kaito Sinclaire --- worlds/tunic/er_scripts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/tunic/er_scripts.py b/worlds/tunic/er_scripts.py index 3c03d11675a3..c0c1d4f7856b 100644 --- a/worlds/tunic/er_scripts.py +++ b/worlds/tunic/er_scripts.py @@ -168,9 +168,9 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]: connected_regions.update(add_dependent_regions(start_region, logic_rules)) if world.options.entrance_rando.value in EntranceRando.options: - plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"] - else: plando_connections = world.multiworld.plando_connections[world.player] + else: + plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"] # universal tracker support stuff, don't need to care about region dependency if hasattr(world.multiworld, "re_gen_passthrough"):