Merge branch 'DoorDevUnstable' of https://github.com/StructuralMike/ALttPDoorRandomizer into StructuralMike-DoorDevUnstable

This commit is contained in:
aerinon
2021-07-27 16:16:53 -06:00
17 changed files with 102 additions and 48 deletions

View File

@@ -114,6 +114,7 @@ class World(object):
set_player_attr('compassshuffle', False) set_player_attr('compassshuffle', False)
set_player_attr('keyshuffle', False) set_player_attr('keyshuffle', False)
set_player_attr('bigkeyshuffle', False) set_player_attr('bigkeyshuffle', False)
set_player_attr('bomblogic', False)
set_player_attr('difficulty_requirements', None) set_player_attr('difficulty_requirements', None)
set_player_attr('boss_shuffle', 'none') set_player_attr('boss_shuffle', 'none')
set_player_attr('enemy_shuffle', 'none') set_player_attr('enemy_shuffle', 'none')
@@ -686,8 +687,7 @@ class CollectionState(object):
# In the future, this can be used to check if the player starts without bombs # In the future, this can be used to check if the player starts without bombs
def can_use_bombs(self, player): def can_use_bombs(self, player):
StartingBombs = True return (not self.world.bomblogic[player] or self.has('Bomb Upgrade (+10)', player))
return StartingBombs or self.has('Bomb Upgrade (+10)', player)
def can_hit_crystal(self, player): def can_hit_crystal(self, player):
return (self.can_use_bombs(player) return (self.can_use_bombs(player)
@@ -719,6 +719,7 @@ class CollectionState(object):
def can_get_good_bee(self, player): def can_get_good_bee(self, player):
cave = self.world.get_region('Good Bee Cave', player) cave = self.world.get_region('Good Bee Cave', player)
return ( return (
self.can_use_bombs(player) and
self.has_bottle(player) and self.has_bottle(player) and
self.has('Bug Catching Net', player) and self.has('Bug Catching Net', player) and
(self.has_Boots(player) or (self.has_sword(player) and self.has('Quake', player))) and (self.has_Boots(player) or (self.has_sword(player) and self.has('Quake', player))) and
@@ -2013,6 +2014,7 @@ class Spoiler(object):
'logic': self.world.logic, 'logic': self.world.logic,
'mode': self.world.mode, 'mode': self.world.mode,
'retro': self.world.retro, 'retro': self.world.retro,
'bomblogic': self.world.bomblogic,
'weapons': self.world.swords, 'weapons': self.world.swords,
'goal': self.world.goal, 'goal': self.world.goal,
'shuffle': self.world.shuffle, 'shuffle': self.world.shuffle,
@@ -2111,6 +2113,7 @@ class Spoiler(object):
outfile.write('Experimental: %s\n' % ('Yes' if self.metadata['experimental'][player] else 'No')) outfile.write('Experimental: %s\n' % ('Yes' if self.metadata['experimental'][player] else 'No'))
outfile.write('Key Drops shuffled: %s\n' % ('Yes' if self.metadata['keydropshuffle'][player] else 'No')) outfile.write('Key Drops shuffled: %s\n' % ('Yes' if self.metadata['keydropshuffle'][player] else 'No'))
outfile.write(f"Shopsanity: {'Yes' if self.metadata['shopsanity'][player] else 'No'}\n") outfile.write(f"Shopsanity: {'Yes' if self.metadata['shopsanity'][player] else 'No'}\n")
outfile.write('Bomblogic: %s\n' % ('Yes' if self.metadata['bomblogic'][player] else 'No'))
if self.doors: if self.doors:
outfile.write('\n\nDoors:\n\n') outfile.write('\n\nDoors:\n\n')
outfile.write('\n'.join( outfile.write('\n'.join(

2
CLI.py
View File

@@ -96,6 +96,7 @@ def parse_cli(argv, no_defaults=False):
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
'bomblogic',
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots', 'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots',
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
@@ -126,6 +127,7 @@ def parse_settings():
settings = { settings = {
"lang": "en", "lang": "en",
"retro": False, "retro": False,
"bomblogic": False,
"mode": "open", "mode": "open",
"logic": "noglitches", "logic": "noglitches",
"goal": "ganon", "goal": "ganon",

View File

@@ -2373,7 +2373,7 @@ Cave_Exits_Base = [['Elder House Exit (East)', 'Elder House Exit (West)'],
['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)'], ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)'],
['Fairy Ascension Cave Exit (Bottom)', 'Fairy Ascension Cave Exit (Top)'], ['Fairy Ascension Cave Exit (Bottom)', 'Fairy Ascension Cave Exit (Top)'],
['Bumper Cave Exit (Top)', 'Bumper Cave Exit (Bottom)'], ['Bumper Cave Exit (Top)', 'Bumper Cave Exit (Bottom)'],
['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']] ['Hookshot Cave Back Exit', 'Hookshot Cave Front Exit']]
Cave_Exits_Base += [('Superbunny Cave Exit (Bottom)', 'Superbunny Cave Exit (Top)'), Cave_Exits_Base += [('Superbunny Cave Exit (Bottom)', 'Superbunny Cave Exit (Top)'),
('Spiral Cave Exit (Top)', 'Spiral Cave Exit')] ('Spiral Cave Exit (Top)', 'Spiral Cave Exit')]
@@ -3115,6 +3115,10 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Dark Death Mountain Drop (West)', 'Dark Death Mountain (West Bottom)'), ('Dark Death Mountain Drop (West)', 'Dark Death Mountain (West Bottom)'),
('East Death Mountain (Top) Mirror Spot', 'East Death Mountain (Top)'), ('East Death Mountain (Top) Mirror Spot', 'East Death Mountain (Top)'),
('Superbunny Cave Climb', 'Superbunny Cave (Top)'), ('Superbunny Cave Climb', 'Superbunny Cave (Top)'),
('Hookshot Cave Front to Middle', 'Hookshot Cave (Middle)'),
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
('Turtle Rock Teleporter', 'Turtle Rock (Top)'), ('Turtle Rock Teleporter', 'Turtle Rock (Top)'),
('Turtle Rock Drop', 'Dark Death Mountain (Top)'), ('Turtle Rock Drop', 'Dark Death Mountain (Top)'),
('Floating Island Drop', 'Dark Death Mountain (Top)'), ('Floating Island Drop', 'Dark Death Mountain (Top)'),
@@ -3233,6 +3237,10 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Turtle Rock Tail Drop', 'Turtle Rock (Top)'), ('Turtle Rock Tail Drop', 'Turtle Rock (Top)'),
('Turtle Rock Drop', 'Dark Death Mountain'), ('Turtle Rock Drop', 'Dark Death Mountain'),
('Superbunny Cave Climb', 'Superbunny Cave (Top)'), ('Superbunny Cave Climb', 'Superbunny Cave (Top)'),
('Hookshot Cave Front to Middle', 'Hookshot Cave (Middle)'),
('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'),
('Hookshot Cave Middle to Back', 'Hookshot Cave (Back)'),
('Hookshot Cave Back to Middle', 'Hookshot Cave (Middle)'),
('Desert Ledge Drop', 'Light World'), ('Desert Ledge Drop', 'Light World'),
('Floating Island Drop', 'Dark Death Mountain'), ('Floating Island Drop', 'Dark Death Mountain'),
('Dark Lake Hylia Central Island Teleporter', 'Lake Hylia Central Island'), ('Dark Lake Hylia Central Island Teleporter', 'Lake Hylia Central Island'),
@@ -3428,16 +3436,16 @@ default_connections = [('Links House', 'Links House'),
('Dark Desert Hint', 'Dark Desert Hint'), ('Dark Desert Hint', 'Dark Desert Hint'),
('Dark Desert Fairy', 'Dark Desert Healer Fairy'), ('Dark Desert Fairy', 'Dark Desert Healer Fairy'),
('Spike Cave', 'Spike Cave'), ('Spike Cave', 'Spike Cave'),
('Hookshot Cave', 'Hookshot Cave'), ('Hookshot Cave', 'Hookshot Cave (Front)'),
('Superbunny Cave (Top)', 'Superbunny Cave (Top)'), ('Superbunny Cave (Top)', 'Superbunny Cave (Top)'),
('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'), ('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'),
('Dark Death Mountain Fairy', 'Dark Death Mountain Healer Fairy'), ('Dark Death Mountain Fairy', 'Dark Death Mountain Healer Fairy'),
('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'),
('Superbunny Cave Exit (Top)', 'Dark Death Mountain (Top)'), ('Superbunny Cave Exit (Top)', 'Dark Death Mountain (Top)'),
('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (South)', 'Dark Death Mountain (Top)'), ('Hookshot Cave Front Exit', 'Dark Death Mountain (Top)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), ('Hookshot Cave Back Exit', 'Death Mountain Floating Island (Dark World)'),
('Hookshot Cave Back Entrance', 'Hookshot Cave'), ('Hookshot Cave Back Entrance', 'Hookshot Cave (Back)'),
('Mimic Cave', 'Mimic Cave'), ('Mimic Cave', 'Mimic Cave'),
('Pyramid Hole', 'Pyramid'), ('Pyramid Hole', 'Pyramid'),
@@ -3562,13 +3570,13 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Dark Desert Hint', 'Dark Desert Hint'), ('Dark Desert Hint', 'Dark Desert Hint'),
('Dark Desert Fairy', 'Dark Desert Healer Fairy'), ('Dark Desert Fairy', 'Dark Desert Healer Fairy'),
('Spike Cave', 'Spike Cave'), ('Spike Cave', 'Spike Cave'),
('Hookshot Cave', 'Hookshot Cave'), ('Hookshot Cave', 'Hookshot Cave (Front)'),
('Superbunny Cave (Top)', 'Superbunny Cave (Top)'), ('Superbunny Cave (Top)', 'Superbunny Cave (Top)'),
('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'), ('Cave Shop (Dark Death Mountain)', 'Cave Shop (Dark Death Mountain)'),
('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'), ('Superbunny Cave (Bottom)', 'Superbunny Cave (Bottom)'),
('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'), ('Superbunny Cave Exit (Bottom)', 'Dark Death Mountain (East Bottom)'),
('Hookshot Cave Exit (North)', 'Death Mountain Floating Island (Dark World)'), ('Hookshot Cave Back Exit', 'Death Mountain Floating Island (Dark World)'),
('Hookshot Cave Back Entrance', 'Hookshot Cave'), ('Hookshot Cave Back Entrance', 'Hookshot Cave (Back)'),
('Mimic Cave', 'Mimic Cave'), ('Mimic Cave', 'Mimic Cave'),
('Inverted Pyramid Hole', 'Pyramid'), ('Inverted Pyramid Hole', 'Pyramid'),
('Inverted Links House', 'Inverted Links House'), ('Inverted Links House', 'Inverted Links House'),
@@ -3589,7 +3597,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'), ('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
('Death Mountain Return Cave Exit (West)', 'Death Mountain'), ('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
('Death Mountain Return Cave Exit (East)', 'Death Mountain'), ('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
('Hookshot Cave Exit (South)', 'Dark Death Mountain'), ('Hookshot Cave Front Exit', 'Dark Death Mountain'),
('Superbunny Cave Exit (Top)', 'Dark Death Mountain'), ('Superbunny Cave Exit (Top)', 'Dark Death Mountain'),
('Pyramid Exit', 'Light World'), ('Pyramid Exit', 'Light World'),
('Inverted Pyramid Entrance', 'Bottom of Pyramid')] ('Inverted Pyramid Entrance', 'Bottom of Pyramid')]
@@ -3937,8 +3945,8 @@ exit_ids = {'Links House Exit': (0x01, 0x00),
'Bumper Cave Exit (Bottom)': (0x16, 0x17), 'Bumper Cave Exit (Bottom)': (0x16, 0x17),
'Superbunny Cave Exit (Top)': (0x14, 0x15), 'Superbunny Cave Exit (Top)': (0x14, 0x15),
'Superbunny Cave Exit (Bottom)': (0x13, 0x14), 'Superbunny Cave Exit (Bottom)': (0x13, 0x14),
'Hookshot Cave Exit (South)': (0x3A, 0x3B), 'Hookshot Cave Front Exit': (0x3A, 0x3B),
'Hookshot Cave Exit (North)': (0x3B, 0x3C), 'Hookshot Cave Back Exit': (0x3B, 0x3C),
'Ganons Tower Exit': (0x37, 0x38), 'Ganons Tower Exit': (0x37, 0x38),
'Inverted Ganons Tower Exit': (0x37, 0x38), 'Inverted Ganons Tower Exit': (0x37, 0x38),
'Pyramid Exit': (0x36, 0x37), 'Pyramid Exit': (0x36, 0x37),

View File

@@ -199,8 +199,11 @@ def create_inverted_regions(world, player):
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']), create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']), create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']), create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
create_cave_region(player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'],
['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), ['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit']),
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
create_dw_region(player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance']), create_dw_region(player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance']),
create_cave_region(player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']), create_cave_region(player, 'Mimic Cave', 'Mimic Cave', ['Mimic Cave']),

View File

@@ -37,7 +37,7 @@ Difficulty = namedtuple('Difficulty',
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield', ['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
'basicshield', 'progressivearmor', 'basicarmor', 'swordless', 'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother', 'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
'retro', 'retro', 'bomblogic',
'extras', 'progressive_sword_limit', 'progressive_shield_limit', 'extras', 'progressive_sword_limit', 'progressive_shield_limit',
'progressive_armor_limit', 'progressive_bottle_limit', 'progressive_armor_limit', 'progressive_bottle_limit',
'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit']) 'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit'])
@@ -61,6 +61,7 @@ difficulties = {
timedohko = ['Green Clock'] * 25, timedohko = ['Green Clock'] * 25,
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
retro = ['Small Key (Universal)'] * 18 + ['Rupees (20)'] * 10, retro = ['Small Key (Universal)'] * 18 + ['Rupees (20)'] * 10,
bomblogic = ['Bomb Upgrade (+10)'] * 2,
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
progressive_sword_limit = 4, progressive_sword_limit = 4,
progressive_shield_limit = 3, progressive_shield_limit = 3,
@@ -86,6 +87,7 @@ difficulties = {
timedohko = ['Green Clock'] * 25, timedohko = ['Green Clock'] * 25,
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
retro = ['Small Key (Universal)'] * 13 + ['Rupees (5)'] * 15, retro = ['Small Key (Universal)'] * 13 + ['Rupees (5)'] * 15,
bomblogic = ['Bomb Upgrade (+10)'] * 2,
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
progressive_sword_limit = 3, progressive_sword_limit = 3,
progressive_shield_limit = 2, progressive_shield_limit = 2,
@@ -111,6 +113,7 @@ difficulties = {
timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5, timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5,
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
retro = ['Small Key (Universal)'] * 13 + ['Rupees (5)'] * 15, retro = ['Small Key (Universal)'] * 13 + ['Rupees (5)'] * 15,
bomblogic = ['Bomb Upgrade (+10)'] * 2,
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
progressive_sword_limit = 2, progressive_sword_limit = 2,
progressive_shield_limit = 1, progressive_shield_limit = 1,
@@ -251,10 +254,10 @@ def generate_itempool(world, player):
# set up item pool # set up item pool
if world.custom: if world.custom:
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.customitemarray) (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.bomblogic[player], world.customitemarray)
world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999)
else: else:
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.doorShuffle[player], world.logic[player]) (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.bomblogic[player], world.doorShuffle[player], world.logic[player])
if player in world.pool_adjustment.keys(): if player in world.pool_adjustment.keys():
amt = world.pool_adjustment[player] amt = world.pool_adjustment[player]
@@ -284,7 +287,7 @@ def generate_itempool(world, player):
if item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']: if item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
if item not in possible_weapons: if item not in possible_weapons:
possible_weapons.append(item) possible_weapons.append(item)
if item in ['Bombs (10)']: if not world.bomblogic[player] and item in ['Bombs (10)']:
if item not in possible_weapons and world.doorShuffle[player] != 'crossed': if item not in possible_weapons and world.doorShuffle[player] != 'crossed':
possible_weapons.append(item) possible_weapons.append(item)
starting_weapon = random.choice(possible_weapons) starting_weapon = random.choice(possible_weapons)
@@ -520,6 +523,15 @@ def set_up_shops(world, player):
rss.locked = True rss.locked = True
cap_shop = world.get_region('Capacity Upgrade', player).shop cap_shop = world.get_region('Capacity Upgrade', player).shop
cap_shop.inventory[1] = None # remove arrow capacity upgrades in retro cap_shop.inventory[1] = None # remove arrow capacity upgrades in retro
if world.bomblogic[player]:
if world.shopsanity[player]:
removals = [item for item in world.itempool if item.name == 'Bomb Upgrade (+5)' and item.player == player]
for remove in removals:
world.itempool.remove(remove)
world.itempool.append(ItemFactory('Rupees (50)', player)) # replace the bomb upgrade
else:
cap_shop = world.get_region('Capacity Upgrade', player).shop
cap_shop.inventory[0] = cap_shop.inventory[1] # remove bomb capacity upgrades in bomblogic
def customize_shops(world, player): def customize_shops(world, player):
@@ -564,7 +576,7 @@ def customize_shops(world, player):
if not found_bomb_upgrade and len(possible_replacements) > 0: if not found_bomb_upgrade and len(possible_replacements) > 0:
choices = [] choices = []
for shop, idx, loc, item in possible_replacements: for shop, idx, loc, item in possible_replacements:
if item.name in ['Bombs (3)', 'Bombs (10)']: if item.name in ['Bombs (3)', 'Bombs (10)'] and not world.bomblogic[player]:
choices.append((shop, idx, loc, item)) choices.append((shop, idx, loc, item))
if len(choices) > 0: if len(choices) > 0:
shop, idx, loc, item = random.choice(choices) shop, idx, loc, item = random.choice(choices)
@@ -709,7 +721,7 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)'
'Rupees (100)': 100, 'Rupees (300)': 300} 'Rupees (100)': 100, 'Rupees (300)': 300}
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, door_shuffle, logic): def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bomblogic, door_shuffle, logic):
pool = [] pool = []
placed_items = {} placed_items = {}
precollected_items = [] precollected_items = []
@@ -756,6 +768,11 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
diff = difficulties[difficulty] diff = difficulties[difficulty]
pool.extend(diff.baseitems) pool.extend(diff.baseitems)
if bomblogic:
pool = [item.replace('Bomb Upgrade (+5)','Rupees (5)') for item in pool]
pool = [item.replace('Bomb Upgrade (+10)','Rupees (5)') for item in pool]
pool.extend(diff.bomblogic)
# expert+ difficulties produce the same contents for # expert+ difficulties produce the same contents for
# all bottles, since only one bottle is available # all bottles, since only one bottle is available
if diff.same_bottle: if diff.same_bottle:
@@ -850,7 +867,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
pool.extend(['Small Key (Universal)']) pool.extend(['Small Key (Universal)'])
return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms)
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, customitemarray): def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bomblogic, customitemarray):
if isinstance(customitemarray,dict) and 1 in customitemarray: if isinstance(customitemarray,dict) and 1 in customitemarray:
customitemarray = customitemarray[1] customitemarray = customitemarray[1]
pool = [] pool = []
@@ -966,20 +983,21 @@ def test():
for shuffle in ['full', 'insanity_legacy']: for shuffle in ['full', 'insanity_legacy']:
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']: for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
for retro in [True, False]: for retro in [True, False]:
for door_shuffle in ['basic', 'crossed', 'vanilla']: for bomblogic in [True, False]:
out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, door_shuffle, logic) for door_shuffle in ['basic', 'crossed', 'vanilla']:
count = len(out[0]) + len(out[1]) out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bomblogic, door_shuffle, logic)
count = len(out[0]) + len(out[1])
correct_count = total_items_to_place correct_count = total_items_to_place
if goal == 'pedestal' and swords != 'vanilla': if goal == 'pedestal' and swords != 'vanilla':
# pedestal goals generate one extra item # pedestal goals generate one extra item
correct_count += 1 correct_count += 1
if retro: if retro:
correct_count += 28 correct_count += 28
try: try:
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro)) assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bomblogic))
except AssertionError as e: except AssertionError as e:
print(e) print(e)
if __name__ == '__main__': if __name__ == '__main__':
test() test()

