More refinement for prize locked parts of a dungeon and key rule interaction
This commit is contained in:
6
Fill.py
6
Fill.py
@@ -245,7 +245,11 @@ def valid_key_placement(item, location, itempool, world):
|
|||||||
return True
|
return True
|
||||||
key_logic = world.key_logic[item.player][dungeon.name]
|
key_logic = world.key_logic[item.player][dungeon.name]
|
||||||
unplaced_keys = len([x for x in itempool if x.name == key_logic.small_key_name and x.player == item.player])
|
unplaced_keys = len([x for x in itempool if x.name == key_logic.small_key_name and x.player == item.player])
|
||||||
return key_logic.check_placement(unplaced_keys, location if item.bigkey else None)
|
prize_loc = None
|
||||||
|
if key_logic.prize_location:
|
||||||
|
prize_loc = world.get_location(key_logic.prize_location, location.player)
|
||||||
|
cr_count = world.crystals_needed_for_gt[location.player]
|
||||||
|
return key_logic.check_placement(unplaced_keys, location if item.bigkey else None, prize_loc, cr_count)
|
||||||
else:
|
else:
|
||||||
inside_dungeon_item = ((item.smallkey and not world.keyshuffle[item.player])
|
inside_dungeon_item = ((item.smallkey and not world.keyshuffle[item.player])
|
||||||
or (item.bigkey and not world.bigkeyshuffle[item.player]))
|
or (item.bigkey and not world.bigkeyshuffle[item.player]))
|
||||||
|
|||||||
@@ -58,10 +58,11 @@ class KeyLogic(object):
|
|||||||
self.outside_keys = 0
|
self.outside_keys = 0
|
||||||
self.dungeon = dungeon_name
|
self.dungeon = dungeon_name
|
||||||
self.sm_doors = {}
|
self.sm_doors = {}
|
||||||
|
self.prize_location = None
|
||||||
|
|
||||||
def check_placement(self, unplaced_keys, big_key_loc=None):
|
def check_placement(self, unplaced_keys, big_key_loc=None, prize_loc=None, cr_count=7):
|
||||||
for rule in self.placement_rules:
|
for rule in self.placement_rules:
|
||||||
if not rule.is_satisfiable(self.outside_keys, unplaced_keys, big_key_loc):
|
if not rule.is_satisfiable(self.outside_keys, unplaced_keys, big_key_loc, prize_loc, cr_count):
|
||||||
return False
|
return False
|
||||||
if big_key_loc:
|
if big_key_loc:
|
||||||
for rule_a, rule_b in itertools.combinations(self.placement_rules, 2):
|
for rule_a, rule_b in itertools.combinations(self.placement_rules, 2):
|
||||||
@@ -120,6 +121,7 @@ class PlacementRule(object):
|
|||||||
self.check_locations_wo_bk = None
|
self.check_locations_wo_bk = None
|
||||||
self.bk_relevant = True
|
self.bk_relevant = True
|
||||||
self.key_reduced = False
|
self.key_reduced = False
|
||||||
|
self.prize_relevance = None
|
||||||
|
|
||||||
def contradicts(self, rule, unplaced_keys, big_key_loc):
|
def contradicts(self, rule, unplaced_keys, big_key_loc):
|
||||||
bk_blocked = big_key_loc in self.bk_conditional_set if self.bk_conditional_set else False
|
bk_blocked = big_key_loc in self.bk_conditional_set if self.bk_conditional_set else False
|
||||||
@@ -154,7 +156,14 @@ class PlacementRule(object):
|
|||||||
left -= rule_needed
|
left -= rule_needed
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_satisfiable(self, outside_keys, unplaced_keys, big_key_loc):
|
def is_satisfiable(self, outside_keys, unplaced_keys, big_key_loc, prize_location, cr_count):
|
||||||
|
if self.prize_relevance and prize_location:
|
||||||
|
if self.prize_relevance == 'BigBomb':
|
||||||
|
if prize_location.item.name not in ['Crystal 5', 'Crystal 6']:
|
||||||
|
return True
|
||||||
|
elif self.prize_relevance == 'GT':
|
||||||
|
if 'Crystal' not in prize_location.item.name or cr_count < 7:
|
||||||
|
return True
|
||||||
bk_blocked = False
|
bk_blocked = False
|
||||||
if self.bk_conditional_set:
|
if self.bk_conditional_set:
|
||||||
for loc in self.bk_conditional_set:
|
for loc in self.bk_conditional_set:
|
||||||
@@ -258,6 +267,7 @@ def analyze_dungeon(key_layout, world, player):
|
|||||||
find_bk_locked_sections(key_layout, world, player)
|
find_bk_locked_sections(key_layout, world, player)
|
||||||
key_logic.bk_chests.update(find_big_chest_locations(key_layout.all_chest_locations))
|
key_logic.bk_chests.update(find_big_chest_locations(key_layout.all_chest_locations))
|
||||||
key_logic.bk_chests.update(find_big_key_locked_locations(key_layout.all_chest_locations))
|
key_logic.bk_chests.update(find_big_key_locked_locations(key_layout.all_chest_locations))
|
||||||
|
key_logic.prize_location = dungeon_table[key_layout.sector.name].prize
|
||||||
if world.retro[player] and world.mode[player] != 'standard':
|
if world.retro[player] and world.mode[player] != 'standard':
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -361,6 +371,7 @@ def create_exhaustive_placement_rules(key_layout, world, player):
|
|||||||
rule.bk_conditional_set = blocked_loc
|
rule.bk_conditional_set = blocked_loc
|
||||||
rule.needed_keys_wo_bk = min_keys
|
rule.needed_keys_wo_bk = min_keys
|
||||||
rule.check_locations_wo_bk = set(filter_big_chest(accessible_loc))
|
rule.check_locations_wo_bk = set(filter_big_chest(accessible_loc))
|
||||||
|
rule.prize_relevance = key_layout.prize_relevant if rule_prize_relevant(key_counter) else None
|
||||||
if valid_rule:
|
if valid_rule:
|
||||||
key_logic.placement_rules.append(rule)
|
key_logic.placement_rules.append(rule)
|
||||||
adjust_locations_rules(key_logic, rule, accessible_loc, key_layout, key_counter, max_ctr)
|
adjust_locations_rules(key_logic, rule, accessible_loc, key_layout, key_counter, max_ctr)
|
||||||
@@ -368,6 +379,10 @@ def create_exhaustive_placement_rules(key_layout, world, player):
|
|||||||
refine_location_rules(key_layout)
|
refine_location_rules(key_layout)
|
||||||
|
|
||||||
|
|
||||||
|
def rule_prize_relevant(key_counter):
|
||||||
|
return not key_counter.prize_doors_opened and not key_counter.prize_received
|
||||||
|
|
||||||
|
|
||||||
def skip_key_counter_due_to_prize(key_layout, key_counter):
|
def skip_key_counter_due_to_prize(key_layout, key_counter):
|
||||||
return key_layout.prize_relevant and key_counter.prize_received and not key_counter.prize_doors_opened
|
return key_layout.prize_relevant and key_counter.prize_received and not key_counter.prize_doors_opened
|
||||||
|
|
||||||
@@ -467,7 +482,7 @@ def refine_placement_rules(key_layout, max_ctr):
|
|||||||
if rule.needed_keys_wo_bk == 0:
|
if rule.needed_keys_wo_bk == 0:
|
||||||
rules_to_remove.append(rule)
|
rules_to_remove.append(rule)
|
||||||
if len(rule.check_locations_wo_bk) < rule.needed_keys_wo_bk or rule.needed_keys_wo_bk > key_layout.max_chests:
|
if len(rule.check_locations_wo_bk) < rule.needed_keys_wo_bk or rule.needed_keys_wo_bk > key_layout.max_chests:
|
||||||
if len(rule.bk_conditional_set) > 0:
|
if not rule.prize_relevance and len(rule.bk_conditional_set) > 0:
|
||||||
key_logic.bk_restricted.update(rule.bk_conditional_set)
|
key_logic.bk_restricted.update(rule.bk_conditional_set)
|
||||||
rules_to_remove.append(rule)
|
rules_to_remove.append(rule)
|
||||||
changed = True # impossible for bk to be here, I think
|
changed = True # impossible for bk to be here, I think
|
||||||
@@ -1432,7 +1447,8 @@ 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)
|
||||||
if smalls_done and bk_done:
|
prize_done = not key_layout.prize_relevant or state.prize_doors_opened
|
||||||
|
if smalls_done and bk_done and prize_done:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
# todo: pretty sure you should OR these paths together, maybe when there's one location and it can
|
# todo: pretty sure you should OR these paths together, maybe when there's one location and it can
|
||||||
@@ -1468,6 +1484,7 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
if not valid:
|
if not valid:
|
||||||
return False
|
return False
|
||||||
# todo: feel like you only open these if the boss is available???
|
# todo: feel like you only open these if the boss is available???
|
||||||
|
# todo: or if a crystal isn't valid placement on this boss
|
||||||
if not state.prize_doors_opened and key_layout.prize_relevant:
|
if not state.prize_doors_opened and key_layout.prize_relevant:
|
||||||
state_copy = state.copy()
|
state_copy = state.copy()
|
||||||
open_a_door(next(iter(state_copy.prize_door_set)), state_copy, flat_proposal, world, player)
|
open_a_door(next(iter(state_copy.prize_door_set)), state_copy, flat_proposal, world, player)
|
||||||
|
|||||||
Reference in New Issue
Block a user