Small refinements for key logic
This commit is contained in:
@@ -689,15 +689,20 @@ class CollectionState(object):
|
|||||||
|
|
||||||
rrp = self.reachable_regions[player]
|
rrp = self.reachable_regions[player]
|
||||||
missing_regions = {x: y for x, y in common_regions.items() if x not in rrp}
|
missing_regions = {x: y for x, y in common_regions.items() if x not in rrp}
|
||||||
|
paths = {}
|
||||||
for k in missing_regions:
|
for k in missing_regions:
|
||||||
rrp[k] = missing_regions[k]
|
rrp[k] = missing_regions[k]
|
||||||
|
possible_path = terminal_states[0].path[k]
|
||||||
|
self.path[k] = paths[k] = possible_path
|
||||||
missing_bc = {}
|
missing_bc = {}
|
||||||
for blocked, crystal in common_bc.items():
|
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
|
missing_bc[blocked] = crystal
|
||||||
for k in missing_bc:
|
for k in missing_bc:
|
||||||
bc[k] = missing_bc[k]
|
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()
|
checklist.clear()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -773,7 +778,7 @@ class CollectionState(object):
|
|||||||
exp_key = (prog_set, frozenset(checklist))
|
exp_key = (prog_set, frozenset(checklist))
|
||||||
if dungeon_name in ec and exp_key in ec[dungeon_name]:
|
if dungeon_name in ec and exp_key in ec[dungeon_name]:
|
||||||
# apply
|
# 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()
|
terminal_queue = deque()
|
||||||
for door in common_doors:
|
for door in common_doors:
|
||||||
self.opened_doors[player].add(door)
|
self.opened_doors[player].add(door)
|
||||||
@@ -793,42 +798,32 @@ class CollectionState(object):
|
|||||||
|
|
||||||
for k in missing_regions:
|
for k in missing_regions:
|
||||||
rrp[k] = missing_regions[k]
|
rrp[k] = missing_regions[k]
|
||||||
|
for r, path in paths.items():
|
||||||
|
self.path[r] = path
|
||||||
for k in missing_bc:
|
for k in missing_bc:
|
||||||
bc[k] = missing_bc[k]
|
bc[k] = missing_bc[k]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
return False
|
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]
|
ec = self.world.exp_cache[player]
|
||||||
prog_set = self.reduce_prog_items(player, dungeon_name)
|
prog_set = self.reduce_prog_items(player, dungeon_name)
|
||||||
exp_key = (prog_set, frozenset(checklist))
|
exp_key = (prog_set, frozenset(checklist))
|
||||||
count = 1
|
ec[dungeon_name][exp_key] = (common_doors, missing_regions, missing_bc, paths)
|
||||||
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)
|
|
||||||
|
|
||||||
def reduce_prog_items(self, player, dungeon_name):
|
def reduce_prog_items(self, player, dungeon_name):
|
||||||
# todo: possibly could include an analysis of dungeon items req. like Hammer, Hookshot, etc
|
# 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
|
# todo: universal smalls where needed
|
||||||
life_count, bottle_count = 0, 0
|
life_count, bottle_count = 0, 0
|
||||||
reduced = Counter()
|
reduced = Counter()
|
||||||
for item, cnt in self.prog_items.items():
|
for item, cnt in self.prog_items.items():
|
||||||
item_name, item_player = item
|
item_name, item_player = item
|
||||||
if item_player == player and self.check_if_progressive(item_name):
|
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
|
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']:
|
elif item_name in ['Boss Heart Container', 'Sanctuary Heart Container', 'Piece of Heart']:
|
||||||
if 'Container' in item_name:
|
if 'Container' in item_name:
|
||||||
life_count += 1
|
life_count += 1
|
||||||
|
|||||||
4
Fill.py
4
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)\
|
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 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):
|
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
|
spot_to_fill = location
|
||||||
break
|
break
|
||||||
if item_to_place.smallkey or item_to_place.bigkey:
|
if item_to_place.smallkey or item_to_place.bigkey:
|
||||||
location.item = None
|
location.item = None
|
||||||
|
|
||||||
|
|||||||
2
Main.py
2
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 ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.4.0.8-u'
|
__version__ = '0.4.1.0-u'
|
||||||
|
|
||||||
|
|
||||||
class EnemizerError(RuntimeError):
|
class EnemizerError(RuntimeError):
|
||||||
|
|||||||
6
Rules.py
6
Rules.py
@@ -1941,8 +1941,6 @@ def add_key_logic_rules(world, player):
|
|||||||
for d_name, d_logic in key_logic.items():
|
for d_name, d_logic in key_logic.items():
|
||||||
for door_name, rule in d_logic.door_rules.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))
|
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:
|
for location in d_logic.bk_restricted:
|
||||||
if not location.forced_item:
|
if not location.forced_item:
|
||||||
forbid_item(location, d_logic.bk_name, player)
|
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))
|
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):
|
def eval_small_key_door_main(state, door_name, dungeon, player):
|
||||||
if state.is_door_open(door_name, player):
|
if state.is_door_open(door_name, player):
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"cli": {
|
"cli": {
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"no": "No",
|
"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",
|
"version": "Version",
|
||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"player": "Player",
|
"player": "Player",
|
||||||
|
|||||||
Reference in New Issue
Block a user