| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | from typing import Dict | 
					
						
							| 
									
										
										
										
											2022-07-16 23:52:47 +02:00
										 |  |  | from BaseClasses import Item, Location, MultiWorld, Tutorial, ItemClassification | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | from .Items import ItemData, FF1Items, FF1_STARTER_ITEMS, FF1_PROGRESSION_LIST, FF1_BRIDGE | 
					
						
							|  |  |  | from .Locations import EventId, FF1Locations, generate_rule, CHAOS_TERMINATED_EVENT | 
					
						
							|  |  |  | from .Options import ff1_options | 
					
						
							| 
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 |  |  | from ..AutoWorld import World, WebWorld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FF1Web(WebWorld): | 
					
						
							|  |  |  |     settings_page = "https://finalfantasyrandomizer.com/" | 
					
						
							| 
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 |  |  |     tutorials = [Tutorial( | 
					
						
							|  |  |  |         "Multiworld Setup Guide", | 
					
						
							|  |  |  |         "A guide to playing Final Fantasy multiworld. This guide only covers playing multiworld.", | 
					
						
							|  |  |  |         "English", | 
					
						
							|  |  |  |         "multiworld_en.md", | 
					
						
							|  |  |  |         "multiworld/en", | 
					
						
							|  |  |  |         ["jat2980"] | 
					
						
							|  |  |  |     )] | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FF1World(World): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Final Fantasy 1, originally released on the NES on 1987, is the game that started the beloved, long running series. | 
					
						
							|  |  |  |     The randomizer takes the original 8-bit Final Fantasy game for NES (USA edition) and allows you to | 
					
						
							|  |  |  |     shuffle important aspects like the location of key items, the difficulty of monsters and fiends, | 
					
						
							|  |  |  |     and even the location of towns and dungeons. | 
					
						
							|  |  |  |     Part puzzle and part speed-run, it breathes new life into one of the most influential games ever made. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 16:46:59 -05:00
										 |  |  |     option_definitions = ff1_options | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |     game = "Final Fantasy" | 
					
						
							|  |  |  |     topology_present = False | 
					
						
							| 
									
										
										
										
											2022-09-05 03:21:00 -04:00
										 |  |  |     data_version = 2 | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ff1_items = FF1Items() | 
					
						
							|  |  |  |     ff1_locations = FF1Locations() | 
					
						
							|  |  |  |     item_name_groups = ff1_items.get_item_names_per_category() | 
					
						
							|  |  |  |     item_name_to_id = ff1_items.get_item_name_to_code_dict() | 
					
						
							|  |  |  |     location_name_to_id = ff1_locations.get_location_name_to_address_dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 |  |  |     web = FF1Web() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |     def __init__(self, world: MultiWorld, player: int): | 
					
						
							|  |  |  |         super().__init__(world, player) | 
					
						
							|  |  |  |         self.locked_items = [] | 
					
						
							|  |  |  |         self.locked_locations = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_early(self): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_regions(self): | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         locations = get_options(self.multiworld, 'locations', self.player) | 
					
						
							|  |  |  |         rules = get_options(self.multiworld, 'rules', self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         menu_region = self.ff1_locations.create_menu_region(self.player, locations, rules) | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         menu_region.multiworld = self.multiworld | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         terminated_event = Location(self.player, CHAOS_TERMINATED_EVENT, EventId, menu_region) | 
					
						
							| 
									
										
										
										
											2022-07-16 23:52:47 +02:00
										 |  |  |         terminated_item = Item(CHAOS_TERMINATED_EVENT, ItemClassification.progression, EventId, self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         terminated_event.place_locked_item(terminated_item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         items = get_options(self.multiworld, 'items', self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         goal_rule = generate_rule([[name for name in items.keys() if name in FF1_PROGRESSION_LIST and name != "Shard"]], | 
					
						
							|  |  |  |                                   self.player) | 
					
						
							|  |  |  |         if "Shard" in items.keys(): | 
					
						
							|  |  |  |             def goal_rule_and_shards(state): | 
					
						
							|  |  |  |                 return goal_rule(state) and state.has("Shard", self.player, 32) | 
					
						
							|  |  |  |             terminated_event.access_rule = goal_rule_and_shards | 
					
						
							| 
									
										
										
										
											2022-09-11 19:55:11 -04:00
										 |  |  |         if "MARK" in items.keys(): | 
					
						
							|  |  |  |             # Fail generation for Noverworld and provide link to old FFR website | 
					
						
							|  |  |  |             raise Exception("FFR Noverworld seeds must be generated on an older version of FFR. Please ensure you generated the settings using " | 
					
						
							|  |  |  |                             "4-4-0.finalfantasyrandomizer.com") | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         menu_region.locations.append(terminated_event) | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.regions += [menu_region] | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def create_item(self, name: str) -> Item: | 
					
						
							|  |  |  |         return self.ff1_items.generate_item(name, self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_rules(self): | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.completion_condition[self.player] = lambda state: state.has(CHAOS_TERMINATED_EVENT, self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def generate_basic(self): | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         items = get_options(self.multiworld, 'items', self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         if FF1_BRIDGE in items.keys(): | 
					
						
							|  |  |  |             self._place_locked_item_in_sphere0(FF1_BRIDGE) | 
					
						
							|  |  |  |         if items: | 
					
						
							|  |  |  |             possible_early_items = [name for name in FF1_STARTER_ITEMS if name in items.keys()] | 
					
						
							|  |  |  |             if possible_early_items: | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |                 progression_item = self.multiworld.random.choice(possible_early_items) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |                 self._place_locked_item_in_sphere0(progression_item) | 
					
						
							| 
									
										
										
										
											2022-02-20 12:36:12 -07:00
										 |  |  |         else: | 
					
						
							|  |  |  |             # Fail generation if there are no items in the pool | 
					
						
							|  |  |  |             raise Exception("FFR settings submitted with no key items. Please ensure you generated the settings using " | 
					
						
							|  |  |  |                             "finalfantasyrandomizer.com AND enabled the AP flag") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |         items = [self.create_item(name) for name, data in items.items() for x in range(data['count']) if name not in | 
					
						
							|  |  |  |                  self.locked_items] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.itempool += items | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _place_locked_item_in_sphere0(self, progression_item: str): | 
					
						
							|  |  |  |         if progression_item: | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |             rules = get_options(self.multiworld, 'rules', self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |             sphere_0_locations = [name for name, rules in rules.items() | 
					
						
							|  |  |  |                                   if rules and len(rules[0]) == 0 and name not in self.locked_locations] | 
					
						
							|  |  |  |             if sphere_0_locations: | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |                 initial_location = self.multiworld.random.choice(sphere_0_locations) | 
					
						
							|  |  |  |                 locked_location = self.multiworld.get_location(initial_location, self.player) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  |                 locked_location.place_locked_item(self.create_item(progression_item)) | 
					
						
							|  |  |  |                 self.locked_items.append(progression_item) | 
					
						
							|  |  |  |                 self.locked_locations.append(locked_location.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fill_slot_data(self) -> Dict[str, object]: | 
					
						
							|  |  |  |         slot_data: Dict[str, object] = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return slot_data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-19 09:37:26 -04:00
										 |  |  |     def get_filler_item_name(self) -> str: | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         return self.multiworld.random.choice(["Heal", "Pure", "Soft", "Tent", "Cabin", "House"]) | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 23:52:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 |  |  | def get_options(world: MultiWorld, name: str, player: int): | 
					
						
							|  |  |  |     return getattr(world, name, None)[player].value |