View File

@@ -81,7 +81,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'), 'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'), 'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'), 'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), 'Bomb Upgrade (+10)': (True, False, None, 0x52, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Bomb Upgrade (+5)': (False, False, None, 0x51, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), 'Bomb Upgrade (+5)': (False, False, None, 0x51, 100, 'increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
'Blue Mail': (False, True, None, 0x22, 50, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the blue mail'), 'Blue Mail': (False, True, None, 0x22, 50, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the blue mail'),
'Red Mail': (False, True, None, 0x23, 100, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the red mail'), 'Red Mail': (False, True, None, 0x23, 100, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the red mail'),

View File

@@ -79,6 +79,7 @@ def main(args, seed=None, fish=None):
world.compassshuffle = args.compassshuffle.copy() world.compassshuffle = args.compassshuffle.copy()
world.keyshuffle = args.keyshuffle.copy() world.keyshuffle = args.keyshuffle.copy()
world.bigkeyshuffle = args.bigkeyshuffle.copy() world.bigkeyshuffle = args.bigkeyshuffle.copy()
world.bomblogic = args.bomblogic.copy()
world.crystals_needed_for_ganon = {player: random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(args.crystals_ganon[player]) for player in range(1, world.players + 1)} world.crystals_needed_for_ganon = {player: random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(args.crystals_ganon[player]) for player in range(1, world.players + 1)}
world.crystals_needed_for_gt = {player: random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player]) for player in range(1, world.players + 1)} world.crystals_needed_for_gt = {player: random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player]) for player in range(1, world.players + 1)}
world.crystals_ganon_orig = args.crystals_ganon.copy() world.crystals_ganon_orig = args.crystals_ganon.copy()
@@ -382,6 +383,7 @@ def copy_world(world):
ret.compassshuffle = world.compassshuffle.copy() ret.compassshuffle = world.compassshuffle.copy()
ret.keyshuffle = world.keyshuffle.copy() ret.keyshuffle = world.keyshuffle.copy()
ret.bigkeyshuffle = world.bigkeyshuffle.copy() ret.bigkeyshuffle = world.bigkeyshuffle.copy()
ret.bomblogic = world.bomblogic.copy()
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()

