diff --git a/worlds/ahit/Locations.py b/worlds/ahit/Locations.py index eb242c96b2..c2bfe7a13b 100644 --- a/worlds/ahit/Locations.py +++ b/worlds/ahit/Locations.py @@ -11,6 +11,7 @@ class LocData(NamedTuple): required_hats: Optional[List[HatType]] = [HatType.NONE] hookshot: Optional[bool] = False dlc_flags: Optional[HatDLC] = HatDLC.none + paintings: Optional[int] = 0 # Paintings required for Subcon painting shuffle # For UmbrellaLogic setting umbrella: Optional[bool] = False # Umbrella required for this check @@ -69,13 +70,17 @@ def is_location_valid(world: World, location: str) -> bool: def get_location_names() -> Dict[str, int]: names = {name: data.id for name, data in location_table.items()} - id_start: int = 300204 + id_start: int = get_tasksanity_start_id() for i in range(TasksanityCheckCount.range_end): names.setdefault(format("Tasksanity Check %i") % (i+1), id_start+i) return names +def get_tasksanity_start_id() -> int: + return 300204 + + ahit_locations = { "Spaceship - Rumbi Abuse": LocData(301000, "Spaceship", dweller_bell=1), @@ -166,66 +171,75 @@ ahit_locations = { "Subcon Village - Graveyard Ice Cube": LocData(325077, "Subcon Forest Area"), "Subcon Village - House Top": LocData(325471, "Subcon Forest Area"), "Subcon Village - Ice Cube House": LocData(325469, "Subcon Forest Area"), - "Subcon Village - Snatcher Statue Chest": LocData(323730, "Subcon Forest Area"), + "Subcon Village - Snatcher Statue Chest": LocData(323730, "Subcon Forest Area", paintings=1), "Subcon Village - Stump Platform Chest": LocData(323729, "Subcon Forest Area"), "Subcon Forest - Giant Tree Climb": LocData(325470, "Subcon Forest Area"), - "Subcon Forest - Swamp Gravestone": LocData(326296, "Subcon Forest Area", required_hats=[HatType.BREWING],), + "Subcon Forest - Swamp Gravestone": LocData(326296, "Subcon Forest Area", + required_hats=[HatType.BREWING], paintings=1), - "Subcon Forest - Swamp Near Well": LocData(324762, "Subcon Forest Area"), - "Subcon Forest - Swamp Tree A": LocData(324763, "Subcon Forest Area"), - "Subcon Forest - Swamp Tree B": LocData(324764, "Subcon Forest Area"), - "Subcon Forest - Swamp Ice Wall": LocData(324706, "Subcon Forest Area"), - "Subcon Forest - Swamp Treehouse": LocData(325468, "Subcon Forest Area"), - "Subcon Forest - Swamp Tree Chest": LocData(323728, "Subcon Forest Area"), + "Subcon Forest - Swamp Near Well": LocData(324762, "Subcon Forest Area", paintings=1), + "Subcon Forest - Swamp Tree A": LocData(324763, "Subcon Forest Area", paintings=1), + "Subcon Forest - Swamp Tree B": LocData(324764, "Subcon Forest Area", paintings=1), + "Subcon Forest - Swamp Ice Wall": LocData(324706, "Subcon Forest Area", paintings=1), + "Subcon Forest - Swamp Treehouse": LocData(325468, "Subcon Forest Area", paintings=1), + "Subcon Forest - Swamp Tree Chest": LocData(323728, "Subcon Forest Area", paintings=1), - "Subcon Forest - Dweller Stump": LocData(324767, "Subcon Forest Area", required_hats=[HatType.DWELLER]), + "Subcon Forest - Dweller Stump": LocData(324767, "Subcon Forest Area", + required_hats=[HatType.DWELLER], paintings=3), - "Subcon Forest - Dweller Floating Rocks": LocData(324464, "Subcon Forest Area", required_hats=[HatType.DWELLER]), + "Subcon Forest - Dweller Floating Rocks": LocData(324464, "Subcon Forest Area", + required_hats=[HatType.DWELLER], paintings=3), - "Subcon Forest - Dweller Platforming Tree A": LocData(324709, "Subcon Forest Area"), + "Subcon Forest - Dweller Platforming Tree A": LocData(324709, "Subcon Forest Area", paintings=3), - "Subcon Forest - Dweller Platforming Tree B": LocData(324855, "Subcon Forest Area", required_hats=[HatType.DWELLER]), + "Subcon Forest - Dweller Platforming Tree B": LocData(324855, "Subcon Forest Area", + required_hats=[HatType.DWELLER], paintings=3), - "Subcon Forest - Giant Time Piece": LocData(325473, "Subcon Forest Area"), - "Subcon Forest - Gallows": LocData(325472, "Subcon Forest Area"), + "Subcon Forest - Giant Time Piece": LocData(325473, "Subcon Forest Area", paintings=3), + "Subcon Forest - Gallows": LocData(325472, "Subcon Forest Area", paintings=3), - "Subcon Forest - Green and Purple Dweller Rocks": LocData(325082, "Subcon Forest Area"), + "Subcon Forest - Green and Purple Dweller Rocks": LocData(325082, "Subcon Forest Area", paintings=3), - "Subcon Forest - Dweller Shack": LocData(324463, "Subcon Forest Area", required_hats=[HatType.DWELLER]), + "Subcon Forest - Dweller Shack": LocData(324463, "Subcon Forest Area", + required_hats=[HatType.DWELLER], paintings=3), "Subcon Forest - Tall Tree Hookshot Swing": LocData(324766, "Subcon Forest Area", required_hats=[HatType.DWELLER], - hookshot=True), + hookshot=True, + paintings=3), - "Subcon Forest - Burning House": LocData(324710, "Subcon Forest Area"), - "Subcon Forest - Burning Tree Climb": LocData(325079, "Subcon Forest Area"), - "Subcon Forest - Burning Stump Chest": LocData(323731, "Subcon Forest Area"), - "Subcon Forest - Burning Forest Treehouse": LocData(325467, "Subcon Forest Area"), - "Subcon Forest - Spider Bone Cage A": LocData(324462, "Subcon Forest Area"), - "Subcon Forest - Spider Bone Cage B": LocData(325080, "Subcon Forest Area"), - "Subcon Forest - Triple Spider Bounce": LocData(324765, "Subcon Forest Area"), - "Subcon Forest - Noose Treehouse": LocData(324856, "Subcon Forest Area", hookshot=True), - "Subcon Forest - Ice Cube Shack": LocData(324465, "Subcon Forest Area"), + "Subcon Forest - Burning House": LocData(324710, "Subcon Forest Area", paintings=2), + "Subcon Forest - Burning Tree Climb": LocData(325079, "Subcon Forest Area", paintings=2), + "Subcon Forest - Burning Stump Chest": LocData(323731, "Subcon Forest Area", paintings=2), + "Subcon Forest - Burning Forest Treehouse": LocData(325467, "Subcon Forest Area", paintings=2), + "Subcon Forest - Spider Bone Cage A": LocData(324462, "Subcon Forest Area", paintings=2), + "Subcon Forest - Spider Bone Cage B": LocData(325080, "Subcon Forest Area", paintings=2), + "Subcon Forest - Triple Spider Bounce": LocData(324765, "Subcon Forest Area", paintings=2), + "Subcon Forest - Noose Treehouse": LocData(324856, "Subcon Forest Area", hookshot=True, paintings=2), + "Subcon Forest - Ice Cube Shack": LocData(324465, "Subcon Forest Area", paintings=1), - "Subcon Forest - Long Tree Climb Chest": LocData(323734, "Subcon Forest Area", required_hats=[HatType.DWELLER]), + "Subcon Forest - Long Tree Climb Chest": LocData(323734, "Subcon Forest Area", + required_hats=[HatType.DWELLER], paintings=2), "Subcon Forest - Boss Arena Chest": LocData(323735, "Subcon Forest Area"), - "Subcon Forest - Manor Rooftop": LocData(325466, "Subcon Forest Area", dweller_bell=2), + "Subcon Forest - Manor Rooftop": LocData(325466, "Subcon Forest Area", dweller_bell=2, paintings=1), - "Subcon Forest - Infinite Yarn Bush": LocData(325478, "Subcon Forest Area", required_hats=[HatType.BREWING]), + "Subcon Forest - Infinite Yarn Bush": LocData(325478, "Subcon Forest Area", + required_hats=[HatType.BREWING], paintings=2), - "Subcon Forest - Magnet Badge Bush": LocData(325479, "Subcon Forest Area", required_hats=[HatType.BREWING]), + "Subcon Forest - Magnet Badge Bush": LocData(325479, "Subcon Forest Area", + required_hats=[HatType.BREWING], paintings=3), - "Subcon Well - Hookshot Badge Chest": LocData(324114, "The Subcon Well", dweller_bell=1), - "Subcon Well - Above Chest": LocData(324612, "The Subcon Well", dweller_bell=1), - "Subcon Well - On Pipe": LocData(324311, "The Subcon Well", hookshot=True, dweller_bell=1), - "Subcon Well - Mushroom": LocData(325318, "The Subcon Well", dweller_bell=1), + "Subcon Well - Hookshot Badge Chest": LocData(324114, "The Subcon Well", dweller_bell=1, paintings=1), + "Subcon Well - Above Chest": LocData(324612, "The Subcon Well", dweller_bell=1, paintings=1), + "Subcon Well - On Pipe": LocData(324311, "The Subcon Well", hookshot=True, dweller_bell=1, paintings=1), + "Subcon Well - Mushroom": LocData(325318, "The Subcon Well", dweller_bell=1, paintings=1), - "Queen Vanessa's Manor - Cellar": LocData(324841, "Queen Vanessa's Manor", dweller_bell=2), - "Queen Vanessa's Manor - Bedroom Chest": LocData(323808, "Queen Vanessa's Manor", dweller_bell=2), - "Queen Vanessa's Manor - Hall Chest": LocData(323896, "Queen Vanessa's Manor", dweller_bell=2), - "Queen Vanessa's Manor - Chandelier": LocData(325546, "Queen Vanessa's Manor", dweller_bell=2), + "Queen Vanessa's Manor - Cellar": LocData(324841, "Queen Vanessa's Manor", dweller_bell=2, paintings=1), + "Queen Vanessa's Manor - Bedroom Chest": LocData(323808, "Queen Vanessa's Manor", dweller_bell=2, paintings=1), + "Queen Vanessa's Manor - Hall Chest": LocData(323896, "Queen Vanessa's Manor", dweller_bell=2, paintings=1), + "Queen Vanessa's Manor - Chandelier": LocData(325546, "Queen Vanessa's Manor", dweller_bell=2, paintings=1), # 330000 range - Alpine Skyline "Alpine Skyline - Goat Village: Below Hookpoint": LocData(334856, "Goat Village"), @@ -328,10 +342,10 @@ act_completions = { "Act Completion (Time Rift - The Moon)": LocData(312785, "Time Rift - The Moon"), "Act Completion (Time Rift - Dead Bird Studio)": LocData(312577, "Time Rift - Dead Bird Studio"), - "Act Completion (Contractual Obligations)": LocData(312317, "Contractual Obligations"), - "Act Completion (The Subcon Well)": LocData(311160, "The Subcon Well", hookshot=True, umbrella=True), - "Act Completion (Toilet of Doom)": LocData(311984, "Toilet of Doom", hookshot=True), - "Act Completion (Queen Vanessa's Manor)": LocData(312017, "Queen Vanessa's Manor", umbrella=True), + "Act Completion (Contractual Obligations)": LocData(312317, "Contractual Obligations", paintings=1), + "Act Completion (The Subcon Well)": LocData(311160, "The Subcon Well", hookshot=True, umbrella=True, paintings=1), + "Act Completion (Toilet of Doom)": LocData(311984, "Toilet of Doom", hookshot=True, paintings=1), + "Act Completion (Queen Vanessa's Manor)": LocData(312017, "Queen Vanessa's Manor", umbrella=True, paintings=1), "Act Completion (Mail Delivery Service)": LocData(312032, "Mail Delivery Service", required_hats=[HatType.SPRINT]), "Act Completion (Your Contract has Expired)": LocData(311390, "Your Contract has Expired", umbrella=True), "Act Completion (Time Rift - Pipe)": LocData(313069, "Time Rift - Pipe", hookshot=True), diff --git a/worlds/ahit/Regions.py b/worlds/ahit/Regions.py index 260c31a596..05bb706dff 100644 --- a/worlds/ahit/Regions.py +++ b/worlds/ahit/Regions.py @@ -1,6 +1,7 @@ from worlds.AutoWorld import World from BaseClasses import Region, Entrance, ItemClassification, Location -from .Locations import HatInTimeLocation, location_table, storybook_pages, event_locs, is_location_valid, shop_locations +from .Locations import HatInTimeLocation, location_table, storybook_pages, event_locs, is_location_valid, \ + shop_locations, get_tasksanity_start_id from .Items import HatInTimeItem from .Types import ChapterIndex import typing @@ -413,11 +414,10 @@ def create_rift_connections(world: World, region: Region): def create_tasksanity_locations(world: World): ship_shape: Region = world.multiworld.get_region("Ship Shape", world.player) - id_start: int = 300204 + id_start: int = get_tasksanity_start_id() for i in range(world.multiworld.TasksanityCheckCount[world.player].value): location = HatInTimeLocation(world.player, format("Tasksanity Check %i" % (i+1)), id_start+i, ship_shape) ship_shape.locations.append(location) - # world.location_name_to_id.setdefault(location.name, location.address) def randomize_act_entrances(world: World): diff --git a/worlds/ahit/Rules.py b/worlds/ahit/Rules.py index 8ff4002a8d..91568e5af5 100644 --- a/worlds/ahit/Rules.py +++ b/worlds/ahit/Rules.py @@ -32,17 +32,7 @@ act_connections = { def can_use_hat(state: CollectionState, world: World, hat: HatType) -> bool: - return state.count("Yarn", world.player) >= get_hat_cost(world, hat) - - -def get_hat_cost(world: World, hat: HatType) -> int: - cost: int = 0 - for h in world.get_hat_craft_order(): - cost += world.get_hat_yarn_costs().get(h) - if h == hat: - break - - return cost + return state.has("Yarn", world.player, world.get_hat_yarn_costs().get(hat)) def can_sdj(state: CollectionState, world: World): @@ -98,23 +88,19 @@ def can_clear_metro(state: CollectionState, world: World) -> bool: def set_rules(world: World): - w = world - mw = world.multiworld - p = world.player - - dlc1: bool = bool(mw.EnableDLC1[p].value > 0) - dlc2: bool = bool(mw.EnableDLC2[p].value > 0) + dlc1: bool = bool(world.multiworld.EnableDLC1[world.player].value > 0) + dlc2: bool = bool(world.multiworld.EnableDLC2[world.player].value > 0) # First, chapter access - starting_chapter = ChapterIndex(mw.StartingChapter[p].value) - w.set_chapter_cost(starting_chapter, 0) + starting_chapter = ChapterIndex(world.multiworld.StartingChapter[world.player].value) + world.set_chapter_cost(starting_chapter, 0) # Chapter costs increase progressively. Randomly decide the chapter order, except for Finale chapter_list: typing.List[ChapterIndex] = [ChapterIndex.MAFIA, ChapterIndex.BIRDS, ChapterIndex.SUBCON, ChapterIndex.ALPINE] final_chapter = ChapterIndex.FINALE - if mw.EndGoal[p].value == 2: + if world.multiworld.EndGoal[world.player].value == 2: final_chapter = ChapterIndex.METRO chapter_list.append(ChapterIndex.FINALE) @@ -125,7 +111,7 @@ def set_rules(world: World): chapter_list.append(ChapterIndex.METRO) chapter_list.remove(starting_chapter) - mw.random.shuffle(chapter_list) + world.multiworld.random.shuffle(chapter_list) if starting_chapter is not ChapterIndex.ALPINE and dlc1 or dlc2: index1: int = 69 @@ -143,15 +129,15 @@ def set_rules(world: World): if lowest_index == 0: pos = 0 else: - pos = mw.random.randint(0, lowest_index) + pos = world.multiworld.random.randint(0, lowest_index) chapter_list.insert(pos, ChapterIndex.ALPINE) - lowest_cost: int = mw.LowestChapterCost[p].value - highest_cost: int = mw.HighestChapterCost[p].value + lowest_cost: int = world.multiworld.LowestChapterCost[world.player].value + highest_cost: int = world.multiworld.HighestChapterCost[world.player].value - cost_increment: int = mw.ChapterCostIncrement[p].value - min_difference: int = mw.ChapterCostMinDifference[p].value + cost_increment: int = world.multiworld.ChapterCostIncrement[world.player].value + min_difference: int = world.multiworld.ChapterCostMinDifference[world.player].value last_cost: int = 0 cost: int loop_count: int = 0 @@ -161,109 +147,112 @@ def set_rules(world: World): if min_range >= highest_cost: min_range = highest_cost-1 - value: int = mw.random.randint(min_range, min(highest_cost, max(lowest_cost, last_cost + cost_increment))) + value: int = world.multiworld.random.randint(min_range, min(highest_cost, + max(lowest_cost, last_cost + cost_increment))) - cost = mw.random.randint(value, min(value + cost_increment, highest_cost)) + cost = world.multiworld.random.randint(value, min(value + cost_increment, highest_cost)) if loop_count >= 1: if last_cost + min_difference > cost: cost = last_cost + min_difference cost = min(cost, highest_cost) - w.set_chapter_cost(chapter, cost) + world.set_chapter_cost(chapter, cost) last_cost = cost loop_count += 1 - w.set_chapter_cost(final_chapter, mw.random.randint(mw.FinalChapterMinCost[p].value, - mw.FinalChapterMaxCost[p].value)) + world.set_chapter_cost(final_chapter, world.multiworld.random.randint( + world.multiworld.FinalChapterMinCost[world.player].value, + world.multiworld.FinalChapterMaxCost[world.player].value)) - add_rule(mw.get_entrance("Telescope -> Mafia Town", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.MAFIA))) + add_rule(world.multiworld.get_entrance("Telescope -> Mafia Town", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.MAFIA))) - add_rule(mw.get_entrance("Telescope -> Battle of the Birds", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.BIRDS))) + add_rule(world.multiworld.get_entrance("Telescope -> Battle of the Birds", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS))) - add_rule(mw.get_entrance("Telescope -> Subcon Forest", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.SUBCON))) + add_rule(world.multiworld.get_entrance("Telescope -> Subcon Forest", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.SUBCON))) - add_rule(mw.get_entrance("Telescope -> Alpine Skyline", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.ALPINE))) + add_rule(world.multiworld.get_entrance("Telescope -> Alpine Skyline", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE))) - add_rule(mw.get_entrance("Telescope -> Time's End", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.FINALE)) - and can_use_hat(state, w, HatType.BREWING) and can_use_hat(state, w, HatType.DWELLER)) + add_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.FINALE)) + and can_use_hat(state, world, HatType.BREWING) and can_use_hat(state, world, HatType.DWELLER)) if dlc1: - add_rule(mw.get_entrance("Telescope -> The Arctic Cruise", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.ALPINE)) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.CRUISE))) + add_rule(world.multiworld.get_entrance("Telescope -> The Arctic Cruise", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE)) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.CRUISE))) if dlc2: - add_rule(mw.get_entrance("Telescope -> Nyakuza Metro", p), - lambda state: state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.ALPINE)) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.METRO)) - and can_use_hat(state, w, HatType.DWELLER) and can_use_hat(state, w, HatType.ICE)) + add_rule(world.multiworld.get_entrance("Telescope -> Nyakuza Metro", world.player), + lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE)) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.METRO)) + and can_use_hat(state, world, HatType.DWELLER) and can_use_hat(state, world, HatType.ICE)) - if mw.ActRandomizer[p].value == 0: - set_default_rift_rules(w) + if world.multiworld.ActRandomizer[world.player].value == 0: + set_default_rift_rules(world) location: Location for (key, data) in location_table.items(): - if not is_location_valid(w, key): + if not is_location_valid(world, key): continue if key in contract_locations.keys(): continue - location = mw.get_location(key, p) + location = world.multiworld.get_location(key, world.player) # Not all locations in Alpine can be reached from The Illness has Spread # as many of the ziplines are blocked off if data.region == "Alpine Skyline Area": if key not in tihs_locations: - add_rule(location, lambda state: state.can_reach("Alpine Free Roam", "Region", p), "and") + add_rule(location, lambda state: state.can_reach("Alpine Free Roam", "Region", world.player), "and") else: - add_rule(location, lambda state: can_use_hookshot(state, w)) + add_rule(location, lambda state: can_use_hookshot(state, world)) if data.region == "The Birdhouse" or data.region == "The Lava Cake" \ or data.region == "The Windmill" or data.region == "The Twilight Bell": - add_rule(location, lambda state: state.can_reach("Alpine Free Roam", "Region", p), "and") + add_rule(location, lambda state: state.can_reach("Alpine Free Roam", "Region", world.player), "and") for hat in data.required_hats: if hat is not HatType.NONE: - add_rule(location, lambda state, hat=hat: can_use_hat(state, w, hat)) + add_rule(location, lambda state, required_hat=hat: can_use_hat(state, world, required_hat)) if data.hookshot: - add_rule(location, lambda state: can_use_hookshot(state, w)) + add_rule(location, lambda state: can_use_hookshot(state, world)) - if data.umbrella and mw.UmbrellaLogic[p].value > 0: - add_rule(location, lambda state: state.has("Umbrella", p)) + if data.umbrella and world.multiworld.UmbrellaLogic[world.player].value > 0: + add_rule(location, lambda state: state.has("Umbrella", world.player)) + + if data.paintings > 0 and world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(location, lambda state, paintings=data.paintings: + state.count("Progressive Painting Unlock", world.player) >= paintings) if data.dweller_bell > 0: if data.dweller_bell == 1: # Required to be hit regardless of Dweller Mask - add_rule(location, lambda state: can_hit_bells(state, w)) + add_rule(location, lambda state: can_hit_bells(state, world)) else: # Can bypass with Dweller Mask - add_rule(location, lambda state: can_hit_bells(state, w) or can_use_hat(state, w, HatType.DWELLER)) + add_rule(location, lambda state: can_hit_bells(state, world) or can_use_hat(state, world, HatType.DWELLER)) - set_specific_rules(w) + set_specific_rules(world) - if mw.LogicDifficulty[p].value >= 1: - mw.SDJLogic[p].value = 1 + if world.multiworld.LogicDifficulty[world.player].value >= 1: + world.multiworld.SDJLogic[world.player].value = 1 - if mw.SDJLogic[p].value > 0: + if world.multiworld.SDJLogic[world.player].value > 0: set_sdj_rules(world) - if mw.ShuffleAlpineZiplines[p].value > 0: - set_alps_zipline_rules(w) - - if mw.ShuffleSubconPaintings[p].value > 0: - set_painting_rules(w) + if world.multiworld.ShuffleAlpineZiplines[world.player].value > 0: + set_alps_zipline_rules(world) for (key, acts) in act_connections.items(): if "Arctic Cruise" in key and not dlc1: continue i: int = 1 - entrance: Entrance = mw.get_entrance(key, p) + entrance: Entrance = world.multiworld.get_entrance(key, world.player) region: Region = entrance.connected_region access_rules: typing.List[typing.Callable[[CollectionState], bool]] = [] entrance.parent_region.exits.remove(entrance) @@ -273,18 +262,18 @@ def set_rules(world: World): entrances: typing.List[Entrance] = [] for act in acts: - act_entrance: Entrance = mw.get_entrance(act, p) + act_entrance: Entrance = world.multiworld.get_entrance(act, world.player) access_rules.append(act_entrance.access_rule) required_region = act_entrance.connected_region name: str = format("%s: Connection %i" % (key, i)) - new_entrance: Entrance = connect_regions(required_region, region, name, p) + new_entrance: Entrance = connect_regions(required_region, region, name, world.player) entrances.append(new_entrance) # Copy access rules from act completions if "Free Roam" not in required_region.name: rule: typing.Callable[[CollectionState], bool] name = format("Act Completion (%s)" % required_region.name) - rule = mw.get_location(name, p).access_rule + rule = world.multiworld.get_location(name, world.player).access_rule access_rules.append(rule) i += 1 @@ -293,186 +282,193 @@ def set_rules(world: World): for rules in access_rules: add_rule(e, rules) - for entrance in mw.get_region("Alpine Free Roam", p).entrances: - add_rule(entrance, lambda state: can_use_hookshot(state, w)) - if mw.UmbrellaLogic[p].value > 0: - add_rule(entrance, lambda state: state.has("Umbrella", p)) + for entrance in world.multiworld.get_region("Alpine Free Roam", world.player).entrances: + add_rule(entrance, lambda state: can_use_hookshot(state, world)) + if world.multiworld.UmbrellaLogic[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Umbrella", world.player)) - if mw.EndGoal[p].value == 1: - mw.completion_condition[p] = lambda state: state.has("Time Piece Cluster", p) - elif mw.EndGoal[p].value == 2: - mw.completion_condition[p] = lambda state: state.has("Rush Hour Cleared", p) + if world.multiworld.EndGoal[world.player].value == 1: + world.multiworld.completion_condition[world.player] = lambda state: state.has("Time Piece Cluster", world.player) + elif world.multiworld.EndGoal[world.player].value == 2: + world.multiworld.completion_condition[world.player] = lambda state: state.has("Rush Hour Cleared", world.player) def set_specific_rules(world: World): - mw = world.multiworld - w = world - p = world.player - dlc1: bool = bool(mw.EnableDLC1[p].value > 0) + dlc1: bool = bool(world.multiworld.EnableDLC1[world.player].value > 0) - add_rule(mw.get_entrance("Alpine Skyline - Finale", p), - lambda state: can_clear_alpine(state, w)) + add_rule(world.multiworld.get_entrance("Alpine Skyline - Finale", world.player), + lambda state: can_clear_alpine(state, world)) - add_rule(mw.get_location("Mafia Boss Shop Item", p), - lambda state: state.has("Time Piece", p, 12) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.BIRDS))) + add_rule(world.multiworld.get_location("Mafia Boss Shop Item", world.player), + lambda state: state.has("Time Piece", world.player, 12) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS))) - add_rule(mw.get_location("Spaceship - Rumbi Abuse", p), - lambda state: state.has("Time Piece", p, 4)) + add_rule(world.multiworld.get_location("Spaceship - Rumbi Abuse", world.player), + lambda state: state.has("Time Piece", world.player, 4)) # Normal logic - if mw.LogicDifficulty[p].value == 0: - add_rule(mw.get_entrance("-> The Birdhouse", p), - lambda state: can_use_hat(state, w, HatType.BREWING)) + if world.multiworld.LogicDifficulty[world.player].value == 0: + add_rule(world.multiworld.get_entrance("-> The Birdhouse", world.player), + lambda state: can_use_hat(state, world, HatType.BREWING)) - add_rule(mw.get_location("Alpine Skyline - Yellow Band Hills", p), - lambda state: can_use_hat(state, w, HatType.BREWING)) + add_rule(world.multiworld.get_location("Alpine Skyline - Yellow Band Hills", world.player), + lambda state: can_use_hat(state, world, HatType.BREWING)) if dlc1: - add_rule(mw.get_location("Act Completion (Time Rift - Deep Sea)", p), - lambda state: can_use_hat(state, w, HatType.DWELLER)) + add_rule(world.multiworld.get_location("Act Completion (Time Rift - Deep Sea)", world.player), + lambda state: can_use_hat(state, world, HatType.DWELLER)) - add_rule(mw.get_location("Rock the Boat - Post Captain Rescue", p), - lambda state: can_use_hat(state, w, HatType.ICE)) + add_rule(world.multiworld.get_location("Rock the Boat - Post Captain Rescue", world.player), + lambda state: can_use_hat(state, world, HatType.ICE)) - add_rule(mw.get_location("Act Completion (Rock the Boat)", p), - lambda state: can_use_hat(state, w, HatType.ICE)) + add_rule(world.multiworld.get_location("Act Completion (Rock the Boat)", world.player), + lambda state: can_use_hat(state, world, HatType.ICE)) # Hard logic, includes SDJ stuff - if mw.LogicDifficulty[p].value >= 1: - add_rule(mw.get_location("Act Completion (Time Rift - The Twilight Bell)", p), - lambda state: can_use_hat(state, w, HatType.SPRINT) and state.has("Scooter Badge", p), "or") + if world.multiworld.LogicDifficulty[world.player].value >= 1: + add_rule(world.multiworld.get_location("Act Completion (Time Rift - The Twilight Bell)", world.player), + lambda state: can_use_hat(state, world, HatType.SPRINT) + and state.has("Scooter Badge", world.player), "or") # Expert logic - if mw.LogicDifficulty[p].value >= 2: - set_rule(mw.get_location("Alpine Skyline - The Twilight Path", p), lambda state: True) + if world.multiworld.LogicDifficulty[world.player].value >= 2: + set_rule(world.multiworld.get_location("Alpine Skyline - The Twilight Path", world.player), lambda state: True) else: - add_rule(mw.get_entrance("-> The Twilight Bell", p), - lambda state: can_use_hat(state, w, HatType.DWELLER)) + add_rule(world.multiworld.get_entrance("-> The Twilight Bell", world.player), + lambda state: can_use_hat(state, world, HatType.DWELLER)) - add_rule(mw.get_location("Mafia Town - Behind HQ Chest", p), - lambda state: state.can_reach("Act Completion (Heating Up Mafia Town)", "Location", p) - or state.can_reach("Down with the Mafia!", "Region", p) - or state.can_reach("Cheating the Race", "Region", p) - or state.can_reach("The Golden Vault", "Region", p)) + add_rule(world.multiworld.get_location("Mafia Town - Behind HQ Chest", world.player), + lambda state: state.can_reach("Act Completion (Heating Up Mafia Town)", "Location", world.player) + or state.can_reach("Down with the Mafia!", "Region", world.player) + or state.can_reach("Cheating the Race", "Region", world.player) + or state.can_reach("The Golden Vault", "Region", world.player)) # Old guys don't appear in SCFOS - add_rule(mw.get_location("Mafia Town - Old Man (Steel Beams)", p), - lambda state: state.can_reach("Welcome to Mafia Town", "Region", p) - or state.can_reach("Barrel Battle", "Region", p) - or state.can_reach("Cheating the Race", "Region", p) - or state.can_reach("The Golden Vault", "Region", p) - or state.can_reach("Down with the Mafia!", "Region", p)) + add_rule(world.multiworld.get_location("Mafia Town - Old Man (Steel Beams)", world.player), + lambda state: state.can_reach("Welcome to Mafia Town", "Region", world.player) + or state.can_reach("Barrel Battle", "Region", world.player) + or state.can_reach("Cheating the Race", "Region", world.player) + or state.can_reach("The Golden Vault", "Region", world.player) + or state.can_reach("Down with the Mafia!", "Region", world.player)) - add_rule(mw.get_location("Mafia Town - Old Man (Seaside Spaghetti)", p), - lambda state: state.can_reach("Welcome to Mafia Town", "Region", p) - or state.can_reach("Barrel Battle", "Region", p) - or state.can_reach("Cheating the Race", "Region", p) - or state.can_reach("The Golden Vault", "Region", p) - or state.can_reach("Down with the Mafia!", "Region", p)) + add_rule(world.multiworld.get_location("Mafia Town - Old Man (Seaside Spaghetti)", world.player), + lambda state: state.can_reach("Welcome to Mafia Town", "Region", world.player) + or state.can_reach("Barrel Battle", "Region", world.player) + or state.can_reach("Cheating the Race", "Region", world.player) + or state.can_reach("The Golden Vault", "Region", world.player) + or state.can_reach("Down with the Mafia!", "Region", world.player)) # Only available outside She Came from Outer Space - add_rule(mw.get_location("Mafia Town - Mafia Geek Platform", p), - lambda state: state.can_reach("Welcome to Mafia Town", "Region", p) - or state.can_reach("Barrel Battle", "Region", p) - or state.can_reach("Down with the Mafia!", "Region", p) - or state.can_reach("Cheating the Race", "Region", p) - or state.can_reach("Heating Up Mafia Town", "Region", p) - or state.can_reach("The Golden Vault", "Region", p)) + add_rule(world.multiworld.get_location("Mafia Town - Mafia Geek Platform", world.player), + lambda state: state.can_reach("Welcome to Mafia Town", "Region", world.player) + or state.can_reach("Barrel Battle", "Region", world.player) + or state.can_reach("Down with the Mafia!", "Region", world.player) + or state.can_reach("Cheating the Race", "Region", world.player) + or state.can_reach("Heating Up Mafia Town", "Region", world.player) + or state.can_reach("The Golden Vault", "Region", world.player)) # Only available outside Down with the Mafia! (for some reason) - add_rule(mw.get_location("Mafia Town - On Scaffolding", p), - lambda state: state.can_reach("Welcome to Mafia Town", "Region", p) - or state.can_reach("Barrel Battle", "Region", p) - or state.can_reach("She Came from Outer Space", "Region", p) - or state.can_reach("Cheating the Race", "Region", p) - or state.can_reach("Heating Up Mafia Town", "Region", p) - or state.can_reach("The Golden Vault", "Region", p)) + add_rule(world.multiworld.get_location("Mafia Town - On Scaffolding", world.player), + lambda state: state.can_reach("Welcome to Mafia Town", "Region", world.player) + or state.can_reach("Barrel Battle", "Region", world.player) + or state.can_reach("She Came from Outer Space", "Region", world.player) + or state.can_reach("Cheating the Race", "Region", world.player) + or state.can_reach("Heating Up Mafia Town", "Region", world.player) + or state.can_reach("The Golden Vault", "Region", world.player)) # For some reason, the brewing crate is removed in HUMT - set_rule(mw.get_location("Mafia Town - Secret Cave", p), - lambda state: state.can_reach("Heating Up Mafia Town", "Region", p) - or can_use_hat(state, w, HatType.BREWING)) + set_rule(world.multiworld.get_location("Mafia Town - Secret Cave", world.player), + lambda state: state.can_reach("Heating Up Mafia Town", "Region", world.player) + or can_use_hat(state, world, HatType.BREWING)) - # Can bounce across the lava to get this without Hookshot (need to die though :P) - set_rule(mw.get_location("Mafia Town - Above Boats", p), - lambda state: state.can_reach("Heating Up Mafia Town", "Region", p) - or can_use_hookshot(state, w)) + # Can bounce across the lava to get this without Hookshot (need to die though :world.player) + set_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player), + lambda state: state.can_reach("Heating Up Mafia Town", "Region", world.player) + or can_use_hookshot(state, world)) - set_rule(mw.get_location("Act Completion (Cheating the Race)", p), - lambda state: can_use_hat(state, w, HatType.TIME_STOP) - or mw.CTRWithSprint[p].value > 0 and can_use_hat(state, w, HatType.SPRINT)) + set_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), + lambda state: can_use_hat(state, world, HatType.TIME_STOP) + or world.multiworld.CTRWithSprint[world.player].value > 0 and can_use_hat(state, world, HatType.SPRINT)) - set_rule(mw.get_location("Subcon Forest - Boss Arena Chest", p), - lambda state: state.can_reach("Toilet of Doom", "Region", p) - and (mw.ShuffleSubconPaintings[p].value == 0 or state.has("Progressive Painting Unlock", p, 1)) - or state.can_reach("Your Contract has Expired", "Region", p)) + set_rule(world.multiworld.get_location("Subcon Forest - Boss Arena Chest", world.player), + lambda state: state.can_reach("Toilet of Doom", "Region", world.player) + and (world.multiworld.ShuffleSubconPaintings[world.player].value == 0 + or state.has("Progressive Painting Unlock", world.player, 1)) + or state.can_reach("Your Contract has Expired", "Region", world.player)) - if mw.UmbrellaLogic[p].value > 0: - add_rule(mw.get_location("Act Completion (Toilet of Doom)", p), - lambda state: state.has("Umbrella", p) or can_use_hat(state, w, HatType.BREWING)) + if world.multiworld.UmbrellaLogic[world.player].value > 0: + add_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player), + lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING)) - set_rule(mw.get_location("Act Completion (Time Rift - Village)", p), - lambda state: can_use_hat(state, w, HatType.BREWING) or state.has("Umbrella", p) - or can_use_hat(state, w, HatType.DWELLER)) + set_rule(world.multiworld.get_location("Act Completion (Time Rift - Village)", world.player), + lambda state: can_use_hat(state, world, HatType.BREWING) or state.has("Umbrella", world.player) + or can_use_hat(state, world, HatType.DWELLER)) - add_rule(mw.get_entrance("Subcon Forest - Act 2", p), - lambda state: state.has("Snatcher's Contract - The Subcon Well", p)) + add_rule(world.multiworld.get_entrance("Subcon Forest - Act 2", world.player), + lambda state: state.has("Snatcher's Contract - The Subcon Well", world.player)) - add_rule(mw.get_entrance("Subcon Forest - Act 3", p), - lambda state: state.has("Snatcher's Contract - Toilet of Doom", p)) + add_rule(world.multiworld.get_entrance("Subcon Forest - Act 3", world.player), + lambda state: state.has("Snatcher's Contract - Toilet of Doom", world.player)) - add_rule(mw.get_entrance("Subcon Forest - Act 4", p), - lambda state: state.has("Snatcher's Contract - Queen Vanessa's Manor", p)) + add_rule(world.multiworld.get_entrance("Subcon Forest - Act 4", world.player), + lambda state: state.has("Snatcher's Contract - Queen Vanessa's Manor", world.player)) - add_rule(mw.get_entrance("Subcon Forest - Act 5", p), - lambda state: state.has("Snatcher's Contract - Mail Delivery Service", p)) + add_rule(world.multiworld.get_entrance("Subcon Forest - Act 5", world.player), + lambda state: state.has("Snatcher's Contract - Mail Delivery Service", world.player)) - if mw.ShuffleSubconPaintings[p].value > 0: + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: for key in contract_locations: if key == "Snatcher's Contract - The Subcon Well": continue - add_rule(mw.get_location(key, p), - lambda state: state.has("Progressive Painting Unlock", p, 1)) + add_rule(world.multiworld.get_location(key, world.player), + lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - add_rule(mw.get_location("Alpine Skyline - Mystifying Time Mesa: Zipline", p), - lambda state: can_use_hat(state, w, HatType.SPRINT) or can_use_hat(state, w, HatType.TIME_STOP)) + add_rule(world.multiworld.get_location("Alpine Skyline - Mystifying Time Mesa: Zipline", world.player), + lambda state: can_use_hat(state, world, HatType.SPRINT) or can_use_hat(state, world, HatType.TIME_STOP)) - if mw.EnableDLC1[p].value > 0: - add_rule(mw.get_entrance("Cruise Ship Entrance BV", p), lambda state: can_use_hookshot(state, w)) + if world.multiworld.EnableDLC1[world.player].value > 0: + add_rule(world.multiworld.get_entrance("Cruise Ship Entrance BV", world.player), + lambda state: can_use_hookshot(state, world)) # This particular item isn't present in Act 3 for some reason, yes in vanilla too - add_rule(mw.get_location("The Arctic Cruise - Toilet", p), - lambda state: state.can_reach("Bon Voyage!", "Region", p) - or state.can_reach("Ship Shape", "Region", p)) + add_rule(world.multiworld.get_location("The Arctic Cruise - Toilet", world.player), + lambda state: state.can_reach("Bon Voyage!", "Region", world.player) + or state.can_reach("Ship Shape", "Region", world.player)) - if mw.EnableDLC2[p].value > 0: - add_rule(mw.get_entrance("-> Bluefin Tunnel", p), - lambda state: state.has("Metro Ticket - Green", p) or state.has("Metro Ticket - Blue", p)) + if world.multiworld.EnableDLC2[world.player].value > 0: + add_rule(world.multiworld.get_entrance("-> Bluefin Tunnel", world.player), + lambda state: state.has("Metro Ticket - Green", world.player) + or state.has("Metro Ticket - Blue", world.player)) - add_rule(mw.get_entrance("-> Pink Paw Station", p), - lambda state: state.has("Metro Ticket - Pink", p) - or state.has("Metro Ticket - Yellow", p) and state.has("Metro Ticket - Blue", p)) + add_rule(world.multiworld.get_entrance("-> Pink Paw Station", world.player), + lambda state: state.has("Metro Ticket - Pink", world.player) + or state.has("Metro Ticket - Yellow", world.player) and state.has("Metro Ticket - Blue", world.player)) - add_rule(mw.get_entrance("Nyakuza Metro - Finale", p), - lambda state: can_clear_metro(state, w)) + add_rule(world.multiworld.get_entrance("Nyakuza Metro - Finale", world.player), + lambda state: can_clear_metro(state, world)) - add_rule(mw.get_location("Act Completion (Rush Hour)", p), - lambda state: state.has("Metro Ticket - Yellow", p) and state.has("Metro Ticket - Blue", p) - and state.has("Metro Ticket - Pink", p)) + add_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), + lambda state: state.has("Metro Ticket - Yellow", world.player) + and state.has("Metro Ticket - Blue", world.player) + and state.has("Metro Ticket - Pink", world.player)) for key in shop_locations.keys(): - if "Green Clean Station Thug B" in key and is_location_valid(w, key): - add_rule(mw.get_location(key, p), lambda state: state.has("Metro Ticket - Yellow", p), "or") + if "Green Clean Station Thug B" in key and is_location_valid(world, key): + add_rule(world.multiworld.get_location(key, world.player), + lambda state: state.has("Metro Ticket - Yellow", world.player), "or") def set_sdj_rules(world: World): add_rule(world.multiworld.get_location("Subcon Forest - Long Tree Climb Chest", world.player), - lambda state: can_sdj(state, world), "or") + lambda state: can_sdj(state, world) + and (world.multiworld.ShuffleSubconPaintings[world.player].value == 0 + or state.count("Progressive Painting Unlock", world.player) >= 2), "or") add_rule(world.multiworld.get_location("Subcon Forest - Green and Purple Dweller Rocks", world.player), - lambda state: can_sdj(state, world), "or") + lambda state: can_sdj(state, world) + and (world.multiworld.ShuffleSubconPaintings[world.player].value == 0 + or state.count("Progressive Painting Unlock", world.player) >= 3), "or") add_rule(world.multiworld.get_location("Alpine Skyline - The Birdhouse: Dweller Platforms Relic", world.player), lambda state: can_sdj(state, world), "or") @@ -525,160 +521,164 @@ def reg_act_connection(world: World, region: typing.Union[str, Region], unlocked # See randomize_act_entrances in Regions.py # Called BEFORE set_rules! def set_rift_rules(world: World, regions: typing.Dict[str, Region]): - w = world - mw = world.multiworld - p = world.player # This is accessing the regions in place of these time rifts, so we can set the rules on all the entrances. for entrance in regions["Time Rift - Gallery"].entrances: - add_rule(entrance, lambda state: can_use_hat(state, w, HatType.BREWING) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.BIRDS))) + add_rule(entrance, lambda state: can_use_hat(state, world, HatType.BREWING) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS))) for entrance in regions["Time Rift - The Lab"].entrances: - add_rule(entrance, lambda state: can_use_hat(state, w, HatType.DWELLER) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.ALPINE))) + add_rule(entrance, lambda state: can_use_hat(state, world, HatType.DWELLER) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE))) for entrance in regions["Time Rift - Sewers"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Mafia Town - Act 4")) - reg_act_connection(w, mw.get_entrance("Mafia Town - Act 4", p).connected_region, entrance) + add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 4")) + reg_act_connection(world, world.multiworld.get_entrance("Mafia Town - Act 4", + world.player).connected_region, entrance) for entrance in regions["Time Rift - Bazaar"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Mafia Town - Act 6")) - reg_act_connection(w, mw.get_entrance("Mafia Town - Act 6", p).connected_region, entrance) + add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 6")) + reg_act_connection(world, world.multiworld.get_entrance("Mafia Town - Act 6", + world.player).connected_region, entrance) for entrance in regions["Time Rift - Mafia of Cooks"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Burger")) + add_rule(entrance, lambda state: has_relic_combo(state, world, "Burger")) for entrance in regions["Time Rift - The Owl Express"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Battle of the Birds - Act 2")) - add_rule(entrance, lambda state: can_clear_act(state, w, "Battle of the Birds - Act 3")) - reg_act_connection(w, mw.get_entrance("Battle of the Birds - Act 2", p).connected_region, entrance) - reg_act_connection(w, mw.get_entrance("Battle of the Birds - Act 3", p).connected_region, entrance) + add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 2")) + add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 3")) + reg_act_connection(world, world.multiworld.get_entrance("Battle of the Birds - Act 2", + world.player).connected_region, entrance) + reg_act_connection(world, world.multiworld.get_entrance("Battle of the Birds - Act 3", + world.player).connected_region, entrance) for entrance in regions["Time Rift - The Moon"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Battle of the Birds - Act 4")) - add_rule(entrance, lambda state: can_clear_act(state, w, "Battle of the Birds - Act 5")) - reg_act_connection(w, mw.get_entrance("Battle of the Birds - Act 4", p).connected_region, entrance) - reg_act_connection(w, mw.get_entrance("Battle of the Birds - Act 5", p).connected_region, entrance) + add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 4")) + add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 5")) + reg_act_connection(world, world.multiworld.get_entrance("Battle of the Birds - Act 4", + world.player).connected_region, entrance) + reg_act_connection(world, world.multiworld.get_entrance("Battle of the Birds - Act 5", + world.player).connected_region, entrance) for entrance in regions["Time Rift - Dead Bird Studio"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Train")) + add_rule(entrance, lambda state: has_relic_combo(state, world, "Train")) for entrance in regions["Time Rift - Pipe"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Subcon Forest - Act 2")) - reg_act_connection(w, mw.get_entrance("Subcon Forest - Act 2", p).connected_region, entrance) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 2)) + add_rule(entrance, lambda state: can_clear_act(state, world, "Subcon Forest - Act 2")) + reg_act_connection(world, world.multiworld.get_entrance("Subcon Forest - Act 2", + world.player).connected_region, entrance) + + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 2)) for entrance in regions["Time Rift - Village"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "Subcon Forest - Act 4")) - reg_act_connection(w, mw.get_entrance("Subcon Forest - Act 4", p).connected_region, entrance) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 2)) + add_rule(entrance, lambda state: can_clear_act(state, world, "Subcon Forest - Act 4")) + reg_act_connection(world, world.multiworld.get_entrance("Subcon Forest - Act 4", + world.player).connected_region, entrance) + + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 2)) for entrance in regions["Time Rift - Sleepy Subcon"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "UFO")) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 3)) + add_rule(entrance, lambda state: has_relic_combo(state, world, "UFO")) + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 3)) for entrance in regions["Time Rift - Curly Tail Trail"].entrances: - add_rule(entrance, lambda state: state.has("Windmill Cleared", p)) + add_rule(entrance, lambda state: state.has("Windmill Cleared", world.player)) for entrance in regions["Time Rift - The Twilight Bell"].entrances: - add_rule(entrance, lambda state: state.has("Twilight Bell Cleared", p)) + add_rule(entrance, lambda state: state.has("Twilight Bell Cleared", world.player)) for entrance in regions["Time Rift - Alpine Skyline"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Crayon")) + add_rule(entrance, lambda state: has_relic_combo(state, world, "Crayon")) - if mw.EnableDLC1[p].value > 0: + if world.multiworld.EnableDLC1[world.player].value > 0: for entrance in regions["Time Rift - Balcony"].entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "The Arctic Cruise - Finale")) + add_rule(entrance, lambda state: can_clear_act(state, world, "The Arctic Cruise - Finale")) for entrance in regions["Time Rift - Deep Sea"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Cake")) + add_rule(entrance, lambda state: has_relic_combo(state, world, "Cake")) - if mw.EnableDLC2[p].value > 0: + if world.multiworld.EnableDLC2[world.player].value > 0: for entrance in regions["Time Rift - Rumbi Factory"].entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Necklace")) + add_rule(entrance, lambda state: has_relic_combo(state, world, "Necklace")) # Basically the same as above, but without the need of the dict since we are just setting defaults # Called if Act Rando is disabled def set_default_rift_rules(world: World): - w = world - mw = world.multiworld - p = world.player - for entrance in mw.get_region("Time Rift - Gallery", p).entrances: - add_rule(entrance, lambda state: can_use_hat(state, w, HatType.BREWING) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.BIRDS))) + for entrance in world.multiworld.get_region("Time Rift - Gallery", world.player).entrances: + add_rule(entrance, lambda state: can_use_hat(state, world, HatType.BREWING) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS))) - for entrance in mw.get_region("Time Rift - The Lab", p).entrances: - add_rule(entrance, lambda state: can_use_hat(state, w, HatType.DWELLER) - and state.has("Time Piece", p, w.get_chapter_cost(ChapterIndex.ALPINE))) + for entrance in world.multiworld.get_region("Time Rift - The Lab", world.player).entrances: + add_rule(entrance, lambda state: can_use_hat(state, world, HatType.DWELLER) + and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE))) - for entrance in mw.get_region("Time Rift - Sewers", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - Sewers", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 4")) - reg_act_connection(w, "Down with the Mafia!", entrance.name) + reg_act_connection(world, "Down with the Mafia!", entrance.name) - for entrance in mw.get_region("Time Rift - Bazaar", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - Bazaar", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 6")) - reg_act_connection(w, "Heating Up Mafia Town", entrance.name) + reg_act_connection(world, "Heating Up Mafia Town", entrance.name) - for entrance in mw.get_region("Time Rift - Mafia of Cooks", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Burger")) + for entrance in world.multiworld.get_region("Time Rift - Mafia of Cooks", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "Burger")) - for entrance in mw.get_region("Time Rift - The Owl Express", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - The Owl Express", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 2")) add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 3")) - reg_act_connection(w, "Murder on the Owl Express", entrance.name) - reg_act_connection(w, "Picture Perfect", entrance.name) + reg_act_connection(world, "Murder on the Owl Express", entrance.name) + reg_act_connection(world, "Picture Perfect", entrance.name) - for entrance in mw.get_region("Time Rift - The Moon", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - The Moon", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 4")) add_rule(entrance, lambda state: can_clear_act(state, world, "Battle of the Birds - Act 5")) - reg_act_connection(w, "Train Rush", entrance.name) - reg_act_connection(w, "The Big Parade", entrance.name) + reg_act_connection(world, "Train Rush", entrance.name) + reg_act_connection(world, "The Big Parade", entrance.name) - for entrance in mw.get_region("Time Rift - Dead Bird Studio", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Train")) + for entrance in world.multiworld.get_region("Time Rift - Dead Bird Studio", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "Train")) - for entrance in mw.get_region("Time Rift - Pipe", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - Pipe", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Subcon Forest - Act 2")) - reg_act_connection(w, "The Subcon Well", entrance.name) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 2)) + reg_act_connection(world, "The Subcon Well", entrance.name) + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - for entrance in mw.get_region("Time Rift - Village", p).entrances: + for entrance in world.multiworld.get_region("Time Rift - Village", world.player).entrances: add_rule(entrance, lambda state: can_clear_act(state, world, "Subcon Forest - Act 4")) - reg_act_connection(w, "Queen Vanessa's Manor", entrance.name) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 2)) + reg_act_connection(world, "Queen Vanessa's Manor", entrance.name) + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - for entrance in mw.get_region("Time Rift - Sleepy Subcon", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "UFO")) - if mw.ShuffleSubconPaintings[p].value > 0: - add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", p, 3)) + for entrance in world.multiworld.get_region("Time Rift - Sleepy Subcon", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "UFO")) + if world.multiworld.ShuffleSubconPaintings[world.player].value > 0: + add_rule(entrance, lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - for entrance in mw.get_region("Time Rift - Curly Tail Trail", p).entrances: - add_rule(entrance, lambda state: state.has("Windmill Cleared", p)) + for entrance in world.multiworld.get_region("Time Rift - Curly Tail Trail", world.player).entrances: + add_rule(entrance, lambda state: state.has("Windmill Cleared", world.player)) - for entrance in mw.get_region("Time Rift - The Twilight Bell", p).entrances: - add_rule(entrance, lambda state: state.has("Twilight Bell Cleared", p)) + for entrance in world.multiworld.get_region("Time Rift - The Twilight Bell", world.player).entrances: + add_rule(entrance, lambda state: state.has("Twilight Bell Cleared", world.player)) - for entrance in mw.get_region("Time Rift - Alpine Skyline", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Crayon")) + for entrance in world.multiworld.get_region("Time Rift - Alpine Skyline", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "Crayon")) - if mw.EnableDLC1[p].value > 0: - for entrance in mw.get_region("Time Rift - Balcony", p).entrances: - add_rule(entrance, lambda state: can_clear_act(state, w, "The Arctic Cruise - Finale")) + if world.multiworld.EnableDLC1[world.player].value > 0: + for entrance in world.multiworld.get_region("Time Rift - Balcony", world.player).entrances: + add_rule(entrance, lambda state: can_clear_act(state, world, "The Arctic Cruise - Finale")) - for entrance in mw.get_region("Time Rift - Deep Sea", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Cake")) + for entrance in world.multiworld.get_region("Time Rift - Deep Sea", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "Cake")) - if mw.EnableDLC2[p].value > 0: - for entrance in mw.get_region("Time Rift - Rumbi Factory", p).entrances: - add_rule(entrance, lambda state: has_relic_combo(state, w, "Necklace")) + if world.multiworld.EnableDLC2[world.player].value > 0: + for entrance in world.multiworld.get_region("Time Rift - Rumbi Factory", world.player).entrances: + add_rule(entrance, lambda state: has_relic_combo(state, world, "Necklace")) def connect_regions(start_region: Region, exit_region: Region, entrancename: str, player: int) -> Entrance: @@ -686,131 +686,3 @@ def connect_regions(start_region: Region, exit_region: Region, entrancename: str start_region.exits.append(entrance) entrance.connect(exit_region) return entrance - - -def set_painting_rules(world: World): - add_rule(world.multiworld.get_location("Subcon Village - Snatcher Statue Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Gravestone", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Near Well", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Tree A", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Tree B", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Ice Wall", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Treehouse", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Swamp Tree Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Ice Cube Shack", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Manor Rooftop", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Well - Hookshot Badge Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Well - Above Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Well - On Pipe", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Well - Mushroom", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Queen Vanessa's Manor - Cellar", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Queen Vanessa's Manor - Bedroom Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Queen Vanessa's Manor - Hall Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Queen Vanessa's Manor - Chandelier", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Subcon Forest - Burning House", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Burning Tree Climb", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Burning Stump Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Burning Forest Treehouse", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Spider Bone Cage A", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Spider Bone Cage B", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Triple Spider Bounce", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Noose Treehouse", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Long Tree Climb Chest", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Infinite Yarn Bush", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 2)) - - add_rule(world.multiworld.get_location("Subcon Forest - Dweller Stump", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Dweller Floating Rocks", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Dweller Platforming Tree A", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Dweller Platforming Tree B", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Giant Time Piece", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Gallows", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Green and Purple Dweller Rocks", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Dweller Shack", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Tall Tree Hookshot Swing", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Subcon Forest - Magnet Badge Bush", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 3)) - - add_rule(world.multiworld.get_location("Act Completion (Contractual Obligations)", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Act Completion (The Subcon Well)", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) - - add_rule(world.multiworld.get_location("Act Completion (Queen Vanessa's Manor)", world.player), - lambda state: state.has("Progressive Painting Unlock", world.player, 1)) diff --git a/worlds/ahit/__init__.py b/worlds/ahit/__init__.py index 5dc5e48356..cd6da357eb 100644 --- a/worlds/ahit/__init__.py +++ b/worlds/ahit/__init__.py @@ -8,7 +8,7 @@ from .Regions import create_region, create_regions, connect_regions, randomize_a create_events, chapter_regions, act_chapters from .Locations import HatInTimeLocation, location_table, get_total_locations, contract_locations, is_location_valid, \ - get_location_names + get_location_names, get_tasksanity_start_id from .Types import HatDLC, HatType, ChapterIndex from .Options import ahit_options, slot_data_options, adjust_options @@ -18,6 +18,7 @@ import typing hat_craft_order: typing.Dict[int, typing.List[HatType]] = {} hat_yarn_costs: typing.Dict[int, typing.Dict[HatType, int]] = {} +slot_data_yarn_costs: typing.Dict[int, typing.Dict[HatType, int]] = {} chapter_timepiece_costs: typing.Dict[int, typing.Dict[ChapterIndex, int]] = {} @@ -79,6 +80,9 @@ class HatInTimeWorld(World): hat_yarn_costs[self.player] = {HatType.SPRINT: -1, HatType.BREWING: -1, HatType.ICE: -1, HatType.DWELLER: -1, HatType.TIME_STOP: -1} + slot_data_yarn_costs[self.player] = {HatType.SPRINT: -1, HatType.BREWING: -1, HatType.ICE: -1, + HatType.DWELLER: -1, HatType.TIME_STOP: -1} + hat_craft_order[self.player] = [HatType.SPRINT, HatType.BREWING, HatType.ICE, HatType.DWELLER, HatType.TIME_STOP] @@ -167,11 +171,11 @@ class HatInTimeWorld(World): return create_item(self, name) def fill_slot_data(self) -> dict: - slot_data: dict = {"SprintYarnCost": hat_yarn_costs[self.player][HatType.SPRINT], - "BrewingYarnCost": hat_yarn_costs[self.player][HatType.BREWING], - "IceYarnCost": hat_yarn_costs[self.player][HatType.ICE], - "DwellerYarnCost": hat_yarn_costs[self.player][HatType.DWELLER], - "TimeStopYarnCost": hat_yarn_costs[self.player][HatType.TIME_STOP], + slot_data: dict = {"SprintYarnCost": slot_data_yarn_costs[self.player][HatType.SPRINT], + "BrewingYarnCost": slot_data_yarn_costs[self.player][HatType.BREWING], + "IceYarnCost": slot_data_yarn_costs[self.player][HatType.ICE], + "DwellerYarnCost": slot_data_yarn_costs[self.player][HatType.DWELLER], + "TimeStopYarnCost": slot_data_yarn_costs[self.player][HatType.TIME_STOP], "Chapter1Cost": chapter_timepiece_costs[self.player][ChapterIndex.MAFIA], "Chapter2Cost": chapter_timepiece_costs[self.player][ChapterIndex.BIRDS], "Chapter3Cost": chapter_timepiece_costs[self.player][ChapterIndex.SUBCON], @@ -203,7 +207,7 @@ class HatInTimeWorld(World): def extend_hint_information(self, hint_data: typing.Dict[int, typing.Dict[int, str]]): new_hint_data = {} - alpine_regions = ["The Birdhouse", "The Lava Cake", "The Windmill", "The Twilight Bell"] + alpine_regions = ["The Birdhouse", "The Lava Cake", "The Windmill", "The Twilight Bell", "Alpine Skyline Area"] metro_regions = ["Yellow Overpass Station", "Green Clean Station", "Bluefin Tunnel", "Pink Paw Station"] for key, data in location_table.items(): @@ -226,7 +230,7 @@ class HatInTimeWorld(World): if self.multiworld.EnableDLC1[self.player].value > 0 and self.multiworld.Tasksanity[self.player].value > 0: ship_shape_region = self.get_shuffled_region("Ship Shape") - id_start: int = 300204 + id_start: int = get_tasksanity_start_id() for i in range(self.multiworld.TasksanityCheckCount[self.player].value): new_hint_data[id_start+i] = ship_shape_region @@ -248,7 +252,8 @@ class HatInTimeWorld(World): max_cost: int = 0 for i in range(5): cost = mw.random.randint(min(min_yarn_cost, max_yarn_cost), max(max_yarn_cost, min_yarn_cost)) - hat_yarn_costs[self.player][HatType(i)] = cost + hat_yarn_costs[self.player][HatType(i)] = cost + max_cost + slot_data_yarn_costs[self.player][HatType(i)] = cost max_cost += cost available_yarn = mw.YarnAvailable[p].value