diff --git a/BaseClasses.py b/BaseClasses.py index cab3c5c7..2c41fbfb 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -689,15 +689,20 @@ class CollectionState(object): rrp = self.reachable_regions[player] missing_regions = {x: y for x, y in common_regions.items() if x not in rrp} + paths = {} for k in missing_regions: rrp[k] = missing_regions[k] + possible_path = terminal_states[0].path[k] + self.path[k] = paths[k] = possible_path missing_bc = {} for blocked, crystal in common_bc.items(): - if blocked not in bc and self.should_visit(blocked.connected_region, rrp, crystal, player): + if (blocked not in bc and blocked.parent_region in rrp + and self.should_visit(blocked.connected_region, rrp, crystal, player)): missing_bc[blocked] = crystal for k in missing_bc: bc[k] = missing_bc[k] - self.record_dungeon_exploration(player, dungeon_name, checklist, common_doors, missing_regions, missing_bc) + self.record_dungeon_exploration(player, dungeon_name, checklist, + common_doors, missing_regions, missing_bc, paths) checklist.clear() @staticmethod @@ -773,7 +778,7 @@ class CollectionState(object): exp_key = (prog_set, frozenset(checklist)) if dungeon_name in ec and exp_key in ec[dungeon_name]: # apply - cnt, miss, common_doors, missing_regions, missing_bc = ec[dungeon_name][exp_key] + common_doors, missing_regions, missing_bc, paths = ec[dungeon_name][exp_key] terminal_queue = deque() for door in common_doors: self.opened_doors[player].add(door) @@ -793,42 +798,32 @@ class CollectionState(object): for k in missing_regions: rrp[k] = missing_regions[k] + for r, path in paths.items(): + self.path[r] = path for k in missing_bc: bc[k] = missing_bc[k] return True return False - def record_dungeon_exploration(self, player, dungeon_name, checklist, common_doors, missing_regions, missing_bc): + def record_dungeon_exploration(self, player, dungeon_name, checklist, + common_doors, missing_regions, missing_bc, paths): ec = self.world.exp_cache[player] prog_set = self.reduce_prog_items(player, dungeon_name) exp_key = (prog_set, frozenset(checklist)) - count = 1 - misses = 0 - # if exp_key in ec: - # if dungeon_name in ec[exp_key]: - # cnt, miss, old_common, old_missing, old_bc, trace = ec[exp_key][dungeon_name] - # if old_common == common_doors and old_missing == missing_regions and old_bc == missing_bc: - # count = cnt + 1 - # else: - # misses = miss + 1 - ec[dungeon_name][exp_key] = (count, misses, common_doors, missing_regions, missing_bc) + ec[dungeon_name][exp_key] = (common_doors, missing_regions, missing_bc, paths) def reduce_prog_items(self, player, dungeon_name): # todo: possibly could include an analysis of dungeon items req. like Hammer, Hookshot, etc - # static logic rules needed most likely + # cross dungeon requirements may be necessary for keysanity - which invalidates the above # todo: universal smalls where needed life_count, bottle_count = 0, 0 reduced = Counter() for item, cnt in self.prog_items.items(): item_name, item_player = item if item_player == player and self.check_if_progressive(item_name): - if item_name.startswith('Bottle'): + if item_name.startswith('Bottle'): # I think magic requirements can require multiple bottles bottle_count += cnt - elif item_name.startswith(('Small Key', 'Big Key')): - d_name = 'Escape' if dungeon_name == 'Hyrule Castle' else dungeon_name - if d_name in item_name: - reduced[item] = cnt elif item_name in ['Boss Heart Container', 'Sanctuary Heart Container', 'Piece of Heart']: if 'Container' in item_name: life_count += 1 diff --git a/Fill.py b/Fill.py index bb608cdb..ee13e990 100644 --- a/Fill.py +++ b/Fill.py @@ -209,8 +209,8 @@ def fill_restrictive(world, base_state, locations, itempool, keys_in_itempool = if (not single_player_placement or location.player == item_to_place.player)\ and location.can_fill(test_state, item_to_place, perform_access_check)\ and valid_key_placement(item_to_place, location, itempool if (keys_in_itempool and keys_in_itempool[item_to_place.player]) else world.itempool, world): - spot_to_fill = location - break + spot_to_fill = location + break if item_to_place.smallkey or item_to_place.bigkey: location.item = None diff --git a/Main.py b/Main.py index c72bcef6..78fcaec8 100644 --- a/Main.py +++ b/Main.py @@ -27,7 +27,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names -__version__ = '0.4.0.8-u' +__version__ = '0.4.1.0-u' class EnemizerError(RuntimeError): diff --git a/Rules.py b/Rules.py index d8796dab..3cd18b2b 100644 --- a/Rules.py +++ b/Rules.py @@ -1941,8 +1941,6 @@ def add_key_logic_rules(world, player): for d_name, d_logic in key_logic.items(): for door_name, rule in d_logic.door_rules.items(): add_rule(world.get_entrance(door_name, player), eval_small_key_door(door_name, d_name, player)) - if rule.allow_small: - set_always_allow(rule.small_location, allow_self_locking_small(d_logic, player)) for location in d_logic.bk_restricted: if not location.forced_item: forbid_item(location, d_logic.bk_name, player) @@ -1960,10 +1958,6 @@ def add_key_logic_rules(world, player): add_rule(door.entrance, create_key_rule('Small Key (Universal)', player, 1)) -def allow_self_locking_small(logic, player): - return lambda state, item: item.player == player and logic.small_key_name == item.name - - def eval_small_key_door_main(state, door_name, dungeon, player): if state.is_door_open(door_name, player): return True diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 145667ef..fa7c355e 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -2,7 +2,7 @@ "cli": { "yes": "Yes", "no": "No", - "app.title": "ALttP Door Randomizer Version %s - Seed: %d, Code: %s", + "app.title": "ALttP Door Randomizer Version %s : --seed %d --code %s", "version": "Version", "seed": "Seed", "player": "Player",