Added support for various avianart modes
Uncle boots hints Some key logic re-working unsure if safe
This commit is contained in:
@@ -514,6 +514,7 @@ class CollectionState(object):
|
|||||||
self.opened_doors = {player: set() for player in range(1, parent.players + 1)}
|
self.opened_doors = {player: set() for player in range(1, parent.players + 1)}
|
||||||
self.dungeons_to_check = {player: defaultdict(dict) for player in range(1, parent.players + 1)}
|
self.dungeons_to_check = {player: defaultdict(dict) for player in range(1, parent.players + 1)}
|
||||||
self.dungeon_limits = None
|
self.dungeon_limits = None
|
||||||
|
self.placing_item = None
|
||||||
# self.trace = None
|
# self.trace = None
|
||||||
|
|
||||||
def update_reachable_regions(self, player):
|
def update_reachable_regions(self, player):
|
||||||
@@ -787,7 +788,8 @@ class CollectionState(object):
|
|||||||
door_candidates.append(door.name)
|
door_candidates.append(door.name)
|
||||||
return door_candidates
|
return door_candidates
|
||||||
door_candidates, skip = [], set()
|
door_candidates, skip = [], set()
|
||||||
if state.world.accessibility[player] != 'locations' and remaining_keys == 0 and dungeon_name != 'Universal':
|
if (state.world.accessibility[player] != 'locations' and remaining_keys == 0 and dungeon_name != 'Universal'
|
||||||
|
and state.placing_item and state.placing_item.name == small_key_name):
|
||||||
key_logic = state.world.key_logic[player][dungeon_name]
|
key_logic = state.world.key_logic[player][dungeon_name]
|
||||||
for door, paired in key_logic.sm_doors.items():
|
for door, paired in key_logic.sm_doors.items():
|
||||||
if door.name in key_logic.door_rules:
|
if door.name in key_logic.door_rules:
|
||||||
@@ -830,6 +832,7 @@ class CollectionState(object):
|
|||||||
player: defaultdict(dict, {name: copy.copy(checklist)
|
player: defaultdict(dict, {name: copy.copy(checklist)
|
||||||
for name, checklist in self.dungeons_to_check[player].items()})
|
for name, checklist in self.dungeons_to_check[player].items()})
|
||||||
for player in range(1, self.world.players + 1)}
|
for player in range(1, self.world.players + 1)}
|
||||||
|
ret.placing_item = self.placing_item
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def apply_dungeon_exploration(self, rrp, player, dungeon_name, checklist):
|
def apply_dungeon_exploration(self, rrp, player, dungeon_name, checklist):
|
||||||
|
|||||||
3
CLI.py
3
CLI.py
@@ -124,7 +124,7 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
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', 'bow_mode', 'take_any',
|
'flute_mode', 'bow_mode', 'take_any', 'boots_hint',
|
||||||
'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',
|
||||||
@@ -161,6 +161,7 @@ def parse_settings():
|
|||||||
"retro": False,
|
"retro": False,
|
||||||
"bombbag": False,
|
"bombbag": False,
|
||||||
"mode": "open",
|
"mode": "open",
|
||||||
|
"boots_hint": False,
|
||||||
"logic": "noglitches",
|
"logic": "noglitches",
|
||||||
"goal": "ganon",
|
"goal": "ganon",
|
||||||
"crystals_gt": "7",
|
"crystals_gt": "7",
|
||||||
|
|||||||
19
Fill.py
19
Fill.py
@@ -24,7 +24,6 @@ def promote_dungeon_items(world):
|
|||||||
item.advancement = True
|
item.advancement = True
|
||||||
elif item.map or item.compass:
|
elif item.map or item.compass:
|
||||||
item.priority = True
|
item.priority = True
|
||||||
dungeon_tracking(world)
|
|
||||||
|
|
||||||
|
|
||||||
def dungeon_tracking(world):
|
def dungeon_tracking(world):
|
||||||
@@ -35,7 +34,6 @@ def dungeon_tracking(world):
|
|||||||
|
|
||||||
|
|
||||||
def fill_dungeons_restrictive(world, shuffled_locations):
|
def fill_dungeons_restrictive(world, shuffled_locations):
|
||||||
dungeon_tracking(world)
|
|
||||||
|
|
||||||
# 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():
|
||||||
@@ -73,11 +71,13 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
|
|
||||||
def fill_restrictive(world, base_state, locations, itempool, key_pool=None, single_player_placement=False,
|
def fill_restrictive(world, base_state, locations, itempool, key_pool=None, single_player_placement=False,
|
||||||
vanilla=False):
|
vanilla=False):
|
||||||
def sweep_from_pool():
|
def sweep_from_pool(placing_item=None):
|
||||||
new_state = base_state.copy()
|
new_state = base_state.copy()
|
||||||
for item in itempool:
|
for item in itempool:
|
||||||
new_state.collect(item, True)
|
new_state.collect(item, True)
|
||||||
|
new_state.placing_item = placing_item
|
||||||
new_state.sweep_for_events()
|
new_state.sweep_for_events()
|
||||||
|
new_state.placing_item = None
|
||||||
return new_state
|
return new_state
|
||||||
|
|
||||||
unplaced_items = []
|
unplaced_items = []
|
||||||
@@ -94,7 +94,7 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing
|
|||||||
while any(player_items.values()) and locations:
|
while any(player_items.values()) and locations:
|
||||||
items_to_place = [[itempool.remove(items[-1]), items.pop()][-1] for items in player_items.values() if items]
|
items_to_place = [[itempool.remove(items[-1]), items.pop()][-1] for items in player_items.values() if items]
|
||||||
|
|
||||||
maximum_exploration_state = sweep_from_pool()
|
maximum_exploration_state = sweep_from_pool(placing_item=items_to_place[0])
|
||||||
has_beaten_game = world.has_beaten_game(maximum_exploration_state)
|
has_beaten_game = world.has_beaten_game(maximum_exploration_state)
|
||||||
|
|
||||||
for item_to_place in items_to_place:
|
for item_to_place in items_to_place:
|
||||||
@@ -522,10 +522,17 @@ def fast_fill_helper(world, item_pool, fill_locations):
|
|||||||
|
|
||||||
|
|
||||||
def fast_fill(world, item_pool, fill_locations):
|
def fast_fill(world, item_pool, fill_locations):
|
||||||
while item_pool and fill_locations:
|
config = world.item_pool_config
|
||||||
|
fast_pool = [x for x in item_pool if (x.name, x.player) not in config.restricted]
|
||||||
|
filtered_pool = [x for x in item_pool if (x.name, x.player) in config.restricted]
|
||||||
|
filtered_fill(world, filtered_pool, fill_locations)
|
||||||
|
while fast_pool and fill_locations:
|
||||||
spot_to_fill = fill_locations.pop()
|
spot_to_fill = fill_locations.pop()
|
||||||
item_to_place = item_pool.pop()
|
item_to_place = fast_pool.pop()
|
||||||
world.push_item(spot_to_fill, item_to_place, False)
|
world.push_item(spot_to_fill, item_to_place, False)
|
||||||
|
item_pool.clear()
|
||||||
|
item_pool.extend(filtered_pool)
|
||||||
|
item_pool.extend(fast_pool)
|
||||||
|
|
||||||
|
|
||||||
def fast_fill_pot_for_multiworld(world, item_pool, fill_locations):
|
def fast_fill_pot_for_multiworld(world, item_pool, fill_locations):
|
||||||
|
|||||||
115
ItemList.py
115
ItemList.py
@@ -6,7 +6,7 @@ import RaceRandom as random
|
|||||||
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
|
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
|
||||||
from EntranceShuffle import connect_entrance
|
from EntranceShuffle import connect_entrance
|
||||||
from Regions import shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location
|
from Regions import shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location
|
||||||
from Fill import FillError, fill_restrictive, get_dungeon_item_pool, is_dungeon_item
|
from Fill import FillError, fill_restrictive, get_dungeon_item_pool, track_dungeon_items, track_outside_keys
|
||||||
from PotShuffle import vanilla_pots
|
from PotShuffle import vanilla_pots
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
|
|
||||||
@@ -391,8 +391,16 @@ def generate_itempool(world, player):
|
|||||||
custom_medallions = medal_map[player]
|
custom_medallions = medal_map[player]
|
||||||
if 'Misery Mire' in custom_medallions:
|
if 'Misery Mire' in custom_medallions:
|
||||||
mm_medallion = custom_medallions['Misery Mire']
|
mm_medallion = custom_medallions['Misery Mire']
|
||||||
|
if isinstance(mm_medallion, dict):
|
||||||
|
mm_medallion = random.choices(list(mm_medallion.keys()), list(mm_medallion.values()), k=1)[0]
|
||||||
|
if mm_medallion == 'Random':
|
||||||
|
mm_medallion = None
|
||||||
if 'Turtle Rock' in custom_medallions:
|
if 'Turtle Rock' in custom_medallions:
|
||||||
tr_medallion = custom_medallions['Turtle Rock']
|
tr_medallion = custom_medallions['Turtle Rock']
|
||||||
|
if isinstance(tr_medallion, dict):
|
||||||
|
tr_medallion = random.choices(list(tr_medallion.keys()), list(tr_medallion.values()), k=1)[0]
|
||||||
|
if tr_medallion == 'Random':
|
||||||
|
tr_medallion = None
|
||||||
if not mm_medallion:
|
if not mm_medallion:
|
||||||
mm_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
mm_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
||||||
if not tr_medallion:
|
if not tr_medallion:
|
||||||
@@ -1261,31 +1269,86 @@ def fill_specific_items(world):
|
|||||||
for player, placement_list in placements.items():
|
for player, placement_list in placements.items():
|
||||||
for location, item in placement_list.items():
|
for location, item in placement_list.items():
|
||||||
loc = world.get_location(location, player)
|
loc = world.get_location(location, player)
|
||||||
item_parts = item.split('#')
|
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
||||||
item_player = player if len(item_parts) < 2 else int(item_parts[1])
|
dungeon_pool, prize_set, prize_pool)
|
||||||
item_name = item_parts[0]
|
if item_to_place:
|
||||||
event_flag = False
|
world.push_item(loc, item_to_place, False)
|
||||||
if is_dungeon_item(item_name, world, item_player):
|
track_outside_keys(item_to_place, loc, world)
|
||||||
item_to_place = next(x for x in dungeon_pool
|
track_dungeon_items(item_to_place, loc, world)
|
||||||
if x.name == item_name and x.player == item_player)
|
loc.event = event_flag or item_to_place.advancement
|
||||||
dungeon_pool.remove(item_to_place)
|
advanced_placements = world.customizer.get_advanced_placements()
|
||||||
event_flag = True
|
if advanced_placements:
|
||||||
elif item_name in prize_set:
|
for player, placement_list in advanced_placements.items():
|
||||||
item_player = player # prizes must be for that player
|
for placement in placement_list:
|
||||||
item_to_place = ItemFactory(item_name, item_player)
|
if placement['type'] == 'LocationGroup':
|
||||||
prize_pool.remove(item_name)
|
item = placement['item']
|
||||||
event_flag = True
|
item_to_place, event_flag = get_item_and_event_flag(item, world, player,
|
||||||
else:
|
dungeon_pool, prize_set, prize_pool)
|
||||||
item_to_place = next((x for x in world.itempool
|
if not item_to_place:
|
||||||
if x.name == item_name and x.player == item_player), None)
|
continue
|
||||||
if item_to_place is None:
|
locations = placement['locations']
|
||||||
item_to_place = ItemFactory(item_name, player)
|
handled = False
|
||||||
else:
|
while not handled:
|
||||||
world.itempool.remove(item_to_place)
|
if isinstance(locations, dict):
|
||||||
world.push_item(loc, item_to_place, False)
|
chosen_loc = random.choices(list(locations.keys()), list(locations.values()), k=1)[0]
|
||||||
# track_outside_keys(item_to_place, spot_to_fill, world)
|
else: # if isinstance(locations, list):
|
||||||
# track_dungeon_items(item_to_place, spot_to_fill, world)
|
chosen_loc = random.choice(locations)
|
||||||
loc.event = event_flag or item_to_place.advancement
|
if chosen_loc == 'Random':
|
||||||
|
if is_dungeon_item(item_to_place.name, world, item_to_place.player):
|
||||||
|
dungeon_pool.append(item_to_place)
|
||||||
|
elif item_to_place.name in prize_set:
|
||||||
|
prize_pool.append(item_to_place.name)
|
||||||
|
else:
|
||||||
|
world.itempool.append(item_to_place)
|
||||||
|
else:
|
||||||
|
loc = world.get_location(chosen_loc, player)
|
||||||
|
if loc.item:
|
||||||
|
continue
|
||||||
|
world.push_item(loc, item_to_place, False)
|
||||||
|
track_outside_keys(item_to_place, loc, world)
|
||||||
|
track_dungeon_items(item_to_place, loc, world)
|
||||||
|
loc.event = (event_flag or item_to_place.advancement
|
||||||
|
or item_to_place.bigkey or item_to_place.smallkey)
|
||||||
|
handled = True
|
||||||
|
elif placement['type'] == 'NotLocationGroup':
|
||||||
|
item = placement['item']
|
||||||
|
item_parts = item.split('#')
|
||||||
|
item_player = player if len(item_parts) < 2 else int(item_parts[1])
|
||||||
|
item_name = item_parts[0]
|
||||||
|
world.item_pool_config.restricted[(item_name, item_player)] = placement['locations']
|
||||||
|
elif placement['type'] == 'PreferredLocationGroup':
|
||||||
|
item = placement['item']
|
||||||
|
item_parts = item.split('#')
|
||||||
|
item_player = player if len(item_parts) < 2 else int(item_parts[1])
|
||||||
|
item_name = item_parts[0]
|
||||||
|
world.item_pool_config.preferred[(item_name, item_player)] = placement['locations']
|
||||||
|
|
||||||
|
|
||||||
|
def get_item_and_event_flag(item, world, player, dungeon_pool, prize_set, prize_pool):
|
||||||
|
item_parts = item.split('#')
|
||||||
|
item_player = player if len(item_parts) < 2 else int(item_parts[1])
|
||||||
|
item_name = item_parts[0]
|
||||||
|
event_flag = False
|
||||||
|
if is_dungeon_item(item_name, world, item_player):
|
||||||
|
item_to_place = next(x for x in dungeon_pool
|
||||||
|
if x.name == item_name and x.player == item_player)
|
||||||
|
dungeon_pool.remove(item_to_place)
|
||||||
|
event_flag = True
|
||||||
|
elif item_name in prize_set:
|
||||||
|
item_player = player # prizes must be for that player
|
||||||
|
item_to_place = ItemFactory(item_name, item_player)
|
||||||
|
prize_pool.remove(item_name)
|
||||||
|
event_flag = True
|
||||||
|
else:
|
||||||
|
matcher = lambda x: x.name == item_name and x.player == item_player
|
||||||
|
if item_name == 'Bottle':
|
||||||
|
matcher = lambda x: x.name.startswith(item_name) and x.player == item_player
|
||||||
|
item_to_place = next((x for x in world.itempool if matcher(x)), None)
|
||||||
|
if item_to_place is None:
|
||||||
|
return None, event_flag
|
||||||
|
else:
|
||||||
|
world.itempool.remove(item_to_place)
|
||||||
|
return item_to_place, event_flag
|
||||||
|
|
||||||
|
|
||||||
def is_dungeon_item(item, world, player):
|
def is_dungeon_item(item, world, player):
|
||||||
|
|||||||
2
Items.py
2
Items.py
@@ -83,7 +83,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
|
|||||||
'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
|
'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
|
||||||
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
|
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
|
||||||
'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
|
'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
|
||||||
'Chicken': (False, False, None, 0x5A, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
|
'Chicken': (False, False, None, 0x5A, 5, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
|
||||||
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
|
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
|
||||||
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
|
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
|
||||||
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
||||||
|
|||||||
@@ -301,10 +301,10 @@ def analyze_dungeon(key_layout, world, player):
|
|||||||
key_logic.bk_restricted.update(filter_big_chest(key_counter.free_locations))
|
key_logic.bk_restricted.update(filter_big_chest(key_counter.free_locations))
|
||||||
# note to self: this is due to the enough_small_locations function in validate_key_layout_sub_loop
|
# note to self: this is due to the enough_small_locations function in validate_key_layout_sub_loop
|
||||||
# I don't like this exception here or there
|
# I don't like this exception here or there
|
||||||
elif available < possible_smalls and avail_bigs and non_big_locs > 0:
|
# elif available < possible_smalls and avail_bigs and non_big_locs > 0:
|
||||||
max_ctr = find_max_counter(key_layout)
|
# max_ctr = find_max_counter(key_layout)
|
||||||
bk_lockdown = [x for x in max_ctr.free_locations if x not in key_counter.free_locations]
|
# bk_lockdown = [x for x in max_ctr.free_locations if x not in key_counter.free_locations]
|
||||||
key_logic.bk_restricted.update(filter_big_chest(bk_lockdown))
|
# key_logic.bk_restricted.update(filter_big_chest(bk_lockdown))
|
||||||
# try to relax the rules here? - smallest requirement that doesn't force a softlock
|
# try to relax the rules here? - smallest requirement that doesn't force a softlock
|
||||||
child_queue = deque()
|
child_queue = deque()
|
||||||
for child in key_counter.child_doors.keys():
|
for child in key_counter.child_doors.keys():
|
||||||
@@ -1489,7 +1489,7 @@ def validate_key_layout_sub_loop(key_layout, state, checked_states, flat_proposa
|
|||||||
# todo: allow more key shuffles - refine placement rules
|
# todo: allow more key shuffles - refine placement rules
|
||||||
# if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
|
# if (not smalls_avail or available_small_locations == 0) and (state.big_key_opened or num_bigs == 0 or available_big_locations == 0):
|
||||||
found_forced_bk = state.found_forced_bk()
|
found_forced_bk = state.found_forced_bk()
|
||||||
smalls_done = not smalls_avail or not enough_small_locations(state, available_small_locations)
|
smalls_done = not smalls_avail # or not enough_small_locations(state, available_small_locations)
|
||||||
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
bk_done = state.big_key_opened or num_bigs == 0 or (available_big_locations == 0 and not found_forced_bk)
|
||||||
# prize door should not be opened if the boss is reachable - but not reached yet
|
# prize door should not be opened if the boss is reachable - but not reached yet
|
||||||
allow_for_prize_lock = (key_layout.prize_can_lock and
|
allow_for_prize_lock = (key_layout.prize_can_lock and
|
||||||
|
|||||||
18
Main.py
18
Main.py
@@ -24,6 +24,7 @@ from RoomData import create_rooms
|
|||||||
from Rules import set_rules
|
from Rules import set_rules
|
||||||
from Dungeons import create_dungeons
|
from Dungeons import create_dungeons
|
||||||
from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive, ensure_good_pots
|
from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive, ensure_good_pots
|
||||||
|
from Fill import dungeon_tracking
|
||||||
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations
|
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations
|
||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
@@ -69,9 +70,8 @@ def main(args, seed=None, fish=None):
|
|||||||
if args.customizer:
|
if args.customizer:
|
||||||
customized = CustomSettings()
|
customized = CustomSettings()
|
||||||
customized.load_yaml(args.customizer)
|
customized.load_yaml(args.customizer)
|
||||||
seed = customized.determine_seed()
|
seed = customized.determine_seed(seed)
|
||||||
if seed:
|
seeded = True
|
||||||
seeded = True
|
|
||||||
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,
|
||||||
@@ -89,6 +89,7 @@ def main(args, seed=None, fish=None):
|
|||||||
if args.securerandom:
|
if args.securerandom:
|
||||||
world.seed = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(9))
|
world.seed = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(9))
|
||||||
|
|
||||||
|
world.boots_hint = args.boots_hint.copy()
|
||||||
world.remote_items = args.remote_items.copy()
|
world.remote_items = args.remote_items.copy()
|
||||||
world.mapshuffle = args.mapshuffle.copy()
|
world.mapshuffle = args.mapshuffle.copy()
|
||||||
world.compassshuffle = args.compassshuffle.copy()
|
world.compassshuffle = args.compassshuffle.copy()
|
||||||
@@ -195,6 +196,16 @@ def main(args, seed=None, fish=None):
|
|||||||
item = ItemFactory(inv_item.strip(), p)
|
item = ItemFactory(inv_item.strip(), p)
|
||||||
if item:
|
if item:
|
||||||
world.push_precollected(item)
|
world.push_precollected(item)
|
||||||
|
if item.dungeon:
|
||||||
|
d = world.get_dungeon(item.dungeon, item.player)
|
||||||
|
match = next((i for i in d.all_items if i.name == item.name), None)
|
||||||
|
if match:
|
||||||
|
if match.map or match.compass:
|
||||||
|
d.dungeon_items.remove(match)
|
||||||
|
elif match.smallkey:
|
||||||
|
d.small_keys.remove(match)
|
||||||
|
elif match.bigkey:
|
||||||
|
d.big_key.remove(match)
|
||||||
if args.print_custom_yaml:
|
if args.print_custom_yaml:
|
||||||
world.settings.record_info(world)
|
world.settings.record_info(world)
|
||||||
|
|
||||||
@@ -258,6 +269,7 @@ def main(args, seed=None, fish=None):
|
|||||||
massage_item_pool(world)
|
massage_item_pool(world)
|
||||||
if args.print_custom_yaml:
|
if args.print_custom_yaml:
|
||||||
world.settings.record_item_pool(world)
|
world.settings.record_item_pool(world)
|
||||||
|
dungeon_tracking(world)
|
||||||
fill_specific_items(world)
|
fill_specific_items(world)
|
||||||
logger.info(world.fish.translate("cli", "cli", "placing.dungeon.prizes"))
|
logger.info(world.fish.translate("cli", "cli", "placing.dungeon.prizes"))
|
||||||
|
|
||||||
|
|||||||
60
Rom.py
60
Rom.py
@@ -1084,9 +1084,14 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x178000 + i, random.randint(0, 255))
|
rom.write_byte(0x178000 + i, random.randint(0, 255))
|
||||||
|
|
||||||
# shuffle prize packs
|
# shuffle prize packs
|
||||||
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0, 0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF,
|
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9,
|
||||||
0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC, 0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2, 0xDF, 0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8,
|
0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA,
|
||||||
0xD8, 0xE3, 0xE0, 0xDB, 0xDE, 0xD8, 0xDB, 0xE2, 0xD9, 0xDA, 0xDB, 0xD9, 0xDB, 0xD9, 0xDB]
|
0xE0, 0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF,
|
||||||
|
0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC,
|
||||||
|
0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2,
|
||||||
|
0xDF, 0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8,
|
||||||
|
0xD8, 0xE3, 0xE0, 0xDB, 0xDE, 0xD8, 0xDB, 0xE2,
|
||||||
|
0xD9, 0xDA, 0xDB, 0xD9, 0xDB, 0xD9, 0xDB]
|
||||||
dig_prizes = [0xB2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
|
dig_prizes = [0xB2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
|
||||||
0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
|
0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
|
||||||
0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
|
0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
|
||||||
@@ -1099,13 +1104,41 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
return [l[i:i+n] for i in range(0, len(l), n)]
|
return [l[i:i+n] for i in range(0, len(l), n)]
|
||||||
|
|
||||||
# randomize last 7 slots
|
# randomize last 7 slots
|
||||||
prizes [-7:] = random.sample(prizes, 7)
|
possible_prizes = {
|
||||||
|
'Small Heart': 0xD8, 'Fairy': 0xE3,
|
||||||
|
'Rupee (1)': 0xD9, 'Rupees (5)': 0xDA, 'Rupees (20)': 0xDB,
|
||||||
|
'Big Magic': 0xE0, 'Small Magic': 0xDF,
|
||||||
|
'Single Bomb': 0xDC, 'Bombs (4)': 0xDD,
|
||||||
|
'Bombs (8)': 0xDE, 'Arrows (5)': 0xE1, 'Arrows (10)': 0xE2
|
||||||
|
} #weights, if desired 13, 1, 9, 7, 6, 3, 6, 7, 1, 2, 5, 3
|
||||||
|
uniform_prizes = list(possible_prizes.values())
|
||||||
|
prizes[-7:] = random.sample(prizes, 7)
|
||||||
|
|
||||||
#shuffle order of 7 main packs
|
#shuffle order of 7 main packs
|
||||||
packs = chunk(prizes[:56], 8)
|
packs = chunk(prizes[:56], 8)
|
||||||
random.shuffle(packs)
|
random.shuffle(packs)
|
||||||
prizes[:56] = [drop for pack in packs for drop in pack]
|
prizes[:56] = [drop for pack in packs for drop in pack]
|
||||||
|
|
||||||
|
if world.customizer:
|
||||||
|
drops = world.customizer.get_drops()
|
||||||
|
if drops:
|
||||||
|
for player, drop_config in drops.items():
|
||||||
|
for pack_num in range(1, 8):
|
||||||
|
if f'Pack {pack_num}' in drop_config:
|
||||||
|
for prize, idx in enumerate(drop_config[f'Pack {pack_num}']):
|
||||||
|
chosen = random.choice(uniform_prizes) if prize == 'Random' else possible_prizes[prize]
|
||||||
|
prizes[(pack_num-1)*8 + idx] = chosen
|
||||||
|
for tree_pull_tier in range(1, 4):
|
||||||
|
if f'Tree Pull Tier {tree_pull_tier}' in drop_config:
|
||||||
|
prize = drop_config[f'Tree Pull Tier {tree_pull_tier}']
|
||||||
|
chosen = random.choice(uniform_prizes) if prize == 'Random' else possible_prizes[prize]
|
||||||
|
prizes[63-tree_pull_tier] = chosen # (62 through 60 in reverse)
|
||||||
|
for key, pos in {'Crab Normal': 59, 'Crab Special': 58, 'Stun Prize': 57, 'Fish': 56}.items():
|
||||||
|
if key in drop_config:
|
||||||
|
prize = drop_config[key]
|
||||||
|
chosen = random.choice(uniform_prizes) if prize == 'Random' else possible_prizes[prize]
|
||||||
|
prizes[pos] = chosen
|
||||||
|
|
||||||
if world.difficulty_adjustments[player] in ['hard', 'expert']:
|
if world.difficulty_adjustments[player] in ['hard', 'expert']:
|
||||||
prize_replacements = {0xE0: 0xDF, # Fairy -> heart
|
prize_replacements = {0xE0: 0xDF, # Fairy -> heart
|
||||||
0xE3: 0xD8} # Big magic -> small magic
|
0xE3: 0xD8} # Big magic -> small magic
|
||||||
@@ -2290,7 +2323,24 @@ def write_strings(rom, world, player, team):
|
|||||||
if world.goal[player] in ['dungeons']:
|
if world.goal[player] in ['dungeons']:
|
||||||
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
||||||
|
|
||||||
tt['uncle_leaving_text'] = Uncle_texts[random.randint(0, len(Uncle_texts) - 1)]
|
if world.boots_hint[player]:
|
||||||
|
starting_boots = next((i for i in world.precollected_items if i.player == player
|
||||||
|
and i.name == 'Pegasus Boots'), None)
|
||||||
|
if starting_boots:
|
||||||
|
uncle_text = 'Lonk! Boots\nare on\nyour feet.'
|
||||||
|
else:
|
||||||
|
boots_location = next((l for l in world.get_locations()
|
||||||
|
if l.player == player and l.item and l.item.name == 'Pegasus Boots'), None)
|
||||||
|
if boots_location:
|
||||||
|
district = next((d for k, d in world.districts[player].items()
|
||||||
|
if boots_location.name in d.locations), 'Zebes')
|
||||||
|
uncle_text = f'Lonk! Boots\nare in {district.name}'
|
||||||
|
else:
|
||||||
|
uncle_text = "I couldn't\nfind the Boots\ntoday.\nRIP me."
|
||||||
|
|
||||||
|
tt['uncle_leaving_text'] = uncle_text
|
||||||
|
else:
|
||||||
|
tt['uncle_leaving_text'] = Uncle_texts[random.randint(0, len(Uncle_texts) - 1)]
|
||||||
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[random.randint(0, len(Triforce_texts) - 1)]
|
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[random.randint(0, len(Triforce_texts) - 1)]
|
||||||
tt['bomb_shop_big_bomb'] = BombShop2_texts[random.randint(0, len(BombShop2_texts) - 1)]
|
tt['bomb_shop_big_bomb'] = BombShop2_texts[random.randint(0, len(BombShop2_texts) - 1)]
|
||||||
|
|
||||||
|
|||||||
4
Rules.py
4
Rules.py
@@ -2091,8 +2091,8 @@ def eval_small_key_door_main(state, door_name, dungeon, player):
|
|||||||
if ruleType == KeyRuleType.WorstCase:
|
if ruleType == KeyRuleType.WorstCase:
|
||||||
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
||||||
elif ruleType == KeyRuleType.AllowSmall:
|
elif ruleType == KeyRuleType.AllowSmall:
|
||||||
if (door_rule.small_location.item and door_rule.small_location.item.name == key_logic.small_key_name
|
small_loc_item = door_rule.small_location.item
|
||||||
and door_rule.small_location.item.player == player):
|
if small_loc_item and small_loc_item.name == key_logic.small_key_name and small_loc_item.player == player:
|
||||||
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
door_openable |= state.has_sm_key(key_logic.small_key_name, player, number)
|
||||||
elif isinstance(ruleType, tuple):
|
elif isinstance(ruleType, tuple):
|
||||||
lock, lock_item = ruleType
|
lock, lock_item = ruleType
|
||||||
|
|||||||
2
Text.py
2
Text.py
@@ -1716,7 +1716,7 @@ class TextTable(object):
|
|||||||
text['game_shooting_choice'] = CompressedTextMapper.convert("20 rupees.\n5 arrows.\nWin rupees!\nWant to play?\n ≥ Yes\n No\n{CHOICE}")
|
text['game_shooting_choice'] = CompressedTextMapper.convert("20 rupees.\n5 arrows.\nWin rupees!\nWant to play?\n ≥ Yes\n No\n{CHOICE}")
|
||||||
text['game_shooting_yes'] = CompressedTextMapper.convert("Let's do this!")
|
text['game_shooting_yes'] = CompressedTextMapper.convert("Let's do this!")
|
||||||
text['game_shooting_no'] = CompressedTextMapper.convert("Where are you going? Straight up!")
|
text['game_shooting_no'] = CompressedTextMapper.convert("Where are you going? Straight up!")
|
||||||
text['game_shooting_continue'] = CompressedTextMapper.convert("Keep playing?\n ≥ yes\n no\n{CHOICE}")
|
text['game_shooting_continue'] = CompressedTextMapper.convert("Keep playing?\n ≥ Yes\n No\n{CHOICE}")
|
||||||
text['pond_of_wishing'] = CompressedTextMapper.convert("-Wishing Pond-\n\n On Vacation")
|
text['pond_of_wishing'] = CompressedTextMapper.convert("-Wishing Pond-\n\n On Vacation")
|
||||||
text['pond_item_select'] = CompressedTextMapper.convert("Pick something\nto throw in.\n{ITEMSELECT}")
|
text['pond_item_select'] = CompressedTextMapper.convert("Pick something\nto throw in.\n{ITEMSELECT}")
|
||||||
text['pond_item_test'] = CompressedTextMapper.convert("You toss this?\n ≥ Yup\n Wrong\n{CHOICE}")
|
text['pond_item_test'] = CompressedTextMapper.convert("You toss this?\n ≥ Yup\n Wrong\n{CHOICE}")
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ in each player section you can set up default settings for that player or you ca
|
|||||||
door_shuffle: basic
|
door_shuffle: basic
|
||||||
```
|
```
|
||||||
|
|
||||||
Player 1's settings will be determined by rolling the mystery weights and player 2's setting will be default except for those two specified in his section. Each settings should be consistent with the CLI arguments.
|
Player 1's settings will be determined by rolling the mystery weights and player 2's setting will be default except for those two specified in his section. Each setting should be consistent with the CLI arguments. Simple weighted settings are supported here. If you need sub-weights though, use a separate yaml file.
|
||||||
|
|
||||||
Start inventory is not supported here. It has a separate section.
|
Start inventory is not supported here. It has a separate section.
|
||||||
|
|
||||||
@@ -71,7 +71,21 @@ You may list each location for a player and the item you wish to place there. A
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
`Pegasus Boots#3` means the boots for player 3.
|
`Pegasus Boots#3` means the boots for player 3.
|
||||||
|
|
||||||
|
|
||||||
|
### advanced_placements
|
||||||
|
|
||||||
|
This must be defined by player. Each player number should be listed with the appropriate section. Each section is a list of placement rules. Each placement rule has a specific type.
|
||||||
|
|
||||||
|
Supported Types: PlacementGroup, NotPlacmentGroup
|
||||||
|
|
||||||
|
#### PlacementGroup
|
||||||
|
|
||||||
|
You may define an item, and a list of locations. The locations may be weighted if desired. The item will be placed at one of the listed locations - this currently ignores logic. The item will be placed there. The special location 'Random' indicates that the item should be placed randomly, without any other consideration. This may be repeated for placement of multiple items like multiple bows or swords.
|
||||||
|
|
||||||
|
#### NotPlacementGroup
|
||||||
|
|
||||||
|
You may define an item and a list of locations that an item should not be placed at. This will apply to all items of that type. The logic is considered for this. If it is otherwise impossible, the item will be considered for the listed locations. This is important for small key layouts mostly, but it will try other locations first.
|
||||||
|
|
||||||
### entrances
|
### entrances
|
||||||
|
|
||||||
@@ -144,7 +158,7 @@ Misery Mire: Ether
|
|||||||
Turtle Rock: Quake
|
Turtle Rock: Quake
|
||||||
```
|
```
|
||||||
|
|
||||||
Leave blank or omit if you wish it to be random.
|
Leave blank or omit if you wish it to be random. Alternatively, a weighted dictionary is supported and a 'Random' option
|
||||||
|
|
||||||
### bosses
|
### bosses
|
||||||
|
|
||||||
@@ -173,4 +187,27 @@ To start with multiple copies of progressive items, list them more than once.
|
|||||||
|
|
||||||
This conflicts with the mystery yaml, if specified. These start inventory items will be added after those are added.
|
This conflicts with the mystery yaml, if specified. These start inventory items will be added after those are added.
|
||||||
|
|
||||||
|
### drops
|
||||||
|
|
||||||
|
This must be defined by player. You may have prize packs, tree pulls, crab drops, stun prizes, and the fish prize defined using the following keys:
|
||||||
|
```
|
||||||
|
drops:
|
||||||
|
1:
|
||||||
|
Pack 1
|
||||||
|
- Small Heart
|
||||||
|
- Bombs (4)
|
||||||
|
- Random
|
||||||
|
- etc
|
||||||
|
Pack 2: (list)
|
||||||
|
...
|
||||||
|
Pack 7: (list)
|
||||||
|
Tree Pull Tier 1: Single Bomb
|
||||||
|
Tree Pull Tier 2: Arrows (10)
|
||||||
|
Tree Pull Tier 3: Fairy
|
||||||
|
Crab Normal: Rupees (20)
|
||||||
|
Crab Special: Small Magic
|
||||||
|
Stun Prize: Bombs (8)
|
||||||
|
Fish: Big Magic
|
||||||
|
```
|
||||||
|
|
||||||
|
Prize packs expect a list of eight items each (anything not specified will be whatever randomization would have normally occurred). The special drops expect a single item. Packs 1 through 7 are supported. Prize pack 0 is not customizable.
|
||||||
1036
docs/antivanilla.yaml
Normal file
1036
docs/antivanilla.yaml
Normal file
File diff suppressed because it is too large
Load Diff
41
docs/avianart/antivrosia.yaml
Normal file
41
docs/avianart/antivrosia.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
mode: inverted
|
||||||
|
mapshuffle: True
|
||||||
|
keyshuffle: wild
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Link's Uncle: Progressive Sword
|
||||||
|
Blacksmith: Progressive Sword
|
||||||
|
Master Sword Pedestal: Progressive Sword
|
||||||
|
Pyramid Fairy - Left: Progressive Sword
|
||||||
|
Desert Palace - Boss: Compass (Desert Palace)
|
||||||
|
Eastern Palace - Boss: Compass (Eastern Palace)
|
||||||
|
Tower of Hera - Boss: Compass (Tower of Hera)
|
||||||
|
Swamp Palace - Boss: Compass (Swamp Palace)
|
||||||
|
Thieves' Town - Boss: Compass (Thieves Town)
|
||||||
|
Skull Woods - Boss: Compass (Skull Woods)
|
||||||
|
Ice Palace - Boss: Compass (Ice Palace)
|
||||||
|
Misery Mire - Boss: Compass (Misery Mire)
|
||||||
|
Turtle Rock - Boss: Compass (Turtle Rock)
|
||||||
|
Palace of Darkness - Boss: Compass (Palace of Darkness)
|
||||||
|
Eastern Palace - Big Key Chest: Big Key (Eastern Palace)
|
||||||
|
Desert Palace - Big Key Chest: Big Key (Desert Palace)
|
||||||
|
Tower of Hera - Big Key Chest: Big Key (Tower of Hera)
|
||||||
|
Palace of Darkness - Big Key Chest: Big Key (Palace of Darkness)
|
||||||
|
Thieves' Town - Big Key Chest: Big Key (Thieves Town)
|
||||||
|
Skull Woods - Big Key Chest: Big Key (Skull Woods)
|
||||||
|
Swamp Palace - Big Key Chest: Big Key (Swamp Palace)
|
||||||
|
Ice Palace - Big Key Chest: Big Key (Ice Palace)
|
||||||
|
Misery Mire - Big Key Chest: Big Key (Misery Mire)
|
||||||
|
Turtle Rock - Big Key Chest: Big Key (Turtle Rock)
|
||||||
|
Ganons Tower - Big Key Chest: Big Key (Ganons Tower)
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Ocarina (Activated)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
73
docs/avianart/invertacrismiser.yaml
Normal file
73
docs/avianart/invertacrismiser.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
mode: inverted
|
||||||
|
goal: dungeons
|
||||||
|
shuffleenemies: shuffled
|
||||||
|
shufflebosses: full
|
||||||
|
item_pool:
|
||||||
|
1:
|
||||||
|
Progressive Bow: 8
|
||||||
|
Blue Boomerang: 4
|
||||||
|
Red Boomerang: 4
|
||||||
|
Hookshot: 4
|
||||||
|
Magic Powder: 4
|
||||||
|
Mushroom: 4
|
||||||
|
Ice Rod: 4
|
||||||
|
Fire Rod: 4
|
||||||
|
Bombos: 4
|
||||||
|
Ether: 4
|
||||||
|
Quake: 4
|
||||||
|
Lamp: 4
|
||||||
|
Hammer: 4
|
||||||
|
Ocarina: 4
|
||||||
|
Shovel: 4
|
||||||
|
Bug Catching Net: 4
|
||||||
|
Book of Mudora: 4
|
||||||
|
Bottle (Random): 16
|
||||||
|
Cane of Byrna: 4
|
||||||
|
Cane of Somaria: 4
|
||||||
|
Cape: 4
|
||||||
|
Magic Mirror: 4
|
||||||
|
Flippers: 4
|
||||||
|
Moon Pearl: 4
|
||||||
|
Pegasus Boots: 4
|
||||||
|
Progressive Glove: 8
|
||||||
|
Progressive Armor: 8
|
||||||
|
Progressive Shield: 12
|
||||||
|
Progressive Sword: 16
|
||||||
|
Magic Upgrade (1/2): 4
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Boss Heart Container
|
||||||
|
- Pegasus Boots
|
||||||
|
- Rupees (5)
|
||||||
|
- Rupees (5)
|
||||||
|
- Rupees (5)
|
||||||
|
- Rupee (1)
|
||||||
|
- Rupee (1)
|
||||||
|
- Rupee (1)
|
||||||
|
- Rupee (1)
|
||||||
|
- Compass (Desert Palace)
|
||||||
|
- Compass (Eastern Palace)
|
||||||
|
- Compass (Tower of Hera)
|
||||||
|
- Compass (Swamp Palace)
|
||||||
|
- Compass (Thieves Town)
|
||||||
|
- Compass (Skull Woods)
|
||||||
|
- Compass (Ice Palace)
|
||||||
|
- Compass (Misery Mire)
|
||||||
|
- Compass (Turtle Rock)
|
||||||
|
- Compass (Palace of Darkness)
|
||||||
|
- Compass (Ganons Tower)
|
||||||
|
drops:
|
||||||
|
1:
|
||||||
|
Tree Pull Tier 1: Single Bomb
|
||||||
|
Tree Pull Tier 2: Bombs (4)
|
||||||
|
Tree Pull Tier 3: Bombs (8)
|
||||||
|
Crab Normal: Rupees (20)
|
||||||
|
Crab Special: Big Magic
|
||||||
|
Stun Prize: Rupees (20)
|
||||||
443
docs/avianart/is_this_even_randomized.yaml
Normal file
443
docs/avianart/is_this_even_randomized.yaml
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
mode:
|
||||||
|
open: 1
|
||||||
|
standard: 1
|
||||||
|
mapshuffle: True
|
||||||
|
compassshuffle: True
|
||||||
|
boots_hint:
|
||||||
|
True: 1
|
||||||
|
False: 1
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- item: Green Pendant
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Prize
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Crystal 5
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Prize
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Crystal 6
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Prize
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Bow
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Bow
|
||||||
|
locations:
|
||||||
|
- Pyramid Fairy - Right
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Book of Mudora
|
||||||
|
locations:
|
||||||
|
- Library
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Hammer
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Hookshot
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Magic Mirror
|
||||||
|
locations:
|
||||||
|
- Old Man
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Ocarina
|
||||||
|
locations:
|
||||||
|
- Flute Spot
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Pegasus Boots
|
||||||
|
locations:
|
||||||
|
- Sahasrahla
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Cape
|
||||||
|
locations:
|
||||||
|
- King's Tomb
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Mushroom
|
||||||
|
locations:
|
||||||
|
- Mushroom
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Shovel
|
||||||
|
locations:
|
||||||
|
- Stumpy
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Lamp
|
||||||
|
locations:
|
||||||
|
Link's House: 1
|
||||||
|
Secret Passage: 1
|
||||||
|
Hyrule Castle - Zelda's Chest: 1
|
||||||
|
Random: 3
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Magic Powder
|
||||||
|
locations:
|
||||||
|
- Potion Shop
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
- Tower of Hera - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Cane of Somaria
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Fire Rod
|
||||||
|
locations:
|
||||||
|
- Skull Woods - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Flippers
|
||||||
|
locations:
|
||||||
|
- King Zora
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Ice Rod
|
||||||
|
locations:
|
||||||
|
- Ice Rod Cave
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bombos
|
||||||
|
locations:
|
||||||
|
- Bombos Tablet
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Ether
|
||||||
|
locations:
|
||||||
|
- Ether Tablet
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Quake
|
||||||
|
locations:
|
||||||
|
- Catfish
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bottle
|
||||||
|
locations:
|
||||||
|
- Bottle Merchant
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bottle
|
||||||
|
locations:
|
||||||
|
- Kakariko Tavern
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bottle
|
||||||
|
locations:
|
||||||
|
- Purple Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bottle
|
||||||
|
locations:
|
||||||
|
- Hobo
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Sword
|
||||||
|
locations:
|
||||||
|
- Link's Uncle
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Sword
|
||||||
|
locations:
|
||||||
|
- Blacksmith
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Sword
|
||||||
|
locations:
|
||||||
|
- Master Sword Pedestal
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Sword
|
||||||
|
locations:
|
||||||
|
- Pyramid Fairy - Left
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Glove
|
||||||
|
locations:
|
||||||
|
- Desert Palace - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Glove
|
||||||
|
locations:
|
||||||
|
- Thieves' Town - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Armor
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Armor
|
||||||
|
locations:
|
||||||
|
- Ganons Tower - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Blue Boomerang
|
||||||
|
locations:
|
||||||
|
- Hyrule Castle - Boomerang Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Red Boomerang
|
||||||
|
locations:
|
||||||
|
- Waterfall Fairy - Left
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Shield
|
||||||
|
locations:
|
||||||
|
- Secret Passage
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Shield
|
||||||
|
locations:
|
||||||
|
- Waterfall Fairy - Right
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Shield
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Big Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Bug Catching Net
|
||||||
|
locations:
|
||||||
|
- Sick Kid
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Cane of Byrna
|
||||||
|
locations:
|
||||||
|
- Spike Cave
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Desert Palace - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Tower of Hera - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Thieves' Town - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Skull Woods - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Boss Heart Container
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Boss
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Sanctuary Heart Container
|
||||||
|
locations:
|
||||||
|
- Sanctuary
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Rupees (300)
|
||||||
|
locations:
|
||||||
|
- Mini Moldorm Cave - Generous Guy
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Rupees (300)
|
||||||
|
locations:
|
||||||
|
- Sewers - Secret Room - Middle
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Rupees (300)
|
||||||
|
locations:
|
||||||
|
- Hype Cave - Generous Guy
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Rupees (300)
|
||||||
|
locations:
|
||||||
|
- Brewery
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Rupees (300)
|
||||||
|
locations:
|
||||||
|
- C-Shaped House
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Magic Upgrade (1/2)
|
||||||
|
locations:
|
||||||
|
- Magic Bat
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Eastern Palace)
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Eastern Palace)
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Desert Palace)
|
||||||
|
locations:
|
||||||
|
- Desert Palace - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Desert Palace)
|
||||||
|
locations:
|
||||||
|
- Desert Palace - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Tower of Hera)
|
||||||
|
locations:
|
||||||
|
- Tower of Hera - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Tower of Hera)
|
||||||
|
locations:
|
||||||
|
- Tower of Hera - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Escape)
|
||||||
|
locations:
|
||||||
|
- Hyrule Castle - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Palace of Darkness)
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Palace of Darkness)
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Thieves Town)
|
||||||
|
locations:
|
||||||
|
- Thieves' Town - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Thieves Town)
|
||||||
|
locations:
|
||||||
|
- Thieves' Town - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Skull Woods)
|
||||||
|
locations:
|
||||||
|
- Skull Woods - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Skull Woods)
|
||||||
|
locations:
|
||||||
|
- Skull Woods - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Swamp Palace)
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Swamp Palace)
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Ice Palace)
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Ice Palace)
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Misery Mire)
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Misery Mire)
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Turtle Rock)
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Compass Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Turtle Rock)
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Roller Room - Left
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Compass (Ganons Tower)
|
||||||
|
locations:
|
||||||
|
- Ganons Tower - Compass Room - Top Left
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Map (Ganons Tower)
|
||||||
|
locations:
|
||||||
|
- Ganons Tower - Map Chest
|
||||||
|
- Random
|
||||||
|
type: LocationGroup
|
||||||
|
medallions:
|
||||||
|
1:
|
||||||
|
Misery Mire:
|
||||||
|
Ether: 1
|
||||||
|
Random: 1
|
||||||
|
Turtle Rock:
|
||||||
|
Quake: 1
|
||||||
|
Random: 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
21
docs/avianart/true_pot_hunt.yaml
Normal file
21
docs/avianart/true_pot_hunt.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
goal: triforcehunt
|
||||||
|
shuffle: crossed
|
||||||
|
keysanity: True
|
||||||
|
shopsanity: True
|
||||||
|
keydropshuffle: True
|
||||||
|
pottery: lottery
|
||||||
|
dungeon_counters: 'on'
|
||||||
|
triforce_goal: 420
|
||||||
|
triforce_pool: 420
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Lamp
|
||||||
|
- Rupees (300)
|
||||||
|
- Rupees (100)
|
||||||
|
- Rupees (20)
|
||||||
21
docs/avianart/truest_pot_hunt.yaml
Normal file
21
docs/avianart/truest_pot_hunt.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
goal: triforcehunt
|
||||||
|
shuffle: crossed
|
||||||
|
keysanity: True
|
||||||
|
shopsanity: True
|
||||||
|
keydropshuffle: True
|
||||||
|
pottery: lottery
|
||||||
|
dungeon_counters: 'on'
|
||||||
|
triforce_goal: 213
|
||||||
|
triforce_pool: 420
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Lamp
|
||||||
|
- Rupees (300)
|
||||||
|
- Rupees (100)
|
||||||
|
- Rupees (20)
|
||||||
259
docs/avianart/why_is_that_there.yaml
Normal file
259
docs/avianart/why_is_that_there.yaml
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
meta:
|
||||||
|
algorithm: balanced
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
bigkeyshuffle: True
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Potion Shop: Shovel
|
||||||
|
Flute Spot: Magic Powder
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- item: Progressive Bow
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Boss
|
||||||
|
- Palace of Darkness - Map Chest
|
||||||
|
- Palace of Darkness - The Arena - Ledge
|
||||||
|
- Eastern Palace - Boss
|
||||||
|
- Ganons Tower - Pre-Moldorm Chest
|
||||||
|
- Ganons Tower - Mini Helmasaur Room - Left
|
||||||
|
- Ganons Tower - Mini Helmasaur Room - Right
|
||||||
|
- Ganons Tower - Validation Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Fire Rod
|
||||||
|
locations:
|
||||||
|
- Ice Palace - Big Chest
|
||||||
|
- Ice Palace - Boss
|
||||||
|
- Ice Palace - Big Key Chest
|
||||||
|
- Ice Palace - Compass Chest
|
||||||
|
- Ice Palace - Map Chest
|
||||||
|
- Ice Palace - Spike Room
|
||||||
|
- Ice Palace - Iced T Room
|
||||||
|
- Ice Palace - Freezor Chest
|
||||||
|
- Desert Palace - Boss
|
||||||
|
- Tower of Hera - Big Key Chest
|
||||||
|
- Misery Mire - Big Key Chest
|
||||||
|
- Misery Mire - Compass Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Pegasus Boots
|
||||||
|
locations:
|
||||||
|
- Hookshot Cave - Top Right
|
||||||
|
- Hookshot Cave - Top Left
|
||||||
|
- Hookshot Cave - Bottom Right
|
||||||
|
- Hookshot Cave - Bottom Left
|
||||||
|
- Mushroom Spot
|
||||||
|
- Zora Ledge
|
||||||
|
- Bombos Tablet
|
||||||
|
- Ether Tablet
|
||||||
|
- Floating Island
|
||||||
|
- Lake Hylia Island
|
||||||
|
- Maze Race
|
||||||
|
- Spectacle Rock
|
||||||
|
- Spectacle Rock Cave
|
||||||
|
- Pyramid
|
||||||
|
- Desert Ledge
|
||||||
|
- Bumper Cave Ledge
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Progressive Sword
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Big Chest
|
||||||
|
- Swamp Palace - Boss
|
||||||
|
- Swamp Palace - Big Key Chest
|
||||||
|
- Swamp Palace - Compass Chest
|
||||||
|
- Swamp Palace - Map Chest
|
||||||
|
- Swamp Palace - Entrance
|
||||||
|
- Swamp Palace - Flooded Room - Left
|
||||||
|
- Swamp Palace - Flooded Room - Right
|
||||||
|
- Swamp Palace - Waterfall Room
|
||||||
|
- Swamp Palace - West Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Titans Mitts
|
||||||
|
locations:
|
||||||
|
- Swamp Palace - Big Chest
|
||||||
|
- Swamp Palace - Boss
|
||||||
|
- Swamp Palace - Big Key Chest
|
||||||
|
- Swamp Palace - Compass Chest
|
||||||
|
- Swamp Palace - Map Chest
|
||||||
|
- Swamp Palace - Entrance
|
||||||
|
- Swamp Palace - Flooded Room - Left
|
||||||
|
- Swamp Palace - Flooded Room - Right
|
||||||
|
- Swamp Palace - Waterfall Room
|
||||||
|
- Swamp Palace - West Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Ice Rod
|
||||||
|
type: LocationGroup
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Big Chest
|
||||||
|
- Turtle Rock - Boss
|
||||||
|
- Turtle Rock - Big Key Chest
|
||||||
|
- Turtle Rock - Compass Chest
|
||||||
|
- Turtle Rock - Roller Room - Left
|
||||||
|
- Turtle Rock - Chain Chomps
|
||||||
|
- Turtle Rock - Crystaroller Room
|
||||||
|
- Turtle Rock - Roller Room - Right
|
||||||
|
- Turtle Rock - Eye Bridge - Bottom Left
|
||||||
|
- Turtle Rock - Eye Bridge - Bottom Right
|
||||||
|
- Turtle Rock - Eye Bridge - Top Left
|
||||||
|
- Turtle Rock - Eye Bridge - Top Right
|
||||||
|
- Mimic Cave
|
||||||
|
- Link's House
|
||||||
|
- Link's Uncle
|
||||||
|
- Secret Passage
|
||||||
|
- Hyrule Castle - Map Chest
|
||||||
|
- Sanctuary
|
||||||
|
- Mushroom Spot
|
||||||
|
- Lost Woods Hideout
|
||||||
|
- Blind's Hideout - Left
|
||||||
|
- Blind's Hideout - Right
|
||||||
|
- Blind's Hideout - Far Left
|
||||||
|
- Blind's Hideout - Far Right
|
||||||
|
- Blind's Hideout - Top
|
||||||
|
- Kakariko Well - Right
|
||||||
|
- Kakariko Well - Left
|
||||||
|
- Kakariko Well - Middle
|
||||||
|
- Kakariko Well - Top
|
||||||
|
- Kakariko Well - Bottom
|
||||||
|
- Chicken House
|
||||||
|
- Bottle Merchant
|
||||||
|
- Kakariko Tavern
|
||||||
|
- Maze Race
|
||||||
|
- Floodgate Chest
|
||||||
|
- Sunken Treasure
|
||||||
|
- Mini Moldorm Cave - Left
|
||||||
|
- Mini Moldorm Cave - Right
|
||||||
|
- Mini Moldorm Cave - Generous Guy
|
||||||
|
- Mini Moldorm Cave - Far Left
|
||||||
|
- Mini Moldorm Cave - Far Right
|
||||||
|
- Sahasrahla's Hut - Middle
|
||||||
|
- Sahasrahla's Hut - Right
|
||||||
|
- Sahasrahla's Hut - Left
|
||||||
|
- Ice Rod Cave
|
||||||
|
- Eastern Palace - Compass Chest
|
||||||
|
- Eastern Palace - Map Chest
|
||||||
|
- Eastern Palace - Cannonball Chest
|
||||||
|
- Aginah's Cave
|
||||||
|
- item: Big Key (Eastern Palace)
|
||||||
|
locations:
|
||||||
|
- Eastern Palace - Cannonball Chest
|
||||||
|
- Eastern Palace - Big Key Chest
|
||||||
|
- Eastern Palace - Compass Chest
|
||||||
|
- Eastern Palace - Map Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Desert Palace)
|
||||||
|
locations:
|
||||||
|
- Desert Palace - Big Key Chest
|
||||||
|
- Desert Palace - Compass Chest
|
||||||
|
- Desert Palace - Map Chest
|
||||||
|
- Desert Palace - Torch
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Palace of Darkness)
|
||||||
|
locations:
|
||||||
|
- Palace of Darkness - Big Key Chest
|
||||||
|
- Palace of Darkness - Compass Chest
|
||||||
|
- Palace of Darkness - Map Chest
|
||||||
|
- Palace of Darkness - Stalfos Basement
|
||||||
|
- Palace of Darkness - Dark Basement - Right
|
||||||
|
- Palace of Darkness - Harmless Hellway
|
||||||
|
- Palace of Darkness - Shooter Room
|
||||||
|
- Palace of Darkness - The Arena - Bridge
|
||||||
|
- Palace of Darkness - The Arena - Ledge
|
||||||
|
- Palace of Darkness - Dark Basement - Left
|
||||||
|
- Palace of Darkness - Dark Maze - Bottom
|
||||||
|
- Palace of Darkness - Dark Maze - Top
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Thieves Town)
|
||||||
|
locations:
|
||||||
|
- Thieves' Town - Big Key Chest
|
||||||
|
- Thieves' Town - Compass Chest
|
||||||
|
- Thieves' Town - Map Chest
|
||||||
|
- Thieves' Town - Ambush Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Misery Mire)
|
||||||
|
locations:
|
||||||
|
- Misery Mire - Big Key Chest
|
||||||
|
- Misery Mire - Compass Chest
|
||||||
|
- Misery Mire - Map Chest
|
||||||
|
- Misery Mire - Spike Chest
|
||||||
|
- Misery Mire - Main Lobby
|
||||||
|
- Misery Mire - Bridge Chest
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Turtle Rock)
|
||||||
|
locations:
|
||||||
|
- Turtle Rock - Big Key Chest
|
||||||
|
- Turtle Rock - Compass Chest
|
||||||
|
- Turtle Rock - Roller Room - Left
|
||||||
|
- Turtle Rock - Chain Chomps
|
||||||
|
- Turtle Rock - Roller Room - Right
|
||||||
|
type: LocationGroup
|
||||||
|
- item: Big Key (Ganons Tower)
|
||||||
|
locations:
|
||||||
|
- Ganons Tower - Big Key Chest
|
||||||
|
- Ganons Tower - Compass Room - Top Left
|
||||||
|
- Ganons Tower - Map Chest
|
||||||
|
- Ganons Tower - Bob's Torch
|
||||||
|
- Ganons Tower - Tile Room
|
||||||
|
- Ganons Tower - Firesnake Room
|
||||||
|
- Ganons Tower - DMs Room - Top Right
|
||||||
|
- Ganons Tower - DMs Room - Top Left
|
||||||
|
- Ganons Tower - DMs Room - Bottom Left
|
||||||
|
- Ganons Tower - DMs Room - Bottom Right
|
||||||
|
- Ganons Tower - Compass Room - Top Right
|
||||||
|
- Ganons Tower - Compass Room - Bottom Right
|
||||||
|
- Ganons Tower - Compass Room - Bottom Left
|
||||||
|
- Ganons Tower - Hope Room - Left
|
||||||
|
- Ganons Tower - Hope Room - Right
|
||||||
|
- Ganons Tower - Randomizer Room - Top Left
|
||||||
|
- Ganons Tower - Randomizer Room - Top Right
|
||||||
|
- Ganons Tower - Randomizer Room - Bottom Right
|
||||||
|
- Ganons Tower - Randomizer Room - Bottom Left
|
||||||
|
- Ganons Tower - Bob's Chest
|
||||||
|
- Ganons Tower - Big Key Room - Left
|
||||||
|
- Ganons Tower - Big Key Room - Right
|
||||||
|
type: LocationGroup
|
||||||
|
item_pool:
|
||||||
|
1:
|
||||||
|
Arrows (10): 12
|
||||||
|
Blue Boomerang: 1
|
||||||
|
Bombos: 1
|
||||||
|
Bombs (10): 1
|
||||||
|
Bombs (3): 16
|
||||||
|
Book of Mudora: 1
|
||||||
|
Boss Heart Container: 10
|
||||||
|
Bottle (Random): 4
|
||||||
|
Bug Catching Net: 1
|
||||||
|
Cane of Byrna: 1
|
||||||
|
Cane of Somaria: 1
|
||||||
|
Cape: 1
|
||||||
|
Ether: 1
|
||||||
|
Fire Rod: 1
|
||||||
|
Flippers: 1
|
||||||
|
Hammer: 1
|
||||||
|
Hookshot: 1
|
||||||
|
Ice Rod: 1
|
||||||
|
Lamp: 1
|
||||||
|
Magic Mirror: 1
|
||||||
|
Magic Powder: 1
|
||||||
|
Magic Upgrade (1/2): 1
|
||||||
|
Moon Pearl: 1
|
||||||
|
Mushroom: 1
|
||||||
|
Ocarina: 1
|
||||||
|
Pegasus Boots: 1
|
||||||
|
Piece of Heart: 24
|
||||||
|
Progressive Armor: 2
|
||||||
|
Progressive Bow: 2
|
||||||
|
Progressive Glove: 2
|
||||||
|
Progressive Shield: 3
|
||||||
|
Progressive Sword: 4
|
||||||
|
Titans Mitts: 1
|
||||||
|
Quake: 1
|
||||||
|
Red Boomerang: 1
|
||||||
|
Rupee (1): 2
|
||||||
|
Rupees (100): 1
|
||||||
|
Rupees (20): 27
|
||||||
|
Rupees (300): 5
|
||||||
|
Rupees (5): 4
|
||||||
|
Rupees (50): 7
|
||||||
|
Sanctuary Heart Container: 1
|
||||||
|
Shovel: 1
|
||||||
|
Single Arrow: 1
|
||||||
@@ -34,6 +34,10 @@
|
|||||||
"retro"
|
"retro"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"boots_hint": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"swords": {
|
"swords": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"random",
|
"random",
|
||||||
|
|||||||
@@ -24,15 +24,20 @@ class CustomSettings(object):
|
|||||||
head, filename = os.path.split(file)
|
head, filename = os.path.split(file)
|
||||||
self.relative_dir = head
|
self.relative_dir = head
|
||||||
|
|
||||||
def determine_seed(self):
|
def determine_seed(self, default_seed):
|
||||||
if 'meta' not in self.file_source:
|
if 'meta' in self.file_source:
|
||||||
return None
|
meta = defaultdict(lambda: None, self.file_source['meta'])
|
||||||
meta = defaultdict(lambda: None, self.file_source['meta'])
|
seed = meta['seed']
|
||||||
seed = meta['seed']
|
if seed:
|
||||||
if seed:
|
random.seed(seed)
|
||||||
random.seed(seed)
|
return seed
|
||||||
return seed
|
if default_seed is None:
|
||||||
return None
|
random.seed(None)
|
||||||
|
seed = random.randint(0, 999999999)
|
||||||
|
else:
|
||||||
|
seed = default_seed
|
||||||
|
random.seed(seed)
|
||||||
|
return seed
|
||||||
|
|
||||||
def determine_players(self):
|
def determine_players(self):
|
||||||
if 'meta' not in self.file_source:
|
if 'meta' not in self.file_source:
|
||||||
@@ -43,7 +48,10 @@ class CustomSettings(object):
|
|||||||
def adjust_args(self, args):
|
def adjust_args(self, args):
|
||||||
def get_setting(value, default):
|
def get_setting(value, default):
|
||||||
if value:
|
if value:
|
||||||
return value
|
if isinstance(value, dict):
|
||||||
|
return random.choices(list(value.keys()), list(value.values()), k=1)[0]
|
||||||
|
else:
|
||||||
|
return value
|
||||||
return default
|
return default
|
||||||
if 'meta' in self.file_source:
|
if 'meta' in self.file_source:
|
||||||
meta = defaultdict(lambda: None, self.file_source['meta'])
|
meta = defaultdict(lambda: None, self.file_source['meta'])
|
||||||
@@ -67,6 +75,7 @@ class CustomSettings(object):
|
|||||||
args.door_shuffle[p] = get_setting(settings['door_shuffle'], args.door_shuffle[p])
|
args.door_shuffle[p] = get_setting(settings['door_shuffle'], args.door_shuffle[p])
|
||||||
args.logic[p] = get_setting(settings['logic'], args.logic[p])
|
args.logic[p] = get_setting(settings['logic'], args.logic[p])
|
||||||
args.mode[p] = get_setting(settings['mode'], args.mode[p])
|
args.mode[p] = get_setting(settings['mode'], args.mode[p])
|
||||||
|
args.boots_hint[p] = get_setting(settings['boots_hint'], args.boots_hint[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.bow_mode[p] = get_setting(settings['bow_mode'], args.bow_mode[p])
|
||||||
@@ -86,6 +95,14 @@ class CustomSettings(object):
|
|||||||
if args.pottery[p] == 'none':
|
if args.pottery[p] == 'none':
|
||||||
args.pottery[p] = 'keys'
|
args.pottery[p] = 'keys'
|
||||||
|
|
||||||
|
if args.retro[p] or args.mode[p] == 'retro':
|
||||||
|
if args.bow_mode[p] == 'progressive':
|
||||||
|
args.bow_mode[p] = 'retro'
|
||||||
|
elif args.bow_mode[p] == 'silvers':
|
||||||
|
args.bow_mode[p] = 'retro_silvers'
|
||||||
|
args.take_any[p] = 'random' if args.take_any[p] == 'none' else args.take_any[p]
|
||||||
|
args.keyshuffle[p] = 'universal'
|
||||||
|
|
||||||
args.mixed_travel[p] = get_setting(settings['mixed_travel'], args.mixed_travel[p])
|
args.mixed_travel[p] = get_setting(settings['mixed_travel'], args.mixed_travel[p])
|
||||||
args.standardize_palettes[p] = get_setting(settings['standardize_palettes'],
|
args.standardize_palettes[p] = get_setting(settings['standardize_palettes'],
|
||||||
args.standardize_palettes[p])
|
args.standardize_palettes[p])
|
||||||
@@ -104,7 +121,8 @@ class CustomSettings(object):
|
|||||||
|
|
||||||
if get_setting(settings['keysanity'], args.keysanity):
|
if get_setting(settings['keysanity'], args.keysanity):
|
||||||
args.bigkeyshuffle[p] = True
|
args.bigkeyshuffle[p] = True
|
||||||
args.keyshuffle[p] = True
|
if args.keyshuffle[p] == 'none':
|
||||||
|
args.keyshuffle[p] = 'wild'
|
||||||
args.mapshuffle[p] = True
|
args.mapshuffle[p] = True
|
||||||
args.compassshuffle[p] = True
|
args.compassshuffle[p] = True
|
||||||
|
|
||||||
@@ -149,6 +167,11 @@ class CustomSettings(object):
|
|||||||
return self.file_source['placements']
|
return self.file_source['placements']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_advanced_placements(self):
|
||||||
|
if 'advanced_placements' in self.file_source:
|
||||||
|
return self.file_source['advanced_placements']
|
||||||
|
return None
|
||||||
|
|
||||||
def get_entrances(self):
|
def get_entrances(self):
|
||||||
if 'entrances' in self.file_source:
|
if 'entrances' in self.file_source:
|
||||||
return self.file_source['entrances']
|
return self.file_source['entrances']
|
||||||
@@ -174,6 +197,11 @@ class CustomSettings(object):
|
|||||||
return self.file_source['medallions']
|
return self.file_source['medallions']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_drops(self):
|
||||||
|
if 'drops' in self.file_source:
|
||||||
|
return self.file_source['drops']
|
||||||
|
return None
|
||||||
|
|
||||||
def create_from_world(self, world):
|
def create_from_world(self, world):
|
||||||
self.player_range = range(1, world.players + 1)
|
self.player_range = range(1, world.players + 1)
|
||||||
settings_dict, meta_dict = {}, {}
|
settings_dict, meta_dict = {}, {}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class ItemPoolConfig(object):
|
|||||||
self.item_pool = None
|
self.item_pool = None
|
||||||
self.placeholders = None
|
self.placeholders = None
|
||||||
self.reserved_locations = defaultdict(set)
|
self.reserved_locations = defaultdict(set)
|
||||||
|
self.restricted = {}
|
||||||
|
self.preferred = {}
|
||||||
|
|
||||||
self.recorded_choices = []
|
self.recorded_choices = []
|
||||||
|
|
||||||
@@ -380,8 +382,10 @@ def vanilla_fallback(item_to_place, locations, world):
|
|||||||
|
|
||||||
|
|
||||||
def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion=False):
|
def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion=False):
|
||||||
|
config = world.item_pool_config
|
||||||
|
item_name = 'Bottle' if item_to_place.name.startswith('Bottle') else item_to_place.name
|
||||||
if world.algorithm == 'vanilla_fill':
|
if world.algorithm == 'vanilla_fill':
|
||||||
config, filtered = world.item_pool_config, []
|
filtered = []
|
||||||
item_name = 'Bottle' if item_to_place.name.startswith('Bottle') else item_to_place.name
|
item_name = 'Bottle' if item_to_place.name.startswith('Bottle') else item_to_place.name
|
||||||
if item_name in config.static_placement[item_to_place.player]:
|
if item_name in config.static_placement[item_to_place.player]:
|
||||||
restricted = config.static_placement[item_to_place.player][item_name]
|
restricted = config.static_placement[item_to_place.player][item_name]
|
||||||
@@ -418,6 +422,12 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False, potion
|
|||||||
if len(filtered) == 0:
|
if len(filtered) == 0:
|
||||||
raise RuntimeError('Can\'t sell potion of a certain type due to district restriction')
|
raise RuntimeError('Can\'t sell potion of a certain type due to district restriction')
|
||||||
return filtered
|
return filtered
|
||||||
|
if (item_name, item_to_place.player) in config.restricted:
|
||||||
|
locs = config.restricted[(item_name, item_to_place.player)]
|
||||||
|
return sorted(locations, key=lambda l: 1 if l.name in locs else 0)
|
||||||
|
if (item_name, item_to_place.player) in config.preferred:
|
||||||
|
locs = config.preferred[(item_name, item_to_place.player)]
|
||||||
|
return sorted(locations, key=lambda l: 0 if l.name in locs else 1)
|
||||||
return locations
|
return locations
|
||||||
|
|
||||||
|
|
||||||
@@ -814,3 +824,26 @@ pot_items = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
valid_pot_items = {y: x for x, y in pot_items.items()}
|
valid_pot_items = {y: x for x, y in pot_items.items()}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import yaml
|
||||||
|
from yaml.representer import Representer
|
||||||
|
advanced_placements = {'advanced_placements': {}}
|
||||||
|
player_map = advanced_placements['advanced_placements']
|
||||||
|
placement_list = []
|
||||||
|
player_map[1] = placement_list
|
||||||
|
for item, location_list in vanilla_mapping.items():
|
||||||
|
for location in location_list:
|
||||||
|
placement = {}
|
||||||
|
placement['type'] = 'LocationGroup'
|
||||||
|
placement['item'] = item
|
||||||
|
locations = placement['locations'] = []
|
||||||
|
locations.append(location)
|
||||||
|
locations.append('Random')
|
||||||
|
placement_list.append(placement)
|
||||||
|
yaml.add_representer(defaultdict, Representer.represent_dict)
|
||||||
|
with open('fillgen.yaml', 'w') as file:
|
||||||
|
yaml.dump(advanced_placements, file)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user