summary refs log tree commit diff stats
path: root/rules.py
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-11-08 18:35:12 -0500
committerGitHub <noreply@github.com>2023-11-08 17:35:12 -0600
commitbbbbc71bee25cfd22c5304f98f5a7881383585a3 (patch)
treed27581db7b8db03da4b731fe8c2d5072d3162cf8 /rules.py
downloadlingo-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.py104
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 @@
1from typing import TYPE_CHECKING
2
3from BaseClasses import CollectionState
4from .options import VictoryCondition
5from .player_logic import LingoPlayerLogic, PlayerLocation
6from .static_logic import PANELS_BY_ROOM, PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS, RoomAndDoor
7
8if TYPE_CHECKING:
9 from . import LingoWorld
10
11
12def 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
20def 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
37def 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
47def lingo_can_use_mastery_location(state: CollectionState, world: "LingoWorld"):
48 return state.has("Mastery Achievement", world.player, world.options.mastery_achievements.value)
49
50
51def _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
64def _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
100def 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)