forked from AmazingAmpharos/OoT-Randomizer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLocation.py
executable file
·144 lines (108 loc) · 4.42 KB
/
Location.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from LocationList import location_table
from Region import TimeOfDay
from enum import Enum
class Location(object):
def __init__(self, name='', address=None, address2=None, default=None, type='Chest', scene=None, parent=None, filter_tags=None, internal=False):
self.name = name
self.parent_region = parent
self.item = None
self.address = address
self.address2 = address2
self.default = default
self.type = type
self.scene = scene
self.internal = internal
self.staleness_count = 0
self.access_rule = lambda state, **kwargs: True
self.access_rules = []
self.item_rule = lambda location, item: True
self.locked = False
self.price = None
self.minor_only = False
self.world = None
self.disabled = DisableType.ENABLED
if filter_tags is None:
self.filter_tags = None
else:
self.filter_tags = list(filter_tags)
def copy(self, new_region):
new_location = Location(self.name, self.address, self.address2, self.default, self.type, self.scene, new_region, self.filter_tags)
new_location.world = new_region.world
if self.item:
new_location.item = self.item.copy(new_region.world)
new_location.item.location = new_location
new_location.access_rule = self.access_rule
new_location.access_rules = list(self.access_rules)
new_location.item_rule = self.item_rule
new_location.locked = self.locked
new_location.internal = self.internal
new_location.minor_only = self.minor_only
new_location.disabled = self.disabled
return new_location
def add_rule(self, lambda_rule):
self.access_rules.append(lambda_rule)
self.access_rule = lambda state, **kwargs: all(rule(state, **kwargs) for rule in self.access_rules)
def set_rule(self, lambda_rule):
self.access_rule = lambda_rule
self.access_rules = [lambda_rule]
def can_fill(self, state, item, check_access=True):
if self.minor_only and item.majoritem:
return False
return (
not self.is_disabled() and
self.can_fill_fast(item) and
(not check_access or state.playthrough.spot_access(self, 'either')))
def can_fill_fast(self, item, manual=False):
return (self.parent_region.can_fill(item, manual) and self.item_rule(self, item))
def is_disabled(self):
return (self.disabled == DisableType.DISABLED) or \
(self.disabled == DisableType.PENDING and self.locked)
# Can the player see what's placed at this location without collecting it?
# Used to reduce JSON spoiler noise
def has_preview(self):
if self.type in ('Collectable', 'BossHeart', 'GS Token', 'Shop'):
return True
if self.type == 'Chest':
return self.scene == 0x10 # Treasure Chest Game Prize
if self.type == 'NPC':
return self.scene in (0x4B, 0x51, 0x57) # Bombchu Bowling, Hyrule Field (OoT), Lake Hylia (RL/FA)
return False
def has_item(self):
return self.item is not None
def has_no_item(self):
return self.item is None
def has_progression_item(self):
return self.item is not None and self.item.advancement
def __str__(self):
return str(self.__unicode__())
def __unicode__(self):
return '%s' % self.name
def LocationFactory(locations, world=None):
ret = []
singleton = False
if isinstance(locations, str):
locations = [locations]
singleton = True
for location in locations:
if location in location_table:
type, scene, default, addresses, filter_tags = location_table[location]
if addresses is None:
addresses = (None, None)
address, address2 = addresses
ret.append(Location(location, address, address2, default, type, scene, filter_tags=filter_tags))
else:
raise KeyError('Unknown Location: %s', location)
if singleton:
return ret[0]
return ret
def LocationIterator(predicate=lambda loc: True):
for location_name in location_table:
location = LocationFactory(location_name)
if predicate(location):
yield location
def IsLocation(name):
return name in location_table
class DisableType(Enum):
ENABLED = 0
PENDING = 1
DISABLED = 2