diff --git a/worlds/blueprince/data_other_locations.py b/worlds/blueprince/data_other_locations.py index ac3f6c168d52..b9554b7f6c7b 100644 --- a/worlds/blueprince/data_other_locations.py +++ b/worlds/blueprince/data_other_locations.py @@ -7,45 +7,53 @@ room_location_mem = {} + def get_room_location_id(room_name: str, n: int = 0) -> int: if room_name not in room_location_mem: room_location_mem[room_name] = [] if n in room_location_mem[room_name]: raise Exception(f"Duplicate location ID for {room_name} {n}") - + if room_name in rooms: - return rooms[room_name][ROOM_ITEM_ID_KEY] * ROOM_MULTIPLIER + n + return rooms[room_name][ROOM_ITEM_ID_KEY] * ROOM_MULTIPLIER + n + 1000 else: - return (room_name.__hash__() % 100 + 1000) * ROOM_MULTIPLIER + n + return (room_name.__hash__() % 10000000 + 1000) * ROOM_MULTIPLIER + n + 1000 + def can_reach_item_location(item_name: str, state: CollectionState, world) -> bool: loc_name = item_name + " First Pickup" if state.has(loc_name, world.player): return True - + if loc_name in locations: return state.can_reach_location(loc_name, world.player) for location, data in locations.items(): if LOCATION_ITEM_KEY in data and data[LOCATION_ITEM_KEY] == item_name: return state.can_reach_location(location, world.player) - + if item_name in armory_items: return state.can_reach_region("The Armory", world.player) - + return False + trophies = { "Full House Trophy": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 0), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: state.count_from_list([x for x in room_layout_lists[INNER_ROOM_KEY] if x not in core_rooms], world.player) >= 43 + LOCATION_RULE: lambda state, world: state.count_from_list( + [x for x in room_layout_lists[INNER_ROOM_KEY] if x not in core_rooms], world.player + ) + >= 43, }, "Trophy of Invention": { LOCATION_ID_KEY: get_room_location_id("Workshop", 0), LOCATION_ROOM_KEY: "Workshop", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in [ + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) + for item in [ "Burning Glass", "Detector Shovel", "Dowsing Rod", @@ -55,12 +63,22 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Pick Sound Amplifier", "Power Hammer", ] - ) + ), }, "Trophy of Drafting": { LOCATION_ID_KEY: get_room_location_id("Mail Room", 0), LOCATION_ROOM_KEY: "Mail Room", - LOCATION_RULE: lambda state, world: len([x for x in rooms if rooms[x][ROOM_LAYOUT_TYPE_KEY] == ROOM_LAYOUT_TYPE_D and not rooms[x][OUTER_ROOM_KEY] and x not in core_rooms and state.can_reach_region(x, world.player)]) >= 20, + LOCATION_RULE: lambda state, world: len( + [ + x + for x in rooms + if rooms[x][ROOM_LAYOUT_TYPE_KEY] == ROOM_LAYOUT_TYPE_D + and not rooms[x][OUTER_ROOM_KEY] + and x not in core_rooms + and state.can_reach_region(x, world.player) + ] + ) + >= 20, }, "Trophy of Wealth": { LOCATION_ID_KEY: get_room_location_id("Showroom", 0), @@ -71,7 +89,7 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo LOCATION_ID_KEY: get_room_location_id("Room 46", 0), LOCATION_ROOM_KEY: "Room 46", }, - "Bullesye Trophy": { + "Bullseye Trophy": { LOCATION_ID_KEY: get_room_location_id("Billiard Room", 0), LOCATION_ROOM_KEY: "Billiard Room", }, @@ -86,12 +104,16 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Explorer's Trophy": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 1), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: state.has_all([x for x in rooms if x not in core_rooms and (x not in classrooms or x == "Classroom 1")], world.player) + LOCATION_RULE: lambda state, world: state.has_all( + [x for x in rooms if x not in core_rooms and (x not in classrooms or x == "Classroom 1")], world.player + ), }, "Trophy of Sigils": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 2), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: all(state.can_reach_region(sanctum, world.player) for sanctum in [ + LOCATION_RULE: lambda state, world: all( + state.can_reach_region(sanctum, world.player) + for sanctum in [ "Orinda Aries Sanctum", "Fenn Aries Sanctum", "Arch Aries Sanctum", @@ -101,12 +123,14 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Verra Sanctum", "Nuance Sanctum", ] - ) + ), }, "Diploma Trophy": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 3), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: all(state.can_reach_region(region, world.player) for region in [ + LOCATION_RULE: lambda state, world: all( + state.can_reach_region(region, world.player) + for region in [ "Schoolhouse", "Classroom 1", "Classroom 2", @@ -118,9 +142,8 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Classroom 8", "Classroom Exam", ] - ) - } - + ), + }, # For if we add new game+ trophies, mostly here for completeness sake # "Dare Bird Trophy": { # LOCATION_ID_KEY: get_room_location_id("Room 46") + 1, @@ -147,7 +170,7 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo # "Trophy of Drafting", # "Trophy of Wealth", # "Inheritance Trophy", - # "Bullesye Trophy", + # "Bullseye Trophy", # "A Logical Trophy", # "Trophy 8", # "Explorer's Trophy", @@ -170,7 +193,7 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Drafting Studio Safe": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 0), LOCATION_ROOM_KEY: "Drafting Studio", - LOCATION_RULE: lambda state, world: can_reach_item_location("MAGNIFYING GLASS", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("MAGNIFYING GLASS", state, world), }, "Drawing Room Safe": { LOCATION_ID_KEY: get_room_location_id("Drawing Room", 0), @@ -185,9 +208,9 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo LOCATION_ROOM_KEY: "Study", }, "Underpass Gate": { - LOCATION_ID_KEY: get_room_location_id("The Underpass", 0), + LOCATION_ID_KEY: get_room_location_id("The Underpass", 1), LOCATION_ROOM_KEY: "The Underpass", - LOCATION_RULE: lambda state, world: state.can_reach_region("Boiler Room", world.player) + LOCATION_RULE: lambda state, world: state.can_reach_region("Boiler Room", world.player), }, "Shelter Safe": { LOCATION_ID_KEY: get_room_location_id("Shelter", 0), @@ -196,14 +219,15 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Orchard Gate": { LOCATION_ID_KEY: get_room_location_id("Campsite", 0), LOCATION_ROOM_KEY: "Campsite", - } + }, } aries_court_mora_jia_boxes = { f"Aries Court Mora Jia Box {n}": { LOCATION_ID_KEY: get_room_location_id("Aries Court", n - 1), LOCATION_ROOM_KEY: "Aries Court", - } for n in range(1, 9) + } + for n in range(1, 9) } mora_jia_boxes = { @@ -211,12 +235,12 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo LOCATION_ID_KEY: get_room_location_id("Master Bedroom", 0), LOCATION_ROOM_KEY: "Master Bedroom", }, - "Closed Exhbit Mora Jia Box": { + "Closed Exhibit Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Closed Exhibit", 0), LOCATION_ROOM_KEY: "Closed Exhibit", }, "Underpass Mora Jia Box": { - LOCATION_ID_KEY: get_room_location_id("The Underpass", 0), + LOCATION_ID_KEY: get_room_location_id("The Underpass", 2), LOCATION_ROOM_KEY: "The Underpass", }, "Tomb Mora Jia Box": { @@ -224,30 +248,33 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo LOCATION_ROOM_KEY: "Tomb", }, "Trading Post Mora Jia Box": { - LOCATION_ID_KEY: get_room_location_id("Trading Post", 0), + LOCATION_ID_KEY: get_room_location_id("Trading Post", 2), LOCATION_ROOM_KEY: "Trading Post", }, "Tunnel Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Tunnel", 0), LOCATION_ROOM_KEY: "Tunnel", }, - "Solaium Mora Jia Box": { + "Solarium Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Solarium", 0), LOCATION_ROOM_KEY: "Solarium", }, "Lost And Found Mora Jia Box": { - LOCATION_ID_KEY: get_room_location_id("Lost And Found", 0), + LOCATION_ID_KEY: get_room_location_id("Lost And Found", 1), LOCATION_ROOM_KEY: "Lost And Found", }, "Throne of the Blue Prince Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Throne Room", 0), LOCATION_ROOM_KEY: "Throne Room", - LOCATION_RULE: lambda state, world: state.has("Ascend The Throne", world.player) and - all(can_reach_item_location(item, state, world) for item in [ - "CROWN", - "ROYAL SCEPTER", - "CURSED EFFIGY", - ]) + LOCATION_RULE: lambda state, world: state.has("Ascend The Throne", world.player) + and all( + can_reach_item_location(item, state, world) + for item in [ + "CROWN", + "ROYAL SCEPTER", + "CURSED EFFIGY", + ] + ), }, "Arch Aries Sanctum Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Arch Aries Sanctum", 0), @@ -280,50 +307,50 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Nuance Sanctum Mora Jia Box": { LOCATION_ID_KEY: get_room_location_id("Nuance Sanctum", 0), LOCATION_ROOM_KEY: "Nuance Sanctum", - } + }, } | aries_court_mora_jia_boxes -# not adding atelier boxes, since they are bascially already at the latest goal +# not adding atelier boxes, since they are basically already at the latest goal drafting_studio_additions = { "Dovecote Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 1), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Dovecote" + NONSANITY_LOCATION_KEY: "Dovecote", }, "The Kennel Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 2), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "The Kennel" + NONSANITY_LOCATION_KEY: "The Kennel", }, "Clock Tower Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 3), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Clock Tower" + NONSANITY_LOCATION_KEY: "Clock Tower", }, "Classroom Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 4), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Classroom Exam" + NONSANITY_LOCATION_KEY: "Classroom Exam", }, "Solarium Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 5), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Solarium" + NONSANITY_LOCATION_KEY: "Solarium", }, "Dormitory Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 6), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Dormitory" + NONSANITY_LOCATION_KEY: "Dormitory", }, "Vestibule Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 7), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Vestibule" + NONSANITY_LOCATION_KEY: "Vestibule", }, "Casino Floorplan": { LOCATION_ID_KEY: get_room_location_id("Drafting Studio", 8), LOCATION_ROOM_KEY: "Drafting Studio", - NONSANITY_LOCATION_KEY: "Casino" + NONSANITY_LOCATION_KEY: "Casino", }, } @@ -331,28 +358,28 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Planetarium Floorplan": { LOCATION_ID_KEY: get_room_location_id("Observatory", 0), LOCATION_ROOM_KEY: "Observatory", - NONSANITY_LOCATION_KEY: "Planetarium" + NONSANITY_LOCATION_KEY: "Planetarium", }, "Mechanarium Floorplan": { LOCATION_ID_KEY: get_room_location_id("Rotating Gear", 0), LOCATION_ROOM_KEY: "Rotating Gear", - NONSANITY_LOCATION_KEY: "Mechanarium" + NONSANITY_LOCATION_KEY: "Mechanarium", }, "Treasure Trove Floorplan": { LOCATION_ID_KEY: get_room_location_id("The Underpass", 0), LOCATION_ROOM_KEY: "The Underpass", LOCATION_RULE: lambda state, world: state.can_reach_region("Boiler Room", world.player), - NONSANITY_LOCATION_KEY: "Treasure Trove" + NONSANITY_LOCATION_KEY: "Treasure Trove", }, "Throne Room Floorplan": { LOCATION_ID_KEY: get_room_location_id("Orindian Ruins", 0), LOCATION_ROOM_KEY: "Orindian Ruins", - NONSANITY_LOCATION_KEY: "Throne Room" + NONSANITY_LOCATION_KEY: "Throne Room", }, "Tunnel Floorplan": { LOCATION_ID_KEY: get_room_location_id("Tunnel Area Past Crates", 0), LOCATION_ROOM_KEY: "Tunnel Area Past Crates", - NONSANITY_LOCATION_KEY: "Tunnel" + NONSANITY_LOCATION_KEY: "Tunnel", }, "Conservatory Floorplan": { LOCATION_ID_KEY: get_room_location_id("Campsite", 1), @@ -369,8 +396,8 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Closed Exhibit Floorplan": { LOCATION_ID_KEY: get_room_location_id("Study", 1), LOCATION_ROOM_KEY: "Study", - NONSANITY_LOCATION_KEY: "Closed Exhibit" - } + NONSANITY_LOCATION_KEY: "Closed Exhibit", + }, } floorplans = drafting_studio_additions | found_floorplans @@ -395,13 +422,18 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo "Gift Shop - Blue Tents": { LOCATION_ID_KEY: get_room_location_id("Gift Shop", 4), LOCATION_ROOM_KEY: "Gift Shop", - LOCATION_RULE: lambda state, world: len([state.can_reach_location(loc, world.player) for loc in trophies.keys()]) >= 8 + LOCATION_RULE: lambda state, world: len( + [state.can_reach_location(loc, world.player) for loc in trophies.keys()] + ) + >= 8, }, "Gift Shop - Cursed Coffers": { LOCATION_ID_KEY: get_room_location_id("Gift Shop", 5), LOCATION_ROOM_KEY: "Gift Shop", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in ["Library", "Shrine"]), - } + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) for region in ["Library", "Shrine"] + ), + }, } bookshop_items = { @@ -433,6 +465,7 @@ def can_reach_item_location(item_name: str, state: CollectionState, world) -> bo shop_items = gift_shop_items | bookshop_items + def get_trading_post_offers(give: str) -> list[str]: if give in TRADING_POST_TIER1[TRADING_POST_GIVE]: return [x for x in TRADING_POST_TIER1[TRADING_POST_RECEIVE] if x != give] @@ -444,623 +477,854 @@ def get_trading_post_offers(give: str) -> list[str]: return [x for x in TRADING_POST_TIER4[TRADING_POST_RECEIVE] if x != give] return [] + # I ignored Cloister upgrades for now, but they should probably be checked eventually, since some of them would be a break in logic for item pickups standard_item_pickup = { "BATTERY PACK First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 2), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 2 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "BATTERY PACK", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Attic", - "Archives", - "Courtyard", - "Laboratory", - "Mail Room", - "Patio", - "Storeroom", - "Wine Cellar", - "Workshop", - "Clock Tower", - "Mechanarium", - "Toolshed", - "Hovel", - "Spare Room", - "Garage", - "Utility Closet", - "Kitchen", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Trading Post", world.player) and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("BATTERY PACK"))) - or (state.can_reach_region("Darkroom", world.player) - and (state.can_reach_region("Utility Closet", world.player) or state.can_reach_region("Shelter", world.player) - or can_reach_item_location("KNIGHTS SHIELD", state, world))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Attic", + "Archives", + "Courtyard", + "Laboratory", + "Mail Room", + "Patio", + "Storeroom", + "Wine Cellar", + "Workshop", + "Clock Tower", + "Mechanarium", + "Toolshed", + "Hovel", + "Spare Room", + "Garage", + "Utility Closet", + "Kitchen", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Trading Post", world.player) + and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("BATTERY PACK")) + ) + or ( + state.can_reach_region("Darkroom", world.player) + and ( + state.can_reach_region("Utility Closet", world.player) + or state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + ) + ), # Also spawns in Spare Patio, but we aren't adding upgraded rooms seperately atm. }, "BROKEN LEVER First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 3), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 3 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "BROKEN LEVER", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Aquarium", - "Attic", - "Cloister", - "Drafting Studio", - "Laboratory", - "Locker Room", - "Observatory", - "Patio", - "Sauna", - "Security", - "Storeroom", - "Weight Room", - "Wine Cellar", - "Workshop", - "Secret Garden", - "Conservatory", - "Spare Room", - "Billiard Room", - "Garage", - "Utility Closet", - "Kitchen", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Aquarium", + "Attic", + "Cloister", + "Drafting Studio", + "Laboratory", + "Locker Room", + "Observatory", + "Patio", + "Sauna", + "Security", + "Storeroom", + "Weight Room", + "Wine Cellar", + "Workshop", + "Secret Garden", + "Conservatory", + "Spare Room", + "Billiard Room", + "Garage", + "Utility Closet", + "Kitchen", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) or can_reach_item_location("SHOVEL", state, world) - or (state.can_reach_region("Darkroom", world.player) - and (state.can_reach_region("Utility Closet", world.player) or state.can_reach_region("Shelter", world.player) - or can_reach_item_location("KNIGHTS SHIELD", state, world))) + or ( + state.can_reach_region("Darkroom", world.player) + and ( + state.can_reach_region("Utility Closet", world.player) + or state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + ) + ), # Also spawns in Spare Greenroom, but we aren't adding upgraded rooms seperately atm. }, "COIN PURSE First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 4), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 4 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "COIN PURSE", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Closet", - "Walk-In Closet", - "Parlor", - "Attic", - "Workshop", - "Dining Room", - "Bedroom", - "Gallery", - "Ballroom", - "Drawing Room", - "Mail Room", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Lavatory", world.player) and - (state.can_reach_region("Shelter", world.player) or can_reach_item_location("KNIGHTS SHIELD", state, world) or can_reach_item_location("Dowsing Rod", state, world))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Closet", + "Walk-In Closet", + "Parlor", + "Attic", + "Workshop", + "Dining Room", + "Bedroom", + "Gallery", + "Ballroom", + "Drawing Room", + "Mail Room", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Lavatory", world.player) + and ( + state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + or can_reach_item_location("Dowsing Rod", state, world) + ) + ), # Also spawns in Her Ladyship's Spare Room and Spare Master Bedroom, but we aren't adding upgraded rooms seperately atm. }, "COMPASS First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 5), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 5 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "COMPASS", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Aquarium", - "Attic", - "Cloister", - "Closet", - "Drafting Studio", - "Observatory", - "Terrace", - "Walk-In Closet", - "Workshop", - "Throne Room", - "Den", - "Commissary", - "Mail Room", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Aquarium", + "Attic", + "Cloister", + "Closet", + "Drafting Studio", + "Observatory", + "Terrace", + "Walk-In Closet", + "Workshop", + "Throne Room", + "Den", + "Commissary", + "Mail Room", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Her Ladyship's Spare Room, Spare Master Bedroom, and Spare Terrace, but we aren't adding upgraded rooms seperately atm. # Also, ignoring chance to spawn in trunks for the moment }, "COUPON BOOK First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 6), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 6 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Attic", - "Conference Room", - "Dining Room", - "Library", - "Mail Room", - "Nook", - "Office", - "Vault", - "Walk-In Closet", - "Morning Room", - "Den", - "Pantry", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Attic", + "Conference Room", + "Dining Room", + "Library", + "Mail Room", + "Nook", + "Office", + "Vault", + "Walk-In Closet", + "Morning Room", + "Den", + "Pantry", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), }, "GEAR WRENCH First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 7), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 7 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "GEAR WRENCH", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Toolshed", - "Lost And Found", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Toolshed", + "Lost And Found", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), }, "HALL PASS First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 8), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 8 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "HALL PASS", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Classroom 1", - "Classroom 2", - "Classroom 3", - "Classroom 4", - "Classroom 5", - "Classroom 6", - "Classroom 7", - "Classroom 8", - "Classroom Exam", - "Dormitory", - "Lost And Found", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Classroom 1", + "Classroom 2", + "Classroom 3", + "Classroom 4", + "Classroom 5", + "Classroom 6", + "Classroom 7", + "Classroom 8", + "Classroom Exam", + "Dormitory", + "Lost And Found", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), }, "LOCK PICK KIT First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 9), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 9 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "LOCK PICK KIT", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Archives", - "Attic", - "Rumpus Room", - "Security", - "Vault", - "Walk-In Closet", - "Wine Cellar", - "Workshop", - "Closed Exhibit", - "Garage", - "Locksmith", - "Mail Room", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Darkroom", world.player) - and (state.can_reach_region("Utility Closet", world.player) or state.can_reach_region("Shelter", world.player) - or can_reach_item_location("KNIGHTS SHIELD", state, world))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Archives", + "Attic", + "Rumpus Room", + "Security", + "Vault", + "Walk-In Closet", + "Wine Cellar", + "Workshop", + "Closed Exhibit", + "Garage", + "Locksmith", + "Mail Room", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Darkroom", world.player) + and ( + state.can_reach_region("Utility Closet", world.player) + or state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + ) + ), # Also spawns in Spare Bedroom (and its upgrades), but we aren't adding upgraded rooms seperately atm. # Also, ignoring chance to spawn in trunks for the moment }, "LUCKY RABBIT'S FOOT First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 10), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 10 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "LUCKY RABBIT'S FOOT", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Closet", - "Walk-In Closet", - "Rumpus Room", - "Nursery", - "Morning Room", - "Throne Room", - "Lost And Found", - "Gallery", - "Den", - "Ballroom", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Lavatory", world.player) and - (state.can_reach_region("Shelter", world.player) or can_reach_item_location("KNIGHTS SHIELD", state, world) - or can_reach_item_location("Dowsing Rod", state, world))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Closet", + "Walk-In Closet", + "Rumpus Room", + "Nursery", + "Morning Room", + "Throne Room", + "Lost And Found", + "Gallery", + "Den", + "Ballroom", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Lavatory", world.player) + and ( + state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + or can_reach_item_location("Dowsing Rod", state, world) + ) + ), # Also spawns in Her Ladyship's Spare Room, Spare Servant's Quarters, and Spare Bedroom, but we aren't adding upgraded rooms seperately atm. }, "MAGNIFYING GLASS First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 11), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 11 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "MAGNIFYING GLASS", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Archives", - "Attic", - "Boudoir", - "Chapel", - "Courtyard", - "Drafting Studio", - "Guest Bedroom", - "Her Ladyship's Chambers", - "Laboratory", - "Library", - "Mail Room", - "Nook", - "Observatory", - "Office", - "Parlor", - "Study", - "Workshop", - "Classroom 1", - "Classroom 2", - "Classroom 3", - "Classroom 4", - "Classroom 5", - "Classroom 6", - "Classroom 7", - "Classroom 8", - "Classroom Exam", - "Conservatory", - "Den", - "Drawing Room", - "Commissary", - ]) or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Archives", + "Attic", + "Boudoir", + "Chapel", + "Courtyard", + "Drafting Studio", + "Guest Bedroom", + "Her Ladyship's Chambers", + "Laboratory", + "Library", + "Mail Room", + "Nook", + "Observatory", + "Office", + "Parlor", + "Study", + "Workshop", + "Classroom 1", + "Classroom 2", + "Classroom 3", + "Classroom 4", + "Classroom 5", + "Classroom 6", + "Classroom 7", + "Classroom 8", + "Classroom Exam", + "Conservatory", + "Den", + "Drawing Room", + "Commissary", + ] + ) + or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)), # Also spawns in Spare Foyer, but we aren't adding upgraded rooms seperately atm. }, "METAL DETECTOR First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 12), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 12 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "METAL DETECTOR", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Archives", - "Attic", - "Closet", - "Courtyard", - "Greenhouse", - "Maids Chamber", - "Mail Room", - "Patio", - "Veranda", - "Workshop", - "Secret Garden", - "Clock Tower", - "Toolshed", - "Garage", - "Boiler Room", - "Commissary", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Archives", + "Attic", + "Closet", + "Courtyard", + "Greenhouse", + "Maids Chamber", + "Mail Room", + "Patio", + "Veranda", + "Workshop", + "Secret Garden", + "Clock Tower", + "Toolshed", + "Garage", + "Boiler Room", + "Commissary", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Spare Patio and Spare Veranda, but we aren't adding upgraded rooms seperately atm. }, "REPELLENT First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Lost And Found", 0), + LOCATION_ID_KEY: get_room_location_id("Lost And Found", 2), LOCATION_ROOM_KEY: "Lost And Found", LOCATION_ITEM_KEY: "REPELLENT", }, "RUNNING SHOES First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 14), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 14 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "RUNNING SHOES", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Closet", - "Gymnasium", - "Locker Room", - "Rumpus Room", - "Sauna", - "The Pool", - "Walk-In Closet", - "Weight Room", - "Dormitory", - "Garage", - "Commissary", - "Locker Room", - "Mail Room", # Frieght Mail - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Closet", + "Gymnasium", + "Locker Room", + "Rumpus Room", + "Sauna", + "The Pool", + "Walk-In Closet", + "Weight Room", + "Dormitory", + "Garage", + "Commissary", + "Locker Room", + "Mail Room", # Freight Mail + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Spare Servant's Quarters, but we aren't adding upgraded rooms seperately atm. }, "SALT SHAKER First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 15), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 15 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SALT SHAKER", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Rumpus Room", - "Walk-In Closet", - "Billiard Room", - "Dining Room", - "Morning Room", - "Pantry", - "Kitchen", - "Commissary", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Trading Post", world.player) and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SALT SHAKER"))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Rumpus Room", + "Walk-In Closet", + "Billiard Room", + "Dining Room", + "Morning Room", + "Pantry", + "Kitchen", + "Commissary", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Trading Post", world.player) + and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SALT SHAKER")) + ), }, "SHOVEL First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 16), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 16 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SHOVEL", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Aquarium", - "Attic", - "Cloister", - "Closet", - "Courtyard", - "Furnace", - "Greenhouse", - "Patio", - "Storeroom", - "Terrace", - "Veranda", - "Wine Cellar", - "Workshop", - "Secret Garden", - "Clock Tower", - "Solarium", - "Tunnel", - "Toolshed", - "Hovel", - "Spare Room", - "Garage", - "Trophy Room", - "Utility Closet", - "Boiler Room", - "Commissary", - "Observatory", # Spiral of Stars - "Mail Room", # Frieght Mail - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Trading Post", world.player) and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SHOVEL"))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Aquarium", + "Attic", + "Cloister", + "Closet", + "Courtyard", + "Furnace", + "Greenhouse", + "Patio", + "Storeroom", + "Terrace", + "Veranda", + "Wine Cellar", + "Workshop", + "Secret Garden", + "Clock Tower", + "Solarium", + "Tunnel", + "Toolshed", + "Hovel", + "Spare Room", + "Garage", + "Trophy Room", + "Utility Closet", + "Boiler Room", + "Commissary", + "Observatory", # Spiral of Stars + "Mail Room", # Freight Mail + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Trading Post", world.player) + and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SHOVEL")) + ), # Also spawns in Spare Greenhouse, Spare Patio, Space Terrace, and Spare Veranda, but we aren't adding upgraded rooms seperately atm. }, "SLEDGE HAMMER First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 17), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 17 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SLEDGE HAMMER", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Attic", - "Closet", - "Courtyard", - "Greenhouse", - "Storeroom", - "Veranda", - "Workshop", - "Wine Cellar", - "Secret Garden", - "Tunnel", - "Toolshed", - "Spare Room", - "Garage", - "Music Room", - "Trophy Room", - "Utility Closet", - "Commissary", - "Observatory", # Spiral of Stars - "Mail Room", # Frieght Mail - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Trading Post", world.player) and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SLEDGE HAMMER"))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Attic", + "Closet", + "Courtyard", + "Greenhouse", + "Storeroom", + "Veranda", + "Workshop", + "Wine Cellar", + "Secret Garden", + "Tunnel", + "Toolshed", + "Spare Room", + "Garage", + "Music Room", + "Trophy Room", + "Utility Closet", + "Commissary", + "Observatory", # Spiral of Stars + "Mail Room", # Freight Mail + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Trading Post", world.player) + and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("SLEDGE HAMMER")) + ), # Also spawns in Spare Hall and Spare Foyer, but we aren't adding upgraded rooms seperately atm. }, "SLEEPING MASK First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 18), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 18 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SLEEPING MASK", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Bedroom", - "Boudoir", - "Closet", - "Master Bedroom", - "Sauna", - "Walk-In Closet", - "Commissary", - "Mail Room", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Bedroom", + "Boudoir", + "Closet", + "Master Bedroom", + "Sauna", + "Walk-In Closet", + "Commissary", + "Mail Room", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Her Ladyship's Spare Room, Spare Bedroom, Spare Master Bedroom, and Spare Servant's Quarters, but we aren't adding upgraded rooms seperately atm. }, "STOPWATCH First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 19), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 19 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "STOPWATCH", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Clock Tower", - "Lost And Found", - ]) or can_reach_item_location("JACK HAMMER", state, world) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Clock Tower", + "Lost And Found", + ] + ) + or can_reach_item_location("JACK HAMMER", state, world), }, "TELESCOPE First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 20), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 20 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "TELESCOPE", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Her Ladyship's Chambers", - "Walk-In Closet", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Trading Post", world.player) and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("TELESCOPE"))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Her Ladyship's Chambers", + "Walk-In Closet", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Trading Post", world.player) + and any(can_reach_item_location(item, state, world) for item in get_trading_post_offers("TELESCOPE")) + ), # Also spawns in Her Ladyship's Spare Room, but we aren't adding upgraded rooms seperately atm. }, "TREASURE MAP First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 21), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 21 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "TREASURE MAP", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Attic", - "Drafting Studio", - "Library", - "Mail Room", - "Observatory", - "Rumpus Room", - "Study", - "Wine Cellar", - "Clock Tower", - "Den", - "Trophy Room", - "Locker Room", - ]) or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) - or (state.can_reach_region("Lavatory", world.player) - and (state.can_reach_region("Shelter", world.player) or can_reach_item_location("KNIGHTS SHIELD", state, world) or can_reach_item_location("Dowsing Rod", state, world))) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Attic", + "Drafting Studio", + "Library", + "Mail Room", + "Observatory", + "Rumpus Room", + "Study", + "Wine Cellar", + "Clock Tower", + "Den", + "Trophy Room", + "Locker Room", + ] + ) + or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) + or ( + state.can_reach_region("Lavatory", world.player) + and ( + state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + or can_reach_item_location("Dowsing Rod", state, world) + ) + ), # Also spawns in Spare Foyer and Spare Secret Passage, but we aren't adding upgraded rooms seperately atm. # Also, ignoring chance to spawn in trunks for the moment }, "WATERING CAN First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 22), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 22 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "WATERING CAN", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Greenhouse", - "Toolshed", - "Hovel", - "Lost And Found", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Greenhouse", + "Toolshed", + "Hovel", + "Lost And Found", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Spare Greenroom, but we aren't adding upgraded rooms seperately atm. }, } special_key_pickup = { "BASEMENT KEY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 30), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 30 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "BASEMENT KEY", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Antechamber", - "Observatory", # Spiral of Stars - ]), + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Antechamber", + "Observatory", # Spiral of Stars + ] + ), }, "CAR KEYS First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 31), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 31 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "CAR KEYS", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Bedroom", - "Billiard Room", - "Dining Room", - "Gymnasium", - "Locker Room", - "Music Room", - "Office", - "Parlor", - "Patio", - "Rumpus Room", - "Sauna", - "Security", - "The Pool", - "Walk-In Closet", - "Gallery", - "Den", - "Locksmith", - "Locker Room", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Bedroom", + "Billiard Room", + "Dining Room", + "Gymnasium", + "Locker Room", + "Music Room", + "Office", + "Parlor", + "Patio", + "Rumpus Room", + "Sauna", + "Security", + "The Pool", + "Walk-In Closet", + "Gallery", + "Den", + "Locksmith", + "Locker Room", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), # Also spawns in Spare Bedroom, Spare Patio, and Spare Servant's Quarters, but we aren't adding upgraded rooms seperately atm. # Also, ignoring chance to spawn in trunks for the moment }, "KEY 8 First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 32), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 32 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "KEY 8", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Gallery", - "Lost And Found", # Day 365+ - ]), + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Gallery", + "Lost And Found", # Day 365+ + ] + ), }, "KEYCARD First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 33), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 33 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "KEYCARD", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Archives", - "Closet", - "Conference Room", - "Guest Bedroom", - "Mail Room", - "Music Room", - "Laboratory", - "Locker Room", - "Office", - "Rumpus Room", - "Sauna", - "Security", - "Study", - "The Pool", - "Vault", - "Walk-In Closet", - "Dormitory", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Darkroom", world.player) - and (state.can_reach_region("Utility Closet", world.player) or state.can_reach_region("Shelter", world.player) or can_reach_item_location("KNIGHTS SHIELD", state, world))) - or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Archives", + "Closet", + "Conference Room", + "Guest Bedroom", + "Mail Room", + "Music Room", + "Laboratory", + "Locker Room", + "Office", + "Rumpus Room", + "Sauna", + "Security", + "Study", + "The Pool", + "Vault", + "Walk-In Closet", + "Dormitory", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Darkroom", world.player) + and ( + state.can_reach_region("Utility Closet", world.player) + or state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + ) + ) + or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)), # Also ignoring chance to spawn in trunks for the moment }, "PRISM KEY_0 First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 34), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 34 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "PRISM KEY_0", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Music Room", - "Lost And Found", - "Locksmith" - ]) or (state.can_reach_region("Freezer", world.player) and any(can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"])) - or (state.can_reach_region("Planetarium", world.player) and can_reach_item_location("TELESCOPE", state, world)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) for region in ["Music Room", "Lost And Found", "Locksmith"] + ) + or ( + state.can_reach_region("Freezer", world.player) + and any(can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"]) + ) + or (state.can_reach_region("Planetarium", world.player) and can_reach_item_location("TELESCOPE", state, world)), }, "SECRET GARDEN KEY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 35), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 35 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SECRET GARDEN KEY", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Attic", - "Music Room", - "Lost And Found", - "Locksmith", - "Billiard Room", - ]) or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) - or can_reach_item_location("SHOVEL", state, world) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Attic", + "Music Room", + "Lost And Found", + "Locksmith", + "Billiard Room", + ] + ) + or (state.can_reach_region("Garage", world.player) and can_reach_item_location("CAR KEYS", state, world)) + or can_reach_item_location("SHOVEL", state, world), # Also ignoring chance to spawn in trunks for the moment }, "SILVER KEY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 36), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 36 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", LOCATION_ITEM_KEY: "SILVER KEY", - LOCATION_RULE: lambda state, world: any(state.can_reach_region(region, world.player) for region in [ - "Closet", - "Music Room", - "Her Ladyship's Chambers", - "Mechanarium", - "Locksmith", - "Billiard Room", - "Mail Room", - "Observatory", # Spiral of Stars - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: any( + state.can_reach_region(region, world.player) + for region in [ + "Closet", + "Music Room", + "Her Ladyship's Chambers", + "Mechanarium", + "Locksmith", + "Billiard Room", + "Mail Room", + "Observatory", # Spiral of Stars + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) or can_reach_item_location("SHOVEL", state, world) - or (state.can_reach_region("Freezer", world.player) and any(can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"]) - and can_reach_item_location("PRISM KEY_0", state, world)) + or ( + state.can_reach_region("Freezer", world.player) + and any(can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"]) + and can_reach_item_location("PRISM KEY_0", state, world) + ), # Also ignoring chance to spawn in trunks for the moment }, # "Wind-up Key First Pickup": { # LOCATION_ID_KEY: get_room_location_id("Campsite", 37), # Doesn't spawn there, but putting it there and adding spawn locations as requirements # LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "Wind-up Key", - # LOCATION_RULE: lambda state, world: obf_can_reach_region("Parlor", state, world) + # LOCATION_RULE: lambda state, world: obf_can_reach_region("Parlor", state, world) # or state.can_reach_region("Observatory", world.player) # Spiral of Stars # or can_reach_item_location("Jack Hammer", state, world) # or state.can_reach_region("Tunnel Area Past Blue Door", world.player) # I would be very suprised if this is the only one a player has access to, but adding just in case # } } + def obf_can_reach_region(region_name: str, state, world) -> bool: res = state.can_reach_region(region_name, world.player) return res -showroom_item_rule = lambda state, world: state.can_reach_region("Showroom", world.player) or state.can_reach_region("Observatory", world.player) # Spiral of Stars + +showroom_item_rule = lambda state, world: state.can_reach_region("Showroom", world.player) or state.can_reach_region( + "Observatory", world.player +) # Spiral of Stars showroom_item_pickup = { "CHRONOGRAPH First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 40), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 40 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "CHRONOGRAPH", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, "EMERALD BRACELET First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 41), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 41 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "EMERALD BRACELET", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, "MASTER KEY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 42), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 42 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "MASTER KEY", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, "MOON PENDANT First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 43), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 43 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "MOON PENDANT", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, "ORNATE COMPASS First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 44), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 44 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "ORNATE COMPASS", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, "SILVER SPOON First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Campsite", 45), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Campsite", 45 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Campsite", # LOCATION_ITEM_KEY: "SILVER SPOON", - LOCATION_RULE: showroom_item_rule + LOCATION_RULE: showroom_item_rule, }, } @@ -1071,19 +1335,22 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: LOCATION_ITEM_KEY: "CROWN", }, "CURSED EFFIGY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Shrine", 0), + LOCATION_ID_KEY: get_room_location_id("Shrine", 1), LOCATION_ROOM_KEY: "Shrine", LOCATION_ITEM_KEY: "CURSED EFFIGY", - LOCATION_RULE: lambda state, world: (can_reach_item_location("SLEDGE HAMMER", state, world) or can_reach_item_location("MORNING STAR", state, world)) - and state.can_reach_region("Gift Shop", world.player) + LOCATION_RULE: lambda state, world: ( + can_reach_item_location("SLEDGE HAMMER", state, world) + or can_reach_item_location("MORNING STAR", state, world) + ) + and state.can_reach_region("Gift Shop", world.player), }, "DIARY KEY First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Her Ladyship's Chambers", 0), + LOCATION_ID_KEY: get_room_location_id("Her Ladyship's Chambers", 1), LOCATION_ROOM_KEY: "Her Ladyship's Chambers", LOCATION_ITEM_KEY: "DIARY KEY", }, "KEY of Aries First Pickup": { - LOCATION_ID_KEY: get_room_location_id("Aries Court", 0), + LOCATION_ID_KEY: get_room_location_id("Aries Court", 99), LOCATION_ROOM_KEY: "Aries Court", LOCATION_ITEM_KEY: "KEY of Aries", }, @@ -1091,19 +1358,20 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: LOCATION_ID_KEY: get_room_location_id("Dining Room", 0), LOCATION_ROOM_KEY: "Dining Room", LOCATION_ITEM_KEY: "LUNCH BOX", - LOCATION_RULE: lambda state, world: state.can_reach_region("Gift Shop", world.player) + LOCATION_RULE: lambda state, world: state.can_reach_region("Gift Shop", world.player), }, "MICROCHIP 1 First Pickup": { LOCATION_ID_KEY: get_room_location_id("West Path", 0), LOCATION_ROOM_KEY: "West Path", LOCATION_ITEM_KEY: "MICROCHIP 1", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world), }, "MICROCHIP 2 First Pickup": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 10), LOCATION_ROOM_KEY: "Entrance Hall", LOCATION_ITEM_KEY: "MICROCHIP 2", - LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) or can_reach_item_location("MORNING STAR", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) + or can_reach_item_location("MORNING STAR", state, world), }, "MICROCHIP 3 First Pickup": { LOCATION_ID_KEY: get_room_location_id("Blackbridge Grotto", 0), @@ -1119,8 +1387,9 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: LOCATION_ID_KEY: get_room_location_id("Treasure Trove", 0), LOCATION_ROOM_KEY: "Treasure Trove", LOCATION_ITEM_KEY: "ROYAL SCEPTER", - LOCATION_RULE: lambda state, world: state.can_reach_region("Shrine", world.player) and can_reach_item_location("KEY of Aries", state, world) - } + LOCATION_RULE: lambda state, world: state.can_reach_region("Shrine", world.player) + and can_reach_item_location("KEY of Aries", state, world), + }, } item_pickups = standard_item_pickup | special_key_pickup | showroom_item_pickup | unique_item_pickup @@ -1130,54 +1399,70 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: LOCATION_ID_KEY: get_room_location_id("Workshop", 1), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Burning Glass", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["MAGNIFYING GLASS", "METAL DETECTOR"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["MAGNIFYING GLASS", "METAL DETECTOR"] + ), }, "Detector Shovel First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 2), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Detector Shovel", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["SHOVEL", "METAL DETECTOR"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["SHOVEL", "METAL DETECTOR"] + ), }, "Dowsing Rod First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 3), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Dowsing Rod", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["SHOVEL", "COMPASS"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["SHOVEL", "COMPASS"] + ), }, "Power Hammer First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 4), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Power Hammer", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["SLEDGE HAMMER", "BROKEN LEVER", "BATTERY PACK"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["SLEDGE HAMMER", "BROKEN LEVER", "BATTERY PACK"] + ), }, "Electromagnet First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 5), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Electromagnet", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["COMPASS", "BATTERY PACK"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["COMPASS", "BATTERY PACK"] + ), }, "Lucky Purse First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 6), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Lucky Purse", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["COIN PURSE", "LUCKY RABBIT'S FOOT"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["COIN PURSE", "LUCKY RABBIT'S FOOT"] + ), }, "Jack Hammer First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 7), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Jack Hammer", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["SHOVEL", "BATTERY PACK", "BROKEN LEVER"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["SHOVEL", "BATTERY PACK", "BROKEN LEVER"] + ), }, "Pick Sound Amplifier First Craft": { LOCATION_ID_KEY: get_room_location_id("Workshop", 8), LOCATION_ROOM_KEY: "Workshop", LOCATION_ITEM_KEY: "Pick Sound Amplifier", - LOCATION_RULE: lambda state, world: all(can_reach_item_location(item, state, world) for item in ["LOCK PICK KIT", "METAL DETECTOR"]) + LOCATION_RULE: lambda state, world: all( + can_reach_item_location(item, state, world) for item in ["LOCK PICK KIT", "METAL DETECTOR"] + ), }, } upgrade_disks = { - "Upgrade Disk - Offic": { + "Upgrade Disk - Office": { LOCATION_ID_KEY: get_room_location_id("Office", 1), LOCATION_ROOM_KEY: "Office", }, @@ -1196,7 +1481,7 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Upgrade Disk - Garage": { LOCATION_ID_KEY: get_room_location_id("Garage", 0), LOCATION_ROOM_KEY: "Garage", - LOCATION_RULE: lambda state, world: can_reach_item_location("CAR KEYS", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("CAR KEYS", state, world), }, "Upgrade Disk - Great Hall": { LOCATION_ID_KEY: get_room_location_id("Great Hall", 0), @@ -1205,24 +1490,30 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Upgrade Disk - Vault": { LOCATION_ID_KEY: get_room_location_id("Vault", 0), LOCATION_ROOM_KEY: "Vault", - LOCATION_RULE: lambda state, world: can_reach_item_location("VAULT KEY 304", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("VAULT KEY 304", state, world), }, "Upgrade Disk - Trading Post Dynamite": { LOCATION_ID_KEY: get_room_location_id("Trading Post", 0), LOCATION_ROOM_KEY: "Trading Post", - LOCATION_RULE: lambda state, world: any(can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"]), + LOCATION_RULE: lambda state, world: any( + can_reach_item_location(item, state, world) for item in ["Burning Glass", "TORCH"] + ), }, "Upgrade Disk - Freezer": { LOCATION_ID_KEY: get_room_location_id("Freezer", 0), LOCATION_ROOM_KEY: "Freezer", - LOCATION_RULE: lambda state, world: any(can_reach_item_location(item, state, world) for item in [ - "Burning Glass", - "TORCH", - "Power Hammer", - ]) or state.can_reach_region("Furnace", world.player) + LOCATION_RULE: lambda state, world: any( + can_reach_item_location(item, state, world) + for item in [ + "Burning Glass", + "TORCH", + "Power Hammer", + ] + ) + or state.can_reach_region("Furnace", world.player), }, "Upgrade Disk - Tomb": { - LOCATION_ID_KEY: get_room_location_id("Tomb", 0), + LOCATION_ID_KEY: get_room_location_id("Tomb", 1), LOCATION_ROOM_KEY: "Tomb", }, "Upgrade Disk - The Foundation": { @@ -1244,7 +1535,7 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Upgrade Disk - Archives": { LOCATION_ID_KEY: get_room_location_id("Archives", 0), LOCATION_ROOM_KEY: "Archives", - LOCATION_RULE: lambda state, world: can_reach_item_location("CABINET KEY 1", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("CABINET KEY 1", state, world), }, "Upgrade Disk - Trading Post Trade": { LOCATION_ID_KEY: get_room_location_id("Trading Post", 1), @@ -1254,100 +1545,125 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: vault_keys = { "Vault Key 149": { - LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 4), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Entrance Hall", 4 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Entrance Hall", LOCATION_ITEM_KEY: "VAULT KEY 149", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) - or any(state.can_reach_region(x, world.player) for x in [ - "Attic", - "Rumpus Room", - "Security", - "Trophy Room", - "Locker Room", - "Music Room", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + or any( + state.can_reach_region(x, world.player) + for x in [ + "Attic", + "Rumpus Room", + "Security", + "Trophy Room", + "Locker Room", + "Music Room", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)), }, "Vault Key 233": { - LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 5), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Entrance Hall", 5 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Entrance Hall", LOCATION_ITEM_KEY: "VAULT KEY 233", LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) - or any(state.can_reach_region(x, world.player) for x in [ - "Office", - "Sauna", - "Wine Cellar", - "Morning Room", - "Locker Room", - "Music Room", - ]) or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) - or (state.can_reach_region("Lavatory", world.player) - and (state.can_reach_region("Shelter", world.player) or can_reach_item_location("KNIGHTS SHIELD", state, world) or can_reach_item_location("Dowsing Rod", state, world))) + or any( + state.can_reach_region(x, world.player) + for x in [ + "Office", + "Sauna", + "Wine Cellar", + "Morning Room", + "Locker Room", + "Music Room", + ] + ) + or (state.has("Satellite Raised", world.player) and state.can_reach_region("Laboratory", world.player)) + or ( + state.can_reach_region("Lavatory", world.player) + and ( + state.can_reach_region("Shelter", world.player) + or can_reach_item_location("KNIGHTS SHIELD", state, world) + or can_reach_item_location("Dowsing Rod", state, world) + ) + ), }, "Vault Key 304": { - LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 6), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Entrance Hall", 6 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Entrance Hall", LOCATION_ITEM_KEY: "VAULT KEY 304", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) - or any(state.can_reach_region(x, world.player) for x in [ - "Conference Room", - "Her Ladyship's Chambers", - "Walk-In Closet", - "Hovel", - "Drawing Room", - ]) + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + or any( + state.can_reach_region(x, world.player) + for x in [ + "Conference Room", + "Her Ladyship's Chambers", + "Walk-In Closet", + "Hovel", + "Drawing Room", + ] + ), # Can also spawn in Spare Hall, but we aren't adding upgraded rooms seperately atm. }, "Vault Key 370": { - LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 7), # Doesn't spawn there, but putting it there and adding spawn locations as requirements + LOCATION_ID_KEY: get_room_location_id( + "Entrance Hall", 7 + ), # Doesn't spawn there, but putting it there and adding spawn locations as requirements LOCATION_ROOM_KEY: "Entrance Hall", LOCATION_ITEM_KEY: "VAULT KEY 370", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) - or state.can_reach_region("Lost And Found", world.player) - } + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + or state.can_reach_region("Lost And Found", world.player), + }, } sanctum_keys = { "Sanctum Key - Room 46": { LOCATION_ID_KEY: get_room_location_id("Room 46", 5), LOCATION_ROOM_KEY: "Room 46", - LOCATION_ITEM_KEY: "SANCTUM KEY ANTECHAMBER" + LOCATION_ITEM_KEY: "SANCTUM KEY ANTECHAMBER", }, "Sanctum Key - Vault": { LOCATION_ID_KEY: get_room_location_id("Vault", 1), LOCATION_ROOM_KEY: "Vault", LOCATION_ITEM_KEY: "SANCTUM KEY VAULT", - LOCATION_RULE: lambda state, world: can_reach_item_location("VAULT KEY 370", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("VAULT KEY 370", state, world), }, "Sanctum Key - Clock Tower": { LOCATION_ID_KEY: get_room_location_id("Clock Tower", 0), LOCATION_ROOM_KEY: "Clock Tower", - LOCATION_ITEM_KEY: "SANCTUM KEY CLOCK TOWER" + LOCATION_ITEM_KEY: "SANCTUM KEY CLOCK TOWER", }, "Sanctum Key - Reservoir Bottom": { LOCATION_ID_KEY: get_room_location_id("Reservoir Bottom", 0), LOCATION_ROOM_KEY: "Reservoir Bottom", - LOCATION_ITEM_KEY: "SANCTUM KEY RESERVOIR" + LOCATION_ITEM_KEY: "SANCTUM KEY RESERVOIR", }, "Sanctum Key - Throne Room": { LOCATION_ID_KEY: get_room_location_id("Throne Room", 1), LOCATION_ROOM_KEY: "Throne Room", - LOCATION_ITEM_KEY: "SANCTUM KEY THRONE ROOM" + LOCATION_ITEM_KEY: "SANCTUM KEY THRONE ROOM", }, "Sanctum Key - Safehouse": { LOCATION_ID_KEY: get_room_location_id("Safehouse", 0), LOCATION_ROOM_KEY: "Safehouse", - LOCATION_ITEM_KEY: "SANCTUM KEY SAFEHOUSE" + LOCATION_ITEM_KEY: "SANCTUM KEY SAFEHOUSE", }, "Sanctum Key - Music Room": { LOCATION_ID_KEY: get_room_location_id("Music Room", 0), LOCATION_ROOM_KEY: "Music Room", - LOCATION_ITEM_KEY: "SANCTUM KEY MUSIC ROOM" + LOCATION_ITEM_KEY: "SANCTUM KEY MUSIC ROOM", }, "Sanctum Key - Mechanarium": { LOCATION_ID_KEY: get_room_location_id("Mechanarium", 1), LOCATION_ROOM_KEY: "Mechanarium", - LOCATION_ITEM_KEY: "SANCTUM KEY MECHANARIUM" - } + LOCATION_ITEM_KEY: "SANCTUM KEY MECHANARIUM", + }, } file_cabinet_keys = { @@ -1355,13 +1671,13 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: LOCATION_ID_KEY: get_room_location_id("Patio", 0), LOCATION_ROOM_KEY: "Patio", LOCATION_ITEM_KEY: "CABINET KEY 1", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world), }, "File Cabinet Key - Laundry Room": { LOCATION_ID_KEY: get_room_location_id("Laundry Room", 0), LOCATION_ROOM_KEY: "Laundry Room", LOCATION_ITEM_KEY: "CABINET KEY 2", - LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SHOVEL", state, world), }, "File Cabinet Key - Tunnel Area Past Crates": { LOCATION_ID_KEY: get_room_location_id("Tunnel Area Past Crates", 1), @@ -1376,12 +1692,14 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Entrance Hall East Vase": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 8), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) or can_reach_item_location("MORNING STAR", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) + or can_reach_item_location("MORNING STAR", state, world), }, "Entrance Hall West Vase": { LOCATION_ID_KEY: get_room_location_id("Entrance Hall", 9), LOCATION_ROOM_KEY: "Entrance Hall", - LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) or can_reach_item_location("MORNING STAR", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("SLEDGE HAMMER", state, world) + or can_reach_item_location("MORNING STAR", state, world), }, "Cursed Coffers": { LOCATION_ID_KEY: get_room_location_id("Shrine", 0), @@ -1407,7 +1725,8 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Scorch Sundial": { LOCATION_ID_KEY: get_room_location_id("Apple Orchard", 1), LOCATION_ROOM_KEY: "Apple Orchard", - LOCATION_RULE: lambda state, world: can_reach_item_location("Burning Glass", state, world) or can_reach_item_location("TORCH", state, world) + LOCATION_RULE: lambda state, world: can_reach_item_location("Burning Glass", state, world) + or can_reach_item_location("TORCH", state, world), }, "VAC Controls": { LOCATION_ID_KEY: get_room_location_id("Utility Closet", 0), @@ -1421,7 +1740,11 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: "Allowance Token - Outer Entrance Hall Vase": { LOCATION_ID_KEY: get_room_location_id("Outer Room", 0), LOCATION_ROOM_KEY: "Outer Room", - LOCATION_RULE: lambda state, world: state.can_reach_region("Shrine", world.player) and (can_reach_item_location("SLEDGE HAMMER", state, world) or can_reach_item_location("MORNING STAR", state, world)) + LOCATION_RULE: lambda state, world: state.can_reach_region("Shrine", world.player) + and ( + can_reach_item_location("SLEDGE HAMMER", state, world) + or can_reach_item_location("MORNING STAR", state, world) + ), }, # Ignoring deposit box allowance tokens for now, since they are missable (don't respawn if not picked up) } @@ -1435,5 +1758,15 @@ def obf_can_reach_region(region_name: str, state, world) -> bool: # Mirror Room Floorplan Duplicates? -locations = trophies | safes_and_small_gates | mora_jia_boxes | floorplans | shop_items | upgrade_disks | keys | misc_locations | item_pickups | workshop_contraptions - \ No newline at end of file +locations = ( + trophies + | safes_and_small_gates + | mora_jia_boxes + | floorplans + | shop_items + | upgrade_disks + | keys + | misc_locations + | item_pickups + | workshop_contraptions +) diff --git a/worlds/blueprince/regions.py b/worlds/blueprince/regions.py index 6a85fcf5219b..e95524a93e3e 100644 --- a/worlds/blueprince/regions.py +++ b/worlds/blueprince/regions.py @@ -13,6 +13,7 @@ if TYPE_CHECKING: from .world import BluePrinceWorld + def create_and_connect_regions(world: BluePrinceWorld) -> None: world.explicit_indirect_conditions = False ################## @@ -159,13 +160,20 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: "Entrance Hall Antechamber", lambda state: ( state.can_reach_region("Great Hall", world.player) - or (state.can_reach_region("Greenhouse", world.player) and can_reach_item_location("BROKEN LEVER", state, world)) + or ( + state.can_reach_region("Greenhouse", world.player) + and can_reach_item_location("BROKEN LEVER", state, world) + ) or state.can_reach_region("Mechanarium", world.player) - or (state.can_reach_region("Weight Room", world.player) and can_reach_item_location("Power Hammer", state, world)) + or ( + state.can_reach_region("Weight Room", world.player) + and can_reach_item_location("Power Hammer", state, world) + ) or state.can_reach_region("Secret Garden", world.player) # This check is redundant # or (state.has("Secret Garden", world.player) and state.has("Power Hammer", world.player)) - ) and can_reach_pick_position("Antechamber", world, state), + ) + and can_reach_pick_position("Antechamber", world, state), ) elif k == "Room 46": antechamber.connect( @@ -178,12 +186,13 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: room, "Library To Bookshop", lambda state: state.has("Bookshop", world.player), - ) # Can only be drafted from the library, so only requires having the bookshop as an item. + ) # Can only be drafted from the library, so only requires having the bookshop as an item. elif k == "The Armory": entrance_hall.connect( room, "Entrance Hall The Armory", - lambda state: state.can_reach_region("Aries Court", world.player) and can_reach_pick_position("The Armory", world, state), + lambda state: state.can_reach_region("Aries Court", world.player) + and can_reach_pick_position("The Armory", world, state), ) # # This is only necessary if we track the day count @@ -193,36 +202,40 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: # room, # f"Entrance Hall {k}", # lambda state: state.has(k, world.player) and state.can_reach_region("Room 46", world.player), - # ) # Has reached Room 46 or Day Count is >= 46, but < 363; Very rarily possible without either with a Silver Key, but that seems to be a bug + # ) # Has reached Room 46 or Day Count is >= 46, but < 363; Very rarely possible without either with a Silver Key, but that seems to be a bug elif k == "Trophy Room": entrance_hall.connect( room, "Entrance Hall Trophy Room", lambda state: ( - state.can_reach_region("Room 46", world.player) or - state.can_reach_location("Full House Trophy", world.player) or - state.can_reach_location("Trophy of Invention", world.player) or - state.can_reach_location("Trophy of Drafting", world.player) or - state.can_reach_location("Trophy of Wealth", world.player) - ) and can_reach_pick_position("Trophy Room", world, state), - ) # Has reached Room 46 or has one of the 4 listed Trophies + state.can_reach_region("Room 46", world.player) + or state.can_reach_location("Full House Trophy", world.player) + or state.can_reach_location("Trophy of Invention", world.player) + or state.can_reach_location("Trophy of Drafting", world.player) + or state.can_reach_location("Trophy of Wealth", world.player) + ) + and can_reach_pick_position("Trophy Room", world, state), + ) # Has reached Room 46 or has one of the 4 listed Trophies elif k == "Gift Shop": entrance_hall.connect( room, "Entrance Hall Gift Shop", - lambda state: state.can_reach_region("Room 46", world.player) and can_reach_pick_position("Gift Shop", world, state), - ) # Has reached Room 46 + lambda state: state.can_reach_region("Room 46", world.player) + and can_reach_pick_position("Gift Shop", world, state), + ) # Has reached Room 46 elif k == "Room 8": entrance_hall.connect( room, "Entrance Hall Room 8", - lambda state: can_reach_item_location("KEY 8", state, world) and can_reach_pick_position("Room 8", world, state), - ) # Has Key 8 + lambda state: can_reach_item_location("KEY 8", state, world) + and can_reach_pick_position("Room 8", world, state), + ) # Has Key 8 elif k == "Secret Garden": entrance_hall.connect( room, "Entrance Hall Secret Garden", - lambda state: can_reach_item_location("SECRET GARDEN KEY", state, world) and can_reach_pick_position("Secret Garden", world, state), + lambda state: can_reach_item_location("SECRET GARDEN KEY", state, world) + and can_reach_pick_position("Secret Garden", world, state), ) elif k in classrooms and k != "Classroom 1": if k == "Classroom Exam": @@ -234,7 +247,7 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: f"{prev} {k}", lambda state: state.has(k, world.player), ) - + # TODO: Add Her Ladyship's Chamber, it has weird requirements elif k == "Entrance Hall": continue @@ -267,13 +280,16 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: private_drive.connect( blakbridge_grotto, "Private Drive To Blackbridge Grotto", - lambda state: state.can_reach_region("Boiler Room", world.player) and state.can_reach_region("Laboratory", world.player), + lambda state: state.can_reach_region("Boiler Room", world.player) + and state.can_reach_region("Laboratory", world.player), ) private_drive.connect(grounds, "Private Drive To Grounds") blakbridge_grotto.connect( orindian_ruins, "Blackbridge Grotto To Orindian Ruins", - lambda state: all(can_reach_item_location(x, state, world) for x in ["MICROCHIP 1", "MICROCHIP 2", "MICROCHIP 3"]) + lambda state: all( + can_reach_item_location(x, state, world) for x in ["MICROCHIP 1", "MICROCHIP 2", "MICROCHIP 3"] + ), ) grounds.connect( the_precipice, @@ -387,12 +403,12 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: abandoned_mine.connect( excavation_tunnel, "Abandoned Mine To Excavation Tunnel", - lambda state: state.can_reach_region("Reservoir Fountain Side", world.player) + lambda state: state.can_reach_region("Reservoir Fountain Side", world.player), ) excavation_tunnel.connect( abandoned_mine, "Excavation Tunnel To Abandoned Mine", - lambda state: state.can_reach_region("Reservoir Fountain Side", world.player) + lambda state: state.can_reach_region("Reservoir Fountain Side", world.player), ) excavation_tunnel.connect( torch_chamber, @@ -431,17 +447,20 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: garage.connect( west_path, "Garage To West Path", - lambda state: state.can_reach_region("Utility Closet", world.player) or state.can_reach_region("Boiler Room", world.player), + lambda state: state.can_reach_region("Utility Closet", world.player) + or state.can_reach_region("Boiler Room", world.player), ) foundation_elevator.connect( basement, "Foundation Elevator To Basement", - lambda state: state.can_reach_region("The Foundation", world.player) and can_reach_item_location("BASEMENT KEY", state, world), + lambda state: state.can_reach_region("The Foundation", world.player) + and can_reach_item_location("BASEMENT KEY", state, world), ) torch_chamber.connect( the_precipice, "Torch Chamber To Precipice", - lambda state: can_reach_item_location("Burning Glass", state, world) or can_reach_item_location("TORCH", state, world), + lambda state: can_reach_item_location("Burning Glass", state, world) + or can_reach_item_location("TORCH", state, world), ) grounds.connect( @@ -452,7 +471,10 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: tunnel_area_post_crates, "Tunnel Area Entrance To Tunnel Area Post Crates", lambda state: state.has("Satellite Raised", world.player) - and (state.can_reach_region("Laboratory", world.player) or state.can_reach_region("Blackbridge Grotto", world.player)), + and ( + state.can_reach_region("Laboratory", world.player) + or state.can_reach_region("Blackbridge Grotto", world.player) + ), ) tunnel_area_post_crates.connect( tunnel_area_post_normal_locked_door, @@ -481,12 +503,15 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: tunnel_area_post_red_door.connect( tunnel_area_post_candle_door, "Tunnel Area Post Red Door to Tunnel Area Post Candle Door", - lambda state: can_reach_item_location("Burning Glass", state, world) or can_reach_item_location("TORCH", state, world), + lambda state: can_reach_item_location("Burning Glass", state, world) + or can_reach_item_location("TORCH", state, world), ) tunnel_area_post_candle_door.connect( tunnel_area_post_sealed_door, "Tunnel Area Post Candle Door to Tunnel Area Post Sealed Door", - lambda state: all(can_reach_item_location(x, state, world) for x in ["MICROCHIP 1", "MICROCHIP 2", "MICROCHIP 3"]), + lambda state: all( + can_reach_item_location(x, state, world) for x in ["MICROCHIP 1", "MICROCHIP 2", "MICROCHIP 3"] + ), ) tunnel_area_post_sealed_door.connect( tunnel_area_post_blue_door, @@ -501,21 +526,22 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: reservoir_gear_side.connect( safehouse, "Reservoir Gear Side To Safehouse", - lambda state: can_reach_pick_position("Pump Room", world, state) - and state.can_reach_region("Reservoir Fountain Side", world.player) + lambda state: can_reach_pick_position("Pump Room", world, state) + and state.can_reach_region("Reservoir Fountain Side", world.player) and state.can_reach_region("Basement", world.player), ) # Pump Room & Fountain Side Access. (take fountain side to gear side, lower again, and make it back down on gear side.) reservoir_gear_side.connect( reservoir_bottom, "Reservoir Gear Side To Reservoir Bottom", - lambda state: state.can_reach_region("Pump Room", world.player) - and state.can_reach_region("Boiler Room", world.player) + lambda state: state.can_reach_region("Pump Room", world.player) + and state.can_reach_region("Boiler Room", world.player) and state.can_reach_region("Basement", world.player), ) # Pump Room and boiler room (both this and safehouse require ability to get to gear side NOT through well side.) rotating_gear.connect( the_underpass, "Rotating Gear To Underpass", - lambda state: state.can_reach_region("Reservoir Fountain Side", world.player) and state.can_reach_region("Reservoir Gear Side", world.player), + lambda state: state.can_reach_region("Reservoir Fountain Side", world.player) + and state.can_reach_region("Reservoir Gear Side", world.player), ) # Require Dual side access rotating_gear.connect( abandoned_mine, @@ -530,7 +556,7 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: outer_room.connect( atelier, "Outer Room To Atelier", - lambda state: state.can_reach_region("Secret Passage", world.player) + lambda state: state.can_reach_region("Secret Passage", world.player) and state.can_reach_region("Shrine", world.player) and can_reach_item_location("WATERING CAN", state, world), ) @@ -541,6 +567,7 @@ def create_and_connect_regions(world: BluePrinceWorld) -> None: lambda state: state.can_reach_region("Pump Room", world.player), ) + def can_reach_pick_position(room: str, world: BluePrinceWorld, state: CollectionState) -> bool: """ Use pre-calculated tables to determine if a the pick position is reachable with the current inventory. @@ -548,9 +575,9 @@ def can_reach_pick_position(room: str, world: BluePrinceWorld, state: Collection if room not in core_rooms and not state.has(room, world.player): return False - + room_data = rooms[room] - + positions_types = room_data[ROOM_PICK_POSITIONS_KEY] inventory = { @@ -562,7 +589,7 @@ def can_reach_pick_position(room: str, world: BluePrinceWorld, state: Collection total_inventory = sum(inventory.values()) - if (room_data[ROOM_LAYOUT_TYPE_KEY] in inventory and inventory[room_data[ROOM_LAYOUT_TYPE_KEY]] > 0): + if room_data[ROOM_LAYOUT_TYPE_KEY] in inventory and inventory[room_data[ROOM_LAYOUT_TYPE_KEY]] > 0: inventory[room_data[ROOM_LAYOUT_TYPE_KEY]] -= 1 for pt in positions_types: @@ -570,13 +597,14 @@ def can_reach_pick_position(room: str, world: BluePrinceWorld, state: Collection continue if matches_minimum_inventory(POSITION_MINIMUM_PIECES[pt], inventory): return True - + return False + def matches_minimum_inventory(required: list[tuple[int]], inventory: dict[str, int]) -> bool: inv = tuple(inventory[k] for k in inventory) for req in required: if all(inv[i] >= req[i] for i in range(4)): return True - - return False \ No newline at end of file + + return False diff --git a/worlds/blueprince/world.py b/worlds/blueprince/world.py index 3a7fe4afe45f..036905f7857e 100644 --- a/worlds/blueprince/world.py +++ b/worlds/blueprince/world.py @@ -7,7 +7,7 @@ # Imports of your world's files must be relative. from . import items, locations, regions, rules, web_world from . import ( - options as blue_prince_optionss, + options as blue_prince_options, ) # rename due to a name conflict with World.options @@ -25,8 +25,8 @@ class BluePrinceWorld(World): web = web_world.BluePrinceWebWorld() # Set the Options - options_dataclass = blue_prince_optionss.BluePrinceOptions - options: blue_prince_optionss.BluePrinceOptions + options_dataclass = blue_prince_options.BluePrinceOptions + options: blue_prince_options.BluePrinceOptions # Our world class must have a static location_name_to_id and item_name_to_id defined. # We define these in regions.py and items.py respectively, so we just set them here. @@ -63,3 +63,27 @@ def get_filler_item_name(self) -> str: # return self.options.as_dict( # "hard_mode", "hammer", "extra_starting_chest", "confetti_explosiveness", "player_sprite" # ) + + # Set up the ability for UT run without needing the yaml. + ut_can_gen_without_yaml = True + + def generate_early(self) -> None: + # implement .yaml-less Universal Tracker support + if hasattr(self.multiworld, "generation_is_fake"): + if hasattr(self.multiworld, "re_gen_passthrough"): + if "Blue Prince" in self.multiworld.re_gen_passthrough: + slot_data = self.multiworld.re_gen_passthrough["Blue Prince"] + self.options.locked_trunks = slot_data["locked_trunks"] + + return + + def fill_slot_data(self): + slot_data = self.options.as_dict( + "death_link_type", + "death_link_grace", + "death_link_monk_exception", + "locked_trunks", + "goal_type", # changes AP items, and how client/mod implements Translator + ) + + return slot_data