about summary refs log tree commit diff stats
path: root/apworld/rules.py
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/rules.py')
-rw-r--r--apworld/rules.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/apworld/rules.py b/apworld/rules.py new file mode 100644 index 0000000..c077858 --- /dev/null +++ b/apworld/rules.py
@@ -0,0 +1,63 @@
1from collections.abc import Callable
2from typing import TYPE_CHECKING
3
4from BaseClasses import CollectionState, Region
5from .player_logic import AccessRequirements
6
7if TYPE_CHECKING:
8 from . import Lingo2World
9
10
11def lingo2_can_satisfy_requirements(state: CollectionState, reqs: AccessRequirements, regions: list[Region],
12 world: "Lingo2World") -> bool:
13 if not all(state.has(item, world.player) for item in reqs.items):
14 return False
15
16 if not all(state.has(item, world.player, amount) for item, amount in reqs.progressives.items()):
17 return False
18
19 if not all(state.can_reach_region(region_name, world.player) for region_name in reqs.rooms):
20 return False
21
22 if not all(state.can_reach(region) for region in regions):
23 return False
24
25 for letter_key, letter_level in reqs.letters.items():
26 if not state.has(letter_key, world.player, letter_level):
27 return False
28
29 if reqs.cyans:
30 if not any(state.has(letter, world.player, amount)
31 for letter, amount in world.player_logic.double_letter_amount.items()):
32 return False
33
34 if len(reqs.or_logic) > 0:
35 if not all(any(lingo2_can_satisfy_requirements(state, sub_reqs, [], world) for sub_reqs in subjunction)
36 for subjunction in reqs.or_logic):
37 return False
38
39 if reqs.complete_at is not None:
40 completed = 0
41 checked = 0
42 for possibility in reqs.possibilities:
43 checked += 1
44 if lingo2_can_satisfy_requirements(state, possibility, [], world):
45 completed += 1
46 if completed >= reqs.complete_at:
47 break
48 elif len(reqs.possibilities) - checked + completed < reqs.complete_at:
49 # There aren't enough remaining possibilities for the check to pass.
50 return False
51 if completed < reqs.complete_at:
52 return False
53
54 return True
55
56def make_location_lambda(reqs: AccessRequirements, world: "Lingo2World",
57 regions: dict[str, Region]) -> Callable[[CollectionState], bool]:
58 # Replace required rooms with regions for the top level requirement, which saves looking up the regions during rule
59 # checking.
60 required_regions = [regions[room_name] for room_name in reqs.rooms]
61 new_reqs = reqs.copy()
62 new_reqs.rooms.clear()
63 return lambda state: lingo2_can_satisfy_requirements(state, new_reqs, required_regions, world)