files.new_contents: import os
  from collections import Counter, OrderedDict
  from enum import Enum
  from math import sqrt
  
  import yaml
  
  from logic.item_types import CONSUMABLE_ITEMS, DUNGEON_NONPROGRESS_ITEMS, DUNGEON_PROGRESS_ITEMS
  from logic.logic import Logic
  from wwrando_paths import DATA_PATH
  import tweaks
  
  ITEM_LOCATION_NAME_TO_EXIT_ZONE_NAME_OVERRIDES = {
    "Pawprint Isle - Wizzrobe Cave": "Pawprint Isle Side Isle",
  }
  
  
  class HintType(Enum):
    PATH = 0
    BARREN = 1
    ITEM = 2
    LOCATION = 3
  
  
  class Hint:
    def __init__(self, type: HintType, place, reward=None):
      self.type = type
      self.place = place
      self.reward = reward
    
    def __str__(self):
      return "<HINT: %s, (%s, %s)>" % (str(self.type), self.place, self.reward)
  
  
  class Hints:
    # A dictionary mapping dungeon name to the dungeon boss.
    # The boss name is used as the path goal in the hint text.
    DUNGEON_NAME_TO_BOSS_NAME = {
      "Dragon Roost Cavern": "Gohma",
      "Forbidden Woods": "Kalle Demos",
      "Tower of the Gods": "Gohdan",
      "Forsaken Fortress": "Helmaroc King",
      "Earth Temple": "Jalhalla",
      "Wind Temple": "Molgera",
      "Hyrule": "Hyrule",
      "Ganon's Tower": "Ganondorf",
    }
    
    # A dictionary mapping dungeon name to the requirement name.
    # This dictionary is used when determining which items are on the path to a goal.
    DUNGEON_NAME_TO_REQUIREMENT_NAME = {
      "Dragon Roost Cavern": "Can Access Other Location \"Dragon Roost Cavern - Gohma Heart Container\"",
      "Forbidden Woods": "Can Access Other Location \"Forbidden Woods - Kalle Demos Heart Container\"",
      "Tower of the Gods": "Can Access Other Location \"Tower of the Gods - Gohdan Heart Container\"",
      "Forsaken Fortress": "Can Access Other Location \"Forsaken Fortress - Helmaroc King Heart Container\"",
      "Earth Temple": "Can Access Other Location \"Earth Temple - Jalhalla Heart Container\"",
      "Wind Temple": "Can Access Other Location \"Wind Temple - Molgera Heart Container\"",
      "Hyrule": "Can Access Hyrule",
      "Ganon's Tower": "Can Reach and Defeat Ganondorf",
    }
    
    def __init__(self, rando):
      self.rando = rando
      self.logic = rando.logic
      self.options = rando.options
      
      self.path_logic = Logic(self.rando)
      self.path_logic_initial_state = self.path_logic.save_simulated_playthrough_state()
      
      # Define instance variable shortcuts for hint distribution options.
      self.max_path_hints = int(self.options.get("num_path_hints", 0))
      self.max_barren_hints = int(self.options.get("num_barren_hints", 0))
      self.max_location_hints = int(self.options.get("num_location_hints", 0))
      self.max_item_hints = int(self.options.get("num_item_hints", 0))
      self.total_num_hints = self.max_path_hints + self.max_barren_hints + self.max_location_hints + self.max_item_hints
      
      self.clearer_hints = self.options.get("clearer_hints")
      self.use_always_hints = self.options.get("use_always_hints")
      
      # Import dictionaries used to build hints from files.
      with open(os.path.join(DATA_PATH, "progress_item_hints.txt"), "r") as f:
        self.progress_item_hints = yaml.safe_load(f)
      with open(os.path.join(DATA_PATH, "island_name_hints.txt"), "r") as f:
        self.island_name_hints = yaml.safe_load(f)
      with open(os.path.join(DATA_PATH, "location_hints.txt"), "r") as f:
        self.location_hints = yaml.safe_load(f)
      
      # Validate location names in location hints file.
      for location_name in self.location_hints:
        assert location_name in rando.logic.item_locations
      
      # Define a dictionary mapping charts to their sunken treasure.
      # This will be
  
  [... the rest is omitted ...]
