Individual settings: map/compass/key/bk shuffle

This commit is contained in:
Bonta-kun 2019-12-16 21:46:47 +01:00
parent dc26dfce77
commit 1315eb55cf
8 changed files with 69 additions and 65 deletions

View File

@ -63,10 +63,10 @@ class World(object):
self.quickswap = quickswap self.quickswap = quickswap
self.fastmenu = fastmenu self.fastmenu = fastmenu
self.disable_music = disable_music self.disable_music = disable_music
self.mapshuffle = False self.mapshuffle = {player: False for player in range(1, players + 1)}
self.compassshuffle = False self.compassshuffle = {player: False for player in range(1, players + 1)}
self.keyshuffle = False self.keyshuffle = {player: False for player in range(1, players + 1)}
self.bigkeyshuffle = False self.bigkeyshuffle = {player: False for player in range(1, players + 1)}
self.retro = retro self.retro = retro
self.custom = custom self.custom = custom
self.customitemarray = customitemarray self.customitemarray = customitemarray
@ -364,7 +364,7 @@ class CollectionState(object):
checked_locations = 0 checked_locations = 0
while new_locations: while new_locations:
reachable_events = [location for location in locations if location.event and reachable_events = [location for location in locations if location.event and
(not key_only or (not self.world.keyshuffle and location.item.smallkey) or (not self.world.bigkeyshuffle and location.item.bigkey)) (not key_only or (not self.world.keyshuffle[location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[location.item.player] and location.item.bigkey))
and location.can_reach(self)] and location.can_reach(self)]
for event in reachable_events: for event in reachable_events:
if (event.name, event.player) not in self.events: if (event.name, event.player) not in self.events:
@ -685,10 +685,10 @@ class Region(object):
return False return False
def can_fill(self, item): def can_fill(self, item):
inside_dungeon_item = ((item.smallkey and not self.world.keyshuffle) inside_dungeon_item = ((item.smallkey and not self.world.keyshuffle[item.player])
or (item.bigkey and not self.world.bigkeyshuffle) or (item.bigkey and not self.world.bigkeyshuffle[item.player])
or (item.map and not self.world.mapshuffle) or (item.map and not self.world.mapshuffle[item.player])
or (item.compass and not self.world.compassshuffle)) or (item.compass and not self.world.compassshuffle[item.player]))
sewer_hack = self.world.mode[item.player] == 'standard' and item.name == 'Small Key (Escape)' sewer_hack = self.world.mode[item.player] == 'standard' and item.name == 'Small Key (Escape)'
if sewer_hack or inside_dungeon_item: if sewer_hack or inside_dungeon_item:
return self.dungeon and self.dungeon.is_dungeon_item(item) and item.player == self.player return self.dungeon and self.dungeon.is_dungeon_item(item) and item.player == self.player
@ -1095,10 +1095,10 @@ class Spoiler(object):
outfile.write('Accessibility: %s\n' % self.metadata['accessibility']) outfile.write('Accessibility: %s\n' % self.metadata['accessibility'])
outfile.write('L\\R Quickswap enabled: %s\n' % ('Yes' if self.world.quickswap else 'No')) outfile.write('L\\R Quickswap enabled: %s\n' % ('Yes' if self.world.quickswap else 'No'))
outfile.write('Menu speed: %s\n' % self.world.fastmenu) outfile.write('Menu speed: %s\n' % self.world.fastmenu)
outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'] else 'No')) outfile.write('Map shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['mapshuffle'].items()})
outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'] else 'No')) outfile.write('Compass shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['compassshuffle'].items()})
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'] else 'No')) outfile.write('Small Key shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['keyshuffle'].items()})
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'] else 'No')) outfile.write('Big Key shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['bigkeyshuffle'].items()})
outfile.write('Players: %d' % self.world.players) outfile.write('Players: %d' % self.world.players)
if self.entrances: if self.entrances:
outfile.write('\n\nEntrances:\n\n') outfile.write('\n\nEntrances:\n\n')

View File

