| 
									
										
										
										
											2022-03-15 08:55:57 -04:00
										 |  |  |  | from enum import Enum | 
					
						
							|  |  |  |  | from typing import List, Callable | 
					
						
							| 
									
										
										
										
											2023-04-08 16:52:34 -04:00
										 |  |  |  | from .Item import Progression | 
					
						
							|  |  |  |  | from . import Region | 
					
						
							|  |  |  |  | from . import World | 
					
						
							| 
									
										
										
										
											2022-03-15 08:55:57 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 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 |