diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2023-11-08 18:35:12 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-08 17:35:12 -0600 |
| commit | bbbbc71bee25cfd22c5304f98f5a7881383585a3 (patch) | |
| tree | d27581db7b8db03da4b731fe8c2d5072d3162cf8 /rules.py | |
| download | lingo-apworld-bbbbc71bee25cfd22c5304f98f5a7881383585a3.tar.gz lingo-apworld-bbbbc71bee25cfd22c5304f98f5a7881383585a3.tar.bz2 lingo-apworld-bbbbc71bee25cfd22c5304f98f5a7881383585a3.zip | |
Lingo: New game (#1806)
Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com> Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com> Co-authored-by: Phar <zach@alliware.com>
Diffstat (limited to 'rules.py')
| -rw-r--r-- | rules.py | 104 |
1 files changed, 104 insertions, 0 deletions
| diff --git a/rules.py b/rules.py new file mode 100644 index 0000000..90c889b --- /dev/null +++ b/rules.py | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | from typing import TYPE_CHECKING | ||
| 2 | |||
| 3 | from BaseClasses import CollectionState | ||
| 4 | from .options import VictoryCondition | ||
| 5 | from .player_logic import LingoPlayerLogic, PlayerLocation | ||
| 6 | from .static_logic import PANELS_BY_ROOM, PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, RoomAndDoor | ||
| 7 | |||
| 8 | if TYPE_CHECKING: | ||
| 9 | from . import LingoWorld | ||
| 10 | |||
| 11 | |||
| 12 | def lingo_can_use_entrance(state: CollectionState, room: str, door: RoomAndDoor, player: int, | ||
| 13 | player_logic: LingoPlayerLogic): | ||
| 14 | if door is None: | ||
| 15 | return True | ||
| 16 | |||
| 17 | return _lingo_can_open_door(state, room, room if door.room is None else door.room, door.door, player, player_logic) | ||
| 18 | |||
| 19 | |||
| 20 | def lingo_can_use_pilgrimage(state: CollectionState, player: int, player_logic: LingoPlayerLogic): | ||
| 21 | fake_pilgrimage = [ | ||
| 22 | ["Second Room", "Exit Door"], ["Crossroads", "Tower Entrance"], | ||
| 23 | ["Orange Tower Fourth Floor", "Hot Crusts Door"], ["Outside The Initiated", "Shortcut to Hub Room"], | ||
| 24 | ["Orange Tower First Floor", "Shortcut to Hub Room"], ["Directional Gallery", "Shortcut to The Undeterred"], | ||
| 25 | ["Orange Tower First Floor", "Salt Pepper Door"], ["Hub Room", "Crossroads Entrance"], | ||
| 26 | ["Champion's Rest", "Shortcut to The Steady"], ["The Bearer", "Shortcut to The Bold"], | ||
| 27 | ["Art Gallery", "Exit"], ["The Tenacious", "Shortcut to Hub Room"], | ||
| 28 | ["Outside The Agreeable", "Tenacious Entrance"] | ||
| 29 | ] | ||
| 30 | for entrance in fake_pilgrimage: | ||
| 31 | if not state.has(player_logic.ITEM_BY_DOOR[entrance[0]][entrance[1]], player): | ||
| 32 | return False | ||
| 33 | |||
| 34 | return True | ||
| 35 | |||
| 36 | |||
| 37 | def lingo_can_use_location(state: CollectionState, location: PlayerLocation, room_name: str, world: "LingoWorld", | ||
| 38 | player_logic: LingoPlayerLogic): | ||
| 39 | for panel in location.panels: | ||
| 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 | |||
| 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 | |||
| 61 | return state.has(item_name, player) | ||
| 62 | |||
| 63 | |||
| 64 | def _lingo_can_solve_panel(state: CollectionState, start_room: str, room: str, panel: str, world: "LingoWorld", | ||
| 65 | player_logic: LingoPlayerLogic): | ||
| 66 | """ | ||
| 67 | Determines whether a panel can be solved | ||
| 68 | """ | ||
| 69 | if start_room != room and not state.has(f"{room} (Reached)", world.player): | ||
| 70 | return False | ||
| 71 | |||
| 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 | |||
| 77 | panel_object = PANELS_BY_ROOM[room][panel] | ||
| 78 | for req_room in panel_object.required_rooms: | ||
| 79 | if not state.has(f"{req_room} (Reached)", world.player): | ||
| 80 | return False | ||
| 81 | |||
| 82 | for req_door in panel_object.required_doors: | ||
| 83 | if not _lingo_can_open_door(state, start_room, room if req_door.room is None else req_door.room, | ||
| 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 | ||
| 91 | |||
| 92 | if len(panel_object.colors) > 0 and world.options.shuffle_colors: | ||
| 93 | for color in panel_object.colors: | ||
| 94 | if not state.has(color.capitalize(), world.player): | ||
| 95 | return False | ||
| 96 | |||
| 97 | return True | ||
| 98 | |||
| 99 | |||
| 100 | def make_location_lambda(location: PlayerLocation, room_name: str, world: "LingoWorld", player_logic: LingoPlayerLogic): | ||
| 101 | if location.name == player_logic.MASTERY_LOCATION: | ||
| 102 | return lambda state: lingo_can_use_mastery_location(state, world) | ||
| 103 | |||
| 104 | return lambda state: lingo_can_use_location(state, location, room_name, world, player_logic) | ||
