Retro break up of various options
This commit is contained in:
+43
-28
@@ -22,7 +22,7 @@ from source.dungeon.RoomObject import RoomObject
|
|||||||
class World(object):
|
class World(object):
|
||||||
|
|
||||||
def __init__(self, players, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
def __init__(self, players, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
||||||
timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints):
|
timer, progressive, goal, algorithm, accessibility, shuffle_ganon, custom, customitemarray, hints):
|
||||||
self.players = players
|
self.players = players
|
||||||
self.teams = 1
|
self.teams = 1
|
||||||
self.shuffle = shuffle.copy()
|
self.shuffle = shuffle.copy()
|
||||||
@@ -64,7 +64,6 @@ class World(object):
|
|||||||
self.fix_trock_exit = {}
|
self.fix_trock_exit = {}
|
||||||
self.shuffle_ganon = shuffle_ganon
|
self.shuffle_ganon = shuffle_ganon
|
||||||
self.fix_gtower_exit = self.shuffle_ganon
|
self.fix_gtower_exit = self.shuffle_ganon
|
||||||
self.retro = retro.copy()
|
|
||||||
self.custom = custom
|
self.custom = custom
|
||||||
self.customitemarray = customitemarray
|
self.customitemarray = customitemarray
|
||||||
self.can_take_damage = True
|
self.can_take_damage = True
|
||||||
@@ -91,10 +90,6 @@ class World(object):
|
|||||||
self.pot_contents = {}
|
self.pot_contents = {}
|
||||||
|
|
||||||
for player in range(1, players + 1):
|
for player in range(1, players + 1):
|
||||||
# If World State is Retro, set to Open and set Retro flag
|
|
||||||
if self.mode[player] == "retro":
|
|
||||||
self.mode[player] = "open"
|
|
||||||
self.retro[player] = True
|
|
||||||
def set_player_attr(attr, val):
|
def set_player_attr(attr, val):
|
||||||
self.__dict__.setdefault(attr, {})[player] = val
|
self.__dict__.setdefault(attr, {})[player] = val
|
||||||
set_player_attr('_region_cache', {})
|
set_player_attr('_region_cache', {})
|
||||||
@@ -118,10 +113,12 @@ class World(object):
|
|||||||
set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['crossed', 'insanity'])
|
set_player_attr('fix_fake_world', logic[player] not in ['owglitches', 'nologic'] or shuffle[player] in ['crossed', 'insanity'])
|
||||||
set_player_attr('mapshuffle', False)
|
set_player_attr('mapshuffle', False)
|
||||||
set_player_attr('compassshuffle', False)
|
set_player_attr('compassshuffle', False)
|
||||||
set_player_attr('keyshuffle', False)
|
set_player_attr('keyshuffle', 'standard')
|
||||||
set_player_attr('bigkeyshuffle', False)
|
set_player_attr('bigkeyshuffle', False)
|
||||||
set_player_attr('restrict_boss_items', 'none')
|
set_player_attr('restrict_boss_items', 'none')
|
||||||
set_player_attr('bombbag', False)
|
set_player_attr('bombbag', False)
|
||||||
|
set_player_attr('flute_mode', False)
|
||||||
|
set_player_attr('bow_mode', 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')
|
||||||
@@ -134,6 +131,7 @@ class World(object):
|
|||||||
set_player_attr('crystals_ganon_orig', {})
|
set_player_attr('crystals_ganon_orig', {})
|
||||||
set_player_attr('crystals_gt_orig', {})
|
set_player_attr('crystals_gt_orig', {})
|
||||||
set_player_attr('open_pyramid', False)
|
set_player_attr('open_pyramid', False)
|
||||||
|
set_player_attr('take_any', 'none')
|
||||||
set_player_attr('treasure_hunt_icon', 'Triforce Piece')
|
set_player_attr('treasure_hunt_icon', 'Triforce Piece')
|
||||||
set_player_attr('treasure_hunt_count', 0)
|
set_player_attr('treasure_hunt_count', 0)
|
||||||
set_player_attr('treasure_hunt_total', 0)
|
set_player_attr('treasure_hunt_total', 0)
|
||||||
@@ -154,6 +152,11 @@ class World(object):
|
|||||||
set_player_attr('exp_cache', defaultdict(dict))
|
set_player_attr('exp_cache', defaultdict(dict))
|
||||||
set_player_attr('enabled_entrances', {})
|
set_player_attr('enabled_entrances', {})
|
||||||
|
|
||||||
|
def finish_init(self):
|
||||||
|
for player in range(1, self.players + 1):
|
||||||
|
if self.mode[player] == 'retro':
|
||||||
|
self.mode[player] == 'open'
|
||||||
|
|
||||||
def get_name_string_for_object(self, obj):
|
def get_name_string_for_object(self, obj):
|
||||||
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
|
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
|
||||||
|
|
||||||
@@ -375,7 +378,8 @@ class World(object):
|
|||||||
|
|
||||||
def push_precollected(self, item):
|
def push_precollected(self, item):
|
||||||
item.world = self
|
item.world = self
|
||||||
if (item.smallkey and self.keyshuffle[item.player]) or (item.bigkey and self.bigkeyshuffle[item.player]):
|
if ((item.smallkey and self.keyshuffle[item.player] != 'none')
|
||||||
|
or (item.bigkey and self.bigkeyshuffle[item.player])):
|
||||||
item.advancement = True
|
item.advancement = True
|
||||||
self.precollected_items.append(item)
|
self.precollected_items.append(item)
|
||||||
self.state.collect(item, True)
|
self.state.collect(item, True)
|
||||||
@@ -587,7 +591,7 @@ class CollectionState(object):
|
|||||||
if key_logic.sm_doors[door]:
|
if key_logic.sm_doors[door]:
|
||||||
self.reached_doors[player].add(key_logic.sm_doors[door].name)
|
self.reached_doors[player].add(key_logic.sm_doors[door].name)
|
||||||
if not connection.can_reach(self):
|
if not connection.can_reach(self):
|
||||||
checklist_key = 'Universal' if self.world.retro[player] else dungeon_name
|
checklist_key = 'Universal' if self.world.keyshuffle[player] == 'universal' else dungeon_name
|
||||||
checklist = self.dungeons_to_check[player][checklist_key]
|
checklist = self.dungeons_to_check[player][checklist_key]
|
||||||
checklist[connection.name] = (connection, crystal_state)
|
checklist[connection.name] = (connection, crystal_state)
|
||||||
elif door.name not in self.opened_doors[player]:
|
elif door.name not in self.opened_doors[player]:
|
||||||
@@ -759,7 +763,7 @@ class CollectionState(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def set_dungeon_limits(self, player, dungeon_name):
|
def set_dungeon_limits(self, player, dungeon_name):
|
||||||
if self.world.retro[player] and self.world.mode[player] == 'standard':
|
if self.world.keyshuffle[player] == 'universal' and self.world.mode[player] == 'standard':
|
||||||
self.dungeon_limits = ['Hyrule Castle', 'Agahnims Tower']
|
self.dungeon_limits = ['Hyrule Castle', 'Agahnims Tower']
|
||||||
else:
|
else:
|
||||||
self.dungeon_limits = [dungeon_name]
|
self.dungeon_limits = [dungeon_name]
|
||||||
@@ -935,7 +939,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[location.item.player] and location.item.smallkey) or (not self.world.bigkeyshuffle[location.item.player] and location.item.bigkey))
|
(not key_only or (self.world.keyshuffle[location.item.player] == 'none' 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)]
|
||||||
reachable_events = self._do_not_flood_the_keys(reachable_events)
|
reachable_events = self._do_not_flood_the_keys(reachable_events)
|
||||||
for event in reachable_events:
|
for event in reachable_events:
|
||||||
@@ -995,7 +999,7 @@ class CollectionState(object):
|
|||||||
return self.prog_items[item, player] >= count
|
return self.prog_items[item, player] >= count
|
||||||
|
|
||||||
def has_sm_key(self, item, player, count=1):
|
def has_sm_key(self, item, player, count=1):
|
||||||
if self.world.retro[player]:
|
if self.world.keyshuffle[player] == 'universal':
|
||||||
if self.world.mode[player] == 'standard' and self.world.doorShuffle[player] == 'vanilla' and item == 'Small Key (Escape)':
|
if self.world.mode[player] == 'standard' and self.world.doorShuffle[player] == 'vanilla' and item == 'Small Key (Escape)':
|
||||||
return True # Cannot access the shop until escape is finished. This is safe because the key is manually placed in make_custom_item_pool
|
return True # Cannot access the shop until escape is finished. This is safe because the key is manually placed in make_custom_item_pool
|
||||||
return self.can_buy_unlimited('Small Key (Universal)', player)
|
return self.can_buy_unlimited('Small Key (Universal)', player)
|
||||||
@@ -1091,7 +1095,7 @@ class CollectionState(object):
|
|||||||
or self.has('Cane of Somaria', player))
|
or self.has('Cane of Somaria', player))
|
||||||
|
|
||||||
def can_shoot_arrows(self, player):
|
def can_shoot_arrows(self, player):
|
||||||
if self.world.retro[player]:
|
if self.world.bow_mode[player] in ['retro', 'retro_silvers']:
|
||||||
#todo: Non-progressive silvers grant wooden arrows, but progressive bows do not. Always require shop arrows to be safe
|
#todo: Non-progressive silvers grant wooden arrows, but progressive bows do not. Always require shop arrows to be safe
|
||||||
return self.has('Bow', player) and (self.can_buy_unlimited('Single Arrow', player) or self.has('Single Arrow', player))
|
return self.has('Bow', player) and (self.can_buy_unlimited('Single Arrow', player) or self.has('Single Arrow', player))
|
||||||
return self.has('Bow', player)
|
return self.has('Bow', player)
|
||||||
@@ -1373,7 +1377,7 @@ 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[item.player])
|
inside_dungeon_item = ((item.smallkey and self.world.keyshuffle[item.player] == 'none')
|
||||||
or (item.bigkey and not self.world.bigkeyshuffle[item.player])
|
or (item.bigkey and not self.world.bigkeyshuffle[item.player])
|
||||||
or (item.map and not self.world.mapshuffle[item.player])
|
or (item.map and not self.world.mapshuffle[item.player])
|
||||||
or (item.compass and not self.world.compassshuffle[item.player]))
|
or (item.compass and not self.world.compassshuffle[item.player]))
|
||||||
@@ -2239,7 +2243,7 @@ class Item(object):
|
|||||||
return item_dungeon
|
return item_dungeon
|
||||||
|
|
||||||
def is_inside_dungeon_item(self, world):
|
def is_inside_dungeon_item(self, world):
|
||||||
return ((self.smallkey and not world.keyshuffle[self.player])
|
return ((self.smallkey and world.keyshuffle[self.player] == 'none')
|
||||||
or (self.bigkey and not world.bigkeyshuffle[self.player])
|
or (self.bigkey and not world.bigkeyshuffle[self.player])
|
||||||
or (self.compass and not world.compassshuffle[self.player])
|
or (self.compass and not world.compassshuffle[self.player])
|
||||||
or (self.map and not world.mapshuffle[self.player]))
|
or (self.map and not world.mapshuffle[self.player]))
|
||||||
@@ -2371,15 +2375,16 @@ class Spoiler(object):
|
|||||||
self.metadata = {'version': ERVersion,
|
self.metadata = {'version': ERVersion,
|
||||||
'logic': self.world.logic,
|
'logic': self.world.logic,
|
||||||
'mode': self.world.mode,
|
'mode': self.world.mode,
|
||||||
'retro': self.world.retro,
|
|
||||||
'bombbag': self.world.bombbag,
|
'bombbag': self.world.bombbag,
|
||||||
'weapons': self.world.swords,
|
'weapons': self.world.swords,
|
||||||
'flute_mode': self.world.flute_mode,
|
'flute_mode': self.world.flute_mode,
|
||||||
|
'bow_mode': self.world.bow_mode,
|
||||||
'goal': self.world.goal,
|
'goal': self.world.goal,
|
||||||
'shuffle': self.world.shuffle,
|
'shuffle': self.world.shuffle,
|
||||||
'shuffleganon': self.world.shuffle_ganon,
|
'shuffleganon': self.world.shuffle_ganon,
|
||||||
'shufflelinks': self.world.shufflelinks,
|
'shufflelinks': self.world.shufflelinks,
|
||||||
'shuffletavern': self.world.shuffletavern,
|
'shuffletavern': self.world.shuffletavern,
|
||||||
|
'take_any': self.world.take_any,
|
||||||
'overworld_map': self.world.overworld_map,
|
'overworld_map': self.world.overworld_map,
|
||||||
'door_shuffle': self.world.doorShuffle,
|
'door_shuffle': self.world.doorShuffle,
|
||||||
'intensity': self.world.intensity,
|
'intensity': self.world.intensity,
|
||||||
@@ -2561,7 +2566,6 @@ class Spoiler(object):
|
|||||||
outfile.write(f'Settings Code: {self.metadata["code"][player]}\n')
|
outfile.write(f'Settings Code: {self.metadata["code"][player]}\n')
|
||||||
outfile.write('Logic: %s\n' % self.metadata['logic'][player])
|
outfile.write('Logic: %s\n' % self.metadata['logic'][player])
|
||||||
outfile.write('Mode: %s\n' % self.metadata['mode'][player])
|
outfile.write('Mode: %s\n' % self.metadata['mode'][player])
|
||||||
outfile.write('Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No'))
|
|
||||||
outfile.write('Swords: %s\n' % self.metadata['weapons'][player])
|
outfile.write('Swords: %s\n' % self.metadata['weapons'][player])
|
||||||
outfile.write('Goal: %s\n' % self.metadata['goal'][player])
|
outfile.write('Goal: %s\n' % self.metadata['goal'][player])
|
||||||
if self.metadata['goal'][player] in ['triforcehunt', 'trinity']:
|
if self.metadata['goal'][player] in ['triforcehunt', 'trinity']:
|
||||||
@@ -2574,6 +2578,7 @@ class Spoiler(object):
|
|||||||
outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player])
|
outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player])
|
||||||
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
||||||
outfile.write(f"Flute Mode: {self.metadata['flute_mode'][player]}\n")
|
outfile.write(f"Flute Mode: {self.metadata['flute_mode'][player]}\n")
|
||||||
|
outfile.write(f"Bow Mode: {self.metadata['bow_mode'][player]}\n")
|
||||||
outfile.write(f"Shopsanity: {yn(self.metadata['shopsanity'][player])}\n")
|
outfile.write(f"Shopsanity: {yn(self.metadata['shopsanity'][player])}\n")
|
||||||
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
|
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
|
||||||
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
|
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
|
||||||
@@ -2583,6 +2588,8 @@ class Spoiler(object):
|
|||||||
outfile.write(f"Back of Tavern Shuffled: {yn(self.metadata['shuffletavern'][player])}\n")
|
outfile.write(f"Back of Tavern Shuffled: {yn(self.metadata['shuffletavern'][player])}\n")
|
||||||
outfile.write(f"GT/Ganon Shuffled: {yn(self.metadata['shuffleganon'])}\n")
|
outfile.write(f"GT/Ganon Shuffled: {yn(self.metadata['shuffleganon'])}\n")
|
||||||
outfile.write(f"Overworld Map: {self.metadata['overworld_map'][player]}\n")
|
outfile.write(f"Overworld Map: {self.metadata['overworld_map'][player]}\n")
|
||||||
|
outfile.write(f"Take Any Caves: {self.metadata['take_any'][player]}\n")
|
||||||
|
outfile.write(f"Overworld Map: {self.metadata['overworld_map'][player]}\n")
|
||||||
if self.metadata['goal'][player] != 'trinity':
|
if self.metadata['goal'][player] != 'trinity':
|
||||||
outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No'))
|
outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No'))
|
||||||
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
|
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
|
||||||
@@ -2597,7 +2604,7 @@ class Spoiler(object):
|
|||||||
outfile.write(f"Pot Shuffle (Legacy): {yn(self.metadata['potshuffle'][player])}\n")
|
outfile.write(f"Pot Shuffle (Legacy): {yn(self.metadata['potshuffle'][player])}\n")
|
||||||
outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
|
outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
|
||||||
outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'][player] else 'No'))
|
outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'][player] else 'No'))
|
||||||
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
|
outfile.write(f"Small Key shuffle: {self.metadata['keyshuffle'][player]}\n")
|
||||||
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
||||||
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
||||||
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'][player])
|
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'][player])
|
||||||
@@ -2835,7 +2842,7 @@ dr_mode = {"basic": 1, "crossed": 2, "vanilla": 0, "partitioned": 3}
|
|||||||
er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4, "insanity": 5, 'lite': 8,
|
er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4, "insanity": 5, 'lite': 8,
|
||||||
'lean': 9, "dungeonsfull": 7, "dungeonssimple": 6}
|
'lean': 9, "dungeonsfull": 7, "dungeonssimple": 6}
|
||||||
|
|
||||||
# byte 1: LLLW WSSR (logic, mode, sword, retro)
|
# byte 1: LLLW WSS? (logic, mode, sword)
|
||||||
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
||||||
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
world_mode = {"open": 0, "standard": 1, "inverted": 2}
|
||||||
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
|
||||||
@@ -2861,7 +2868,7 @@ counter_mode = {"default": 0, "off": 1, "on": 2, "pickup": 3}
|
|||||||
# byte 6: CCCC CPAA (crystals ganon, pyramid, access
|
# byte 6: CCCC CPAA (crystals ganon, pyramid, access
|
||||||
access_mode = {"items": 0, "locations": 1, "none": 2}
|
access_mode = {"items": 0, "locations": 1, "none": 2}
|
||||||
|
|
||||||
# byte 7: BSMC DDEE (big, small, maps, compass, door_type, enemies)
|
# byte 7: B?MC DDEE (big, ?, maps, compass, door_type, enemies)
|
||||||
door_type_mode = {'original': 0, 'big': 1, 'all': 2, 'chaos': 3}
|
door_type_mode = {'original': 0, 'big': 1, 'all': 2, 'chaos': 3}
|
||||||
enemy_mode = {"none": 0, "shuffled": 1, "chaos": 2, "random": 2, "legacy": 3}
|
enemy_mode = {"none": 0, "shuffled": 1, "chaos": 2, "random": 2, "legacy": 3}
|
||||||
|
|
||||||
@@ -2878,15 +2885,18 @@ boss_mode = {"none": 0, "simple": 1, "full": 2, "chaos": 3, 'random': 3, 'unique
|
|||||||
|
|
||||||
|
|
||||||
# byte 10: settings_version
|
# byte 10: settings_version
|
||||||
# byte 11: F???, ???? (flute_mode)
|
# byte 11: FBBB, TTSS (flute_mode, bow_mode, take_any, small_key_mode)
|
||||||
flute_mode = {'normal': 0, 'active': 1}
|
flute_mode = {'normal': 0, 'active': 1}
|
||||||
|
keyshuffle_mode = {'none': 0, 'wild': 1, 'universal': 2} # reserved 8 modes?
|
||||||
|
take_any_mode = {'none': 0, 'random': 1, 'fixed': 2}
|
||||||
|
bow_mode = {'progressive': 0, 'silvers': 1, 'retro': 2, 'retro_silver': 3}
|
||||||
|
|
||||||
# additions
|
# additions
|
||||||
# psuedoboots does not effect code
|
# psuedoboots does not effect code
|
||||||
# sfx_shuffle and other adjust items does not effect settings code
|
# sfx_shuffle and other adjust items does not effect settings code
|
||||||
|
|
||||||
# Bump this when making changes that are not backwards compatible (nearly all of them)
|
# Bump this when making changes that are not backwards compatible (nearly all of them)
|
||||||
settings_version = 0
|
settings_version = 1
|
||||||
|
|
||||||
|
|
||||||
class Settings(object):
|
class Settings(object):
|
||||||
@@ -2897,7 +2907,7 @@ class Settings(object):
|
|||||||
(dr_mode[w.doorShuffle[p]] << 5) | er_mode[w.shuffle[p]],
|
(dr_mode[w.doorShuffle[p]] << 5) | er_mode[w.shuffle[p]],
|
||||||
|
|
||||||
(logic_mode[w.logic[p]] << 5) | (world_mode[w.mode[p]] << 3)
|
(logic_mode[w.logic[p]] << 5) | (world_mode[w.mode[p]] << 3)
|
||||||
| (sword_mode[w.swords[p]] << 1) | (1 if w.retro[p] else 0),
|
| (sword_mode[w.swords[p]] << 1),
|
||||||
|
|
||||||
(goal_mode[w.goal[p]] << 5) | (diff_mode[w.difficulty[p]] << 3)
|
(goal_mode[w.goal[p]] << 5) | (diff_mode[w.difficulty[p]] << 3)
|
||||||
| (func_mode[w.difficulty_adjustments[p]] << 1) | (1 if w.hints[p] else 0),
|
| (func_mode[w.difficulty_adjustments[p]] << 1) | (1 if w.hints[p] else 0),
|
||||||
@@ -2915,7 +2925,7 @@ class Settings(object):
|
|||||||
((8 if w.crystals_ganon_orig[p] == "random" else int(w.crystals_ganon_orig[p])) << 3)
|
((8 if w.crystals_ganon_orig[p] == "random" else int(w.crystals_ganon_orig[p])) << 3)
|
||||||
| (0x4 if w.open_pyramid[p] else 0) | access_mode[w.accessibility[p]],
|
| (0x4 if w.open_pyramid[p] else 0) | access_mode[w.accessibility[p]],
|
||||||
|
|
||||||
(0x80 if w.bigkeyshuffle[p] else 0) | (0x40 if w.keyshuffle[p] else 0)
|
(0x80 if w.bigkeyshuffle[p] else 0)
|
||||||
| (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0)
|
| (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0)
|
||||||
| (door_type_mode[w.door_type_mode[p]] << 2) | (enemy_mode[w.enemy_shuffle[p]]),
|
| (door_type_mode[w.door_type_mode[p]] << 2) | (enemy_mode[w.enemy_shuffle[p]]),
|
||||||
|
|
||||||
@@ -2926,14 +2936,16 @@ class Settings(object):
|
|||||||
|
|
||||||
settings_version,
|
settings_version,
|
||||||
|
|
||||||
flute_mode[w.flute_mode[p]] << 7])
|
(flute_mode[w.flute_mode[p]] << 7 | bow_mode[w.bow_mode[p]] << 4
|
||||||
|
| take_any_mode[w.take_any[p]] << 2 | keyshuffle_mode[w.keyshuffle[p]])
|
||||||
|
])
|
||||||
return base64.b64encode(code, "+-".encode()).decode()
|
return base64.b64encode(code, "+-".encode()).decode()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def adjust_args_from_code(code, player, args):
|
def adjust_args_from_code(code, player, args):
|
||||||
settings, p = base64.b64decode(code.encode(), "+-".encode()), player
|
settings, p = base64.b64decode(code.encode(), "+-".encode()), player
|
||||||
|
|
||||||
if len(settings) < 11:
|
if len(settings) < 12:
|
||||||
raise Exception('Provided code is incompatible with this version')
|
raise Exception('Provided code is incompatible with this version')
|
||||||
if settings[10] != settings_version:
|
if settings[10] != settings_version:
|
||||||
raise Exception('Provided code is incompatible with this version')
|
raise Exception('Provided code is incompatible with this version')
|
||||||
@@ -2950,7 +2962,7 @@ class Settings(object):
|
|||||||
args.item_functionality[p] = r(func_mode)[(settings[2] & 0x6) >> 1]
|
args.item_functionality[p] = r(func_mode)[(settings[2] & 0x6) >> 1]
|
||||||
args.goal[p] = r(goal_mode)[(settings[2] & 0xE0) >> 5]
|
args.goal[p] = r(goal_mode)[(settings[2] & 0xE0) >> 5]
|
||||||
args.accessibility[p] = r(access_mode)[settings[6] & 0x3]
|
args.accessibility[p] = r(access_mode)[settings[6] & 0x3]
|
||||||
args.retro[p] = True if settings[1] & 0x01 else False
|
# args.retro[p] = True if settings[1] & 0x01 else False
|
||||||
args.hints[p] = True if settings[2] & 0x01 else False
|
args.hints[p] = True if settings[2] & 0x01 else False
|
||||||
args.shopsanity[p] = True if settings[3] & 0x80 else False
|
args.shopsanity[p] = True if settings[3] & 0x80 else False
|
||||||
args.decoupledoors[p] = True if settings[3] & 0x40 else False
|
args.decoupledoors[p] = True if settings[3] & 0x40 else False
|
||||||
@@ -2973,7 +2985,7 @@ class Settings(object):
|
|||||||
args.openpyramid[p] = True if settings[6] & 0x4 else False
|
args.openpyramid[p] = True if settings[6] & 0x4 else False
|
||||||
|
|
||||||
args.bigkeyshuffle[p] = True if settings[7] & 0x80 else False
|
args.bigkeyshuffle[p] = True if settings[7] & 0x80 else False
|
||||||
args.keyshuffle[p] = True if settings[7] & 0x40 else False
|
# args.keyshuffle[p] = True if settings[7] & 0x40 else False
|
||||||
args.mapshuffle[p] = True if settings[7] & 0x20 else False
|
args.mapshuffle[p] = True if settings[7] & 0x20 else False
|
||||||
args.compassshuffle[p] = True if settings[7] & 0x10 else False
|
args.compassshuffle[p] = True if settings[7] & 0x10 else False
|
||||||
args.door_type_mode[p] = r(door_type_mode)[(settings[7] & 0xc) >> 2]
|
args.door_type_mode[p] = r(door_type_mode)[(settings[7] & 0xc) >> 2]
|
||||||
@@ -2990,6 +3002,9 @@ class Settings(object):
|
|||||||
args.shufflebosses[p] = r(boss_mode)[(settings[9] & 0x07)]
|
args.shufflebosses[p] = r(boss_mode)[(settings[9] & 0x07)]
|
||||||
if len(settings) > 11:
|
if len(settings) > 11:
|
||||||
args.flute_mode[p] = r(flute_mode)[(settings[11] & 0x80) >> 7]
|
args.flute_mode[p] = r(flute_mode)[(settings[11] & 0x80) >> 7]
|
||||||
|
args.bow_mode[p] = r(bow_mode)[(settings[11] & 0x70) >> 4]
|
||||||
|
args.take_any[p] = r(take_any_mode)[(settings[11] & 0xC) >> 2]
|
||||||
|
args.keyshuffle[p] = r(keyshuffle_mode)[settings[11] & 0x3]
|
||||||
|
|
||||||
|
|
||||||
class KeyRuleType(FastEnum):
|
class KeyRuleType(FastEnum):
|
||||||
|
|||||||
@@ -103,19 +103,28 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
ret = parser.parse_args(argv)
|
ret = parser.parse_args(argv)
|
||||||
|
|
||||||
if ret.keysanity:
|
if ret.keysanity:
|
||||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
ret.mapshuffle, ret.compassshuffle, ret.bigkeyshuffle = [True] * 3
|
||||||
|
ret.keyshuffle = 'wild'
|
||||||
|
|
||||||
if ret.keydropshuffle:
|
if ret.keydropshuffle:
|
||||||
ret.dropshuffle = True
|
ret.dropshuffle = True
|
||||||
ret.pottery = 'keys' if ret.pottery == 'none' else ret.pottery
|
ret.pottery = 'keys' if ret.pottery == 'none' else ret.pottery
|
||||||
|
|
||||||
|
if ret.retro or ret.mode == 'retro':
|
||||||
|
if ret.bow_mode == 'progressive':
|
||||||
|
ret.bow_mode = 'retro'
|
||||||
|
elif ret.bow_mode == 'silvers':
|
||||||
|
ret.bow_mode = 'retro_silvers'
|
||||||
|
ret.take_any = 'random' if ret.take_any == 'none' else ret.take_any
|
||||||
|
ret.keyshuffle = 'universal'
|
||||||
|
|
||||||
if player_num:
|
if player_num:
|
||||||
defaults = copy.deepcopy(ret)
|
defaults = copy.deepcopy(ret)
|
||||||
for player in range(1, player_num + 1):
|
for player in range(1, player_num + 1):
|
||||||
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
|
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
|
||||||
|
|
||||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
|
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
|
||||||
'flute_mode',
|
'flute_mode', 'bow_mode', 'take_any',
|
||||||
'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',
|
||||||
'usestartinventory', 'bombbag', 'overworld_map', 'restrict_boss_items',
|
'usestartinventory', 'bombbag', 'overworld_map', 'restrict_boss_items',
|
||||||
@@ -158,6 +167,7 @@ def parse_settings():
|
|||||||
"crystals_ganon": "7",
|
"crystals_ganon": "7",
|
||||||
"swords": "random",
|
"swords": "random",
|
||||||
'flute_mode': 'normal',
|
'flute_mode': 'normal',
|
||||||
|
'bow_mode': 'progressive',
|
||||||
"difficulty": "normal",
|
"difficulty": "normal",
|
||||||
"item_functionality": "normal",
|
"item_functionality": "normal",
|
||||||
"timer": "none",
|
"timer": "none",
|
||||||
@@ -175,6 +185,7 @@ def parse_settings():
|
|||||||
"shufflelinks": False,
|
"shufflelinks": False,
|
||||||
"shuffletavern": False,
|
"shuffletavern": False,
|
||||||
"overworld_map": "default",
|
"overworld_map": "default",
|
||||||
|
'take_any': 'none',
|
||||||
"pseudoboots": False,
|
"pseudoboots": False,
|
||||||
|
|
||||||
"shuffleenemies": "none",
|
"shuffleenemies": "none",
|
||||||
@@ -189,11 +200,11 @@ def parse_settings():
|
|||||||
'pottery': 'none',
|
'pottery': 'none',
|
||||||
'colorizepots': False,
|
'colorizepots': False,
|
||||||
'shufflepots': False,
|
'shufflepots': False,
|
||||||
"mapshuffle": False,
|
'mapshuffle': False,
|
||||||
"compassshuffle": False,
|
'compassshuffle': False,
|
||||||
"keyshuffle": False,
|
'keyshuffle': 'none',
|
||||||
"bigkeyshuffle": False,
|
'bigkeyshuffle': False,
|
||||||
"keysanity": False,
|
'keysanity': False,
|
||||||
"door_shuffle": "basic",
|
"door_shuffle": "basic",
|
||||||
"intensity": 2,
|
"intensity": 2,
|
||||||
'door_type_mode': 'original',
|
'door_type_mode': 'original',
|
||||||
|
|||||||
+7
-7
@@ -470,7 +470,7 @@ def choose_portals(world, player):
|
|||||||
for dungeon, info in shuffled_info:
|
for dungeon, info in shuffled_info:
|
||||||
outstanding_portals = list(dungeon_portals[dungeon])
|
outstanding_portals = list(dungeon_portals[dungeon])
|
||||||
hc_flag = std_flag and dungeon == 'Hyrule Castle'
|
hc_flag = std_flag and dungeon == 'Hyrule Castle'
|
||||||
rupee_bow_flag = hc_flag and world.retro[player] # rupee bow
|
rupee_bow_flag = hc_flag and world.bow_mode[player].startswith('retro') # rupee bow
|
||||||
if hc_flag:
|
if hc_flag:
|
||||||
sanc = world.get_portal('Sanctuary', player)
|
sanc = world.get_portal('Sanctuary', player)
|
||||||
sanc.destination = True
|
sanc.destination = True
|
||||||
@@ -843,7 +843,7 @@ def main_dungeon_pool(dungeon_pool, world, player):
|
|||||||
|
|
||||||
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
||||||
target_items = 34
|
target_items = 34
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
target_items += 1 if world.dropshuffle[player] else 0 # the hc big key
|
target_items += 1 if world.dropshuffle[player] else 0 # the hc big key
|
||||||
else:
|
else:
|
||||||
target_items += 29 # small keys in chests
|
target_items += 29 # small keys in chests
|
||||||
@@ -1248,7 +1248,7 @@ def cross_dungeon(world, player):
|
|||||||
assign_cross_keys(dungeon_builders, world, player)
|
assign_cross_keys(dungeon_builders, world, player)
|
||||||
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
|
||||||
target_items = 34
|
target_items = 34
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
target_items += 1 if world.dropshuffle[player] else 0 # the hc big key
|
target_items += 1 if world.dropshuffle[player] else 0 # the hc big key
|
||||||
else:
|
else:
|
||||||
target_items += 29 # small keys in chests
|
target_items += 29 # small keys in chests
|
||||||
@@ -1336,7 +1336,7 @@ def filter_key_door_pool(pool, selected_custom):
|
|||||||
def assign_cross_keys(dungeon_builders, world, player):
|
def assign_cross_keys(dungeon_builders, world, player):
|
||||||
logging.getLogger('').info(world.fish.translate("cli", "cli", "shuffling.keydoors"))
|
logging.getLogger('').info(world.fish.translate("cli", "cli", "shuffling.keydoors"))
|
||||||
start = time.process_time()
|
start = time.process_time()
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
remaining = 29
|
remaining = 29
|
||||||
if world.dropshuffle[player]:
|
if world.dropshuffle[player]:
|
||||||
remaining += 13
|
remaining += 13
|
||||||
@@ -1424,7 +1424,7 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
# Last Step: Adjust Small Key Dungeon Pool
|
# Last Step: Adjust Small Key Dungeon Pool
|
||||||
for name, builder in dungeon_builders.items():
|
for name, builder in dungeon_builders.items():
|
||||||
reassign_key_doors(builder, world, player)
|
reassign_key_doors(builder, world, player)
|
||||||
if not world.retro[player]:
|
if world.keyshuffle[player] != 'universal':
|
||||||
log_key_logic(builder.name, world.key_logic[player][builder.name])
|
log_key_logic(builder.name, world.key_logic[player][builder.name])
|
||||||
actual_chest_keys = max(builder.key_doors_num - builder.key_drop_cnt, 0)
|
actual_chest_keys = max(builder.key_doors_num - builder.key_drop_cnt, 0)
|
||||||
dungeon = world.get_dungeon(name, player)
|
dungeon = world.get_dungeon(name, player)
|
||||||
@@ -1963,7 +1963,7 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, worl
|
|||||||
# time to re-assign
|
# time to re-assign
|
||||||
reassign_key_doors(small_map, world, player)
|
reassign_key_doors(small_map, world, player)
|
||||||
for dungeon_name in pool:
|
for dungeon_name in pool:
|
||||||
if not world.retro[player]:
|
if world.keyshuffle[player] != 'universal':
|
||||||
builder = world.dungeon_layouts[player][dungeon_name]
|
builder = world.dungeon_layouts[player][dungeon_name]
|
||||||
log_key_logic(builder.name, world.key_logic[player][builder.name])
|
log_key_logic(builder.name, world.key_logic[player][builder.name])
|
||||||
if world.doorShuffle[player] != 'basic':
|
if world.doorShuffle[player] != 'basic':
|
||||||
@@ -2470,7 +2470,7 @@ def reassign_big_key_doors(bk_map, world, player):
|
|||||||
pass # we don't have spiral stairs candidates yet that aren't already key doors
|
pass # we don't have spiral stairs candidates yet that aren't already key doors
|
||||||
elif d.type is DoorType.Normal:
|
elif d.type is DoorType.Normal:
|
||||||
change_door_to_big_key(d, world, player)
|
change_door_to_big_key(d, world, player)
|
||||||
if not world.decoupledoors[player] and d.dest:
|
if not world.decoupledoors[player] and d.dest and world.door_type_mode[player] != 'original':
|
||||||
if d.dest.type in [DoorType.Normal]:
|
if d.dest.type in [DoorType.Normal]:
|
||||||
dest_room = world.get_room(d.dest.roomIndex, player)
|
dest_room = world.get_room(d.dest.roomIndex, player)
|
||||||
if stateful_door(d.dest, dest_room.kind(d.dest)):
|
if stateful_door(d.dest, dest_room.kind(d.dest)):
|
||||||
|
|||||||
+1
-1
@@ -1355,7 +1355,7 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player, dunge
|
|||||||
sanc_builder = random.choice(lw_builders)
|
sanc_builder = random.choice(lw_builders)
|
||||||
assign_sector(sanc, sanc_builder, candidate_sectors, global_pole)
|
assign_sector(sanc, sanc_builder, candidate_sectors, global_pole)
|
||||||
|
|
||||||
bow_sectors, retro_std_flag = {}, world.retro[player] and world.mode[player] == 'standard'
|
bow_sectors, retro_std_flag = {}, world.bow_mode[player].startswith('retro') and world.mode[player] == 'standard'
|
||||||
free_location_sectors = {}
|
free_location_sectors = {}
|
||||||
crystal_switches = {}
|
crystal_switches = {}
|
||||||
crystal_barriers = {}
|
crystal_barriers = {}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ from Items import ItemFactory
|
|||||||
|
|
||||||
def create_dungeons(world, player):
|
def create_dungeons(world, player):
|
||||||
def make_dungeon(name, id, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
|
def make_dungeon(name, id, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
|
||||||
dungeon = Dungeon(name, dungeon_regions, big_key, [] if world.retro[player] else small_keys,
|
dungeon = Dungeon(name, dungeon_regions, big_key, [] if world.keyshuffle[player] == 'universal' else small_keys,
|
||||||
dungeon_items, player, id)
|
dungeon_items, player, id)
|
||||||
dungeon.boss = BossFactory(default_boss, player)
|
dungeon.boss = BossFactory(default_boss, player)
|
||||||
for region in dungeon.regions:
|
for region in dungeon.regions:
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ 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[item.player]) or (item.bigkey and world.bigkeyshuffle[item.player]):
|
if ((item.smallkey and world.keyshuffle[item.player] != 'none')
|
||||||
|
or (item.bigkey and world.bigkeyshuffle[item.player])):
|
||||||
item.advancement = True
|
item.advancement = True
|
||||||
elif (item.map and world.mapshuffle[item.player]) or (item.compass and world.compassshuffle[item.player]):
|
elif (item.map and world.mapshuffle[item.player]) or (item.compass and world.compassshuffle[item.player]):
|
||||||
item.priority = True
|
item.priority = True
|
||||||
@@ -50,7 +51,7 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
(bigs if i.bigkey else smalls if i.smallkey else others).append(i)
|
(bigs if i.bigkey else smalls if i.smallkey else others).append(i)
|
||||||
unplaced_smalls = list(smalls)
|
unplaced_smalls = list(smalls)
|
||||||
for i in world.itempool:
|
for i in world.itempool:
|
||||||
if i.smallkey and world.keyshuffle[i.player]:
|
if i.smallkey and world.keyshuffle[i.player] != 'none':
|
||||||
unplaced_smalls.append(i)
|
unplaced_smalls.append(i)
|
||||||
|
|
||||||
def fill(base_state, items, key_pool):
|
def fill(base_state, items, key_pool):
|
||||||
@@ -160,7 +161,7 @@ def valid_key_placement(item, location, key_pool, world):
|
|||||||
if not valid_reserved_placement(item, location, world):
|
if not valid_reserved_placement(item, location, world):
|
||||||
return False
|
return False
|
||||||
if ((not item.smallkey and not item.bigkey) or item.player != location.player
|
if ((not item.smallkey and not item.bigkey) or item.player != location.player
|
||||||
or world.retro[item.player] or world.logic[item.player] == 'nologic'):
|
or world.keyshuffle[item.player] == 'universal' or world.logic[item.player] == 'nologic'):
|
||||||
return True
|
return True
|
||||||
dungeon = location.parent_region.dungeon
|
dungeon = location.parent_region.dungeon
|
||||||
if dungeon:
|
if dungeon:
|
||||||
@@ -215,7 +216,7 @@ def track_dungeon_items(item, location, world):
|
|||||||
|
|
||||||
|
|
||||||
def is_dungeon_item(item, world):
|
def is_dungeon_item(item, world):
|
||||||
return ((item.smallkey and not world.keyshuffle[item.player])
|
return ((item.smallkey and world.keyshuffle[item.player] == 'none')
|
||||||
or (item.bigkey and not world.bigkeyshuffle[item.player])
|
or (item.bigkey and not world.bigkeyshuffle[item.player])
|
||||||
or (item.compass and not world.compassshuffle[item.player])
|
or (item.compass and not world.compassshuffle[item.player])
|
||||||
or (item.map and not world.mapshuffle[item.player]))
|
or (item.map and not world.mapshuffle[item.player]))
|
||||||
@@ -419,7 +420,8 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
|||||||
|
|
||||||
# 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
|
||||||
# todo: crossed
|
# todo: crossed
|
||||||
progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.keyshuffle[item.player] and world.mode[item.player] == 'standard' else 0)
|
progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)'
|
||||||
|
and world.keyshuffle[item.player] != 'none' and world.mode[item.player] == 'standard' else 0)
|
||||||
key_pool = [x for x in progitempool if x.smallkey]
|
key_pool = [x for x in progitempool if x.smallkey]
|
||||||
|
|
||||||
# sort maps and compasses to the back -- this may not be viable in equitable & ambrosia
|
# sort maps and compasses to the back -- this may not be viable in equitable & ambrosia
|
||||||
@@ -498,7 +500,7 @@ def ensure_good_pots(world, write_skips=False):
|
|||||||
else:
|
else:
|
||||||
loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.player)
|
loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.player)
|
||||||
# do the arrow retro check
|
# do the arrow retro check
|
||||||
if world.retro[loc.item.player] and loc.item.name in {'Arrows (5)', 'Arrows (10)'}:
|
if world.bow_mode[loc.item.player].startswith('retro') and loc.item.name in {'Arrows (5)', 'Arrows (10)'}:
|
||||||
loc.item = ItemFactory('Rupees (5)', loc.item.player)
|
loc.item = ItemFactory('Rupees (5)', loc.item.player)
|
||||||
# don't write out all pots to spoiler
|
# don't write out all pots to spoiler
|
||||||
if write_skips:
|
if write_skips:
|
||||||
@@ -663,7 +665,7 @@ def balance_multiworld_progression(world):
|
|||||||
candidate_items = collections.defaultdict(set)
|
candidate_items = collections.defaultdict(set)
|
||||||
while True:
|
while True:
|
||||||
for location in balancing_sphere:
|
for location in balancing_sphere:
|
||||||
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):
|
if location.event and (world.keyshuffle[location.item.player] != 'none' 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)
|
||||||
player = location.item.player
|
player = location.item.player
|
||||||
if player in balancing_players and not location.locked and location.player != player:
|
if player in balancing_players and not location.locked and location.player != player:
|
||||||
@@ -738,7 +740,7 @@ def balance_multiworld_progression(world):
|
|||||||
sphere_locations.add(location)
|
sphere_locations.add(location)
|
||||||
|
|
||||||
for location in sphere_locations:
|
for location in sphere_locations:
|
||||||
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):
|
if location.event and (world.keyshuffle[location.item.player] != 'none' 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 |= sphere_locations
|
checked_locations |= sphere_locations
|
||||||
|
|
||||||
@@ -812,7 +814,9 @@ def balance_money_progression(world):
|
|||||||
return True
|
return True
|
||||||
if item.name in ['Progressive Armor', 'Blue Mail', 'Red Mail']:
|
if item.name in ['Progressive Armor', 'Blue Mail', 'Red Mail']:
|
||||||
return True
|
return True
|
||||||
if world.retro[player] and (item.name in ['Single Arrow', 'Small Key (Universal)']):
|
if world.keyshuffle[player] == 'universal' and item.name == 'Small Key (Universal)':
|
||||||
|
return True
|
||||||
|
if world.bow_mode[player].startswith('retro') and item.name == 'Single Arrow':
|
||||||
return True
|
return True
|
||||||
if location.name in pay_for_locations:
|
if location.name in pay_for_locations:
|
||||||
return True
|
return True
|
||||||
|
|||||||
+2
-2
@@ -73,7 +73,7 @@ class InitialSram:
|
|||||||
if startingstate.has('Bow', player):
|
if startingstate.has('Bow', player):
|
||||||
equip[0x340] = 3 if startingstate.has('Silver Arrows', player) else 1
|
equip[0x340] = 3 if startingstate.has('Silver Arrows', player) else 1
|
||||||
equip[0x38E] |= 0x20 # progressive flag to get the correct hint in all cases
|
equip[0x38E] |= 0x20 # progressive flag to get the correct hint in all cases
|
||||||
if not world.retro[player]:
|
if not world.bow_mode[player].startswith('retro'):
|
||||||
equip[0x38E] |= 0x80
|
equip[0x38E] |= 0x80
|
||||||
if startingstate.has('Silver Arrows', player):
|
if startingstate.has('Silver Arrows', player):
|
||||||
equip[0x38E] |= 0x40
|
equip[0x38E] |= 0x40
|
||||||
@@ -188,7 +188,7 @@ class InitialSram:
|
|||||||
elif item.name in bombs:
|
elif item.name in bombs:
|
||||||
starting_bombs += bombs[item.name]
|
starting_bombs += bombs[item.name]
|
||||||
elif item.name in arrows:
|
elif item.name in arrows:
|
||||||
if world.retro[player]:
|
if world.bow_mode[player].startswith('retro'):
|
||||||
equip[0x38E] |= 0x80
|
equip[0x38E] |= 0x80
|
||||||
starting_arrows = 1
|
starting_arrows = 1
|
||||||
else:
|
else:
|
||||||
|
|||||||
+81
-60
@@ -264,10 +264,10 @@ def generate_itempool(world, player):
|
|||||||
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = make_customizer_pool(world, player)
|
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = make_customizer_pool(world, player)
|
||||||
skip_pool_adjustments = True
|
skip_pool_adjustments = True
|
||||||
elif world.custom:
|
elif 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.bombbag[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, player, world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[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.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] == 'active')
|
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world, player, 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.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] == 'active')
|
||||||
|
|
||||||
if player in world.pool_adjustment.keys() and not skip_pool_adjustments:
|
if player in world.pool_adjustment.keys() and not skip_pool_adjustments:
|
||||||
amt = world.pool_adjustment[player]
|
amt = world.pool_adjustment[player]
|
||||||
@@ -295,7 +295,8 @@ def generate_itempool(world, player):
|
|||||||
if not found_sword and world.swords[player] != 'swordless':
|
if not found_sword and world.swords[player] != 'swordless':
|
||||||
found_sword = True
|
found_sword = True
|
||||||
possible_weapons.append(item)
|
possible_weapons.append(item)
|
||||||
if item in ['Progressive Bow', 'Bow'] and not found_bow and not world.retro[player]:
|
if (item in ['Progressive Bow', 'Bow'] and not found_bow
|
||||||
|
and not world.bow_mode[player].startswith('retro')):
|
||||||
found_bow = True
|
found_bow = True
|
||||||
possible_weapons.append(item)
|
possible_weapons.append(item)
|
||||||
if item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
|
if item in ['Hammer', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
|
||||||
@@ -349,7 +350,7 @@ def generate_itempool(world, player):
|
|||||||
world.treasure_hunt_icon[player] = 'Triforce Piece'
|
world.treasure_hunt_icon[player] = 'Triforce Piece'
|
||||||
|
|
||||||
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[player])
|
and ((item.smallkey and world.keyshuffle[player] != 'none')
|
||||||
or (item.bigkey and world.bigkeyshuffle[player])
|
or (item.bigkey and world.bigkeyshuffle[player])
|
||||||
or (item.map and world.mapshuffle[player])
|
or (item.map and world.mapshuffle[player])
|
||||||
or (item.compass and world.compassshuffle[player]))])
|
or (item.compass and world.compassshuffle[player]))])
|
||||||
@@ -409,8 +410,9 @@ def generate_itempool(world, player):
|
|||||||
|
|
||||||
set_up_shops(world, player)
|
set_up_shops(world, player)
|
||||||
|
|
||||||
if world.retro[player]:
|
if world.take_any[player] != 'none':
|
||||||
set_up_take_anys(world, player, skip_pool_adjustments)
|
set_up_take_anys(world, player, skip_pool_adjustments)
|
||||||
|
if world.keyshuffle[player] == 'universal':
|
||||||
if world.dropshuffle[player] and not skip_pool_adjustments:
|
if world.dropshuffle[player] and not skip_pool_adjustments:
|
||||||
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 13
|
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 13
|
||||||
if world.pottery[player] not in ['none', 'cave'] and not skip_pool_adjustments:
|
if world.pottery[player] not in ['none', 'cave'] and not skip_pool_adjustments:
|
||||||
@@ -432,6 +434,10 @@ take_any_locations = [
|
|||||||
'Palace of Darkness Hint', 'East Dark World Hint', 'Archery Game', 'Dark Lake Hylia Ledge Hint',
|
'Palace of Darkness Hint', 'East Dark World Hint', 'Archery Game', 'Dark Lake Hylia Ledge Hint',
|
||||||
'Dark Lake Hylia Ledge Spike Cave', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Dark Desert Hint']
|
'Dark Lake Hylia Ledge Spike Cave', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Dark Desert Hint']
|
||||||
|
|
||||||
|
fixed_take_anys = [
|
||||||
|
'Desert Healer Fairy', 'Swamp Healer Fairy', 'Dark Death Mountain Healer Fairy',
|
||||||
|
'Dark Lake Hylia Ledge Healer Fairy', 'Bonk Fairy (Dark)']
|
||||||
|
|
||||||
|
|
||||||
def set_up_take_anys(world, player, skip_adjustments=False):
|
def set_up_take_anys(world, player, skip_adjustments=False):
|
||||||
if world.mode[player] == 'inverted':
|
if world.mode[player] == 'inverted':
|
||||||
@@ -440,9 +446,12 @@ def set_up_take_anys(world, player, skip_adjustments=False):
|
|||||||
if 'Archery Game' in take_any_locations:
|
if 'Archery Game' in take_any_locations:
|
||||||
take_any_locations.remove('Archery Game')
|
take_any_locations.remove('Archery Game')
|
||||||
|
|
||||||
|
if world.take_any[player] == 'random':
|
||||||
take_any_candidates = [x for x in take_any_locations if len(world.get_region(x, player).locations) == 0]
|
take_any_candidates = [x for x in take_any_locations if len(world.get_region(x, player).locations) == 0]
|
||||||
|
|
||||||
regions = random.sample(take_any_candidates, 5)
|
regions = random.sample(take_any_candidates, 5)
|
||||||
|
elif world.take_any[player] == 'fixed':
|
||||||
|
regions = list(fixed_take_anys)
|
||||||
|
random.shuffle(regions)
|
||||||
|
|
||||||
old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave, 'the sword cave', player)
|
old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave, 'the sword cave', player)
|
||||||
world.regions.append(old_man_take_any)
|
world.regions.append(old_man_take_any)
|
||||||
@@ -539,38 +548,47 @@ def fill_prizes(world, attempts=15):
|
|||||||
|
|
||||||
|
|
||||||
def set_up_shops(world, player):
|
def set_up_shops(world, player):
|
||||||
if world.retro[player]:
|
retro_bow = world.bow_mode[player].startswith('retro')
|
||||||
|
universal_keys = world.keyshuffle[player] == 'universal'
|
||||||
|
if retro_bow or universal_keys:
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
|
removals = []
|
||||||
|
if retro_bow:
|
||||||
removals = [next(item for item in world.itempool if item.name == 'Arrows (10)' and item.player == player)]
|
removals = [next(item for item in world.itempool if item.name == 'Arrows (10)' and item.player == player)]
|
||||||
red_pots = [item for item in world.itempool if item.name == 'Red Potion' and item.player == player][:5]
|
|
||||||
shields_n_hearts = [item for item in world.itempool if item.name in ['Blue Shield', 'Small Heart'] and item.player == player]
|
|
||||||
removals.extend([item for item in world.itempool if item.name == 'Arrow Upgrade (+5)' and item.player == player])
|
removals.extend([item for item in world.itempool if item.name == 'Arrow Upgrade (+5)' and item.player == player])
|
||||||
removals.extend(red_pots)
|
shields_n_hearts = [item for item in world.itempool if item.name in ['Blue Shield', 'Small Heart'] and item.player == player]
|
||||||
removals.extend(random.sample(shields_n_hearts, 5))
|
removals.extend(random.sample(shields_n_hearts, 5))
|
||||||
|
if universal_keys:
|
||||||
|
red_pots = [item for item in world.itempool if item.name == 'Red Potion' and item.player == player][:5]
|
||||||
|
removals.extend(red_pots)
|
||||||
for remove in removals:
|
for remove in removals:
|
||||||
world.itempool.remove(remove)
|
world.itempool.remove(remove)
|
||||||
|
if retro_bow:
|
||||||
for i in range(6): # replace the Arrows (10) and randomly selected hearts/blue shield
|
for i in range(6): # replace the Arrows (10) and randomly selected hearts/blue shield
|
||||||
arrow_item = ItemFactory('Single Arrow', player)
|
arrow_item = ItemFactory('Single Arrow', player)
|
||||||
arrow_item.advancement = True
|
arrow_item.advancement = True
|
||||||
world.itempool.append(arrow_item)
|
world.itempool.append(arrow_item)
|
||||||
|
world.itempool.append(ItemFactory('Rupees (50)', player)) # replaces the arrow upgrade
|
||||||
|
if universal_keys:
|
||||||
for i in range(5): # replace the red potions
|
for i in range(5): # replace the red potions
|
||||||
world.itempool.append(ItemFactory('Small Key (Universal)', player))
|
world.itempool.append(ItemFactory('Small Key (Universal)', player))
|
||||||
world.itempool.append(ItemFactory('Rupees (50)', player)) # replaces the arrow upgrade
|
|
||||||
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
||||||
else:
|
else:
|
||||||
|
if retro_bow:
|
||||||
rss = world.get_region('Red Shield Shop', player).shop
|
rss = world.get_region('Red Shield Shop', player).shop
|
||||||
if not rss.locked:
|
if not rss.locked:
|
||||||
rss.custom = True
|
rss.custom = True
|
||||||
rss.add_inventory(2, 'Single Arrow', 80)
|
rss.add_inventory(2, 'Single Arrow', 80)
|
||||||
for shop in random.sample([s for s in world.shops[player] if not s.locked and s.region.player == player], 5):
|
|
||||||
shop.custom = True
|
|
||||||
shop.locked = True
|
|
||||||
shop.add_inventory(0, 'Single Arrow', 80)
|
|
||||||
shop.add_inventory(1, 'Small Key (Universal)', 100)
|
|
||||||
shop.add_inventory(2, 'Bombs (10)', 50)
|
|
||||||
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
|
||||||
|
for shop in random.sample([s for s in world.shops[player] if not s.locked and s.region.player == player], 5):
|
||||||
|
shop.custom = True
|
||||||
|
shop.locked = True
|
||||||
|
if retro_bow:
|
||||||
|
shop.add_inventory(0, 'Single Arrow', 80)
|
||||||
|
if universal_keys:
|
||||||
|
shop.add_inventory(1, 'Small Key (Universal)', 100)
|
||||||
if world.bombbag[player]:
|
if world.bombbag[player]:
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
removals = [item for item in world.itempool if item.name == 'Bomb Upgrade (+5)' and item.player == player]
|
removals = [item for item in world.itempool if item.name == 'Bomb Upgrade (+5)' and item.player == player]
|
||||||
@@ -583,10 +601,11 @@ def set_up_shops(world, player):
|
|||||||
|
|
||||||
|
|
||||||
def customize_shops(world, player):
|
def customize_shops(world, player):
|
||||||
found_bomb_upgrade, found_arrow_upgrade = False, world.retro[player]
|
retro_bow = world.bow_mode[player].startswith('retro')
|
||||||
|
found_bomb_upgrade, found_arrow_upgrade = False, retro_bow
|
||||||
possible_replacements = []
|
possible_replacements = []
|
||||||
shops_to_customize = shop_to_location_table.copy()
|
shops_to_customize = shop_to_location_table.copy()
|
||||||
if world.retro[player]:
|
if world.take_any[player] != 'none':
|
||||||
shops_to_customize.update(retro_shops)
|
shops_to_customize.update(retro_shops)
|
||||||
for shop_name, loc_list in shops_to_customize.items():
|
for shop_name, loc_list in shops_to_customize.items():
|
||||||
shop = world.get_region(shop_name, player).shop
|
shop = world.get_region(shop_name, player).shop
|
||||||
@@ -609,7 +628,7 @@ def customize_shops(world, player):
|
|||||||
price = 0
|
price = 0
|
||||||
else:
|
else:
|
||||||
price = 120 if shop_name == 'Potion Shop' and item.name == 'Red Potion' else item.price
|
price = 120 if shop_name == 'Potion Shop' and item.name == 'Red Potion' else item.price
|
||||||
if world.retro[player] and item.name == 'Single Arrow':
|
if retro_bow and item.name == 'Single Arrow':
|
||||||
price = 80
|
price = 80
|
||||||
# randomize price
|
# randomize price
|
||||||
shop.add_inventory(idx, item.name, randomize_price(price), max_repeat, player=item.player)
|
shop.add_inventory(idx, item.name, randomize_price(price), max_repeat, player=item.player)
|
||||||
@@ -636,7 +655,7 @@ def customize_shops(world, player):
|
|||||||
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
if not found_arrow_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 == 'Arrows (10)' or (item.name == 'Single Arrow' and not world.retro[player]):
|
if item.name == 'Arrows (10)' or (item.name == 'Single Arrow' and not retro_bow):
|
||||||
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)
|
||||||
@@ -780,16 +799,17 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)'
|
|||||||
|
|
||||||
|
|
||||||
def add_pot_contents(world, player):
|
def add_pot_contents(world, player):
|
||||||
|
retro_bow = world.bow_mode[player].startswith('retro')
|
||||||
for super_tile, pot_list in vanilla_pots.items():
|
for super_tile, pot_list in vanilla_pots.items():
|
||||||
for pot in pot_list:
|
for pot in pot_list:
|
||||||
if pot.item not in [PotItem.Hole, PotItem.Key, PotItem.Switch]:
|
if pot.item not in [PotItem.Hole, PotItem.Key, PotItem.Switch]:
|
||||||
if valid_pot_location(pot, world.pot_pool[player], world, player):
|
if valid_pot_location(pot, world.pot_pool[player], world, player):
|
||||||
item = ('Rupees (5)' if world.retro[player] and pot_items[pot.item] == 'Arrows (5)'
|
item = ('Rupees (5)' if retro_bow and pot_items[pot.item] == 'Arrows (5)'
|
||||||
else pot_items[pot.item])
|
else pot_items[pot.item])
|
||||||
world.itempool.append(ItemFactory(item, player))
|
world.itempool.append(ItemFactory(item, player))
|
||||||
|
|
||||||
|
|
||||||
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag,
|
def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, bombbag,
|
||||||
door_shuffle, logic, flute_activated):
|
door_shuffle, logic, flute_activated):
|
||||||
pool = []
|
pool = []
|
||||||
placed_items = {}
|
placed_items = {}
|
||||||
@@ -862,7 +882,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
|
|||||||
else:
|
else:
|
||||||
pool.extend(diff.basicarmor)
|
pool.extend(diff.basicarmor)
|
||||||
|
|
||||||
if want_progressives():
|
if 'silvers' not in world.bow_mode[player]:
|
||||||
pool.extend(['Progressive Bow'] * 2)
|
pool.extend(['Progressive Bow'] * 2)
|
||||||
elif swords != 'swordless':
|
elif swords != 'swordless':
|
||||||
pool.extend(diff.basicbow)
|
pool.extend(diff.basicbow)
|
||||||
@@ -910,13 +930,14 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
|
|||||||
|
|
||||||
if goal in ['pedestal', 'trinity'] and swords != 'vanilla':
|
if goal in ['pedestal', 'trinity'] and swords != 'vanilla':
|
||||||
place_item('Master Sword Pedestal', 'Triforce')
|
place_item('Master Sword Pedestal', 'Triforce')
|
||||||
if retro:
|
if world.bow_mode[player].startswith('retro'):
|
||||||
pool = [item.replace('Single Arrow', 'Rupees (5)') for item in pool]
|
pool = [item.replace('Single Arrow', 'Rupees (5)') for item in pool]
|
||||||
pool = [item.replace('Arrows (10)', 'Rupees (5)') for item in pool]
|
pool = [item.replace('Arrows (10)', 'Rupees (5)') for item in pool]
|
||||||
pool = [item.replace('Arrow Upgrade (+5)', 'Rupees (5)') for item in pool]
|
pool = [item.replace('Arrow Upgrade (+5)', 'Rupees (5)') for item in pool]
|
||||||
pool = [item.replace('Arrow Upgrade (+10)', 'Rupees (5)') for item in pool]
|
pool = [item.replace('Arrow Upgrade (+10)', 'Rupees (5)') for item in pool]
|
||||||
|
if world.keyshuffle[player] == 'universal':
|
||||||
pool.extend(diff.retro)
|
pool.extend(diff.retro)
|
||||||
if door_shuffle != 'vanilla': # door shuffle needs more keys for retro
|
if door_shuffle != 'vanilla': # door shuffle needs more keys for universal keys
|
||||||
replace = 'Rupees (20)' if difficulty == 'normal' else 'Rupees (5)'
|
replace = 'Rupees (20)' if difficulty == 'normal' else 'Rupees (5)'
|
||||||
indices = [i for i, x in enumerate(pool) if x == replace]
|
indices = [i for i, x in enumerate(pool) if x == replace]
|
||||||
for i in range(0, min(10, len(indices))):
|
for i in range(0, min(10, len(indices))):
|
||||||
@@ -932,7 +953,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
|
|||||||
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, bombbag, customitemarray):
|
def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer, goal, mode, swords, bombbag, 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 = []
|
||||||
@@ -1014,7 +1035,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||||||
itemtotal = itemtotal + 1
|
itemtotal = itemtotal + 1
|
||||||
|
|
||||||
if mode == 'standard':
|
if mode == 'standard':
|
||||||
if retro:
|
if world.keyshuffle[player] == 'universal':
|
||||||
key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
||||||
place_item(key_location, 'Small Key (Universal)')
|
place_item(key_location, 'Small Key (Universal)')
|
||||||
pool.extend(['Small Key (Universal)'] * max((customitemarray["generickeys"] - 1), 0))
|
pool.extend(['Small Key (Universal)'] * max((customitemarray["generickeys"] - 1), 0))
|
||||||
@@ -1028,7 +1049,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||||||
pool.extend(['Magic Mirror'] * customitemarray["mirror"])
|
pool.extend(['Magic Mirror'] * customitemarray["mirror"])
|
||||||
pool.extend(['Moon Pearl'] * customitemarray["pearl"])
|
pool.extend(['Moon Pearl'] * customitemarray["pearl"])
|
||||||
|
|
||||||
if retro:
|
if world.keyshuffle[player] == 'universal':
|
||||||
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in Retro Mode
|
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in Retro Mode
|
||||||
if itemtotal < total_items_to_place:
|
if itemtotal < total_items_to_place:
|
||||||
nothings = total_items_to_place - itemtotal
|
nothings = total_items_to_place - itemtotal
|
||||||
@@ -1066,7 +1087,7 @@ def make_customizer_pool(world, player):
|
|||||||
pool.append(random.choice(diff.bottles))
|
pool.append(random.choice(diff.bottles))
|
||||||
elif item_name.startswith('Small Key') and item_name != 'Small Key (Universal)':
|
elif item_name.startswith('Small Key') and item_name != 'Small Key (Universal)':
|
||||||
d_item = ItemFactory(item_name, player)
|
d_item = ItemFactory(item_name, player)
|
||||||
if not world.keyshuffle[player]:
|
if world.keyshuffle[player] == 'none':
|
||||||
d_name = d_item.dungeon
|
d_name = d_item.dungeon
|
||||||
dungeon = world.get_dungeon(d_name, player)
|
dungeon = world.get_dungeon(d_name, player)
|
||||||
target_amount = max(amount, len(dungeon.small_keys))
|
target_amount = max(amount, len(dungeon.small_keys))
|
||||||
@@ -1121,7 +1142,7 @@ def make_customizer_pool(world, player):
|
|||||||
guaranteed_items = alwaysitems + ['Magic Mirror', 'Moon Pearl']
|
guaranteed_items = alwaysitems + ['Magic Mirror', 'Moon Pearl']
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion'])
|
guaranteed_items.extend(['Blue Potion', 'Green Potion', 'Red Potion'])
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
guaranteed_items.append('Small Key (Universal)')
|
guaranteed_items.append('Small Key (Universal)')
|
||||||
for item in guaranteed_items:
|
for item in guaranteed_items:
|
||||||
if item not in pool:
|
if item not in pool:
|
||||||
@@ -1199,34 +1220,34 @@ def set_default_triforce(goal, custom_goal, custom_total):
|
|||||||
|
|
||||||
|
|
||||||
# A quick test to ensure all combinations generate the correct amount of items.
|
# A quick test to ensure all combinations generate the correct amount of items.
|
||||||
def test():
|
# def test():
|
||||||
for difficulty in ['normal', 'hard', 'expert']:
|
# for difficulty in ['normal', 'hard', 'expert']:
|
||||||
for goal in ['ganon', 'triforcehunt', 'pedestal', 'trinity']:
|
# for goal in ['ganon', 'triforcehunt', 'pedestal', 'trinity']:
|
||||||
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
|
# for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
|
||||||
for mode in ['open', 'standard', 'inverted', 'retro']:
|
# for mode in ['open', 'standard', 'inverted', 'retro']:
|
||||||
for swords in ['random', 'assured', 'swordless', 'vanilla']:
|
# for swords in ['random', 'assured', 'swordless', 'vanilla']:
|
||||||
for progressive in ['on', 'off']:
|
# for progressive in ['on', 'off']:
|
||||||
for shuffle in ['full']:
|
# for shuffle in ['full']:
|
||||||
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 bombbag in [True, False]:
|
# for bombbag in [True, False]:
|
||||||
for door_shuffle in ['basic', 'crossed', 'vanilla']:
|
# for door_shuffle in ['basic', 'crossed', 'vanilla']:
|
||||||
out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic)
|
# out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic)
|
||||||
count = len(out[0]) + len(out[1])
|
# count = len(out[0]) + len(out[1])
|
||||||
|
#
|
||||||
correct_count = total_items_to_place
|
# correct_count = total_items_to_place
|
||||||
if goal in ['pedestal', 'trinity'] and swords != 'vanilla':
|
# if goal in ['pedestal', 'trinity'] 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, bombbag))
|
# 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, bombbag))
|
||||||
except AssertionError as e:
|
# except AssertionError as e:
|
||||||
print(e)
|
# print(e)
|
||||||
|
#
|
||||||
if __name__ == '__main__':
|
# if __name__ == '__main__':
|
||||||
test()
|
# test()
|
||||||
|
|
||||||
|
|
||||||
def fill_specific_items(world):
|
def fill_specific_items(world):
|
||||||
@@ -1270,7 +1291,7 @@ def fill_specific_items(world):
|
|||||||
|
|
||||||
|
|
||||||
def is_dungeon_item(item, world, player):
|
def is_dungeon_item(item, world, player):
|
||||||
return ((item.startswith('Small Key') and not world.keyshuffle[player])
|
return ((item.startswith('Small Key') and world.keyshuffle[player] == 'none')
|
||||||
or (item.startswith('Big Key') and not world.bigkeyshuffle[player])
|
or (item.startswith('Big Key') and not world.bigkeyshuffle[player])
|
||||||
or (item.startswith('Compass') and not world.compassshuffle[player])
|
or (item.startswith('Compass') and not world.compassshuffle[player])
|
||||||
or (item.startswith('Map') and not world.mapshuffle[player]))
|
or (item.startswith('Map') and not world.mapshuffle[player]))
|
||||||
|
|||||||
+13
-12
@@ -158,7 +158,7 @@ class PlacementRule(object):
|
|||||||
left -= rule_needed
|
left -= rule_needed
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_satisfiable(self, outside_keys, unplaced_keys, big_key_loc, prize_location, cr_count):
|
def is_satisfiable(self, outside_keys, wild_keys, unplaced_keys, big_key_loc, prize_location, cr_count):
|
||||||
if self.prize_relevance and prize_location:
|
if self.prize_relevance and prize_location:
|
||||||
if self.prize_relevance == 'BigBomb':
|
if self.prize_relevance == 'BigBomb':
|
||||||
if prize_location.item.name not in ['Crystal 5', 'Crystal 6']:
|
if prize_location.item.name not in ['Crystal 5', 'Crystal 6']:
|
||||||
@@ -272,7 +272,7 @@ def analyze_dungeon(key_layout, world, player):
|
|||||||
key_logic.bk_chests.update(find_big_chest_locations(key_layout.all_chest_locations))
|
key_logic.bk_chests.update(find_big_chest_locations(key_layout.all_chest_locations))
|
||||||
key_logic.bk_chests.update(find_big_key_locked_locations(key_layout.all_chest_locations))
|
key_logic.bk_chests.update(find_big_key_locked_locations(key_layout.all_chest_locations))
|
||||||
key_logic.prize_location = dungeon_table[key_layout.sector.name].prize
|
key_logic.prize_location = dungeon_table[key_layout.sector.name].prize
|
||||||
if world.retro[player] and world.mode[player] != 'standard':
|
if world.keyshuffle[player] == 'universal' and world.mode[player] != 'standard':
|
||||||
return
|
return
|
||||||
|
|
||||||
original_key_counter = find_counter({}, False, key_layout, False)
|
original_key_counter = find_counter({}, False, key_layout, False)
|
||||||
@@ -923,7 +923,7 @@ def self_lock_possible(counter):
|
|||||||
|
|
||||||
|
|
||||||
def available_chest_small_keys(key_counter, world, player):
|
def available_chest_small_keys(key_counter, world, player):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if world.keyshuffle[player] == 'none':
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for loc in key_counter.free_locations:
|
for loc in key_counter.free_locations:
|
||||||
if key_counter.big_key_opened or '- Big Chest' not in loc.name:
|
if key_counter.big_key_opened or '- Big Chest' not in loc.name:
|
||||||
@@ -934,7 +934,7 @@ def available_chest_small_keys(key_counter, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def available_chest_small_keys_logic(key_counter, world, player, sm_restricted):
|
def available_chest_small_keys_logic(key_counter, world, player, sm_restricted):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if world.keyshuffle[player] == 'none':
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for loc in key_counter.free_locations:
|
for loc in key_counter.free_locations:
|
||||||
if loc not in sm_restricted and (key_counter.big_key_opened or '- Big Chest' not in loc.name):
|
if loc not in sm_restricted and (key_counter.big_key_opened or '- Big Chest' not in loc.name):
|
||||||
@@ -1446,8 +1446,9 @@ def validate_bk_layout(proposal, builder, start_regions, world, player):
|
|||||||
|
|
||||||
# Soft lock stuff
|
# Soft lock stuff
|
||||||
def validate_key_layout(key_layout, world, player):
|
def validate_key_layout(key_layout, world, player):
|
||||||
# retro is all good - except for hyrule castle in standard mode
|
# universal key is all good - except for hyrule castle in standard mode
|
||||||
if (world.retro[player] and (world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle')) or world.logic[player] == 'nologic':
|
if world.logic[player] == 'nologic' or (world.keyshuffle[player] == 'universal' and
|
||||||
|
(world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle')):
|
||||||
return True
|
return True
|
||||||
flat_proposal = key_layout.flat_prop
|
flat_proposal = key_layout.flat_prop
|
||||||
state = ExplorationState(dungeon=key_layout.sector.name)
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
@@ -1575,8 +1576,8 @@ def enough_small_locations(state, avail_small_loc):
|
|||||||
|
|
||||||
|
|
||||||
def determine_prize_lock(key_layout, world, player):
|
def determine_prize_lock(key_layout, world, player):
|
||||||
if ((world.retro[player] and (world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle'))
|
if world.logic[player] == 'nologic' or (world.keyshuffle[player] == 'universal' and
|
||||||
or world.logic[player] == 'nologic'):
|
(world.mode[player] != 'standard' or key_layout.sector.name != 'Hyrule Castle')):
|
||||||
return # done, doesn't matter what
|
return # done, doesn't matter what
|
||||||
flat_proposal = key_layout.flat_prop
|
flat_proposal = key_layout.flat_prop
|
||||||
state = ExplorationState(dungeon=key_layout.sector.name)
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
@@ -1608,7 +1609,7 @@ def determine_prize_lock(key_layout, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if world.keyshuffle[player] == 'none':
|
||||||
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
bk_adj = 1 if state.big_key_opened and not state.big_key_special else 0
|
||||||
avail_chest_keys = min(free_locations - bk_adj, state.key_locations - key_only)
|
avail_chest_keys = min(free_locations - bk_adj, state.key_locations - key_only)
|
||||||
return max(0, avail_chest_keys + key_only - state.used_smalls)
|
return max(0, avail_chest_keys + key_only - state.used_smalls)
|
||||||
@@ -1616,7 +1617,7 @@ def cnt_avail_small_locations(free_locations, key_only, state, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def cnt_avail_small_locations_by_ctr(free_locations, counter, layout, world, player):
|
def cnt_avail_small_locations_by_ctr(free_locations, counter, layout, world, player):
|
||||||
if not world.keyshuffle[player] and not world.retro[player]:
|
if world.keyshuffle[player] == 'none':
|
||||||
bk_adj = 1 if counter.big_key_opened and not layout.big_key_special else 0
|
bk_adj = 1 if counter.big_key_opened and not layout.big_key_special else 0
|
||||||
avail_chest_keys = min(free_locations - bk_adj, layout.max_chests)
|
avail_chest_keys = min(free_locations - bk_adj, layout.max_chests)
|
||||||
return max(0, avail_chest_keys + len(counter.key_only_locations) - counter.used_keys)
|
return max(0, avail_chest_keys + len(counter.key_only_locations) - counter.used_keys)
|
||||||
@@ -2059,14 +2060,14 @@ def val_rule(rule, skn, allow=False, loc=None, askn=None, setCheck=None):
|
|||||||
|
|
||||||
# Soft lock stuff
|
# Soft lock stuff
|
||||||
def validate_key_placement(key_layout, world, player):
|
def validate_key_placement(key_layout, world, player):
|
||||||
if world.retro[player] or world.accessibility[player] == 'none':
|
if world.keyshuffle[player] == 'universal' or world.accessibility[player] == 'none':
|
||||||
return True # Can't keylock in retro. Expected if beatable only.
|
return True # Can't keylock in retro. Expected if beatable only.
|
||||||
max_counter = find_max_counter(key_layout)
|
max_counter = find_max_counter(key_layout)
|
||||||
keys_outside = 0
|
keys_outside = 0
|
||||||
big_key_outside = False
|
big_key_outside = False
|
||||||
smallkey_name = dungeon_keys[key_layout.sector.name]
|
smallkey_name = dungeon_keys[key_layout.sector.name]
|
||||||
bigkey_name = dungeon_bigs[key_layout.sector.name]
|
bigkey_name = dungeon_bigs[key_layout.sector.name]
|
||||||
if world.keyshuffle[player]:
|
if world.keyshuffle[player] != 'none':
|
||||||
keys_outside = key_layout.max_chests - sum(1 for i in max_counter.free_locations if i.item is not None and i.item.name == smallkey_name and i.item.player == player)
|
keys_outside = key_layout.max_chests - sum(1 for i in max_counter.free_locations if i.item is not None and i.item.name == smallkey_name and i.item.player == player)
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
max_counter = find_max_counter(key_layout)
|
max_counter = find_max_counter(key_layout)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ def main(args, seed=None, fish=None):
|
|||||||
customized.adjust_args(args)
|
customized.adjust_args(args)
|
||||||
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
world = World(args.multi, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
||||||
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
|
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
|
||||||
args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
args.accessibility, args.shuffleganon, args.custom, args.customitemarray, args.hints)
|
||||||
world.customizer = customized if customized else None
|
world.customizer = customized if customized else None
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
if seed is None:
|
if seed is None:
|
||||||
@@ -96,6 +96,7 @@ def main(args, seed=None, fish=None):
|
|||||||
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
||||||
world.bombbag = args.bombbag.copy()
|
world.bombbag = args.bombbag.copy()
|
||||||
world.flute_mode = args.flute_mode.copy()
|
world.flute_mode = args.flute_mode.copy()
|
||||||
|
world.bow_mode = args.bow_mode.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()
|
||||||
@@ -124,11 +125,13 @@ def main(args, seed=None, fish=None):
|
|||||||
world.shuffletavern = args.shuffletavern.copy()
|
world.shuffletavern = args.shuffletavern.copy()
|
||||||
world.pseudoboots = args.pseudoboots.copy()
|
world.pseudoboots = args.pseudoboots.copy()
|
||||||
world.overworld_map = args.overworld_map.copy()
|
world.overworld_map = args.overworld_map.copy()
|
||||||
|
world.take_any = args.take_any.copy()
|
||||||
world.restrict_boss_items = args.restrict_boss_items.copy()
|
world.restrict_boss_items = args.restrict_boss_items.copy()
|
||||||
world.collection_rate = args.collection_rate.copy()
|
world.collection_rate = args.collection_rate.copy()
|
||||||
world.colorizepots = args.colorizepots.copy()
|
world.colorizepots = args.colorizepots.copy()
|
||||||
|
|
||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
|
world.finish_init()
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
world.fish.translate("cli","cli","app.title") + "\n",
|
world.fish.translate("cli","cli","app.title") + "\n",
|
||||||
@@ -247,7 +250,7 @@ def main(args, seed=None, fish=None):
|
|||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
sell_potions(world, player)
|
sell_potions(world, player)
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
sell_keys(world, player)
|
sell_keys(world, player)
|
||||||
else:
|
else:
|
||||||
lock_shop_locations(world, player)
|
lock_shop_locations(world, player)
|
||||||
@@ -425,7 +428,7 @@ def copy_world(world):
|
|||||||
# ToDo: Not good yet
|
# ToDo: Not good yet
|
||||||
ret = World(world.players, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
ret = World(world.players, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
||||||
world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm,
|
world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm,
|
||||||
world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints)
|
world.accessibility, world.shuffle_ganon, world.custom, world.customitemarray, world.hints)
|
||||||
ret.teams = world.teams
|
ret.teams = world.teams
|
||||||
ret.player_names = copy.deepcopy(world.player_names)
|
ret.player_names = copy.deepcopy(world.player_names)
|
||||||
ret.remote_items = world.remote_items.copy()
|
ret.remote_items = world.remote_items.copy()
|
||||||
|
|||||||
+4
-3
@@ -879,7 +879,8 @@ def shuffle_pots(world, player):
|
|||||||
elif old_pot.item == PotItem.Switch:
|
elif old_pot.item == PotItem.Switch:
|
||||||
available_pots = (pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch))
|
available_pots = (pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch))
|
||||||
elif old_pot.item == PotItem.Key:
|
elif old_pot.item == PotItem.Key:
|
||||||
if world.doorShuffle[player] == 'vanilla' and not world.retro[player] and world.pottery[player] == 'none' and world.logic[player] != 'nologic':
|
if (world.doorShuffle[player] == 'vanilla' and world.keyshuffle[player] != 'universal'
|
||||||
|
and world.pottery[player] == 'none' and world.logic[player] != 'nologic'):
|
||||||
available_pots = (pot for pot in new_pots if pot.room not in invalid_key_rooms)
|
available_pots = (pot for pot in new_pots if pot.room not in invalid_key_rooms)
|
||||||
else:
|
else:
|
||||||
available_pots = new_pots
|
available_pots = new_pots
|
||||||
@@ -890,7 +891,7 @@ def shuffle_pots(world, player):
|
|||||||
|
|
||||||
new_pot = random.choice(available_pots)
|
new_pot = random.choice(available_pots)
|
||||||
new_pot.item = old_pot.item
|
new_pot.item = old_pot.item
|
||||||
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
if world.bow_mode[player].startswith('retro') and new_pot.item == PotItem.FiveArrows:
|
||||||
new_pot.item = PotItem.FiveRupees
|
new_pot.item = PotItem.FiveRupees
|
||||||
|
|
||||||
if new_pot.item == PotItem.Key:
|
if new_pot.item == PotItem.Key:
|
||||||
@@ -938,7 +939,7 @@ def shuffle_pot_switches(world, player):
|
|||||||
|
|
||||||
new_pot = random.choice(available_pots)
|
new_pot = random.choice(available_pots)
|
||||||
new_pot.item, old_pot.item = old_pot.item, new_pot.item
|
new_pot.item, old_pot.item = old_pot.item, new_pot.item
|
||||||
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
if world.bow_mode[player].startswith('retro') and new_pot.item == PotItem.FiveArrows:
|
||||||
new_pot.item = PotItem.FiveRupees
|
new_pot.item = PotItem.FiveRupees
|
||||||
|
|
||||||
if new_pot.item == PotItem.Switch and (new_pot.flags & PotFlags.SwitchLogicChange):
|
if new_pot.item == PotItem.Switch and (new_pot.flags & PotFlags.SwitchLogicChange):
|
||||||
|
|||||||
+1
-1
@@ -1029,7 +1029,7 @@ def adjust_locations(world, player):
|
|||||||
loc.event = False
|
loc.event = False
|
||||||
item_dungeon = key_item.dungeon
|
item_dungeon = key_item.dungeon
|
||||||
dungeon = world.get_dungeon(item_dungeon, player)
|
dungeon = world.get_dungeon(item_dungeon, player)
|
||||||
if key_item.smallkey and not world.retro[player]:
|
if key_item.smallkey and world.keyshuffle[player] != 'universal':
|
||||||
dungeon.small_keys.append(key_item)
|
dungeon.small_keys.append(key_item)
|
||||||
elif key_item.bigkey:
|
elif key_item.bigkey:
|
||||||
dungeon.big_key = key_item
|
dungeon.big_key = key_item
|
||||||
|
|||||||
@@ -797,7 +797,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x138002, 2)
|
rom.write_byte(0x138002, 2)
|
||||||
for name, layout in world.key_layout[player].items():
|
for name, layout in world.key_layout[player].items():
|
||||||
offset = compass_data[name][4]//2
|
offset = compass_data[name][4]//2
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
rom.write_byte(0x13f030+offset, layout.max_chests + layout.max_drops)
|
rom.write_byte(0x13f030+offset, layout.max_chests + layout.max_drops)
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
||||||
@@ -898,7 +898,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x142A50, 1) # StandingItemsOn
|
rom.write_byte(0x142A50, 1) # StandingItemsOn
|
||||||
multiClientFlags = ((0x1 if world.dropshuffle[player] else 0)
|
multiClientFlags = ((0x1 if world.dropshuffle[player] else 0)
|
||||||
| (0x2 if world.shopsanity[player] else 0)
|
| (0x2 if world.shopsanity[player] else 0)
|
||||||
| (0x4 if world.retro[player] else 0)
|
| (0x4 if world.take_any[player] != 'none' else 0)
|
||||||
| (0x8 if world.pottery[player] != 'none' else 0)
|
| (0x8 if world.pottery[player] != 'none' else 0)
|
||||||
| (0x10 if is_mystery else 0))
|
| (0x10 if is_mystery else 0))
|
||||||
rom.write_byte(0x142A51, multiClientFlags)
|
rom.write_byte(0x142A51, multiClientFlags)
|
||||||
@@ -1112,7 +1112,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
||||||
dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes]
|
dig_prizes = [prize_replacements.get(prize, prize) for prize in dig_prizes]
|
||||||
|
|
||||||
if world.retro[player]:
|
if world.bow_mode[player].startswith('retro'):
|
||||||
prize_replacements = {0xE1: 0xDA, #5 Arrows -> Blue Rupee
|
prize_replacements = {0xE1: 0xDA, #5 Arrows -> Blue Rupee
|
||||||
0xE2: 0xDB} #10 Arrows -> Red Rupee
|
0xE2: 0xDB} #10 Arrows -> Red Rupee
|
||||||
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
prizes = [prize_replacements.get(prize, prize) for prize in prizes]
|
||||||
@@ -1155,7 +1155,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees
|
0x12, 0x01, 0x35, 0xFF, # lamp -> 5 rupees
|
||||||
0x51, 0x00 if world.bombbag[player] else 0x06, 0x31 if world.bombbag[player] else 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade. If bombbag -> turns into Bombs (10)
|
0x51, 0x00 if world.bombbag[player] else 0x06, 0x31 if world.bombbag[player] else 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade. If bombbag -> 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.bow_mode[player].startswith('retro') 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
|
||||||
0x17, difficulty.heart_piece_limit, 0x47, 0xff, # piece of heart -> green 20
|
0x17, difficulty.heart_piece_limit, 0x47, 0xff, # piece of heart -> green 20
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel
|
0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel
|
||||||
@@ -1204,7 +1204,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
ERtimeincrease = 10
|
ERtimeincrease = 10
|
||||||
else:
|
else:
|
||||||
ERtimeincrease = 20
|
ERtimeincrease = 20
|
||||||
if world.keyshuffle[player] or world.bigkeyshuffle[player] or world.mapshuffle[player]:
|
if world.keyshuffle[player] != 'none' or world.bigkeyshuffle[player] or world.mapshuffle[player]:
|
||||||
ERtimeincrease = ERtimeincrease + 15
|
ERtimeincrease = ERtimeincrease + 15
|
||||||
if world.clock_mode == 'none':
|
if world.clock_mode == 'none':
|
||||||
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
|
rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode
|
||||||
@@ -1337,7 +1337,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
# m - enabled for inside maps
|
# m - enabled for inside maps
|
||||||
# c - enabled for inside compasses
|
# c - enabled for inside compasses
|
||||||
# s - enabled for inside small keys
|
# s - enabled for inside small keys
|
||||||
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.keyshuffle[player] else 0x00)
|
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.keyshuffle[player] == 'wild' else 0x00)
|
||||||
| (0x02 if world.compassshuffle[player] else 0x00)
|
| (0x02 if world.compassshuffle[player] else 0x00)
|
||||||
| (0x04 if world.mapshuffle[player] else 0x00)
|
| (0x04 if world.mapshuffle[player] else 0x00)
|
||||||
| (0x08 if world.bigkeyshuffle[player] else 0x00))) # free roaming item text boxes
|
| (0x08 if world.bigkeyshuffle[player] else 0x00))) # free roaming item text boxes
|
||||||
@@ -1403,7 +1403,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
# a - Small Key
|
# a - Small Key
|
||||||
#
|
#
|
||||||
enable_menu_map_check = world.overworld_map[player] != 'default' and world.shuffle[player] != 'none'
|
enable_menu_map_check = world.overworld_map[player] != 'default' and world.shuffle[player] != 'none'
|
||||||
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] else 0x00)
|
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] == 'wild' else 0x00)
|
||||||
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
||||||
| (0x04 if world.mapshuffle[player] or enable_menu_map_check else 0x00)
|
| (0x04 if world.mapshuffle[player] or enable_menu_map_check else 0x00)
|
||||||
| (0x08 if world.compassshuffle[player] else 0x00))) # free roaming items in menu
|
| (0x08 if world.compassshuffle[player] else 0x00))) # free roaming items in menu
|
||||||
@@ -1434,17 +1434,17 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
write_int16(rom, 0x18017A, get_reveal_bytes('Green Pendant') if world.mapshuffle[player] 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[player] 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[player] else 0x00) # universal keys
|
rom.write_byte(0x180172, 0x01 if world.keyshuffle[player] == 'universal' else 0x00) # universal keys
|
||||||
rom.write_byte(0x180175, 0x01 if world.retro[player] else 0x00) # rupee bow
|
rom.write_byte(0x180175, 0x01 if world.bow_mode[player].startswith('retro') else 0x00) # rupee bow
|
||||||
rom.write_byte(0x180176, 0x0A if world.retro[player] else 0x00) # wood arrow cost
|
rom.write_byte(0x180176, 0x0A if world.bow_mode[player].startswith('retro') else 0x00) # wood arrow cost
|
||||||
rom.write_byte(0x180178, 0x32 if world.retro[player] else 0x00) # silver arrow cost
|
rom.write_byte(0x180178, 0x32 if world.bow_mode[player].startswith('retro') else 0x00) # silver arrow cost
|
||||||
rom.write_byte(0x301FC, 0xDA if world.retro[player] else 0xE1) # rupees replace arrows under pots
|
rom.write_byte(0x301FC, 0xDA if world.bow_mode[player].startswith('retro') else 0xE1) # rupees replace arrows under pots
|
||||||
if enemized:
|
if enemized:
|
||||||
rom.write_byte(0x1B152e, 0xDA if world.retro[player] else 0xE1)
|
rom.write_byte(0x1B152e, 0xDA if world.bow_mode[player].startswith('retro') else 0xE1)
|
||||||
rom.write_byte(0x30052, 0xDB if world.retro[player] else 0xE2) # replace arrows in fish prize from bottle merchant
|
rom.write_byte(0x30052, 0xDB if world.bow_mode[player].startswith('retro') else 0xE2) # replace arrows in fish prize from bottle merchant
|
||||||
rom.write_bytes(0xECB4E, [0xA9, 0x00, 0xEA, 0xEA] if world.retro[player] else [0xAF, 0x77, 0xF3, 0x7E]) # Thief steals rupees instead of arrows
|
rom.write_bytes(0xECB4E, [0xA9, 0x00, 0xEA, 0xEA] if world.bow_mode[player].startswith('retro') else [0xAF, 0x77, 0xF3, 0x7E]) # Thief steals rupees instead of arrows
|
||||||
rom.write_bytes(0xF0D96, [0xA9, 0x00, 0xEA, 0xEA] if world.retro[player] else [0xAF, 0x77, 0xF3, 0x7E]) # Pikit steals rupees instead of arrows
|
rom.write_bytes(0xF0D96, [0xA9, 0x00, 0xEA, 0xEA] if world.bow_mode[player].startswith('retro') else [0xAF, 0x77, 0xF3, 0x7E]) # Pikit steals rupees instead of arrows
|
||||||
rom.write_bytes(0xEDA5, [0x35, 0x41] if world.retro[player] else [0x43, 0x44]) # Chest game gives rupees instead of arrows
|
rom.write_bytes(0xEDA5, [0x35, 0x41] if world.bow_mode[player].startswith('retro') else [0x43, 0x44]) # Chest game gives rupees instead of arrows
|
||||||
digging_game_rng = random.randint(1, 30) # set rng for digging game
|
digging_game_rng = random.randint(1, 30) # set rng for digging game
|
||||||
rom.write_byte(0x180020, digging_game_rng)
|
rom.write_byte(0x180020, digging_game_rng)
|
||||||
rom.write_byte(0xEFD95, digging_game_rng)
|
rom.write_byte(0xEFD95, digging_game_rng)
|
||||||
@@ -2151,7 +2151,7 @@ def write_strings(rom, world, player, team):
|
|||||||
# 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
|
# 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.
|
# of how many exist. This supports many settings well.
|
||||||
items_to_hint = RelevantItems.copy()
|
items_to_hint = RelevantItems.copy()
|
||||||
if world.keyshuffle[player]:
|
if world.keyshuffle[player] == 'wild':
|
||||||
items_to_hint.extend(SmallKeys)
|
items_to_hint.extend(SmallKeys)
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
items_to_hint.extend(BigKeys)
|
items_to_hint.extend(BigKeys)
|
||||||
|
|||||||
@@ -2072,7 +2072,7 @@ def add_key_logic_rules(world, player):
|
|||||||
add_rule(big_chest, create_rule(d_logic.bk_name, player))
|
add_rule(big_chest, create_rule(d_logic.bk_name, player))
|
||||||
if len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1:
|
if len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1:
|
||||||
set_always_allow(big_chest, allow_big_key_in_big_chest(d_logic.bk_name, player))
|
set_always_allow(big_chest, allow_big_key_in_big_chest(d_logic.bk_name, player))
|
||||||
if world.retro[player]:
|
if world.keyshuffle[player] == 'universal':
|
||||||
for d_name, layout in world.key_layout[player].items():
|
for d_name, layout in world.key_layout[player].items():
|
||||||
for door in layout.flat_prop:
|
for door in layout.flat_prop:
|
||||||
if world.mode[player] != 'standard' or not retro_in_hc(door.entrance):
|
if world.mode[player] != 'standard' or not retro_in_hc(door.entrance):
|
||||||
|
|||||||
+15
-3
@@ -48,6 +48,11 @@
|
|||||||
flute_mode:
|
flute_mode:
|
||||||
normal: 3
|
normal: 3
|
||||||
active: 1
|
active: 1
|
||||||
|
bow_mode:
|
||||||
|
progressive: 5
|
||||||
|
silvers: 5
|
||||||
|
retro: 1
|
||||||
|
retro_silvers: 1
|
||||||
entrance_shuffle:
|
entrance_shuffle:
|
||||||
none: 15
|
none: 15
|
||||||
dungeonssimple: 3
|
dungeonssimple: 3
|
||||||
@@ -66,9 +71,10 @@
|
|||||||
open: 1
|
open: 1
|
||||||
inverted: 1
|
inverted: 1
|
||||||
retro: 0
|
retro: 0
|
||||||
retro:
|
take_any:
|
||||||
on: 1
|
random: 1
|
||||||
off: 4
|
fixed: 3
|
||||||
|
none: 16
|
||||||
goals:
|
goals:
|
||||||
ganon: 2
|
ganon: 2
|
||||||
fast_ganon: 2
|
fast_ganon: 2
|
||||||
@@ -86,6 +92,12 @@
|
|||||||
mc: 3
|
mc: 3
|
||||||
mcs: 2
|
mcs: 2
|
||||||
full: 5
|
full: 5
|
||||||
|
mcu: 1 # map, compass, universal smalls
|
||||||
|
# for use when you aren't using the dungeon_items above
|
||||||
|
# smallkey_shuffle:
|
||||||
|
# standard: 5
|
||||||
|
# wild: 1
|
||||||
|
# universal: 1
|
||||||
dungeon_counters:
|
dungeon_counters:
|
||||||
on: 5
|
on: 5
|
||||||
off: 0
|
off: 0
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ world_state:
|
|||||||
standard: 1
|
standard: 1
|
||||||
open: 1
|
open: 1
|
||||||
inverted: 1
|
inverted: 1
|
||||||
retro: 0
|
|
||||||
retro:
|
retro:
|
||||||
on: 1
|
on: 1
|
||||||
off: 1
|
off: 1
|
||||||
|
|||||||
@@ -48,6 +48,14 @@
|
|||||||
"active"
|
"active"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"bow_mode": {
|
||||||
|
"choices": [
|
||||||
|
"progressive",
|
||||||
|
"silvers",
|
||||||
|
"retro",
|
||||||
|
"retro_silvers"
|
||||||
|
]
|
||||||
|
},
|
||||||
"goal": {
|
"goal": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"ganon",
|
"ganon",
|
||||||
@@ -266,8 +274,11 @@
|
|||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
"keyshuffle": {
|
"keyshuffle": {
|
||||||
"action": "store_true",
|
"choices": [
|
||||||
"type": "bool"
|
"none",
|
||||||
|
"wild",
|
||||||
|
"universal"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"bigkeyshuffle": {
|
"bigkeyshuffle": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
@@ -286,6 +297,13 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"take_any": {
|
||||||
|
"choices": [
|
||||||
|
"none",
|
||||||
|
"random",
|
||||||
|
"fixed"
|
||||||
|
]
|
||||||
|
},
|
||||||
"startinventory": {},
|
"startinventory": {},
|
||||||
"usestartinventory": {
|
"usestartinventory": {
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
|||||||
@@ -122,10 +122,17 @@
|
|||||||
"Expert: Greatly reduced functionality."
|
"Expert: Greatly reduced functionality."
|
||||||
],
|
],
|
||||||
"flute_mode": [
|
"flute_mode": [
|
||||||
"Determine if you need to wake up the bird or not on flute pickup (default: %(default)s)",
|
"Determines if you need to wake up the bird or not on flute pickup (default: %(default)s)",
|
||||||
"Normal: Normal functionality.",
|
"Normal: Normal functionality.",
|
||||||
"Active: Flute is activated on pickup."
|
"Active: Flute is activated on pickup."
|
||||||
],
|
],
|
||||||
|
"bow_mode": [
|
||||||
|
"Determines how the bow acts in the pool (default: %(default)s)",
|
||||||
|
"Progressive: Two progressive bows placed. First picked up is the bow. Second is silvers.",
|
||||||
|
"Silvers Separate: Bow and silvers are completely separate items.",
|
||||||
|
"Retro: Z1 Bow where arrows cost money and the Single Arrow must be bought or found to shoot",
|
||||||
|
"Retro + Silvers: Bow and silvers are completely separate items."
|
||||||
|
],
|
||||||
"timer": [
|
"timer": [
|
||||||
"Select game timer setting. Affects available itempool. (default: %(default)s)",
|
"Select game timer setting. Affects available itempool. (default: %(default)s)",
|
||||||
"None: No timer.",
|
"None: No timer.",
|
||||||
@@ -300,6 +307,12 @@
|
|||||||
"Keys are universal, shooting arrows costs rupees,",
|
"Keys are universal, shooting arrows costs rupees,",
|
||||||
"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)"
|
||||||
],
|
],
|
||||||
|
"take_any": [
|
||||||
|
"Take Any caves from Zelda 1 (default: %(default)s)",
|
||||||
|
"None: No take any caves",
|
||||||
|
"Random: Take any caves can replace a random set of un-interesting caves. See documentation for full list",
|
||||||
|
"Fixed: Take any caves will replace certain location. See documentation for full list"
|
||||||
|
],
|
||||||
"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"],
|
||||||
"bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
|
"bombbag": ["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)" ],
|
||||||
|
|||||||
@@ -53,6 +53,9 @@
|
|||||||
"randomizer.dungeon.mapshuffle": "Maps",
|
"randomizer.dungeon.mapshuffle": "Maps",
|
||||||
"randomizer.dungeon.compassshuffle": "Compasses",
|
"randomizer.dungeon.compassshuffle": "Compasses",
|
||||||
"randomizer.dungeon.smallkeyshuffle": "Small Keys",
|
"randomizer.dungeon.smallkeyshuffle": "Small Keys",
|
||||||
|
"randomizer.dungeon.smallkeyshuffle.standard": "In Dungeon",
|
||||||
|
"randomizer.dungeon.smallkeyshuffle.wild": "Randomized",
|
||||||
|
"randomizer.dungeon.smallkeyshuffle.universal": "Universal",
|
||||||
"randomizer.dungeon.bigkeyshuffle": "Big Keys",
|
"randomizer.dungeon.bigkeyshuffle": "Big Keys",
|
||||||
"randomizer.dungeon.keydropshuffle": "Key Drop Shuffle (Legacy)",
|
"randomizer.dungeon.keydropshuffle": "Key Drop Shuffle (Legacy)",
|
||||||
"randomizer.dungeon.decoupledoors": "Decouple Doors",
|
"randomizer.dungeon.decoupledoors": "Decouple Doors",
|
||||||
@@ -155,7 +158,10 @@
|
|||||||
"randomizer.entrance.entranceshuffle.dungeonsfull": "Dungeons + Full",
|
"randomizer.entrance.entranceshuffle.dungeonsfull": "Dungeons + Full",
|
||||||
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
|
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
|
||||||
|
|
||||||
|
"randomizer.entrance.take_any": "Take Any Caves",
|
||||||
|
"randomizer.entrance.take_any.none": "None",
|
||||||
|
"randomizer.entrance.take_any.random": "Random",
|
||||||
|
"randomizer.entrance.take_any.fixed": "Fixed",
|
||||||
|
|
||||||
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
|
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
|
||||||
"randomizer.gameoptions.quickswap": "L/R Quickswapping",
|
"randomizer.gameoptions.quickswap": "L/R Quickswapping",
|
||||||
@@ -219,7 +225,7 @@
|
|||||||
"randomizer.generation.rom.dialog.allfiles": "All Files",
|
"randomizer.generation.rom.dialog.allfiles": "All Files",
|
||||||
|
|
||||||
"randomizer.item.hints": "Include Helpful Hints",
|
"randomizer.item.hints": "Include Helpful Hints",
|
||||||
"randomizer.item.retro": "Retro mode (universal keys)",
|
"randomizer.item.retro": "Retro mode",
|
||||||
"randomizer.item.pseudoboots": "Start with Pseudo Boots",
|
"randomizer.item.pseudoboots": "Start with Pseudo Boots",
|
||||||
"randomizer.item.bombbag": "Bombbag",
|
"randomizer.item.bombbag": "Bombbag",
|
||||||
|
|
||||||
@@ -289,6 +295,12 @@
|
|||||||
"randomizer.item.flute_mode.normal": "Normal",
|
"randomizer.item.flute_mode.normal": "Normal",
|
||||||
"randomizer.item.flute_mode.active": "Pre-Activated",
|
"randomizer.item.flute_mode.active": "Pre-Activated",
|
||||||
|
|
||||||
|
"randomizer.item.bow_mode": "Bow Mode",
|
||||||
|
"randomizer.item.bow_mode.progressive": "Progressive",
|
||||||
|
"randomizer.item.bow_mode.silvers": "Silvers Separate",
|
||||||
|
"randomizer.item.bow_mode.retro": "Retro (Progressive)",
|
||||||
|
"randomizer.item.bow_mode.retro_silvers": "Retro + Silvers",
|
||||||
|
|
||||||
"randomizer.item.timer": "Timer Setting",
|
"randomizer.item.timer": "Timer Setting",
|
||||||
"randomizer.item.timer.none": "No Timer",
|
"randomizer.item.timer.none": "No Timer",
|
||||||
"randomizer.item.timer.display": "Stopwatch",
|
"randomizer.item.timer.display": "Stopwatch",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"keysanity": {
|
"keysanity": {
|
||||||
"mapshuffle": { "type": "checkbox" },
|
"mapshuffle": { "type": "checkbox" },
|
||||||
"compassshuffle": { "type": "checkbox" },
|
"compassshuffle": { "type": "checkbox" },
|
||||||
"smallkeyshuffle": { "type": "checkbox" },
|
|
||||||
"bigkeyshuffle": { "type": "checkbox" }
|
"bigkeyshuffle": { "type": "checkbox" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"widgets": {
|
"widgets": {
|
||||||
|
"keyshuffle": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"options": [
|
||||||
|
"standard",
|
||||||
|
"wild",
|
||||||
|
"universal"
|
||||||
|
]
|
||||||
|
},
|
||||||
"dungeondoorshuffle": {
|
"dungeondoorshuffle": {
|
||||||
"type": "selectbox",
|
"type": "selectbox",
|
||||||
"default": "basic",
|
"default": "basic",
|
||||||
|
|||||||
@@ -29,6 +29,14 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"width": 45
|
"width": 45
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"take_any": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"options": [
|
||||||
|
"none",
|
||||||
|
"random",
|
||||||
|
"fixed"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,15 @@
|
|||||||
"active"
|
"active"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"bow_mode": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"options": [
|
||||||
|
"progressive",
|
||||||
|
"silvers",
|
||||||
|
"retro",
|
||||||
|
"retro_silvers"
|
||||||
|
]
|
||||||
|
},
|
||||||
"timer": {
|
"timer": {
|
||||||
"type": "selectbox",
|
"type": "selectbox",
|
||||||
"options": [
|
"options": [
|
||||||
|
|||||||
@@ -69,11 +69,13 @@ class CustomSettings(object):
|
|||||||
args.mode[p] = get_setting(settings['mode'], args.mode[p])
|
args.mode[p] = get_setting(settings['mode'], args.mode[p])
|
||||||
args.swords[p] = get_setting(settings['swords'], args.swords[p])
|
args.swords[p] = get_setting(settings['swords'], args.swords[p])
|
||||||
args.flute_mode[p] = get_setting(settings['flute_mode'], args.flute_mode[p])
|
args.flute_mode[p] = get_setting(settings['flute_mode'], args.flute_mode[p])
|
||||||
|
args.bow_mode[p] = get_setting(settings['bow_mode'], args.bow_mode[p])
|
||||||
args.item_functionality[p] = get_setting(settings['item_functionality'], args.item_functionality[p])
|
args.item_functionality[p] = get_setting(settings['item_functionality'], args.item_functionality[p])
|
||||||
args.goal[p] = get_setting(settings['goal'], args.goal[p])
|
args.goal[p] = get_setting(settings['goal'], args.goal[p])
|
||||||
args.difficulty[p] = get_setting(settings['difficulty'], args.difficulty[p])
|
args.difficulty[p] = get_setting(settings['difficulty'], args.difficulty[p])
|
||||||
args.accessibility[p] = get_setting(settings['accessibility'], args.accessibility[p])
|
args.accessibility[p] = get_setting(settings['accessibility'], args.accessibility[p])
|
||||||
args.retro[p] = get_setting(settings['retro'], args.retro[p])
|
args.retro[p] = get_setting(settings['retro'], args.retro[p])
|
||||||
|
args.take_any[p] = get_setting(settings['take_any'], args.take_any[p])
|
||||||
args.hints[p] = get_setting(settings['hints'], args.hints[p])
|
args.hints[p] = get_setting(settings['hints'], args.hints[p])
|
||||||
args.shopsanity[p] = get_setting(settings['shopsanity'], args.shopsanity[p])
|
args.shopsanity[p] = get_setting(settings['shopsanity'], args.shopsanity[p])
|
||||||
args.dropshuffle[p] = get_setting(settings['dropshuffle'], args.dropshuffle[p])
|
args.dropshuffle[p] = get_setting(settings['dropshuffle'], args.dropshuffle[p])
|
||||||
@@ -191,11 +193,12 @@ class CustomSettings(object):
|
|||||||
settings_dict[p]['mode'] = world.mode[p]
|
settings_dict[p]['mode'] = world.mode[p]
|
||||||
settings_dict[p]['swords'] = world.swords[p]
|
settings_dict[p]['swords'] = world.swords[p]
|
||||||
settings_dict[p]['flute_mode'] = world.flute_mode[p]
|
settings_dict[p]['flute_mode'] = world.flute_mode[p]
|
||||||
|
settings_dict[p]['bow_mode'] = world.bow_mode[p]
|
||||||
settings_dict[p]['difficulty'] = world.difficulty[p]
|
settings_dict[p]['difficulty'] = world.difficulty[p]
|
||||||
settings_dict[p]['goal'] = world.goal[p]
|
settings_dict[p]['goal'] = world.goal[p]
|
||||||
settings_dict[p]['accessibility'] = world.accessibility[p]
|
settings_dict[p]['accessibility'] = world.accessibility[p]
|
||||||
settings_dict[p]['item_functionality'] = world.difficulty_adjustments[p]
|
settings_dict[p]['item_functionality'] = world.difficulty_adjustments[p]
|
||||||
settings_dict[p]['retro'] = world.retro[p]
|
settings_dict[p]['take_any'] = world.take_any[p]
|
||||||
settings_dict[p]['hints'] = world.hints[p]
|
settings_dict[p]['hints'] = world.hints[p]
|
||||||
settings_dict[p]['shopsanity'] = world.shopsanity[p]
|
settings_dict[p]['shopsanity'] = world.shopsanity[p]
|
||||||
settings_dict[p]['dropshuffle'] = world.dropshuffle[p]
|
settings_dict[p]['dropshuffle'] = world.dropshuffle[p]
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ SETTINGSTOPROCESS = {
|
|||||||
"weapons": "swords",
|
"weapons": "swords",
|
||||||
"itempool": "difficulty",
|
"itempool": "difficulty",
|
||||||
"flute_mode": "flute_mode",
|
"flute_mode": "flute_mode",
|
||||||
|
"bow_mode": "bow_mode",
|
||||||
"timer": "timer",
|
"timer": "timer",
|
||||||
"accessibility": "accessibility",
|
"accessibility": "accessibility",
|
||||||
"sortingalgo": "algorithm",
|
"sortingalgo": "algorithm",
|
||||||
@@ -81,6 +82,7 @@ SETTINGSTOPROCESS = {
|
|||||||
"shuffletavern": "shuffletavern",
|
"shuffletavern": "shuffletavern",
|
||||||
"entranceshuffle": "shuffle",
|
"entranceshuffle": "shuffle",
|
||||||
"overworld_map": "overworld_map",
|
"overworld_map": "overworld_map",
|
||||||
|
"take_any": "take_any",
|
||||||
},
|
},
|
||||||
"enemizer": {
|
"enemizer": {
|
||||||
"enemyshuffle": "shuffleenemies",
|
"enemyshuffle": "shuffleenemies",
|
||||||
|
|||||||
@@ -285,4 +285,12 @@ def create_guiargs(parent):
|
|||||||
guiargs.dropshuffle = 1
|
guiargs.dropshuffle = 1
|
||||||
guiargs.pottery = 'keys' if guiargs.pottery == 'none' else guiargs.pottery
|
guiargs.pottery = 'keys' if guiargs.pottery == 'none' else guiargs.pottery
|
||||||
|
|
||||||
|
if guiargs.retro or guiargs.mode == 'retro':
|
||||||
|
if guiargs.bow_mode == 'progressive':
|
||||||
|
guiargs.bow_mode = 'retro'
|
||||||
|
elif guiargs.bow_mode == 'silvers':
|
||||||
|
guiargs.bow_mode = 'retro_silvers'
|
||||||
|
guiargs.take_any = 'random' if guiargs.take_any == 'none' else guiargs.take_any
|
||||||
|
guiargs.keyshuffle = 'universal'
|
||||||
|
|
||||||
return guiargs
|
return guiargs
|
||||||
|
|||||||
+12
-9
@@ -82,10 +82,11 @@ def create_item_pool_config(world):
|
|||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
for item, locs in shop_vanilla_mapping.items():
|
for item, locs in shop_vanilla_mapping.items():
|
||||||
config.static_placement[player][item].extend(locs)
|
config.static_placement[player][item].extend(locs)
|
||||||
if world.retro[player]:
|
if world.take_any[player] != 'none':
|
||||||
for item, locs in retro_vanilla_mapping.items():
|
for item, locs in retro_vanilla_mapping.items():
|
||||||
config.static_placement[player][item].extend(locs)
|
config.static_placement[player][item].extend(locs)
|
||||||
# universal keys
|
# universal keys
|
||||||
|
if world.keyshuffle[player] == 'universal':
|
||||||
universal_key_locations = []
|
universal_key_locations = []
|
||||||
for item, locs in vanilla_mapping.items():
|
for item, locs in vanilla_mapping.items():
|
||||||
if 'Small Key' in item:
|
if 'Small Key' in item:
|
||||||
@@ -98,12 +99,13 @@ def create_item_pool_config(world):
|
|||||||
for item, locs in potkeys_vanilla_mapping.items():
|
for item, locs in potkeys_vanilla_mapping.items():
|
||||||
universal_key_locations.extend(locs)
|
universal_key_locations.extend(locs)
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
single_arrow_placement = list(shop_vanilla_mapping['Red Potion'])
|
|
||||||
single_arrow_placement.append('Red Shield Shop - Right')
|
|
||||||
config.static_placement[player]['Single Arrow'] = single_arrow_placement
|
|
||||||
universal_key_locations.extend(shop_vanilla_mapping['Small Heart'])
|
universal_key_locations.extend(shop_vanilla_mapping['Small Heart'])
|
||||||
universal_key_locations.extend(shop_vanilla_mapping['Blue Shield'])
|
universal_key_locations.extend(shop_vanilla_mapping['Blue Shield'])
|
||||||
config.static_placement[player]['Small Key (Universal)'] = universal_key_locations
|
config.static_placement[player]['Small Key (Universal)'] = universal_key_locations
|
||||||
|
if world.bow_mode[player].startswith('retro') and world.shopsanity[player]:
|
||||||
|
single_arrow_placement = list(shop_vanilla_mapping['Red Potion'])
|
||||||
|
single_arrow_placement.append('Red Shield Shop - Right')
|
||||||
|
config.static_placement[player]['Single Arrow'] = single_arrow_placement
|
||||||
config.location_groups[player] = [
|
config.location_groups[player] = [
|
||||||
LocationGroup('Major').locs(mode_grouping['Overworld Major'] + mode_grouping['Big Chests'] + mode_grouping['Heart Containers']),
|
LocationGroup('Major').locs(mode_grouping['Overworld Major'] + mode_grouping['Big Chests'] + mode_grouping['Heart Containers']),
|
||||||
LocationGroup('bkhp').locs(mode_grouping['Heart Pieces']),
|
LocationGroup('bkhp').locs(mode_grouping['Heart Pieces']),
|
||||||
@@ -124,7 +126,7 @@ def create_item_pool_config(world):
|
|||||||
groups.locations.extend(mode_grouping['Big Keys'])
|
groups.locations.extend(mode_grouping['Big Keys'])
|
||||||
if world.dropshuffle[player] != 'none':
|
if world.dropshuffle[player] != 'none':
|
||||||
groups.locations.extend(mode_grouping['Big Key Drops'])
|
groups.locations.extend(mode_grouping['Big Key Drops'])
|
||||||
if world.keyshuffle[player]:
|
if world.keyshuffle[player] != 'none':
|
||||||
groups.locations.extend(mode_grouping['Small Keys'])
|
groups.locations.extend(mode_grouping['Small Keys'])
|
||||||
if world.dropshuffle[player] != 'none':
|
if world.dropshuffle[player] != 'none':
|
||||||
groups.locations.extend(mode_grouping['Key Drops'])
|
groups.locations.extend(mode_grouping['Key Drops'])
|
||||||
@@ -137,7 +139,7 @@ def create_item_pool_config(world):
|
|||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
groups.locations.append('Capacity Upgrade - Left')
|
groups.locations.append('Capacity Upgrade - Left')
|
||||||
groups.locations.append('Capacity Upgrade - Right')
|
groups.locations.append('Capacity Upgrade - Right')
|
||||||
if world.retro[player]:
|
if world.take_any[player] != 'none':
|
||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
groups.locations.extend(retro_vanilla_mapping['Heart Container'])
|
groups.locations.extend(retro_vanilla_mapping['Heart Container'])
|
||||||
groups.locations.append('Old Man Sword Cave Item 1')
|
groups.locations.append('Old Man Sword Cave Item 1')
|
||||||
@@ -249,7 +251,7 @@ def previously_reserved(location, world, player):
|
|||||||
if world.restrict_boss_items[player] == 'dungeon' and (not world.compassshuffle[player]
|
if world.restrict_boss_items[player] == 'dungeon' and (not world.compassshuffle[player]
|
||||||
or not world.mapshuffle[player]
|
or not world.mapshuffle[player]
|
||||||
or not world.bigkeyshuffle[player]
|
or not world.bigkeyshuffle[player]
|
||||||
or not (world.keyshuffle[player] or world.retro[player])):
|
or world.keyshuffle[player] == 'standard'):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -335,7 +337,7 @@ def determine_major_items(world, player):
|
|||||||
pass # now what?
|
pass # now what?
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
major_item_set.update({x for x, y in item_table.items() if y[2] == 'BigKey'})
|
major_item_set.update({x for x, y in item_table.items() if y[2] == 'BigKey'})
|
||||||
if world.keyshuffle[player]:
|
if world.keyshuffle[player] != 'none':
|
||||||
major_item_set.update({x for x, y in item_table.items() if y[2] == 'SmallKey'})
|
major_item_set.update({x for x, y in item_table.items() if y[2] == 'SmallKey'})
|
||||||
if world.compassshuffle[player]:
|
if world.compassshuffle[player]:
|
||||||
major_item_set.update({x for x, y in item_table.items() if y[2] == 'Compass'})
|
major_item_set.update({x for x, y in item_table.items() if y[2] == 'Compass'})
|
||||||
@@ -344,8 +346,9 @@ def determine_major_items(world, player):
|
|||||||
if world.shopsanity[player]:
|
if world.shopsanity[player]:
|
||||||
major_item_set.add('Bomb Upgrade (+5)')
|
major_item_set.add('Bomb Upgrade (+5)')
|
||||||
major_item_set.add('Arrow Upgrade (+5)')
|
major_item_set.add('Arrow Upgrade (+5)')
|
||||||
if world.retro[player]:
|
if world.bow_mode[player].startswith('retro'):
|
||||||
major_item_set.add('Single Arrow')
|
major_item_set.add('Single Arrow')
|
||||||
|
if world.keyshuffle[player] == 'universal':
|
||||||
major_item_set.add('Small Key (Universal)')
|
major_item_set.add('Small Key (Universal)')
|
||||||
if world.goal == 'triforcehunt':
|
if world.goal == 'triforcehunt':
|
||||||
major_item_set.add('Triforce Piece')
|
major_item_set.add('Triforce Piece')
|
||||||
|
|||||||
@@ -64,7 +64,13 @@ def roll_settings(weights):
|
|||||||
dungeon_items = 'mcsb' if dungeon_items == 'full' else dungeon_items
|
dungeon_items = 'mcsb' if dungeon_items == 'full' else dungeon_items
|
||||||
ret.mapshuffle = get_choice('map_shuffle') == 'on' if 'map_shuffle' in weights else 'm' in dungeon_items
|
ret.mapshuffle = get_choice('map_shuffle') == 'on' if 'map_shuffle' in weights else 'm' in dungeon_items
|
||||||
ret.compassshuffle = get_choice('compass_shuffle') == 'on' if 'compass_shuffle' in weights else 'c' in dungeon_items
|
ret.compassshuffle = get_choice('compass_shuffle') == 'on' if 'compass_shuffle' in weights else 'c' in dungeon_items
|
||||||
ret.keyshuffle = get_choice('smallkey_shuffle') == 'on' if 'smallkey_shuffle' in weights else 's' in dungeon_items
|
if 'smallkey_shuffle' in weights:
|
||||||
|
ret.keyshuffle = get_choice('smallkey_shuffle')
|
||||||
|
else:
|
||||||
|
if 's' in dungeon_items:
|
||||||
|
ret.keyshuffle = 'wild'
|
||||||
|
if 'u' in dungeon_items:
|
||||||
|
ret.keyshuffle = 'universal'
|
||||||
ret.bigkeyshuffle = get_choice('bigkey_shuffle') == 'on' if 'bigkey_shuffle' in weights else 'b' in dungeon_items
|
ret.bigkeyshuffle = get_choice('bigkey_shuffle') == 'on' if 'bigkey_shuffle' in weights else 'b' in dungeon_items
|
||||||
|
|
||||||
ret.accessibility = get_choice('accessibility')
|
ret.accessibility = get_choice('accessibility')
|
||||||
@@ -130,6 +136,7 @@ def roll_settings(weights):
|
|||||||
ret.mode = 'open'
|
ret.mode = 'open'
|
||||||
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.take_any = get_choice_default('take_any', default='none')
|
||||||
|
|
||||||
ret.bombbag = get_choice('bombbag') == 'on'
|
ret.bombbag = get_choice('bombbag') == 'on'
|
||||||
|
|
||||||
@@ -145,6 +152,7 @@ def roll_settings(weights):
|
|||||||
|
|
||||||
ret.difficulty = get_choice('item_pool')
|
ret.difficulty = get_choice('item_pool')
|
||||||
ret.flute_mode = get_choice_default('flute_mode', default='normal')
|
ret.flute_mode = get_choice_default('flute_mode', default='normal')
|
||||||
|
ret.bow_mode = get_choice_default('bow_mode', default='progressive')
|
||||||
|
|
||||||
ret.item_functionality = get_choice('item_functionality')
|
ret.item_functionality = get_choice('item_functionality')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user