Merged in DR v1.2.0.18

This commit is contained in:
codemann8
2023-07-19 16:12:09 -05:00
5 changed files with 55 additions and 33 deletions

View File

@@ -1963,7 +1963,7 @@ def shuffle_big_key_doors(door_type_pools, used_doors, start_regions_map, all_cu
if flex_map[dungeon] > 0: if flex_map[dungeon] > 0:
queue.append(dungeon) queue.append(dungeon)
# time to re-assign # time to re-assign
reassign_big_key_doors(bk_map, world, player) reassign_big_key_doors(bk_map, used_doors, world, player)
for name, big_list in bk_map.items(): for name, big_list in bk_map.items():
used_doors.update(flatten_pair_list(big_list)) used_doors.update(flatten_pair_list(big_list))
return used_doors return used_doors
@@ -2048,7 +2048,7 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_
else: else:
builder.key_doors_num -= 1 builder.key_doors_num -= 1
# time to re-assign # time to re-assign
reassign_key_doors(small_map, world, player) reassign_key_doors(small_map, used_doors, world, player)
for dungeon_name in pool: for dungeon_name in pool:
if world.keyshuffle[player] != 'universal': if world.keyshuffle[player] != 'universal':
builder = world.dungeon_layouts[player][dungeon_name] builder = world.dungeon_layouts[player][dungeon_name]
@@ -2130,7 +2130,7 @@ def shuffle_bomb_dash_doors(door_type_pools, used_doors, start_regions_map, all_
suggestion_map[dungeon] = pair suggestion_map[dungeon] = pair
queue.append(dungeon) queue.append(dungeon)
# time to re-assign # time to re-assign
reassign_bd_doors(bd_map, world, player) reassign_bd_doors(bd_map, used_doors, world, player)
for name, pair in bd_map.items(): for name, pair in bd_map.items():
used_doors.update(flatten_pair_list(pair[0])) used_doors.update(flatten_pair_list(pair[0]))
used_doors.update(flatten_pair_list(pair[1])) used_doors.update(flatten_pair_list(pair[1]))
@@ -2540,7 +2540,7 @@ def find_current_bk_doors(builder):
return current_doors return current_doors
def reassign_big_key_doors(bk_map, world, player): def reassign_big_key_doors(bk_map, used_doors, world, player):
logger = logging.getLogger('') logger = logging.getLogger('')
for name, big_doors in bk_map.items(): for name, big_doors in bk_map.items():
flat_proposal = flatten_pair_list(big_doors) flat_proposal = flatten_pair_list(big_doors)
@@ -2548,11 +2548,12 @@ def reassign_big_key_doors(bk_map, world, player):
queue = deque(find_current_bk_doors(builder)) queue = deque(find_current_bk_doors(builder))
while len(queue) > 0: while len(queue) > 0:
d = queue.pop() d = queue.pop()
if d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal: if (d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal
and d not in used_doors and d.dest not in used_doors):
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.bigKey = False d.bigKey = False
elif d.type is DoorType.Normal and d not in flat_proposal: elif d.type is DoorType.Normal and d not in flat_proposal and d not in used_doors:
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.bigKey = False d.bigKey = False
@@ -2796,7 +2797,7 @@ def find_valid_bd_combination(builder, suggested, world, player):
return bomb_proposal, dash_proposal, ttl_needed return bomb_proposal, dash_proposal, ttl_needed
def reassign_bd_doors(bd_map, world, player): def reassign_bd_doors(bd_map, used_doors, world, player):
for name, pair in bd_map.items(): for name, pair in bd_map.items():
flat_bomb_proposal = flatten_pair_list(pair[0]) flat_bomb_proposal = flatten_pair_list(pair[0])
flat_dash_proposal = flatten_pair_list(pair[1]) flat_dash_proposal = flatten_pair_list(pair[1])
@@ -2809,10 +2810,10 @@ def reassign_bd_doors(bd_map, world, player):
queue = deque(find_current_bd_doors(builder, world)) queue = deque(find_current_bd_doors(builder, world))
while len(queue) > 0: while len(queue) > 0:
d = queue.pop() d = queue.pop()
if d.type is DoorType.Interior and not_in_proposal(d): if d.type is DoorType.Interior and not_in_proposal(d) and d not in used_doors and d.dest not in used_doors:
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
elif d.type is DoorType.Normal and not_in_proposal(d): elif d.type is DoorType.Normal and not_in_proposal(d) and d not in used_doors:
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
do_bombable_dashable(pair[0], DoorKind.Bombable, world, player) do_bombable_dashable(pair[0], DoorKind.Bombable, world, player)
@@ -3004,7 +3005,7 @@ def valid_key_door_pair(door1, door2):
return len(door1.entrance.parent_region.exits) <= 1 or len(door2.entrance.parent_region.exits) <= 1 return len(door1.entrance.parent_region.exits) <= 1 or len(door2.entrance.parent_region.exits) <= 1
def reassign_key_doors(small_map, world, player): def reassign_key_doors(small_map, used_doors, world, player):
logger = logging.getLogger('') logger = logging.getLogger('')
for name, small_doors in small_map.items(): for name, small_doors in small_map.items():
logger.debug(f'Key doors for {name}') logger.debug(f'Key doors for {name}')
@@ -3014,7 +3015,7 @@ def reassign_key_doors(small_map, world, player):
queue = deque(find_current_key_doors(builder)) queue = deque(find_current_key_doors(builder))
while len(queue) > 0: while len(queue) > 0:
d = queue.pop() d = queue.pop()
if d.type is DoorType.SpiralStairs and d not in proposal: if d.type is DoorType.SpiralStairs and d not in proposal and d not in used_doors:
room = world.get_room(d.roomIndex, player) room = world.get_room(d.roomIndex, player)
if room.doorList[d.doorListPos][1] == DoorKind.StairKeyLow: if room.doorList[d.doorListPos][1] == DoorKind.StairKeyLow:
room.delete(d.doorListPos) room.delete(d.doorListPos)
@@ -3024,13 +3025,14 @@ def reassign_key_doors(small_map, world, player):
else: else:
room.delete(d.doorListPos) room.delete(d.doorListPos)
d.smallKey = False d.smallKey = False
elif d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal: elif (d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal
and d not in used_doors and d.dest not in used_doors):
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.smallKey = False d.smallKey = False
d.dest.smallKey = False d.dest.smallKey = False
queue.remove(d.dest) queue.remove(d.dest)
elif d.type is DoorType.Normal and d not in flat_proposal: elif d.type is DoorType.Normal and d not in flat_proposal and d not in used_doors:
if not d.entranceFlag: if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.smallKey = False d.smallKey = False

View File

@@ -1487,7 +1487,8 @@ def make_customizer_pool(world, player):
bow_found = next((i for i in pool if i in {'Bow', 'Progressive Bow'}), None) bow_found = next((i for i in pool if i in {'Bow', 'Progressive Bow'}), None)
if not bow_found: if not bow_found:
missing_items.append('Progressive Bow') missing_items.append('Progressive Bow')
logging.getLogger('').warning(f'The following items are not in the custom item pool {", ".join(missing_items)}') if missing_items:
logging.getLogger('').warning(f'The following items are not in the custom item pool {", ".join(missing_items)}')
g, t = set_default_triforce(world.goal[player], world.treasure_hunt_count[player], g, t = set_default_triforce(world.goal[player], world.treasure_hunt_count[player],
world.treasure_hunt_total[player]) world.treasure_hunt_total[player])
@@ -1496,20 +1497,23 @@ def make_customizer_pool(world, player):
if pieces < t: if pieces < t:
pool.extend(['Triforce Piece'] * (t - pieces)) pool.extend(['Triforce Piece'] * (t - pieces))
if not world.customizer.get_start_inventory(): sphere_0 = world.customizer.get_start_inventory()
if world.logic[player] in ['owglitches', 'nologic']: no_start_inventory = not sphere_0 or not sphere_0[player]
precollected_items.append('Pegasus Boots') init_equip = [] if no_start_inventory else sphere_0[player]
if 'Pegasus Boots' in pool: if (world.logic[player] in ['owglitches', 'nologic']
pool.remove('Pegasus Boots') and (no_start_inventory or all(x != 'Pegasus Boots' for x in init_equip))):
pool.append('Rupees (20)') precollected_items.append('Pegasus Boots')
if world.swords[player] == 'assured': if 'Pegasus Boots' in pool:
precollected_items.append('Progressive Sword') pool.remove('Pegasus Boots')
if 'Progressive Sword' in pool: pool.append('Rupees (20)')
pool.remove('Progressive Sword') if world.swords[player] == 'assured' and (no_start_inventory or all(' Sword' not in x for x in init_equip)):
pool.append('Rupees (50)') precollected_items.append('Progressive Sword')
elif 'Fighter Sword' in pool: if 'Progressive Sword' in pool:
pool.remove('Fighter Sword') pool.remove('Progressive Sword')
pool.append('Rupees (50)') pool.append('Rupees (50)')
elif 'Fighter Sword' in pool:
pool.remove('Fighter Sword')
pool.append('Rupees (50)')
return pool, placed_items, precollected_items, clock_mode, 1 return pool, placed_items, precollected_items, clock_mode, 1
@@ -1578,10 +1582,13 @@ def fill_specific_items(world):
dungeon_pool, prize_set, prize_pool) dungeon_pool, prize_set, prize_pool)
if item_to_place: if item_to_place:
world.push_item(loc, item_to_place, False) world.push_item(loc, item_to_place, False)
loc.locked = True
track_outside_keys(item_to_place, loc, world) track_outside_keys(item_to_place, loc, world)
track_dungeon_items(item_to_place, loc, world) track_dungeon_items(item_to_place, loc, world)
loc.event = (event_flag or item_to_place.advancement loc.event = (event_flag or item_to_place.advancement
or item_to_place.bigkey or item_to_place.smallkey) or item_to_place.bigkey or item_to_place.smallkey)
else:
raise Exception(f'Did not find "{item}" in item pool to place at "{location}"')
advanced_placements = world.customizer.get_advanced_placements() advanced_placements = world.customizer.get_advanced_placements()
if advanced_placements: if advanced_placements:
for player, placement_list in advanced_placements.items(): for player, placement_list in advanced_placements.items():
@@ -1591,7 +1598,7 @@ def fill_specific_items(world):
item_to_place, event_flag = get_item_and_event_flag(item, world, player, item_to_place, event_flag = get_item_and_event_flag(item, world, player,
dungeon_pool, prize_set, prize_pool) dungeon_pool, prize_set, prize_pool)
if not item_to_place: if not item_to_place:
continue raise Exception(f'Did not find "{item}" in item pool to place for a LocationGroup"')
locations = placement['locations'] locations = placement['locations']
handled = False handled = False
while not handled: while not handled:
@@ -1611,6 +1618,7 @@ def fill_specific_items(world):
if loc.item: if loc.item:
continue continue
world.push_item(loc, item_to_place, False) world.push_item(loc, item_to_place, False)
loc.locked = True
track_outside_keys(item_to_place, loc, world) track_outside_keys(item_to_place, loc, world)
track_dungeon_items(item_to_place, loc, world) track_dungeon_items(item_to_place, loc, world)
loc.event = (event_flag or item_to_place.advancement loc.event = (event_flag or item_to_place.advancement

View File

@@ -36,7 +36,7 @@ from source.overworld.EntranceShuffle2 import link_entrances_new
from source.tools.BPS import create_bps_from_data from source.tools.BPS import create_bps_from_data
from source.classes.CustomSettings import CustomSettings from source.classes.CustomSettings import CustomSettings
version_number = '1.2.0.17' version_number = '1.2.0.18'
version_branch = '-u' version_branch = '-u'
__version__ = f'{version_number}{version_branch}' __version__ = f'{version_number}{version_branch}'
@@ -814,7 +814,9 @@ def create_playthrough(world):
logging.getLogger('').debug(world.fish.translate("cli", "cli", "building.calculating.spheres"), len(collection_spheres), len(sphere), len(prog_locations)) logging.getLogger('').debug(world.fish.translate("cli", "cli", "building.calculating.spheres"), len(collection_spheres), len(sphere), len(prog_locations))
if not sphere: if not sphere:
logging.getLogger('').error(world.fish.translate("cli", "cli", "cannot.reach.items"), [world.fish.translate("cli","cli","cannot.reach.item") % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates]) if world.accessibility[location.item.player] != 'none':
logging.getLogger('').error(world.fish.translate("cli", "cli", "cannot.reach.items"),
[world.fish.translate("cli","cli","cannot.reach.item") % (location.item.name, location.item.player, location.name, location.player) for location in sphere_candidates])
if any([location.name not in optional_locations and world.accessibility[location.item.player] != 'none' for location in sphere_candidates]): if any([location.name not in optional_locations and world.accessibility[location.item.player] != 'none' for location in sphere_candidates]):
raise RuntimeError(world.fish.translate("cli", "cli", "cannot.reach.progression")) raise RuntimeError(world.fish.translate("cli", "cli", "cannot.reach.progression"))
else: else:

View File

@@ -57,7 +57,7 @@ Please see [Customizer documentation](docs/Customizer.md) on how to create custo
## New Goals ## New Goals
### Triforce Hunt + Ganon ### Ganonhunt
Collect the requisite triforce pieces, then defeat Ganon. (Aga2 not required). Use `ganonhunt` on CLI Collect the requisite triforce pieces, then defeat Ganon. (Aga2 not required). Use `ganonhunt` on CLI
### Completionist ### Completionist
@@ -109,6 +109,16 @@ These are now independent of retro mode and have three options: None, Random, an
# Bug Fixes and Notes # Bug Fixes and Notes
* 1.2.0.18u
* Fixed an issue with pyramid hole being in logic when it is not opened.
* Crystal cutscene at GT use new symmetrical layouts (thanks Codemann)
* Fix for Hera Boss music (thanks Codemann)
* Fixed an issue where certain vanilla door types would not allow other types to be placed.
* Customizer: fixed an issue where last ditch placements would move customized items. Those are now locked and the generation will fail instead is no alternative are found.
* Customizer: fixed an issue with assured sword and start_inventory
* Customizer: warns when trying to specifically place an item that's not in the item pool
* Fixed "accessibility: none" displaying a spoiling message
* Fixed warning message about custom item pool when it is fine
* 1.2.0.17u * 1.2.0.17u
* Fixed logic bug that allowed Pearl to be behind Graveyard Cave or King's Tomb entrances with only Mirror and West Dark World access (cross world shuffles only) * Fixed logic bug that allowed Pearl to be behind Graveyard Cave or King's Tomb entrances with only Mirror and West Dark World access (cross world shuffles only)
* Removed backup locations for Dungeon Only and Major Only algorithms. If item cannot be placed in the appropriate location, the seed will fail to generate instead * Removed backup locations for Dungeon Only and Major Only algorithms. If item cannot be placed in the appropriate location, the seed will fail to generate instead

View File

@@ -269,7 +269,7 @@
"randomizer.item.goal.triforcehunt": "Triforce Hunt", "randomizer.item.goal.triforcehunt": "Triforce Hunt",
"randomizer.item.goal.trinity": "Trinity", "randomizer.item.goal.trinity": "Trinity",
"randomizer.item.goal.crystals": "Crystals", "randomizer.item.goal.crystals": "Crystals",
"randomizer.item.goal.ganonhunt": "Triforce Hunt + Ganon", "randomizer.item.goal.ganonhunt": "Ganonhunt",
"randomizer.item.goal.completionist": "Completionist", "randomizer.item.goal.completionist": "Completionist",
"randomizer.item.crystals_gt": "Crystals to open GT", "randomizer.item.crystals_gt": "Crystals to open GT",