2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import settings
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import typing
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											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
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Options import FF1Options
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from ..AutoWorld import World, WebWorld
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class FF1Settings(settings.Group):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    display_msgs: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class FF1Web(WebWorld):
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-23 19:20:08 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    options_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.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    options: FF1Options
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    options_dataclass = FF1Options
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    settings: typing.ClassVar[FF1Settings]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    settings_key = "ffr_options"
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    game = "Final Fantasy"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    topology_present = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    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 = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-15 15:46:10 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def stage_assert_generate(cls, multiworld: MultiWorld) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Fail generation if there are no items in the pool
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for player in multiworld.get_game_players(cls.game):
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            items = multiworld.worlds[player].options.items.value
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert items, \
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-15 15:46:10 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                f"FFR settings submitted with no key items ({multiworld.get_player_name(player)}). Please ensure you " \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"generated the settings using finalfantasyrandomizer.com AND enabled the AP flag"
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def create_regions(self):
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        locations = self.options.locations.value
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        rules = self.options.rules.value
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-13 18:06:43 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        menu_region = self.ff1_locations.create_menu_region(self.player, locations, rules, 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)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        items = self.options.items.value
							 | 
						
					
						
							
								
									
										
										
										
											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)
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-01 12:13:35 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        terminated_event.access_rule = goal_rule
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-28 14:32:08 -07:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        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
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-15 15:46:10 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            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
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-10 18:51:13 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_items(self):
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        items = self.options.items.value
							 | 
						
					
						
							
								
									
										
										
										
											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
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											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:
							 | 
						
					
						
							
								
									
										
										
										
											2024-05-17 13:19:55 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rules = self.options.rules.value
							 | 
						
					
						
							
								
									
										
										
										
											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"])
							 |