@ -136,16 +136,16 @@ def fill_dungeons_restrictive(world, shuffled_locations):
# with shuffled dungeon items they are distributed as part of the normal item pool # with shuffled dungeon items they are distributed as part of the normal item pool
for item in world.get_items(): for item in world.get_items():
if (item.smallkey and world.keyshuffle) or (item.bigkey and world.bigkeyshuffle): if (item.smallkey and world.keyshuffle[item.player]) or (item.bigkey and world.bigkeyshuffle[item.player]):
all_state_base.collect(item, True) all_state_base.collect(item, True)
item.advancement = True item.advancement = True
elif (item.map and world.mapshuffle) or (item.compass and world.compassshuffle): elif (item.map and world.mapshuffle[item.player]) or (item.compass and world.compassshuffle[item.player]):
item.priority = True item.priority = True
dungeon_items = [item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle) dungeon_items = [item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle[item.player])
or (item.bigkey and not world.bigkeyshuffle) or (item.bigkey and not world.bigkeyshuffle[item.player])
or (item.map and not world.mapshuffle) or (item.map and not world.mapshuffle[item.player])
or (item.compass and not world.compassshuffle))] or (item.compass and not world.compassshuffle[item.player]))]
# sort in the order Big Key, Small Key, Other before placing dungeon items # sort in the order Big Key, Small Key, Other before placing dungeon items
sort_order = {"BigKey": 3, "SmallKey": 2} sort_order = {"BigKey": 3, "SmallKey": 2}

View File

@ -278,7 +278,9 @@ def parse_arguments(argv, no_defaults=False):
for player in range(1, multiargs.multi + 1): for player in range(1, multiargs.multi + 1):
playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True) playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True)
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid']: for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1: if player == 1:
setattr(ret, name, {1: value}) setattr(ret, name, {1: value})

View File

@ -243,8 +243,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
fill_locations.reverse() fill_locations.reverse()
# Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots # Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots
if world.keyshuffle: progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.mode[item.player] == 'standard' and world.keyshuffle[item.player] else 0)
progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.mode[item.player] == 'standard' else 0)
fill_restrictive(world, world.state, fill_locations, progitempool) fill_restrictive(world, world.state, fill_locations, progitempool)
@ -355,7 +354,7 @@ def balance_multiworld_progression(world):
candidate_items = [] candidate_items = []
while True: while True:
for location in balancing_sphere: for location in balancing_sphere:
if location.event and (world.keyshuffle or not location.item.smallkey) and (world.bigkeyshuffle or not location.item.bigkey): if location.event and (world.keyshuffle[location.item.player] or not location.item.smallkey) and (world.bigkeyshuffle[location.item.player] or not location.item.bigkey):
balancing_state.collect(location.item, True, location) balancing_state.collect(location.item, True, location)
if location.item.player in balancing_players and not location.locked: if location.item.player in balancing_players and not location.locked:
candidate_items.append(location) candidate_items.append(location)
@ -411,7 +410,7 @@ def balance_multiworld_progression(world):
sphere_locations.append(location) sphere_locations.append(location)
for location in sphere_locations: for location in sphere_locations:
if location.event and (world.keyshuffle or not location.item.smallkey) and (world.bigkeyshuffle or not location.item.bigkey): if location.event and (world.keyshuffle[location.item.player] or not location.item.smallkey) and (world.bigkeyshuffle[location.item.player] or not location.item.bigkey):
state.collect(location.item, True, location) state.collect(location.item, True, location)
checked_locations.extend(sphere_locations) checked_locations.extend(sphere_locations)

View File

@ -219,10 +219,10 @@ def generate_itempool(world, player):
world.treasure_hunt_icon = treasure_hunt_icon world.treasure_hunt_icon = treasure_hunt_icon
world.itempool.extend([item for item in get_dungeon_item_pool(world) if item.player == player world.itempool.extend([item for item in get_dungeon_item_pool(world) if item.player == player
and ((item.smallkey and world.keyshuffle) and ((item.smallkey and world.keyshuffle[player])
or (item.bigkey and world.bigkeyshuffle) or (item.bigkey and world.bigkeyshuffle[player])
or (item.map and world.mapshuffle) or (item.map and world.mapshuffle[player])
or (item.compass and world.compassshuffle))]) or (item.compass and world.compassshuffle[player]))])
# logic has some branches where having 4 hearts is one possible requirement (of several alternatives) # logic has some branches where having 4 hearts is one possible requirement (of several alternatives)
# rather than making all hearts/heart pieces progression items (which slows down generation considerably) # rather than making all hearts/heart pieces progression items (which slows down generation considerably)

