More prize door refinement
Incorporating drop entrances better in the find proposal algorithm
This commit is contained in:
@@ -14,7 +14,7 @@ from RoomData import DoorKind, PairedDoor, reset_rooms
|
|||||||
from DungeonGenerator import ExplorationState, convert_regions, generate_dungeon, pre_validate, determine_required_paths, drop_entrances
|
from DungeonGenerator import ExplorationState, convert_regions, generate_dungeon, pre_validate, determine_required_paths, drop_entrances
|
||||||
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
|
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
|
||||||
from DungeonGenerator import dungeon_portals, dungeon_drops, GenerationException
|
from DungeonGenerator import dungeon_portals, dungeon_drops, GenerationException
|
||||||
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout
|
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
|
||||||
from Utils import ncr, kth_combination
|
from Utils import ncr, kth_combination
|
||||||
|
|
||||||
|
|
||||||
@@ -1463,6 +1463,7 @@ def find_valid_combination(builder, start_regions, world, player, drop_keys=True
|
|||||||
start_regions = [x for x in start_regions if x not in excluded.keys()]
|
start_regions = [x for x in start_regions if x not in excluded.keys()]
|
||||||
|
|
||||||
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
|
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
|
||||||
|
determine_prize_lock(key_layout, world, player)
|
||||||
while not validate_key_layout(key_layout, world, player):
|
while not validate_key_layout(key_layout, world, player):
|
||||||
itr += 1
|
itr += 1
|
||||||
stop_early = False
|
stop_early = False
|
||||||
|
|||||||
@@ -56,11 +56,6 @@ def pre_validate(builder, entrance_region_names, split_dungeon, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def generate_dungeon(builder, entrance_region_names, split_dungeon, world, player):
|
def generate_dungeon(builder, entrance_region_names, split_dungeon, world, player):
|
||||||
sector = generate_dungeon_main(builder, entrance_region_names, split_dungeon, world, player)
|
|
||||||
return sector
|
|
||||||
|
|
||||||
|
|
||||||
def generate_dungeon_main(builder, entrance_region_names, split_dungeon, world, player):
|
|
||||||
if builder.valid_proposal: # we made this earlier in gen, just use it
|
if builder.valid_proposal: # we made this earlier in gen, just use it
|
||||||
proposed_map = builder.valid_proposal
|
proposed_map = builder.valid_proposal
|
||||||
else:
|
else:
|
||||||
@@ -99,6 +94,15 @@ def generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon
|
|||||||
if (access_region.name in world.inaccessible_regions[player] and
|
if (access_region.name in world.inaccessible_regions[player] and
|
||||||
region.name not in world.enabled_entrances[player]):
|
region.name not in world.enabled_entrances[player]):
|
||||||
excluded[region] = None
|
excluded[region] = None
|
||||||
|
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]
|
||||||
|
or x.parent_region.name == 'Sewer Drop')
|
||||||
|
if access_region.name == 'Sewer Drop':
|
||||||
|
access_region = next(x.parent_region for x in access_region.entrances)
|
||||||
|
if (access_region.name in world.inaccessible_regions[player] and
|
||||||
|
region.name not in world.enabled_entrances[player]):
|
||||||
|
excluded[region] = None
|
||||||
entrance_regions = [x for x in entrance_regions if x not in excluded.keys()]
|
entrance_regions = [x for x in entrance_regions if x not in excluded.keys()]
|
||||||
doors_to_connect = {}
|
doors_to_connect = {}
|
||||||
all_regions = set()
|
all_regions = set()
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class KeyLayout(object):
|
|||||||
|
|
||||||
self.found_doors = set()
|
self.found_doors = set()
|
||||||
self.prize_relevant = None
|
self.prize_relevant = None
|
||||||
|
self.prize_can_lock = None # if true, then you may need to beat the bo
|
||||||
# bk special?
|
# bk special?
|
||||||
# bk required? True if big chests or big doors exists
|
# bk required? True if big chests or big doors exists
|
||||||
|
|
||||||
@@ -1447,7 +1448,10 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
found_forced_bk = state.found_forced_bk()
|
found_forced_bk = state.found_forced_bk()
|
||||||
smalls_done = not smalls_avail or not enough_small_locations(state, available_small_locations)
|
smalls_done = not smalls_avail or not enough_small_locations(state, available_small_locations)
|
||||||
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
||||||
prize_done = not key_layout.prize_relevant or state.prize_doors_opened
|
# prize door should not be opened if the boss is reachable - but not reached yet
|
||||||
|
allow_for_prize_lock = (key_layout.prize_can_lock and
|
||||||
|
not any(x for x in state.found_locations if '- Prize' in x.name))
|
||||||
|
prize_done = not key_layout.prize_relevant or state.prize_doors_opened or allow_for_prize_lock
|
||||||
if smalls_done and bk_done and prize_done:
|
if smalls_done and bk_done and prize_done:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@@ -1531,6 +1535,39 @@ def enough_small_locations(state, avail_small_loc):
|
|||||||
return avail_small_loc >= len(unique_d_set)
|
return avail_small_loc >= len(unique_d_set)
|
||||||
|
|
||||||
|
|
||||||
|
def determine_prize_lock(key_layout, world, player):
|
||||||
|
if ((world.retro[player] and (world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle'))
|
||||||
|
or world.logic[player] == 'nologic'):
|
||||||
|
return # done, doesn't matter what
|
||||||
|
flat_proposal = key_layout.flat_prop
|
||||||
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
|
state.key_locations = key_layout.max_chests
|
||||||
|
state.big_key_special = check_bk_special(key_layout.sector.regions, world, player)
|
||||||
|
prize_lock_possible = False
|
||||||
|
for region in key_layout.start_regions:
|
||||||
|
dungeon_entrance, portal_door = find_outside_connection(region)
|
||||||
|
prize_relevant_flag = prize_relevance(key_layout, dungeon_entrance)
|
||||||
|
if prize_relevant_flag:
|
||||||
|
state.append_door_to_list(portal_door, state.prize_doors)
|
||||||
|
state.prize_door_set[portal_door] = dungeon_entrance
|
||||||
|
key_layout.prize_relevant = prize_relevant_flag
|
||||||
|
prize_lock_possible = True
|
||||||
|
else:
|
||||||
|
state.visit_region(region, key_checks=True)
|
||||||
|
state.add_all_doors_check_keys(region, flat_proposal, world, player)
|
||||||
|
if not prize_lock_possible:
|
||||||
|
return # done, no prize entrances to worry about
|
||||||
|
expand_key_state(state, flat_proposal, world, player)
|
||||||
|
while len(state.small_doors) > 0 or len(state.big_doors) > 0:
|
||||||
|
if len(state.big_doors) > 0:
|
||||||
|
open_a_door(state.big_doors[0].door, state, flat_proposal, world, player)
|
||||||
|
elif len(state.small_doors) > 0:
|
||||||
|
open_a_door(state.small_doors[0].door, state, flat_proposal, world, player)
|
||||||
|
expand_key_state(state, flat_proposal, world, player)
|
||||||
|
if any(x for x in state.found_locations if '- Prize' in x.name):
|
||||||
|
key_layout.prize_can_lock = True
|
||||||
|
|
||||||
|
|
||||||
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if not world.keyshuffle[player] and not world.retro[player]:
|
||||||
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
||||||
|
|||||||
Reference in New Issue
Block a user