Fix can_beat_game error
Add start_region awareness to door finder combinations Added dungeon table
This commit is contained in:
@@ -441,8 +441,6 @@ class World(object):
|
|||||||
return True
|
return True
|
||||||
state = starting_state.copy()
|
state = starting_state.copy()
|
||||||
else:
|
else:
|
||||||
if self.has_beaten_game(self.state):
|
|
||||||
return True
|
|
||||||
state = CollectionState(self)
|
state = CollectionState(self)
|
||||||
|
|
||||||
if self.has_beaten_game(state):
|
if self.has_beaten_game(state):
|
||||||
|
|||||||
@@ -1456,6 +1456,14 @@ def find_valid_combination(builder, start_regions, world, player, drop_keys=True
|
|||||||
random.shuffle(sample_list)
|
random.shuffle(sample_list)
|
||||||
proposal = kth_combination(sample_list[itr], builder.candidates, builder.key_doors_num)
|
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)
|
key_layout = build_key_layout(builder, start_regions, proposal, world, player)
|
||||||
while not validate_key_layout(key_layout, world, player):
|
while not validate_key_layout(key_layout, world, player):
|
||||||
itr += 1
|
itr += 1
|
||||||
|
|||||||
45
Dungeons.py
45
Dungeons.py
@@ -373,6 +373,38 @@ flexible_starts = {
|
|||||||
'Skull Woods': ['Skull Left Drop', 'Skull Pinball']
|
'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 = {
|
dungeon_keys = {
|
||||||
'Hyrule Castle': 'Small Key (Escape)',
|
'Hyrule Castle': 'Small Key (Escape)',
|
||||||
'Eastern Palace': 'Small Key (Eastern Palace)',
|
'Eastern Palace': 'Small Key (Eastern Palace)',
|
||||||
@@ -405,19 +437,6 @@ dungeon_bigs = {
|
|||||||
'Ganons Tower': 'Big Key (Ganons Tower)'
|
'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 = {
|
dungeon_hints = {
|
||||||
'Hyrule Castle': 'in Hyrule Castle',
|
'Hyrule Castle': 'in Hyrule Castle',
|
||||||
'Eastern Palace': 'in Eastern Palace',
|
'Eastern Palace': 'in Eastern Palace',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from collections import defaultdict, deque
|
|||||||
|
|
||||||
from BaseClasses import DoorType, dungeon_keys, KeyRuleType, RegionType
|
from BaseClasses import DoorType, dungeon_keys, KeyRuleType, RegionType
|
||||||
from Regions import dungeon_events
|
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 ExplorationState, special_big_key_doors, count_locations_exclude_big_chest, prize_or_event
|
||||||
from DungeonGenerator import reserved_location, blind_boss_unavail
|
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)
|
dungeon_entrance, portal_door = find_outside_connection(region)
|
||||||
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
|
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
|
||||||
dungeon_entrance.name in ['Ganons Tower', 'Inverted Ganons Tower', 'Pyramid Fairy']
|
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.append_door_to_list(portal_door, state.prize_doors)
|
||||||
state.prize_door_set[portal_door] = dungeon_entrance
|
state.prize_door_set[portal_door] = dungeon_entrance
|
||||||
key_layout.prize_relevant = True
|
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)
|
dungeon_entrance, portal_door = find_outside_connection(region)
|
||||||
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
|
if (len(key_layout.start_regions) > 1 and dungeon_entrance and
|
||||||
dungeon_entrance.name in ['Ganons Tower', 'Inverted Ganons Tower', 'Pyramid Fairy']
|
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.append_door_to_list(portal_door, state.prize_doors)
|
||||||
state.prize_door_set[portal_door] = dungeon_entrance
|
state.prize_door_set[portal_door] = dungeon_entrance
|
||||||
key_layout.prize_relevant = True
|
key_layout.prize_relevant = True
|
||||||
@@ -1966,8 +1966,8 @@ def validate_key_placement(key_layout, world, player):
|
|||||||
len(counter.key_only_locations) + keys_outside
|
len(counter.key_only_locations) + keys_outside
|
||||||
if key_layout.prize_relevant:
|
if key_layout.prize_relevant:
|
||||||
found_prize = any(x for x in counter.important_locations if '- Prize' in x.name)
|
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:
|
if not found_prize and dungeon_table[key_layout.sector.name].prize:
|
||||||
prize_loc = world.get_location(dungeon_prize[key_layout.sector.name], player)
|
prize_loc = world.get_location(dungeon_table[key_layout.sector.name].prize, player)
|
||||||
# todo: pyramid fairy only care about crystals 5 & 6
|
# todo: pyramid fairy only care about crystals 5 & 6
|
||||||
found_prize = 'Crystal' not in prize_loc.item.name
|
found_prize = 'Crystal' not in prize_loc.item.name
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user