View File

@@ -176,6 +176,8 @@ def roll_settings(weights):
ret.retro = True ret.retro = True
ret.retro = get_choice('retro') == 'on' # this overrides world_state if used ret.retro = get_choice('retro') == 'on' # this overrides world_state if used
ret.bomblogic = get_choice('bomblogic') == 'on'
ret.hints = get_choice('hints') == 'on' ret.hints = get_choice('hints') == 'on'
ret.swords = {'randomized': 'random', ret.swords = {'randomized': 'random',

View File

@@ -51,7 +51,7 @@ vanilla_pots = {
43: [Pot(16, 5, PotItem.Heart, 'PoD Sexy Statue'), Pot(44, 5, PotItem.Switch, 'PoD Sexy Statue'), Pot(16, 6, PotItem.Heart, 'PoD Sexy Statue'), Pot(44, 6, PotItem.Bomb, 'PoD Sexy Statue'), Pot(16, 7, PotItem.Heart, 'PoD Sexy Statue'), 43: [Pot(16, 5, PotItem.Heart, 'PoD Sexy Statue'), Pot(44, 5, PotItem.Switch, 'PoD Sexy Statue'), Pot(16, 6, PotItem.Heart, 'PoD Sexy Statue'), Pot(44, 6, PotItem.Bomb, 'PoD Sexy Statue'), Pot(16, 7, PotItem.Heart, 'PoD Sexy Statue'),
Pot(44, 7, PotItem.Bomb, 'PoD Sexy Statue'), Pot(146, 21, PotItem.Bomb, 'PoD Map Balcony'), Pot(170, 21, PotItem.FiveArrows, 'PoD Map Balcony'), Pot(146, 22, PotItem.Bomb, 'PoD Map Balcony'), Pot(44, 7, PotItem.Bomb, 'PoD Sexy Statue'), Pot(146, 21, PotItem.Bomb, 'PoD Map Balcony'), Pot(170, 21, PotItem.FiveArrows, 'PoD Map Balcony'), Pot(146, 22, PotItem.Bomb, 'PoD Map Balcony'),
Pot(170, 22, PotItem.FiveArrows, 'PoD Map Balcony')], Pot(170, 22, PotItem.FiveArrows, 'PoD Map Balcony')],
44: [Pot(108, 24, PotItem.Heart, 'Hookshot Cave'), Pot(112, 24, PotItem.Heart, 'Hookshot Cave')], 44: [Pot(108, 24, PotItem.Heart, 'Hookshot Cave (Middle)'), Pot(112, 24, PotItem.Heart, 'Hookshot Cave (Middle)')],
47: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (top)'), 47: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (top)'),
Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')], Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')],
49: [Pot(92, 28, PotItem.Bomb, 'Hera Beetles'), Pot(96, 28, PotItem.Nothing, 'Hera Beetles')], 49: [Pot(92, 28, PotItem.Bomb, 'Hera Beetles'), Pot(96, 28, PotItem.Nothing, 'Hera Beetles')],
@@ -66,8 +66,8 @@ vanilla_pots = {
55: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')], 55: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')],
56: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')], 56: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')],
57: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')], 57: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')],
60: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave'), Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave'), Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave'), Pot(20, 19, PotItem.Nothing, 'Hookshot Cave'), 60: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave (Front)'), Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave (Front)'), Pot(20, 19, PotItem.Nothing, 'Hookshot Cave (Front)'),
Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave'), Pot(96, 19, PotItem.Heart, 'Hookshot Cave'), Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave'), Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave')], Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(96, 19, PotItem.Heart, 'Hookshot Cave (Front)'), Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave (Front)')],
61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'), 61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'),
Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')], Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')],
62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')], 62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')],

