diff options
Diffstat (limited to 'regions.py')
| -rw-r--r-- | regions.py | 105 |
1 files changed, 94 insertions, 11 deletions
| diff --git a/regions.py b/regions.py index 5fddabd..4b357db 100644 --- a/regions.py +++ b/regions.py | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | from typing import Dict, Optional, TYPE_CHECKING | 1 | from typing import Dict, Optional, TYPE_CHECKING |
| 2 | 2 | ||
| 3 | from BaseClasses import Entrance, ItemClassification, Region | 3 | from BaseClasses import Entrance, ItemClassification, Region |
| 4 | from .datatypes import Room, RoomAndDoor | 4 | from .datatypes import EntranceType, Room, RoomAndDoor |
| 5 | from .items import LingoItem | 5 | from .items import LingoItem |
| 6 | from .locations import LingoLocation | 6 | from .locations import LingoLocation |
| 7 | from .rules import lingo_can_use_entrance, make_location_lambda | 7 | from .options import SunwarpAccess |
| 8 | from .rules import lingo_can_do_pilgrimage, lingo_can_use_entrance, make_location_lambda | ||
| 8 | from .static_logic import ALL_ROOMS, PAINTINGS | 9 | from .static_logic import ALL_ROOMS, PAINTINGS |
| 9 | 10 | ||
| 10 | if TYPE_CHECKING: | 11 | if TYPE_CHECKING: |
| @@ -25,8 +26,20 @@ def create_region(room: Room, world: "LingoWorld") -> Region: | |||
| 25 | return new_region | 26 | return new_region |
| 26 | 27 | ||
| 27 | 28 | ||
| 29 | def is_acceptable_pilgrimage_entrance(entrance_type: EntranceType, world: "LingoWorld") -> bool: | ||
| 30 | allowed_entrance_types = EntranceType.NORMAL | ||
| 31 | |||
| 32 | if world.options.pilgrimage_allows_paintings: | ||
| 33 | allowed_entrance_types |= EntranceType.PAINTING | ||
| 34 | |||
| 35 | if world.options.pilgrimage_allows_roof_access: | ||
| 36 | allowed_entrance_types |= EntranceType.CROSSROADS_ROOF_ACCESS | ||
| 37 | |||
| 38 | return bool(entrance_type & allowed_entrance_types) | ||
| 39 | |||
| 40 | |||
| 28 | def connect_entrance(regions: Dict[str, Region], source_region: Region, target_region: Region, description: str, | 41 | def connect_entrance(regions: Dict[str, Region], source_region: Region, target_region: Region, description: str, |
| 29 | door: Optional[RoomAndDoor], world: "LingoWorld"): | 42 | door: Optional[RoomAndDoor], entrance_type: EntranceType, pilgrimage: bool, world: "LingoWorld"): |
| 30 | connection = Entrance(world.player, description, source_region) | 43 | connection = Entrance(world.player, description, source_region) |
| 31 | connection.access_rule = lambda state: lingo_can_use_entrance(state, target_region.name, door, world) | 44 | connection.access_rule = lambda state: lingo_can_use_entrance(state, target_region.name, door, world) |
| 32 | 45 | ||
| @@ -38,6 +51,21 @@ def connect_entrance(regions: Dict[str, Region], source_region: Region, target_r | |||
| 38 | if door.door not in world.player_logic.item_by_door.get(effective_room, {}): | 51 | if door.door not in world.player_logic.item_by_door.get(effective_room, {}): |
| 39 | for region in world.player_logic.calculate_door_requirements(effective_room, door.door, world).rooms: | 52 | for region in world.player_logic.calculate_door_requirements(effective_room, door.door, world).rooms: |
| 40 | world.multiworld.register_indirect_condition(regions[region], connection) | 53 | world.multiworld.register_indirect_condition(regions[region], connection) |
| 54 | |||
| 55 | if not pilgrimage and world.options.enable_pilgrimage and is_acceptable_pilgrimage_entrance(entrance_type, world)\ | ||
| 56 | and source_region.name != "Menu": | ||
| 57 | for part in range(1, 6): | ||
| 58 | pilgrimage_descriptor = f" (Pilgrimage Part {part})" | ||
| 59 | pilgrim_source_region = regions[f"{source_region.name}{pilgrimage_descriptor}"] | ||
| 60 | pilgrim_target_region = regions[f"{target_region.name}{pilgrimage_descriptor}"] | ||
| 61 | |||
| 62 | effective_door = door | ||
| 63 | if effective_door is not None: | ||
| 64 | effective_room = target_region.name if door.room is None else door.room | ||
| 65 | effective_door = RoomAndDoor(effective_room, door.door) | ||
| 66 | |||
| 67 | connect_entrance(regions, pilgrim_source_region, pilgrim_target_region, | ||
| 68 | f"{description}{pilgrimage_descriptor}", effective_door, entrance_type, True, world) | ||
| 41 | 69 | ||
| 42 | 70 | ||
| 43 | def connect_painting(regions: Dict[str, Region], warp_enter: str, warp_exit: str, world: "LingoWorld") -> None: | 71 | def connect_painting(regions: Dict[str, Region], warp_enter: str, warp_exit: str, world: "LingoWorld") -> None: |
| @@ -48,7 +76,8 @@ def connect_painting(regions: Dict[str, Region], warp_enter: str, warp_exit: str | |||
| 48 | source_region = regions[source_painting.room] | 76 | source_region = regions[source_painting.room] |
| 49 | 77 | ||
| 50 | entrance_name = f"{source_painting.room} to {target_painting.room} ({source_painting.id} Painting)" | 78 | entrance_name = f"{source_painting.room} to {target_painting.room} ({source_painting.id} Painting)" |
| 51 | connect_entrance(regions, source_region, target_region, entrance_name, source_painting.required_door, world) | 79 | connect_entrance(regions, source_region, target_region, entrance_name, source_painting.required_door, |
| 80 | EntranceType.PAINTING, False, world) | ||
| 52 | 81 | ||
| 53 | 82 | ||
| 54 | def create_regions(world: "LingoWorld") -> None: | 83 | def create_regions(world: "LingoWorld") -> None: |
| @@ -63,11 +92,26 @@ def create_regions(world: "LingoWorld") -> None: | |||
| 63 | for room in ALL_ROOMS: | 92 | for room in ALL_ROOMS: |
| 64 | regions[room.name] = create_region(room, world) | 93 | regions[room.name] = create_region(room, world) |
| 65 | 94 | ||
| 95 | if world.options.enable_pilgrimage: | ||
| 96 | for part in range(1, 6): | ||
| 97 | pilgrimage_region_name = f"{room.name} (Pilgrimage Part {part})" | ||
| 98 | regions[pilgrimage_region_name] = Region(pilgrimage_region_name, world.player, world.multiworld) | ||
| 99 | |||
| 66 | # Connect all created regions now that they exist. | 100 | # Connect all created regions now that they exist. |
| 101 | allowed_entrance_types = EntranceType.NORMAL | EntranceType.WARP | EntranceType.CROSSROADS_ROOF_ACCESS | ||
| 102 | |||
| 103 | if not painting_shuffle: | ||
| 104 | # Don't use the vanilla painting connections if we are shuffling paintings. | ||
| 105 | allowed_entrance_types |= EntranceType.PAINTING | ||
| 106 | |||
| 107 | if world.options.sunwarp_access != SunwarpAccess.option_disabled and not world.options.shuffle_sunwarps: | ||
| 108 | # Don't connect sunwarps if sunwarps are disabled or if we're shuffling sunwarps. | ||
| 109 | allowed_entrance_types |= EntranceType.SUNWARP | ||
| 110 | |||
| 67 | for room in ALL_ROOMS: | 111 | for room in ALL_ROOMS: |
| 68 | for entrance in room.entrances: | 112 | for entrance in room.entrances: |
| 69 | # Don't use the vanilla painting connections if we are shuffling paintings. | 113 | effective_entrance_type = entrance.type & allowed_entrance_types |
| 70 | if entrance.painting and painting_shuffle: | 114 | if not effective_entrance_type: |
| 71 | continue | 115 | continue |
| 72 | 116 | ||
| 73 | entrance_name = f"{entrance.room} to {room.name}" | 117 | entrance_name = f"{entrance.room} to {room.name}" |
| @@ -77,17 +121,56 @@ def create_regions(world: "LingoWorld") -> None: | |||
| 77 | else: | 121 | else: |
| 78 | entrance_name += f" (through {room.name} - {entrance.door.door})" | 122 | entrance_name += f" (through {room.name} - {entrance.door.door})" |
| 79 | 123 | ||
| 80 | connect_entrance(regions, regions[entrance.room], regions[room.name], entrance_name, entrance.door, world) | 124 | effective_door = entrance.door |
| 125 | if entrance.type == EntranceType.SUNWARP and world.options.sunwarp_access == SunwarpAccess.option_normal: | ||
| 126 | effective_door = None | ||
| 127 | |||
| 128 | connect_entrance(regions, regions[entrance.room], regions[room.name], entrance_name, effective_door, | ||
| 129 | effective_entrance_type, False, world) | ||
| 130 | |||
| 131 | if world.options.enable_pilgrimage: | ||
| 132 | # Connect the start of the pilgrimage. We check for all sunwarp items here. | ||
| 133 | pilgrim_start_from = regions[world.player_logic.sunwarp_entrances[0]] | ||
| 134 | pilgrim_start_to = regions[f"{world.player_logic.sunwarp_exits[0]} (Pilgrimage Part 1)"] | ||
| 135 | |||
| 136 | if world.options.sunwarp_access >= SunwarpAccess.option_unlock: | ||
| 137 | pilgrim_start_from.connect(pilgrim_start_to, f"Pilgrimage Part 1", | ||
| 138 | lambda state: lingo_can_do_pilgrimage(state, world)) | ||
| 139 | else: | ||
| 140 | pilgrim_start_from.connect(pilgrim_start_to, f"Pilgrimage Part 1") | ||
| 81 | 141 | ||
| 82 | # Add the fake pilgrimage. | 142 | # Create connections between each segment of the pilgrimage. |
| 83 | connect_entrance(regions, regions["Outside The Agreeable"], regions["Pilgrim Antechamber"], "Pilgrimage", | 143 | for i in range(1, 6): |
| 84 | RoomAndDoor("Pilgrim Antechamber", "Pilgrimage"), world) | 144 | from_room = f"{world.player_logic.sunwarp_entrances[i]} (Pilgrimage Part {i})" |
| 145 | to_room = f"{world.player_logic.sunwarp_exits[i]} (Pilgrimage Part {i+1})" | ||
| 146 | if i == 5: | ||
| 147 | to_room = "Pilgrim Antechamber" | ||
| 148 | |||
| 149 | regions[from_room].connect(regions[to_room], f"Pilgrimage Part {i+1}") | ||
| 150 | else: | ||
| 151 | connect_entrance(regions, regions["Starting Room"], regions["Pilgrim Antechamber"], "Sun Painting", | ||
| 152 | RoomAndDoor("Pilgrim Antechamber", "Sun Painting"), EntranceType.PAINTING, False, world) | ||
| 85 | 153 | ||
| 86 | if early_color_hallways: | 154 | if early_color_hallways: |
| 87 | regions["Starting Room"].connect(regions["Outside The Undeterred"], "Early Color Hallways") | 155 | connect_entrance(regions, regions["Starting Room"], regions["Outside The Undeterred"], "Early Color Hallways", |
| 156 | None, EntranceType.PAINTING, False, world) | ||
| 88 | 157 | ||
| 89 | if painting_shuffle: | 158 | if painting_shuffle: |
| 90 | for warp_enter, warp_exit in world.player_logic.painting_mapping.items(): | 159 | for warp_enter, warp_exit in world.player_logic.painting_mapping.items(): |
| 91 | connect_painting(regions, warp_enter, warp_exit, world) | 160 | connect_painting(regions, warp_enter, warp_exit, world) |
| 92 | 161 | ||
| 162 | if world.options.shuffle_sunwarps: | ||
| 163 | for i in range(0, 6): | ||
| 164 | if world.options.sunwarp_access == SunwarpAccess.option_normal: | ||
| 165 | effective_door = None | ||
| 166 | else: | ||
| 167 | effective_door = RoomAndDoor("Sunwarps", f"{i + 1} Sunwarp") | ||
| 168 | |||
| 169 | source_region = regions[world.player_logic.sunwarp_entrances[i]] | ||
| 170 | target_region = regions[world.player_logic.sunwarp_exits[i]] | ||
| 171 | |||
| 172 | entrance_name = f"{source_region.name} to {target_region.name} ({i + 1} Sunwarp)" | ||
| 173 | connect_entrance(regions, source_region, target_region, entrance_name, effective_door, EntranceType.SUNWARP, | ||
| 174 | False, world) | ||
| 175 | |||
| 93 | world.multiworld.regions += regions.values() | 176 | world.multiworld.regions += regions.values() |
