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

@@ -991,7 +991,7 @@ def count_locations_exclude_big_chest(state):
return cnt
def count_key_only_locations(state):
def count_small_key_only_locations(state):
cnt = 0
for loc in state.found_locations:
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
# 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_key_only = count_key_only_locations(state)
available_small_locations = cnt_avail_small_locations(ttl_locations, ttl_key_only, state, world, player)
ttl_small_key_only = count_small_key_only_locations(state)
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)
if invalid_self_locking_key(key_layout, state, prev_state, prev_avail, world, player):
return False
@@ -1267,7 +1267,7 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
state_copy = state.copy()
open_a_door(exp_door.door, state_copy, flat_proposal)
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
code = state_id(state_copy, flat_proposal)
if code not in checked_states.keys():
@@ -1343,7 +1343,10 @@ def create_key_counters(key_layout, world, player):
key_counters = {}
flat_proposal = key_layout.flat_prop
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
for region in key_layout.start_regions:
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):
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:
max_counter = find_counter_hint(dict.fromkeys(key_layout.flat_prop), True, key_layout)
return max_counter
@@ -1685,7 +1690,10 @@ def validate_key_placement(key_layout, world, player):
for code, counter in key_layout.key_counters.items():
if len(counter.child_doors) == 0:
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:
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)