View File

@@ -190,8 +190,11 @@ def create_regions(world, player):
create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']), create_cave_region(player, 'Superbunny Cave (Top)', 'a connector', ['Superbunny Cave - Top', 'Superbunny Cave - Bottom'], ['Superbunny Cave Exit (Top)']),
create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']), create_cave_region(player, 'Superbunny Cave (Bottom)', 'a connector', None, ['Superbunny Cave Climb', 'Superbunny Cave Exit (Bottom)']),
create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']), create_cave_region(player, 'Spike Cave', 'Spike Cave', ['Spike Cave']),
create_cave_region(player, 'Hookshot Cave', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'], create_cave_region(player, 'Hookshot Cave (Front)', 'a connector', ['Hookshot Cave - Top Right', 'Hookshot Cave - Top Left', 'Hookshot Cave - Bottom Right', 'Hookshot Cave - Bottom Left'],
['Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)']), ['Hookshot Cave Front to Middle', 'Hookshot Cave Front Exit']),
create_cave_region(player, 'Hookshot Cave (Back)', 'a connector', None, ['Hookshot Cave Back to Middle', 'Hookshot Cave Back Exit']),
create_cave_region(player, 'Hookshot Cave (Middle)', 'a connector', None, ['Hookshot Cave Middle to Back', 'Hookshot Cave Middle to Front']),
create_dw_region(player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']), create_dw_region(player, 'Death Mountain Floating Island (Dark World)', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot']),
create_lw_region(player, 'Death Mountain Floating Island (Light World)', ['Floating Island']), create_lw_region(player, 'Death Mountain Floating Island (Light World)', ['Floating Island']),
create_dw_region(player, 'Turtle Rock (Top)', None, ['Turtle Rock Drop']), create_dw_region(player, 'Turtle Rock (Top)', None, ['Turtle Rock Drop']),

