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:
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user