diff --git a/DungeonGenerator.py b/DungeonGenerator.py index 445ed9b3..f982cb6f 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -16,6 +16,7 @@ from Dungeons import dungeon_regions, split_region_starts from RoomData import DoorKind from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal +from source.dungeon.DungeonStitcher import GenerationException as OtherGenException class GraphPiece: @@ -1505,6 +1506,8 @@ def calc_allowance_and_dead_ends(builder, connections_tuple, world, player): builder.branches -= 1 if entrance not in drop_entrances_allowance: needed_connections.append(entrance) + if builder.sewers_access: + starting_allowance += 1 builder.allowance = starting_allowance for entrance in needed_connections: sector = find_sector(entrance, builder.sectors) @@ -3051,7 +3054,7 @@ def split_dungeon_builder(builder, split_list, builder_info): comb_w_replace = len(dungeon_map) ** len(candidate_sectors) return balance_split(candidate_sectors, dungeon_map, global_pole, builder_info) except (GenerationException, NeutralizingException): - if comb_w_replace and comb_w_replace <= 10000: + if comb_w_replace and comb_w_replace <= 10000 and not builder.throne_door: attempts += 5 # all the combinations were tried already, no use repeating else: attempts += 1 @@ -3535,7 +3538,7 @@ def check_for_valid_layout(builder, sector_list, builder_info): split_list['Sewers'].remove(temp_builder.throne_door.entrance.parent_region.name) builder.exception_list = list(sector_list) return True, {}, package - except (GenerationException, NeutralizingException): + except (GenerationException, NeutralizingException, OtherGenException): builder.split_dungeon_map = None builder.valid_proposal = None if temp_builder.name == 'Hyrule Castle' and temp_builder.throne_door: @@ -3948,20 +3951,20 @@ def find_free_equation(equations): def copy_door_equations(builder, sector_list): equations = {} for sector in builder.sectors + sector_list: - sector.equations = calc_sector_equations(sector) + sector.equations = calc_sector_equations(sector, builder.sewers_access) curr_list = equations[sector] = [] for equation in sector.equations: curr_list.append(equation.copy()) return equations -def calc_sector_equations(sector): +def calc_sector_equations(sector, sewers_flag=False): equations = [] - is_entrance = sector.is_entrance_sector() and not sector.destination_entrance + is_entrance = (sector.is_entrance_sector() and not sector.destination_entrance) or sewers_flag if is_entrance: flagged_equations = [] for door in sector.outstanding_doors: - equation, flag = calc_door_equation(door, sector, True) + equation, flag = calc_door_equation(door, sector, True, sewers_flag) if flag: flagged_equations.append(equation) equations.append(equation) @@ -3977,9 +3980,9 @@ def calc_sector_equations(sector): return equations -def calc_door_equation(door, sector, look_for_entrance): +def calc_door_equation(door, sector, look_for_entrance, sewers_flag=None): if look_for_entrance and not door.blocked: - flag = sector.is_entrance_sector() + flag = sector.is_entrance_sector() or sewers_flag if flag: eq = DoorEquation(door) eq.benefit[hook_from_door(door)].append(door) diff --git a/Rom.py b/Rom.py index 544f2c5b..18677375 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '0be31dc5cb338e7e85d1ce65e839c99e' +RANDOMIZERBASEHASH = '61c296effe6180274721d570d2471e1c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9740c94d..03d6471e 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ diff --git a/source/dungeon/DungeonStitcher.py b/source/dungeon/DungeonStitcher.py index aa74dee0..b5e7515e 100644 --- a/source/dungeon/DungeonStitcher.py +++ b/source/dungeon/DungeonStitcher.py @@ -56,6 +56,8 @@ def generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon if (access_region.name in world.inaccessible_regions[player] and region.name not in world.enabled_entrances[player]): excluded[region] = None + elif split_dungeon and builder.sewers_access and builder.sewers_access.entrance.parent_region == region: + continue elif len(region.entrances) == 1: # for holes access_region = next(x.parent_region for x in region.entrances if x.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld] @@ -182,11 +184,17 @@ def modify_proposal(proposed_map, explored_state, doors_to_connect, hash_code_se return proposed_map, hash_code attempt, opp_hook = None, None - opp_hook_len = 0 + opp_hook_len, possible_swaps = 0, list(visited_choices) while opp_hook_len == 0: - attempt = random.choice(visited_choices) + if len(possible_swaps) == 0: + break + attempt = random.choice(possible_swaps) + possible_swaps.remove(attempt) opp_hook = type_map[hook_from_door(attempt)] opp_hook_len = len(unvisted_bucket[opp_hook]) + if opp_hook_len == 0: + itr += 1 + continue unvisted_bucket[opp_hook].sort(key=lambda d: d.name) new_door = random.choice(unvisted_bucket[opp_hook]) old_target = proposed_map[attempt] diff --git a/test/customizer/rainprevent_keydoor.yaml b/test/customizer/rainprevent_keydoor.yaml new file mode 100644 index 00000000..31930dce --- /dev/null +++ b/test/customizer/rainprevent_keydoor.yaml @@ -0,0 +1,13 @@ +meta: + players: 1 +settings: + 1: + door_shuffle: crossed + mode: standard + shuffle: crossed +doors: + 1: + doors: + Hyrule Castle East Lobby N: + dest: Sewers Secret Room Key Door S + type: Key Door