diff options
Diffstat (limited to 'rules.py')
| -rw-r--r-- | rules.py | 112 |
1 files changed, 56 insertions, 56 deletions
| diff --git a/rules.py b/rules.py index d59b8a1..ee9dcc4 100644 --- a/rules.py +++ b/rules.py | |||
| @@ -1,23 +1,23 @@ | |||
| 1 | from typing import TYPE_CHECKING | 1 | from typing import TYPE_CHECKING |
| 2 | 2 | ||
| 3 | from BaseClasses import CollectionState | 3 | from BaseClasses import CollectionState |
| 4 | from .options import VictoryCondition | 4 | from .player_logic import AccessRequirements, LingoPlayerLogic, PlayerLocation |
| 5 | from .player_logic import LingoPlayerLogic, PlayerLocation | 5 | from .static_logic import PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, RoomAndDoor |
| 6 | from .static_logic import PANELS_BY_ROOM, PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, RoomAndDoor | ||
| 7 | 6 | ||
| 8 | if TYPE_CHECKING: | 7 | if TYPE_CHECKING: |
| 9 | from . import LingoWorld | 8 | from . import LingoWorld |
| 10 | 9 | ||
| 11 | 10 | ||
| 12 | def lingo_can_use_entrance(state: CollectionState, room: str, door: RoomAndDoor, player: int, | 11 | def lingo_can_use_entrance(state: CollectionState, room: str, door: RoomAndDoor, world: "LingoWorld", |
| 13 | player_logic: LingoPlayerLogic): | 12 | player_logic: LingoPlayerLogic): |
| 14 | if door is None: | 13 | if door is None: |
| 15 | return True | 14 | return True |
| 16 | 15 | ||
| 17 | return _lingo_can_open_door(state, room, room if door.room is None else door.room, door.door, player, player_logic) | 16 | effective_room = room if door.room is None else door.room |
| 17 | return _lingo_can_open_door(state, effective_room, door.door, world, player_logic) | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | def lingo_can_use_pilgrimage(state: CollectionState, player: int, player_logic: LingoPlayerLogic): | 20 | def lingo_can_use_pilgrimage(state: CollectionState, world: "LingoWorld", player_logic: LingoPlayerLogic): |
| 21 | fake_pilgrimage = [ | 21 | fake_pilgrimage = [ |
| 22 | ["Second Room", "Exit Door"], ["Crossroads", "Tower Entrance"], | 22 | ["Second Room", "Exit Door"], ["Crossroads", "Tower Entrance"], |
| 23 | ["Orange Tower Fourth Floor", "Hot Crusts Door"], ["Outside The Initiated", "Shortcut to Hub Room"], | 23 | ["Orange Tower Fourth Floor", "Hot Crusts Door"], ["Outside The Initiated", "Shortcut to Hub Room"], |
| @@ -28,77 +28,77 @@ def lingo_can_use_pilgrimage(state: CollectionState, player: int, player_logic: | |||
| 28 | ["Outside The Agreeable", "Tenacious Entrance"] | 28 | ["Outside The Agreeable", "Tenacious Entrance"] |
| 29 | ] | 29 | ] |
| 30 | for entrance in fake_pilgrimage: | 30 | for entrance in fake_pilgrimage: |
| 31 | if not state.has(player_logic.ITEM_BY_DOOR[entrance[0]][entrance[1]], player): | 31 | if not _lingo_can_open_door(state, entrance[0], entrance[1], world, player_logic): |
| 32 | return False | 32 | return False |
| 33 | 33 | ||
| 34 | return True | 34 | return True |
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | def lingo_can_use_location(state: CollectionState, location: PlayerLocation, room_name: str, world: "LingoWorld", | 37 | def lingo_can_use_location(state: CollectionState, location: PlayerLocation, world: "LingoWorld", |
| 38 | player_logic: LingoPlayerLogic): | 38 | player_logic: LingoPlayerLogic): |
| 39 | for panel in location.panels: | 39 | return _lingo_can_satisfy_requirements(state, location.access, world, player_logic) |
| 40 | panel_room = room_name if panel.room is None else panel.room | ||
| 41 | if not _lingo_can_solve_panel(state, room_name, panel_room, panel.panel, world, player_logic): | ||
| 42 | return False | ||
| 43 | |||
| 44 | return True | ||
| 45 | |||
| 46 | 40 | ||
| 47 | def lingo_can_use_mastery_location(state: CollectionState, world: "LingoWorld"): | ||
| 48 | return state.has("Mastery Achievement", world.player, world.options.mastery_achievements.value) | ||
| 49 | |||
| 50 | |||
| 51 | def _lingo_can_open_door(state: CollectionState, start_room: str, room: str, door: str, player: int, | ||
| 52 | player_logic: LingoPlayerLogic): | ||
| 53 | """ | ||
| 54 | Determines whether a door can be opened | ||
| 55 | """ | ||
| 56 | item_name = player_logic.ITEM_BY_DOOR[room][door] | ||
| 57 | if item_name in PROGRESSIVE_ITEMS: | ||
| 58 | progression = PROGRESSION_BY_ROOM[room][door] | ||
| 59 | return state.has(item_name, player, progression.index) | ||
| 60 | 41 | ||
| 61 | return state.has(item_name, player) | 42 | def lingo_can_use_mastery_location(state: CollectionState, world: "LingoWorld", player_logic: LingoPlayerLogic): |
| 43 | satisfied_count = 0 | ||
| 44 | for access_req in player_logic.mastery_reqs: | ||
| 45 | if _lingo_can_satisfy_requirements(state, access_req, world, player_logic): | ||
| 46 | satisfied_count += 1 | ||
| 47 | return satisfied_count >= world.options.mastery_achievements.value | ||
| 62 | 48 | ||
| 63 | 49 | ||
| 64 | def _lingo_can_solve_panel(state: CollectionState, start_room: str, room: str, panel: str, world: "LingoWorld", | 50 | def lingo_can_use_level_2_location(state: CollectionState, world: "LingoWorld", player_logic: LingoPlayerLogic): |
| 65 | player_logic: LingoPlayerLogic): | 51 | counted_panels = 0 |
| 66 | """ | 52 | state.update_reachable_regions(world.player) |
| 67 | Determines whether a panel can be solved | 53 | for region in state.reachable_regions[world.player]: |
| 68 | """ | 54 | for access_req, panel_count in player_logic.counting_panel_reqs.get(region.name, []): |
| 69 | if start_room != room and not state.can_reach(room, "Region", world.player): | 55 | if _lingo_can_satisfy_requirements(state, access_req, world, player_logic): |
| 70 | return False | 56 | counted_panels += panel_count |
| 57 | if counted_panels >= world.options.level_2_requirement.value - 1: | ||
| 58 | return True | ||
| 59 | return False | ||
| 71 | 60 | ||
| 72 | if room == "Second Room" and panel == "ANOTHER TRY" \ | ||
| 73 | and world.options.victory_condition == VictoryCondition.option_level_2 \ | ||
| 74 | and not state.has("Counting Panel Solved", world.player, world.options.level_2_requirement.value - 1): | ||
| 75 | return False | ||
| 76 | 61 | ||
| 77 | panel_object = PANELS_BY_ROOM[room][panel] | 62 | def _lingo_can_satisfy_requirements(state: CollectionState, access: AccessRequirements, world: "LingoWorld", |
| 78 | for req_room in panel_object.required_rooms: | 63 | player_logic: LingoPlayerLogic): |
| 64 | for req_room in access.rooms: | ||
| 79 | if not state.can_reach(req_room, "Region", world.player): | 65 | if not state.can_reach(req_room, "Region", world.player): |
| 80 | return False | 66 | return False |
| 81 | 67 | ||
| 82 | for req_door in panel_object.required_doors: | 68 | for req_door in access.doors: |
| 83 | if not _lingo_can_open_door(state, start_room, room if req_door.room is None else req_door.room, | 69 | if not _lingo_can_open_door(state, req_door.room, req_door.door, world, player_logic): |
| 84 | req_door.door, world.player, player_logic): | ||
| 85 | return False | ||
| 86 | |||
| 87 | for req_panel in panel_object.required_panels: | ||
| 88 | if not _lingo_can_solve_panel(state, start_room, room if req_panel.room is None else req_panel.room, | ||
| 89 | req_panel.panel, world, player_logic): | ||
| 90 | return False | 70 | return False |
| 91 | 71 | ||
| 92 | if len(panel_object.colors) > 0 and world.options.shuffle_colors: | 72 | if len(access.colors) > 0 and world.options.shuffle_colors: |
| 93 | for color in panel_object.colors: | 73 | for color in access.colors: |
| 94 | if not state.has(color.capitalize(), world.player): | 74 | if not state.has(color.capitalize(), world.player): |
| 95 | return False | 75 | return False |
| 96 | 76 | ||
| 97 | return True | 77 | return True |
| 98 | 78 | ||
| 99 | 79 | ||
| 100 | def make_location_lambda(location: PlayerLocation, room_name: str, world: "LingoWorld", player_logic: LingoPlayerLogic): | 80 | def _lingo_can_open_door(state: CollectionState, room: str, door: str, world: "LingoWorld", |
| 101 | if location.name == player_logic.MASTERY_LOCATION: | 81 | player_logic: LingoPlayerLogic): |
| 102 | return lambda state: lingo_can_use_mastery_location(state, world) | 82 | """ |
| 83 | Determines whether a door can be opened | ||
| 84 | """ | ||
| 85 | if door not in player_logic.item_by_door.get(room, {}): | ||
| 86 | return _lingo_can_satisfy_requirements(state, player_logic.door_reqs[room][door], world, player_logic) | ||
| 87 | |||
| 88 | item_name = player_logic.item_by_door[room][door] | ||
| 89 | if item_name in PROGRESSIVE_ITEMS: | ||
| 90 | progression = PROGRESSION_BY_ROOM[room][door] | ||
| 91 | return state.has(item_name, world.player, progression.index) | ||
| 92 | |||
| 93 | return state.has(item_name, world.player) | ||
| 94 | |||
| 95 | |||
| 96 | def make_location_lambda(location: PlayerLocation, world: "LingoWorld", player_logic: LingoPlayerLogic): | ||
| 97 | if location.name == player_logic.mastery_location: | ||
| 98 | return lambda state: lingo_can_use_mastery_location(state, world, player_logic) | ||
| 99 | |||
| 100 | if world.options.level_2_requirement > 1\ | ||
| 101 | and (location.name == "Second Room - ANOTHER TRY" or location.name == player_logic.level_2_location): | ||
| 102 | return lambda state: lingo_can_use_level_2_location(state, world, player_logic) | ||
| 103 | 103 | ||
| 104 | return lambda state: lingo_can_use_location(state, location, room_name, world, player_logic) | 104 | return lambda state: lingo_can_use_location(state, location, world, player_logic) |