9
Rom.py
View File

@@ -1049,7 +1049,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_bytes(0x184000, [ rom.write_bytes(0x184000, [
# original_item, limit, replacement_item, filler # original_item, limit, replacement_item, filler
0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees 0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees
0x51, 0x06, 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade 0x51, 0x00 if world.bomblogic[player] else 0x06, 0x31 if world.bomblogic[player] else 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade. If bomblogic -> turns into Bombs (10)
0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade 0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade
0x58, 0x01, 0x36 if world.retro[player] else 0x43, 0xFF, # silver arrows -> single arrow (red 20 in retro mode) 0x58, 0x01, 0x36 if world.retro[player] else 0x43, 0xFF, # silver arrows -> single arrow (red 20 in retro mode)
0x3E, difficulty.boss_heart_container_limit, 0x47, 0xff, # boss heart -> green 20 0x3E, difficulty.boss_heart_container_limit, 0x47, 0xff, # boss heart -> green 20
@@ -1186,7 +1186,10 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
equip[0x36C] = 0x18 equip[0x36C] = 0x18
equip[0x36D] = 0x18 equip[0x36D] = 0x18
equip[0x379] = 0x68 equip[0x379] = 0x68
starting_max_bombs = 10 if world.bomblogic[player]:
starting_max_bombs = 0
else:
starting_max_bombs = 10
starting_max_arrows = 30 starting_max_arrows = 30
startingstate = CollectionState(world) startingstate = CollectionState(world)
@@ -1478,7 +1481,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_bytes(0x180188, [0, 0, 10]) # Zelda respawn refills (magic, bombs, arrows) rom.write_bytes(0x180188, [0, 0, 10]) # Zelda respawn refills (magic, bombs, arrows)
rom.write_bytes(0x18018B, [0, 0, 10]) # Mantle respawn refills (magic, bombs, arrows) rom.write_bytes(0x18018B, [0, 0, 10]) # Mantle respawn refills (magic, bombs, arrows)
bow_max, bow_small = 70, 10 bow_max, bow_small = 70, 10
elif uncle_location.item is not None and uncle_location.item.name in ['Bombs (10)']: elif uncle_location.item is not None and uncle_location.item.name in ['Bomb Upgrade (+10)' if world.bomblogic[player] else 'Bombs (10)']:
rom.write_byte(0x18004E, 2) # Escape Fill (bombs) rom.write_byte(0x18004E, 2) # Escape Fill (bombs)
rom.write_bytes(0x180185, [0, 50, 0]) # Uncle respawn refills (magic, bombs, arrows) rom.write_bytes(0x180185, [0, 50, 0]) # Uncle respawn refills (magic, bombs, arrows)
rom.write_bytes(0x180188, [0, 3, 0]) # Zelda respawn refills (magic, bombs, arrows) rom.write_bytes(0x180188, [0, 3, 0]) # Zelda respawn refills (magic, bombs, arrows)

View File

@@ -561,7 +561,8 @@ def global_rules(world, player):
def bomb_rules(world, player): def bomb_rules(world, player):
bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended. bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended.
bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave', bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave',
'Hookshot Cave Exit (South)', 'Hookshot Cave Exit (North)', 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery'] 'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front','Hookshot Cave Middle to Back',
'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery']
for entrance in bonkable_doors: for entrance in bonkable_doors:
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
for entrance in bombable_doors: for entrance in bombable_doors:
@@ -576,9 +577,10 @@ def bomb_rules(world, player):
for location in bombable_items: for location in bombable_items:
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player)) add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player))
cave_kill_locations = ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right', 'Mini Moldorm Cave - Generous Guy'] cave_kill_locations = ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right', 'Mini Moldorm Cave - Generous Guy', 'Spiral Cave']
for location in cave_kill_locations: for location in cave_kill_locations:
add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player)) add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player))
add_rule(world.get_entrance('Spiral Cave (top to bottom)', player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player))
paradox_switch_chests = ['Paradox Cave Lower - Far Left', 'Paradox Cave Lower - Left', 'Paradox Cave Lower - Right', 'Paradox Cave Lower - Far Right', 'Paradox Cave Lower - Middle'] paradox_switch_chests = ['Paradox Cave Lower - Far Left', 'Paradox Cave Lower - Left', 'Paradox Cave Lower - Right', 'Paradox Cave Lower - Far Right', 'Paradox Cave Lower - Middle']
for location in paradox_switch_chests: for location in paradox_switch_chests:
@@ -1160,7 +1162,7 @@ def standard_rules(world, player):
def bomb_escape_rule(): def bomb_escape_rule():
loc = world.get_location("Link's Uncle", player) loc = world.get_location("Link's Uncle", player)
return loc.item and loc.item.name == 'Bombs (10)' return loc.item and loc.item.name in ['Bomb Upgrade (+10)' if world.bomblogic[player] else 'Bombs (10)']
def standard_escape_rule(state): def standard_escape_rule(state):
return state.can_kill_most_things(player) or bomb_escape_rule() return state.can_kill_most_things(player) or bomb_escape_rule()
@@ -1671,7 +1673,7 @@ def set_bunny_rules(world, player, inverted):
# regions for the exits of multi-entrace caves/drops that bunny cannot pass # regions for the exits of multi-entrace caves/drops that bunny cannot pass
# Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing. # Note spiral cave may be technically passible, but it would be too absurd to require since OHKO mode is a thing.
bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave', bunny_impassable_caves = ['Bumper Cave', 'Two Brothers House', 'Hookshot Cave (Middle)',
'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)'] 'Pyramid', 'Spiral Cave (Top)', 'Fairy Ascension Cave (Drop)']
bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree', bunny_accessible_locations = ['Link\'s Uncle', 'Sahasrahla', 'Sick Kid', 'Lost Woods Hideout', 'Lumberjack Tree',
'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid',

