Fix conflicts

This commit is contained in:
compiling
2020-01-05 21:51:07 +11:00
parent 9803515315
commit 0c2580dea9
9 changed files with 48 additions and 44 deletions

View File

@@ -14,7 +14,7 @@ class World(object):
def __init__(self, players, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, retro, custom, customitemarray, hints): def __init__(self, players, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, retro, custom, customitemarray, hints):
self.players = players self.players = players
self.shuffle = shuffle.copy() self.shuffle = shuffle.copy()
self.doorShuffle = doorShuffle.copy() self.doorShuffle = doorShuffle
self.logic = logic.copy() self.logic = logic.copy()
self.mode = mode.copy() self.mode = mode.copy()
self.swords = swords.copy() self.swords = swords.copy()
@@ -45,9 +45,9 @@ class World(object):
self.lock_aga_door_in_escape = False self.lock_aga_door_in_escape = False
self.save_and_quit_from_boss = True self.save_and_quit_from_boss = True
self.accessibility = accessibility.copy() self.accessibility = accessibility.copy()
self.fix_skullwoods_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] or self.doorShuffle not in ['vanilla'] self.fix_skullwoods_exit = {}
self.fix_palaceofdarkness_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] self.fix_palaceofdarkness_exit = {}
self.fix_trock_exit = self.shuffle not in ['vanilla', 'simple', 'restricted', 'dungeonssimple'] self.fix_trock_exit = {}
self.shuffle_ganon = shuffle_ganon self.shuffle_ganon = shuffle_ganon
self.fix_gtower_exit = self.shuffle_ganon self.fix_gtower_exit = self.shuffle_ganon
self.quickswap = quickswap self.quickswap = quickswap

View File

@@ -127,7 +127,7 @@ def vanilla_key_logic(world, player):
raise Exception('Vanilla key layout not valid %s' % builder.name) raise Exception('Vanilla key layout not valid %s' % builder.name)
if player not in world.key_logic.keys(): if player not in world.key_logic.keys():
world.key_logic[player] = {} world.key_logic[player] = {}
key_layout = analyze_dungeon(key_layout, world, player) analyze_dungeon(key_layout, world, player)
world.key_logic[player][builder.name] = key_layout.key_logic world.key_logic[player][builder.name] = key_layout.key_logic
validate_vanilla_key_logic(world, player) validate_vanilla_key_logic(world, player)

View File

