Implemented Parallel Worlds functionality

This commit is contained in:
codemann8
2021-05-05 15:15:58 -05:00
parent a5e17526da
commit d1b82e5910
3 changed files with 437 additions and 71 deletions

View File

@@ -1,5 +1,16 @@
from BaseClasses import OWEdge, Direction, Terrain, WorldType, PolSlot from BaseClasses import OWEdge, Direction, Terrain, WorldType, PolSlot
from enum import Enum, unique
@unique
class OpenStd(Enum):
Open = 0
Standard = 1
@unique
class IsParallel(Enum):
No = 0
Yes = 1
# constants # constants
We = Direction.West We = Direction.West
@@ -16,6 +27,12 @@ DW = WorldType.Dark
Vt = PolSlot.NorthSouth Vt = PolSlot.NorthSouth
Hz = PolSlot.EastWest Hz = PolSlot.EastWest
Op = OpenStd.Open
St = OpenStd.Standard
PL = IsParallel.Yes
NP = IsParallel.No
def create_owedges(world, player): def create_owedges(world, player):
edges = [ edges = [
@@ -312,13 +329,27 @@ def create_owedge(player, name, owIndex, direction, terrain, edge_id, owSlotInde
OWEdgeGroups = { OWEdgeGroups = {
(LW, Hz, Ld, 1): ( #(IsStandard, World, EdgeAxis, Terrain, HasParallel, NumberInGroup)
(St, LW, Vt, Ld, PL, 1): (
[
['Hyrule Castle SW'],
['Hyrule Castle SE']
],
[
['Central Bonk Rocks NW'],
['Links House NE']
]
),
(St, LW, Hz, Ld, PL, 3): (
[['Central Bonk Rocks EN', 'Central Bonk Rocks EC', 'Central Bonk Rocks ES']],
[['Links House WN', 'Links House WC', 'Links House WS']]
),
(Op, LW, Hz, Ld, PL, 1): (
[ [
['Lost Woods EN'], ['Lost Woods EN'],
['East Death Mountain EN'], ['East Death Mountain EN'],
['Sanctuary EC'], ['Sanctuary EC'],
['Graveyard EC'], ['Graveyard EC'],
['Forgotten Forest ES'],
['Kakariko ES'], ['Kakariko ES'],
['Hyrule Castle ES'], ['Hyrule Castle ES'],
['Maze Race ES'], ['Maze Race ES'],
@@ -338,7 +369,6 @@ OWEdgeGroups = {
['Death Mountain TR Pegs WN'], ['Death Mountain TR Pegs WN'],
['Graveyard WC'], ['Graveyard WC'],
['River Bend WC'], ['River Bend WC'],
['Hyrule Castle WN'],
['Blacksmith WS'], ['Blacksmith WS'],
['Sand Dunes WN'], ['Sand Dunes WN'],
['Kakariko Suburb WS'], ['Kakariko Suburb WS'],
@@ -354,7 +384,15 @@ OWEdgeGroups = {
['East Death Mountain WS'] ['East Death Mountain WS']
] ]
), ),
(LW, Vt, Ld, 1): ( (Op, LW, Hz, Ld, NP, 1): (
[
['Forgotten Forest ES']
],
[
['Hyrule Castle WN']
]
),
(Op, LW, Vt, Ld, PL, 1): (
[ [
['Lumberjack SW'], ['Lumberjack SW'],
['Mountain Entry SE'], ['Mountain Entry SE'],
@@ -363,8 +401,6 @@ OWEdgeGroups = {
['Kakariko Fortune SC'], ['Kakariko Fortune SC'],
['Wooden Bridge SW'], ['Wooden Bridge SW'],
['Kakariko SE'], ['Kakariko SE'],
['Hyrule Castle SW'],
['Hyrule Castle SE'],
['Sand Dunes SC'], ['Sand Dunes SC'],
['Eastern Palace SW'], ['Eastern Palace SW'],
['Eastern Palace SE'], ['Eastern Palace SE'],
@@ -384,8 +420,6 @@ OWEdgeGroups = {
['Kakariko NE'], ['Kakariko NE'],
['Sand Dunes NW'], ['Sand Dunes NW'],
['Kakariko Suburb NE'], ['Kakariko Suburb NE'],
['Central Bonk Rocks NW'],
['Links House NE'],
['Stone Bridge NC'], ['Stone Bridge NC'],
['Tree Line NW'], ['Tree Line NW'],
['Eastern Nook NE'], ['Eastern Nook NE'],
@@ -398,11 +432,10 @@ OWEdgeGroups = {
['Octoballoon NE'] ['Octoballoon NE']
] ]
), ),
(LW, Hz, Ld, 2): ( (Op, LW, Hz, Ld, PL, 2): (
[ [
['Kakariko Fortune EN', 'Kakariko Fortune ES'], ['Kakariko Fortune EN', 'Kakariko Fortune ES'],
['Kakariko Pond EN', 'Kakariko Pond ES'], ['Kakariko Pond EN', 'Kakariko Pond ES'],
['Desert EC', 'Desert ES'],
['Desert Pass EC', 'Desert Pass ES'], ['Desert Pass EC', 'Desert Pass ES'],
['River Bend EC', 'River Bend ES'], ['River Bend EC', 'River Bend ES'],
['C Whirlpool EN', 'C Whirlpool ES'] ['C Whirlpool EN', 'C Whirlpool ES']
@@ -410,13 +443,20 @@ OWEdgeGroups = {
[ [
['Kakariko Pond WN', 'Kakariko Pond WS'], ['Kakariko Pond WN', 'Kakariko Pond WS'],
['Sanctuary WN', 'Sanctuary WS'], ['Sanctuary WN', 'Sanctuary WS'],
['Desert Pass WC', 'Desert Pass WS'],
['Dam WC', 'Dam WS'], ['Dam WC', 'Dam WS'],
['Potion Shop WC', 'Potion Shop WS'], ['Potion Shop WC', 'Potion Shop WS'],
['Statues WN', 'Statues WS'] ['Statues WN', 'Statues WS']
] ]
), ),
(LW, Vt, Ld, 2): ( (Op, LW, Hz, Ld, NP, 2): (
[
['Desert EC', 'Desert ES']
],
[
['Desert Pass WC', 'Desert Pass WS']
]
),
(Op, LW, Vt, Ld, PL, 2): (
[ [
['Lost Woods SW', 'Lost Woods SC'], ['Lost Woods SW', 'Lost Woods SC'],
['Lost Woods Pass SW', 'Lost Woods Pass SE'], ['Lost Woods Pass SW', 'Lost Woods Pass SE'],
@@ -432,11 +472,7 @@ OWEdgeGroups = {
['Wooden Bridge NW', 'Wooden Bridge NE'] ['Wooden Bridge NW', 'Wooden Bridge NE']
] ]
), ),
(LW, Hz, Ld, 3): ( (Op, LW, Hz, Wr, PL, 1): (
[['Central Bonk Rocks EN', 'Central Bonk Rocks EC', 'Central Bonk Rocks ES']],
[['Links House WN', 'Links House WC', 'Links House WS']]
),
(LW, Hz, Wr, 1): (
[ [
['Potion Shop EN'], ['Potion Shop EN'],
['Lake Hylia EC'], ['Lake Hylia EC'],
@@ -452,7 +488,7 @@ OWEdgeGroups = {
['Statues WC'] ['Statues WC']
] ]
), ),
(LW, Vt, Wr, 1): ( (Op, LW, Vt, Wr, PL, 1): (
[ [
['Tree Line SC'], ['Tree Line SC'],
['Ice Cave SW'], ['Ice Cave SW'],
@@ -464,7 +500,7 @@ OWEdgeGroups = {
['Wooden Bridge NC'] ['Wooden Bridge NC']
] ]
), ),
(DW, Hz, Ld, 1): ( (Op, DW, Hz, Ld, PL, 1): (
[ [
['Skull Woods EN'], ['Skull Woods EN'],
['East Dark Death Mountain EN'], ['East Dark Death Mountain EN'],
@@ -502,7 +538,7 @@ OWEdgeGroups = {
['East Dark Death Mountain WS'] ['East Dark Death Mountain WS']
] ]
), ),
(DW, Vt, Ld, 1): ( (Op, DW, Vt, Ld, PL, 1): (
[ [
['Dark Lumberjack SW'], ['Dark Lumberjack SW'],
['Bumper Cave SE'], ['Bumper Cave SE'],
@@ -546,12 +582,11 @@ OWEdgeGroups = {
['Bomber Corner NE'] ['Bomber Corner NE']
] ]
), ),
(DW, Hz, Ld, 2): ( (Op, DW, Hz, Ld, PL, 2): (
[ [
['Dark Fortune EN', 'Dark Fortune ES'], ['Dark Fortune EN', 'Dark Fortune ES'],
['Outcast Pond EN', 'Outcast Pond ES'], ['Outcast Pond EN', 'Outcast Pond ES'],
['Swamp Nook EC', 'Swamp Nook ES'], ['Swamp Nook EC', 'Swamp Nook ES'],
['Dig Game EC', 'Dig Game ES'],
['Qirn Jump EC', 'Qirn Jump ES'], ['Qirn Jump EC', 'Qirn Jump ES'],
['Dark C Whirlpool EN', 'Dark C Whirlpool ES'] ['Dark C Whirlpool EN', 'Dark C Whirlpool ES']
], ],
@@ -559,12 +594,19 @@ OWEdgeGroups = {
['Outcast Pond WN', 'Outcast Pond WS'], ['Outcast Pond WN', 'Outcast Pond WS'],
['Dark Chapel WN', 'Dark Chapel WS'], ['Dark Chapel WN', 'Dark Chapel WS'],
['Swamp WC', 'Swamp WS'], ['Swamp WC', 'Swamp WS'],
['Frog WC', 'Frog WS'],
['Dark Witch WC', 'Dark Witch WS'], ['Dark Witch WC', 'Dark Witch WS'],
['Hype Cave WN', 'Hype Cave WS'] ['Hype Cave WN', 'Hype Cave WS']
] ]
), ),
(DW, Vt, Ld, 2): ( (Op, DW, Hz, Ld, NP, 2): (
[
['Dig Game EC', 'Dig Game ES']
],
[
['Frog WC', 'Frog WS']
]
),
(Op, DW, Vt, Ld, PL, 2): (
[ [
['Skull Woods SW', 'Skull Woods SC'], ['Skull Woods SW', 'Skull Woods SC'],
['Skull Woods Pass SW', 'Skull Woods Pass SE'], ['Skull Woods Pass SW', 'Skull Woods Pass SE'],
@@ -580,11 +622,11 @@ OWEdgeGroups = {
['Broken Bridge NW', 'Broken Bridge NE'] ['Broken Bridge NW', 'Broken Bridge NE']
] ]
), ),
(DW, Hz, Ld, 3): ( (Op, DW, Hz, Ld, PL, 3): (
[['Dark Bonk Rocks EN', 'Dark Bonk Rocks EC', 'Dark Bonk Rocks ES']], [['Dark Bonk Rocks EN', 'Dark Bonk Rocks EC', 'Dark Bonk Rocks ES']],
[['Big Bomb Shop WN', 'Big Bomb Shop WC', 'Big Bomb Shop WS']] [['Big Bomb Shop WN', 'Big Bomb Shop WC', 'Big Bomb Shop WS']]
), ),
(DW, Hz, Wr, 1): ( (Op, DW, Hz, Wr, PL, 1): (
[ [
['Dark Witch EN'], ['Dark Witch EN'],
['Ice Lake EC'], ['Ice Lake EC'],
@@ -600,7 +642,7 @@ OWEdgeGroups = {
['Hype Cave WC'] ['Hype Cave WC']
] ]
), ),
(DW, Vt, Wr, 1): ( (Op, DW, Vt, Wr, PL, 1): (
[ [
['Dark Tree Line SC'], ['Dark Tree Line SC'],
['Shopping Mall SW'], ['Shopping Mall SW'],

View File

@@ -1,6 +1,7 @@
import random import random
from BaseClasses import OWEdge, WorldType, Direction, Terrain from BaseClasses import OWEdge, WorldType, Direction, Terrain
from OWEdges import OWEdgeGroups from Utils import bidict
from OWEdges import OWEdgeGroups, IsParallel
__version__ = '0.1.1.2-u' __version__ = '0.1.1.2-u'
@@ -18,55 +19,180 @@ def link_overworld(world, player):
for exitname, destname in default_connections: for exitname, destname in default_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player)
else: else:
remaining_edges = [] connected_edges = []
for exitname, destname in default_connections:
remaining_edges.append(exitname)
remaining_edges.append(destname)
if world.mode[player] == 'standard': if world.owKeepSimilar[player] and world.owParallelWorlds[player]:
for exitname, destname in standard_connections: for exitname, destname in parallelsimilar_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player)
remaining_edges.remove(exitname) connected_edges.append(exitname)
remaining_edges.remove(destname) connected_edges.append(destname)
#TODO: Remove, just for testing #TODO: Remove, just for testing
for exitname, destname in test_connections: for exitname, destname in test_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player)
remaining_edges.remove(exitname) connected_edges.append(exitname)
remaining_edges.remove(destname) connected_edges.append(destname)
trimmed_groups = remove_reserved(world, OWEdgeGroups, connected_edges, player)
if world.owShuffle[player] == 'full': if world.owShuffle[player] == 'full':
#predefined shuffle groups get reorganized here
if world.owKeepSimilar[player]: if world.owKeepSimilar[player]:
#TODO: remove edges from list that are already placed, Std and Plando if world.owParallelWorlds[player]:
# shuffle edges in groups that connect the same pair of tiles if world.mode[player] == 'standard':
for grouping in (OWEdgeGroups, None): #tuple stays (A,B,C,D,E,F)
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work for grouping in (trimmed_groups, None):
groups = list(grouping.values()) if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
groups = list(grouping.values())
else:
#tuple goes to (_,B,C,D,E,F)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
new_grouping[(region, axis, terrain, parallel, count)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
(forward_edges, back_edges) = grouping[group]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel, count)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
else:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,F)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(std, region, axis, terrain, _, count) = group
new_grouping[(std, region, axis, terrain, count)] = ([], [])
for group in grouping.keys():
(std, region, axis, terrain, _, count) = group
(forward_edges, back_edges) = grouping[group]
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, count)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(std, region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,_,F)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, _, count) = group
new_grouping[(region, axis, terrain, count)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, _, count) = group
(forward_edges, back_edges) = grouping[group]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, count)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
else: else:
for grouping in (OWEdgeGroups, None): if world.owParallelWorlds[player]:
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work if world.mode[player] == 'standard':
new_grouping = {} #tuple stays (A,B,C,D,E,_)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys(): for group in grouping.keys():
(area, dir, terrain, count) = group (std, region, axis, terrain, parallel, _) = group
new_grouping[(area, dir, terrain)] = ([], []) new_grouping[(std, region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys(): for group in grouping.keys():
(forward_edges, back_edges) = grouping[group] (std, region, axis, terrain, parallel, _) = group
forward_edges = [[i] for l in forward_edges for i in l] (forward_edges, back_edges) = grouping[group]
back_edges = [[i] for l in back_edges for i in l] forward_edges = [[i] for l in forward_edges for i in l]
for (e1, e2) in test_connections: back_edges = [[i] for l in back_edges for i in l]
forward_edges = list(filter(([e1]).__ne__, forward_edges))
forward_edges = list(filter(([e2]).__ne__, forward_edges)) (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, parallel)]
back_edges = list(filter(([e1]).__ne__, back_edges)) exist_forward_edges.extend(forward_edges)
back_edges = list(filter(([e2]).__ne__, back_edges)) exist_back_edges.extend(back_edges)
(area, dir, terrain, _) = group new_grouping[(std, region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
(exist_forward_edges, exist_back_edges) = new_grouping[(area, dir, terrain)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(area, dir, terrain)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values()) groups = list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,E,_)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
new_grouping[(region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
else:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,_)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(std, region, axis, terrain, _, _) = group
new_grouping[(std, region, axis, terrain)] = ([], [])
for group in grouping.keys():
(std, region, axis, terrain, _, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(std, region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,_,_)
for grouping in (trimmed_groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, _, _) = group
new_grouping[(region, axis, terrain)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, _, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
groups = list(new_grouping.values())
#all shuffling occurs here #all shuffling occurs here
random.shuffle(groups) random.shuffle(groups)
@@ -77,10 +203,14 @@ def link_overworld(world, player):
assert len(forward_set) == len(back_set) assert len(forward_set) == len(back_set)
for (forward_edge, back_edge) in zip(forward_set, back_set): for (forward_edge, back_edge) in zip(forward_set, back_set):
connect_two_way(world, forward_edge, back_edge, player) connect_two_way(world, forward_edge, back_edge, player)
remaining_edges.remove(forward_edge) connected_edges.append(forward_edge)
remaining_edges.remove(back_edge) connected_edges.append(back_edge)
if world.owParallelWorlds[player] and forward_edge in parallel_links.keys():
assert len(remaining_edges) == 0, remaining_edges connect_two_way(world, parallel_links[forward_edge], parallel_links[back_edge], player)
connected_edges.append(parallel_links[forward_edge])
connected_edges.append(parallel_links[back_edge])
assert len(connected_edges) == len(default_connections) * 2, connected_edges
else: else:
raise NotImplementedError('Shuffling not supported yet') raise NotImplementedError('Shuffling not supported yet')
@@ -88,8 +218,8 @@ def connect_custom(world, player):
if hasattr(world, 'custom_overworld') and world.custom_overworld[player]: if hasattr(world, 'custom_overworld') and world.custom_overworld[player]:
for edgename1, edgename2 in world.custom_overworld[player]: for edgename1, edgename2 in world.custom_overworld[player]:
connect_two_way(world, edgename1, edgename2, player) connect_two_way(world, edgename1, edgename2, player)
remaining_edges.remove(edgename1) connected_edges.append(edgename1)
remaining_edges.remove(edgename2) connected_edges.append(edgename2)
def connect_simple(world, exitname, regionname, player): def connect_simple(world, exitname, regionname, player):
world.get_entrance(exitname, player).connect(world.get_region(regionname, player)) world.get_entrance(exitname, player).connect(world.get_region(regionname, player))
@@ -118,6 +248,38 @@ def connect_two_way(world, edgename1, edgename2, player):
world.spoiler.set_overworld(edgename2, edgename1, 'both', player) world.spoiler.set_overworld(edgename2, edgename1, 'both', player)
def remove_reserved(world, groupedlist, connected_edges, player):
#TODO: Remove edges set in connect_custom
new_grouping = {}
for group in groupedlist.keys():
new_grouping[group] = ([], [])
for group in groupedlist.keys():
(std, region, axis, terrain, parallel, count) = group
(forward_edges, back_edges) = groupedlist[group]
for edge in connected_edges:
forward_edges = list(list(filter((edge).__ne__, i)) for i in forward_edges)
back_edges = list(list(filter((edge).__ne__, i)) for i in back_edges)
if world.owParallelWorlds[player] and parallel == IsParallel.Yes and region == WorldType.Dark:
for edge in parallel_links:
forward_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in forward_edges)
back_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in back_edges)
forward_edges = list(filter(([]).__ne__, forward_edges))
back_edges = list(filter(([]).__ne__, back_edges))
#TODO: The lists above can be left with invalid counts of edges, they need to get put into their appropriate group
(exist_forward_edges, exist_back_edges) = new_grouping[group]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
if len(exist_forward_edges) > 0:
new_grouping[group] = (exist_forward_edges, exist_back_edges)
return new_grouping
test_connections = [ test_connections = [
#('Links House ES', 'Octoballoon WS'), #('Links House ES', 'Octoballoon WS'),
#('Links House NE', 'Lost Woods Pass SW') #('Links House NE', 'Lost Woods Pass SW')
@@ -375,6 +537,147 @@ standard_connections = [('Hyrule Castle SW', 'Central Bonk Rocks NW'),
('Central Bonk Rocks ES', 'Links House WS') ('Central Bonk Rocks ES', 'Links House WS')
] ]
parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'),
('Dig Game EC', 'Frog WC'),
('Dig Game ES', 'Frog WS')
]
parallel_links = bidict({'Lost Woods SW': 'Skull Woods SW',
'Lost Woods SC': 'Skull Woods SC',
'Lost Woods SE': 'Skull Woods SE',
'Lost Woods EN': 'Skull Woods EN',
'Lumberjack SW': 'Dark Lumberjack SW',
'Lumberjack WN': 'Dark Lumberjack WN',
'West Death Mountain EN': 'West Dark Death Mountain EN',
'West Death Mountain ES': 'West Dark Death Mountain ES',
'East Death Mountain WN': 'East Dark Death Mountain WN',
'East Death Mountain WS': 'East Dark Death Mountain WS',
'East Death Mountain EN': 'East Dark Death Mountain EN',
'Death Mountain TR Pegs WN': 'Turtle Rock WN',
'Mountain Entry NW': 'Bumper Cave NW',
'Mountain Entry SE': 'Bumper Cave SE',
'Zora Approach SE': 'Catfish SE',
'Lost Woods Pass NW': 'Skull Woods Pass NW',
'Lost Woods Pass NE': 'Skull Woods Pass NE',
'Lost Woods Pass SW': 'Skull Woods Pass SW',
'Lost Woods Pass SE': 'Skull Woods Pass SE',
'Kakariko Fortune NE': 'Dark Fortune NE',
'Kakariko Fortune SC': 'Dark Fortune SC',
'Kakariko Fortune EN': 'Dark Fortune EN',
'Kakariko Fortune ES': 'Dark Fortune ES',
'Kakariko Pond NE': 'Outcast Pond NE',
'Kakariko Pond SW': 'Outcast Pond SW',
'Kakariko Pond SE': 'Outcast Pond SE',
'Kakariko Pond WN': 'Outcast Pond WN',
'Kakariko Pond WS': 'Outcast Pond WS',
'Kakariko Pond EN': 'Outcast Pond EN',
'Kakariko Pond ES': 'Outcast Pond ES',
'Sanctuary WN': 'Dark Chapel WN',
'Sanctuary WS': 'Dark Chapel WS',
'Sanctuary EC': 'Dark Chapel EC',
'Graveyard WC': 'Dark Graveyard WC',
'Graveyard EC': 'Dark Graveyard ES',
'River Bend SW': 'Qirn Jump SW',
'River Bend SC': 'Qirn Jump SC',
'River Bend SE': 'Qirn Jump SE',
'River Bend WC': 'Qirn Jump WC',
'River Bend EN': 'Qirn Jump EN',
'River Bend EC': 'Qirn Jump EC',
'River Bend ES': 'Qirn Jump ES',
'Potion Shop WN': 'Dark Witch WN',
'Potion Shop WC': 'Dark Witch WC',
'Potion Shop WS': 'Dark Witch WS',
'Potion Shop EN': 'Dark Witch EN',
'Potion Shop EC': 'Dark Witch EC',
'Zora Warning NE': 'Catfish Approach NE',
'Zora Warning WN': 'Catfish Approach WN',
'Zora Warning WC': 'Catfish Approach WC',
'Kakariko NW': 'Village of Outcasts NW',
'Kakariko NC': 'Village of Outcasts NC',
'Kakariko NE': 'Village of Outcasts NE',
'Kakariko SE': 'Village of Outcasts SE',
'Kakariko ES': 'Village of Outcasts ES',
'Forgotten Forest NW': 'Shield Shop NW',
'Forgotten Forest NE': 'Shield Shop NE',
'Hyrule Castle SW': 'Pyramid SW',
'Hyrule Castle SE': 'Pyramid SE',
'Hyrule Castle ES': 'Pyramid ES',
'Wooden Bridge NW': 'Broken Bridge NW',
'Wooden Bridge NC': 'Broken Bridge NC',
'Wooden Bridge NE': 'Broken Bridge NE',
'Wooden Bridge SW': 'Broken Bridge SW',
'Eastern Palace SW': 'Palace of Darkness SW',
'Eastern Palace SE': 'Palace of Darkness SE',
'Blacksmith WS': 'Hammer Pegs WS',
'Sand Dunes NW': 'Dark Dunes NW',
'Sand Dunes SC': 'Dark Dunes SC',
'Sand Dunes WN': 'Dark Dunes WN',
'Maze Race ES': 'Dig Game ES',
'Kakariko Suburb NE': 'Frog NE',
'Kakariko Suburb WS': 'Frog WS',
'Kakariko Suburb ES': 'Frog ES',
'Flute Boy SW': 'Stumpy SW',
'Flute Boy SC': 'Stumpy SC',
'Flute Boy WS': 'Stumpy WS',
'Central Bonk Rocks NW': 'Dark Bonk Rocks NW',
'Central Bonk Rocks SW': 'Dark Bonk Rocks SW',
'Central Bonk Rocks EN': 'Dark Bonk Rocks EN',
'Central Bonk Rocks EC': 'Dark Bonk Rocks EC',
'Central Bonk Rocks ES': 'Dark Bonk Rocks ES',
'Links House NE': 'Big Bomb Shop NE',
'Links House SC': 'Big Bomb Shop SC',
'Links House WN': 'Big Bomb Shop WN',
'Links House WC': 'Big Bomb Shop WC',
'Links House WS': 'Big Bomb Shop WS',
'Links House ES': 'Big Bomb Shop ES',
'Stone Bridge NC': 'Hammer Bridge NC',
'Stone Bridge SC': 'Hammer Bridge SC',
'Stone Bridge WS': 'Hammer Bridge WS',
'Stone Bridge EN': 'Hammer Bridge EN',
'Stone Bridge EC': 'Hammer Bridge EC',
'Tree Line NW': 'Dark Tree Line NW',
'Tree Line SC': 'Dark Tree Line SC',
'Tree Line SE': 'Dark Tree Line SE',
'Tree Line WN': 'Dark Tree Line WN',
'Tree Line WC': 'Dark Tree Line WC',
'Eastern Nook NE': 'Palace of Darkness Nook NE',
'Cave 45 NW': 'Circle of Bushes NW',
'Cave 45 NC': 'Circle of Bushes NC',
'Cave 45 EC': 'Circle of Bushes EC',
'C Whirlpool NW': 'Dark C Whirlpool NW',
'C Whirlpool SC': 'Dark C Whirlpool SC',
'C Whirlpool WC': 'Dark C Whirlpool WC',
'C Whirlpool EN': 'Dark C Whirlpool EN',
'C Whirlpool EC': 'Dark C Whirlpool EC',
'C Whirlpool ES': 'Dark C Whirlpool ES',
'Statues NC': 'Hype Cave NC',
'Statues SC': 'Hype Cave SC',
'Statues WN': 'Hype Cave WN',
'Statues WC': 'Hype Cave WC',
'Statues WS': 'Hype Cave WS',
'Lake Hylia NW': 'Ice Lake NW',
'Lake Hylia NC': 'Ice Lake NC',
'Lake Hylia NE': 'Ice Lake NE',
'Lake Hylia WS': 'Ice Lake WS',
'Lake Hylia EC': 'Ice Lake EC',
'Lake Hylia ES': 'Ice Lake ES',
'Ice Cave SW': 'Shopping Mall SW',
'Ice Cave SE': 'Shopping Mall SE',
'Desert Pass EC': 'Swamp Nook EC',
'Desert Pass ES': 'Swamp Nook ES',
'Dam NC': 'Swamp NC',
'Dam WC': 'Swamp WC',
'Dam WS': 'Swamp WS',
'Dam EC': 'Swamp EC',
'South Pass WC': 'Dark South Pass WC',
'South Pass NC': 'Dark South Pass NC',
'South Pass ES': 'Dark South Pass ES',
'Octoballoon NW': 'Bomber Corner NW',
'Octoballoon NE': 'Bomber Corner NE',
'Octoballoon WC': 'Bomber Corner WC',
'Octoballoon WS': 'Bomber Corner WS'
})
# non shuffled overworld # non shuffled overworld
default_connections = [('Lost Woods SW', 'Lost Woods Pass NW'), default_connections = [('Lost Woods SW', 'Lost Woods Pass NW'),
('Lost Woods SC', 'Lost Woods Pass NE'), ('Lost Woods SC', 'Lost Woods Pass NE'),

View File

@@ -657,6 +657,27 @@ def extract_data_from_jp_rom(rom):
print() print()
class bidict(dict):
def __init__(self, *args, **kwargs):
super(bidict, self).__init__(*args, **kwargs)
self.inverse = {}
for key, value in self.items():
self.inverse.setdefault(value,[]).append(key)
def __setitem__(self, key, value):
if key in self:
self.inverse[self[key]].remove(key)
super(bidict, self).__setitem__(key, value)
self.inverse.setdefault(value,[]).append(key)
def __delitem__(self, key):
value = self[key]
self.inverse.setdefault(value,[]).remove(key)
if value in self.inverse and not self.inverse[value]:
del self.inverse[value]
super(bidict, self).__delitem__(key)
if __name__ == '__main__': if __name__ == '__main__':
# make_new_base2current() # make_new_base2current()
# read_entrance_data(old_rom=sys.argv[1]) # read_entrance_data(old_rom=sys.argv[1])