View File

@@ -220,6 +220,10 @@
"type": "bool", "type": "bool",
"help": "suppress" "help": "suppress"
}, },
"bomblogic": {
"action": "store_true",
"type": "bool"
},
"retro": { "retro": {
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"

View File

@@ -264,6 +264,7 @@
"and a few other little things make this more like Zelda-1. (default: %(default)s)" "and a few other little things make this more like Zelda-1. (default: %(default)s)"
], ],
"pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s"], "pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s"],
"bomblogic": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
"startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ], "startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ],
"usestartinventory": [ "Toggle usage of Starting Inventory." ], "usestartinventory": [ "Toggle usage of Starting Inventory." ],
"custom": [ "Not supported." ], "custom": [ "Not supported." ],

View File

@@ -190,6 +190,7 @@
"randomizer.item.hints": "Include Helpful Hints", "randomizer.item.hints": "Include Helpful Hints",
"randomizer.item.retro": "Retro mode (universal keys)", "randomizer.item.retro": "Retro mode (universal keys)",
"randomizer.item.pseudoboots": "Start with Pseudo Boots", "randomizer.item.pseudoboots": "Start with Pseudo Boots",
"randomizer.item.bomblogic": "Bomblogic",
"randomizer.item.worldstate": "World State", "randomizer.item.worldstate": "World State",
"randomizer.item.worldstate.standard": "Standard", "randomizer.item.worldstate.standard": "Standard",

View File

@@ -1,6 +1,7 @@
{ {
"checkboxes": { "checkboxes": {
"retro": { "type": "checkbox" }, "retro": { "type": "checkbox" },
"bomblogic": { "type": "checkbox" },
"shopsanity": { "type": "checkbox" }, "shopsanity": { "type": "checkbox" },
"hints": { "hints": {
"type": "checkbox" "type": "checkbox"

View File

@@ -57,6 +57,7 @@ SETTINGSTOPROCESS = {
"item": { "item": {
"hints": "hints", "hints": "hints",
"retro": "retro", "retro": "retro",
"bomblogic": "bomblogic",
"shopsanity": "shopsanity", "shopsanity": "shopsanity",
"pseudoboots": "pseudoboots", "pseudoboots": "pseudoboots",
"worldstate": "mode", "worldstate": "mode",