Standing Items refinement - starting testing no keydrops and pot shuffle
Fairly substantial change to Crossed Sector distribution due to so many pots making it fail
This commit is contained in:
@@ -2382,11 +2382,11 @@ class Spoiler(object):
|
||||
listed_locations.update(cave_locations)
|
||||
|
||||
for dungeon in self.world.dungeons:
|
||||
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item]
|
||||
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item and not loc.skip]
|
||||
self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations])
|
||||
listed_locations.update(dungeon_locations)
|
||||
|
||||
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations]
|
||||
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and not loc.skip]
|
||||
if other_locations:
|
||||
self.locations['Other Locations'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in other_locations])
|
||||
listed_locations.update(other_locations)
|
||||
|
||||
@@ -2302,6 +2302,8 @@ logical_connections = [
|
||||
('TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
|
||||
('TR Crystal Maze End to Ranged Crystal', 'TR Crystal Maze End - Ranged Crystal'),
|
||||
('TR Crystal Maze End Ranged Crystal Exit', 'TR Crystal Maze End'),
|
||||
('TR Final Abyss Balcony Path', 'TR Final Abyss Ledge'),
|
||||
('TR Final Abyss Ledge Path', 'TR Final Abyss Balcony'),
|
||||
|
||||
('GT Blocked Stairs Block Path', 'GT Big Chest'),
|
||||
('GT Speed Torch South Path', 'GT Speed Torch'),
|
||||
|
||||
2
Doors.py
2
Doors.py
@@ -1048,6 +1048,8 @@ def create_doors(world, player):
|
||||
create_door(player, 'TR Crystal Maze End Ranged Crystal Exit', Lgcl),
|
||||
create_door(player, 'TR Crystal Maze North Stairs', StrS).dir(No, 0xc4, Mid, High),
|
||||
create_door(player, 'TR Final Abyss South Stairs', StrS).dir(So, 0xb4, Mid, High),
|
||||
create_door(player, 'TR Final Abyss Balcony Path', Lgcl),
|
||||
create_door(player, 'TR Final Abyss Ledge Path', Lgcl),
|
||||
create_door(player, 'TR Final Abyss NW', Nrml).dir(No, 0xb4, Left, High).big_key().pos(0),
|
||||
create_door(player, 'TR Boss SW', Nrml).dir(So, 0xa4, Left, High).no_exit().trap(0x4).pos(0), # .portal(Z, 0x00), -enemizer doesn't work
|
||||
|
||||
|
||||
@@ -1326,7 +1326,17 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player,
|
||||
polarized_sectors[sector] = None
|
||||
if bow_sectors:
|
||||
assign_bow_sectors(dungeon_map, bow_sectors, global_pole)
|
||||
assign_location_sectors(dungeon_map, free_location_sectors, global_pole, world, player)
|
||||
leftover = assign_location_sectors_minimal(dungeon_map, free_location_sectors, global_pole, world, player)
|
||||
free_location_sectors = scatter_extra_location_sectors(dungeon_map, leftover, global_pole)
|
||||
for sector in free_location_sectors:
|
||||
if sector.c_switch:
|
||||
crystal_switches[sector] = None
|
||||
elif sector.blue_barrier:
|
||||
crystal_barriers[sector] = None
|
||||
elif sector.polarity().is_neutral():
|
||||
neutral_sectors[sector] = None
|
||||
else:
|
||||
polarized_sectors[sector] = None
|
||||
leftover = assign_crystal_switch_sectors(dungeon_map, crystal_switches, crystal_barriers, global_pole)
|
||||
ensure_crystal_switches_reachable(dungeon_map, leftover, polarized_sectors, crystal_barriers, global_pole)
|
||||
for sector in leftover:
|
||||
@@ -1558,33 +1568,85 @@ def assign_bow_sectors(dungeon_map, bow_sectors, global_pole):
|
||||
assign_sector(sector_list[i], builder, bow_sectors, global_pole)
|
||||
|
||||
|
||||
def assign_location_sectors(dungeon_map, free_location_sectors, global_pole, world, player):
|
||||
def scatter_extra_location_sectors(dungeon_map, free_location_sectors, global_pole):
|
||||
population = [n for n in dungeon_map.keys()]
|
||||
k = round(len(free_location_sectors) * .50)
|
||||
valid = False
|
||||
choices = None
|
||||
candidates = []
|
||||
sector_list = list(free_location_sectors)
|
||||
while not valid:
|
||||
candidates = random.sample(sector_list, k=k)
|
||||
choices = random.choices(population, k=len(candidates))
|
||||
sector_dict = defaultdict(list)
|
||||
for i, choice in enumerate(choices):
|
||||
builder = dungeon_map[choice]
|
||||
sector_dict[builder].append(candidates[i])
|
||||
valid = global_pole.is_valid_multi_choice_2(dungeon_map, dungeon_map.values(), sector_dict)
|
||||
for i, choice in enumerate(choices):
|
||||
builder = dungeon_map[choice]
|
||||
assign_sector(candidates[i], builder, free_location_sectors, global_pole)
|
||||
return free_location_sectors
|
||||
|
||||
|
||||
def assign_location_sectors_minimal(dungeon_map, free_location_sectors, global_pole, world, player):
|
||||
valid = False
|
||||
choices = defaultdict(list)
|
||||
sector_list = list(free_location_sectors)
|
||||
random.shuffle(sector_list)
|
||||
orig_location_set = build_orig_location_set(dungeon_map)
|
||||
num_dungeon_items = requested_dungeon_items(world, player)
|
||||
d_idx = {builder.name: i for i, builder in enumerate(dungeon_map.values())}
|
||||
next_sector = sector_list.pop()
|
||||
while not valid:
|
||||
choices, d_idx, totals = weighted_random_locations(dungeon_map, sector_list)
|
||||
location_set = {x: set(y) for x, y in orig_location_set.items()}
|
||||
for i, sector in enumerate(sector_list):
|
||||
d_name = choices[i].name
|
||||
choice = d_idx[d_name]
|
||||
totals[choice] += sector.chest_locations
|
||||
location_set[d_name].update(sector.chest_location_set)
|
||||
valid = True
|
||||
for d_name, idx in d_idx.items():
|
||||
free_items = count_reserved_locations(world, player, location_set[d_name])
|
||||
target = max(free_items, 2) + num_dungeon_items
|
||||
if totals[idx] < target:
|
||||
valid = False
|
||||
break
|
||||
for i, choice in enumerate(choices):
|
||||
builder = dungeon_map[choice.name]
|
||||
assign_sector(sector_list[i], builder, free_location_sectors, global_pole)
|
||||
choice, totals, location_set = weighted_random_location(dungeon_map, choices, orig_location_set, world, player)
|
||||
if not choice:
|
||||
break
|
||||
choices[choice].append(next_sector)
|
||||
if global_pole.is_valid_multi_choice_2(dungeon_map, dungeon_map.values(), choices):
|
||||
idx = d_idx[choice.name]
|
||||
totals[idx] += next_sector.chest_locations
|
||||
location_set[choice.name].update(next_sector.chest_location_set)
|
||||
valid = True
|
||||
for d_name, idx in d_idx.items():
|
||||
free_items = count_reserved_locations(world, player, location_set[d_name])
|
||||
target = max(free_items, 2) + num_dungeon_items
|
||||
if totals[idx] < target:
|
||||
valid = False
|
||||
break
|
||||
if not valid:
|
||||
if len(sector_list) == 0:
|
||||
choices = defaultdict(list)
|
||||
sector_list = list(free_location_sectors)
|
||||
else:
|
||||
next_sector = sector_list.pop()
|
||||
else:
|
||||
choices[choice].remove(next_sector)
|
||||
for builder, choice_list in choices.items():
|
||||
for choice in choice_list:
|
||||
assign_sector(choice, builder, free_location_sectors, global_pole)
|
||||
return free_location_sectors
|
||||
|
||||
|
||||
def weighted_random_location(dungeon_map, choices, orig_location_set, world, player):
|
||||
population = []
|
||||
totals = []
|
||||
location_set = {x: set(y) for x, y in orig_location_set.items()}
|
||||
num_dungeon_items = requested_dungeon_items(world, player)
|
||||
for i, dungeon_builder in enumerate(dungeon_map.values()):
|
||||
ttl = dungeon_builder.location_cnt + sum(sector.chest_locations for sector in choices[dungeon_builder])
|
||||
totals.append(ttl)
|
||||
builder_set = location_set[dungeon_builder.name]
|
||||
builder_set.update(set().union(*(s.chest_location_set for s in choices[dungeon_builder])))
|
||||
free_items = count_reserved_locations(world, player, builder_set)
|
||||
target = max(free_items, 2) + num_dungeon_items
|
||||
if ttl < target:
|
||||
population.append(dungeon_builder)
|
||||
choice = random.choice(population) if len(population) > 0 else None
|
||||
return choice, totals, location_set
|
||||
|
||||
|
||||
# deprecated
|
||||
def weighted_random_locations(dungeon_map, free_location_sectors):
|
||||
population = []
|
||||
ttl_assigned = 0
|
||||
|
||||
18
Dungeons.py
18
Dungeons.py
@@ -170,15 +170,17 @@ mire_regions = [
|
||||
tr_regions = [
|
||||
'TR Main Lobby', 'TR Lobby Ledge', 'TR Compass Room', 'TR Hub', 'TR Torches Ledge', 'TR Torches', 'TR Roller Room',
|
||||
'TR Tile Room', 'TR Refill', 'TR Pokey 1', 'TR Chain Chomps Top', 'TR Chain Chomps Top - Crystal',
|
||||
'TR Chain Chomps Bottom', 'TR Chain Chomps Bottom - Ranged Crystal', 'TR Pipe Pit', 'TR Pipe Ledge', 'TR Lava Dual Pipes',
|
||||
'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2 Top', 'TR Pokey 2 Top - Crystal', 'TR Pokey 2 Bottom', 'TR Pokey 2 Bottom - Ranged Crystal',
|
||||
'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers', 'TR Big View','TR Big Chest', 'TR Big Chest Entrance',
|
||||
'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull', 'TR Rupees', 'TR Crystaroller Bottom',
|
||||
'TR Crystaroller Middle', 'TR Crystaroller Top', 'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest',
|
||||
'TR Crystaroller Middle - Ranged Crystal', 'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge',
|
||||
'TR Chain Chomps Bottom', 'TR Chain Chomps Bottom - Ranged Crystal', 'TR Pipe Pit', 'TR Pipe Ledge',
|
||||
'TR Lava Dual Pipes', 'TR Lava Island', 'TR Lava Escape', 'TR Pokey 2 Top', 'TR Pokey 2 Top - Crystal',
|
||||
'TR Pokey 2 Bottom', 'TR Pokey 2 Bottom - Ranged Crystal', 'TR Twin Pokeys', 'TR Hallway', 'TR Dodgers',
|
||||
'TR Big View','TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull',
|
||||
'TR Rupees', 'TR Crystaroller Bottom', 'TR Crystaroller Middle', 'TR Crystaroller Top',
|
||||
'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', 'TR Crystaroller Middle - Ranged Crystal',
|
||||
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dash Bridge', 'TR Eye Bridge',
|
||||
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
|
||||
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss', 'TR Boss', 'Turtle Rock Main Portal',
|
||||
'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal', 'Turtle Rock Eye Bridge Portal'
|
||||
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss Balcony', 'TR Final Abyss Ledge', 'TR Boss',
|
||||
'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal',
|
||||
'Turtle Rock Eye Bridge Portal'
|
||||
]
|
||||
|
||||
gt_regions = [
|
||||
|
||||
2
Fill.py
2
Fill.py
@@ -7,6 +7,7 @@ from BaseClasses import CollectionState, FillError, LocationType
|
||||
from Items import ItemFactory
|
||||
from Regions import shop_to_location_table, retro_shops
|
||||
from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback
|
||||
from source.item.FillUtil import filter_pot_locations
|
||||
|
||||
|
||||
def get_dungeon_item_pool(world):
|
||||
@@ -362,6 +363,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||
world.itempool.remove(pot_item)
|
||||
pot_locations = [location for location in fill_locations
|
||||
if location.type == LocationType.Pot and location.player == player]
|
||||
pot_locations = filter_pot_locations(pot_locations, world)
|
||||
fast_fill_helper(world, pot_pool, pot_locations)
|
||||
pots_used = True
|
||||
if pots_used:
|
||||
|
||||
9
Main.py
9
Main.py
@@ -14,7 +14,7 @@ from Bosses import place_bosses
|
||||
from Items import ItemFactory
|
||||
from KeyDoorShuffle import validate_key_placement
|
||||
from OverworldGlitchRules import create_owg_connections
|
||||
from PotShuffle import shuffle_pots
|
||||
from PotShuffle import shuffle_pots, shuffle_pot_switches
|
||||
from Regions import create_regions, create_shops, mark_light_world_regions, create_dungeon_regions, adjust_locations
|
||||
from InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
||||
from EntranceShuffle import link_entrances, link_inverted_entrances
|
||||
@@ -157,8 +157,11 @@ def main(args, seed=None, fish=None):
|
||||
if any(world.potshuffle.values()):
|
||||
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
|
||||
for player in range(1, world.players + 1):
|
||||
if world.potshuffle[player] and world.keydropshuffle[player] != 'potsanity':
|
||||
shuffle_pots(world, player)
|
||||
if world.potshuffle[player]:
|
||||
if world.keydropshuffle[player] != 'potsanity':
|
||||
shuffle_pots(world, player)
|
||||
else:
|
||||
shuffle_pot_switches(world, player)
|
||||
|
||||
logger.info(world.fish.translate("cli","cli","shuffling.world"))
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier
|
||||
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier, LocationType
|
||||
from Utils import int16_as_bytes, pc_to_snes
|
||||
|
||||
movable_switch_rooms = defaultdict(lambda: [],
|
||||
@@ -79,8 +79,10 @@ vanilla_pots = {
|
||||
61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'),
|
||||
Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')],
|
||||
62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')],
|
||||
0x3F: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
|
||||
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'), Pot(28, 23, PotItem.Key, 'Ice Hammer Block')],
|
||||
0x3F: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'),
|
||||
Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
|
||||
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'),
|
||||
Pot(28, 23, PotItem.Key, 'Ice Hammer Block')],
|
||||
0x41: [Pot(100, 10, PotItem.Heart, 'Sewers Behind Tapestry'), Pot(52, 15, PotItem.OneRupee, 'Sewers Behind Tapestry'), Pot(52, 16, PotItem.SmallMagic, 'Sewers Behind Tapestry'), Pot(148, 22, PotItem.SmallMagic, 'Sewers Behind Tapestry')],
|
||||
0x43: [Pot(66, 4, PotItem.FiveArrows, 'Desert Wall Slide'), Pot(78, 4, PotItem.SmallMagic, 'Desert Wall Slide'), Pot(66, 9, PotItem.Heart, 'Desert Wall Slide'), Pot(78, 9, PotItem.Heart, 'Desert Wall Slide'),
|
||||
Pot(112, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 20, PotItem.Nothing, 'Desert Tiles 2'), Pot(112, 20, PotItem.Key, 'Desert Tiles 2')],
|
||||
@@ -191,7 +193,7 @@ vanilla_pots = {
|
||||
145: [Pot(84, 4, PotItem.Heart, 'Mire Falling Foes'), Pot(104, 4, PotItem.SmallMagic, 'Mire Falling Foes')],
|
||||
146: [Pot(86, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(92, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(98, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(104, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy')],
|
||||
0x93: [Pot(28, 7, PotItem.Switch, 'Mire Dark Shooters'),
|
||||
Pot(0x9C, 0x17, PotItem.Switch, 'Mire Block X', PotFlags.Block),
|
||||
Pot(0x9C, 0x17, PotItem.Nothing, 'Mire Block X', PotFlags.Block),
|
||||
Pot(96, 7, PotItem.Heart, 'Mire Dark Shooters', PotFlags.NoSwitch)],
|
||||
0x96: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'),
|
||||
Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'),
|
||||
@@ -243,13 +245,13 @@ vanilla_pots = {
|
||||
Pot(48, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion),
|
||||
Pot(76, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion)],
|
||||
0xB3: [Pot(12, 20, PotItem.Key, 'Mire Spikes'), Pot(48, 20, PotItem.SmallMagic, 'Mire Spikes'), Pot(48, 28, PotItem.Switch, 'Mire Spikes')],
|
||||
180: [Pot(44, 28, PotItem.BigMagic, 'TR Final Abyss'), Pot(48, 28, PotItem.Heart, 'TR Final Abyss')],
|
||||
181: [Pot(112, 4, PotItem.FiveRupees, 'TR Dark Ride'), Pot(112, 15, PotItem.Heart, 'TR Dark Ride'), Pot(76, 16, PotItem.Switch, 'TR Dark Ride'), Pot(112, 16, PotItem.BigMagic, 'TR Dark Ride'), Pot(112, 17, PotItem.Heart, 'TR Dark Ride'),
|
||||
Pot(112, 28, PotItem.Bomb, 'TR Dark Ride')],
|
||||
182: [Pot(94, 9, PotItem.BigMagic, 'TR Refill')],
|
||||
183: [Pot(30, 5, PotItem.SmallMagic, 'TR Roller Room')],
|
||||
184: [Pot(96, 13, PotItem.Switch, 'Eastern Big Key'), Pot(88, 16, PotItem.Heart, 'Eastern Big Key'), Pot(104, 16, PotItem.Heart, 'Eastern Big Key')],
|
||||
185: [Pot(92, 18, PotItem.OneRupee, 'Eastern Cannonball'), Pot(96, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(104, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(108, 18, PotItem.OneRupee, 'Eastern Cannonball')],
|
||||
0xB4: [Pot(44, 28, PotItem.BigMagic, 'TR Final Abyss Balcony'), Pot(48, 28, PotItem.Heart, 'TR Final Abyss Balcony')],
|
||||
0xB5: [Pot(112, 4, PotItem.FiveRupees, 'TR Dark Ride'), Pot(112, 15, PotItem.Heart, 'TR Dark Ride'), Pot(76, 16, PotItem.Switch, 'TR Dark Ride'), Pot(112, 16, PotItem.BigMagic, 'TR Dark Ride'), Pot(112, 17, PotItem.Heart, 'TR Dark Ride'),
|
||||
Pot(112, 28, PotItem.Bomb, 'TR Dark Ride')],
|
||||
0xB6: [Pot(94, 9, PotItem.BigMagic, 'TR Refill')],
|
||||
0xB7: [Pot(30, 5, PotItem.SmallMagic, 'TR Roller Room')],
|
||||
0xB8: [Pot(96, 13, PotItem.Switch, 'Eastern Big Key'), Pot(88, 16, PotItem.Heart, 'Eastern Big Key'), Pot(104, 16, PotItem.Heart, 'Eastern Big Key')],
|
||||
0xB9: [Pot(92, 18, PotItem.OneRupee, 'Eastern Cannonball'), Pot(96, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(104, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(108, 18, PotItem.OneRupee, 'Eastern Cannonball')],
|
||||
0xBA: [Pot(100, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(88, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(94, 4, PotItem.OneRupee, 'Eastern Dark Pots'), Pot(76, 6, PotItem.Heart, 'Eastern Dark Pots'),
|
||||
Pot(112, 6, PotItem.Key, 'Eastern Dark Pots'), Pot(76, 10, PotItem.Heart, 'Eastern Dark Pots'), Pot(112, 10, PotItem.SmallMagic, 'Eastern Dark Pots'), Pot(94, 12, PotItem.OneRupee, 'Eastern Dark Pots')],
|
||||
0xBC: [Pot(86, 4, PotItem.Heart, 'Thieves Hallway'), Pot(102, 4, PotItem.Key, 'Thieves Hallway'), Pot(138, 3, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(178, 3, PotItem.Switch, 'Thieves Conveyor Maze'),
|
||||
@@ -271,8 +273,10 @@ vanilla_pots = {
|
||||
201: [Pot(30, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(94, 22, PotItem.OneRupee, 'Eastern Lobby'), Pot(60, 22, PotItem.Switch, 'Eastern Lobby')],
|
||||
203: [Pot(80, 4, PotItem.Nothing, 'Thieves Ambush'), Pot(80, 28, PotItem.Nothing, 'Thieves Ambush'), Pot(88, 16, PotItem.Heart, 'Thieves Ambush'), Pot(88, 28, PotItem.FiveRupees, 'Thieves Ambush')],
|
||||
204: [Pot(36, 4, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(36, 28, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(112, 4, PotItem.Heart, 'Thieves BK Corner'), Pot(112, 28, PotItem.Bomb, 'Thieves BK Corner')],
|
||||
206: [Pot(76, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(80, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(108, 12, PotItem.Bomb, 'Ice Antechamber'), Pot(112, 12, PotItem.FiveArrows, 'Ice Antechamber'),
|
||||
Pot(204, 11, PotItem.Hole, 'Ice Antechamber')], # Pot(0x6c, 8, PotItem.Nothing, 'Ice Antechamber', PotFlags.Block) this one has jellies
|
||||
0xCE: [Pot(76, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(80, 8, PotItem.SmallMagic, 'Ice Antechamber'),
|
||||
Pot(108, 12, PotItem.Bomb, 'Ice Antechamber'), Pot(112, 12, PotItem.FiveArrows, 'Ice Antechamber'),
|
||||
Pot(204, 11, PotItem.Hole, 'Ice Antechamber'),
|
||||
Pot(0x6c, 8, PotItem.Nothing, 'Ice Antechamber', PotFlags.Block)],
|
||||
208: [Pot(158, 5, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(140, 11, PotItem.OneRupee, 'Tower Dark Maze'), Pot(42, 13, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(48, 16, PotItem.Heart, 'Tower Dark Maze'),
|
||||
Pot(176, 20, PotItem.OneRupee, 'Tower Dark Maze'), Pot(146, 23, PotItem.FiveRupees, 'Tower Dark Maze'), Pot(12, 28, PotItem.Heart, 'Tower Dark Maze')],
|
||||
209: [Pot(48, 4, PotItem.BigMagic, 'Mire Conveyor Barrier'), Pot(168, 7, PotItem.OneRupee, 'Mire Conveyor Barrier'), Pot(76, 4, PotItem.OneRupee, 'Mire Neglected Room'), Pot(112, 4, PotItem.FiveArrows, 'Mire Neglected Room'),
|
||||
@@ -350,8 +354,8 @@ def shuffle_pots(world, player):
|
||||
|
||||
new_pot_contents = PotSecretTable()
|
||||
|
||||
for supertile in vanilla_pots:
|
||||
old_pots = vanilla_pots[supertile]
|
||||
for super_tile in vanilla_pots:
|
||||
old_pots = vanilla_pots[super_tile]
|
||||
new_pots = [Pot(pot.x, pot.y, PotItem.Nothing, pot.room, pot.flags) for pot in old_pots]
|
||||
# sort in the order Hole, Switch, Key, Other, Nothing
|
||||
sort_order = {PotItem.Hole: 4, PotItem.Switch: 3, PotItem.Key: 2, PotItem.Nothing: 0}
|
||||
@@ -401,11 +405,54 @@ def shuffle_pots(world, player):
|
||||
else:
|
||||
raise Exception("Switch location in room %s requires logic change" % new_pot.room)
|
||||
|
||||
new_pot_contents.room_map[supertile] = new_pots
|
||||
new_pot_contents.room_map[super_tile] = new_pots
|
||||
|
||||
world.pot_contents[player] = new_pot_contents
|
||||
|
||||
|
||||
def shuffle_pot_switches(world, player):
|
||||
import RaceRandom as random
|
||||
|
||||
for super_tile in vanilla_pots:
|
||||
old_pots = vanilla_pots[super_tile]
|
||||
new_pots = world.pot_contents[player].room_map[super_tile]
|
||||
# sort in the order Hole, Switch, Key, Other, Nothing
|
||||
sort_order = {PotItem.Hole: 4, PotItem.Switch: 3, PotItem.Key: 2, PotItem.Nothing: 0}
|
||||
old_pots = sorted(old_pots, key=lambda pot: sort_order.get(pot.item, 1), reverse=True)
|
||||
|
||||
for old_pot in old_pots:
|
||||
if old_pot.item != PotItem.Switch:
|
||||
break
|
||||
else:
|
||||
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)]
|
||||
|
||||
new_pot = random.choice(available_pots)
|
||||
new_pot.item, old_pot.item = old_pot.item, new_pot.item
|
||||
if world.retro[player] and new_pot.item == PotItem.FiveArrows:
|
||||
new_pot.item = PotItem.FiveRupees
|
||||
|
||||
if new_pot.item == PotItem.Switch and (new_pot.flags & PotFlags.SwitchLogicChange):
|
||||
if new_pot.room == 'PoD Basement Ledge':
|
||||
basement = world.get_region(old_pot.room, player)
|
||||
ledge = world.get_region(new_pot.room, player)
|
||||
ledge.locations.append(basement.locations.pop())
|
||||
elif new_pot.room == 'Swamp Push Statue':
|
||||
from Rules import set_rule
|
||||
set_rule(world.get_entrance('Swamp Push Statue NE', player), lambda state: state.has('Cane of Somaria', player))
|
||||
world.get_door('Swamp Push Statue NW', player).blocked = True
|
||||
elif new_pot.room == 'Thieves Attic Hint':
|
||||
# Rule is created based on barrier
|
||||
world.get_door('Thieves Attic ES', player).barrier(CrystalBarrier.Orange)
|
||||
else:
|
||||
raise Exception("Switch location in room %s requires logic change" % new_pot.room)
|
||||
for location in world.get_locations():
|
||||
if location.player == player and location.type == LocationType.Pot and location.pot.item == PotItem.Switch:
|
||||
location.real = False
|
||||
world.dynamic_locations.remove(location)
|
||||
location.parent.locations.remove(location)
|
||||
world.clear_location_cache()
|
||||
|
||||
|
||||
key_drop_data = {
|
||||
'Hyrule Castle - Map Guard Key Drop': ['Drop', (0x09E20C, 0x72), 'in Hyrule Castle', 'Small Key (Escape)'],
|
||||
'Hyrule Castle - Boomerang Guard Key Drop': ['Drop', (0x09E204, 0x71), 'in Hyrule Castle', 'Small Key (Escape)'],
|
||||
@@ -459,9 +506,8 @@ class PotSecretTable(object):
|
||||
data_address = pc_to_snes(data_pointer) & 0xFFFF
|
||||
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(data_address))
|
||||
for pot in self.room_map[room]:
|
||||
if not pot.empty():
|
||||
rom.write_bytes(data_pointer + list_idx * 3, pot.pot_data())
|
||||
list_idx += 1
|
||||
rom.write_bytes(data_pointer + list_idx * 3, pot.pot_data())
|
||||
list_idx += 1
|
||||
rom.write_bytes(data_pointer + list_idx * 3, [0xFF, 0xFF])
|
||||
data_pointer += 3 * list_idx + 2
|
||||
else:
|
||||
@@ -472,7 +518,7 @@ class PotSecretTable(object):
|
||||
size = 0x128 * 2
|
||||
for room in range(0, 0x128):
|
||||
if room in self.room_map:
|
||||
pot_list = [p for p in self.room_map[room] if not p.empty()]
|
||||
pot_list = [p for p in self.room_map[room]]
|
||||
if pot_list:
|
||||
size += len(pot_list) * 3 + 2
|
||||
return size
|
||||
|
||||
71
Regions.py
71
Regions.py
@@ -726,7 +726,8 @@ def create_dungeon_regions(world, player):
|
||||
create_dungeon_region(player, 'TR Crystal Maze Interior', 'Turtle Rock', None, ['TR Crystal Maze Interior to End Barrier - Blue', 'TR Crystal Maze Interior to Start Barrier - Blue', 'TR Crystal Maze Interior to Start Bypass', 'TR Crystal Maze Interior to End Bypass']),
|
||||
create_dungeon_region(player, 'TR Crystal Maze End', 'Turtle Rock', None, ['TR Crystal Maze North Stairs', 'TR Crystal Maze End to Interior Barrier - Blue', 'TR Crystal Maze End to Ranged Crystal']),
|
||||
create_dungeon_region(player, 'TR Crystal Maze End - Ranged Crystal', 'Turtle Rock', None, ['TR Crystal Maze End Ranged Crystal Exit']),
|
||||
create_dungeon_region(player, 'TR Final Abyss', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss NW']),
|
||||
create_dungeon_region(player, 'TR Final Abyss Balcony', 'Turtle Rock', None, ['TR Final Abyss South Stairs', 'TR Final Abyss Balcony Path']),
|
||||
create_dungeon_region(player, 'TR Final Abyss Ledge', 'Turtle Rock', None, ['TR Final Abyss NW', 'TR Final Abyss Ledge Path']),
|
||||
create_dungeon_region(player, 'TR Boss', 'Turtle Rock', ['Turtle Rock - Boss', 'Turtle Rock - Prize'], ['TR Boss SW']),
|
||||
|
||||
# gt
|
||||
@@ -981,49 +982,53 @@ def create_shops(world, player):
|
||||
|
||||
|
||||
def adjust_locations(world, player):
|
||||
if world.keydropshuffle[player] != 'none':
|
||||
world.pot_contents[player] = PotSecretTable()
|
||||
for location in key_drop_data.keys():
|
||||
loc = world.get_location(location, player)
|
||||
# handle pots
|
||||
world.pot_contents[player] = PotSecretTable()
|
||||
for location, datum in key_drop_data.items():
|
||||
loc = world.get_location(location, player)
|
||||
if 'Drop' == datum[0]:
|
||||
loc.type = LocationType.Drop
|
||||
snes_address, room = datum[1]
|
||||
loc.address = snes_address
|
||||
else:
|
||||
loc.type = LocationType.Pot
|
||||
pot = next(p for p in vanilla_pots[datum[1]] if p.item == PotItem.Key).copy()
|
||||
loc.pot = pot
|
||||
world.pot_contents[player].room_map[datum[1]].append(pot)
|
||||
if world.keydropshuffle[player] == 'none':
|
||||
loc.skip = True
|
||||
else:
|
||||
key_item = loc.item
|
||||
key_item.location = None
|
||||
|
||||
loc.forced_item = None
|
||||
loc.item = None
|
||||
loc.event = False
|
||||
datum = key_drop_data[location]
|
||||
# todo: set type of location
|
||||
if 'Drop' == datum[0]:
|
||||
loc.type = LocationType.Drop
|
||||
snes_address, room = datum[1]
|
||||
loc.address = snes_address
|
||||
else:
|
||||
loc.type = LocationType.Pot
|
||||
pot = next(p for p in vanilla_pots[datum[1]] if p.item == PotItem.Key).copy()
|
||||
loc.pot = pot
|
||||
world.pot_contents[player].room_map[datum[1]].append(pot)
|
||||
item_dungeon = key_item.dungeon
|
||||
dungeon = world.get_dungeon(item_dungeon, player)
|
||||
if key_item.smallkey and not world.retro[player]:
|
||||
dungeon.small_keys.append(key_item)
|
||||
elif key_item.bigkey:
|
||||
dungeon.big_key = key_item
|
||||
if world.keydropshuffle[player] == 'potsanity':
|
||||
for super_tile, pot_list in vanilla_pots.items():
|
||||
for pot_index, pot_orig in enumerate(pot_list):
|
||||
pot = pot_orig.copy()
|
||||
if pot.item in [PotItem.Hole, PotItem.Switch]:
|
||||
world.pot_contents[player].room_map[super_tile].append(pot)
|
||||
elif pot.item != PotItem.Key:
|
||||
parent = world.get_region(pot.room, player)
|
||||
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||
pot_location = Location(player, f'{pot.room} {descriptor}', player, hint_text='in a pot',
|
||||
parent=parent)
|
||||
world.dynamic_locations.append(pot_location)
|
||||
pot_location.pot = pot
|
||||
world.pot_contents[player].room_map[super_tile].append(pot)
|
||||
pot_location.type = LocationType.Pot
|
||||
parent.locations.append(pot_location)
|
||||
for super_tile, pot_list in vanilla_pots.items():
|
||||
for pot_index, pot_orig in enumerate(pot_list):
|
||||
pot = pot_orig.copy()
|
||||
if pot.item != PotItem.Key:
|
||||
world.pot_contents[player].room_map[super_tile].append(pot)
|
||||
if world.keydropshuffle[player] == 'potsanity':
|
||||
if (pot.item not in [PotItem.Key, PotItem.Hole]
|
||||
and (pot.item != PotItem.Switch or world.potshuffle[player])):
|
||||
parent = world.get_region(pot.room, player)
|
||||
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
|
||||
# todo: better hints
|
||||
hint_text = 'under a block' if pot.flags & PotFlags.Block else 'in a pot'
|
||||
pot_location = Location(player, f'{pot.room} {descriptor}', player, hint_text=hint_text,
|
||||
parent=parent)
|
||||
world.dynamic_locations.append(pot_location)
|
||||
pot_location.pot = pot
|
||||
|
||||
pot_location.type = LocationType.Pot
|
||||
parent.locations.append(pot_location)
|
||||
if world.shopsanity[player]:
|
||||
index = 0
|
||||
for shop, location_list in shop_to_location_table.items():
|
||||
@@ -1041,6 +1046,8 @@ def adjust_locations(world, player):
|
||||
if location:
|
||||
location.type = LocationType.Logical
|
||||
location.real = False
|
||||
if l not in ['Ganon', 'Agahnim 1', 'Agahnim 2']:
|
||||
location.skip = True
|
||||
|
||||
|
||||
|
||||
|
||||
33
Rom.py
33
Rom.py
@@ -35,7 +35,7 @@ from source.classes.SFX import randomize_sfx
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '3ee527f67af25e860ffd4364d2369f0e'
|
||||
RANDOMIZERBASEHASH = 'c1b18f6455af56b738d4fe8f266ef055'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -731,10 +731,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
dr_flags |= DROptions.Fix_EG
|
||||
|
||||
my_locations = world.get_filled_locations(player)
|
||||
valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and l.pot.indicator)
|
||||
valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and not l.forced_item)
|
||||
or (l.type == LocationType.Drop and not l.forced_item)
|
||||
or (l.type == LocationType.Normal and not l.forced_item)
|
||||
or (l.type == LocationType.Shop and world.shopsanity[player]))]
|
||||
valid_loc_by_dungeon = valid_dungeon_locations(valid_locations)
|
||||
|
||||
# fix hc big key problems (map and compass too)
|
||||
if world.doorShuffle[player] == 'crossed' or world.keydropshuffle[player] != 'none':
|
||||
@@ -742,7 +743,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
rom.write_byte(0x15270, 2)
|
||||
sanctuary = world.get_region('Sanctuary', player)
|
||||
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
|
||||
update_compasses(rom, valid_locations, world, player)
|
||||
update_compasses(rom, valid_loc_by_dungeon, world, player)
|
||||
|
||||
def should_be_bunny(region, mode):
|
||||
if mode != 'inverted':
|
||||
@@ -774,10 +775,14 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
else:
|
||||
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
||||
rom.write_byte(0x13f030+offset, layout.max_chests)
|
||||
# todo: fix these for pot shuffle
|
||||
builder = world.dungeon_layouts[player][name]
|
||||
rom.write_byte(0x13f080+offset, builder.location_cnt % 10)
|
||||
rom.write_byte(0x13f090+offset, builder.location_cnt // 10)
|
||||
rom.write_byte(0x13f0a0+offset, builder.location_cnt)
|
||||
valid_cnt = len(valid_loc_by_dungeon[name])
|
||||
if valid_cnt > 99:
|
||||
logging.getLogger('').warning(f'{name} exceeds 99 in locations ({valid_cnt})')
|
||||
rom.write_byte(0x13f080+offset, valid_cnt % 10)
|
||||
rom.write_byte(0x13f090+offset, valid_cnt // 10)
|
||||
rom.write_byte(0x13f0a0+offset, valid_cnt)
|
||||
bk_status = 1 if builder.bk_required else 0
|
||||
bk_status = 2 if builder.bk_provided else bk_status
|
||||
rom.write_byte(0x13f040+offset*2, bk_status)
|
||||
@@ -865,19 +870,25 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
if world.keydropshuffle[player] != 'none':
|
||||
rom.write_byte(0x142A50, 1)
|
||||
rom.write_byte(0x142A51, 1)
|
||||
rom.write_byte(0x142A52, 216-credits_total) # todo: this is now a delta
|
||||
if world.keydropshuffle[player] == 'potsanity':
|
||||
rom.write_bytes(0x04DFD8, [0x18, 0x0B, 0x1C])
|
||||
rom.write_byte(0x04E002, 0xFF)
|
||||
rom.write_byte(0x142A52, credits_total - 216) # todo: this is now a delta
|
||||
|
||||
write_int16(rom, 0x187010, credits_total) # dynamic credits
|
||||
if credits_total != 216:
|
||||
# collection rate address (hi):
|
||||
cr_address = 0x238057
|
||||
cr_pc = cr_address - 0x120000 # convert to pc
|
||||
first_top, first_bot = credits_digit((credits_total // 100) % 10)
|
||||
mid_top, mid_bot = credits_digit((credits_total // 10) % 10)
|
||||
last_top, last_bot = credits_digit(credits_total % 10)
|
||||
# top half
|
||||
rom.write_byte(cr_pc, first_top)
|
||||
rom.write_byte(cr_pc+0x1, mid_top)
|
||||
rom.write_byte(cr_pc+0x2, last_top)
|
||||
# bottom half
|
||||
rom.write_byte(cr_pc+0x1e, first_bot)
|
||||
rom.write_byte(cr_pc+0x1f, mid_bot)
|
||||
rom.write_byte(cr_pc+0x20, last_bot)
|
||||
|
||||
@@ -1441,7 +1452,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
elif world.dungeon_counters[player] == 'on':
|
||||
compass_mode = 0x02 # always on
|
||||
elif (world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla'
|
||||
or world.dungeon_counters[player] == 'pickup' or world.keydropshuffle != 'none'):
|
||||
or world.dungeon_counters[player] == 'pickup' or world.keydropshuffle[player] != 'none'):
|
||||
compass_mode = 0x01 # show on pickup
|
||||
if world.shuffle[player] != 'vanilla' and world.overworld_map[player] != 'default':
|
||||
compass_mode |= 0x80 # turn on locating dungeons
|
||||
@@ -2615,11 +2626,15 @@ def patch_shuffled_dark_sanc(world, rom, player):
|
||||
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
|
||||
|
||||
|
||||
def update_compasses(rom, valid_locations, world, player):
|
||||
def valid_dungeon_locations(valid_locations):
|
||||
dungeon_locations = collections.defaultdict(set)
|
||||
for l in valid_locations:
|
||||
if l.parent_region.dungeon:
|
||||
dungeon_locations[l.parent_region.dungeon.name].add(l)
|
||||
return dungeon_locations
|
||||
|
||||
|
||||
def update_compasses(rom, dungeon_locations, world, player):
|
||||
layouts = world.dungeon_layouts[player]
|
||||
provided_dungeon = False
|
||||
for name, builder in layouts.items():
|
||||
|
||||
8
Rules.py
8
Rules.py
@@ -336,8 +336,8 @@ def global_rules(world, player):
|
||||
set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player))
|
||||
set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_entrance('TR Final Abyss South Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_entrance('TR Final Abyss NW', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_entrance('TR Final Abyss Balcony Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_entrance('TR Final Abyss Ledge Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Bottom Right', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||
set_rule(world.get_location('Turtle Rock - Eye Bridge - Top Left', player), lambda state: state.has('Cane of Byrna', player) or state.has('Cape', player) or state.has('Mirror Shield', player))
|
||||
@@ -1912,7 +1912,7 @@ bunny_revivable_entrances = {
|
||||
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
|
||||
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
|
||||
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
|
||||
"Mire Spikes", "TR Final Abyss", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
|
||||
"Mire Spikes", "TR Final Abyss Balcony", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
|
||||
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
|
||||
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
|
||||
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
|
||||
@@ -1980,7 +1980,7 @@ bunny_impassible_doors = {
|
||||
'TR Pokey 2 Bottom to Top Barrier - Blue', 'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
|
||||
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs',
|
||||
'TR Dark Ride SW', 'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue',
|
||||
'TR Final Abyss South Stairs', 'TR Final Abyss NW', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
||||
'TR Final Abyss Balcony Path', 'TR Final Abyss Ledge Path', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
||||
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
|
||||
'GT Crystal Conveyor NE', 'GT Crystal Conveyor WN', 'GT Conveyor Cross EN', 'GT Conveyor Cross WN',
|
||||
'GT Hookshot East-North Path', 'GT Hookshot East-South Path', 'GT Hookshot North-East Path',
|
||||
|
||||
Binary file not shown.
@@ -492,6 +492,19 @@ def filter_locations(item_to_place, locations, world, vanilla_skip=False):
|
||||
return locations
|
||||
|
||||
|
||||
def filter_pot_locations(locations, world):
|
||||
if world.algorithm == 'district':
|
||||
config = world.item_pool_config
|
||||
restricted = config.location_groups[0].locations
|
||||
filtered = [l for l in locations if l.name not in restricted or l.player not in restricted[l.name]]
|
||||
return filtered if len(filtered) > 0 else locations
|
||||
if world.algorithm == 'vanilla_fill':
|
||||
# todo: vanilla pot location stuff
|
||||
pass
|
||||
return locations
|
||||
|
||||
|
||||
|
||||
vanilla_mapping = {
|
||||
'Green Pendant': ['Eastern Palace - Prize'],
|
||||
'Red Pendant': ['Desert Palace - Prize', 'Tower of Hera - Prize'],
|
||||
|
||||
Reference in New Issue
Block a user