112 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
from enum import Enum
 | 
						|
from typing import List, Callable
 | 
						|
from worlds.smz3.TotalSMZ3.Item import Progression
 | 
						|
import worlds.smz3.TotalSMZ3.Region as Region
 | 
						|
import worlds.smz3.TotalSMZ3.World as 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 |