39
Main.py
View File

@ -34,19 +34,10 @@ def main(args, seed=None):
world.seed = int(seed) world.seed = int(seed)
random.seed(world.seed) random.seed(world.seed)
world.mapshuffle = args.mapshuffle world.mapshuffle = args.mapshuffle.copy()
world.compassshuffle = args.compassshuffle world.compassshuffle = args.compassshuffle.copy()
world.keyshuffle = args.keyshuffle world.keyshuffle = args.keyshuffle.copy()
world.bigkeyshuffle = args.bigkeyshuffle world.bigkeyshuffle = args.bigkeyshuffle.copy()
mcsb_name = ''
if all([world.mapshuffle, world.compassshuffle, world.keyshuffle, world.bigkeyshuffle]):
mcsb_name = '-keysanity'
elif [world.mapshuffle, world.compassshuffle, world.keyshuffle, world.bigkeyshuffle].count(True) == 1:
mcsb_name = '-mapshuffle' if world.mapshuffle else '-compassshuffle' if world.compassshuffle else '-keyshuffle' if world.keyshuffle else '-bigkeyshuffle'
elif any([world.mapshuffle, world.compassshuffle, world.keyshuffle, world.bigkeyshuffle]):
mcsb_name = '-%s%s%s%sshuffle' % ('M' if world.mapshuffle else '', 'C' if world.compassshuffle else '', 'S' if world.keyshuffle else '', 'B' if world.bigkeyshuffle else '')
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.open_pyramid = args.openpyramid.copy() world.open_pyramid = args.openpyramid.copy()
@ -94,7 +85,8 @@ def main(args, seed=None):
logger.info('Placing Dungeon Items.') logger.info('Placing Dungeon Items.')
shuffled_locations = None shuffled_locations = None
if args.algorithm in ['balanced', 'vt26'] or args.mapshuffle or args.compassshuffle or args.keyshuffle or args.bigkeyshuffle: if args.algorithm in ['balanced', 'vt26'] or any(list(args.mapshuffle.values()) + list(args.compassshuffle.values()) +
list(args.keyshuffle.values()) + list(args.bigkeyshuffle.values())):
shuffled_locations = world.get_unfilled_locations() shuffled_locations = world.get_unfilled_locations()
random.shuffle(shuffled_locations) random.shuffle(shuffled_locations)
fill_dungeons_restrictive(world, shuffled_locations) fill_dungeons_restrictive(world, shuffled_locations)
@ -182,6 +174,17 @@ def main(args, seed=None):
rom.write_bytes(int(addr), values) rom.write_bytes(int(addr), values)
apply_rom_settings(rom, args.heartbeep, args.heartcolor, world.quickswap, world.fastmenu, world.disable_music, sprite, player_names) apply_rom_settings(rom, args.heartbeep, args.heartcolor, world.quickswap, world.fastmenu, world.disable_music, sprite, player_names)
mcsb_name = ''
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player], world.bigkeyshuffle[player]]):
mcsb_name = '-keysanity'
elif [world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player], world.bigkeyshuffle[player]].count(True) == 1:
mcsb_name = '-mapshuffle' if world.mapshuffle[player] else '-compassshuffle' if world.compassshuffle[player] else '-keyshuffle' if world.keyshuffle[player] else '-bigkeyshuffle'
elif any([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player], world.bigkeyshuffle[player]]):
mcsb_name = '-%s%s%s%sshuffle' % (
'M' if world.mapshuffle[player] else '', 'C' if world.compassshuffle[player] else '',
'S' if world.keyshuffle[player] else '', 'B' if world.bigkeyshuffle[player] else '')
outfilesuffix = ('%s%s_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' % (f'_P{player}' if world.players > 1 else '', outfilesuffix = ('%s%s_%s_%s-%s-%s-%s%s_%s-%s%s%s%s%s' % (f'_P{player}' if world.players > 1 else '',
f'_{player_names[player]}' if player in player_names else '', f'_{player_names[player]}' if player in player_names else '',
world.logic[player], world.difficulty[player], world.difficulty_adjustments[player], world.logic[player], world.difficulty[player], world.difficulty_adjustments[player],
@ -235,10 +238,10 @@ def copy_world(world):
ret.difficulty_requirements = world.difficulty_requirements.copy() ret.difficulty_requirements = world.difficulty_requirements.copy()
ret.fix_fake_world = world.fix_fake_world ret.fix_fake_world = world.fix_fake_world
ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms
ret.mapshuffle = world.mapshuffle ret.mapshuffle = world.mapshuffle.copy()
ret.compassshuffle = world.compassshuffle ret.compassshuffle = world.compassshuffle.copy()
ret.keyshuffle = world.keyshuffle ret.keyshuffle = world.keyshuffle.copy()
ret.bigkeyshuffle = world.bigkeyshuffle ret.bigkeyshuffle = world.bigkeyshuffle.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.open_pyramid = world.open_pyramid.copy() ret.open_pyramid = world.open_pyramid.copy()

34
Rom.py
View File

@ -490,14 +490,14 @@ def patch_rom(world, player, rom, enemized):
# patch music # patch music
music_addresses = dungeon_music_addresses[location.name] music_addresses = dungeon_music_addresses[location.name]
if world.mapshuffle: if world.mapshuffle[player]:
music = random.choice([0x11, 0x16]) music = random.choice([0x11, 0x16])
else: else:
music = 0x11 if 'Pendant' in location.item.name else 0x16 music = 0x11 if 'Pendant' in location.item.name else 0x16
for music_address in music_addresses: for music_address in music_addresses:
rom.write_byte(music_address, music) rom.write_byte(music_address, music)
if world.mapshuffle: if world.mapshuffle[player]:
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
# patch entrance/exits/holes # patch entrance/exits/holes
@ -839,7 +839,7 @@ def patch_rom(world, player, rom, enemized):
ERtimeincrease = 10 ERtimeincrease = 10
else: else:
ERtimeincrease = 20 ERtimeincrease = 20
if world.keyshuffle or world.bigkeyshuffle or world.mapshuffle: if world.keyshuffle[player] or world.bigkeyshuffle[player] or world.mapshuffle[player]:
ERtimeincrease = ERtimeincrease + 15 ERtimeincrease = ERtimeincrease + 15
if world.clock_mode == 'off': if world.clock_mode == 'off':
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
@ -956,24 +956,24 @@ def patch_rom(world, player, rom, enemized):
rom.write_byte(0x18005F, world.crystals_needed_for_ganon[player]) rom.write_byte(0x18005F, world.crystals_needed_for_ganon[player])
rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" else 0x00) # block HC upstairs doors in rain state in standard mode rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" else 0x00) # block HC upstairs doors in rain state in standard mode
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.keyshuffle else 0x00) rom.write_byte(0x18016A, 0x10 | ((0x01 if world.keyshuffle[player] else 0x00)
| (0x02 if world.compassshuffle else 0x00) | (0x02 if world.compassshuffle[player] else 0x00)
| (0x04 if world.mapshuffle else 0x00) | (0x04 if world.mapshuffle[player] else 0x00)
| (0x08 if world.bigkeyshuffle else 0x00))) # free roaming item text boxes | (0x08 if world.bigkeyshuffle[player] else 0x00))) # free roaming item text boxes
rom.write_byte(0x18003B, 0x01 if world.mapshuffle else 0x00) # maps showing crystals on overworld rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
# compasses showing dungeon count # compasses showing dungeon count
if world.clock_mode != 'off': if world.clock_mode != 'off':
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
elif world.compassshuffle: elif world.compassshuffle[player]:
rom.write_byte(0x18003C, 0x01) # show on pickup rom.write_byte(0x18003C, 0x01) # show on pickup
else: else:
rom.write_byte(0x18003C, 0x00) rom.write_byte(0x18003C, 0x00)
rom.write_byte(0x180045, ((0x01 if world.keyshuffle else 0x00) rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] else 0x00)
| (0x02 if world.bigkeyshuffle else 0x00) | (0x02 if world.bigkeyshuffle[player] else 0x00)
| (0x04 if world.compassshuffle else 0x00) | (0x04 if world.compassshuffle[player] else 0x00)
| (0x08 if world.mapshuffle else 0x00))) # free roaming items in menu | (0x08 if world.mapshuffle[player] else 0x00))) # free roaming items in menu
# Map reveals # Map reveals
reveal_bytes = { reveal_bytes = {
@ -998,8 +998,8 @@ def patch_rom(world, player, rom, enemized):
return reveal_bytes.get(location.parent_region.dungeon.name, 0x0000) return reveal_bytes.get(location.parent_region.dungeon.name, 0x0000)
return 0x0000 return 0x0000
write_int16(rom, 0x18017A, get_reveal_bytes('Green Pendant') if world.mapshuffle else 0x0000) # Sahasrahla reveal write_int16(rom, 0x18017A, get_reveal_bytes('Green Pendant') if world.mapshuffle[player] else 0x0000) # Sahasrahla reveal
write_int16(rom, 0x18017C, get_reveal_bytes('Crystal 5')|get_reveal_bytes('Crystal 6') if world.mapshuffle else 0x0000) # Bomb Shop Reveal write_int16(rom, 0x18017C, get_reveal_bytes('Crystal 5')|get_reveal_bytes('Crystal 6') if world.mapshuffle[player] else 0x0000) # Bomb Shop Reveal
rom.write_byte(0x180172, 0x01 if world.retro else 0x00) # universal keys rom.write_byte(0x180172, 0x01 if world.retro else 0x00) # universal keys
rom.write_byte(0x180175, 0x01 if world.retro else 0x00) # rupee bow rom.write_byte(0x180175, 0x01 if world.retro else 0x00) # rupee bow
@ -1493,9 +1493,9 @@ def write_strings(rom, world, player):
# Lastly we write hints to show where certain interesting items are. It is done the way it is to re-use the silver code and also to give one hint per each type of item regardless of how many exist. This supports many settings well. # Lastly we write hints to show where certain interesting items are. It is done the way it is to re-use the silver code and also to give one hint per each type of item regardless of how many exist. This supports many settings well.
items_to_hint = RelevantItems.copy() items_to_hint = RelevantItems.copy()
if world.keyshuffle: if world.keyshuffle[player]:
items_to_hint.extend(SmallKeys) items_to_hint.extend(SmallKeys)
if world.bigkeyshuffle: if world.bigkeyshuffle[player]:
items_to_hint.extend(BigKeys) items_to_hint.extend(BigKeys)
random.shuffle(items_to_hint) random.shuffle(items_to_hint)
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8 hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8

View File

@ -804,7 +804,7 @@ def set_trock_key_rules(world, player):
non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left',
'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left',
'Turtle Rock - Eye Bridge - Top Right'] 'Turtle Rock - Eye Bridge - Top Right']
if not world.keyshuffle: if not world.keyshuffle[player]:
non_big_key_locations += ['Turtle Rock - Big Key Chest'] non_big_key_locations += ['Turtle Rock - Big Key Chest']
else: else:
set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 2) if item_in_locations(state, 'Big Key (Turtle Rock)', player, [('Turtle Rock - Compass Chest', player), ('Turtle Rock - Roller Room - Left', player), ('Turtle Rock - Roller Room - Right', player)]) else state.has_key('Small Key (Turtle Rock)', player, 4)) set_rule(world.get_entrance('Turtle Rock (Chain Chomp Room) (South)', player), lambda state: state.has_key('Small Key (Turtle Rock)', player, 2) if item_in_locations(state, 'Big Key (Turtle Rock)', player, [('Turtle Rock - Compass Chest', player), ('Turtle Rock - Roller Room - Left', player), ('Turtle Rock - Roller Room - Right', player)]) else state.has_key('Small Key (Turtle Rock)', player, 4))
@ -814,7 +814,7 @@ def set_trock_key_rules(world, player):
non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left', non_big_key_locations += ['Turtle Rock - Crystaroller Room', 'Turtle Rock - Eye Bridge - Bottom Left',
'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Bottom Right', 'Turtle Rock - Eye Bridge - Top Left',
'Turtle Rock - Eye Bridge - Top Right'] 'Turtle Rock - Eye Bridge - Top Right']
if not world.keyshuffle: if not world.keyshuffle[player]:
non_big_key_locations += ['Turtle Rock - Big Key Chest', 'Turtle Rock - Chain Chomps'] non_big_key_locations += ['Turtle Rock - Big Key Chest', 'Turtle Rock - Chain Chomps']
# set big key restrictions # set big key restrictions