files.new_path: hints.py
files.old_contents: import os
  from collections import Counter, OrderedDict
  from enum import Enum
  from math import sqrt
  
  import yaml
  
  from logic.item_types import CONSUMABLE_ITEMS, DUNGEON_NONPROGRESS_ITEMS, DUNGEON_PROGRESS_ITEMS
  from logic.logic import Logic
  from wwrando_paths import DATA_PATH
  import tweaks
  
  ITEM_LOCATION_NAME_TO_EXIT_ZONE_NAME_OVERRIDES = {
    "Pawprint Isle - Wizzrobe Cave": "Pawprint Isle Side Isle",
  }
  
  
  class HintType(Enum):
    PATH = 0
    BARREN = 1
    ITEM = 2
    LOCATION = 3
  
  
  class Hint:
    def __init__(self, type: HintType, place, reward=None):
      self.type = type
      self.place = place
      self.reward = reward
    
    def __str__(self):
      return "<HINT: %s, (%s, %s)>" % (str(self.type), self.place, self.reward)
  
  
  class Hints:
    # A dictionary mapping dungeon name to the dungeon boss.
    # The boss name is used as the path goal in the hint text.
    DUNGEON_NAME_TO_BOSS_NAME = {
      "Dragon Roost Cavern": "Gohma",
      "Forbidden Woods": "Kalle Demos",
      "Tower of the Gods": "Gohdan",
      "Forsaken Fortress": "Helmaroc King",
      "Earth Temple": "Jalhalla",
      "Wind Temple": "Molgera",
      "Hyrule": "Hyrule",
      "Ganon's Tower": "Ganondorf",
    }
    
    # A dictionary mapping dungeon name to the requirement name.
    # This dictionary is used when determining which items are on the path to a goal.
    DUNGEON_NAME_TO_REQUIREMENT_NAME = {
      "Dragon Roost Cavern": "Can Access Other Location \"Dragon Roost Cavern - Gohma Heart Container\"",
      "Forbidden Woods": "Can Access Other Location \"Forbidden Woods - Kalle Demos Heart Container\"",
      "Tower of the Gods": "Can Access Other Location \"Tower of the Gods - Gohdan Heart Container\"",
      "Forsaken Fortress": "Can Access Other Location \"Forsaken Fortress - Helmaroc King Heart Container\"",
      "Earth Temple": "Can Access Other Location \"Earth Temple - Jalhalla Heart Container\"",
      "Wind Temple": "Can Access Other Location \"Wind Temple - Molgera Heart Container\"",
      "Hyrule": "Can Access Hyrule",
      "Ganon's Tower": "Can Reach and Defeat Ganondorf",
    }
    
    def __init__(self, rando):
      self.rando = rando
      self.logic = rando.logic
      self.options = rando.options
      
      # Define instance variable shortcuts for hint distribution options.
      self.max_path_hints = int(self.options.get("num_path_hints", 0))
      self.max_barren_hints = int(self.options.get("num_barren_hints", 0))
      self.max_location_hints = int(self.options.get("num_location_hints", 0))
      self.max_item_hints = int(self.options.get("num_item_hints", 0))
      self.total_num_hints = self.max_path_hints + self.max_barren_hints + self.max_location_hints + self.max_item_hints
      
      self.clearer_hints = self.options.get("clearer_hints")
      self.use_always_hints = self.options.get("use_always_hints")
      
      # Import dictionaries used to build hints from files.
      with open(os.path.join(DATA_PATH, "progress_item_hints.txt"), "r") as f:
        self.progress_item_hints = yaml.safe_load(f)
      with open(os.path.join(DATA_PATH, "island_name_hints.txt"), "r") as f:
        self.island_name_hints = yaml.safe_load(f)
      with open(os.path.join(DATA_PATH, "location_hints.txt"), "r") as f:
        self.location_hints = yaml.safe_load(f)
      
      # Validate location names in location hints file.
      for location_name in self.location_hints:
        assert location_name in rando.logic.item_locations
      
      # Define a dictionary mapping charts to their sunken treasure.
      # This will be used to check whether or not the chart leads to a junk item. If so, the chart itself can be
      # considered junk.
      self.ch
  
  [... the rest is omitted ...]
