Fix can_beat_game error

Add start_region awareness to door finder combinations
Added dungeon table
This commit is contained in:
aerinon
2021-08-26 15:21:10 -06:00
parent f259e8bdc8
commit 6f06dbcd04
4 changed files with 45 additions and 20 deletions

View File

@@ -441,8 +441,6 @@ class World(object):
return True
state = starting_state.copy()
else:
if self.has_beaten_game(self.state):
return True
state = CollectionState(self)
if self.has_beaten_game(state):

View File

@@ -1456,6 +1456,14 @@ def find_valid_combination(builder, start_regions, world, player, drop_keys=True
random.shuffle(sample_list)
proposal = kth_combination(sample_list[itr], builder.candidates, builder.key_doors_num)
# eliminate start region if portal marked as destination
excluded = {}
for region in start_regions:
portal = next((x for x in world.dungeon_portals[player] if x.door.entrance.parent_region == region), None)
if portal and portal.destination:
excluded[region] = None
start_regions = [x for x in start_regions if x not in excluded.keys()]
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
while not validate_key_layout(key_layout, world, player):
itr += 1

View File

@@ -373,6 +373,38 @@ flexible_starts = {
'Skull Woods': ['Skull Left Drop', 'Skull Pinball']
}
class DungeonInfo:
def __init__(self, free, keys, bk, map, compass, bk_drop, drops, prize=None):
# todo reduce static maps ideas: prize, bk_name, sm_name, cmp_name, map_name):
self.free_items = free
self.key_num = keys
self.bk_present = bk
self.map_present = map
self.compass_present = compass
self.bk_drops = bk_drop
self.key_drops = drops
self.prize = prize
dungeon_table = {
'Hyrule Castle': DungeonInfo(6, 1, False, True, False, True, 3, None),
'Eastern Palace': DungeonInfo(3, 0, True, True, True, False, 2, 'Eastern Palace - Prize'),
'Desert Palace': DungeonInfo(2, 1, True, True, True, False, 3, 'Desert Palace - Prize'),
'Tower of Hera': DungeonInfo(2, 1, True, True, True, False, 0, 'Tower of Hera - Prize'),
'Agahnims Tower': DungeonInfo(0, 2, False, False, False, False, 2, None),
'Palace of Darkness': DungeonInfo(5, 6, True, True, True, False, 0, 'Palace of Darkness - Prize'),
'Swamp Palace': DungeonInfo(6, 1, True, True, True, False, 5, 'Swamp Palace - Prize'),
'Skull Woods': DungeonInfo(2, 3, True, True, True, False, 2, 'Skull Woods - Prize'),
'Thieves Town': DungeonInfo(4, 1, True, True, True, False, 2, "Thieves' Town - Prize"),
'Ice Palace': DungeonInfo(3, 2, True, True, True, False, 4, 'Ice Palace - Prize'),
'Misery Mire': DungeonInfo(2, 3, True, True, True, False, 3, 'Misery Mire - Prize'),
'Turtle Rock': DungeonInfo(5, 4, True, True, True, False, 2, 'Turtle Rock - Prize'),
'Ganons Tower': DungeonInfo(20, 4, True, True, True, False, 4, None),
}
dungeon_keys = {
'Hyrule Castle': 'Small Key (Escape)',
'Eastern Palace': 'Small Key (Eastern Palace)',
@@ -405,19 +437,6 @@ dungeon_bigs = {
'Ganons Tower': 'Big Key (Ganons Tower)'
}
dungeon_prize = {
'Eastern Palace': 'Eastern Palace - Prize',
'Desert Palace': 'Desert Palace - Prize',
'Tower of Hera': 'Tower of Hera - Prize',
'Palace of Darkness': 'Palace of Darkness - Prize',
'Swamp Palace': 'Swamp Palace - Prize',
'Skull Woods': 'Skull Woods - Prize',
'Thieves Town': "Thieves' Town - Prize",
'Ice Palace': 'Ice Palace - Prize',
'Misery Mire': 'Misery Mire - Prize',
'Turtle Rock': 'Turtle Rock - Prize',
}
dungeon_hints = {
'Hyrule Castle': 'in Hyrule Castle',
'Eastern Palace': 'in Eastern Palace',

View File

@@ -4,7 +4,7 @@ from collections import defaultdict, deque
from BaseClasses import DoorType, dungeon_keys, KeyRuleType, RegionType
from Regions import dungeon_events
from Dungeons import dungeon_keys, dungeon_bigs, dungeon_prize
from Dungeons import dungeon_keys, dungeon_bigs, dungeon_table
from DungeonGenerator import ExplorationState, special_big_key_doors, count_locations_exclude_big_chest, prize_or_event
from DungeonGenerator import reserved_location, blind_boss_unavail
@@ -1378,7 +1378,7 @@ def validate_key_layout(key_layout, world, player):
dungeon_entrance, portal_door = find_outside_connection(region)
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
dungeon_entrance.name in ['Ganons Tower', 'Inverted Ganons Tower', 'Pyramid Fairy']
and key_layout.key_logic.dungeon in dungeon_prize):
and dungeon_table[key_layout.key_logic.dungeon].prize):
state.append_door_to_list(portal_door, state.prize_doors)
state.prize_door_set[portal_door] = dungeon_entrance
key_layout.prize_relevant = True
@@ -1541,7 +1541,7 @@ def create_key_counters(key_layout, world, player):
dungeon_entrance, portal_door = find_outside_connection(region)
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
dungeon_entrance.name in ['Ganons Tower', 'Inverted Ganons Tower', 'Pyramid Fairy']
and key_layout.key_logic.dungeon in dungeon_prize):
and dungeon_table[key_layout.key_logic.dungeon].prize):
state.append_door_to_list(portal_door, state.prize_doors)
state.prize_door_set[portal_door] = dungeon_entrance
key_layout.prize_relevant = True
@@ -1966,8 +1966,8 @@ def validate_key_placement(key_layout, world, player):
len(counter.key_only_locations) + keys_outside
if key_layout.prize_relevant:
found_prize = any(x for x in counter.important_locations if '- Prize' in x.name)
if not found_prize and key_layout.sector.name in dungeon_prize:
prize_loc = world.get_location(dungeon_prize[key_layout.sector.name], player)
if not found_prize and dungeon_table[key_layout.sector.name].prize:
prize_loc = world.get_location(dungeon_table[key_layout.sector.name].prize, player)
# todo: pyramid fairy only care about crystals 5 & 6
found_prize = 'Crystal' not in prize_loc.item.name
else: