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 |