| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | from worlds.AutoWorld import CollectionState | 
					
						
							|  |  |  | from worlds.generic.Rules import add_rule, set_rule | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  | from .Locations import location_table, zipline_unlocks, is_location_valid, shop_locations, event_locs | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | from .Types import HatType, ChapterIndex, hat_type_to_item, Difficulty, HitType | 
					
						
							|  |  |  | from BaseClasses import Location, Entrance, Region | 
					
						
							|  |  |  | from typing import TYPE_CHECKING, List, Callable, Union, Dict | 
					
						
							|  |  |  | from .Options import EndGoal, CTRLogic, NoTicketSkips | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if TYPE_CHECKING: | 
					
						
							|  |  |  |     from . import HatInTimeWorld | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | act_connections = { | 
					
						
							|  |  |  |     "Mafia Town - Act 2": ["Mafia Town - Act 1"], | 
					
						
							|  |  |  |     "Mafia Town - Act 3": ["Mafia Town - Act 1"], | 
					
						
							|  |  |  |     "Mafia Town - Act 4": ["Mafia Town - Act 2", "Mafia Town - Act 3"], | 
					
						
							|  |  |  |     "Mafia Town - Act 6": ["Mafia Town - Act 4"], | 
					
						
							|  |  |  |     "Mafia Town - Act 7": ["Mafia Town - Act 4"], | 
					
						
							|  |  |  |     "Mafia Town - Act 5": ["Mafia Town - Act 6", "Mafia Town - Act 7"], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "Battle of the Birds - Act 2": ["Battle of the Birds - Act 1"], | 
					
						
							|  |  |  |     "Battle of the Birds - Act 3": ["Battle of the Birds - Act 1"], | 
					
						
							|  |  |  |     "Battle of the Birds - Act 4": ["Battle of the Birds - Act 2", "Battle of the Birds - Act 3"], | 
					
						
							|  |  |  |     "Battle of the Birds - Act 5": ["Battle of the Birds - Act 2", "Battle of the Birds - Act 3"], | 
					
						
							|  |  |  |     "Battle of the Birds - Finale A": ["Battle of the Birds - Act 4", "Battle of the Birds - Act 5"], | 
					
						
							|  |  |  |     "Battle of the Birds - Finale B": ["Battle of the Birds - Finale A"], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "Subcon Forest - Finale": ["Subcon Forest - Act 1", "Subcon Forest - Act 2", | 
					
						
							|  |  |  |                                "Subcon Forest - Act 3", "Subcon Forest - Act 4", | 
					
						
							|  |  |  |                                "Subcon Forest - Act 5"], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     "The Arctic Cruise - Act 2":  ["The Arctic Cruise - Act 1"], | 
					
						
							|  |  |  |     "The Arctic Cruise - Finale": ["The Arctic Cruise - Act 2"], | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def can_use_hat(state: CollectionState, world: "HatInTimeWorld", hat: HatType) -> bool: | 
					
						
							|  |  |  |     if world.options.HatItems: | 
					
						
							|  |  |  |         return state.has(hat_type_to_item[hat], world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.hat_yarn_costs[hat] <= 0:  # this means the hat was put into starting inventory | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return state.has("Yarn", world.player, get_hat_cost(world, hat)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_hat_cost(world: "HatInTimeWorld", hat: HatType) -> int: | 
					
						
							|  |  |  |     cost = 0 | 
					
						
							|  |  |  |     for h in world.hat_craft_order: | 
					
						
							|  |  |  |         cost += world.hat_yarn_costs[h] | 
					
						
							|  |  |  |         if h == hat: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return cost | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def painting_logic(world: "HatInTimeWorld") -> bool: | 
					
						
							|  |  |  |     return bool(world.options.ShuffleSubconPaintings) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # -1 = Normal, 0 = Moderate, 1 = Hard, 2 = Expert | 
					
						
							|  |  |  | def get_difficulty(world: "HatInTimeWorld") -> Difficulty: | 
					
						
							|  |  |  |     return Difficulty(world.options.LogicDifficulty) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def has_paintings(state: CollectionState, world: "HatInTimeWorld", count: int, allow_skip: bool = True) -> bool: | 
					
						
							|  |  |  |     if not painting_logic(world): | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not world.options.NoPaintingSkips and allow_skip: | 
					
						
							|  |  |  |         # In Moderate there is a very easy trick to skip all the walls, except for the one guarding the boss arena | 
					
						
							|  |  |  |         if get_difficulty(world) >= Difficulty.MODERATE: | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return state.has("Progressive Painting Unlock", world.player, count) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def zipline_logic(world: "HatInTimeWorld") -> bool: | 
					
						
							|  |  |  |     return bool(world.options.ShuffleAlpineZiplines) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def can_use_hookshot(state: CollectionState, world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     return state.has("Hookshot Badge", world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def can_hit(state: CollectionState, world: "HatInTimeWorld", umbrella_only: bool = False): | 
					
						
							|  |  |  |     if not world.options.UmbrellaLogic: | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return state.has("Umbrella", world.player) or not umbrella_only and can_use_hat(state, world, HatType.BREWING) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def has_relic_combo(state: CollectionState, world: "HatInTimeWorld", relic: str) -> bool: | 
					
						
							|  |  |  |     return state.has_group(relic, world.player, len(world.item_name_groups[relic])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_relic_count(state: CollectionState, world: "HatInTimeWorld", relic: str) -> int: | 
					
						
							|  |  |  |     return state.count_group(relic, world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # This is used to determine if the player can clear an act that's required to unlock a Time Rift | 
					
						
							|  |  |  | def can_clear_required_act(state: CollectionState, world: "HatInTimeWorld", act_entrance: str) -> bool: | 
					
						
							|  |  |  |     entrance: Entrance = world.multiworld.get_entrance(act_entrance, world.player) | 
					
						
							|  |  |  |     if not state.can_reach(entrance.connected_region, "Region", world.player): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if "Free Roam" in entrance.connected_region.name: | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     name: str = f"Act Completion ({entrance.connected_region.name})" | 
					
						
							|  |  |  |     return world.multiworld.get_location(name, world.player).access_rule(state) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def can_clear_alpine(state: CollectionState, world: "HatInTimeWorld") -> bool: | 
					
						
							|  |  |  |     return state.has("Birdhouse Cleared", world.player) and state.has("Lava Cake Cleared", world.player) \ | 
					
						
							|  |  |  |             and state.has("Windmill Cleared", world.player) and state.has("Twilight Bell Cleared", world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def can_clear_metro(state: CollectionState, world: "HatInTimeWorld") -> bool: | 
					
						
							|  |  |  |     return state.has("Nyakuza Intro Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Yellow Overpass Station Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Yellow Overpass Manhole Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Green Clean Station Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Green Clean Manhole Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Bluefin Tunnel Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Pink Paw Station Cleared", world.player) \ | 
					
						
							|  |  |  |            and state.has("Pink Paw Manhole Cleared", world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     # First, chapter access | 
					
						
							|  |  |  |     starting_chapter = ChapterIndex(world.options.StartingChapter) | 
					
						
							|  |  |  |     world.chapter_timepiece_costs[starting_chapter] = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Chapter costs increase progressively. Randomly decide the chapter order, except for Finale | 
					
						
							|  |  |  |     chapter_list: List[ChapterIndex] = [ChapterIndex.MAFIA, ChapterIndex.BIRDS, | 
					
						
							|  |  |  |                                         ChapterIndex.SUBCON, ChapterIndex.ALPINE] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     final_chapter = ChapterIndex.FINALE | 
					
						
							|  |  |  |     if world.options.EndGoal == EndGoal.option_rush_hour: | 
					
						
							|  |  |  |         final_chapter = ChapterIndex.METRO | 
					
						
							|  |  |  |         chapter_list.append(ChapterIndex.FINALE) | 
					
						
							|  |  |  |     elif world.options.EndGoal == EndGoal.option_seal_the_deal: | 
					
						
							|  |  |  |         final_chapter = None | 
					
						
							|  |  |  |         chapter_list.append(ChapterIndex.FINALE) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         chapter_list.append(ChapterIndex.CRUISE) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  |     if world.is_dlc2() and final_chapter != ChapterIndex.METRO: | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  |         chapter_list.append(ChapterIndex.METRO) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     chapter_list.remove(starting_chapter) | 
					
						
							|  |  |  |     world.random.shuffle(chapter_list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Make sure Alpine is unlocked before any DLC chapters are, as the Alpine door needs to be open to access them | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  |     if starting_chapter != ChapterIndex.ALPINE and (world.is_dlc1() or world.is_dlc2()): | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  |         index1 = 69 | 
					
						
							|  |  |  |         index2 = 69 | 
					
						
							|  |  |  |         pos: int | 
					
						
							|  |  |  |         lowest_index: int | 
					
						
							|  |  |  |         chapter_list.remove(ChapterIndex.ALPINE) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if world.is_dlc1(): | 
					
						
							|  |  |  |             index1 = chapter_list.index(ChapterIndex.CRUISE) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  |         if world.is_dlc2() and final_chapter != ChapterIndex.METRO: | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  |             index2 = chapter_list.index(ChapterIndex.METRO) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lowest_index = min(index1, index2) | 
					
						
							|  |  |  |         if lowest_index == 0: | 
					
						
							|  |  |  |             pos = 0 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             pos = world.random.randint(0, lowest_index) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         chapter_list.insert(pos, ChapterIndex.ALPINE) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lowest_cost: int = world.options.LowestChapterCost.value | 
					
						
							|  |  |  |     highest_cost: int = world.options.HighestChapterCost.value | 
					
						
							|  |  |  |     cost_increment: int = world.options.ChapterCostIncrement.value | 
					
						
							|  |  |  |     min_difference: int = world.options.ChapterCostMinDifference.value | 
					
						
							|  |  |  |     last_cost = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for i, chapter in enumerate(chapter_list): | 
					
						
							|  |  |  |         min_range: int = lowest_cost + (cost_increment * i) | 
					
						
							|  |  |  |         if min_range >= highest_cost: | 
					
						
							|  |  |  |             min_range = highest_cost-1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         value: int = world.random.randint(min_range, min(highest_cost, max(lowest_cost, last_cost + cost_increment))) | 
					
						
							|  |  |  |         cost = world.random.randint(value, min(value + cost_increment, highest_cost)) | 
					
						
							|  |  |  |         if i >= 1: | 
					
						
							|  |  |  |             if last_cost + min_difference > cost: | 
					
						
							|  |  |  |                 cost = last_cost + min_difference | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cost = min(cost, highest_cost) | 
					
						
							|  |  |  |         world.chapter_timepiece_costs[chapter] = cost | 
					
						
							|  |  |  |         last_cost = cost | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if final_chapter is not None: | 
					
						
							|  |  |  |         final_chapter_cost: int | 
					
						
							|  |  |  |         if world.options.FinalChapterMinCost == world.options.FinalChapterMaxCost: | 
					
						
							|  |  |  |             final_chapter_cost = world.options.FinalChapterMaxCost.value | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             final_chapter_cost = world.random.randint(world.options.FinalChapterMinCost.value, | 
					
						
							|  |  |  |                                                       world.options.FinalChapterMaxCost.value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         world.chapter_timepiece_costs[final_chapter] = final_chapter_cost | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Mafia Town", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.MAFIA])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Battle of the Birds", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Subcon Forest", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.SUBCON])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Alpine Skyline", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.FINALE]) | 
					
						
							|  |  |  |              and can_use_hat(state, world, HatType.BREWING) and can_use_hat(state, world, HatType.DWELLER)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("Telescope -> Arctic Cruise", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE]) | 
					
						
							|  |  |  |                  and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.CRUISE])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("Telescope -> Nyakuza Metro", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE]) | 
					
						
							|  |  |  |                  and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.METRO]) | 
					
						
							|  |  |  |                  and can_use_hat(state, world, HatType.DWELLER) and can_use_hat(state, world, HatType.ICE)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not world.options.ActRandomizer: | 
					
						
							|  |  |  |         set_default_rift_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     table = {**location_table, **event_locs} | 
					
						
							|  |  |  |     for (key, data) in table.items(): | 
					
						
							|  |  |  |         if not is_location_valid(world, key): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         loc = world.multiworld.get_location(key, world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for hat in data.required_hats: | 
					
						
							|  |  |  |             add_rule(loc, lambda state, h=hat: can_use_hat(state, world, h)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if data.hookshot: | 
					
						
							|  |  |  |             add_rule(loc, lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if data.paintings > 0 and world.options.ShuffleSubconPaintings: | 
					
						
							|  |  |  |             add_rule(loc, lambda state, paintings=data.paintings: has_paintings(state, world, paintings)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  |         if data.hit_type != HitType.none and world.options.UmbrellaLogic: | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  |             if data.hit_type == HitType.umbrella: | 
					
						
							|  |  |  |                 add_rule(loc, lambda state: state.has("Umbrella", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             elif data.hit_type == HitType.umbrella_or_brewing: | 
					
						
							|  |  |  |                 add_rule(loc, lambda state: state.has("Umbrella", world.player) | 
					
						
							|  |  |  |                          or can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             elif data.hit_type == HitType.dweller_bell: | 
					
						
							|  |  |  |                 add_rule(loc, lambda state: state.has("Umbrella", world.player) | 
					
						
							|  |  |  |                          or can_use_hat(state, world, HatType.BREWING) | 
					
						
							|  |  |  |                          or can_use_hat(state, world, HatType.DWELLER)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for misc in data.misc_required: | 
					
						
							|  |  |  |             add_rule(loc, lambda state, item=misc: state.has(item, world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_specific_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Putting all of this here, so it doesn't get overridden by anything | 
					
						
							|  |  |  |     # Illness starts the player past the intro | 
					
						
							|  |  |  |     alpine_entrance = world.multiworld.get_entrance("AFR -> Alpine Skyline Area", world.player) | 
					
						
							|  |  |  |     add_rule(alpine_entrance, lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  |     if world.options.UmbrellaLogic: | 
					
						
							|  |  |  |         add_rule(alpine_entrance, lambda state: state.has("Umbrella", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if zipline_logic(world): | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("-> The Birdhouse", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Zipline Unlock - The Birdhouse Path", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("-> The Lava Cake", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Zipline Unlock - The Lava Cake Path", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("-> The Windmill", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Zipline Unlock - The Windmill Path", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_entrance("-> The Twilight Bell", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Zipline Unlock - The Twilight Bell Path", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_location("Act Completion (The Illness has Spread)", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Zipline Unlock - The Birdhouse Path", world.player) | 
					
						
							|  |  |  |                  and state.has("Zipline Unlock - The Lava Cake Path", world.player) | 
					
						
							|  |  |  |                  and state.has("Zipline Unlock - The Windmill Path", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if zipline_logic(world): | 
					
						
							|  |  |  |         for (loc, zipline) in zipline_unlocks.items(): | 
					
						
							|  |  |  |             add_rule(world.multiworld.get_location(loc, world.player), | 
					
						
							|  |  |  |                      lambda state, z=zipline: state.has(z, world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dummy_entrances: List[Entrance] = [] | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |     for (key, acts) in act_connections.items(): | 
					
						
							|  |  |  |         if "Arctic Cruise" in key and not world.is_dlc1(): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         entrance: Entrance = world.multiworld.get_entrance(key, world.player) | 
					
						
							|  |  |  |         region: Region = entrance.connected_region | 
					
						
							|  |  |  |         access_rules: List[Callable[[CollectionState], bool]] = [] | 
					
						
							|  |  |  |         dummy_entrances.append(entrance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Entrances to this act that we have to set access_rules on | 
					
						
							|  |  |  |         entrances: List[Entrance] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for i, act in enumerate(acts, start=1): | 
					
						
							|  |  |  |             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 = f"{key}: Connection {i}" | 
					
						
							|  |  |  |             new_entrance: Entrance = required_region.connect(region, name) | 
					
						
							|  |  |  |             entrances.append(new_entrance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Copy access rules from act completions | 
					
						
							|  |  |  |             if "Free Roam" not in required_region.name: | 
					
						
							|  |  |  |                 rule: Callable[[CollectionState], bool] | 
					
						
							|  |  |  |                 name = f"Act Completion ({required_region.name})" | 
					
						
							|  |  |  |                 rule = world.multiworld.get_location(name, world.player).access_rule | 
					
						
							|  |  |  |                 access_rules.append(rule) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for e in entrances: | 
					
						
							|  |  |  |             for rules in access_rules: | 
					
						
							|  |  |  |                 add_rule(e, rules) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for e in dummy_entrances: | 
					
						
							|  |  |  |         set_rule(e, lambda state: False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_event_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.options.EndGoal == EndGoal.option_finale: | 
					
						
							|  |  |  |         world.multiworld.completion_condition[world.player] = lambda state: state.has("Time Piece Cluster", world.player) | 
					
						
							|  |  |  |     elif world.options.EndGoal == EndGoal.option_rush_hour: | 
					
						
							|  |  |  |         world.multiworld.completion_condition[world.player] = lambda state: state.has("Rush Hour Cleared", world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_specific_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     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.chapter_timepiece_costs[ChapterIndex.BIRDS])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_mafia_town_rules(world) | 
					
						
							|  |  |  |     set_botb_rules(world) | 
					
						
							|  |  |  |     set_subcon_rules(world) | 
					
						
							|  |  |  |     set_alps_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         set_dlc1_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         set_dlc2_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     difficulty: Difficulty = get_difficulty(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if difficulty >= Difficulty.MODERATE: | 
					
						
							|  |  |  |         set_moderate_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if difficulty >= Difficulty.HARD: | 
					
						
							|  |  |  |         set_hard_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if difficulty >= Difficulty.EXPERT: | 
					
						
							|  |  |  |         set_expert_rules(world) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_moderate_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     # Moderate: Gallery without Brewing Hat | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Time Rift - Gallery)", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Above Boats via Ice Hat Sliding | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hat(state, world, HatType.ICE), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Clock Tower Chest + Ruined Tower with nothing | 
					
						
							| 
									
										
										
										
											2024-08-29 07:11:02 +01:00
										 |  |  |     set_rule(world.multiworld.get_location("Mafia Town - Clock Tower Chest", world.player), lambda state: True) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Mafia Town - Top of Ruined Tower", world.player), lambda state: True) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: enter and clear The Subcon Well without Hookshot and without hitting the bell | 
					
						
							|  |  |  |     for loc in world.multiworld.get_region("The Subcon Well", world.player).locations: | 
					
						
							|  |  |  |         set_rule(loc, lambda state: has_paintings(state, world, 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Vanessa Manor with nothing | 
					
						
							|  |  |  |     for loc in world.multiworld.get_region("Queen Vanessa's Manor", world.player).locations: | 
					
						
							|  |  |  |         set_rule(loc, lambda state: has_paintings(state, world, 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Manor Rooftop", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Village Time Rift with nothing IF umbrella logic is off | 
					
						
							|  |  |  |     if not world.options.UmbrellaLogic: | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Time Rift - Village)", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: get to Birdhouse/Yellow Band Hills without Brewing Hat | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_entrance("-> The Birdhouse", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Alpine Skyline - Yellow Band Hills", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: The Birdhouse - Dweller Platforms Relic with only Birdhouse access | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Alpine Skyline - The Birdhouse: Dweller Platforms Relic", world.player), | 
					
						
							|  |  |  |              lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Twilight Path without Dweller Mask | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Alpine Skyline - The Twilight Path", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Mystifying Time Mesa time trial without hats | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Alpine Skyline - Mystifying Time Mesa: Zipline", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Goat Refinery from TIHS with Sprint only | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("TIHS Access", world.player) | 
					
						
							|  |  |  |              and can_use_hat(state, world, HatType.SPRINT), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Finale Telescope with only Ice Hat | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.FINALE]) | 
					
						
							|  |  |  |              and can_use_hat(state, world, HatType.ICE), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Moderate: Finale without Hookshot | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (The Finale)", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hat(state, world, HatType.DWELLER)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         # Moderate: clear Rock the Boat without Ice Hat | 
					
						
							| 
									
										
										
										
											2024-08-29 07:11:02 +01:00
										 |  |  |         set_rule(world.multiworld.get_location("Rock the Boat - Post Captain Rescue", world.player), lambda state: True) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Rock the Boat)", world.player), lambda state: True) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Moderate: clear Deep Sea without Ice Hat | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Time Rift - Deep Sea)", world.player), | 
					
						
							|  |  |  |                  lambda state: can_use_hookshot(state, world) and can_use_hat(state, world, HatType.DWELLER)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # There is a glitched fall damage volume near the Yellow Overpass time piece that warps the player to Pink Paw. | 
					
						
							|  |  |  |     # Yellow Overpass time piece can also be reached without Hookshot quite easily. | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         # No Hookshot | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Yellow Overpass Station)", world.player), | 
					
						
							|  |  |  |                  lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # No Dweller, Hookshot, or Time Stop for these | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Pink Paw Station - Cat Vacuum", world.player), lambda state: True) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Pink Paw Station - Behind Fan", world.player), lambda state: True) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Pink Paw Station - Pink Ticket Booth", world.player), lambda state: True) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Pink Paw Station)", world.player), lambda state: True) | 
					
						
							|  |  |  |         for key in shop_locations.keys(): | 
					
						
							|  |  |  |             if "Pink Paw Station Thug" in key and is_location_valid(world, key): | 
					
						
							|  |  |  |                 set_rule(world.multiworld.get_location(key, world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Moderate: clear Rush Hour without Hookshot | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Metro Ticket - Pink", world.player) | 
					
						
							|  |  |  |                  and state.has("Metro Ticket - Yellow", world.player) | 
					
						
							|  |  |  |                  and state.has("Metro Ticket - Blue", world.player) | 
					
						
							|  |  |  |                  and can_use_hat(state, world, HatType.ICE) | 
					
						
							|  |  |  |                  and can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Moderate: Bluefin Tunnel + Pink Paw Station without tickets | 
					
						
							|  |  |  |         if not world.options.NoTicketSkips: | 
					
						
							|  |  |  |             set_rule(world.multiworld.get_entrance("-> Pink Paw Station", world.player), lambda state: True) | 
					
						
							|  |  |  |             set_rule(world.multiworld.get_entrance("-> Bluefin Tunnel", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_hard_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     # Hard: clear Time Rift - The Twilight Bell with Sprint+Scooter only | 
					
						
							|  |  |  |     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") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # No Dweller Mask required | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Dweller Floating Rocks", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 3)) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Dweller Platforming Tree B", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 3)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Cherry bridge over boss arena gap (painting still expected) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Boss Arena Chest", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 1, False) or state.has("YCHE Access", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Noose Treehouse", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 2, True)) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Long Tree Climb Chest", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 2, True)) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Tall Tree Hookshot Swing", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 3, True)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # SDJ | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Subcon Forest - Long Tree Climb Chest", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hat(state, world, HatType.SPRINT) and has_paintings(state, world, 2), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Act Completion (Time Rift - Curly Tail Trail)", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hat(state, world, HatType.SPRINT), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Hard: Goat Refinery from TIHS with nothing | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("TIHS Access", world.player), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         # Hard: clear Deep Sea without Dweller Mask | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Time Rift - Deep Sea)", world.player), | 
					
						
							|  |  |  |                  lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         # Hard: clear Green Clean Manhole without Dweller Mask | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Green Clean Manhole)", world.player), | 
					
						
							|  |  |  |                  lambda state: can_use_hat(state, world, HatType.ICE)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Hard: clear Rush Hour with Brewing Hat only | 
					
						
							| 
									
										
										
										
											2024-07-27 13:16:52 -04:00
										 |  |  |         if world.options.NoTicketSkips != NoTicketSkips.option_true: | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  |             set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), | 
					
						
							|  |  |  |                      lambda state: can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), | 
					
						
							|  |  |  |                      lambda state: can_use_hat(state, world, HatType.BREWING) | 
					
						
							|  |  |  |                      and state.has("Metro Ticket - Yellow", world.player) | 
					
						
							|  |  |  |                      and state.has("Metro Ticket - Blue", world.player) | 
					
						
							|  |  |  |                      and state.has("Metro Ticket - Pink", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_expert_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     # Finale Telescope with no hats | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.FINALE])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: Mafia Town - Above Boats, Top of Lighthouse, and Hot Air Balloon with nothing | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player), lambda state: True) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Mafia Town - Top of Lighthouse", world.player), lambda state: True) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Mafia Town - Hot Air Balloon", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: Clear Dead Bird Studio with nothing | 
					
						
							|  |  |  |     for loc in world.multiworld.get_region("Dead Bird Studio - Post Elevator Area", world.player).locations: | 
					
						
							|  |  |  |         set_rule(loc, lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Dead Bird Studio)", world.player), lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: Clear Dead Bird Studio Basement without Hookshot | 
					
						
							|  |  |  |     for loc in world.multiworld.get_region("Dead Bird Studio Basement", world.player).locations: | 
					
						
							|  |  |  |         set_rule(loc, lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: get to and clear Twilight Bell without Dweller Mask. | 
					
						
							|  |  |  |     # Dweller Mask OR Sprint Hat OR Brewing Hat OR Time Stop + Umbrella required to complete act. | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("-> The Twilight Bell", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Act Completion (The Twilight Bell)", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hat(state, world, HatType.BREWING) | 
					
						
							|  |  |  |              or can_use_hat(state, world, HatType.DWELLER) | 
					
						
							|  |  |  |              or can_use_hat(state, world, HatType.SPRINT) | 
					
						
							|  |  |  |              or (can_use_hat(state, world, HatType.TIME_STOP) and state.has("Umbrella", world.player))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: Time Rift - Curly Tail Trail with nothing | 
					
						
							|  |  |  |     # Time Rift - Twilight Bell and Time Rift - Village with nothing | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Time Rift - Curly Tail Trail)", world.player), | 
					
						
							|  |  |  |              lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Time Rift - Village)", world.player), lambda state: True) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Time Rift - The Twilight Bell)", world.player), | 
					
						
							|  |  |  |              lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Expert: Cherry Hovering | 
					
						
							|  |  |  |     subcon_area = world.multiworld.get_region("Subcon Forest Area", world.player) | 
					
						
							|  |  |  |     yche = world.multiworld.get_region("Your Contract has Expired", world.player) | 
					
						
							|  |  |  |     entrance = yche.connect(subcon_area, "Subcon Forest Entrance YCHE") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.options.NoPaintingSkips: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: has_paintings(state, world, 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world) and can_hit(state, world) | 
					
						
							|  |  |  |              and has_paintings(state, world, 1, True)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Set painting rules only. Skipping paintings is determined in has_paintings | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Boss Arena Chest", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 1, True)) | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Magnet Badge Bush", world.player), | 
					
						
							|  |  |  |              lambda state: has_paintings(state, world, 3, True)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # You can cherry hover to Snatcher's post-fight cutscene, which completes the level without having to fight him | 
					
						
							|  |  |  |     subcon_area.connect(yche, "Snatcher Hover") | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Your Contract has Expired)", world.player), | 
					
						
							|  |  |  |              lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         # Expert: clear Rush Hour with nothing | 
					
						
							|  |  |  |         if not world.options.NoTicketSkips: | 
					
						
							|  |  |  |             set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), lambda state: True) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             set_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)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Expert: Yellow/Green Manhole with nothing using a Boop Clip | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Yellow Overpass Manhole)", world.player), | 
					
						
							|  |  |  |                  lambda state: True) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Green Clean Manhole)", world.player), | 
					
						
							|  |  |  |                  lambda state: True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_mafia_town_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     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(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(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(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(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 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Mafia Town - Secret Cave", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("HUMT Access", world.player), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Can bounce across the lava to get this without Hookshot (need to die though) | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("HUMT Access", world.player), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.options.CTRLogic == CTRLogic.option_nothing: | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), lambda state: True) | 
					
						
							|  |  |  |     elif world.options.CTRLogic == CTRLogic.option_sprint: | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), | 
					
						
							|  |  |  |                  lambda state: can_use_hat(state, world, HatType.SPRINT), "or") | 
					
						
							|  |  |  |     elif world.options.CTRLogic == CTRLogic.option_scooter: | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), | 
					
						
							|  |  |  |                  lambda state: can_use_hat(state, world, HatType.SPRINT) | 
					
						
							|  |  |  |                  and state.has("Scooter Badge", world.player), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_botb_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     if not world.options.UmbrellaLogic and get_difficulty(world) < Difficulty.MODERATE: | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Dead Bird Studio - DJ Grooves Sign Chest", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Dead Bird Studio - Tepee Chest", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Dead Bird Studio - Conductor Chest", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  |         set_rule(world.multiworld.get_location("Act Completion (Dead Bird Studio)", world.player), | 
					
						
							|  |  |  |                  lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_subcon_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     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)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # You can't skip over the boss arena wall without cherry hover, so these two need to be set this way | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Subcon Forest - Boss Arena Chest", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("TOD Access", world.player) and can_use_hookshot(state, world) | 
					
						
							|  |  |  |              and has_paintings(state, world, 1, False) or state.has("YCHE Access", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # The painting wall can't be skipped without cherry hover, which is Expert | 
					
						
							|  |  |  |     set_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world) and can_hit(state, world) | 
					
						
							|  |  |  |              and has_paintings(state, world, 1, False)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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(world.multiworld.get_entrance("Subcon Forest - Act 3", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Snatcher's Contract - Toilet of Doom", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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(world.multiworld.get_entrance("Subcon Forest - Act 5", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("Snatcher's Contract - Mail Delivery Service", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if painting_logic(world): | 
					
						
							|  |  |  |         add_rule(world.multiworld.get_location("Act Completion (Contractual Obligations)", world.player), | 
					
						
							|  |  |  |                  lambda state: has_paintings(state, world, 1, False)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_alps_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("-> The Birdhouse", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world) and can_use_hat(state, world, HatType.BREWING)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("-> The Lava Cake", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("-> The Windmill", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("-> The Twilight Bell", world.player), | 
					
						
							|  |  |  |              lambda state: can_use_hookshot(state, world) and can_use_hat(state, world, HatType.DWELLER)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_entrance("Alpine Skyline - Finale", world.player), | 
					
						
							|  |  |  |              lambda state: can_clear_alpine(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player), | 
					
						
							|  |  |  |              lambda state: state.has("AFR Access", world.player) | 
					
						
							|  |  |  |              and can_use_hookshot(state, world) | 
					
						
							|  |  |  |              and can_hit(state, world, True)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_dlc1_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     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(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)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_dlc2_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     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(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(world.multiworld.get_entrance("Nyakuza Metro - Finale", world.player), | 
					
						
							|  |  |  |              lambda state: can_clear_metro(state, world)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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(world, key): | 
					
						
							|  |  |  |             add_rule(world.multiworld.get_location(key, world.player), | 
					
						
							|  |  |  |                      lambda state: state.has("Metro Ticket - Yellow", world.player), "or") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def reg_act_connection(world: "HatInTimeWorld", region: Union[str, Region], unlocked_entrance: Union[str, Entrance]): | 
					
						
							|  |  |  |     reg: Region | 
					
						
							|  |  |  |     entrance: Entrance | 
					
						
							|  |  |  |     if isinstance(region, str): | 
					
						
							|  |  |  |         reg = world.multiworld.get_region(region, world.player) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         reg = region | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if isinstance(unlocked_entrance, str): | 
					
						
							|  |  |  |         entrance = world.multiworld.get_entrance(unlocked_entrance, world.player) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         entrance = unlocked_entrance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     world.multiworld.register_indirect_condition(reg, entrance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # See randomize_act_entrances in Regions.py | 
					
						
							|  |  |  | # Called before set_rules | 
					
						
							|  |  |  | def set_rift_rules(world: "HatInTimeWorld", regions: Dict[str, Region]): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # 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, world, HatType.BREWING) | 
					
						
							|  |  |  |                  and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - The Lab"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_use_hat(state, world, HatType.DWELLER) | 
					
						
							|  |  |  |                  and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Sewers"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_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_required_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, world, "Burger")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - The Owl Express"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Battle of the Birds - Act 2")) | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_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_required_act(state, world, "Battle of the Birds - Act 4")) | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_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, world, "Train")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Pipe"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_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 painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Village"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_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 painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Sleepy Subcon"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: has_relic_combo(state, world, "UFO")) | 
					
						
							|  |  |  |         if painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 3)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Curly Tail Trail"].entrances: | 
					
						
							|  |  |  |         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", world.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in regions["Time Rift - Alpine Skyline"].entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: has_relic_combo(state, world, "Crayon")) | 
					
						
							| 
									
										
										
										
											2024-08-29 07:11:42 +01:00
										 |  |  |         if entrance.parent_region.name == "Alpine Free Roam": | 
					
						
							|  |  |  |             add_rule(entrance, | 
					
						
							|  |  |  |                      lambda state: can_use_hookshot(state, world) and can_hit(state, world, umbrella_only=True)) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         for entrance in regions["Time Rift - Balcony"].entrances: | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: can_clear_required_act(state, world, "The Arctic Cruise - Finale")) | 
					
						
							| 
									
										
										
										
											2024-07-14 08:17:05 -04:00
										 |  |  |             reg_act_connection(world, world.multiworld.get_entrance("The Arctic Cruise - Finale", | 
					
						
							|  |  |  |                                                                     world.player).connected_region, entrance) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for entrance in regions["Time Rift - Deep Sea"].entrances: | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_relic_combo(state, world, "Cake")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc2(): | 
					
						
							|  |  |  |         for entrance in regions["Time Rift - Rumbi Factory"].entrances: | 
					
						
							|  |  |  |             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: "HatInTimeWorld"): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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.chapter_timepiece_costs[ChapterIndex.BIRDS])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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.chapter_timepiece_costs[ChapterIndex.ALPINE])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in world.multiworld.get_region("Time Rift - Sewers", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Mafia Town - Act 4")) | 
					
						
							|  |  |  |         reg_act_connection(world, "Down with the Mafia!", entrance.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in world.multiworld.get_region("Time Rift - Bazaar", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Mafia Town - Act 6")) | 
					
						
							|  |  |  |         reg_act_connection(world, "Heating Up Mafia Town", entrance.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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 world.multiworld.get_region("Time Rift - The Owl Express", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Battle of the Birds - Act 2")) | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Battle of the Birds - Act 3")) | 
					
						
							|  |  |  |         reg_act_connection(world, "Murder on the Owl Express", entrance.name) | 
					
						
							|  |  |  |         reg_act_connection(world, "Picture Perfect", entrance.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in world.multiworld.get_region("Time Rift - The Moon", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Battle of the Birds - Act 4")) | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Battle of the Birds - Act 5")) | 
					
						
							|  |  |  |         reg_act_connection(world, "Train Rush", entrance.name) | 
					
						
							|  |  |  |         reg_act_connection(world, "The Big Parade", entrance.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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 world.multiworld.get_region("Time Rift - Pipe", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Subcon Forest - Act 2")) | 
					
						
							|  |  |  |         reg_act_connection(world, "The Subcon Well", entrance.name) | 
					
						
							|  |  |  |         if painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for entrance in world.multiworld.get_region("Time Rift - Village", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: can_clear_required_act(state, world, "Subcon Forest - Act 4")) | 
					
						
							|  |  |  |         reg_act_connection(world, "Queen Vanessa's Manor", entrance.name) | 
					
						
							|  |  |  |         if painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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 painting_logic(world): | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: has_paintings(state, world, 3)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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 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 world.multiworld.get_region("Time Rift - Alpine Skyline", world.player).entrances: | 
					
						
							|  |  |  |         add_rule(entrance, lambda state: has_relic_combo(state, world, "Crayon")) | 
					
						
							| 
									
										
										
										
											2024-08-29 07:11:42 +01:00
										 |  |  |         if entrance.parent_region.name == "Alpine Free Roam": | 
					
						
							|  |  |  |             add_rule(entrance, | 
					
						
							|  |  |  |                      lambda state: can_use_hookshot(state, world) and can_hit(state, world, umbrella_only=True)) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if world.is_dlc1(): | 
					
						
							|  |  |  |         for entrance in world.multiworld.get_region("Time Rift - Balcony", world.player).entrances: | 
					
						
							|  |  |  |             add_rule(entrance, lambda state: can_clear_required_act(state, world, "The Arctic Cruise - Finale")) | 
					
						
							| 
									
										
										
										
											2024-07-14 08:17:05 -04:00
										 |  |  |             reg_act_connection(world, "Rock the Boat", entrance.name) | 
					
						
							| 
									
										
										
										
											2024-05-20 03:04:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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 world.is_dlc2(): | 
					
						
							|  |  |  |         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 set_event_rules(world: "HatInTimeWorld"): | 
					
						
							|  |  |  |     for (name, data) in event_locs.items(): | 
					
						
							|  |  |  |         if not is_location_valid(world, name): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         event: Location = world.multiworld.get_location(name, world.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if data.act_event: | 
					
						
							|  |  |  |             add_rule(event, world.multiworld.get_location(f"Act Completion ({data.region})", world.player).access_rule) |