Crossed Dungeon generation work

-Added a bunch of crystal switch logic
-Added a check for maiden backtracking
-OrderedFrozenSet to prevent randomization leaks with the same seed
-A few key improvements from an outstanding PR
This commit is contained in:
aerinon
2020-08-13 16:23:40 -06:00
parent df52ca2730
commit 2eb6c1ebc0
5 changed files with 464 additions and 351 deletions

View File

@@ -1120,6 +1120,7 @@ pol_comp = {
'Mod': lambda x: 0 if x == 0 else 1 'Mod': lambda x: 0 if x == 0 else 1
} }
@unique @unique
class PolSlot(Enum): class PolSlot(Enum):
NorthSouth = 0 NorthSouth = 0

View File

@@ -764,7 +764,7 @@ def find_small_key_door_candidates(builder, start_regions, world, player):
checked_doors = set() checked_doors = set()
for region in start_regions: for region in start_regions:
possible, checked = find_key_door_candidates(region, checked_doors, world, player) possible, checked = find_key_door_candidates(region, checked_doors, world, player)
candidates.extend(possible) candidates.extend([x for x in possible if x not in candidates])
checked_doors.update(checked) checked_doors.update(checked)
flat_candidates = [] flat_candidates = []
for candidate in candidates: for candidate in candidates:

File diff suppressed because it is too large Load Diff

View File

@@ -991,7 +991,7 @@ def count_locations_exclude_big_chest(state):
return cnt return cnt
def count_key_only_locations(state): def count_small_key_only_locations(state):
cnt = 0 cnt = 0
for loc in state.found_locations: for loc in state.found_locations:
if loc.forced_item and loc.item.smallkey: if loc.forced_item and loc.item.smallkey:
@@ -1252,8 +1252,8 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
return True # I think that's the end return True # I think that's the end
# todo: fix state to separate out these types # todo: fix state to separate out these types
ttl_locations = count_free_locations(state) if state.big_key_opened else count_locations_exclude_big_chest(state) ttl_locations = count_free_locations(state) if state.big_key_opened else count_locations_exclude_big_chest(state)
ttl_key_only = count_key_only_locations(state) ttl_small_key_only = count_small_key_only_locations(state)
available_small_locations = cnt_avail_small_locations(ttl_locations, ttl_key_only, state, world, player) available_small_locations = cnt_avail_small_locations(ttl_locations, ttl_small_key_only, state, world, player)
available_big_locations = cnt_avail_big_locations(ttl_locations, state, world, player) available_big_locations = cnt_avail_big_locations(ttl_locations, state, world, player)
if invalid_self_locking_key(key_layout, state, prev_state, prev_avail, world, player): if invalid_self_locking_key(key_layout, state, prev_state, prev_avail, world, player):
return False return False
@@ -1267,7 +1267,7 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
state_copy = state.copy() state_copy = state.copy()
open_a_door(exp_door.door, state_copy, flat_proposal) open_a_door(exp_door.door, state_copy, flat_proposal)
state_copy.used_smalls += 1 state_copy.used_smalls += 1
if state_copy.used_smalls > ttl_key_only: if state_copy.used_smalls > ttl_small_key_only:
state_copy.used_locations += 1 state_copy.used_locations += 1
code = state_id(state_copy, flat_proposal) code = state_id(state_copy, flat_proposal)
if code not in checked_states.keys(): if code not in checked_states.keys():
@@ -1343,7 +1343,10 @@ def create_key_counters(key_layout, world, player):
key_counters = {} key_counters = {}
flat_proposal = key_layout.flat_prop flat_proposal = key_layout.flat_prop
state = ExplorationState(dungeon=key_layout.sector.name) state = ExplorationState(dungeon=key_layout.sector.name)
state.key_locations = len(world.get_dungeon(key_layout.sector.name, player).small_keys) if world.doorShuffle[player] == 'vanilla':
state.key_locations = len(world.get_dungeon(key_layout.sector.name, player).small_keys)
else:
state.key_locations = world.dungeon_layouts[player][key_layout.sector.name].key_doors_num
state.big_key_special = world.get_region('Hyrule Dungeon Cellblock', player) in key_layout.sector.regions state.big_key_special = world.get_region('Hyrule Dungeon Cellblock', player) in key_layout.sector.regions
for region in key_layout.start_regions: for region in key_layout.start_regions:
state.visit_region(region, key_checks=True) state.visit_region(region, key_checks=True)
@@ -1471,6 +1474,8 @@ def find_counter_hint(opened_doors, bk_hint, key_layout):
def find_max_counter(key_layout): def find_max_counter(key_layout):
max_counter = find_counter_hint(dict.fromkeys(key_layout.flat_prop), False, key_layout) max_counter = find_counter_hint(dict.fromkeys(key_layout.flat_prop), False, key_layout)
if max_counter is None:
raise Exception("Max Counter is none - something is amiss")
if len(max_counter.child_doors) > 0: if len(max_counter.child_doors) > 0:
max_counter = find_counter_hint(dict.fromkeys(key_layout.flat_prop), True, key_layout) max_counter = find_counter_hint(dict.fromkeys(key_layout.flat_prop), True, key_layout)
return max_counter return max_counter
@@ -1685,7 +1690,10 @@ def validate_key_placement(key_layout, world, player):
for code, counter in key_layout.key_counters.items(): for code, counter in key_layout.key_counters.items():
if len(counter.child_doors) == 0: if len(counter.child_doors) == 0:
continue continue
big_found = any(i.item == dungeon.big_key for i in counter.free_locations if "- Big Chest" not in i.name) or big_key_outside if key_layout.big_key_special:
big_found = any(i.forced_item is not None and i.item.bigkey for i in counter.other_locations) or big_key_outside
else:
big_found = any(i.item is not None and i.item == dungeon.big_key for i in counter.free_locations if "- Big Chest" not in i.name) or big_key_outside
if counter.big_key_opened and not big_found: if counter.big_key_opened and not big_found:
continue # Can't get to this state continue # Can't get to this state
found_locations = set(i for i in counter.free_locations if big_found or "- Big Chest" not in i.name) found_locations = set(i for i in counter.free_locations if big_found or "- Big Chest" not in i.name)

View File

@@ -10,7 +10,7 @@
"shuffling.dungeons": "Shuffling dungeons", "shuffling.dungeons": "Shuffling dungeons",
"basic.traversal": "--Basic Traversal", "basic.traversal": "--Basic Traversal",
"generating.dungeon": "Generating dungeons", "generating.dungeon": "Generating dungeons",
"shuffling.keydoors": "Shuffling Key doors for", "shuffling.keydoors": "Shuffling Key doors",
"lowering.keys.candidates": "Lowering key door count because not enough candidates", "lowering.keys.candidates": "Lowering key door count because not enough candidates",
"lowering.keys.layouts": "Lowering key door count because no valid layouts", "lowering.keys.layouts": "Lowering key door count because no valid layouts",
"keydoor.shuffle.time": "Key door shuffle time", "keydoor.shuffle.time": "Key door shuffle time",