@@ -172,7 +172,7 @@ def parse_arguments(argv, no_defaults=False):
The dungeon variants only mix up dungeons and keep the rest of The dungeon variants only mix up dungeons and keep the rest of
the overworld vanilla. the overworld vanilla.
''') ''')
parser.add_argument('--door_shuffle', default=defvalue('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'basic', 'crossed', 'experimental'], parser.add_argument('--door_shuffle', default=defval('vanilla'), const='vanilla', nargs='?', choices=['vanilla', 'basic', 'crossed', 'experimental'],
help='''\ help='''\
Select Door Shuffling Algorithm. (default: %(default)s) Select Door Shuffling Algorithm. (default: %(default)s)
Basic: Doors are mixed within a single dungeon. Basic: Doors are mixed within a single dungeon.

View File

@@ -194,7 +194,7 @@ def fill_restrictive(world, base_state, locations, itempool, single_player_place
spot_to_fill = None spot_to_fill = None
for location in locations: for location in locations:
if item_to_place.key: # a better test to see if a key can go there if item_to_place.smallkey or item_to_place.bigkey: # a better test to see if a key can go there
location.item = item_to_place location.item = item_to_place
test_state = maximum_exploration_state.copy() test_state = maximum_exploration_state.copy()
test_state.stale[item_to_place.player] = True test_state.stale[item_to_place.player] = True
@@ -204,7 +204,7 @@ def fill_restrictive(world, base_state, locations, itempool, single_player_place
and location.can_fill(test_state, item_to_place, perform_access_check): and location.can_fill(test_state, item_to_place, perform_access_check):
spot_to_fill = location spot_to_fill = location
break break
elif item_to_place.key: elif item_to_place.smallkey or item_to_place.bigkey:
location.item = None location.item = None
if spot_to_fill is None: if spot_to_fill is None:

3
Gui.py
View File

@@ -11,7 +11,7 @@ from urllib.parse import urlparse
from urllib.request import urlopen from urllib.request import urlopen
from AdjusterMain import adjust from AdjusterMain import adjust
from EntranceRandomizer import parse_arguments from DungeonRandomizer import parse_arguments
from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress
from Main import main, __version__ as ESVersion from Main import main, __version__ as ESVersion
from Rom import Sprite from Rom import Sprite
@@ -329,7 +329,6 @@ def guiMain(args=None):
shuffleFrame.pack(expand=True, anchor=E) shuffleFrame.pack(expand=True, anchor=E)
doorShuffleFrame.pack(expand=True, anchor=E) doorShuffleFrame.pack(expand=True, anchor=E)
swordsFrame.pack(expand=True, anchor=E)
difficultyFrame.pack(expand=True, anchor=E) difficultyFrame.pack(expand=True, anchor=E)
itemfunctionFrame.pack(expand=True, anchor=E) itemfunctionFrame.pack(expand=True, anchor=E)
timerFrame.pack(expand=True, anchor=E) timerFrame.pack(expand=True, anchor=E)

View File

@@ -114,7 +114,7 @@ def analyze_dungeon(key_layout, world, player):
while len(queue) > 0: while len(queue) > 0:
queue = collections.deque(sorted(queue, key=queue_sorter)) queue = collections.deque(sorted(queue, key=queue_sorter))
parent_door, key_counter = queue.popleft() parent_door, key_counter = queue.popleft()
chest_keys = available_chest_small_keys(key_counter, world) chest_keys = available_chest_small_keys(key_counter, world, player)
raw_avail = chest_keys + len(key_counter.key_only_locations) raw_avail = chest_keys + len(key_counter.key_only_locations)
available = raw_avail - key_counter.used_keys available = raw_avail - key_counter.used_keys
possible_smalls = count_unique_small_doors(key_counter, key_layout.flat_prop) possible_smalls = count_unique_small_doors(key_counter, key_layout.flat_prop)
@@ -135,10 +135,10 @@ def analyze_dungeon(key_layout, world, player):
while len(child_queue) > 0: while len(child_queue) > 0:
child, odd_counter = child_queue.popleft() child, odd_counter = child_queue.popleft()
if not child.bigKey: if not child.bigKey:
best_counter = find_best_counter(child, odd_counter, key_counter, key_layout, world, False) best_counter = find_best_counter(child, odd_counter, key_counter, key_layout, world, player, False)
rule = create_rule(best_counter, key_counter, key_layout, world) rule = create_rule(best_counter, key_counter, key_layout, world, player)
check_for_self_lock_key(rule, child, best_counter, key_layout, world) check_for_self_lock_key(rule, child, best_counter, key_layout, world)
bk_restricted_rules(rule, child, odd_counter, key_counter, key_layout, world) bk_restricted_rules(rule, child, odd_counter, key_counter, key_layout, world, player)
key_logic.door_rules[child.name] = rule key_logic.door_rules[child.name] = rule
doors_completed.add(child) doors_completed.add(child)
next_counter = find_next_counter(child, key_counter, key_layout) next_counter = find_next_counter(child, key_counter, key_layout)
@@ -217,7 +217,7 @@ def unique_child_door(child, key_counter):
return True return True
def find_best_counter(door, odd_counter, key_counter, key_layout, world, skip_bk): # try to waste as many keys as possible? def find_best_counter(door, odd_counter, key_counter, key_layout, world, player, skip_bk): # try to waste as many keys as possible?
ignored_doors = {door, door.dest} if door is not None else {} ignored_doors = {door, door.dest} if door is not None else {}
finished = False finished = False
opened_doors = dict(key_counter.open_doors) opened_doors = dict(key_counter.open_doors)
@@ -238,7 +238,7 @@ def find_best_counter(door, odd_counter, key_counter, key_layout, world, skip_bk
if relative_empty_counter(odd_counter, new_counter): if relative_empty_counter(odd_counter, new_counter):
ignored_doors.add(new_door) ignored_doors.add(new_door)
else: else:
if not key_wasted(new_door, last_counter, new_counter, key_layout, world): if not key_wasted(new_door, last_counter, new_counter, key_layout, world, player):
ignored_doors.add(new_door) ignored_doors.add(new_door)
else: else:
last_counter = new_counter last_counter = new_counter
@@ -266,12 +266,12 @@ def find_potential_open_doors(key_counter, ignored_doors, key_layout, skip_bk):
return small_doors + big_doors return small_doors + big_doors
def key_wasted(new_door, old_counter, new_counter, key_layout, world): def key_wasted(new_door, old_counter, new_counter, key_layout, world, player):
if new_door.bigKey: # big keys are not wastes - it uses up a location if new_door.bigKey: # big keys are not wastes - it uses up a location
return True return True
chest_keys = available_chest_small_keys(old_counter, world) chest_keys = available_chest_small_keys(old_counter, world, player)
old_avail = chest_keys + len(old_counter.key_only_locations) - old_counter.used_keys old_avail = chest_keys + len(old_counter.key_only_locations) - old_counter.used_keys
new_chest_keys = available_chest_small_keys(new_counter, world) new_chest_keys = available_chest_small_keys(new_counter, world, player)
new_avail = new_chest_keys + len(new_counter.key_only_locations) - new_counter.used_keys new_avail = new_chest_keys + len(new_counter.key_only_locations) - new_counter.used_keys
if new_avail < old_avail: if new_avail < old_avail:
return True return True
@@ -285,7 +285,7 @@ def key_wasted(new_door, old_counter, new_counter, key_layout, world):
proposed_doors = {**opened_doors, **dict.fromkeys([new_child, new_child.dest])} proposed_doors = {**opened_doors, **dict.fromkeys([new_child, new_child.dest])}
bk_open = bk_opened or new_door.bigKey bk_open = bk_opened or new_door.bigKey
new_counter = find_counter(proposed_doors, bk_open, key_layout) new_counter = find_counter(proposed_doors, bk_open, key_layout)
if key_wasted(new_child, current_counter, new_counter, key_layout, world): if key_wasted(new_child, current_counter, new_counter, key_layout, world, player):
return True # waste is possible return True # waste is possible
return False return False
@@ -303,16 +303,16 @@ def check_special_locations(locations):
return False return False
def calc_avail_keys(key_counter, world): def calc_avail_keys(key_counter, world, player):
chest_keys = available_chest_small_keys(key_counter, world) chest_keys = available_chest_small_keys(key_counter, world, player)
raw_avail = chest_keys + len(key_counter.key_only_locations) raw_avail = chest_keys + len(key_counter.key_only_locations)
return raw_avail - key_counter.used_keys return raw_avail - key_counter.used_keys
def create_rule(key_counter, prev_counter, key_layout, world): def create_rule(key_counter, prev_counter, key_layout, world, player):
# prev_chest_keys = available_chest_small_keys(prev_counter, world) # prev_chest_keys = available_chest_small_keys(prev_counter, world)
# prev_avail = prev_chest_keys + len(prev_counter.key_only_locations) # prev_avail = prev_chest_keys + len(prev_counter.key_only_locations)
chest_keys = available_chest_small_keys(key_counter, world) chest_keys = available_chest_small_keys(key_counter, world, player)
key_gain = len(key_counter.key_only_locations) - len(prev_counter.key_only_locations) key_gain = len(key_counter.key_only_locations) - len(prev_counter.key_only_locations)
raw_avail = chest_keys + len(key_counter.key_only_locations) raw_avail = chest_keys + len(key_counter.key_only_locations)
available = raw_avail - key_counter.used_keys available = raw_avail - key_counter.used_keys
@@ -405,8 +405,8 @@ def self_lock_possible(counter):
return len(counter.free_locations) <= 1 and len(counter.key_only_locations) == 0 and not counter.important_location return len(counter.free_locations) <= 1 and len(counter.key_only_locations) == 0 and not counter.important_location
def available_chest_small_keys(key_counter, world): def available_chest_small_keys(key_counter, world, player):
if not world.keysanity and world.mode != 'retro': if not world.keyshuffle[player] and not world.retro[player]:
cnt = 0 cnt = 0
for loc in key_counter.free_locations: for loc in key_counter.free_locations:
if key_counter.big_key_opened or '- Big Chest' not in loc.name: if key_counter.big_key_opened or '- Big Chest' not in loc.name:
@@ -416,11 +416,11 @@ def available_chest_small_keys(key_counter, world):
return key_counter.max_chests return key_counter.max_chests
def bk_restricted_rules(rule, door, odd_counter, key_counter, key_layout, world): def bk_restricted_rules(rule, door, odd_counter, key_counter, key_layout, world, player):
if key_counter.big_key_opened: if key_counter.big_key_opened:
return return
best_counter = find_best_counter(door, odd_counter, key_counter, key_layout, world, True) best_counter = find_best_counter(door, odd_counter, key_counter, key_layout, world, player, True)
bk_number = create_rule(best_counter, key_counter, key_layout, world).small_key_num bk_number = create_rule(best_counter, key_counter, key_layout, world, player).small_key_num
if bk_number == rule.small_key_num: if bk_number == rule.small_key_num:
return return
door_open = find_next_counter(door, best_counter, key_layout) door_open = find_next_counter(door, best_counter, key_layout)
@@ -649,8 +649,8 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
if not smalls_avail and num_bigs == 0: if not smalls_avail and num_bigs == 0:
return True # I think that's the end return True # I think that's the end
ttl_locations = state.ttl_locations if state.big_key_opened else count_locations_exclude_big_chest(state) ttl_locations = state.ttl_locations if state.big_key_opened else count_locations_exclude_big_chest(state)
available_small_locations = cnt_avail_small_locations(key_layout, ttl_locations, state, world) available_small_locations = cnt_avail_small_locations(key_layout, ttl_locations, state, world, player)
available_big_locations = cnt_avail_big_locations(ttl_locations, state, world) available_big_locations = cnt_avail_big_locations(ttl_locations, state, world, player)
if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0): if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
return False return False
else: else:
@@ -683,14 +683,14 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
return True return True
def cnt_avail_small_locations(key_layout, ttl_locations, state, world): def cnt_avail_small_locations(key_layout, ttl_locations, state, world, player):
if not world.keysanity and world.mode != 'retro': if not world.keyshuffle[player] and not world.retro[player]:
return min(ttl_locations - state.used_locations, state.key_locations - state.used_smalls) return min(ttl_locations - state.used_locations, state.key_locations - state.used_smalls)
return key_layout.max_chests + state.key_locations - state.used_smalls return key_layout.max_chests + state.key_locations - state.used_smalls
def cnt_avail_big_locations(ttl_locations, state, world): def cnt_avail_big_locations(ttl_locations, state, world, player):
if not world.keysanity: if not world.bigkeyshuffle[player]:
return ttl_locations - state.used_locations if not state.big_key_special else 0 return ttl_locations - state.used_locations if not state.big_key_special else 0
return 1 if not state.big_key_special else 0 return 1 if not state.big_key_special else 0

View File

@@ -35,7 +35,7 @@ def main(args, seed=None):
start = time.perf_counter() start = time.perf_counter()
# initialize the world # initialize the world
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints) world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.retro, args.custom, args.customitemarray, args.hints)
logger = logging.getLogger('') logger = logging.getLogger('')
if seed is None: if seed is None:
random.seed(None) random.seed(None)
@@ -72,8 +72,7 @@ def main(args, seed=None):
create_doors(world, player) create_doors(world, player)
create_rooms(world, player) create_rooms(world, player)
create_dungeons(world, player) create_dungeons(world, player)
else: else:
for player in range(1, world.players + 1):
create_inverted_regions(world, player) # todo: port all the dungeon region work create_inverted_regions(world, player) # todo: port all the dungeon region work
create_doors(world, player) create_doors(world, player)
create_rooms(world, player) create_rooms(world, player)
@@ -84,7 +83,6 @@ def main(args, seed=None):
for player in range(1, world.players + 1): for player in range(1, world.players + 1):
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
link_entrances(world, player) link_entrances(world, player)
for player in range(1, world.players + 1):
else: else:
link_inverted_entrances(world, player) link_inverted_entrances(world, player)
@@ -246,7 +244,7 @@ def main(args, seed=None):
def copy_world(world): def copy_world(world):
# ToDo: Not good yet # ToDo: Not good yet
ret = World(world.players, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.retro, world.custom, world.customitemarray, world.boss_shuffle, world.hints) ret = World(world.players, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.retro, world.custom, world.customitemarray, world.hints)
ret.required_medallions = world.required_medallions.copy() ret.required_medallions = world.required_medallions.copy()
ret.swamp_patch_required = world.swamp_patch_required.copy() ret.swamp_patch_required = world.swamp_patch_required.copy()
ret.ganon_at_pyramid = world.ganon_at_pyramid.copy() ret.ganon_at_pyramid = world.ganon_at_pyramid.copy()

View File

@@ -744,10 +744,10 @@ def _create_region(player, name, type, hint='Hyrule', locations=None, exits=None
ret.exits.append(Entrance(player, exit, ret)) ret.exits.append(Entrance(player, exit, ret))
for location in locations: for location in locations:
if location in key_only_locations: if location in key_only_locations:
ret.locations.append(Location(player, location, None, False, None, ret, key_only_locations[location], player_address)) ret.locations.append(Location(player, location, None, False, None, ret, key_only_locations[location]))
else: else:
address, crystal, hint_text = location_table[location] address, player_address, crystal, hint_text = location_table[location]
ret.locations.append(Location(player, location, address, crystal, hint_text, ret, player_address)) ret.locations.append(Location(player, location, address, crystal, hint_text, ret, None, player_address))
return ret return ret
def mark_light_world_regions(world, player): def mark_light_world_regions(world, player):
@@ -1086,6 +1086,13 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
'Frog': (None, None, False, None), 'Frog': (None, None, False, None),
'Missing Smith': (None, None, False, None), 'Missing Smith': (None, None, False, None),
'Dark Blacksmith Ruins': (None, None, False, None), 'Dark Blacksmith Ruins': (None, None, False, None),
'Trench 1 Switch': (None, None, False, None),
'Trench 2 Switch': (None, None, False, None),
'Swamp Drain': (None, None, False, None),
'Attic Cracked Floor': (None, None, False, None),
'Suspicious Maiden': (None, None, False, None),
'Revealing Light': (None, None, False, None),
'Ice Block Drop': (None, None, False, None),
'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'), 'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'),
'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'), 'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'),
'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'), 'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'),

File diff suppressed because one or more lines are too long