112 lines
3.7 KiB
Python
112 lines
3.7 KiB
Python
from enum import Enum
|
|
from typing import List, Callable
|
|
from .Item import Progression
|
|
from . import Region
|
|
from . import World
|
|
|
|
class LocationType(Enum):
|
|
Regular = 0
|
|
HeraStandingKey = 1
|
|
Pedestal = 2
|
|
Ether = 3
|
|
Bombos = 4
|
|
NotInDungeon = 5
|
|
|
|
Visible = 6
|
|
Chozo = 7
|
|
Hidden = 8
|
|
|
|
# delegate bool Requirement(Progression items);
|
|
# delegate bool Verification(Item item, Progression items);
|
|
|
|
class Location:
|
|
Id: int
|
|
Name: str
|
|
Type: LocationType
|
|
Address: int
|
|
Region: Region
|
|
|
|
def Weight(self): return self.weight if self.weight != None else self.Region.Weight
|
|
|
|
canAccess: Callable = lambda items: True
|
|
alwaysAllow: Callable = lambda item, items: True
|
|
allow: Callable = lambda item, items: True
|
|
weight: int
|
|
|
|
def ItemIs(self, type, world: World):
|
|
item = self.APLocation.item.item if self.APLocation.item is not None and self.APLocation.item.game == "SMZ3" else None
|
|
return item.Is(type, world) if item != None else False
|
|
def ItemIsNot(self, type, world: World): return not self.ItemIs(type, world)
|
|
|
|
def __init__(self, region: Region, id: int, address: int, type: LocationType, name: str, access: Callable = lambda items : True):
|
|
self.Region = region
|
|
self.Id = id
|
|
self.Name = name
|
|
self.Type = type
|
|
self.Item = None
|
|
self.Address = address
|
|
self.canAccess = access
|
|
self.alwaysAllow = lambda item, items: False
|
|
self.allow = lambda item, items: True
|
|
|
|
def Weighted(self, weight: int):
|
|
self.weight = weight
|
|
return self
|
|
|
|
def AlwaysAllow(self, allow: Callable):
|
|
self.alwaysAllow = allow
|
|
return self
|
|
|
|
def Allow(self, allow: Callable):
|
|
self.allow = allow
|
|
return self
|
|
|
|
def Available(self, items: Progression):
|
|
return self.Region.CanEnter(items) and self.canAccess(items)
|
|
|
|
def CanFill(self, item, items: Progression):
|
|
oldItem = self.Item
|
|
self.Item = item
|
|
fillable = self.alwaysAllow(item, items) or (self.Region.CanFill(item) and self.allow(item, items) and self.Available(items))
|
|
self.Item = oldItem
|
|
return fillable
|
|
|
|
@staticmethod
|
|
def Get(locations, name: str):
|
|
loc = next((l for l in locations if l.Name == name), None)
|
|
if (loc == None):
|
|
raise Exception(f"Could not find location name {name}")
|
|
return loc
|
|
|
|
@staticmethod
|
|
def Empty(locations):
|
|
return [l for l in locations if l.Item == None]
|
|
|
|
@staticmethod
|
|
def Filled(locations):
|
|
return [l for l in locations if l.Item != None]
|
|
|
|
@staticmethod
|
|
def AvailableWithinWorld(locations, items):
|
|
result = []
|
|
worldList = []
|
|
[worldList.append(l.Region.World) for l in locations if l.Region.World not in worldList]
|
|
for world in worldList:
|
|
result += Location.AvailableGlobal([l for l in locations if l.Region.World == world], [i for i in items if i.World == world])
|
|
return result
|
|
|
|
@staticmethod
|
|
def AvailableGlobal(locations, items):
|
|
progression = Progression(items)
|
|
return [l for l in locations if l.Available(progression)]
|
|
|
|
@staticmethod
|
|
def CanFillWithinWorld(locations, item, items):
|
|
itemWorldProgression = Progression([i for i in items if i.World == item.World].append(item))
|
|
worldList = []
|
|
[worldList.append(l.Region.World) for l in locations if l.Region.World not in worldList]
|
|
worldProgression = {world.Id : Progression([i for i in items if i.World == world]) for world in worldList}
|
|
return [l for l in locations if l.CanFill(item, worldProgression[l.Region.World.Id] and next(ll for ll in item.World.Locations if ll.Id == l.Id).Available(itemWorldProgression))]
|
|
|
|
# Start of AP integration
|
|
locations_start_id = 85000 |