files.old_path: hints.py
files.new_contents: 
  import yaml
  import re
  from collections import OrderedDict
  import copy
  
  import os
  
  from logic.item_types import PROGRESS_ITEMS, NONPROGRESS_ITEMS, CONSUMABLE_ITEMS, DUPLICATABLE_CONSUMABLE_ITEMS, DUNGEON_PROGRESS_ITEMS, DUNGEON_NONPROGRESS_ITEMS
  from wwrando_paths import LOGIC_PATH
  from randomizers import entrances
  
  class Logic:
    DUNGEON_NAMES = OrderedDict([
      ("DRC",  "Dragon Roost Cavern"),
      ("FW",   "Forbidden Woods"),
      ("TotG", "Tower of the Gods"),
      ("FF",   "Forsaken Fortress"),
      ("ET",   "Earth Temple"),
      ("WT",   "Wind Temple"),
    ])
    DUNGEON_NAME_TO_SHORT_DUNGEON_NAME = OrderedDict([v, k] for k, v in DUNGEON_NAMES.items())
    
    PROGRESS_ITEM_GROUPS = OrderedDict([
      ("Triforce Shards",  [
        "Triforce Shard 1",
        "Triforce Shard 2",
        "Triforce Shard 3",
        "Triforce Shard 4",
        "Triforce Shard 5",
        "Triforce Shard 6",
        "Triforce Shard 7",
        "Triforce Shard 8",
      ]),
      ("Goddess Pearls",  [
        "Nayru's Pearl",
        "Din's Pearl",
        "Farore's Pearl",
      ]),
      ("Tingle Statues",  [
        "Dragon Tingle Statue",
        "Forbidden Tingle Statue",
        "Goddess Tingle Statue",
        "Earth Tingle Statue",
        "Wind Tingle Statue",
      ]),
    ])
    
    initial_item_locations = None
    initial_macros = None
    
    def __init__(self, rando):
      self.rando = rando
      self.requirement_met_cache = {}
      
      
      # Initialize location related attributes.
      self.item_locations = Logic.load_and_parse_item_locations()
      self.load_and_parse_macros()
      
      self.locations_by_zone_name = OrderedDict()
      for location_name in self.item_locations:
        zone_name, specific_location_name = self.split_location_name_by_zone(location_name)
        if zone_name not in self.locations_by_zone_name:
          self.locations_by_zone_name[zone_name] = []
        self.locations_by_zone_name[zone_name].append(location_name)
      
      self.remaining_item_locations = list(self.item_locations.keys())
      self.prerandomization_item_locations = OrderedDict()
      
      self.done_item_locations = OrderedDict()
      for location_name in self.item_locations:
        self.done_item_locations[location_name] = None
      
      self.rock_spire_shop_ship_locations = []
      for location_name, location in self.item_locations.items():
        if location_name.startswith("Rock Spire Isle - Beedle's Special Shop Ship - "):
          self.rock_spire_shop_ship_locations.append(location_name)
      
      # Sync the logic macros with the randomizer.
      self.update_entrance_connection_macros()
      self.update_chart_macros()
      
      
      # Initialize item related attributes.
      self.all_progress_items = PROGRESS_ITEMS.copy()
      self.all_nonprogress_items = NONPROGRESS_ITEMS.copy()
      self.all_fixed_consumable_items = CONSUMABLE_ITEMS.copy()
      self.duplicatable_consumable_items = DUPLICATABLE_CONSUMABLE_ITEMS.copy()
      
      self.triforce_chart_names = []
      self.treasure_chart_names = []
      for i in range(1, 8+1):
        self.triforce_chart_names.append("Triforce Chart %d" % i)
      for i in range(1, 41+1):
        self.treasure_chart_names.append("Treasure Chart %d" % i)
      
      if self.rando.options.get("sword_mode") == "Swordless":
        self.all_progress_items = [
          item_name for item_name in self.all_progress_items
          if item_name != "Progressive Sword"
        ]
        self.all_nonprogress_items = [
          item_name for item_name in self.all_nonprogress_items
          if item_name != "Hurricane Spin
  
  [... the rest is omitted ...]
files.new_path: logic/logic.py
files.old_contents: 
  import yaml
  import re
  from collections import OrderedDict
  import copy
  
  import os
  
  from logic.item_types import PROGRESS_ITEMS, NONPROGRESS_ITEMS, CONSUMABLE_ITEMS, DUPLICATABLE_CONSUMABLE_ITEMS, DUNGEON_PROGRESS_ITEMS, DUNGEON_NONPROGRESS_ITEMS
  from wwrando_paths import LOGIC_PATH
  from randomizers import entrances
  
  class Logic:
    DUNGEON_NAMES = OrderedDict([
      ("DRC",  "Dragon Roost Cavern"),
      ("FW",   "Forbidden Woods"),
      ("TotG", "Tower of the Gods"),
      ("FF",   "Forsaken Fortress"),
      ("ET",   "Earth Temple"),
      ("WT",   "Wind Temple"),
    ])
    DUNGEON_NAME_TO_SHORT_DUNGEON_NAME = OrderedDict([v, k] for k, v in DUNGEON_NAMES.items())
    
    PROGRESS_ITEM_GROUPS = OrderedDict([
      ("Triforce Shards",  [
        "Triforce Shard 1",
        "Triforce Shard 2",
        "Triforce Shard 3",
        "Triforce Shard 4",
        "Triforce Shard 5",
        "Triforce Shard 6",
        "Triforce Shard 7",
        "Triforce Shard 8",
      ]),
      ("Goddess Pearls",  [
        "Nayru's Pearl",
        "Din's Pearl",
        "Farore's Pearl",
      ]),
      ("Tingle Statues",  [
        "Dragon Tingle Statue",
        "Forbidden Tingle Statue",
        "Goddess Tingle Statue",
        "Earth Tingle Statue",
        "Wind Tingle Statue",
      ]),
    ])
    
    initial_item_locations = None
    initial_macros = None
    
    def __init__(self, rando):
      self.rando = rando
      self.requirement_met_cache = {}
      
      
      # Initialize location related attributes.
      self.item_locations = Logic.load_and_parse_item_locations()
      self.load_and_parse_macros()
      
      self.locations_by_zone_name = OrderedDict()
      for location_name in self.item_locations:
        zone_name, specific_location_name = self.split_location_name_by_zone(location_name)
        if zone_name not in self.locations_by_zone_name:
          self.locations_by_zone_name[zone_name] = []
        self.locations_by_zone_name[zone_name].append(location_name)
      
      self.remaining_item_locations = list(self.item_locations.keys())
      self.prerandomization_item_locations = OrderedDict()
      
      self.done_item_locations = OrderedDict()
      for location_name in self.item_locations:
        self.done_item_locations[location_name] = None
      
      self.rock_spire_shop_ship_locations = []
      for location_name, location in self.item_locations.items():
        if location_name.startswith("Rock Spire Isle - Beedle's Special Shop Ship - "):
          self.rock_spire_shop_ship_locations.append(location_name)
      
      # Sync the logic macros with the randomizer.
      self.update_entrance_connection_macros()
      self.update_chart_macros()
      
      
      # Initialize item related attributes.
      self.all_progress_items = PROGRESS_ITEMS.copy()
      self.all_nonprogress_items = NONPROGRESS_ITEMS.copy()
      self.all_fixed_consumable_items = CONSUMABLE_ITEMS.copy()
      self.duplicatable_consumable_items = DUPLICATABLE_CONSUMABLE_ITEMS.copy()
      
      self.triforce_chart_names = []
      self.treasure_chart_names = []
      for i in range(1, 8+1):
        self.triforce_chart_names.append("Triforce Chart %d" % i)
      for i in range(1, 41+1):
        self.treasure_chart_names.append("Treasure Chart %d" % i)
      
      if self.rando.options.get("sword_mode") == "Swordless":
        self.all_progress_items = [
          item_name for item_name in self.all_progress_items
          if item_name != "Progressive Sword"
        ]
        self.all_nonprogress_items = [
          item_name for item_name in self.all_nonprogress_items
          if item_name != "Hurricane Spin
  
  [... the rest is omitted ...]
files.old_path: logic/logic.py