Ban big keys from locations that will block required freestanding keys
TBD how to handle regular rules
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import logging
|
||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
|
|
||||||
from Regions import dungeon_events
|
from Regions import dungeon_events
|
||||||
@@ -46,8 +47,9 @@ class KeyLogic(object):
|
|||||||
|
|
||||||
class DoorRules(object):
|
class DoorRules(object):
|
||||||
|
|
||||||
def __init__(self, number):
|
def __init__(self, number, is_valid):
|
||||||
self.small_key_num = number
|
self.small_key_num = number
|
||||||
|
self.is_valid = is_valid
|
||||||
# allowing a different number if bk is behind this door in a set of locations
|
# allowing a different number if bk is behind this door in a set of locations
|
||||||
self.alternate_small_key = None
|
self.alternate_small_key = None
|
||||||
self.alternate_big_key_loc = set()
|
self.alternate_big_key_loc = set()
|
||||||
@@ -144,6 +146,8 @@ def analyze_dungeon(key_layout, world, player):
|
|||||||
if not child.bigKey and child not in doors_completed:
|
if not child.bigKey and child not in doors_completed:
|
||||||
best_counter = find_best_counter(child, odd_counter, key_counter, key_layout, world, player, False, empty_flag)
|
best_counter = find_best_counter(child, odd_counter, key_counter, key_layout, world, player, False, empty_flag)
|
||||||
rule = create_rule(best_counter, key_counter, key_layout, world, player)
|
rule = create_rule(best_counter, key_counter, key_layout, world, player)
|
||||||
|
if not rule.is_valid:
|
||||||
|
logging.getLogger('').warning('Key logic for door %s requires too many chests. Seed may be beatable anyway.', child.name)
|
||||||
if smallest_rule is None or rule.small_key_num < smallest_rule:
|
if smallest_rule is None or rule.small_key_num < smallest_rule:
|
||||||
smallest_rule = rule.small_key_num
|
smallest_rule = rule.small_key_num
|
||||||
check_for_self_lock_key(rule, child, best_counter, key_layout, world, player)
|
check_for_self_lock_key(rule, child, best_counter, key_layout, world, player)
|
||||||
@@ -343,9 +347,10 @@ def create_rule(key_counter, prev_counter, key_layout, world, player):
|
|||||||
required_keys = key_counter.used_keys + 1 # this makes more sense, if key_counter has wasted all keys
|
required_keys = key_counter.used_keys + 1 # this makes more sense, if key_counter has wasted all keys
|
||||||
adj_chest_keys = min(chest_keys, required_keys)
|
adj_chest_keys = min(chest_keys, required_keys)
|
||||||
needed_chests = required_keys - len(key_counter.key_only_locations)
|
needed_chests = required_keys - len(key_counter.key_only_locations)
|
||||||
|
is_valid = needed_chests <= chest_keys
|
||||||
unneeded_chests = min(key_gain, adj_chest_keys - needed_chests)
|
unneeded_chests = min(key_gain, adj_chest_keys - needed_chests)
|
||||||
rule_num = required_keys - unneeded_chests
|
rule_num = required_keys - unneeded_chests
|
||||||
return DoorRules(rule_num)
|
return DoorRules(rule_num, is_valid)
|
||||||
|
|
||||||
|
|
||||||
def check_for_self_lock_key(rule, door, parent_counter, key_layout, world, player):
|
def check_for_self_lock_key(rule, door, parent_counter, key_layout, world, player):
|
||||||
@@ -451,8 +456,8 @@ def bk_restricted_rules(rule, door, odd_counter, empty_flag, key_counter, key_la
|
|||||||
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, player, True, empty_flag)
|
best_counter = find_best_counter(door, odd_counter, key_counter, key_layout, world, player, True, empty_flag)
|
||||||
bk_number = create_rule(best_counter, key_counter, key_layout, world, player).small_key_num
|
bk_rule = create_rule(best_counter, key_counter, key_layout, world, player)
|
||||||
if bk_number == rule.small_key_num:
|
if bk_rule.is_valid and bk_rule.small_key_num == 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)
|
||||||
ignored_doors = dict_intersection(best_counter.child_doors, door_open.child_doors)
|
ignored_doors = dict_intersection(best_counter.child_doors, door_open.child_doors)
|
||||||
@@ -463,10 +468,11 @@ def bk_restricted_rules(rule, door, odd_counter, empty_flag, key_counter, key_la
|
|||||||
ignored_doors = {**ignored_doors, **dict.fromkeys(dest_ignored)}
|
ignored_doors = {**ignored_doors, **dict.fromkeys(dest_ignored)}
|
||||||
post_counter = open_some_counter(door_open, key_layout, ignored_doors.keys())
|
post_counter = open_some_counter(door_open, key_layout, ignored_doors.keys())
|
||||||
unique_loc = dict_difference(post_counter.free_locations, best_counter.free_locations)
|
unique_loc = dict_difference(post_counter.free_locations, best_counter.free_locations)
|
||||||
if len(unique_loc) > 0:
|
if bk_rule.is_valid and len(unique_loc) > 0:
|
||||||
rule.alternate_small_key = bk_number
|
rule.alternate_small_key = bk_rule.small_key_num
|
||||||
rule.alternate_big_key_loc.update(unique_loc)
|
rule.alternate_big_key_loc.update(unique_loc)
|
||||||
|
elif not bk_rule.is_valid:
|
||||||
|
key_layout.key_logic.bk_restricted.update(unique_loc)
|
||||||
|
|
||||||
def open_a_door(door, child_state, flat_proposal):
|
def open_a_door(door, child_state, flat_proposal):
|
||||||
if door.bigKey:
|
if door.bigKey:
|
||||||
@@ -604,7 +610,7 @@ def check_rules(original_counter, key_layout, world, player):
|
|||||||
access_rules = key_only_map[loc]
|
access_rules = key_only_map[loc]
|
||||||
if access_door is None or access_door.name not in key_layout.key_logic.door_rules.keys():
|
if access_door is None or access_door.name not in key_layout.key_logic.door_rules.keys():
|
||||||
if access_door is None or not access_door.bigKey:
|
if access_door is None or not access_door.bigKey:
|
||||||
access_rules.append(DoorRules(0))
|
access_rules.append(DoorRules(0, True))
|
||||||
else:
|
else:
|
||||||
rule = key_layout.key_logic.door_rules[access_door.name]
|
rule = key_layout.key_logic.door_rules[access_door.name]
|
||||||
if rule not in access_rules:
|
if rule not in access_rules:
|
||||||
|
|||||||
Reference in New Issue
Block a user