76 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			76 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								import json
							 | 
						||
| 
								 | 
							
								from pathlib import Path
							 | 
						||
| 
								 | 
							
								from typing import Dict, NamedTuple, List, Optional
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from BaseClasses import Region, RegionType, Location
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EventId: Optional[int] = None
							 | 
						||
| 
								 | 
							
								CHAOS_TERMINATED_EVENT = 'Terminated Chaos'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class LocationData(NamedTuple):
							 | 
						||
| 
								 | 
							
								    name: str
							 | 
						||
| 
								 | 
							
								    address: int
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FF1Locations:
							 | 
						||
| 
								 | 
							
								    _location_table: List[LocationData] = []
							 | 
						||
| 
								 | 
							
								    _location_table_lookup: Dict[str, LocationData] = {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _populate_item_table_from_data(self):
							 | 
						||
| 
								 | 
							
								        base_path = Path(__file__).parent
							 | 
						||
| 
								 | 
							
								        file_path = (base_path / "data/locations.json").resolve()
							 | 
						||
| 
								 | 
							
								        with open(file_path) as file:
							 | 
						||
| 
								 | 
							
								            locations = json.load(file)
							 | 
						||
| 
								 | 
							
								            # Hardcode progression and categories for now
							 | 
						||
| 
								 | 
							
								            self._location_table = [LocationData(name, code) for name, code in locations.items()]
							 | 
						||
| 
								 | 
							
								            self._location_table_lookup = {item.name: item for item in self._location_table}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_location_table(self) -> List[LocationData]:
							 | 
						||
| 
								 | 
							
								        if not self._location_table or not self._location_table_lookup:
							 | 
						||
| 
								 | 
							
								            self._populate_item_table_from_data()
							 | 
						||
| 
								 | 
							
								        return self._location_table
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_location_table_lookup(self) -> Dict[str, LocationData]:
							 | 
						||
| 
								 | 
							
								        if not self._location_table or not self._location_table_lookup:
							 | 
						||
| 
								 | 
							
								            self._populate_item_table_from_data()
							 | 
						||
| 
								 | 
							
								        return self._location_table_lookup
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_location_name_to_address_dict(self) -> Dict[str, int]:
							 | 
						||
| 
								 | 
							
								        data = {name: location.address for name, location in self._get_location_table_lookup().items()}
							 | 
						||
| 
								 | 
							
								        data[CHAOS_TERMINATED_EVENT] = EventId
							 | 
						||
| 
								 | 
							
								        return data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def create_menu_region(player: int, locations: Dict[str, int],
							 | 
						||
| 
								 | 
							
								                           rules: Dict[str, List[List[str]]]) -> Region:
							 | 
						||
| 
								 | 
							
								        menu_region = Region("Menu", RegionType.Generic, "Menu", player)
							 | 
						||
| 
								 | 
							
								        for name, address in locations.items():
							 | 
						||
| 
								 | 
							
								            location = Location(player, name, address, menu_region)
							 | 
						||
| 
								 | 
							
								            ## TODO REMOVE WHEN LOGIC FOR TOFR IS CORRECT
							 | 
						||
| 
								 | 
							
								            if "ToFR" in name:
							 | 
						||
| 
								 | 
							
								                rules_list = [["Rod", "Cube", "Lute", "Key", "Chime", "Oxyale",
							 | 
						||
| 
								 | 
							
								                               "Ship", "Canoe", "Floater", "Canal",
							 | 
						||
| 
								 | 
							
								                               "Crown", "Crystal", "Herb", "Tnt", "Adamant", "Slab", "Ruby", "Bottle"]]
							 | 
						||
| 
								 | 
							
								                location.access_rule = generate_rule(rules_list, player)
							 | 
						||
| 
								 | 
							
								            elif name in rules:
							 | 
						||
| 
								 | 
							
								                rules_list = rules[name]
							 | 
						||
| 
								 | 
							
								                location.access_rule = generate_rule(rules_list, player)
							 | 
						||
| 
								 | 
							
								            menu_region.locations.append(location)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return menu_region
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def generate_rule(rules_list, player):
							 | 
						||
| 
								 | 
							
								    def x(state):
							 | 
						||
| 
								 | 
							
								        for rule in rules_list:
							 | 
						||
| 
								 | 
							
								            current_state = True
							 | 
						||
| 
								 | 
							
								            for item in rule:
							 | 
						||
| 
								 | 
							
								                if not state.has(item, player):
							 | 
						||
| 
								 | 
							
								                    current_state = False
							 | 
						||
| 
								 | 
							
								                    break
							 | 
						||
| 
								 | 
							
								            if current_state:
							 | 
						||
| 
								 | 
							
								                return True
							 | 
						||
| 
								 | 
							
								        return False
							 | 
						||
| 
								 | 
							
								    return x
							 |