diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index 26db7f9e..5b690c22 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -169,21 +169,11 @@ class KeyCounter(object): self.big_key_opened = False self.important_location = False self.other_locations = {} + self.important_locations = {} def used_smalls_loc(self, reserve=0): return max(self.used_keys + reserve - len(self.key_only_locations), 0) - def copy(self): - ret = KeyCounter(self.max_chests) - ret.free_locations.update(self.free_locations) - ret.key_only_locations.update(self.key_only_locations) - ret.child_doors.update(self.child_doors) - ret.used_keys = self.used_keys - ret.open_doors.update(self.open_doors) - ret.big_key_opened = self.big_key_opened - ret.important_location = self.important_location - return ret - def build_key_layout(builder, start_regions, proposal, world, player): key_layout = KeyLayout(builder.master_sector, start_regions, proposal) @@ -540,6 +530,9 @@ def relative_empty_counter(odd_counter, key_counter): return False if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0: return False + # important only + if len(set(odd_counter.important_locations).difference(key_counter.important_locations)) > 0: + return False new_child_door = False for child in odd_counter.child_doors: if unique_child_door(child, key_counter): @@ -555,6 +548,9 @@ def relative_empty_counter_2(odd_counter, key_counter): return False if len(set(odd_counter.free_locations).difference(key_counter.free_locations)) > 0: return False + # important only + if len(set(odd_counter.important_locations).difference(key_counter.important_locations)) > 0: + return False for child in odd_counter.child_doors: if unique_child_door_2(child, key_counter): return False @@ -981,11 +977,15 @@ def filter_big_chest(locations): def count_locations_exclude_logic(locations, key_logic): cnt = 0 for loc in locations: - if loc not in key_logic.bk_restricted and not loc.forced_item and not prize_or_event(loc): - cnt += 1 + if not location_is_bk_locked(loc, key_logic) and not loc.forced_item and not prize_or_event(loc): + cnt += 1 return cnt +def location_is_bk_locked(loc, key_logic): + return loc in key_logic.bk_chests or loc in key_logic.bk_locked + + def prize_or_event(loc): return loc.name in dungeon_events or '- Prize' in loc.name or loc.name in ['Agahnim 1', 'Agahnim 2'] @@ -1417,6 +1417,7 @@ def create_key_counter(state, key_layout, world, player): if important_location(loc, world, player): key_counter.important_location = True key_counter.other_locations[loc] = None + key_counter.important_locations[loc] = None elif loc.forced_item and loc.item.name == key_layout.key_logic.small_key_name: key_counter.key_only_locations[loc] = None elif loc.forced_item and loc.item.name == key_layout.key_logic.bk_name: @@ -1456,6 +1457,7 @@ def create_odd_key_counter(door, parent_counter, key_layout, world, player): odd_counter.key_only_locations = dict_difference(next_counter.key_only_locations, parent_counter.key_only_locations) odd_counter.child_doors = dict_difference(next_counter.child_doors, parent_counter.child_doors) odd_counter.other_locations = dict_difference(next_counter.other_locations, parent_counter.other_locations) + odd_counter.important_locations = dict_difference(next_counter.important_locations, parent_counter.important_locations) for loc in odd_counter.other_locations: if important_location(loc, world, player): odd_counter.important_location = True diff --git a/Main.py b/Main.py index c0e52af4..20cd433f 100644 --- a/Main.py +++ b/Main.py @@ -24,7 +24,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items from Utils import output_path, parse_player_names -__version__ = '0.2.0.15u' +__version__ = '0.2.0.16u' class EnemizerError(RuntimeError): pass diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e4aca12d..eb30ad5e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -92,6 +92,13 @@ testing to verify logic is all good. # Bug Fixes +* 2.0.16u + * Prevent HUD from showing key counter when in the overworld. (Aga 2 doesn't always clear the dungeon indicator) + * Fixed key logic regarding certain isolated "important" locations + * Fixed a problem with keydropshuffle thinking certain progression items are keys + * A couple of inverted rules fixed + * A more accurate count of which locations are blocked by teh big key in Ganon's Tower + * Updated base rom to 31.0.7 (includes potential hera basement cage fix) * 2.0.15u * Allow Aga Tower lobby door as a a paired keydoor (typo) * Fix portal check for multi-entrance dungeons diff --git a/Rom.py b/Rom.py index 59a82fef..99ee1f2a 100644 --- a/Rom.py +++ b/Rom.py @@ -26,7 +26,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '55b2f851e5d643e1e72befc631ea3c6d' +RANDOMIZERBASEHASH = '185a0f74ab0e2ce8899c8d7d309ca68c' class JsonRom(object): diff --git a/Rules.py b/Rules.py index 118b3bb2..ce769974 100644 --- a/Rules.py +++ b/Rules.py @@ -467,7 +467,7 @@ def default_rules(world, player): set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has_Pearl(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # ToDo any fake flipper set up? + set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.has_Pearl(player) and state.can_lift_rocks(player)) set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -513,6 +513,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Castle Ledge S&Q', player), lambda state: state.has_Mirror(player) and state.has('Beat Agahnim 1', player)) # overworld requirements + set_rule(world.get_location('Ice Rod Cave', player), lambda state: state.has_Pearl(player)) set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player)) set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has_Pearl(player)) @@ -664,6 +665,7 @@ def no_glitches_rules(world, player): add_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) + add_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player)) else: add_rule(world.get_entrance('Zoras River', player), lambda state: state.has_Pearl(player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has_Pearl(player) and state.has('Flippers', player)) # can be fake flippered to @@ -673,6 +675,7 @@ def no_glitches_rules(world, player): add_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) add_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) add_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) + add_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player)) # todo: move some dungeon rules to no glictes logic - see these for examples # add_rule(world.get_entrance('Ganons Tower (Hookshot Room)', player), lambda state: state.has('Hookshot', player) or state.has_Boots(player)) diff --git a/asm/hudadditions.asm b/asm/hudadditions.asm index f0ed773e..9b78a0a4 100644 --- a/asm/hudadditions.asm +++ b/asm/hudadditions.asm @@ -15,8 +15,9 @@ HudAdditions: LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit ++ - ldx $040c : cpx #$ff : bne + : rts : + - lda.l DRMode : bne + : rts : + + LDX $1B : BNE + : RTS : + ; Skip if outdoors + ldx $040c : cpx #$ff : bne + : rts : + ; Skip if not in dungeon + lda.l DRMode : bne + : rts : + ; Skip if not door rando phb : phk : plb lda $7ef364 : and.l $0098c0, x : beq + lda.w CompassBossIndicator, x : and #$00ff : cmp $a0 : bne + diff --git a/asm/keydropshuffle.asm b/asm/keydropshuffle.asm index 7b64746f..a150774f 100644 --- a/asm/keydropshuffle.asm +++ b/asm/keydropshuffle.asm @@ -126,7 +126,7 @@ KeyGet: lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive phx lda $040c : lsr : tax - lda $00 : cmp KeyTable, x : bne + + lda $00 : CMP.l KeyTable, x : bne + - JSL.l FullInventoryExternal : jsl CountChestKeyLong : plx : pla : rtl + cmp #$af : beq - ; universal key cmp #$24 : beq - ; small key for this dungeon diff --git a/data/base2current.bps b/data/base2current.bps index 2b70fcc0..61323175 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