mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-25 12:43:19 -07:00
Merge branch 'main' into civ6-1.0
This commit is contained in:
@@ -430,7 +430,7 @@ class MultiWorld():
|
||||
subworld = self.worlds[player]
|
||||
for item in subworld.get_pre_fill_items():
|
||||
subworld.collect(ret, item)
|
||||
ret.sweep_for_events()
|
||||
ret.sweep_for_advancements()
|
||||
|
||||
if use_cache:
|
||||
self._all_state = ret
|
||||
@@ -661,7 +661,7 @@ class CollectionState():
|
||||
multiworld: MultiWorld
|
||||
reachable_regions: Dict[int, Set[Region]]
|
||||
blocked_connections: Dict[int, Set[Entrance]]
|
||||
events: Set[Location]
|
||||
advancements: Set[Location]
|
||||
path: Dict[Union[Region, Entrance], PathValue]
|
||||
locations_checked: Set[Location]
|
||||
stale: Dict[int, bool]
|
||||
@@ -673,7 +673,7 @@ class CollectionState():
|
||||
self.multiworld = parent
|
||||
self.reachable_regions = {player: set() for player in parent.get_all_ids()}
|
||||
self.blocked_connections = {player: set() for player in parent.get_all_ids()}
|
||||
self.events = set()
|
||||
self.advancements = set()
|
||||
self.path = {}
|
||||
self.locations_checked = set()
|
||||
self.stale = {player: True for player in parent.get_all_ids()}
|
||||
@@ -722,7 +722,7 @@ class CollectionState():
|
||||
self.reachable_regions.items()}
|
||||
ret.blocked_connections = {player: entrance_set.copy() for player, entrance_set in
|
||||
self.blocked_connections.items()}
|
||||
ret.events = self.events.copy()
|
||||
ret.advancements = self.advancements.copy()
|
||||
ret.path = self.path.copy()
|
||||
ret.locations_checked = self.locations_checked.copy()
|
||||
for function in self.additional_copy_functions:
|
||||
@@ -755,19 +755,24 @@ class CollectionState():
|
||||
return self.multiworld.get_region(spot, player).can_reach(self)
|
||||
|
||||
def sweep_for_events(self, locations: Optional[Iterable[Location]] = None) -> None:
|
||||
Utils.deprecate("sweep_for_events has been renamed to sweep_for_advancements. The functionality is the same. "
|
||||
"Please switch over to sweep_for_advancements.")
|
||||
return self.sweep_for_advancements(locations)
|
||||
|
||||
def sweep_for_advancements(self, locations: Optional[Iterable[Location]] = None) -> None:
|
||||
if locations is None:
|
||||
locations = self.multiworld.get_filled_locations()
|
||||
reachable_events = True
|
||||
# since the loop has a good chance to run more than once, only filter the events once
|
||||
locations = {location for location in locations if location.advancement and location not in self.events}
|
||||
reachable_advancements = True
|
||||
# since the loop has a good chance to run more than once, only filter the advancements once
|
||||
locations = {location for location in locations if location.advancement and location not in self.advancements}
|
||||
|
||||
while reachable_events:
|
||||
reachable_events = {location for location in locations if location.can_reach(self)}
|
||||
locations -= reachable_events
|
||||
for event in reachable_events:
|
||||
self.events.add(event)
|
||||
assert isinstance(event.item, Item), "tried to collect Event with no Item"
|
||||
self.collect(event.item, True, event)
|
||||
while reachable_advancements:
|
||||
reachable_advancements = {location for location in locations if location.can_reach(self)}
|
||||
locations -= reachable_advancements
|
||||
for advancement in reachable_advancements:
|
||||
self.advancements.add(advancement)
|
||||
assert isinstance(advancement.item, Item), "tried to collect Event with no Item"
|
||||
self.collect(advancement.item, True, advancement)
|
||||
|
||||
# item name related
|
||||
def has(self, item: str, player: int, count: int = 1) -> bool:
|
||||
@@ -871,7 +876,7 @@ class CollectionState():
|
||||
self.stale[item.player] = True
|
||||
|
||||
if changed and not prevent_sweep:
|
||||
self.sweep_for_events()
|
||||
self.sweep_for_advancements()
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
14
Fill.py
14
Fill.py
@@ -29,7 +29,7 @@ def sweep_from_pool(base_state: CollectionState, itempool: typing.Sequence[Item]
|
||||
new_state = base_state.copy()
|
||||
for item in itempool:
|
||||
new_state.collect(item, True)
|
||||
new_state.sweep_for_events(locations=locations)
|
||||
new_state.sweep_for_advancements(locations=locations)
|
||||
return new_state
|
||||
|
||||
|
||||
@@ -329,8 +329,8 @@ def accessibility_corrections(multiworld: MultiWorld, state: CollectionState, lo
|
||||
pool.append(location.item)
|
||||
state.remove(location.item)
|
||||
location.item = None
|
||||
if location in state.events:
|
||||
state.events.remove(location)
|
||||
if location in state.advancements:
|
||||
state.advancements.remove(location)
|
||||
locations.append(location)
|
||||
if pool and locations:
|
||||
locations.sort(key=lambda loc: loc.progress_type != LocationProgressType.PRIORITY)
|
||||
@@ -363,7 +363,7 @@ def distribute_early_items(multiworld: MultiWorld,
|
||||
early_priority_locations: typing.List[Location] = []
|
||||
loc_indexes_to_remove: typing.Set[int] = set()
|
||||
base_state = multiworld.state.copy()
|
||||
base_state.sweep_for_events(locations=(loc for loc in multiworld.get_filled_locations() if loc.address is None))
|
||||
base_state.sweep_for_advancements(locations=(loc for loc in multiworld.get_filled_locations() if loc.address is None))
|
||||
for i, loc in enumerate(fill_locations):
|
||||
if loc.can_reach(base_state):
|
||||
if loc.progress_type == LocationProgressType.PRIORITY:
|
||||
@@ -558,7 +558,7 @@ def flood_items(multiworld: MultiWorld) -> None:
|
||||
progress_done = False
|
||||
|
||||
# sweep once to pick up preplaced items
|
||||
multiworld.state.sweep_for_events()
|
||||
multiworld.state.sweep_for_advancements()
|
||||
|
||||
# fill multiworld from top of itempool while we can
|
||||
while not progress_done:
|
||||
@@ -746,7 +746,7 @@ def balance_multiworld_progression(multiworld: MultiWorld) -> None:
|
||||
), items_to_test):
|
||||
reducing_state.collect(location.item, True, location)
|
||||
|
||||
reducing_state.sweep_for_events(locations=locations_to_test)
|
||||
reducing_state.sweep_for_advancements(locations=locations_to_test)
|
||||
|
||||
if multiworld.has_beaten_game(balancing_state):
|
||||
if not multiworld.has_beaten_game(reducing_state):
|
||||
@@ -829,7 +829,7 @@ def distribute_planned(multiworld: MultiWorld) -> None:
|
||||
warn(warning, force)
|
||||
|
||||
swept_state = multiworld.state.copy()
|
||||
swept_state.sweep_for_events()
|
||||
swept_state.sweep_for_advancements()
|
||||
reachable = frozenset(multiworld.get_reachable_locations(swept_state))
|
||||
early_locations: typing.Dict[int, typing.List[str]] = collections.defaultdict(list)
|
||||
non_early_locations: typing.Dict[int, typing.List[str]] = collections.defaultdict(list)
|
||||
|
||||
@@ -14,7 +14,7 @@ import tkinter as tk
|
||||
from argparse import Namespace
|
||||
from concurrent.futures import as_completed, ThreadPoolExecutor
|
||||
from glob import glob
|
||||
from tkinter import Tk, Frame, Label, StringVar, Entry, filedialog, messagebox, Button, Radiobutton, LEFT, X, TOP, LabelFrame, \
|
||||
from tkinter import Tk, Frame, Label, StringVar, Entry, filedialog, messagebox, Button, Radiobutton, LEFT, X, BOTH, TOP, LabelFrame, \
|
||||
IntVar, Checkbutton, E, W, OptionMenu, Toplevel, BOTTOM, RIGHT, font as font, PhotoImage
|
||||
from tkinter.constants import DISABLED, NORMAL
|
||||
from urllib.parse import urlparse
|
||||
@@ -29,7 +29,8 @@ from Utils import output_path, local_path, user_path, open_file, get_cert_none_s
|
||||
|
||||
|
||||
GAME_ALTTP = "A Link to the Past"
|
||||
|
||||
WINDOW_MIN_HEIGHT = 525
|
||||
WINDOW_MIN_WIDTH = 425
|
||||
|
||||
class AdjusterWorld(object):
|
||||
def __init__(self, sprite_pool):
|
||||
@@ -242,16 +243,17 @@ def adjustGUI():
|
||||
from argparse import Namespace
|
||||
from Utils import __version__ as MWVersion
|
||||
adjustWindow = Tk()
|
||||
adjustWindow.minsize(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT)
|
||||
adjustWindow.wm_title("Archipelago %s LttP Adjuster" % MWVersion)
|
||||
set_icon(adjustWindow)
|
||||
|
||||
rom_options_frame, rom_vars, set_sprite = get_rom_options_frame(adjustWindow)
|
||||
|
||||
bottomFrame2 = Frame(adjustWindow)
|
||||
bottomFrame2 = Frame(adjustWindow, padx=8, pady=2)
|
||||
|
||||
romFrame, romVar = get_rom_frame(adjustWindow)
|
||||
|
||||
romDialogFrame = Frame(adjustWindow)
|
||||
romDialogFrame = Frame(adjustWindow, padx=8, pady=2)
|
||||
baseRomLabel2 = Label(romDialogFrame, text='Rom to adjust')
|
||||
romVar2 = StringVar()
|
||||
romEntry2 = Entry(romDialogFrame, textvariable=romVar2)
|
||||
@@ -261,9 +263,9 @@ def adjustGUI():
|
||||
romVar2.set(rom)
|
||||
|
||||
romSelectButton2 = Button(romDialogFrame, text='Select Rom', command=RomSelect2)
|
||||
romDialogFrame.pack(side=TOP, expand=True, fill=X)
|
||||
baseRomLabel2.pack(side=LEFT)
|
||||
romEntry2.pack(side=LEFT, expand=True, fill=X)
|
||||
romDialogFrame.pack(side=TOP, expand=False, fill=X)
|
||||
baseRomLabel2.pack(side=LEFT, expand=False, fill=X, padx=(0, 8))
|
||||
romEntry2.pack(side=LEFT, expand=True, fill=BOTH, pady=1)
|
||||
romSelectButton2.pack(side=LEFT)
|
||||
|
||||
def adjustRom():
|
||||
@@ -331,12 +333,11 @@ def adjustGUI():
|
||||
messagebox.showinfo(title="Success", message="Settings saved to persistent storage")
|
||||
|
||||
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
||||
rom_options_frame.pack(side=TOP)
|
||||
rom_options_frame.pack(side=TOP, padx=8, pady=8, fill=BOTH, expand=True)
|
||||
adjustButton.pack(side=LEFT, padx=(5,5))
|
||||
|
||||
saveButton = Button(bottomFrame2, text='Save Settings', command=saveGUISettings)
|
||||
saveButton.pack(side=LEFT, padx=(5,5))
|
||||
|
||||
bottomFrame2.pack(side=TOP, pady=(5,5))
|
||||
|
||||
tkinter_center_window(adjustWindow)
|
||||
@@ -576,7 +577,7 @@ class AttachTooltip(object):
|
||||
def get_rom_frame(parent=None):
|
||||
adjuster_settings = get_adjuster_settings(GAME_ALTTP)
|
||||
|
||||
romFrame = Frame(parent)
|
||||
romFrame = Frame(parent, padx=8, pady=8)
|
||||
baseRomLabel = Label(romFrame, text='LttP Base Rom: ')
|
||||
romVar = StringVar(value=adjuster_settings.baserom)
|
||||
romEntry = Entry(romFrame, textvariable=romVar)
|
||||
@@ -596,20 +597,19 @@ def get_rom_frame(parent=None):
|
||||
romSelectButton = Button(romFrame, text='Select Rom', command=RomSelect)
|
||||
|
||||
baseRomLabel.pack(side=LEFT)
|
||||
romEntry.pack(side=LEFT, expand=True, fill=X)
|
||||
romEntry.pack(side=LEFT, expand=True, fill=BOTH, pady=1)
|
||||
romSelectButton.pack(side=LEFT)
|
||||
romFrame.pack(side=TOP, expand=True, fill=X)
|
||||
romFrame.pack(side=TOP, fill=X)
|
||||
|
||||
return romFrame, romVar
|
||||
|
||||
def get_rom_options_frame(parent=None):
|
||||
adjuster_settings = get_adjuster_settings(GAME_ALTTP)
|
||||
|
||||
romOptionsFrame = LabelFrame(parent, text="Rom options")
|
||||
romOptionsFrame.columnconfigure(0, weight=1)
|
||||
romOptionsFrame.columnconfigure(1, weight=1)
|
||||
romOptionsFrame = LabelFrame(parent, text="Rom options", padx=8, pady=8)
|
||||
|
||||
for i in range(5):
|
||||
romOptionsFrame.rowconfigure(i, weight=1)
|
||||
romOptionsFrame.rowconfigure(i, weight=0, pad=4)
|
||||
vars = Namespace()
|
||||
|
||||
vars.MusicVar = IntVar()
|
||||
@@ -660,7 +660,7 @@ def get_rom_options_frame(parent=None):
|
||||
spriteSelectButton = Button(spriteDialogFrame, text='...', command=SpriteSelect)
|
||||
|
||||
baseSpriteLabel.pack(side=LEFT)
|
||||
spriteEntry.pack(side=LEFT)
|
||||
spriteEntry.pack(side=LEFT, expand=True, fill=X)
|
||||
spriteSelectButton.pack(side=LEFT)
|
||||
|
||||
oofDialogFrame = Frame(romOptionsFrame)
|
||||
|
||||
@@ -24,7 +24,7 @@ class TestBase(unittest.TestCase):
|
||||
for item in items:
|
||||
item.classification = ItemClassification.progression
|
||||
state.collect(item, prevent_sweep=True)
|
||||
state.sweep_for_events()
|
||||
state.sweep_for_advancements()
|
||||
state.update_reachable_regions(1)
|
||||
self._state_cache[self.multiworld, tuple(items)] = state
|
||||
return state
|
||||
@@ -221,8 +221,8 @@ class WorldTestBase(unittest.TestCase):
|
||||
if isinstance(items, Item):
|
||||
items = (items,)
|
||||
for item in items:
|
||||
if item.location and item.advancement and item.location in self.multiworld.state.events:
|
||||
self.multiworld.state.events.remove(item.location)
|
||||
if item.location and item.advancement and item.location in self.multiworld.state.advancements:
|
||||
self.multiworld.state.advancements.remove(item.location)
|
||||
self.multiworld.state.remove(item)
|
||||
|
||||
def can_reach_location(self, location: str) -> bool:
|
||||
|
||||
@@ -192,7 +192,7 @@ class TestFillRestrictive(unittest.TestCase):
|
||||
location_pool = player1.locations[1:] + player2.locations
|
||||
item_pool = player1.prog_items[:-1] + player2.prog_items
|
||||
fill_restrictive(multiworld, multiworld.state, location_pool, item_pool)
|
||||
multiworld.state.sweep_for_events() # collect everything
|
||||
multiworld.state.sweep_for_advancements() # collect everything
|
||||
|
||||
# all of player2's locations and items should be accessible (not all of player1's)
|
||||
for item in player2.prog_items:
|
||||
@@ -443,8 +443,8 @@ class TestFillRestrictive(unittest.TestCase):
|
||||
item = player1.prog_items[0]
|
||||
item.code = None
|
||||
location.place_locked_item(item)
|
||||
multiworld.state.sweep_for_events()
|
||||
multiworld.state.sweep_for_events()
|
||||
multiworld.state.sweep_for_advancements()
|
||||
multiworld.state.sweep_for_advancements()
|
||||
self.assertTrue(multiworld.state.prog_items[item.player][item.name], "Sweep did not collect - Test flawed")
|
||||
self.assertEqual(multiworld.state.prog_items[item.player][item.name], 1, "Sweep collected multiple times")
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ def fill_dungeons_restrictive(multiworld: MultiWorld):
|
||||
pass
|
||||
for item in pre_fill_items:
|
||||
multiworld.worlds[item.player].collect(all_state_base, item)
|
||||
all_state_base.sweep_for_events()
|
||||
all_state_base.sweep_for_advancements()
|
||||
|
||||
# Remove completion condition so that minimal-accessibility worlds place keys properly
|
||||
for player in {item.player for item in in_dungeon_items}:
|
||||
@@ -262,8 +262,8 @@ def fill_dungeons_restrictive(multiworld: MultiWorld):
|
||||
all_state_base.remove(item_factory(key_data[3], multiworld.worlds[player]))
|
||||
loc = multiworld.get_location(key_loc, player)
|
||||
|
||||
if loc in all_state_base.events:
|
||||
all_state_base.events.remove(loc)
|
||||
if loc in all_state_base.advancements:
|
||||
all_state_base.advancements.remove(loc)
|
||||
fill_restrictive(multiworld, all_state_base, locations, in_dungeon_items, lock=True, allow_excluded=True,
|
||||
name="LttP Dungeon Items")
|
||||
|
||||
|
||||
@@ -682,7 +682,7 @@ def get_pool_core(world, player: int):
|
||||
if 'triforce_hunt' in goal:
|
||||
|
||||
if world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_extra:
|
||||
treasure_hunt_total = (world.triforce_pieces_available[player].value
|
||||
treasure_hunt_total = (world.triforce_pieces_required[player].value
|
||||
+ world.triforce_pieces_extra[player].value)
|
||||
elif world.triforce_pieces_mode[player].value == TriforcePiecesMode.option_percentage:
|
||||
percentage = float(world.triforce_pieces_percentage[player].value) / 100
|
||||
|
||||
@@ -54,7 +54,7 @@ class TestDungeon(LTTPTestBase):
|
||||
|
||||
for item in items:
|
||||
item.classification = ItemClassification.progression
|
||||
state.collect(item, prevent_sweep=True) # prevent_sweep=True prevents running sweep_for_events() and picking up
|
||||
state.sweep_for_events() # key drop keys repeatedly
|
||||
state.collect(item, prevent_sweep=True) # prevent_sweep=True prevents running sweep_for_advancements() and picking up
|
||||
state.sweep_for_advancements() # key drop keys repeatedly
|
||||
|
||||
self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), access, f"failed {self.multiworld.get_location(location, 1)} with: {item_pool}")
|
||||
|
||||
@@ -85,7 +85,7 @@ class LingoWorld(World):
|
||||
state.collect(self.create_item(self.player_logic.forced_good_item), True)
|
||||
|
||||
all_locations = self.multiworld.get_locations(self.player)
|
||||
state.sweep_for_events(locations=all_locations)
|
||||
state.sweep_for_advancements(locations=all_locations)
|
||||
|
||||
unreachable_locations = [location for location in all_locations
|
||||
if not state.can_reach_location(location.name, self.player)]
|
||||
|
||||
@@ -445,7 +445,7 @@ def shuffle_random_entrances(ootworld):
|
||||
|
||||
# Gather locations to keep reachable for validation
|
||||
all_state = ootworld.get_state_with_complete_itempool()
|
||||
all_state.sweep_for_events(locations=ootworld.get_locations())
|
||||
all_state.sweep_for_advancements(locations=ootworld.get_locations())
|
||||
locations_to_ensure_reachable = {loc for loc in world.get_reachable_locations(all_state, player) if not (loc.type == 'Drop' or (loc.type == 'Event' and 'Subrule' in loc.name))}
|
||||
|
||||
# Set entrance data for all entrances
|
||||
@@ -791,8 +791,8 @@ def validate_world(ootworld, entrance_placed, locations_to_ensure_reachable, all
|
||||
all_state = all_state_orig.copy()
|
||||
none_state = none_state_orig.copy()
|
||||
|
||||
all_state.sweep_for_events(locations=ootworld.get_locations())
|
||||
none_state.sweep_for_events(locations=ootworld.get_locations())
|
||||
all_state.sweep_for_advancements(locations=ootworld.get_locations())
|
||||
none_state.sweep_for_advancements(locations=ootworld.get_locations())
|
||||
|
||||
if ootworld.shuffle_interior_entrances or ootworld.shuffle_overworld_entrances or ootworld.spawn_positions:
|
||||
time_travel_state = none_state.copy()
|
||||
|
||||
@@ -228,7 +228,7 @@ def set_shop_rules(ootworld):
|
||||
def set_entrances_based_rules(ootworld):
|
||||
|
||||
all_state = ootworld.get_state_with_complete_itempool()
|
||||
all_state.sweep_for_events(locations=ootworld.get_locations())
|
||||
all_state.sweep_for_advancements(locations=ootworld.get_locations())
|
||||
|
||||
for location in filter(lambda location: location.type == 'Shop', ootworld.get_locations()):
|
||||
# If a shop is not reachable as adult, it can't have Goron Tunic or Zora Tunic as child can't buy these
|
||||
|
||||
@@ -847,7 +847,7 @@ class OOTWorld(World):
|
||||
# Make sure to only kill actual internal events, not in-game "events"
|
||||
all_state = self.get_state_with_complete_itempool()
|
||||
all_locations = self.get_locations()
|
||||
all_state.sweep_for_events(locations=all_locations)
|
||||
all_state.sweep_for_advancements(locations=all_locations)
|
||||
reachable = self.multiworld.get_reachable_locations(all_state, self.player)
|
||||
unreachable = [loc for loc in all_locations if
|
||||
(loc.internal or loc.type == 'Drop') and loc.address is None and loc.locked and loc not in reachable]
|
||||
@@ -875,7 +875,7 @@ class OOTWorld(World):
|
||||
state = base_state.copy()
|
||||
for item in self.get_pre_fill_items():
|
||||
self.collect(state, item)
|
||||
state.sweep_for_events(locations=self.get_locations())
|
||||
state.sweep_for_advancements(locations=self.get_locations())
|
||||
return state
|
||||
|
||||
# Prefill shops, songs, and dungeon items
|
||||
@@ -887,7 +887,7 @@ class OOTWorld(World):
|
||||
state = CollectionState(self.multiworld)
|
||||
for item in self.itempool:
|
||||
self.collect(state, item)
|
||||
state.sweep_for_events(locations=self.get_locations())
|
||||
state.sweep_for_advancements(locations=self.get_locations())
|
||||
|
||||
# Place dungeon items
|
||||
special_fill_types = ['GanonBossKey', 'BossKey', 'SmallKey', 'HideoutSmallKey', 'Map', 'Compass']
|
||||
|
||||
@@ -56,8 +56,8 @@ class OSRSWorld(World):
|
||||
|
||||
locations_by_category: typing.Dict[str, typing.List[LocationRow]]
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
super().__init__(world, player)
|
||||
def __init__(self, multiworld: MultiWorld, player: int):
|
||||
super().__init__(multiworld, player)
|
||||
self.region_name_to_data = {}
|
||||
self.location_name_to_data = {}
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ class PokemonRedBlueWorld(World):
|
||||
if attempt > 1:
|
||||
for mon in poke_data.pokemon_data.keys():
|
||||
state.collect(self.create_item(mon), True)
|
||||
state.sweep_for_events()
|
||||
state.sweep_for_advancements()
|
||||
self.multiworld.random.shuffle(badges)
|
||||
self.multiworld.random.shuffle(badgelocs)
|
||||
badgelocs_copy = badgelocs.copy()
|
||||
|
||||
@@ -2439,7 +2439,7 @@ def door_shuffle(world, multiworld, player, badges, badge_locs):
|
||||
|
||||
state_copy = state.copy()
|
||||
state_copy.collect(item, True)
|
||||
state.sweep_for_events(locations=event_locations)
|
||||
state.sweep_for_advancements(locations=event_locations)
|
||||
new_reachable_entrances = len([entrance for entrance in entrances if entrance in reachable_entrances or
|
||||
entrance.parent_region.can_reach(state_copy)])
|
||||
return new_reachable_entrances > len(reachable_entrances)
|
||||
@@ -2480,7 +2480,7 @@ def door_shuffle(world, multiworld, player, badges, badge_locs):
|
||||
|
||||
while entrances:
|
||||
state.update_reachable_regions(player)
|
||||
state.sweep_for_events(locations=event_locations)
|
||||
state.sweep_for_advancements(locations=event_locations)
|
||||
|
||||
multiworld.random.shuffle(entrances)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class WitnessWorld(World):
|
||||
"laser_ids_to_hints": self.laser_ids_to_hints,
|
||||
"progressive_item_lists": self.player_items.get_progressive_item_ids_in_pool(),
|
||||
"obelisk_side_id_to_EPs": static_witness_logic.OBELISK_SIDE_ID_TO_EP_HEXES,
|
||||
"precompleted_puzzles": [int(h, 16) for h in self.player_logic.EXCLUDED_LOCATIONS],
|
||||
"precompleted_puzzles": [int(h, 16) for h in self.player_logic.EXCLUDED_ENTITIES],
|
||||
"entity_to_name": static_witness_logic.ENTITY_ID_TO_NAME,
|
||||
"panel_hunt_required_absolute": self.panel_hunt_required_count
|
||||
}
|
||||
@@ -219,7 +219,7 @@ class WitnessWorld(World):
|
||||
# Only sweeps for events because having this behavior be random based on Tutorial Gate would be strange.
|
||||
|
||||
state = CollectionState(self.multiworld)
|
||||
state.sweep_for_events(locations=event_locations)
|
||||
state.sweep_for_advancements(locations=event_locations)
|
||||
|
||||
num_early_locs = sum(1 for loc in self.multiworld.get_reachable_locations(state, self.player) if loc.address)
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ class EntityHuntPicker:
|
||||
|
||||
return (
|
||||
self.player_logic.solvability_guaranteed(panel_hex)
|
||||
and panel_hex not in self.player_logic.EXCLUDED_ENTITIES
|
||||
and not (
|
||||
# Due to an edge case, Discards have to be on in disable_non_randomized even if Discard Shuffle is off.
|
||||
# However, I don't think they should be hunt panels in this case.
|
||||
|
||||
@@ -44,7 +44,7 @@ class WitnessPlayerLocations:
|
||||
|
||||
self.CHECK_LOCATIONS = self.CHECK_LOCATIONS - {
|
||||
static_witness_logic.ENTITIES_BY_HEX[entity_hex]["checkName"]
|
||||
for entity_hex in player_logic.COMPLETELY_DISABLED_ENTITIES | player_logic.PRECOMPLETED_LOCATIONS
|
||||
for entity_hex in player_logic.COMPLETELY_DISABLED_ENTITIES
|
||||
}
|
||||
|
||||
self.CHECK_PANELHEX_TO_ID = {
|
||||
|
||||
@@ -108,8 +108,7 @@ class WitnessPlayerLogic:
|
||||
self.EVENT_ITEM_PAIRS: Dict[str, Tuple[str, str]] = {}
|
||||
self.COMPLETELY_DISABLED_ENTITIES: Set[str] = set()
|
||||
self.DISABLE_EVERYTHING_BEHIND: Set[str] = set()
|
||||
self.PRECOMPLETED_LOCATIONS: Set[str] = set()
|
||||
self.EXCLUDED_LOCATIONS: Set[str] = set()
|
||||
self.EXCLUDED_ENTITIES: Set[str] = set()
|
||||
self.ADDED_CHECKS: Set[str] = set()
|
||||
self.VICTORY_LOCATION = "0x0356B"
|
||||
|
||||
@@ -659,7 +658,7 @@ class WitnessPlayerLogic:
|
||||
self.COMPLETELY_DISABLED_ENTITIES.add(loc_obj["entity_hex"])
|
||||
|
||||
elif loc_obj["entityType"] == "Panel":
|
||||
self.EXCLUDED_LOCATIONS.add(loc_obj["entity_hex"])
|
||||
self.EXCLUDED_ENTITIES.add(loc_obj["entity_hex"])
|
||||
|
||||
for adjustment_lineset in adjustment_linesets_in_order:
|
||||
current_adjustment_type = None
|
||||
|
||||
@@ -23,7 +23,7 @@ class TestMaxPanelHuntMinChecks(WitnessTestBase):
|
||||
|
||||
for _ in range(100):
|
||||
state_100.collect(panel_hunt_item, True)
|
||||
state_100.sweep_for_events([self.world.get_location("Tutorial Gate Open Solved")])
|
||||
state_100.sweep_for_advancements([self.world.get_location("Tutorial Gate Open Solved")])
|
||||
|
||||
self.assertTrue(self.multiworld.completion_condition[self.player](state_100))
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestMaxPanelHuntMinChecks(WitnessTestBase):
|
||||
|
||||
for _ in range(99):
|
||||
state_99.collect(panel_hunt_item, True)
|
||||
state_99.sweep_for_events([self.world.get_location("Tutorial Gate Open Solved")])
|
||||
state_99.sweep_for_advancements([self.world.get_location("Tutorial Gate Open Solved")])
|
||||
|
||||
self.assertFalse(self.multiworld.completion_condition[self.player](state_99))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user