From 055921841268da3b21420ffd385b1397bd44b2bc Mon Sep 17 00:00:00 2001 From: Lucent Date: Tue, 10 Oct 2023 12:13:02 +0200 Subject: [PATCH] initial commit --- .gitignore | 5 + Fusion_Graph.py | 217 ++ Fusion_Items.py | 39 + GUI.py | 292 +++ LICENSE | 674 +++++++ MFOR.py | 75 + README.md | 39 + Randomizer.py | 4722 ++++++++++++++++++++++++++++++++++++++++++++ data/MFOR.bps | Bin 0 -> 15877 bytes data/NodeData.json | 1025 ++++++++++ data/SeedHash.json | 139 ++ 11 files changed, 7227 insertions(+) create mode 100644 .gitignore create mode 100644 Fusion_Graph.py create mode 100644 Fusion_Items.py create mode 100644 GUI.py create mode 100644 LICENSE create mode 100644 MFOR.py create mode 100644 README.md create mode 100644 Randomizer.py create mode 100644 data/MFOR.bps create mode 100644 data/NodeData.json create mode 100644 data/SeedHash.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee0922e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/** +*.gba +settings.json +flips/flips +flips/flips.exe diff --git a/Fusion_Graph.py b/Fusion_Graph.py new file mode 100644 index 0000000..c36018c --- /dev/null +++ b/Fusion_Graph.py @@ -0,0 +1,217 @@ +# Source Generated with Decompyle++ +# File: Fusion_Graph.pyc (Python 3.8) + +import struct +import sys + +class Game: + + def __init__(self, vanillaGame, randoSettings = (None,)): + self.graph = dict() + self.areaConnections = dict() + self.areaConnectionOffsets = dict() + self.doorConnections = dict() + self.rooms = dict() + self.requirements = dict() + self.visited = list() + self.queue = list() + self.majorItemLocations = list() + self.minorItemLocations = list() + self.itemLocations = list() + self.patcher = dict() + self.graph.clear() + self.areaConnections.clear() + self.areaConnectionOffsets.clear() + self.doorConnections.clear() + self.rooms.clear() + self.requirements.clear() + self.visited.clear() + self.queue.clear() + self.majorItemLocations.clear() + self.minorItemLocations.clear() + self.itemLocations.clear() + self.patcher.clear() + # WARNING: Decompyle incomplete + + + def set_setting(self, setting, value): + self.settings[setting] = value + + + def get_setting(self, setting): + return self.settings[setting] + + + def AddNodeToRoom(self, room, node): + nodeList = self.rooms.get(room) + nodeList.append(node) + nodeList.sort() + self.rooms.update({ + room: nodeList }) + + + def RemoveNodeFromRoom(self, room, node): + nodeList = self.rooms.get(room) + if node in nodeList: + nodeList.remove(node) + nodeList.sort() + self.rooms.update({ + room: nodeList }) + + + def ClearGraph(self): + self.graph.clear() + + + def ConnectAllNodes(self): + self.ClearGraph() + self.ConnectNodesInRooms() + self.ConnectNodesBetweenRooms() + + + def ConnectNodesInRooms(self): + for room in self.rooms: + for start in self.rooms[room]: + for end in self.rooms[room]: + if start != end: + self.add_edges(start, end) + continue + continue + continue + return None + + + def ConnectNodesBetweenRooms(self): + for connection in self.doorConnections.items(): + if len(connection) == 2: + self.add_directed_edge(connection[0], connection[1]) + continue + return None + + + def UpdateDoorConnection(self, source, destination): + self.doorConnections.update({ + source: destination }) + connectedArea = self.areaConnections.get(source) + if connectedArea != None: + self.areaConnections.update({ + source: int(destination[1:2]) }) + return self.areaConnectionOffsets.get(source) + + + def AddConnectedNodesToRoom(self, targetRoom, *nodes): + for currentNode in nodes: + if targetRoom in self.rooms: + self.rooms[targetRoom].append(currentNode) + for targetNode in self.rooms[targetRoom]: + if currentNode != targetNode: + self.add_edges(currentNode, targetNode) + continue + continue + self.rooms[targetRoom] = [ + currentNode] + continue + return None + + + def add_directed_edge(self, start, end): + if start != end: + if start in self.graph or end not in self.graph[start]: + self.graph[start].append(end) + else: + self.graph[start] = [ + end] + + + def add_edges(self, start, *nodes): + for end in nodes: + self.add_directed_edge(start, end) + self.add_directed_edge(end, start) + + + def add_to_majors(self, item): + if item not in self.itemLocations: + self.itemLocations.append(item) + if item not in self.majorItemLocations: + self.majorItemLocations.append(item) + + + def add_list_to_majors(self, locations): + for item in locations: + if item not in self.itemLocations: + self.itemLocations.append(item) + if item not in self.majorItemLocations: + self.majorItemLocations.append(item) + continue + return None + + + def add_to_minors(self, item): + if item not in self.itemLocations: + self.itemLocations.append(item) + if item not in self.minorItemLocations: + self.minorItemLocations.append(item) + + + def add_list_to_minors(self, locations): + for item in locations: + if item not in self.itemLocations: + self.itemLocations.append(item) + if item not in self.minorItemLocations: + self.minorItemLocations.append(item) + continue + return None + + + def get_requirements(self, start, end): + checkRequirement = (start, end) + return self.requirements.get(checkRequirement) + + + def get_path(self, start, end, LimitArea, path, depth = (False, None, 100)): + if path == None: + self.visited.clear() + self.queue.clear() + path = list() + path = path + [ + start] + if start not in self.graph: + return None + if None == end: + return path + # if None(path) >= depth: + if path >= depth: + return None + for point in None.graph[start]: + if point in self.itemLocations and point not in end: + continue + if point in path: + continue + if LimitArea: + for area in range(0, 7): + if 'S{}'.format(area) in start and 'S{}'.format(area) not in point: + return None + edge = (start, point) + self.queue.append(edge) + if self.queue: + edge = self.queue.pop() + if edge not in self.visited: + self.visited.append(edge) + node = edge[1] + pathReqs = self.get_requirements(start, node) + if pathReqs == None: + newpath = self.get_path(node, end, LimitArea, path, depth) + if newpath: + path = path + [ + node] + return newpath + if pathReqs == True: + newpath = self.get_path(node, end, LimitArea, path, depth) + if newpath: + path = path + [ + node] + return newpath + continue + return None + + diff --git a/Fusion_Items.py b/Fusion_Items.py new file mode 100644 index 0000000..6c2ef77 --- /dev/null +++ b/Fusion_Items.py @@ -0,0 +1,39 @@ +# Source Generated with Decompyle++ +# File: Fusion_Items.pyc (Python 3.8) + +ChargeBeam = False +WideBeam = False +PlasmaBeam = False +WaveBeam = False +IceBeam = False +MainMissiles = False +SuperMissileItem = False +IceMissileItem = False +DiffusionItem = False +Bombs = False +MainPowerBombs = False +VariaSuit = False +GravitySuit = False +MorphBall = False +HiJumpBoots = False +SpeedBooster = False +SpaceJump = False +ScrewAttack = False +BlueDoors = False +GreenDoors = False +YellowDoors = False +RedDoors = False +Missiles = False +SuperMissiles = False +IceMissiles = False +Diffusion = False +PowerBombs = False +HiJump = False +SpringBall = False +Ice = False +WallJump = False +IBJ = False +UseBombs = False +BombJump = False +WaterLowered = False +Impossible = False diff --git a/GUI.py b/GUI.py new file mode 100644 index 0000000..5ad67b0 --- /dev/null +++ b/GUI.py @@ -0,0 +1,292 @@ +# Source Generated with Decompyle++ +# File: GUI.pyc (Python 3.8) + +import PySimpleGUI as ui +import zlib +import time +import threading +import os + +ui.theme('SystemDefault') +tt_race = ' Generating a race seed will not generate a spoiler log. ' +tt_createpatch = ' Automatically creates a .bps patch after generating a randomized game, so you can easily share with others. ' +tt_difficulty = ' Higher difficulty means harder tricks. Difficulty 0 means no tricks are expected outside of vanilla strategies. ' +tt_itempool = ' Limit where important items can be placed. If checked, major upgrades will only be in Data rooms, \n at bosses, or at vanilla E-tank locations. If unchecked, any item can be anywhere within logic. ' +tt_missileswithupgrades = ' If checked, collecting any major Missile item will enable Missiles. Logic will account for this setting. ' +tt_pbswithoutbombs = ' If checked, Power Bombs can be used without having regular Bombs. Logic will account for this setting. ' +tt_damageruns = ' Allow logic to require Samus to run through damaging environments to acquire important items. \n Examples include heated rooms, electrified water, and lava. ' +tt_splitsecurity = ' If checked, each door color must be unlocked independently. \n If unchecked, unlocking higher security levels will unlock all security levels below it. \n E.G.: unlocking Level 2 (Green) doors will also unlock Level 1 (Blue) doors. ' +tt_SectorShuffle = ' Randomly shuffle the arrangement of the Sectors. ' +tt_HideItems = ' Make all items appear as ? tanks. ' +generating = False + +def fileHash(file): + checksum = 0 + return checksum +# WARNING: Decompyle incomplete + + +def rando_thread(window = None, values = None): + global failedgen, randoerror, generating, fileName, basegame, failedgen, randoerror, generating, finishGenerating + values.update({ + 'Difficulty': int(values.get('Difficulty')) }) + if values['Num']: + values.update({ + 'Num': int(values.get('Num')) }) + else: + values.update({ + 'Num': 1 }) + if values['Num'] < 1: + values.update({ + 'Num': 1 }) + values.pop(0) + failedgen = False + randoerror = False + generating = True + + from Randomizer import start_randomizer + if values['Debug']: + fileName = start_randomizer(basegame, values) + else: + # FIXME: let it explode + #try: + fileName = start_randomizer(basegame, values) + # finally: + # pass + #except SystemExit: + # failedgen = True + #except: + # print('An error occurred, no game was generated.') + # randoerror = True + + + generating = False + finishGenerating = True + + +def main_window(debug): + global fileName, finishGenerating, basegame, finishGenerating + itemPool = [ + [ + ui.Text('Charge Beam'), + ui.Radio('Shuffled', 'radioChargeBeam', default=True), + ui.Radio('Starting', 'radioChargeBeam'), + ui.Radio('Disabled', 'radioChargeBeam')], + [ + ui.Text('Wide Beam'), + ui.Radio('Shuffled', 'radioWideBeam', default=True), + ui.Radio('Starting', 'radioWideBeam'), + ui.Radio('Disabled', 'radioWideBeam')], + [ + ui.Text('Plasma Beam'), + ui.Radio('Shuffled', 'radioPlasmaBeam', default=True), + ui.Radio('Starting', 'radioPlasmaBeam'), + ui.Radio('Disabled', 'radioPlasmaBeam')], + [ + ui.Text('Wave Beam'), + ui.Radio('Shuffled', 'radioWaveBeam', default=True), + ui.Radio('Starting', 'radioWaveBeam'), + ui.Radio('Disabled', 'radioWaveBeam')], + [ + ui.Text('Ice Beam'), + ui.Radio('Shuffled', 'radioIceBeam', default=True), + ui.Radio('Starting', 'radioIceBeam'), + ui.Radio('Disabled', 'radioIceBeam')], + [ + ui.Text('Missile Data'), + ui.Radio('Shuffled', 'radioMissileData', default=True), + ui.Radio('Starting', 'radioMissileData'), + ui.Radio('Disabled', 'radioMissileData')], + [ + ui.Text('Super Missile Data'), + ui.Radio('Shuffled', 'radioSuperMissile', default=True), + ui.Radio('Starting', 'radioSuperMissile'), + ui.Radio('Disabled', 'radioSuperMissile')], + [ + ui.Text('Ice Missile Data'), + ui.Radio('Shuffled', 'radioIceMissile', default=True), + ui.Radio('Starting', 'radioIceMissile'), + ui.Radio('Disabled', 'radioIceMissile')], + [ + ui.Text('Diffusion Data'), + ui.Radio('Shuffled', 'radioDiffusion', default=True), + ui.Radio('Starting', 'radioDiffusion'), + ui.Radio('Disabled', 'radioDiffusion')], + [ + ui.Text('Bombs'), + ui.Radio('Shuffled', 'radioBombs', default=True), + ui.Radio('Starting', 'radioBombs'), + ui.Radio('Disabled', 'radioBombs')], + [ + ui.Text('Power Bomb Data'), + ui.Radio('Shuffled', 'radioPowerBombData', default=True), + ui.Radio('Starting', 'radioPowerBombData'), + ui.Radio('Disabled', 'radioPowerBombData')], + [ + ui.Text('Hi-Jump Boots'), + ui.Radio('Shuffled', 'radioHiJump', default=True), + ui.Radio('Starting', 'radioHiJump'), + ui.Radio('Disabled', 'radioHiJump')], + [ + ui.Text('Speed Booster'), + ui.Radio('Shuffled', 'radioSpeedBooster', default=True), + ui.Radio('Starting', 'radioSpeedBooster'), + ui.Radio('Disabled', 'radioSpeedBooster')], + [ + ui.Text('Space Jump'), + ui.Radio('Shuffled', 'radioSpaceJump', default=True), + ui.Radio('Starting', 'radioSpaceJump'), + ui.Radio('Disabled', 'radioSpaceJump')], + [ + ui.Text('Screw Attack'), + ui.Radio('Shuffled', 'radioScrewAttack', default=True), + ui.Radio('Starting', 'radioScrewAttack'), + ui.Radio('Disabled', 'radioScrewAttack')], + [ + ui.Text('Varia Suit'), + ui.Radio('Shuffled', 'radioVariaSuit', default=True), + ui.Radio('Starting', 'radioVariaSuit'), + ui.Radio('Disabled', 'radioVariaSuit')], + [ + ui.Text('Gravity Suit'), + ui.Radio('Shuffled', 'radioGravitySuit', default=True), + ui.Radio('Starting', 'radioGravitySuit'), + ui.Radio('Disabled', 'radioGravitySuit')], + [ + ui.Text('Morph Ball'), + ui.Radio('Shuffled', 'radioMorphBall', default=True), + ui.Radio('Starting', 'radioMorphBall'), + ui.Radio('Disabled', 'radioMorphBall')], + [ + ui.Text('Blue Doors (Level 1)'), + ui.Radio('Standard', 'radioBlueDoors', default=True), + ui.Radio('Starting', 'radioBlueDoors'), + ui.Radio('Shuffled', 'radioBlueDoors')], + [ + ui.Text('Green Doors (Level 2)'), + ui.Radio('Standard', 'radioGreenDoors', default=True), + ui.Radio('Starting', 'radioGreenDoors'), + ui.Radio('Shuffled', 'radioGreenDoors')], + [ + ui.Text('Yellow Doors (Level 3)'), + ui.Radio('Standard', 'radioYellowDoors', default=True), + ui.Radio('Starting', 'radioYellowDoors'), + ui.Radio('Shuffled', 'radioYellowDoors')], + [ + ui.Text('Red Doors (Level 4)'), + ui.Radio('Standard', 'radioRedDoors', default=True), + ui.Radio('Starting', 'radioRedDoors'), + ui.Radio('Shuffled', 'radioRedDoors')]] + settings = [ + [ + ui.Text('Difficulty'), + ui.Slider(range=(0, 5), orientation='h', tooltip=tt_difficulty, key='Difficulty')], + [ + ui.Checkbox(text='Major/minor item split', key='MajorMinor', tooltip=tt_itempool)], + [ + ui.Checkbox(text='Missile upgrades enable Missiles', key='MissilesWithoutMainData', tooltip=tt_missileswithupgrades)], + [ + ui.Checkbox(text='Enable Power Bombs without Bombs', key='PowerBombsWithoutBombs', tooltip=tt_pbswithoutbombs)], + [ + ui.Checkbox(text='Damage runs', key='DamageRuns', tooltip=tt_damageruns)], + [ + ui.Checkbox(text='Split security levels', key='SplitSecurity', tooltip=tt_splitsecurity)], + [ + ui.Checkbox(text='Sector Shuffle', key='SectorShuffle', tooltip=tt_SectorShuffle)], + [ + ui.Checkbox(text='Hide item graphics', key='HideItems', tooltip=tt_HideItems)], + [ + ui.Checkbox(text='Race seed', key='RaceSeed', tooltip=tt_race)]] + tabLayout = [ + [ + ui.TabGroup([ + [ + ui.Tab('Logic', settings)]], tab_location='topleft')]] + layout = [ + [ + ui.Text('Seed value'), + ui.Input(key='Seed')], + [ + tabLayout], + [ + ui.Text('Number of Seeds to generate:'), + ui.Input(key='Num', size=5, justification='center', enable_events=True), + ui.Push(), + ui.Checkbox(text='Create patch', key='Patch', tooltip=tt_createpatch), + ui.Button(button_text='Generate', bind_return_key=True)]] + window = ui.Window('Open Metroid Fusion Open Randomizer', layout) + fileName = str() + finishGenerating = False + oldNum = str() + (event, values) = window.read() + if event == ui.WINDOW_CLOSED: + pass + elif event == 'Num': + if len(values['Num']) > 3: + window['Num'].update(oldNum) + for x in range(4): + if x < len(values['Num']) or values['Num'][x] not in '0123456789': + window['Num'].update(oldNum) + + oldNum = values['Num'] + # continue + if event == 'Generate': + basegame = ui.popup_get_file('Choose base game', no_titlebar=True, file_types=[('GBA File', '*.gba')], history=True, history_setting_filename=os.path.join('.', 'settings.json')) + if basegame == '': + ui.popup('Please select a Metroid Fusion (U) rom.', title='No source rom selected') + if basegame != None and basegame != '': + checksum = fileHash(basegame) + # if checksum != 1819625372: + if checksum != 0: + ui.popup('Only Metroid Fusion (U) is supported.\nCheck the CRC32 value: it should be 6C75479C', title='Bad Checksum') + else: + values.update({ + 'Debug': debug }) + threading.Thread(target=rando_thread, args=[window, values], daemon=True).start() + window['Difficulty'].update(disabled=True) + window['MajorMinor'].update(disabled=True) + window['MissilesWithoutMainData'].update(disabled=True) + window['PowerBombsWithoutBombs'].update(disabled=True) + window['DamageRuns'].update(disabled=True) + window['SplitSecurity'].update(disabled=True) + window['SectorShuffle'].update(disabled=True) + window['HideItems'].update(disabled=True) + window['Seed'].update(disabled=True) + window['RaceSeed'].update(disabled=True) + window['Num'].update(disabled=True) + window['Patch'].update(disabled=True) + window['Generate'].update(disabled=True) + if generating: + ui.popup_animated(ui.DEFAULT_BASE64_LOADING_GIF, 'Generating game, please wait...', time_between_frames=20) + window.Refresh() + # continue + if finishGenerating: + ui.popup_animated(None) + if failedgen: + ui.popup('Could not generate a game with the current settings. Try changing your settings.', title='Metroid Fusion Open Randomizer') + elif randoerror: + ui.popup('An error occurred, no game was generated.', title='Error') + elif ui.Input.get(window['Num']) != '': + if int(ui.Input.get(window['Num'])) > 1: + ui.popup('Multiple games have been added to the seeds folder.', title='Success!') + else: + ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!') + else: + ui.popup('{}\nhas been added to the seeds folder.'.format(fileName), title='Success!') + window['Difficulty'].update(disabled=False) + window['MajorMinor'].update(disabled=False) + window['MissilesWithoutMainData'].update(disabled=False) + window['PowerBombsWithoutBombs'].update(disabled=False) + window['DamageRuns'].update(disabled=False) + window['SplitSecurity'].update(disabled=False) + window['SectorShuffle'].update(disabled=False) + window['HideItems'].update(disabled=False) + window['Seed'].update(disabled=False) + window['RaceSeed'].update(disabled=False) + window['Num'].update(disabled=False) + window['Patch'].update(disabled=False) + window['Generate'].update(disabled=False) + finishGenerating = False + # continue + window.close() + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/MFOR.py b/MFOR.py new file mode 100644 index 0000000..5ad8cc7 --- /dev/null +++ b/MFOR.py @@ -0,0 +1,75 @@ +# Source Generated with Decompyle++ +# File: MFOR.pyc (Python 3.8) + +import argparse +import os +parser = argparse.ArgumentParser() +parser.add_argument('-seed', help='Seed value, optional') +parser.add_argument('-race', default=False, action='store_true', help='Generate race rom (no spoiler log)') +parser.add_argument('-patch', default=False, action='store_true', help='Generate BPS patch with seed (for easy sharing)') +parser.add_argument('-diff', help='Trick difficulty level (0-5, default 0)') +parser.add_argument('-limit', default=False, action='store_true', help='Major/minor item pool') +parser.add_argument('-missiles', default=False, action='store_true', help='Missile upgrades enable the missile launcher (default off)') +parser.add_argument('-pbs', default=False, action='store_true', help='Enable Power Bombs without normal Bombs (default off)') +parser.add_argument('-damage-runs', default=False, action='store_true', help='Allow logical damage runs (default off)') +parser.add_argument('-split-security', default=False, action='store_true', help='Separated Security levels (default off)') +parser.add_argument('-sector-shuffle', default=False, action='store_true', help='Randomly shuffle the arrangement of the Sectors') +parser.add_argument('-rom', help='Base rom (Metroid Fusion (U).gba)') +parser.add_argument('-nogui', default=False, action='store_true', help='Termnial based seed generation (this)') +parser.add_argument('-num', help='Number of seeds to generate (default 1)') +parser.add_argument('-hideitems', default=False, action='store_true', help='All items use ? tank graphics') +parser.add_argument('-debug', default=False, action='store_true', help='Debugging, for my own use') +args = parser.parse_args() +if not os.path.exists(os.path.join('.', 'data')): + os.mkdir('data') +if not os.path.exists(os.path.join('.', 'seeds')): + os.mkdir('seeds') +if not os.path.exists(os.path.join('.', 'spoilers')): + os.mkdir('spoilers') +if not args.debug: + args.debug = False +if args.nogui: + settings = dict() + settings.update({ + 'Seed': None }) + if args.seed: + settings.update({ + 'Seed': args.seed }) + settings.update({ + 'Debug': args.debug }) + settings.update({ + 'Patch': args.patch }) + if not args.diff: + args.diff = 0 + if int(args.diff) <= 0: + args.diff = 0 + elif int(args.diff) >= 5: + args.diff = 5 + settings.update({ + 'Difficulty': args.diff }) + settings.update({ + 'MajorMinor': args.limit }) + settings.update({ + 'MissilesWithoutMainData': args.missiles }) + settings.update({ + 'PowerBombsWithoutBombs': args.pbs }) + settings.update({ + 'DamageRuns': args.damage_runs }) + settings.update({ + 'SplitSecurity': args.split_security }) + settings.update({ + 'SectorShuffle': args.sector_shuffle }) + settings.update({ + 'HideItems': args.hideitems }) + settings.update({ + 'RaceSeed': args.race }) + settings.update({ + 'Num': None }) + if args.num: + settings.update({ + 'Num': int(args.num) }) + from Randomizer import start_randomizer + start_randomizer(args.rom, settings) +else: + import GUI as gui + gui.main_window(args.debug) diff --git a/README.md b/README.md new file mode 100644 index 0000000..188cb7a --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# (Open) Metroid Fusion Open Randomizer + +This is the official unofficial Git repository for the Metroid Fusion Open Randomizer reverse engineering efforts, more casually referred to as MFOR or Fusion rando. + +Considering the original repository states that the software is GPL-3.0 licensed, but no source was ever released, we're endeavouring on this (potentially failing) task of making MFOR Open Again️™️ + +## Project Status + +- [x] Decent disassembly +- [x] GUI +- [ ] CRC verification +- [ ] Logic +- [ ] Patching + +## Usage + +Beware: stuff doesn't work as it should yet. Prerequisites are PySimpleGUI (and tkinter by proxy). A prerequisites file is going to be added in the future. + +Clone the repository, install prerequisites manually via pip or your favourite package manager, `python MFOR.py`. Choose your game options (hover over a given option to see a tooltip explaining it), then click Generate. A popup will ask you to open an unmodified copy of the original game. This is not provided with the randomizer for legal reasons. + +The randomizer currently works with **only** the USA/Australia version of the game. To ensure you have the correct version of the game, the CRC32 checksum should be: `6C75479C` + +## Help + +* Join the Metroid Fusion speedrunning Discord server + +## Special Thanks + +[https://github.com/zrax/pycdc](Decompyle++) has been used for the initial disassembly. [https://github.com/rocky](R. Bernstein) because uncompyle6, decompile3, xdis and python-control-flow kickstarted this project. + +[https://github.com/Kazuto88](Kazuto88) for the actual development of the randomizer. Next lines are his special thanks to the people that contributed with the patching necessary to make this a reality: + +Much thanks to the folks in the MAGConst Discord for longtime help with Metroid Fusion/general GBA modding. + +Thanks to biospark for creating the Fusion level editor MAGE, and nearly all of the documented data on Metroid Fusion that helped make this randomizer a possibility. + +Thanks to interdpth for direct code assistance, and for his longtime contributions to the GBAtroid modding scene. + +Thanks to everyone who helped with early testing, bug finding, proposed fixes, etc. diff --git a/Randomizer.py b/Randomizer.py new file mode 100644 index 0000000..2338551 --- /dev/null +++ b/Randomizer.py @@ -0,0 +1,4722 @@ +# Source Generated with Decompyle++ +# File: Randomizer.pyc (Python 3.8) + +import struct +import random +import time +import re +import sys +import argparse +import json +import os +import zlib +import math +import Fusion_Graph as Graph +from Fusion_Items import * +version = '0.11.6' + +def ceiling(num, denom): + return -(num // -denom) + + +def fileHash(file): + checksum = 0 + return checksum +# WARNING: Decompyle incomplete + + +def enable_item(graph, item): + globals()[item] = True + update_items(graph) + update_requirements(graph) + + +def disable_item(graph, item): + globals()[item] = False + update_items(graph) + update_requirements(graph) + + +def update_items(graph): + global Missiles, Missiles, SuperMissiles, IceMissiles, Diffusion, Ice, HiJump, SpringBall, WallJump, PowerBombs, PowerBombs, UseBombs, BombJump, IBJ, MissileDamage, MissileDamage, MissileDamage, MissileDamage, MissileDamage + if SeedSettings['MissilesWithoutMainData'] == True: + if not MainMissiles and SuperMissileItem and IceMissileItem: + pass + Missiles = DiffusionItem + else: + Missiles = MainMissiles + if Missiles: + pass + SuperMissiles = SuperMissileItem + if Missiles: + pass + IceMissiles = IceMissileItem + if Missiles: + pass + Diffusion = DiffusionItem + if not IceMissiles: + pass + Ice = IceBeam + if not HiJumpBoots: + pass + HiJump = SpaceJump + SpringBall = HiJumpBoots + if not SpaceJump: + pass + WallJump = WallJumpSetting + if SeedSettings['PowerBombsWithoutBombs'] == True: + if MorphBall: + pass + PowerBombs = MainPowerBombs + elif MorphBall and Bombs: + pass + PowerBombs = MainPowerBombs + if not MorphBall and Bombs: + pass + UseBombs = PowerBombs + if not MorphBall and Bombs: + pass + BombJump = SpringBall + if MorphBall and Bombs: + pass + IBJ = InfiniteBombJump + MissileDamage = 0 + if Missiles: + if MainMissiles: + MissileDamage += 10 + if IceMissiles: + MissileDamage += 10 + if SuperMissiles: + MissileDamage += 20 + if Diffusion: + MissileDamage += 5 + + +def update_requirements(graph): + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and PowerBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall or PowerBombs: + pass + if not MorphBall or PowerBombs: + pass + if MorphBall: + pass + if not Missiles: + pass + if not Missiles: + pass + if not Missiles: + pass + if not Missiles and RedDoors and HiJump and WallJump: + pass + if not RedDoors and HiJump and WallJump: + pass + if not RedDoors and HiJump and WallJump: + pass + if not RedDoors and HiJump and WallJump: + pass + if GreenDoors: + if not ((HiJump or Ice) and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if GreenDoors: + if not (HiJump and Ice and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if GreenDoors: + if not ((HiJump or Ice) and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if GreenDoors: + if not ((HiJump or Ice) and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if GreenDoors: + if not ((HiJump or Ice) and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if GreenDoors: + if not ((HiJump or Ice) and Missiles or ChargeBeam) and SpaceJump and WallJump: + pass + if PowerBombs: + pass + if not MorphBall and UseBombs: + pass + if PowerBombs: + pass + if not MorphBall and UseBombs: + pass + if PowerBombs: + pass + if not MorphBall and UseBombs: + pass + if PowerBombs: + pass + if not MorphBall and UseBombs: + pass + if not MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and PowerBombs: + pass + if not MorphBall and ScrewAttack and BombJump and HiJump and WallJump: + pass + if not MorphBall and ScrewAttack and BombJump and HiJump and WallJump: + pass + if MorphBall and ScrewAttack: + pass + if MorphBall and ScrewAttack: + pass + if MorphBall and ScrewAttack: + pass + if MorphBall and ScrewAttack: + pass + if not MorphBall and ScrewAttack and BombJump and HiJump and WallJump: + pass + if not MorphBall and ScrewAttack and BombJump and HiJump and WallJump: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Ice: + if not (Missiles and ChargeBeam or ScrewAttack) and SpaceJump and WallJump: + pass + if MorphBall and SpeedBooster: + pass + if not MorphBall: + pass + if not MorphBall: + pass + if MorphBall and SpeedBooster: + pass + if (Missiles or ChargeBeam) and MorphBall: + pass + if not Missiles and PowerBombs: + pass + if not Missiles and PowerBombs: + pass + if not Missiles: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and SpaceJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and SpaceJump and WallJump: + pass + if not MorphBall and UseBombs and SpaceJump and WallJump: + pass + if not MorphBall and UseBombs and SpaceJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and SpaceJump: + pass + if not MorphBall and SpaceJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not SpaceJump: + pass + if not MorphBall and SpaceJump: + pass + if not SpaceJump: + pass + if not MorphBall and SpaceJump: + pass + if not SpaceJump: + pass + if not MorphBall and SpaceJump: + pass + if MorphBall: + pass + if not MorphBall and ScrewAttack and SpaceJump: + pass + if not SpeedBooster: + pass + if not SpeedBooster: + pass + if Missiles and ChargeBeam: + pass + if not Missiles and ChargeBeam and PlasmaBeam and RedDoors and HiJump and WallJump: + pass + if not Missiles and SpeedBooster and PowerBombs: + pass + if not Missiles and SpeedBooster and PowerBombs: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if not (Missiles or MorphBall) and ChargeBeam and PowerBombs: + pass + if (Missiles or MorphBall) and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles: + pass + if not Missiles and ChargeBeam and PowerBombs: + pass + if not Missiles and ChargeBeam and PowerBombs: + pass + if not Missiles and ChargeBeam and PowerBombs: + pass + if not Missiles and ChargeBeam and PowerBombs: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if Missiles and ChargeBeam and PowerBombs and ScrewAttack and SpeedBooster: + pass + if SpaceJump: + pass + if SpaceJump: + pass + if not DamageRuns or Energy >= 199: + pass + if DamageRuns or Energy >= 99 or GravitySuit: + pass + if MorphBall: + pass + if MorphBall: + pass + if DamageRuns or Energy >= 99 or GravitySuit: + pass + if MorphBall: + pass + if DamageRuns or Energy >= 99 or GravitySuit: + pass + if (DamageRuns or Energy >= 99 or GravitySuit) and MorphBall: + pass + if MorphBall and ScrewAttack: + pass + if (DamageRuns or Energy >= 99 or GravitySuit) and MorphBall and ScrewAttack: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if Missiles and MorphBall: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not Missiles and MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not Missiles and MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not Missiles and MorphBall and UseBombs and HiJump and WallJump: + pass + if MorphBall and UseBombs: + if not (PowerBombs or WaveBeam) and Missiles and ChargeBeam: + pass + if MorphBall: + pass + if not Missiles: + pass + if not MorphBall and ScrewAttack and SpaceJump: + pass + if not MorphBall and ScrewAttack and SpaceJump: + pass + if MorphBall: + pass + if not Missiles: + pass + if MorphBall and SpaceJump: + pass + if MorphBall and WaveBeam and SpaceJump: + pass + if Missiles or ChargeBeam: + pass + if MorphBall: + pass + if not Missiles: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if (Missiles or ChargeBeam) and MorphBall: + pass + if not (ChargeBeam or WaveBeam or PowerBombs) and Missiles: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and PowerBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if ScrewAttack: + pass + if MorphBall: + pass + if MorphBall and UseBombs and SpringBall: + pass + if not MorphBall or UseBombs: + pass + if not MorphBall and UseBombs or SpringBall: + pass + if not MorphBall and UseBombs and WaveBeam and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if not Missiles: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not Missiles: + pass + if not Missiles: + pass + if not SpaceJump: + pass + if not ScrewAttack and SpaceJump and WallJump: + pass + if not ScrewAttack and SpaceJump and WallJump: + pass + if ScrewAttack: + pass + if not ScrewAttack and SpaceJump: + pass + if not MorphBall and UseBombs: + pass + if not MorphBall and UseBombs: + pass + if MorphBall: + if not UseBombs or SpringBall: + if (UseBombs or ScrewAttack) and SpringBall: + pass + if MorphBall: + if not UseBombs or SpringBall: + if (UseBombs or ScrewAttack or SpringBall) and ScrewAttack: + pass + if not MorphBall and UseBombs: + pass + if not MorphBall and UseBombs: + pass + if MorphBall: + if not UseBombs or SpringBall: + if (UseBombs or ScrewAttack) and SpringBall: + pass + if MorphBall: + if not UseBombs or SpringBall: + if (UseBombs or ScrewAttack or SpringBall) and ScrewAttack: + pass + if not SpeedBooster and SpaceJump: + pass + if not MorphBall and SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not MorphBall and SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not SpeedBooster and SpaceJump: + pass + if not MorphBall and SpeedBooster and SpaceJump and WallJump: + pass + if not MorphBall and SpeedBooster and SpaceJump and WallJump: + pass + if not MorphBall and Ice and SpaceJump: + pass + if not MorphBall and UseBombs and WaveBeam: + pass + if not MorphBall and Ice and UseBombs and WaveBeam and GravitySuit and HiJump and WallJump: + pass + if not MorphBall or UseBombs: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if not MorphBall and HiJump and WallJump: + pass + if MorphBall: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if Missiles: + pass + if not MorphBall: + pass + if not MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and ScrewAttack and SpeedBooster and Ice: + pass + if not MorphBall and ScrewAttack and SpeedBooster and Ice: + pass + if not MorphBall and ScrewAttack and SpeedBooster and Ice: + pass + if not MorphBall and ScrewAttack and SpeedBooster and Ice: + pass + if SpeedBooster: + pass + if MorphBall and UseBombs and BombJump: + pass + if MorphBall and UseBombs and BombJump: + pass + if MorphBall: + pass + if SuperMissiles and PowerBombs or ScrewAttack: + pass + if not MorphBall and SuperMissiles and PowerBombs: + pass + if not MorphBall and ScrewAttack and UseBombs and SuperMissiles: + pass + if SuperMissiles and PowerBombs or ScrewAttack: + pass + if not MorphBall and UseBombs: + pass + if MorphBall: + if not SpringBall or ScrewAttack: + if BombJump or PowerBombs or UseBombs: + if SuperMissiles and PowerBombs or ScrewAttack: + pass + if MorphBall: + if not UseBombs: + if (SpringBall or ScrewAttack or BombJump) and PowerBombs: + pass + if not MorphBall and UseBombs: + pass + if not MorphBall and UseBombs and HiJump and WallJump: + pass + if MorphBall: + if not UseBombs or SpringBall: + pass + if SpeedBooster and SpaceJump or IBJ: + pass + if SpeedBooster and SpaceJump or IBJ: + pass + if SpeedBooster and SpaceJump or IBJ: + pass + if VariaSuit: + pass + if Missiles and ChargeBeam and Ice or ScrewAttack: + pass + if not Ice and SpaceJump: + if Missiles and ChargeBeam or ScrewAttack: + pass + if Missiles and ChargeBeam or ScrewAttack: + pass + if Missiles and ChargeBeam or ScrewAttack: + pass + if not Missiles: + pass + if VariaSuit: + pass + if GravitySuit and WaveBeam: + pass + if GravitySuit: + pass + if GravitySuit: + pass + if GravitySuit: + pass + if ChargeBeam or Difficulty > 0: + pass + if not ChargeBeam: + pass + if not SpaceJump: + if ChargeBeam or Difficulty > 0: + pass + if not ChargeBeam: + pass + if not SpaceJump: + if ChargeBeam or Difficulty > 0: + pass + if ChargeBeam or Difficulty > 0: + pass + if not MorphBall and SuperMissiles and PowerBombs: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if MorphBall and UseBombs: + if SuperMissiles and PowerBombs or ScrewAttack: + pass + if MorphBall: + pass + if not VariaSuit and DamageRuns and Energy >= 199: + pass + if not VariaSuit and DamageRuns and Energy >= 199 and SpeedBooster and UseBombs: + pass + if MorphBall or UseBombs or ScrewAttack: + pass + if (HiJump or Ice) and SpaceJump and IBJ and MorphBall and UseBombs and Missiles and SpeedBooster: + pass + if not MorphBall or UseBombs: + pass + if MorphBall or UseBombs or ScrewAttack: + if (HiJump or Ice) and SpaceJump and IBJ and Missiles and SpeedBooster: + pass + if MorphBall or UseBombs or ScrewAttack: + pass + if GravitySuit: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam: + pass + if MorphBall: + if WaterLowered or DamageRuns: + if (Diffusion or WaveBeam) and IceBeam: + pass + if not WaterLowered: + pass + if MorphBall and Diffusion and WaveBeam: + pass + if not RedDoors and WaterLowered: + pass + if MorphBall: + if (WaterLowered or DamageRuns) and Diffusion and WaveBeam: + pass + if MorphBall: + if (WaterLowered or DamageRuns) and Diffusion and WaveBeam: + pass + if not RedDoors and WaterLowered: + pass + if MorphBall: + if (WaterLowered or DamageRuns) and Diffusion and WaveBeam: + pass + if not WaterLowered: + pass + if MorphBall: + if WaterLowered or DamageRuns: + if (Diffusion or WaveBeam) and IceBeam: + pass + if MorphBall: + if WaterLowered or DamageRuns: + if (Diffusion or WaveBeam) and IceBeam: + pass + if MorphBall: + pass + if MorphBall and UseBombs and SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall: + pass + if SpeedBooster and MorphBall: + if not (UseBombs or PowerBombs) and SpaceJump and WallJump: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if SpeedBooster and MorphBall: + if not (UseBombs or PowerBombs) and SpaceJump and WallJump: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if not Missiles: + pass + if not GravitySuit and SpeedBooster: + pass + if not GravitySuit and SpeedBooster: + pass + if not GravitySuit and SpaceJump: + pass + if not MorphBall and GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if not MorphBall and GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if MorphBall: + if (GravitySuit or ScrewAttack) and Ice: + if not BombJump or GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if GravitySuit: + pass + if GravitySuit: + pass + if MorphBall: + if (GravitySuit or ScrewAttack) and Diffusion: + if not BombJump or GravitySuit: + pass + if not GravitySuit and SpeedBooster: + pass + if MorphBall: + if (GravitySuit or ScrewAttack) and Diffusion: + if not BombJump or GravitySuit: + pass + if GravitySuit: + pass + if MorphBall and Ice: + if (UseBombs or GravitySuit) and SpringBall and GravitySuit: + pass + if not MorphBall and UseBombs: + if (HiJump or SpeedBooster) and WaterLowered and DamageRuns: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall and UseBombs and ScrewAttack: + if (HiJump or SpeedBooster) and WaterLowered and DamageRuns: + pass + if not MorphBall and UseBombs and WaterLowered: + pass + if MorphBall and SpeedBooster and WaterLowered and DamageRuns: + pass + if not MorphBall or UseBombs: + pass + if SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall and SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall: + if (UseBombs or ScrewAttack) and SpeedBooster and WaterLowered and DamageRuns: + pass + if not MorphBall and UseBombs and ScrewAttack and WaterLowered: + pass + if not MorphBall or UseBombs: + pass + if MorphBall: + if (UseBombs or ScrewAttack) and SpeedBooster and WaterLowered and DamageRuns: + pass + if WaterLowered or DamageRuns: + pass + if not WaterLowered: + pass + if not MorphBall and WaterLowered: + pass + if WaterLowered or DamageRuns: + pass + if WaterLowered or DamageRuns: + pass + if WaterLowered or DamageRuns: + pass + if MorphBall: + pass + if SpeedBooster: + pass + if MorphBall and GravitySuit: + pass + if HiJump or GravitySuit: + pass + if SpeedBooster: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and GravitySuit and ScrewAttack: + pass + if MorphBall and SpeedBooster and GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or SpringBall) and GravitySuit and GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or SpringBall) and GravitySuit and GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or GravitySuit) and ScrewAttack: + pass + if Missiles and MorphBall and UseBombs and GravitySuit: + pass + if MorphBall and SpringBall and UseBombs: + pass + if GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and SpringBall and UseBombs: + pass + if MorphBall and GravitySuit: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not HiJumpBoots: + pass + if not HiJumpBoots: + pass + if MorphBall and UseBombs and GravitySuit: + pass + if (MorphBall or UseBombs) and GravitySuit: + pass + if MorphBall and UseBombs and GravitySuit: + pass + if GravitySuit: + pass + if MorphBall: + pass + if MorphBall and Diffusion and GravitySuit: + pass + if MorphBall: + pass + if Missiles and MorphBall and GravitySuit and SpaceJump and HiJump: + pass + if GravitySuit: + pass + if Missiles and MorphBall and GravitySuit and SpaceJump and HiJump: + pass + if not Missiles and MorphBall and GravitySuit and ScrewAttack and SpaceJump: + pass + if not GravitySuit and ScrewAttack and SpaceJump: + pass + if not Missiles and MorphBall and GravitySuit and ScrewAttack and SpaceJump: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles and MorphBall and GravitySuit: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if MorphBall: + if (PowerBombs and WaveBeam or ChargeBeam) and Difficulty >= 1 and Missiles and ChargeBeam: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles: + pass + if Missiles and MorphBall: + pass + if Missiles and MorphBall: + pass + if Missiles and MorphBall: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if SpeedBooster and VariaSuit: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if SpeedBooster and VariaSuit: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if MorphBall and UseBombs and VariaSuit: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if SpeedBooster and VariaSuit: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if MorphBall and SpeedBooster and VariaSuit and PowerBombs and UseBombs: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if MorphBall and SpeedBooster and VariaSuit and YellowDoors and PowerBombs and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall and VariaSuit and PowerBombs and UseBombs: + pass + if VariaSuit: + pass + if VariaSuit: + pass + if VariaSuit: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if VariaSuit: + pass + if MorphBall and BombJump: + pass + if VariaSuit and SpaceJump: + pass + if not VariaSuit and Ice: + pass + if MorphBall and BombJump: + pass + if VariaSuit and SpaceJump: + pass + if not MorphBall and VariaSuit and Ice: + pass + if MorphBall and VariaSuit: + pass + if MorphBall and VariaSuit and SpaceJump: + pass + if not VariaSuit and Ice: + pass + if VariaSuit: + pass + if MorphBall and BombJump: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if SpeedBooster and GravitySuit: + pass + if not HiJump: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall: + if not (PowerBombs or UseBombs) and ScrewAttack and HiJump: + pass + if SpeedBooster and GravitySuit: + pass + if not HiJump: + pass + if not HiJump: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + if (PowerBombs or UseBombs) and ScrewAttack: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if MorphBall: + if (PowerBombs or UseBombs) and ScrewAttack and SpeedBooster: + pass + if MorphBall: + if (PowerBombs or UseBombs) and ScrewAttack and SpeedBooster and GravitySuit: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + if (PowerBombs or UseBombs) and ScrewAttack: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if SpeedBooster and GravitySuit: + pass + if MorphBall and UseBombs and SpeedBooster: + pass + if MorphBall and PowerBombs and UseBombs: + pass + if SpeedBooster and GravitySuit: + pass + if not SpaceJump: + pass + if not SpaceJump: + pass + if MorphBall: + pass + if not HiJump: + pass + if not MorphBall and PowerBombs and HiJump: + pass + if not HiJump: + pass + if not HiJump: + pass + if not HiJump: + pass + if not MorphBall and PowerBombs and HiJump: + pass + if not HiJump: + pass + if not HiJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not Missiles: + pass + if MorphBall and PowerBombs: + pass + if not MorphBall and PowerBombs and VariaSuit and Ice and SpaceJump: + pass + if MorphBall and PowerBombs: + pass + if not MorphBall and PowerBombs and VariaSuit and Ice and SpaceJump: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if not MorphBall and PowerBombs and VariaSuit and Ice and SpaceJump: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall: + pass + if not SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if MorphBall: + pass + if not SpaceJump: + pass + if not (HiJump or Ice) and SpaceJump: + pass + if MorphBall: + pass + if not SpaceJump: + pass + if MorphBall: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if ScrewAttack: + pass + if SpeedBooster and VariaSuit: + pass + if MorphBall: + pass + if MorphBall: + pass + if VariaSuit: + pass + if MorphBall and BombJump: + pass + if not VariaSuit and Ice: + pass + if MorphBall and BombJump: + pass + if not MorphBall and VariaSuit and Ice: + pass + if MorphBall and VariaSuit: + pass + if Missiles and MorphBall: + pass + if not Missiles and MorphBall and GravitySuit and ScrewAttack and SpaceJump: + pass + if Missiles: + pass + if not GravitySuit and ScrewAttack and SpaceJump: + pass + if Missiles and MorphBall: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if SuperMissiles and PowerBombs and ScrewAttack and SpeedBooster: + pass + if MorphBall: + pass + if MorphBall and UseBombs and SuperMissiles and PowerBombs and ScrewAttack and SpeedBooster: + pass + if not SuperMissiles and PowerBombs: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and SuperMissiles and PowerBombs: + pass + if SpeedBooster: + pass + if not SpeedBooster and ScrewAttack and VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not MorphBall and PowerBombs and VariaSuit: + pass + if not MorphBall and PowerBombs and RedDoors and VariaSuit: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if Missiles and ChargeBeam: + pass + if SpeedBooster: + pass + if MorphBall: + pass + if HiJump: + pass + if not HiJump and WallJump: + pass + if not HiJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if not VariaSuit: + pass + if SpeedBooster and RedDoors: + pass + if SpeedBooster and RedDoors: + pass + if SpeedBooster: + pass + if SpeedBooster and RedDoors: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if Missiles and MorphBall: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if Missiles: + pass + if Missiles and MorphBall: + pass + if Missiles: + pass + if not MorphBall and PowerBombs and BombJump: + pass + if MorphBall: + pass + if not MorphBall and PowerBombs and BombJump: + pass + if (Missiles or ChargeBeam) and MorphBall: + pass + if (Missiles or ChargeBeam) and MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if Missiles and ChargeBeam: + pass + if not Missiles and ChargeBeam: + pass + if not SpaceJump: + pass + if not SpaceJump: + pass + if not SpaceJump: + pass + if not SpaceJump: + pass + if not Missiles and ChargeBeam: + pass + if not GravitySuit or SpaceJump: + if (SpeedBooster or Difficulty > 0) and DamageRuns: + pass + if GravitySuit and DamageRuns: + pass + if MorphBall and GravitySuit and DamageRuns: + if not Energy >= 299 or VariaSuit: + pass + if GreenDoors and GravitySuit and DamageRuns: + pass + if GravitySuit and SpaceJump and DamageRuns: + pass + if SpaceJump and SpeedBooster: + pass + if MorphBall and GravitySuit and DamageRuns: + if not Energy >= 199 or VariaSuit: + pass + if GreenDoors and GravitySuit and DamageRuns: + pass + if MorphBall and GreenDoors and GravitySuit and DamageRuns: + if not Energy >= 299 or VariaSuit: + pass + if MorphBall and GravitySuit and DamageRuns: + if not Energy >= 199 or VariaSuit: + pass + if not Missiles and Difficulty > 4: + if (Difficulty > 3 or ChargeBeam) and ChargeBeam: + pass + if not SpaceJump and WallJump: + pass + if not Missiles and MorphBall and Diffusion and Ice: + pass + if not Missiles and MorphBall and Diffusion and Ice: + pass + if not Missiles and MorphBall and Diffusion and Ice: + pass + if MorphBall: + pass + if MorphBall: + pass + if not Missiles and MorphBall and Diffusion and Ice: + pass + if MorphBall: + pass + if MorphBall: + pass + if HiJump: + pass + if MorphBall: + if (SpaceJump or HiJump) and WallJump: + pass + if ScrewAttack: + pass + if MorphBall and BombJump and ScrewAttack: + pass + if MorphBall: + pass + if Missiles or ChargeBeam: + pass + if Missiles: + pass + if MorphBall and BombJump and SpeedBooster: + pass + if MorphBall and BombJump and SpeedBooster: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if not Missiles: + pass + if not (Missiles or ChargeBeam) and ScrewAttack and SpaceJump and WallJump: + pass + if not HiJump and WallJump: + pass + if not ScrewAttack and SpaceJump and WallJump: + pass + if not (Missiles or ChargeBeam) and ScrewAttack and HiJump and WallJump: + pass + if Missiles: + pass + if not Missiles and ChargeBeam: + pass + if not Missiles and ChargeBeam: + pass + if MorphBall: + if not (UseBombs or SpringBall) and GravitySuit: + pass + if MorphBall: + if not (UseBombs or SpringBall) and GravitySuit: + pass + if not ScrewAttack and SpaceJump and WallJump: + pass + if not SpaceJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and BombJump: + pass + if MorphBall: + pass + if not MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if not MorphBall and UseBombs: + pass + if MorphBall: + pass + if not MorphBall and UseBombs and BombJump: + pass + if not HiJump and IBJ and Ice and SpeedBooster: + pass + if MorphBall: + if not (UseBombs or WaveBeam or HiJump) and SpaceJump and GravitySuit and Ice and SpaceJump and WallJump: + pass + if not MorphBall and Ice and UseBombs and WaveBeam and GravitySuit and HiJump and IBJ: + pass + if not HiJump and SpaceJump and GravitySuit and Ice and IBJ: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if not SpaceJump and WallJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs and BombJump: + pass + if not MorphBall and SuperMissiles: + pass + if MorphBall and UseBombs: + if SuperMissiles or ScrewAttack: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if not MorphBall and UseBombs: + pass + if not MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if not MorphBall and UseBombs or SpringBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if SpeedBooster and SpaceJump or IBJ: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if MorphBall and PowerBombs and GravitySuit and DamageRuns: + if not Energy >= 399 or VariaSuit: + pass + if MorphBall and PowerBombs and GravitySuit and DamageRuns: + pass + if MorphBall and PowerBombs: + if (Missiles and ChargeBeam and Ice or ScrewAttack) and GravitySuit and DamageRuns: + if not Energy >= 199 or VariaSuit: + pass + if MorphBall and PowerBombs and GravitySuit and DamageRuns: + if not Energy >= 399 or VariaSuit: + pass + if MorphBall and BombJump: + if (Ice or SpaceJump) and VariaSuit: + pass + if MorphBall: + if (Ice or SpaceJump) and VariaSuit: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall and GravitySuit: + pass + if MorphBall: + if UseBombs and SpringBall or SpaceJump: + pass + if MorphBall: + pass + if MorphBall: + if UseBombs and SpringBall or SpaceJump: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and BombJump: + if Ice or SpaceJump: + pass + if MorphBall: + if Ice or SpaceJump: + pass + if MorphBall and BombJump: + if (Ice or SpaceJump) and GravitySuit: + pass + if MorphBall: + if (Ice or SpaceJump) and GravitySuit: + pass + if SpeedBooster: + if not MorphBall or UseBombs: + pass + if not MorphBall or UseBombs: + pass + if not MorphBall or UseBombs: + pass + if SpeedBooster: + if not MorphBall or UseBombs: + pass + if SpeedBooster: + pass + if not MorphBall and PowerBombs and HiJump and Ice: + pass + if not MorphBall and PowerBombs and HiJump and WallJump: + pass + if not MorphBall and PowerBombs and SpeedBooster and HiJump and Ice: + pass + if not MorphBall and PowerBombs and SpeedBooster and HiJump and Ice: + pass + if not SuperMissiles and PowerBombs: + pass + if not SuperMissiles and PowerBombs: + pass + if not MorphBall or UseBombs: + pass + if not MorphBall or UseBombs: + pass + if MorphBall or UseBombs or ScrewAttack: + if not (HiJump or Ice) and SpaceJump: + pass + if not MorphBall or UseBombs: + pass + if SpeedBooster and GravitySuit: + pass + if SpeedBooster: + pass + if SpeedBooster and GravitySuit: + pass + if SpeedBooster: + pass + if not (MorphBall and UseBombs or SpringBall) and IBJ: + pass + if not (MorphBall and UseBombs or SpringBall) and IBJ: + pass + if not (MorphBall and UseBombs or SpringBall) and IBJ: + pass + if not (MorphBall and UseBombs or SpringBall) and IBJ: + pass + if not MorphBall and PowerBombs and WaterLowered: + pass + if not MorphBall and PowerBombs and WaterLowered: + pass + if not MorphBall and PowerBombs and WaterLowered: + pass + if MorphBall and PowerBombs and SpeedBooster and WaterLowered and DamageRuns: + pass + if not MorphBall and PowerBombs and WaterLowered: + pass + if MorphBall and PowerBombs: + if (WaterLowered or DamageRuns) and SpaceJump and WallJump and IBJ and SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall and PowerBombs and SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall and PowerBombs and SpaceJump and WallJump and IBJ and SpeedBooster and WaterLowered and DamageRuns: + pass + if MorphBall: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if Missiles and MorphBall: + pass + if MorphBall: + pass + if not GravitySuit and SpaceJump: + pass + if not GravitySuit and SpaceJump: + pass + if MorphBall: + pass + if GravitySuit: + pass + if GravitySuit and ScrewAttack: + pass + if SpeedBooster and GravitySuit: + pass + if GravitySuit: + pass + if GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or SpringBall) and GravitySuit and GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or GravitySuit) and ScrewAttack: + pass + if Missiles and MorphBall and UseBombs and GravitySuit: + pass + if Missiles and MorphBall: + if (UseBombs or SpringBall) and GravitySuit and GravitySuit: + pass + if MorphBall and SpeedBooster and HiJump and WaterLowered and GravitySuit: + pass + if SpeedBooster and MorphBall and HiJump and GravitySuit: + pass + if MorphBall and BlueDoors: + if (WaterLowered or BombJump) and DamageRuns and SpringBall and UseBombs: + pass + if MorphBall and DamageRuns and SpringBall and UseBombs: + pass + if MorphBall and BombJump and BlueDoors: + pass + if MorphBall: + pass + if MorphBall: + if (WaterLowered or SuperMissiles) and PowerBombs and WaveBeam and ScrewAttack and DamageRuns and SuperMissiles and PowerBombs and WaveBeam and GravitySuit: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam: + if (WaterLowered or SuperMissiles) and PowerBombs and WaveBeam and ScrewAttack and DamageRuns and Energy >= 199 and SuperMissiles and PowerBombs and WaveBeam and GravitySuit: + pass + if not WaterLowered: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam and WaterLowered and DamageRuns: + pass + if MorphBall: + if (Diffusion or WaveBeam) and IceBeam: + if (WaterLowered or SuperMissiles) and PowerBombs and WaveBeam and ScrewAttack and DamageRuns and Energy >= 199 and SuperMissiles and PowerBombs and WaveBeam and GravitySuit: + pass + if not WaterLowered: + pass + if MorphBall and SpeedBooster and GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and SpeedBooster and GravitySuit: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and SpeedBooster: + pass + if MorphBall and GravitySuit: + pass + if MorphBall and SpeedBooster: + pass + if MorphBall and UseBombs and SpringBall and BombJump: + pass + if MorphBall: + pass + if SpeedBooster and GravitySuit and WaveBeam and HiJump: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall and BombJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and PowerBombs and HiJump: + pass + if not MorphBall and PowerBombs and HiJump: + pass + if MorphBall: + pass + if MorphBall: + pass + if Missiles: + if not (ChargeBeam or Difficulty > 0) and HiJump: + pass + if Missiles: + if not (ChargeBeam or Difficulty > 0) and HiJump: + pass + if Missiles: + if not (ChargeBeam or Difficulty > 0) and HiJump: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and UseBombs: + pass + if not MorphBall and PowerBombs and VariaSuit and Ice and SpaceJump: + pass + if MorphBall and UseBombs: + pass + if MorphBall and PowerBombs: + pass + if MorphBall and BombJump and Ice: + pass + if MorphBall: + if not UseBombs or SpringBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + if not UseBombs or SpringBall: + pass + if MorphBall and Missiles and ChargeBeam: + pass + if MorphBall: + pass + if not Missiles and MorphBall and PowerBombs: + pass + if not Missiles and MorphBall and UseBombs: + pass + if not Missiles and MorphBall and UseBombs: + pass + if not Missiles and MorphBall and UseBombs: + pass + if not Missiles and MorphBall and PowerBombs: + pass + if not Missiles and MorphBall and PowerBombs: + pass + if MorphBall: + pass + if MorphBall: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if SpeedBooster: + pass + if not MorphBall and VariaSuit and Ice: + pass + if MorphBall: + pass + if Missiles: + pass + if Missiles: + pass + if not MorphBall and UseBombs and SpringBall and Ice: + pass + if MorphBall: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if (SpringBall or PowerBombs) and GravitySuit: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if SpringBall or PowerBombs: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if (SpringBall or PowerBombs) and GravitySuit: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if (SpringBall or PowerBombs) and GravitySuit: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if (SpringBall or PowerBombs) and GravitySuit: + pass + if Missiles: + if (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs: + if (SpringBall or PowerBombs) and GravitySuit: + pass + if MorphBall and UseBombs and HiJump and ScrewAttack and Diffusion and WaveBeam: + pass + if MorphBall and UseBombs: + pass + if MorphBall: + pass + if HiJump: + pass + if MorphBall and UseBombs and Diffusion and WaveBeam: + pass + if WaveBeam: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if MorphBall: + pass + if not MorphBall and SpaceJump and IBJ: + pass + if not MorphBall and SpaceJump and IBJ: + pass + if MorphBall: + pass + if MorphBall and UseBombs: + pass + if MorphBall and Bombs: + pass + if MorphBall and Bombs: + pass + if SpeedBooster: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (YellowDoors and SpeedBooster or GravitySuit) and HiJump: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (SpeedBooster or GravitySuit) and HiJump and WaveBeam: + pass + if (YellowDoors and SpeedBooster or GravitySuit) and HiJump: + pass + if (YellowDoors and SpeedBooster or GravitySuit) and HiJump: + pass + graph.requirements = { + ('S0-06', 'S0-0B'): GreenDoors, + ('S0-08', 'S0-0A'): Impossible, + ('S0-08', 'S0-0C'): Impossible, + ('S0-08', 'S0-0D'): PowerBombs, + ('S0-08', 'S0-0F'): RedDoors, + ('S0-0A', 'S0-08'): Impossible, + ('S0-0A', 'S0-0C'): Impossible, + ('S0-0A', 'S0-0D'): Impossible, + ('S0-0A', 'S0-0F'): Impossible, + ('S0-0A', 'S0-11'): Impossible, + ('S0-0C', 'S0-08'): Impossible, + ('S0-0C', 'S0-0A'): Impossible, + ('S0-0C', 'S0-0D'): Impossible, + ('S0-0C', 'S0-0F'): Impossible, + ('S0-0C', 'S0-11'): Impossible, + ('S0-0D', 'S0-08'): PowerBombs, + ('S0-0D', 'S0-0A'): Impossible, + ('S0-0D', 'S0-0C'): Impossible, + ('S0-0D', 'S0-0F'): RedDoors, + ('S0-0D', 'S0-11'): PowerBombs, + ('S0-0F', 'S0-0A'): Impossible, + ('S0-0F', 'S0-0C'): Impossible, + ('S0-0F', 'S0-0D'): PowerBombs, + ('S0-11', 'S0-0A'): Impossible, + ('S0-11', 'S0-0C'): Impossible, + ('S0-11', 'S0-0D'): PowerBombs, + ('S0-11', 'S0-0F'): RedDoors, + ('S0-0E', 'S0-6C'): PowerBombs, + ('S0-6C', 'S0-0E'): SpeedBooster, + ('S0-6C', 'S0-13'): SpeedBooster, + ('S0-13', 'S0-6C'): PowerBombs, + ('S0-53', 'S0-56'): ChargeBeam, + ('S0-54', 'S0-56'): ChargeBeam, + ('S0-55', 'S0-56'): ChargeBeam, + ('S0-16', 'S0-1B'): Missiles, + ('S0-16', 'S0-41'): Missiles, + ('S0-16', 'S0-8D'): Missiles, + ('S0-16', 'S0-C1'): IBJ, + ('S0-1B', 'S0-16'): Missiles, + ('S0-1B', 'S0-C1'): IBJ, + ('S0-41', 'S0-16'): Missiles, + ('S0-41', 'S0-C1'): IBJ, + ('S0-8D', 'S0-16'): Missiles, + ('S0-8D', 'S0-C1'): IBJ, + ('S0-C1', 'S0-16'): Missiles, + ('S0-1C', 'S0-23'): MorphBall, + ('S0-23', 'S0-1C'): MorphBall, + ('S0-1E', 'S0-1F'): GreenDoors, + ('S0-1E', 'S0-9D'): IBJ, + ('S0-1E', 'S0-9E'): IBJ, + ('S0-1F', 'S0-1E'): GreenDoors, + ('S0-1F', 'S0-9D'): IBJ, + ('S0-1F', 'S0-9E'): IBJ, + ('S0-9D', 'S0-1E'): GreenDoors, + ('S0-9D', 'S0-1F'): GreenDoors, + ('S0-9D', 'S0-9E'): IBJ, + ('S0-9E', 'S0-1E'): GreenDoors, + ('S0-9E', 'S0-1F'): GreenDoors, + ('S0-9E', 'S0-9D'): IBJ, + ('S0-15', 'S0-84'): GreenDoors, + ('S0-15', 'S0-CB'): ScrewAttack, + ('S0-24', 'S0-15'): GreenDoors, + ('S0-24', 'S0-84'): GreenDoors, + ('S0-24', 'S0-CB'): ScrewAttack, + ('S0-26', 'S0-15'): GreenDoors, + ('S0-26', 'S0-84'): GreenDoors, + ('S0-26', 'S0-CB'): ScrewAttack, + ('S0-27', 'S0-15'): GreenDoors, + ('S0-27', 'S0-84'): GreenDoors, + ('S0-27', 'S0-CB'): ScrewAttack, + ('S0-84', 'S0-15'): GreenDoors, + ('S0-84', 'S0-CB'): ScrewAttack, + ('S0-CB', 'S0-15'): GreenDoors, + ('S0-CB', 'S0-24'): UseBombs, + ('S0-CB', 'S0-26'): UseBombs, + ('S0-CB', 'S0-27'): UseBombs, + ('S0-CB', 'S0-84'): GreenDoors, + ('S0-2A', 'S0-A8'): MorphBall, + ('S0-2A', 'S0-CA'): IBJ, + ('S0-A8', 'S0-2A'): MorphBall, + ('S0-A8', 'S0-CA'): IBJ, + ('S0-A8', 'S0-2B'): MorphBall, + ('S0-A8', 'S0-68'): MorphBall, + ('S0-CA', 'S0-2A'): BombJump, + ('S0-CA', 'S0-A8'): BombJump, + ('S0-CA', 'S0-2B'): BombJump, + ('S0-CA', 'S0-68'): BombJump, + ('S0-2B', 'S0-A8'): MorphBall, + ('S0-2B', 'S0-CA'): IBJ, + ('S0-68', 'S0-A8'): MorphBall, + ('S0-68', 'S0-CA'): IBJ, + ('S0-1D', 'S0-2C'): ScrewAttack, + ('S0-1D', 'S0-2D'): ScrewAttack, + ('S0-1D', 'S0-5B'): ScrewAttack, + ('S0-2C', 'S0-1D'): ScrewAttack, + ('S0-2D', 'S0-1D'): ScrewAttack, + ('S0-5B', 'S0-1D'): ScrewAttack, + ('S0-2F', 'S0-2E'): IBJ, + ('S0-30', 'S0-4A'): Difficulty >= 2, + ('S0-4A', 'S0-30'): SpeedBooster, + ('S0-4A', 'S0-A6'): SpeedBooster, + ('S0-A6', 'S0-4A'): Difficulty >= 2, + ('S0-34', 'S0-35'): BlueDoors, + ('S0-44', 'S0-35'): BlueDoors, + ('S0-36', 'S0-37'): GreenDoors, + ('S0-37', 'S0-36'): BlueDoors, + ('S0-46', 'S0-36'): BlueDoors, + ('S0-46', 'S0-37'): GreenDoors, + ('S0-48', 'S0-38'): GreenDoors, + ('S0-3A', 'S0-3B'): BlueDoors, + ('S0-43', 'S0-3B'): BlueDoors, + ('S0-3C', 'S0-3D'): GreenDoors, + ('S0-3D', 'S0-3C'): BlueDoors, + ('S0-45', 'S0-3C'): BlueDoors, + ('S0-45', 'S0-3D'): GreenDoors, + ('S0-47', 'S0-3E'): GreenDoors, + ('S0-40', 'S0-69'): BombJump, + ('S0-69', 'S0-40'): Impossible, + ('S0-4E', 'S0-4F'): Impossible, + ('S0-4F', 'S0-4E'): ScrewAttack, + ('S0-4F', 'S0-65'): ScrewAttack, + ('S0-65', 'S0-4F'): Impossible, + ('S0-51', 'S0-52'): Impossible, + ('S0-52', 'S0-51'): Impossible, + ('S0-3F', 'S0-62'): Impossible, + ('S0-62', 'S0-3F'): Impossible, + ('S0-67', 'S0-6A'): Impossible, + ('S0-67', 'S0-C3'): Impossible, + ('S0-6A', 'S0-67'): Impossible, + ('S0-6A', 'S0-C3'): MorphBall, + ('S0-C3', 'S0-67'): Impossible, + ('S0-C3', 'S0-6A'): Impossible, + ('S0-6B', 'S0-C4'): Impossible, + ('S0-C4', 'S0-6B'): ChargeBeam, + ('S0-6D', 'S0-6F'): RedDoors, + ('S0-6E', 'S0-6D'): RedDoors, + ('S0-6E', 'S0-6F'): PowerBombs, + ('S0-6F', 'S0-6D'): RedDoors, + ('S0-6F', 'S0-6E'): PowerBombs, + ('S0-70', 'S0-7D'): IBJ, + ('S0-7D', 'S0-70'): UseBombs, + ('S0-7D', 'S0-71'): UseBombs, + ('S0-7D', 'S0-7C'): UseBombs, + ('S0-7D', 'S0-82'): UseBombs, + ('S0-71', 'S0-7D'): IBJ, + ('S0-7C', 'S0-7D'): IBJ, + ('S0-82', 'S0-7D'): IBJ, + ('S0-77', 'S0-76'): WaveBeam, + ('S0-7E', 'S0-7F'): UseBombs, + ('S0-7F', 'S0-7E'): UseBombs, + ('S0-86', 'S0-87'): IBJ, + ('S0-87', 'S0-86'): IBJ, + ('S0-87', 'S0-88'): UseBombs, + ('S0-87', 'S0-89'): UseBombs, + ('S0-87', 'S0-8A'): UseBombs, + ('S0-88', 'S0-86'): IBJ, + ('S0-88', 'S0-87'): IBJ, + ('S0-89', 'S0-86'): IBJ, + ('S0-89', 'S0-87'): IBJ, + ('S0-8A', 'S0-86'): IBJ, + ('S0-8A', 'S0-87'): IBJ, + ('S0-8F', 'S0-90'): RedDoors, + ('S0-90', 'S0-8F'): WallJump, + ('S0-93', 'S0-94'): RedDoors, + ('S0-94', 'S0-93'): RedDoors, + ('S0-95', 'S0-96'): RedDoors, + ('S0-96', 'S0-95'): RedDoors, + ('S0-9A', 'S0-99'): RedDoors, + ('S0-9B', 'S0-9C'): MorphBall, + ('S0-9C', 'S0-9B'): MorphBall, + ('S0-9F', 'S0-A0'): Impossible, + ('S0-9F', 'S0-A1'): Impossible, + ('S0-9F', 'S0-A2'): WaveBeam, + ('S0-9F', 'S0-A3'): Impossible, + ('S0-A0', 'S0-9F'): GreenDoors, + ('S0-A0', 'S0-A1'): Impossible, + ('S0-A0', 'S0-A2'): WaveBeam, + ('S0-A0', 'S0-A3'): Impossible, + ('S0-A1', 'S0-9F'): GreenDoors, + ('S0-A1', 'S0-A0'): GreenDoors, + ('S0-A1', 'S0-A2'): WaveBeam, + ('S0-A1', 'S0-A3'): Impossible, + ('S0-A2', 'S0-9F'): GreenDoors, + ('S0-A2', 'S0-A0'): Impossible, + ('S0-A2', 'S0-A1'): Impossible, + ('S0-A2', 'S0-A3'): Impossible, + ('S0-A3', 'S0-9F'): GreenDoors, + ('S0-A3', 'S0-A0'): GreenDoors, + ('S0-A3', 'S0-A1'): GreenDoors, + ('S0-A3', 'S0-A2'): WaveBeam, + ('S0-AC', 'S0-AF'): Missiles, + ('S0-AF', 'S0-AC'): Missiles, + ('S0-AF', 'S0-AD'): Missiles, + ('S0-AF', 'S0-AE'): Missiles, + ('S0-AD', 'S0-AF'): Missiles, + ('S0-AE', 'S0-AF'): Missiles, + ('S0-B1', 'S0-B0'): GreenDoors, + ('S0-64', 'S0-B3'): GreenDoors, + ('S0-B2', 'S0-B3'): GreenDoors, + ('S0-B4', 'S0-B5'): Impossible, + ('S0-B4', 'S0-B6'): Impossible, + ('S0-B4', 'S0-B7'): Impossible, + ('S0-B5', 'S0-B4'): Impossible, + ('S0-B5', 'S0-B6'): Impossible, + ('S0-B5', 'S0-B7'): Impossible, + ('S0-B6', 'S0-B4'): Impossible, + ('S0-B6', 'S0-B5'): Impossible, + ('S0-B6', 'S0-B7'): RedDoors, + ('S0-B7', 'S0-B4'): Impossible, + ('S0-B7', 'S0-B5'): Impossible, + ('S0-B7', 'S0-B6'): RedDoors, + ('S0-B8', 'S0-B9'): RedDoors, + ('S0-B8', 'S0-BA'): Impossible, + ('S0-B9', 'S0-B8'): RedDoors, + ('S0-B9', 'S0-BA'): Impossible, + ('S0-BA', 'S0-B8'): Impossible, + ('S0-BA', 'S0-B9'): Impossible, + ('S0-BD', 'S0-BE'): Impossible, + ('S0-BE', 'S0-BD'): SpaceJump, + ('S0-BB', 'S0-BC'): RedDoors, + ('S0-BC', 'S0-BB'): RedDoors, + ('S0-C5', 'S0-C6'): Impossible, + ('S0-C6', 'S0-C5'): Impossible, + ('S0-C6', 'S0-C7'): Impossible, + ('S0-C7', 'S0-C5'): RedDoors, + ('S0-C7', 'S0-C6'): Impossible, + ('S0-92', 'S0-CC'): PlasmaBeam, + ('S0-CC', 'S0-92'): IBJ, + ('S1-01', 'S1-4C'): GreenDoors, + ('S1-4C', 'S1-01'): BlueDoors, + ('S1-4C', 'S1-02'): GreenDoors, + ('S1-4C', 'S1-03'): GreenDoors, + ('S1-02', 'S1-01'): BlueDoors, + ('S1-02', 'S1-4C'): GreenDoors, + ('S1-03', 'S1-01'): BlueDoors, + ('S1-03', 'S1-4C'): GreenDoors, + ('S1-09', 'S1-0A'): ScrewAttack, + ('S1-0A', 'S1-09'): ScrewAttack, + ('S1-0B', 'S1-0C'): Difficulty >= 3, + ('S1-0C', 'S1-0B'): Difficulty >= 3, + ('S1-17', 'S1-58'): ScrewAttack, + ('S1-58', 'S1-17'): Difficulty >= 3, + ('S1-18', 'S1-5C'): MorphBall, + ('S1-5C', 'S1-18'): MorphBall, + ('S1-5C', 'S1-54'): MorphBall, + ('S1-54', 'S1-5C'): MorphBall, + ('S1-1D', 'S1-1E'): ScrewAttack, + ('S1-1E', 'S1-1D'): ScrewAttack, + ('S1-16', 'S1-59'): WaveBeam, + ('S1-20', 'S1-21'): ScrewAttack, + ('S1-20', 'S1-4B'): ScrewAttack, + ('S1-21', 'S1-20'): Difficulty >= 4, + ('S1-21', 'S1-4B'): Difficulty >= 4, + ('S1-4B', 'S1-20'): Difficulty >= 4, + ('S1-4B', 'S1-21'): Difficulty >= 4, + ('S1-22', 'S1-23'): ScrewAttack, + ('S1-23', 'S1-22'): ScrewAttack, + ('S1-23', 'S1-5E'): ScrewAttack, + ('S1-5E', 'S1-23'): ScrewAttack, + ('S1-24', 'S1-25'): GravitySuit, + ('S1-25', 'S1-24'): GreenDoors, + ('S1-26', 'S1-27'): ScrewAttack, + ('S1-27', 'S1-26'): ScrewAttack, + ('S1-2A', 'S1-2B'): GreenDoors, + ('S1-2A', 'S1-6A'): ScrewAttack, + ('S1-2B', 'S1-2A'): BlueDoors, + ('S1-2B', 'S1-6A'): ScrewAttack, + ('S1-6A', 'S1-2A'): BlueDoors, + ('S1-6A', 'S1-2B'): GreenDoors, + ('S1-2D', 'S1-2E'): UseBombs, + ('S1-2D', 'S1-2F'): UseBombs, + ('S1-2D', 'S1-5F'): UseBombs, + ('S1-2D', 'S1-6E'): UseBombs, + ('S1-2E', 'S1-2D'): UseBombs, + ('S1-2E', 'S1-2F'): MorphBall, + ('S1-2E', 'S1-5F'): MorphBall, + ('S1-2E', 'S1-6E'): MorphBall, + ('S1-2F', 'S1-2D'): IBJ, + ('S1-2F', 'S1-2E'): IBJ, + ('S1-5F', 'S1-2D'): IBJ, + ('S1-5F', 'S1-2E'): IBJ, + ('S1-6E', 'S1-2D'): IBJ, + ('S1-6E', 'S1-2E'): IBJ, + ('S1-30', 'S1-31'): ScrewAttack, + ('S1-31', 'S1-30'): UseBombs, + ('S1-38', 'S1-39'): ChargeBeam, + ('S1-3B', 'S1-29'): WaveBeam, + ('S1-3E', 'S1-3F'): WallJump, + ('S1-3F', 'S1-3E'): WallJump, + ('S1-43', 'S1-46'): Impossible, + ('S1-43', 'S1-47'): Impossible, + ('S1-46', 'S1-43'): Impossible, + ('S1-46', 'S1-47'): WaveBeam, + ('S1-46', 'S1-44'): Impossible, + ('S1-46', 'S1-45'): Impossible, + ('S1-47', 'S1-43'): Impossible, + ('S1-47', 'S1-44'): Impossible, + ('S1-47', 'S1-45'): Impossible, + ('S1-44', 'S1-46'): Impossible, + ('S1-44', 'S1-47'): Impossible, + ('S1-45', 'S1-46'): Impossible, + ('S1-45', 'S1-47'): Impossible, + ('S1-4A', 'S1-6C'): MorphBall, + ('S1-6C', 'S1-4A'): UseBombs, + ('S1-49', 'S1-48'): ChargeBeam, + ('S1-07', 'S1-08'): ScrewAttack, + ('S1-08', 'S1-07'): ScrewAttack, + ('S1-19', 'S1-4D'): MorphBall, + ('S1-19', 'S1-53'): MorphBall, + ('S1-19', 'S1-64'): UseBombs, + ('S1-4D', 'S1-19'): Impossible, + ('S1-4D', 'S1-53'): ChargeBeam, + ('S1-4D', 'S1-64'): UseBombs, + ('S1-53', 'S1-19'): Impossible, + ('S1-53', 'S1-64'): UseBombs, + ('S1-64', 'S1-19'): Impossible, + ('S1-64', 'S1-4D'): UseBombs, + ('S1-64', 'S1-53'): UseBombs, + ('S1-4F', 'S1-50'): MorphBall, + ('S1-50', 'S1-4F'): MorphBall, + ('S1-6F', 'S1-70'): ScrewAttack, + ('S1-70', 'S1-6F'): HiJump, + ('S2-01', 'S2-03'): PowerBombs, + ('S2-01', 'S2-04'): BlueDoors, + ('S2-01', 'S2-20'): UseBombs, + ('S2-03', 'S2-01'): PowerBombs, + ('S2-03', 'S2-04'): BlueDoors, + ('S2-03', 'S2-20'): PowerBombs, + ('S2-03', 'S2-02'): PowerBombs, + ('S2-03', 'S2-05'): PowerBombs, + ('S2-03', 'S2-0F'): PowerBombs, + ('S2-04', 'S2-03'): PowerBombs, + ('S2-04', 'S2-20'): UseBombs, + ('S2-20', 'S2-01'): UseBombs, + ('S2-20', 'S2-03'): PowerBombs, + ('S2-20', 'S2-04'): BlueDoors, + ('S2-20', 'S2-02'): UseBombs, + ('S2-20', 'S2-05'): UseBombs, + ('S2-20', 'S2-0F'): UseBombs, + ('S2-02', 'S2-03'): PowerBombs, + ('S2-02', 'S2-04'): BlueDoors, + ('S2-02', 'S2-20'): UseBombs, + ('S2-05', 'S2-03'): PowerBombs, + ('S2-05', 'S2-04'): BlueDoors, + ('S2-05', 'S2-20'): UseBombs, + ('S2-0F', 'S2-03'): PowerBombs, + ('S2-0F', 'S2-04'): BlueDoors, + ('S2-0F', 'S2-20'): UseBombs, + ('S2-0D', 'S2-3A'): BlueDoors, + ('S2-0D', 'S2-80'): ScrewAttack, + ('S2-3A', 'S2-80'): ScrewAttack, + ('S2-80', 'S2-0D'): ScrewAttack, + ('S2-80', 'S2-3A'): BlueDoors, + ('S2-80', 'S2-3C'): ScrewAttack, + ('S2-3C', 'S2-3A'): BlueDoors, + ('S2-3C', 'S2-80'): ScrewAttack, + ('S2-14', 'S2-15'): UseBombs, + ('S2-15', 'S2-14'): ScrewAttack, + ('S2-16', 'S2-17'): ScrewAttack, + ('S2-17', 'S2-16'): ScrewAttack, + ('S2-18', 'S2-1B'): IBJ, + ('S2-1B', 'S2-18'): IBJ, + ('S2-26', 'S2-27'): Impossible, + ('S2-26', 'S2-5D'): Impossible, + ('S2-27', 'S2-26'): Impossible, + ('S2-5D', 'S2-26'): Impossible, + ('S2-5D', 'S2-27'): ChargeBeam, + ('S2-29', 'S2-46'): PowerBombs, + ('S2-29', 'S2-6C'): PowerBombs, + ('S2-46', 'S2-29'): PowerBombs, + ('S2-46', 'S2-2A'): PowerBombs, + ('S2-46', 'S2-58'): PowerBombs, + ('S2-6C', 'S2-29'): PowerBombs, + ('S2-6C', 'S2-2A'): PowerBombs, + ('S2-6C', 'S2-58'): PowerBombs, + ('S2-2A', 'S2-46'): PowerBombs, + ('S2-2A', 'S2-6C'): PowerBombs, + ('S2-58', 'S2-46'): PowerBombs, + ('S2-58', 'S2-6C'): PowerBombs, + ('S2-2E', 'S2-30'): ChargeBeam, + ('S2-2F', 'S2-30'): ChargeBeam, + ('S2-34', 'S2-35'): MorphBall, + ('S2-35', 'S2-34'): MorphBall, + ('S2-37', 'S2-87'): MorphBall, + ('S2-87', 'S2-37'): Impossible, + ('S2-3B', 'S2-3D'): IBJ, + ('S2-3B', 'S2-83'): IBJ, + ('S2-3D', 'S2-3B'): BlueDoors, + ('S2-3D', 'S2-83'): IBJ, + ('S2-83', 'S2-3B'): BlueDoors, + ('S2-83', 'S2-3D'): IBJ, + ('S2-3E', 'S2-3F'): MorphBall, + ('S2-3F', 'S2-3E'): MorphBall, + ('S2-10', 'S2-12'): ScrewAttack, + ('S2-10', 'S2-45'): BlueDoors, + ('S2-10', 'S2-54'): ScrewAttack, + ('S2-12', 'S2-10'): ScrewAttack, + ('S2-12', 'S2-45'): BlueDoors, + ('S2-45', 'S2-12'): ScrewAttack, + ('S2-45', 'S2-54'): ScrewAttack, + ('S2-54', 'S2-10'): ScrewAttack, + ('S2-54', 'S2-45'): BlueDoors, + ('S2-2B', 'S2-47'): Impossible, + ('S2-2B', 'S2-48'): Impossible, + ('S2-2B', 'S2-75'): MorphBall, + ('S2-47', 'S2-2B'): Impossible, + ('S2-47', 'S2-75'): Impossible, + ('S2-47', 'S2-2C'): Impossible, + ('S2-47', 'S2-2D'): Impossible, + ('S2-47', 'S2-78'): Impossible, + ('S2-48', 'S2-2B'): Impossible, + ('S2-48', 'S2-75'): Impossible, + ('S2-48', 'S2-2C'): Impossible, + ('S2-48', 'S2-2D'): Impossible, + ('S2-48', 'S2-78'): Impossible, + ('S2-75', 'S2-2B'): MorphBall, + ('S2-75', 'S2-47'): Impossible, + ('S2-75', 'S2-48'): Impossible, + ('S2-75', 'S2-2C'): MorphBall, + ('S2-75', 'S2-2D'): MorphBall, + ('S2-75', 'S2-78'): MorphBall, + ('S2-2C', 'S2-47'): Impossible, + ('S2-2C', 'S2-48'): Impossible, + ('S2-2C', 'S2-75'): MorphBall, + ('S2-2D', 'S2-47'): Impossible, + ('S2-2D', 'S2-48'): Impossible, + ('S2-2D', 'S2-75'): MorphBall, + ('S2-78', 'S2-47'): Impossible, + ('S2-78', 'S2-48'): Impossible, + ('S2-78', 'S2-75'): MorphBall, + ('S2-49', 'S2-7D'): ScrewAttack, + ('S2-7D', 'S2-49'): ScrewAttack, + ('S2-4D', 'S2-7A'): MorphBall, + ('S2-50', 'S2-4D'): IBJ, + ('S2-50', 'S2-7A'): IBJ, + ('S2-50', 'S2-4E'): IBJ, + ('S2-50', 'S2-4F'): IBJ, + ('S2-50', 'S2-79'): IBJ, + ('S2-51', 'S2-4D'): IBJ, + ('S2-51', 'S2-7A'): IBJ, + ('S2-51', 'S2-4E'): IBJ, + ('S2-51', 'S2-4F'): IBJ, + ('S2-51', 'S2-79'): IBJ, + ('S2-7A', 'S2-4D'): MorphBall, + ('S2-7A', 'S2-50'): MorphBall, + ('S2-7A', 'S2-51'): MorphBall, + ('S2-7A', 'S2-4E'): MorphBall, + ('S2-7A', 'S2-4F'): MorphBall, + ('S2-7A', 'S2-79'): IBJ, + ('S2-4E', 'S2-7A'): MorphBall, + ('S2-4F', 'S2-7A'): MorphBall, + ('S2-79', 'S2-7A'): IBJ, + ('S2-53', 'S2-91'): MorphBall, + ('S2-91', 'S2-53'): IBJ, + ('S2-38', 'S2-5F'): GravitySuit, + ('S2-5F', 'S2-38'): IBJ, + ('S2-64', 'S2-65'): ScrewAttack, + ('S2-65', 'S2-64'): Impossible, + ('S2-67', 'S2-66'): Impossible, + ('S2-1E', 'S2-1F'): IBJ, + ('S2-1E', 'S2-71'): IBJ, + ('S2-1F', 'S2-1E'): UseBombs, + ('S2-1F', 'S2-68'): UseBombs, + ('S2-1F', 'S2-69'): UseBombs, + ('S2-1F', 'S2-6A'): UseBombs, + ('S2-1F', 'S2-6B'): UseBombs, + ('S2-1F', 'S2-70'): UseBombs, + ('S2-1F', 'S2-71'): IBJ, + ('S2-68', 'S2-1F'): IBJ, + ('S2-68', 'S2-71'): IBJ, + ('S2-69', 'S2-1F'): IBJ, + ('S2-69', 'S2-71'): IBJ, + ('S2-6A', 'S2-1F'): IBJ, + ('S2-6A', 'S2-71'): IBJ, + ('S2-6B', 'S2-1F'): IBJ, + ('S2-6B', 'S2-71'): IBJ, + ('S2-70', 'S2-1F'): IBJ, + ('S2-70', 'S2-71'): IBJ, + ('S2-71', 'S2-1E'): MorphBall, + ('S2-71', 'S2-1F'): UseBombs, + ('S2-71', 'S2-68'): MorphBall, + ('S2-71', 'S2-69'): MorphBall, + ('S2-71', 'S2-6A'): MorphBall, + ('S2-71', 'S2-6B'): MorphBall, + ('S2-71', 'S2-70'): MorphBall, + ('S2-6D', 'S2-73'): IBJ, + ('S2-6E', 'S2-6D'): IBJ, + ('S2-6E', 'S2-73'): IBJ, + ('S2-73', 'S2-6D'): IBJ, + ('S2-7B', 'S2-7C'): Impossible, + ('S2-88', 'S2-89'): UseBombs, + ('S2-89', 'S2-88'): UseBombs, + ('S2-36', 'S2-8A'): WaveBeam, + ('S2-36', 'S2-8B'): Missiles, + ('S2-8A', 'S2-36'): Missiles, + ('S2-8B', 'S2-36'): Missiles, + ('S2-8B', 'S2-8A'): WaveBeam, + ('S2-52', 'S2-8E'): WaveBeam, + ('S2-8D', 'S2-8E'): WaveBeam, + ('S2-8F', 'S2-90'): UseBombs, + ('S2-90', 'S2-8F'): UseBombs, + ('S3-01', 'S3-04'): SpaceJump, + ('S3-04', 'S3-01'): MorphBall, + ('S3-04', 'S3-02'): MorphBall, + ('S3-04', 'S3-03'): MorphBall, + ('S3-04', 'S3-35'): MorphBall, + ('S3-02', 'S3-04'): SpaceJump, + ('S3-03', 'S3-04'): SpaceJump, + ('S3-35', 'S3-04'): SpaceJump, + ('S3-08', 'S3-09'): GreenDoors, + ('S3-08', 'S3-4C'): SpeedBooster, + ('S3-09', 'S3-08'): SpeedBooster, + ('S3-09', 'S3-4C'): SpeedBooster, + ('S3-4C', 'S3-08'): Impossible, + ('S3-4C', 'S3-09'): Impossible, + ('S3-0A', 'S3-4D'): Impossible, + ('S3-4D', 'S3-0A'): GreenDoors, + ('S3-0B', 'S3-0C'): GreenDoors, + ('S3-3D', 'S3-0C'): GreenDoors, + ('S3-0D', 'S3-0E'): GreenDoors, + ('S3-0D', 'S3-0F'): ScrewAttack, + ('S3-0D', 'S3-3C'): PowerBombs, + ('S3-0E', 'S3-0D'): GreenDoors, + ('S3-0E', 'S3-0F'): MorphBall, + ('S3-0E', 'S3-3C'): ScrewAttack, + ('S3-0F', 'S3-0D'): GreenDoors, + ('S3-0F', 'S3-0E'): GreenDoors, + ('S3-0F', 'S3-3C'): ScrewAttack, + ('S3-3C', 'S3-0D'): Impossible, + ('S3-3C', 'S3-0E'): Impossible, + ('S3-3C', 'S3-0F'): Impossible, + ('S3-11', 'S3-12'): IBJ, + ('S3-12', 'S3-11'): ScrewAttack, + ('S3-13', 'S3-53'): ScrewAttack, + ('S3-13', 'S3-54'): ScrewAttack, + ('S3-53', 'S3-13'): ScrewAttack, + ('S3-53', 'S3-54'): ScrewAttack, + ('S3-53', 'S3-26'): ScrewAttack, + ('S3-54', 'S3-13'): ScrewAttack, + ('S3-54', 'S3-53'): ScrewAttack, + ('S3-54', 'S3-26'): ScrewAttack, + ('S3-26', 'S3-53'): ScrewAttack, + ('S3-26', 'S3-54'): ScrewAttack, + ('S3-14', 'S3-15'): GreenDoors, + ('S3-14', 'S3-46'): GreenDoors, + ('S3-15', 'S3-46'): GreenDoors, + ('S3-46', 'S3-15'): GreenDoors, + ('S3-39', 'S3-15'): GreenDoors, + ('S3-39', 'S3-46'): GreenDoors, + ('S3-16', 'S3-17'): VariaSuit, + ('S3-17', 'S3-16'): GreenDoors, + ('S3-18', 'S3-19'): VariaSuit, + ('S3-19', 'S3-18'): VariaSuit, + ('S3-1A', 'S3-1B'): VariaSuit, + ('S3-1B', 'S3-1A'): VariaSuit, + ('S3-1C', 'S3-1D'): IBJ, + ('S3-1E', 'S3-1F'): VariaSuit, + ('S3-1F', 'S3-1E'): VariaSuit, + ('S3-20', 'S3-21'): VariaSuit, + ('S3-21', 'S3-20'): VariaSuit, + ('S3-22', 'S3-31'): ChargeBeam, + ('S3-24', 'S3-2B'): GreenDoors, + ('S3-28', 'S3-4B'): WaveBeam, + ('S3-28', 'S3-4E'): ScrewAttack, + ('S3-4B', 'S3-28'): VariaSuit, + ('S3-4B', 'S3-4E'): ScrewAttack, + ('S3-4E', 'S3-28'): ScrewAttack, + ('S3-4E', 'S3-4B'): ScrewAttack, + ('S3-2D', 'S3-10'): GreenDoors, + ('S3-40', 'S3-10'): GreenDoors, + ('S3-25', 'S3-2B'): GreenDoors, + ('S3-25', 'S3-2E'): Difficulty > 0, + ('S3-2B', 'S3-25'): GreenDoors, + ('S3-2B', 'S3-2E'): Difficulty > 0, + ('S3-2E', 'S3-25'): GreenDoors, + ('S3-2E', 'S3-2B'): GreenDoors, + ('S3-2F', 'S3-30'): ScrewAttack, + ('S3-2F', 'S3-3F'): ScrewAttack, + ('S3-30', 'S3-2F'): GreenDoors, + ('S3-30', 'S3-3F'): UseBombs, + ('S3-3F', 'S3-2F'): Impossible, + ('S3-3F', 'S3-30'): Impossible, + ('S3-36', 'S3-37'): SpeedBooster, + ('S3-37', 'S3-36'): ScrewAttack, + ('S3-3A', 'S3-3B'): Impossible, + ('S3-3A', 'S3-3E'): Impossible, + ('S3-3B', 'S3-3A'): SpeedBooster, + ('S3-3E', 'S3-3A'): SpeedBooster, + ('S3-3E', 'S3-3B'): Impossible, + ('S3-27', 'S3-47'): GreenDoors, + ('S3-27', 'S3-4A'): Difficulty >= 4, + ('S3-47', 'S3-27'): ScrewAttack, + ('S3-47', 'S3-4A'): Difficulty >= 4, + ('S3-4A', 'S3-47'): GreenDoors, + ('S3-4F', 'S3-50'): SpeedBooster, + ('S3-50', 'S3-4F'): Impossible, + ('S4-08', 'S4-09'): RedDoors, + ('S4-08', 'S4-1B'): RedDoors, + ('S4-08', 'S4-54'): DamageRuns, + ('S4-09', 'S4-08'): IceBeam, + ('S4-09', 'S4-1B'): DamageRuns, + ('S4-09', 'S4-54'): IceBeam, + ('S4-1B', 'S4-08'): IceBeam, + ('S4-1B', 'S4-09'): DamageRuns, + ('S4-1B', 'S4-54'): IceBeam, + ('S4-54', 'S4-08'): DamageRuns, + ('S4-54', 'S4-09'): RedDoors, + ('S4-54', 'S4-1B'): RedDoors, + ('S4-0D', 'S4-0E'): UseBombs, + ('S4-0D', 'S4-12'): GravitySuit, + ('S4-0D', 'S4-41'): UseBombs, + ('S4-0E', 'S4-0D'): IBJ, + ('S4-0E', 'S4-12'): GravitySuit, + ('S4-12', 'S4-0D'): GravitySuit, + ('S4-12', 'S4-0E'): GravitySuit, + ('S4-12', 'S4-41'): GravitySuit, + ('S4-41', 'S4-0D'): IBJ, + ('S4-41', 'S4-12'): GravitySuit, + ('S4-14', 'S4-15'): MorphBall, + ('S4-15', 'S4-14'): MorphBall, + ('S4-15', 'S4-4A'): MorphBall, + ('S4-4A', 'S4-15'): MorphBall, + ('S4-17', 'S4-18'): SpeedBooster, + ('S4-18', 'S4-17'): Impossible, + ('S4-16', 'S4-3F'): Impossible, + ('S4-16', 'S4-40'): Impossible, + ('S4-3F', 'S4-16'): Impossible, + ('S4-3F', 'S4-40'): ChargeBeam, + ('S4-40', 'S4-16'): Impossible, + ('S4-40', 'S4-3F'): GravitySuit, + ('S4-58', 'S4-5F'): SpaceJump, + ('S4-59', 'S4-5F'): SpaceJump, + ('S4-1E', 'S4-1D'): Impossible, + ('S4-75', 'S4-1D'): Impossible, + ('S4-1F', 'S4-4F'): MorphBall, + ('S4-21', 'S4-1F'): IBJ, + ('S4-21', 'S4-4F'): IBJ, + ('S4-21', 'S4-20'): IBJ, + ('S4-21', 'S4-60'): IBJ, + ('S4-22', 'S4-1F'): IBJ, + ('S4-22', 'S4-4F'): IBJ, + ('S4-22', 'S4-20'): IBJ, + ('S4-22', 'S4-60'): IBJ, + ('S4-4F', 'S4-1F'): MorphBall, + ('S4-4F', 'S4-21'): MorphBall, + ('S4-4F', 'S4-22'): MorphBall, + ('S4-4F', 'S4-20'): MorphBall, + ('S4-4F', 'S4-60'): MorphBall, + ('S4-20', 'S4-4F'): MorphBall, + ('S4-60', 'S4-4F'): MorphBall, + ('S4-24', 'S4-25'): RedDoors, + ('S4-29', 'S4-28'): RedDoors, + ('S4-2A', 'S4-37'): ScrewAttack, + ('S4-2A', 'S4-5A'): SpringBall, + ('S4-2A', 'S4-74'): MorphBall, + ('S4-37', 'S4-2A'): ScrewAttack, + ('S4-37', 'S4-5A'): ScrewAttack, + ('S4-37', 'S4-74'): ScrewAttack, + ('S4-5A', 'S4-2A'): SpringBall, + ('S4-5A', 'S4-37'): ScrewAttack, + ('S4-5A', 'S4-74'): SpringBall, + ('S4-74', 'S4-2A'): MorphBall, + ('S4-74', 'S4-37'): ScrewAttack, + ('S4-74', 'S4-5A'): ScrewAttack, + ('S4-11', 'S4-2B'): GravitySuit, + ('S4-11', 'S4-3B'): GravitySuit, + ('S4-11', 'S4-47'): GravitySuit, + ('S4-2B', 'S4-11'): DamageRuns, + ('S4-2B', 'S4-3B'): GravitySuit, + ('S4-2B', 'S4-47'): ScrewAttack, + ('S4-3B', 'S4-11'): GravitySuit, + ('S4-3B', 'S4-2B'): GravitySuit, + ('S4-3B', 'S4-47'): GravitySuit, + ('S4-47', 'S4-11'): DamageRuns, + ('S4-47', 'S4-2B'): ScrewAttack, + ('S4-47', 'S4-3B'): GravitySuit, + ('S4-2C', 'S4-2D'): RedDoors, + ('S4-2C', 'S4-2E'): MorphBall, + ('S4-2C', 'S4-4B'): BlueDoors, + ('S4-2D', 'S4-2C'): DamageRuns, + ('S4-2D', 'S4-2E'): DamageRuns, + ('S4-2D', 'S4-4B'): BlueDoors, + ('S4-2E', 'S4-2D'): RedDoors, + ('S4-2E', 'S4-4B'): BlueDoors, + ('S4-4B', 'S4-2D'): RedDoors, + ('S4-4B', 'S4-2E'): MorphBall, + ('S4-2F', 'S4-45'): MorphBall, + ('S4-45', 'S4-2F'): UseBombs, + ('S4-30', 'S4-35'): GravitySuit, + ('S4-30', 'S4-4E'): ScrewAttack, + ('S4-35', 'S4-30'): Impossible, + ('S4-35', 'S4-4D'): Impossible, + ('S4-35', 'S4-4E'): Impossible, + ('S4-4D', 'S4-30'): RedDoors, + ('S4-4D', 'S4-35'): GravitySuit, + ('S4-4D', 'S4-4E'): ScrewAttack, + ('S4-4E', 'S4-30'): RedDoors, + ('S4-4E', 'S4-35'): ScrewAttack, + ('S4-4E', 'S4-4D'): ScrewAttack, + ('S4-31', 'S4-50'): ScrewAttack, + ('S4-36', 'S4-31'): RedDoors, + ('S4-36', 'S4-50'): ScrewAttack, + ('S4-50', 'S4-31'): RedDoors, + ('S4-50', 'S4-36'): ScrewAttack, + ('S4-32', 'S4-33'): RedDoors, + ('S4-32', 'S4-64'): GravitySuit, + ('S4-33', 'S4-32'): RedDoors, + ('S4-33', 'S4-53'): GravitySuit, + ('S4-33', 'S4-64'): BombJump, + ('S4-53', 'S4-32'): RedDoors, + ('S4-53', 'S4-33'): RedDoors, + ('S4-53', 'S4-64'): GravitySuit, + ('S4-64', 'S4-32'): RedDoors, + ('S4-64', 'S4-33'): RedDoors, + ('S4-64', 'S4-53'): GravitySuit, + ('S4-34', 'S4-62'): Impossible, + ('S4-62', 'S4-34'): RedDoors, + ('S4-42', 'S4-43'): UseBombs, + ('S4-42', 'S4-44'): Impossible, + ('S4-42', 'S4-71'): Impossible, + ('S4-43', 'S4-42'): UseBombs, + ('S4-43', 'S4-44'): Impossible, + ('S4-43', 'S4-71'): Impossible, + ('S4-44', 'S4-42'): Impossible, + ('S4-44', 'S4-43'): Impossible, + ('S4-44', 'S4-71'): MorphBall, + ('S4-71', 'S4-42'): Impossible, + ('S4-71', 'S4-43'): Impossible, + ('S4-71', 'S4-44'): MorphBall, + ('S4-46', 'S4-49'): GravitySuit, + ('S4-49', 'S4-46'): GravitySuit, + ('S4-48', 'S4-51'): Impossible, + ('S4-48', 'S4-52'): Impossible, + ('S4-51', 'S4-48'): ScrewAttack, + ('S4-51', 'S4-52'): ScrewAttack, + ('S4-52', 'S4-48'): ScrewAttack, + ('S4-52', 'S4-51'): ScrewAttack, + ('S4-1C', 'S4-38'): Diffusion, + ('S4-1C', 'S4-6D'): ScrewAttack, + ('S4-1C', 'S4-70'): Diffusion, + ('S4-38', 'S4-1C'): Ice, + ('S4-38', 'S4-6D'): ScrewAttack, + ('S4-38', 'S4-70'): Ice, + ('S4-6D', 'S4-1C'): WallJump, + ('S4-6D', 'S4-38'): WallJump, + ('S4-6D', 'S4-70'): WallJump, + ('S4-70', 'S4-1C'): MorphBall, + ('S4-70', 'S4-38'): MorphBall, + ('S4-70', 'S4-6D'): ScrewAttack, + ('S4-56', 'S4-57'): UseBombs, + ('S4-57', 'S4-56'): RedDoors, + ('S4-5D', 'S4-5E'): ScrewAttack, + ('S4-5E', 'S4-5D'): ScrewAttack, + ('S4-65', 'S4-66'): WaveBeam, + ('S4-66', 'S4-65'): MorphBall, + ('S4-6E', 'S4-6F'): MorphBall, + ('S4-6F', 'S4-6E'): MorphBall, + ('S5-01', 'S5-42'): YellowDoors, + ('S5-01', 'S5-4D'): MorphBall, + ('S5-01', 'S5-51'): YellowDoors, + ('S5-42', 'S5-4D'): MorphBall, + ('S5-42', 'S5-51'): YellowDoors, + ('S5-4D', 'S5-01'): MorphBall, + ('S5-4D', 'S5-42'): YellowDoors, + ('S5-4D', 'S5-51'): YellowDoors, + ('S5-51', 'S5-42'): YellowDoors, + ('S5-51', 'S5-4D'): YellowDoors, + ('S5-07', 'S5-08'): IBJ, + ('S5-08', 'S5-07'): YellowDoors, + ('S5-09', 'S5-07'): YellowDoors, + ('S5-09', 'S5-08'): IBJ, + ('S5-4E', 'S5-07'): YellowDoors, + ('S5-4E', 'S5-08'): IBJ, + ('S5-34', 'S5-59'): YellowDoors, + ('S5-59', 'S5-34'): YellowDoors, + ('S5-0B', 'S5-0C'): IBJ, + ('S5-0C', 'S5-0B'): YellowDoors, + ('S5-0D', 'S5-0B'): YellowDoors, + ('S5-0D', 'S5-0C'): IBJ, + ('S5-50', 'S5-0B'): YellowDoors, + ('S5-50', 'S5-0C'): IBJ, + ('S5-0E', 'S5-0F'): VariaSuit, + ('S5-0E', 'S5-10'): VariaSuit, + ('S5-0E', 'S5-1E'): VariaSuit, + ('S5-0E', 'S5-38'): ScrewAttack, + ('S5-0E', 'S5-63'): YellowDoors, + ('S5-0F', 'S5-0E'): VariaSuit, + ('S5-0F', 'S5-10'): VariaSuit, + ('S5-0F', 'S5-1E'): VariaSuit, + ('S5-0F', 'S5-38'): ScrewAttack, + ('S5-0F', 'S5-63'): YellowDoors, + ('S5-10', 'S5-0E'): VariaSuit, + ('S5-10', 'S5-0F'): VariaSuit, + ('S5-10', 'S5-1E'): VariaSuit, + ('S5-10', 'S5-38'): ScrewAttack, + ('S5-10', 'S5-63'): YellowDoors, + ('S5-1E', 'S5-0E'): VariaSuit, + ('S5-1E', 'S5-0F'): VariaSuit, + ('S5-1E', 'S5-10'): VariaSuit, + ('S5-1E', 'S5-38'): ScrewAttack, + ('S5-1E', 'S5-63'): YellowDoors, + ('S5-38', 'S5-0E'): ScrewAttack, + ('S5-38', 'S5-0F'): ScrewAttack, + ('S5-38', 'S5-10'): ScrewAttack, + ('S5-38', 'S5-1E'): ScrewAttack, + ('S5-38', 'S5-63'): ScrewAttack, + ('S5-63', 'S5-0E'): VariaSuit, + ('S5-63', 'S5-0F'): VariaSuit, + ('S5-63', 'S5-10'): VariaSuit, + ('S5-63', 'S5-1E'): VariaSuit, + ('S5-63', 'S5-38'): ScrewAttack, + ('S5-24', 'S5-40'): WaveBeam, + ('S5-40', 'S5-24'): VariaSuit, + ('S5-12', 'S5-14'): YellowDoors, + ('S5-14', 'S5-12'): YellowDoors, + ('S5-28', 'S5-13'): YellowDoors, + ('S5-15', 'S5-16'): VariaSuit, + ('S5-16', 'S5-15'): VariaSuit, + ('S5-18', 'S5-31'): YellowDoors, + ('S5-18', 'S5-4F'): VariaSuit, + ('S5-18', 'S5-5A'): YellowDoors, + ('S5-31', 'S5-18'): SpaceJump, + ('S5-31', 'S5-4F'): VariaSuit, + ('S5-31', 'S5-5A'): YellowDoors, + ('S5-4F', 'S5-18'): SpaceJump, + ('S5-4F', 'S5-31'): YellowDoors, + ('S5-4F', 'S5-5A'): YellowDoors, + ('S5-5A', 'S5-18'): SpaceJump, + ('S5-5A', 'S5-31'): YellowDoors, + ('S5-5A', 'S5-4F'): VariaSuit, + ('S5-1B', 'S5-1D'): GravitySuit, + ('S5-1B', 'S5-39'): ScrewAttack, + ('S5-1B', 'S5-46'): YellowDoors, + ('S5-1C', 'S5-1B'): GravitySuit, + ('S5-1C', 'S5-1D'): GravitySuit, + ('S5-1C', 'S5-39'): GravitySuit, + ('S5-1C', 'S5-46'): YellowDoors, + ('S5-1C', 'S5-1F'): GravitySuit, + ('S5-1C', 'S5-35'): GravitySuit, + ('S5-1D', 'S5-1B'): GravitySuit, + ('S5-1D', 'S5-1C'): GravitySuit, + ('S5-1D', 'S5-39'): GravitySuit, + ('S5-1D', 'S5-46'): YellowDoors, + ('S5-1D', 'S5-1F'): GravitySuit, + ('S5-1D', 'S5-35'): GravitySuit, + ('S5-39', 'S5-1B'): ScrewAttack, + ('S5-39', 'S5-1C'): ScrewAttack, + ('S5-39', 'S5-1D'): GravitySuit, + ('S5-39', 'S5-46'): YellowDoors, + ('S5-39', 'S5-1F'): ScrewAttack, + ('S5-39', 'S5-35'): ScrewAttack, + ('S5-46', 'S5-1B'): GravitySuit, + ('S5-46', 'S5-1C'): GravitySuit, + ('S5-46', 'S5-1D'): UseBombs, + ('S5-46', 'S5-39'): GravitySuit, + ('S5-46', 'S5-1F'): GravitySuit, + ('S5-46', 'S5-35'): GravitySuit, + ('S5-1F', 'S5-1D'): GravitySuit, + ('S5-1F', 'S5-39'): ScrewAttack, + ('S5-1F', 'S5-46'): YellowDoors, + ('S5-35', 'S5-1D'): GravitySuit, + ('S5-35', 'S5-39'): ScrewAttack, + ('S5-35', 'S5-46'): YellowDoors, + ('S5-5B', 'S5-5C'): YellowDoors, + ('S5-5C', 'S5-5B'): IBJ, + ('S5-5C', 'S5-5D'): IBJ, + ('S5-5D', 'S5-5C'): YellowDoors, + ('S5-22', 'S5-78'): PowerBombs, + ('S5-3D', 'S5-22'): IBJ, + ('S5-3D', 'S5-78'): IBJ, + ('S5-3D', 'S5-23'): IBJ, + ('S5-3D', 'S5-77'): IBJ, + ('S5-3E', 'S5-22'): IBJ, + ('S5-3E', 'S5-78'): IBJ, + ('S5-3E', 'S5-23'): IBJ, + ('S5-3E', 'S5-77'): IBJ, + ('S5-78', 'S5-22'): UseBombs, + ('S5-78', 'S5-3D'): UseBombs, + ('S5-78', 'S5-3E'): UseBombs, + ('S5-78', 'S5-23'): UseBombs, + ('S5-78', 'S5-77'): UseBombs, + ('S5-23', 'S5-78'): PowerBombs, + ('S5-77', 'S5-78'): PowerBombs, + ('S5-25', 'S5-26'): ChargeBeam, + ('S5-2A', 'S5-6C'): VariaSuit, + ('S5-2A', 'S5-6D'): VariaSuit, + ('S5-2A', 'S5-6E'): WallJump, + ('S5-6C', 'S5-2A'): VariaSuit, + ('S5-6C', 'S5-6D'): VariaSuit, + ('S5-6C', 'S5-6E'): WallJump, + ('S5-6D', 'S5-2A'): VariaSuit, + ('S5-6D', 'S5-6C'): VariaSuit, + ('S5-6D', 'S5-6E'): WallJump, + ('S5-6E', 'S5-2A'): VariaSuit, + ('S5-6E', 'S5-6C'): VariaSuit, + ('S5-6E', 'S5-6D'): VariaSuit, + ('S5-19', 'S5-30'): YellowDoors, + ('S5-19', 'S5-69'): PowerBombs, + ('S5-30', 'S5-19'): IBJ, + ('S5-30', 'S5-68'): IBJ, + ('S5-30', 'S5-69'): PowerBombs, + ('S5-61', 'S5-19'): IBJ, + ('S5-61', 'S5-30'): YellowDoors, + ('S5-61', 'S5-68'): IBJ, + ('S5-61', 'S5-69'): PowerBombs, + ('S5-68', 'S5-19'): IBJ, + ('S5-68', 'S5-30'): YellowDoors, + ('S5-68', 'S5-69'): PowerBombs, + ('S5-69', 'S5-19'): Impossible, + ('S5-69', 'S5-30'): Impossible, + ('S5-69', 'S5-61'): Impossible, + ('S5-69', 'S5-68'): Impossible, + ('S5-3B', 'S5-3C'): GravitySuit, + ('S5-3C', 'S5-3B'): GravitySuit, + ('S5-41', 'S5-11'): YellowDoors, + ('S5-43', 'S5-49'): ScrewAttack, + ('S5-49', 'S5-43'): YellowDoors, + ('S5-03', 'S5-52'): YellowDoors, + ('S5-52', 'S5-03'): YellowDoors, + ('S5-1A', 'S5-27'): Impossible, + ('S5-27', 'S5-1A'): MorphBall, + ('S5-55', 'S5-56'): YellowDoors, + ('S5-56', 'S5-55'): WaveBeam, + ('S5-67', 'S5-66'): Ice, + ('S5-64', 'S5-65'): Impossible, + ('S5-65', 'S5-64'): YellowDoors, + ('S5-6A', 'S5-6B'): UseBombs, + ('S5-6B', 'S5-6A'): UseBombs, + ('S5-5E', 'S5-5F'): YellowDoors, + ('S5-5E', 'S5-60'): VariaSuit, + ('S5-5F', 'S5-5E'): SpaceJump, + ('S5-5F', 'S5-60'): VariaSuit, + ('S5-60', 'S5-5E'): SpaceJump, + ('S5-60', 'S5-5F'): YellowDoors, + ('S5-36', 'S5-44'): Ice, + ('S5-44', 'S5-36'): WallJump, + ('S5-44', 'S5-70'): MorphBall, + ('S5-70', 'S5-36'): WallJump, + ('S5-70', 'S5-44'): Ice, + ('S5-73', 'S5-7B'): GravitySuit, + ('S5-7B', 'S5-73'): GravitySuit, + ('S6-01', 'S6-33'): Impossible, + ('S6-01', 'S6-4F'): ScrewAttack, + ('S6-33', 'S6-01'): Impossible, + ('S6-33', 'S6-4F'): Impossible, + ('S6-33', 'S6-02'): Impossible, + ('S6-4F', 'S6-01'): ScrewAttack, + ('S6-4F', 'S6-33'): Impossible, + ('S6-4F', 'S6-02'): ScrewAttack, + ('S6-02', 'S6-33'): Impossible, + ('S6-02', 'S6-4F'): ScrewAttack, + ('S6-07', 'S6-08'): Difficulty >= 1, + ('S6-07', 'S6-32'): UseBombs, + ('S6-07', 'S6-4B'): Difficulty >= 1, + ('S6-08', 'S6-07'): ScrewAttack, + ('S6-08', 'S6-32'): ScrewAttack, + ('S6-08', 'S6-4B'): UseBombs, + ('S6-32', 'S6-07'): UseBombs, + ('S6-32', 'S6-08'): ScrewAttack, + ('S6-32', 'S6-4B'): ScrewAttack, + ('S6-4B', 'S6-07'): ScrewAttack, + ('S6-4B', 'S6-08'): UseBombs, + ('S6-4B', 'S6-32'): ScrewAttack, + ('S6-0B', 'S6-52'): ScrewAttack, + ('S6-0B', 'S6-55'): Impossible, + ('S6-52', 'S6-0B'): ScrewAttack, + ('S6-52', 'S6-55'): Impossible, + ('S6-52', 'S6-0C'): ScrewAttack, + ('S6-52', 'S6-0D'): ScrewAttack, + ('S6-52', 'S6-0E'): ScrewAttack, + ('S6-55', 'S6-0B'): SpeedBooster, + ('S6-55', 'S6-52'): ScrewAttack, + ('S6-55', 'S6-0C'): SpeedBooster, + ('S6-55', 'S6-0D'): SpeedBooster, + ('S6-55', 'S6-0E'): SpeedBooster, + ('S6-0C', 'S6-52'): ScrewAttack, + ('S6-0C', 'S6-55'): Impossible, + ('S6-0D', 'S6-52'): ScrewAttack, + ('S6-0D', 'S6-55'): Energy > 499, + ('S6-0E', 'S6-52'): ScrewAttack, + ('S6-0E', 'S6-55'): Impossible, + ('S6-20', 'S6-30'): Energy > 499, + ('S6-30', 'S6-20'): Energy > 499, + ('S6-03', 'S6-21'): Energy > 499, + ('S6-21', 'S6-03'): Energy > 499, + ('S6-0F', 'S6-47'): ScrewAttack, + ('S6-47', 'S6-0F'): MorphBall, + ('S6-47', 'S6-10'): MorphBall, + ('S6-10', 'S6-47'): ScrewAttack, + ('S6-11', 'S6-12'): SpeedBooster, + ('S6-11', 'S6-2E'): SpeedBooster, + ('S6-12', 'S6-11'): SpeedBooster, + ('S6-2E', 'S6-11'): Impossible, + ('S6-14', 'S6-1B'): MorphBall, + ('S6-1B', 'S6-14'): UseBombs, + ('S6-1B', 'S6-15'): UseBombs, + ('S6-1B', 'S6-3D'): UseBombs, + ('S6-15', 'S6-1B'): MorphBall, + ('S6-3D', 'S6-1B'): MorphBall, + ('S6-17', 'S6-18'): GreenDoors, + ('S6-1A', 'S6-59'): ScrewAttack, + ('S6-1C', 'S6-1A'): RedDoors, + ('S6-1C', 'S6-59'): Impossible, + ('S6-59', 'S6-1A'): RedDoors, + ('S6-59', 'S6-1C'): MorphBall, + ('S6-25', 'S6-58'): ScrewAttack, + ('S6-58', 'S6-25'): ScrewAttack, + ('S6-28', 'S6-2A'): RedDoors, + ('S6-29', 'S6-28'): IBJ, + ('S6-29', 'S6-2A'): RedDoors, + ('S6-2A', 'S6-28'): IBJ, + ('S6-2C', 'S6-2D'): WaveBeam, + ('S6-2D', 'S6-2C'): RedDoors, + ('S6-35', 'S6-3E'): GreenDoors, + ('S6-3E', 'S6-35'): GreenDoors, + ('S6-13', 'S6-36'): UseBombs, + ('S6-36', 'S6-13'): PowerBombs, + ('S6-37', 'S6-38'): PowerBombs, + ('S6-38', 'S6-37'): PowerBombs, + ('S6-39', 'S6-3A'): MorphBall, + ('S6-3A', 'S6-39'): MorphBall, + ('S6-3F', 'S6-42'): Impossible, + ('S6-40', 'S6-42'): Impossible, + ('S6-41', 'S6-43'): Energy >= 599, + ('S6-41', 'S6-44'): Energy >= 599, + ('S6-43', 'S6-41'): Energy > 599, + ('S6-43', 'S6-4D'): Energy > 599, + ('S6-44', 'S6-41'): Energy > 599, + ('S6-44', 'S6-4D'): Energy > 599, + ('S6-4D', 'S6-43'): Energy > 599, + ('S6-4D', 'S6-44'): Energy > 599, + ('S0-0E', 'Item S0-0E-0B'): PowerBombs, + ('Item S0-0E-0B', 'S0-0E'): PowerBombs, + ('Item S0-0E-0B', 'S0-13'): PowerBombs, + ('Item S0-0E-0B', 'S0-6C'): PowerBombs, + ('S0-13', 'Item S0-0E-0B'): PowerBombs, + ('S0-6C', 'Item S0-0E-0B'): PowerBombs, + ('S0-20', 'Item S0-05-16'): BackwardsLabs, + ('S0-20', 'S0-22'): BackwardsLabs, + ('Item S0-05-16', 'S0-20'): RedDoors, + ('Item S0-05-16', 'S0-22'): BackwardsLabs, + ('S0-22', 'S0-20'): RedDoors, + ('S0-22', 'Item S0-05-16'): RedDoors, + ('Item S0-14-07', 'S0-4F'): Impossible, + ('S0-4F', 'Item S0-14-07'): Missiles, + ('S0-58', 'Arachnus'): Missiles, + ('S0-58', 'S0-59'): MorphBall, + ('S0-58', 'S0-C8'): Missiles, + ('Item S0-18-06', 'S0-58'): Missiles, + ('Item S0-18-06', 'Arachnus'): Missiles, + ('Item S0-18-06', 'S0-59'): MorphBall, + ('Item S0-18-06', 'S0-C8'): Missiles, + ('Arachnus', 'S0-58'): ScrewAttack, + ('Arachnus', 'Item S0-18-06'): ScrewAttack, + ('Arachnus', 'S0-59'): MorphBall, + ('Arachnus', 'S0-C8'): ScrewAttack, + ('S0-59', 'S0-58'): ScrewAttack, + ('S0-59', 'Item S0-18-06'): ScrewAttack, + ('S0-59', 'Arachnus'): MorphBall, + ('S0-59', 'S0-C8'): ScrewAttack, + ('S0-C8', 'S0-58'): Missiles, + ('S0-C8', 'Item S0-18-06'): Missiles, + ('S0-C8', 'Arachnus'): Missiles, + ('S0-C8', 'S0-59'): MorphBall, + ('S0-6B', 'Item S0-08-0B'): SpringBall, + ('Item S0-08-0B', 'S0-6B'): PowerBombs, + ('Item S0-08-0B', 'S0-C4'): Impossible, + ('S0-C4', 'Item S0-08-0B'): SpringBall, + ('S0-74', 'Item S0-16-12'): MorphBall, + ('S0-74', 'S0-75'): UseBombs, + ('Item S0-16-12', 'S0-74'): MorphBall, + ('Item S0-16-12', 'S0-75'): UseBombs, + ('S0-75', 'S0-74'): Impossible, + ('S0-75', 'Item S0-16-12'): Impossible, + ('S0-83', 'Item S0-0E-07'): BombJump, + ('Item S0-0E-07', 'S0-83'): GreenDoors, + ('S0-9F', 'Item S0-09-04'): WaveBeam, + ('Item S0-09-04', 'S0-9F'): GreenDoors, + ('Item S0-09-04', 'S0-A0'): Impossible, + ('Item S0-09-04', 'S0-A1'): Impossible, + ('Item S0-09-04', 'S0-A2'): WaveBeam, + ('Item S0-09-04', 'S0-A3'): Impossible, + ('S0-A0', 'Item S0-09-04'): WaveBeam, + ('S0-A9', 'Item S0-0C-09'): MorphBall, + ('Item S0-0C-09', 'S0-A9'): MorphBall, + ('S0-AA', 'Item S0-05-08'): SpeedBooster, + ('Item S0-05-08', 'S0-AA'): SpeedBooster, + ('S0-C2', 'End-of-Game'): PlasmaBeam, + ('End-of-Game', 'S0-C2'): RedDoors, + ('S0-03', 'Yakuza'): Difficulty > 0, + ('S0-03', 'S0-79'): IBJ, + ('Yakuza', 'S0-03'): IBJ, + ('Yakuza', 'S0-79'): IBJ, + ('S0-79', 'S0-03'): IBJ, + ('S0-79', 'Yakuza'): Difficulty > 0, + ('S1-0D', 'Item S1-0D-02'): MorphBall, + ('Item S1-0D-02', 'S1-0D'): MorphBall, + ('Item S1-0D-02', 'S1-0E'): MorphBall, + ('S1-0E', 'Item S1-0D-02'): MorphBall, + ('S1-24', 'Item S1-05-03'): Energy >= 199, + ('S1-24', 'Item S1-06-03'): Energy >= 199, + ('S1-24', 'Item S1-07-04'): Energy >= 399, + ('Item S1-05-03', 'S1-24'): Energy >= 199, + ('Item S1-05-03', 'S1-25'): Energy >= 199, + ('Item S1-05-03', 'Item S1-06-03'): Impossible, + ('Item S1-05-03', 'Item S1-07-04'): Impossible, + ('S1-25', 'Item S1-05-03'): Difficulty > 0, + ('S1-25', 'Item S1-07-04'): Energy >= 299, + ('Item S1-06-03', 'S1-24'): Energy >= 199, + ('Item S1-06-03', 'Item S1-05-03'): Impossible, + ('Item S1-06-03', 'Item S1-07-04'): Impossible, + ('Item S1-07-04', 'S1-24'): Energy >= 399, + ('Item S1-07-04', 'Item S1-05-03'): Impossible, + ('Item S1-07-04', 'S1-25'): Energy >= 299, + ('Item S1-07-04', 'Item S1-06-03'): Impossible, + ('S1-3A', 'Ridley'): PlasmaBeam, + ('Ridley', 'S1-3A'): IBJ, + ('S1-3E', 'Item S1-03-0A'): ScrewAttack, + ('Item S1-03-0A', 'S1-3E'): ScrewAttack, + ('Item S1-03-0A', 'S1-3F'): ScrewAttack, + ('Item S1-03-0A', '3E'): BombJump, + ('Item S1-03-0A', '3F'): BombJump, + ('S1-3F', 'Item S1-03-0A'): ScrewAttack, + ('3E', 'Item S1-03-0A'): BombJump, + ('3F', 'Item S1-03-0A'): BombJump, + ('S1-51', 'Item S1-07-00'): ScrewAttack, + ('S1-51', 'S1-66'): ScrewAttack, + ('Item S1-07-00', 'S1-51'): GreenDoors, + ('Item S1-07-00', 'S1-66'): MorphBall, + ('S1-66', 'S1-51'): GreenDoors, + ('S1-66', 'Item S1-07-00'): BombJump, + ('S1-52', 'Item S1-09-04'): SpeedBooster, + ('S1-52', 'Charge Core-X'): Missiles, + ('S1-52', 'S1-55'): Missiles, + ('Item S1-09-04', 'S1-52'): Missiles, + ('Item S1-09-04', 'Charge Core-X'): Missiles, + ('Item S1-09-04', 'S1-55'): Missiles, + ('Charge Core-X', 'Item S1-09-04'): Impossible, + ('S1-55', 'S1-52'): Missiles, + ('S1-55', 'Item S1-09-04'): SpeedBooster, + ('S1-55', 'Charge Core-X'): Missiles, + ('S1-5D', 'Item S1-0A-04'): MorphBall, + ('Item S1-0A-04', 'S1-5D'): MorphBall, + ('S1-65', 'Item S1-0C-07'): GravitySuit, + ('Item S1-0C-07', 'S1-65'): GravitySuit, + ('S1-6D', 'Item S1-11-02'): MorphBall, + ('Item S1-11-02', 'S1-6D'): MorphBall, + ('S2-0E', 'Item S2-09-03'): UseBombs, + ('Item S2-09-03', 'S2-0E'): BlueDoors, + ('Data S2', 'S2-13'): BlueDoors, + ('S2-14', 'Item S2-00-05'): UseBombs, + ('Item S2-00-05', 'S2-14'): MorphBall, + ('Item S2-00-05', 'S2-15'): UseBombs, + ('S2-15', 'Item S2-00-05'): HiJump, + ('S2-16', 'Item S2-02-0E'): UseBombs, + ('Item S2-02-0E', 'S2-16'): SpringBall, + ('Item S2-02-0E', 'S2-17'): UseBombs, + ('S2-17', 'Item S2-02-0E'): UseBombs, + ('S2-26', 'Item S2-0C-0B'): Impossible, + ('Item S2-0C-0B', 'S2-26'): Impossible, + ('Item S2-0C-0B', 'S2-27'): ChargeBeam, + ('S2-28', 'Zazabi'): Missiles, + ('S2-28', 'S2-85'): IBJ, + ('Zazabi', 'S2-28'): IBJ, + ('Zazabi', 'S2-85'): IBJ, + ('S2-85', 'S2-28'): IBJ, + ('S2-85', 'Zazabi'): ScrewAttack, + ('S2-31', 'Item S2-0C-04'): MorphBall, + ('Item S2-0C-04', 'S2-31'): MorphBall, + ('S2-32', 'Nettori'): Impossible, + ('S2-32', 'S2-33'): Impossible, + ('Nettori', 'S2-33'): Impossible, + ('S2-33', 'S2-32'): Difficulty > 0, + ('S2-33', 'Nettori'): Difficulty > 0, + ('S2-39', 'Item S2-03-0C'): PowerBombs, + ('Item S2-03-0C', 'S2-39'): PowerBombs, + ('S2-83', 'Security-Level-1'): ScrewAttack, + ('Security-Level-1', 'S2-83'): IBJ, + ('Security-Level-1', 'S2-3B'): BlueDoors, + ('Security-Level-1', 'S2-3D'): IBJ, + ('S2-3E', 'Item S2-09-05'): UseBombs, + ('Item S2-09-05', 'S2-3E'): UseBombs, + ('Item S2-09-05', 'S2-3F'): UseBombs, + ('S2-3F', 'Item S2-09-05'): UseBombs, + ('S2-10', 'Item S2-04-04'): UseBombs, + ('S2-12', 'Item S2-04-04'): ScrewAttack, + ('Item S2-04-04', 'S2-10'): UseBombs, + ('Item S2-04-04', 'S2-12'): ScrewAttack, + ('Item S2-04-04', 'S2-45'): BlueDoors, + ('Item S2-04-04', 'S2-54'): ScrewAttack, + ('S2-45', 'Item S2-04-04'): UseBombs, + ('S2-54', 'Item S2-04-04'): ScrewAttack, + ('S2-49', 'Item S2-04-03'): ScrewAttack, + ('Item S2-04-03', 'S2-7D'): ScrewAttack, + ('S2-7D', 'Item S2-04-03'): ScrewAttack, + ('S2-38', 'Item S2-04-0B'): IBJ, + ('Item S2-04-0B', 'S2-38'): WallJump, + ('S2-5F', 'Item S2-04-0B'): WallJump, + ('S2-6D', 'Item S2-08-08'): IBJ, + ('Item S2-08-08', 'S2-6D'): IBJ, + ('Item S2-08-08', 'S2-73'): IBJ, + ('S2-6E', 'Item S2-08-08'): IBJ, + ('S2-73', 'Item S2-08-08'): IBJ, + ('S2-72', 'Item S2-05-08'): Ice, + ('S2-72', 'Item S2-05-0A'): Ice, + ('Item S2-05-08', 'S2-72'): UseBombs, + ('Item S2-05-0A', 'S2-72'): UseBombs, + ('S2-84', 'Item S2-05-00'): SpaceJump, + ('S2-84', 'Item S2-05-01'): SpaceJump, + ('Item S2-05-00', 'S2-84'): UseBombs, + ('S2-86', 'Item S2-10-0C'): SpeedBooster, + ('S2-86', 'Item S2-10-0E'): SpeedBooster, + ('S3-08', 'Item S3-06-06'): SpeedBooster, + ('Item S3-06-06', 'S3-08'): SpeedBooster, + ('Item S3-06-06', 'S3-09'): GreenDoors, + ('Item S3-06-06', 'S3-4C'): SpeedBooster, + ('S3-4C', 'Item S3-06-06'): Impossible, + ('Security-Level-2', 'S3-0A'): GreenDoors, + ('Security-Level-2', 'S3-4D'): Impossible, + ('S3-4D', 'Security-Level-2'): MorphBall, + ('S3-0D', 'Item S3-0B-04'): ScrewAttack, + ('Item S3-0B-04', 'S3-0D'): GreenDoors, + ('Item S3-0B-04', 'S3-0E'): GreenDoors, + ('Item S3-0B-04', 'S3-0F'): UseBombs, + ('Item S3-0B-04', 'S3-3C'): ScrewAttack, + ('S3-0E', 'Item S3-0B-04'): MorphBall, + ('S3-0F', 'Item S3-0B-04'): ScrewAttack, + ('S3-3C', 'Item S3-0B-04'): Impossible, + ('S3-11', 'Item S3-0A-01'): PowerBombs, + ('S3-11', 'Item S3-0B-02'): UseBombs, + ('Item S3-0A-01', 'S3-11'): MorphBall, + ('Item S3-0A-01', 'S3-12'): HiJump, + ('Item S3-0B-02', 'S3-11'): ScrewAttack, + ('Item S3-0B-02', 'S3-12'): HiJump, + ('S3-12', 'Item S3-0A-01'): PowerBombs, + ('S3-12', 'Item S3-0B-02'): UseBombs, + ('S3-13', 'Item S3-0F-00'): SpeedBooster, + ('Item S3-0F-00', 'S3-53'): ScrewAttack, + ('Item S3-0F-00', 'S3-54'): ScrewAttack, + ('S3-26', 'Item S3-0F-00'): SpeedBooster, + ('S3-53', 'Item S3-0F-00'): ScrewAttack, + ('S3-54', 'Item S3-0F-00'): ScrewAttack, + ('S3-18', 'Item S3-07-0B'): Energy >= 599, + ('Item S3-07-0B', 'S3-18'): Energy >= 199, + ('Item S3-07-0B', 'S3-19'): Energy >= 299, + ('S3-19', 'Item S3-07-0B'): Energy >= 599, + ('S3-28', 'Item S3-11-0A'): WaveBeam, + ('S3-28', 'Item S3-12-09'): WaveBeam, + ('Item S3-11-0A', 'S3-28'): VariaSuit, + ('Item S3-11-0A', 'Item S3-12-09'): VariaSuit, + ('Item S3-11-0A', 'S3-4B'): VariaSuit, + ('Item S3-11-0A', 'S3-4E'): ScrewAttack, + ('Item S3-12-09', 'S3-28'): VariaSuit, + ('Item S3-12-09', 'Item S3-11-0A'): VariaSuit, + ('Item S3-12-09', 'S3-4B'): VariaSuit, + ('Item S3-12-09', 'S3-4E'): ScrewAttack, + ('S3-4B', 'Item S3-11-0A'): VariaSuit, + ('S3-4B', 'Item S3-12-09'): VariaSuit, + ('S3-4E', 'Item S3-11-0A'): ScrewAttack, + ('S3-4E', 'Item S3-12-09'): ScrewAttack, + ('Data S3', 'S3-2C'): GreenDoors, + ('S3-32', 'Wide Core-X'): Missiles, + ('S3-38', 'Item S3-01-02'): ScrewAttack, + ('S3-38', 'S3-57'): ScrewAttack, + ('Item S3-01-02', 'S3-38'): ScrewAttack, + ('Item S3-01-02', 'Item S3-03-04'): ScrewAttack, + ('Item S3-01-02', 'S3-57'): ScrewAttack, + ('Item S3-03-04', 'Item S3-01-02'): ScrewAttack, + ('Item S3-03-04', 'S3-57'): ScrewAttack, + ('S3-57', 'S3-38'): ScrewAttack, + ('S3-57', 'Item S3-01-02'): ScrewAttack, + ('S3-57', 'Item S3-03-04'): ScrewAttack, + ('S3-3A', 'Item S3-0B-06'): IBJ, + ('Item S3-0B-06', 'S3-3A'): IBJ, + ('Item S3-0B-06', 'S3-3B'): Impossible, + ('Item S3-0B-06', 'S3-3E'): Impossible, + ('S3-3B', 'Item S3-0B-06'): IBJ, + ('S3-3E', 'Item S3-0B-06'): IBJ, + ('S3-45', 'Item S3-11-04'): ScrewAttack, + ('Item S3-11-04', 'S3-45'): ScrewAttack, + ('S3-27', 'Item S3-0E-0A'): ScrewAttack, + ('Item S3-0E-0A', 'S3-27'): ScrewAttack, + ('Item S3-0E-0A', 'S3-47'): GreenDoors, + ('Item S3-0E-0A', 'S3-4A'): IBJ, + ('S3-4A', 'Item S3-0E-0A'): ScrewAttack, + ('S3-4F', 'Item S3-14-03'): ScrewAttack, + ('S3-4F', 'Item S3-14-09'): GravitySuit, + ('Item S3-14-03', 'S3-4F'): Impossible, + ('Item S3-14-03', 'S3-50'): ScrewAttack, + ('Item S3-14-09', 'S3-4F'): Impossible, + ('Item S3-14-09', 'S3-50'): GravitySuit, + ('S3-50', 'Item S3-14-03'): Impossible, + ('S3-50', 'Item S3-14-09'): Impossible, + ('S3-58', 'Item S3-00-05'): ScrewAttack, + ('Item S3-00-05', 'S3-58'): ScrewAttack, + ('Item S3-00-05', 'S3-59'): ScrewAttack, + ('S3-59', 'Item S3-00-05'): ScrewAttack, + ('Data S4', 'S4-0A'): RedDoors, + ('S4-0D', 'Item S4-0C-06'): DamageRuns, + ('Item S4-0C-06', 'S4-0D'): DamageRuns, + ('Item S4-0C-06', 'S4-0E'): DamageRuns, + ('Item S4-0C-06', 'S4-12'): GravitySuit, + ('Item S4-0C-06', 'S4-41'): DamageRuns, + ('S4-0E', 'Item S4-0C-06'): GravitySuit, + ('S4-12', 'Item S4-0C-06'): GravitySuit, + ('S4-41', 'Item S4-0C-06'): GravitySuit, + ('Item S4-09-02', 'S4-3F'): Impossible, + ('Item S4-09-02', 'S4-40'): Impossible, + ('S4-3F', 'Item S4-09-02'): Impossible, + ('S4-40', 'Item S4-09-02'): Impossible, + ('S4-1D', 'Item S4-0D-01'): UseBombs, + ('S4-1D', 'Item S4-0E-02'): UseBombs, + ('Item S4-0D-01', 'S4-1D'): Impossible, + ('Item S4-0D-01', 'S4-1E'): UseBombs, + ('Item S4-0D-01', 'S4-75'): UseBombs, + ('Item S4-0E-02', 'S4-1D'): Impossible, + ('S4-1E', 'Item S4-0D-01'): UseBombs, + ('S4-1E', 'Item S4-0E-02'): UseBombs, + ('S4-75', 'Item S4-0D-01'): UseBombs, + ('S4-75', 'Item S4-0E-02'): UseBombs, + ('S4-23', 'Item S4-0B-08'): None, + ('Item S4-0B-08', 'S4-23'): None, + ('S4-26', 'Item S4-0A-0C'): PowerBombs, + ('Item S4-0A-0C', 'S4-26'): IBJ, + ('Item S4-0A-0C', 'S4-27'): IBJ, + ('S4-27', 'Item S4-0A-0C'): PowerBombs, + ('S4-30', 'Item S4-07-08'): ScrewAttack, + ('Item S4-07-08', 'S4-30'): RedDoors, + ('Item S4-07-08', 'S4-35'): ScrewAttack, + ('Item S4-07-08', 'S4-4D'): ScrewAttack, + ('Item S4-07-08', 'S4-4E'): MorphBall, + ('S4-35', 'Item S4-07-08'): Impossible, + ('S4-4D', 'Item S4-07-08'): ScrewAttack, + ('S4-4E', 'Item S4-07-08'): MorphBall, + ('S4-31', 'Item S4-07-0A'): ScrewAttack, + ('Item S4-07-0A', 'S4-31'): RedDoors, + ('Item S4-07-0A', 'S4-36'): ScrewAttack, + ('Item S4-07-0A', 'S4-50'): MorphBall, + ('S4-36', 'Item S4-07-0A'): ScrewAttack, + ('S4-50', 'Item S4-07-0A'): MorphBall, + ('Security-Level-4', 'S4-34'): RedDoors, + ('Security-Level-4', 'S4-62'): Impossible, + ('S4-04', 'Item S4-09-06'): MorphBall, + ('Item S4-09-06', 'S4-04'): MorphBall, + ('Item S4-09-06', 'S4-3C'): MorphBall, + ('S4-3C', 'Item S4-09-06'): MorphBall, + ('S4-4C', 'Item S4-00-06'): DamageRuns, + ('S4-4C', 'Water Pump'): DamageRuns, + ('Item S4-00-06', 'S4-4C'): GravitySuit, + ('Item S4-00-06', 'Water Pump'): GravitySuit, + ('Water Pump', 'S4-4C'): WaterLowered, + ('Water Pump', 'Item S4-00-06'): WaterLowered, + ('S4-55', 'Item S4-0F-06'): ScrewAttack, + ('S4-55', 'S4-5B'): Energy >= 199, + ('S4-55', 'S4-5C'): Energy >= 199, + ('Item S4-0F-06', 'S4-55'): Energy >= 199, + ('Item S4-0F-06', 'S4-5B'): Energy >= 199, + ('Item S4-0F-06', 'S4-5C'): Energy >= 199, + ('S4-5B', 'S4-55'): Energy >= 199, + ('S4-5B', 'Item S4-0F-06'): ScrewAttack, + ('S4-5B', 'S4-5C'): DamageRuns, + ('S4-5C', 'S4-55'): Energy >= 199, + ('S4-5C', 'Item S4-0F-06'): ScrewAttack, + ('S4-5C', 'S4-5B'): DamageRuns, + ('S4-5D', 'Item S4-13-07'): ScrewAttack, + ('Item S4-12-07', 'Item S4-13-07'): Impossible, + ('Item S4-12-07', 'S4-5E'): ScrewAttack, + ('Item S4-13-07', 'S4-5D'): ScrewAttack, + ('Item S4-13-07', 'Item S4-12-07'): ScrewAttack, + ('Item S4-13-07', 'S4-5E'): GravitySuit, + ('S4-5E', 'Item S4-12-07'): ScrewAttack, + ('S4-5E', 'Item S4-13-07'): GravitySuit, + ('S4-67', 'Item S4-06-0E'): GravitySuit, + ('Item S4-06-0E', 'S4-67'): UseBombs, + ('S4-1A', 'Serris'): Missiles, + ('S4-1A', 'S4-68'): Missiles, + ('S4-68', 'S4-1A'): Missiles, + ('S4-68', 'Serris'): Missiles, + ('S4-72', 'Item S4-05-03'): MorphBall, + ('Item S4-05-03', 'S4-72'): MorphBall, + ('S5-0A', 'Item S5-04-01'): YellowDoors, + ('Item S5-05-01', 'Item S5-04-01'): Impossible, + ('Data S5', 'S5-34'): YellowDoors, + ('Data S5', 'S5-59'): YellowDoors, + ('Security-Level-3', 'S5-13'): YellowDoors, + ('S5-28', 'S5-13'): YellowDoors, + ('S5-17', 'Item S5-0C-07'): BombJump, + ('Item S5-0C-07', 'S5-17'): BombJump, + ('S5-45', 'Item S5-0F-07'): VariaSuit, + ('Item S5-0F-07', 'S5-45'): MorphBall, + ('S5-22', 'Item S5-12-04'): PowerBombs, + ('Item S5-12-04', 'S5-22'): UseBombs, + ('Item S5-12-04', 'S5-23'): UseBombs, + ('Item S5-12-04', 'S5-3D'): UseBombs, + ('Item S5-12-04', 'S5-3E'): UseBombs, + ('Item S5-12-04', 'S5-77'): UseBombs, + ('Item S5-12-04', 'S5-78'): UseBombs, + ('S5-23', 'Item S5-12-04'): PowerBombs, + ('S5-3D', 'Item S5-12-04'): IBJ, + ('S5-3E', 'Item S5-12-04'): IBJ, + ('S5-77', 'Item S5-12-04'): PowerBombs, + ('S5-78', 'Item S5-12-04'): UseBombs, + ('S5-3A', 'Nightmare'): SpaceJump, + ('S5-3A', 'S5-54'): Impossible, + ('Nightmare', 'S5-54'): Impossible, + ('S5-54', 'S5-3A'): SpaceJump, + ('S5-54', 'Nightmare'): SpaceJump, + ('S5-2A', 'Item S5-07-0B'): VariaSuit, + ('S5-6C', 'Item S5-07-0B'): VariaSuit, + ('Item S5-07-0B', 'S5-2A'): VariaSuit, + ('Item S5-07-0B', 'S5-6C'): VariaSuit, + ('Item S5-07-0B', 'S5-6D'): VariaSuit, + ('Item S5-07-0B', 'S5-6E'): WallJump, + ('S5-6D', 'Item S5-07-0B'): VariaSuit, + ('S5-6E', 'Item S5-07-0B'): VariaSuit, + ('S5-37', 'Item S5-06-05'): VariaSuit, + ('Item S5-06-05', 'S5-37'): VariaSuit, + ('Item S5-03-04', 'S5-43'): YellowDoors, + ('Item S5-03-04', 'S5-49'): ScrewAttack, + ('S5-49', 'Item S5-03-04'): ScrewAttack, + ('S5-03', 'Item S5-05-04'): ScrewAttack, + ('Item S5-05-04', 'S5-03'): YellowDoors, + ('Item S5-05-04', 'S5-52'): YellowDoors, + ('S5-52', 'Item S5-05-04'): ScrewAttack, + ('S5-1A', 'Item S5-16-04'): Impossible, + ('Item S5-16-04', 'S5-1A'): SpaceJump, + ('Item S5-16-04', 'S5-27'): Impossible, + ('S5-27', 'Item S5-16-04'): UseBombs, + ('S5-4B', 'Item S5-0B-01'): ScrewAttack, + ('Item S5-0B-01', 'S5-4B'): ScrewAttack, + ('Item S5-0B-01', 'S5-57'): ScrewAttack, + ('Item S5-0B-01', 'S5-58'): ScrewAttack, + ('S5-57', 'Item S5-0B-01'): ScrewAttack, + ('S5-58', 'Item S5-0B-01'): ScrewAttack, + ('S5-76', 'Item S5-11-05'): PowerBombs, + ('Item S5-11-05', 'S5-76'): PowerBombs, + ('S5-73', 'Item S5-14-07'): GravitySuit, + ('Item S5-14-07', 'S5-7B'): GravitySuit, + ('S5-7B', 'Item S5-14-07'): GravitySuit, + ('S5-2F', 'Item S5-0E-08'): SpaceJump, + ('Item S5-0E-08', 'S5-2F'): VariaSuit, + ('S6-01', 'Item S6-05-03'): Impossible, + ('Item S6-05-03', 'S6-01'): Impossible, + ('Item S6-05-03', 'S6-02'): Impossible, + ('Item S6-05-03', 'S6-33'): MorphBall, + ('Item S6-05-03', 'S6-4F'): Impossible, + ('S6-02', 'Item S6-05-03'): Impossible, + ('S6-33', 'Item S6-05-03'): MorphBall, + ('S6-4F', 'Item S6-05-03'): Impossible, + ('S6-19', 'Mega Core-X'): ChargeBeam, + ('Mega Core-X', 'S6-19'): GreenDoors, + ('S6-34', 'S6-19'): GreenDoors, + ('S6-34', 'Mega Core-X'): ChargeBeam, + ('S6-1D', 'Item S6-05-0B'): IBJ, + ('Item S6-05-0B', 'S6-1D'): UseBombs, + ('S6-1E', 'Wave Core-X'): GravitySuit, + ('S6-1E', 'S6-1F'): GravitySuit, + ('S6-1E', 'S6-24'): GravitySuit, + ('S6-1E', 'S6-57'): ScrewAttack, + ('Wave Core-X', 'S6-1E'): Impossible, + ('Wave Core-X', 'S6-57'): Impossible, + ('S6-1F', 'S6-1E'): Impossible, + ('S6-1F', 'Wave Core-X'): GravitySuit, + ('S6-1F', 'S6-24'): GravitySuit, + ('S6-1F', 'S6-57'): Impossible, + ('S6-24', 'S6-1E'): Impossible, + ('S6-24', 'Wave Core-X'): GravitySuit, + ('S6-24', 'S6-1F'): GravitySuit, + ('S6-24', 'S6-57'): Impossible, + ('S6-57', 'S6-1E'): ScrewAttack, + ('S6-57', 'Wave Core-X'): ScrewAttack, + ('S6-57', 'S6-1F'): ScrewAttack, + ('S6-57', 'S6-24'): ScrewAttack, + ('S6-25', 'Item S6-09-05'): IceBeam, + ('S6-25', 'Item S6-0A-06'): WaveBeam, + ('Item S6-09-05', 'S6-25'): ScrewAttack, + ('Item S6-09-05', 'S6-58'): UseBombs, + ('Item S6-0A-06', 'S6-25'): WaveBeam, + ('Item S6-0A-06', 'S6-58'): ScrewAttack, + ('S6-58', 'Item S6-09-05'): IceBeam, + ('S6-58', 'Item S6-0A-06'): ScrewAttack, + ('S6-31', 'Item S6-0E-03'): UseBombs, + ('Item S6-0E-03', 'S6-31'): UseBombs, + ('Data S6', 'S6-35'): GreenDoors, + ('Data S6', 'S6-3E'): GreenDoors, + ('Item S6-06-08', 'S6-36'): UseBombs, + ('S6-36', 'Item S6-06-08'): PowerBombs, + ('S6-3F', 'Item S6-0C-08'): Impossible, + ('S6-3F', 'Item S6-0B-09'): WallJump, + ('Item S6-0C-08', 'S6-42'): Impossible, + ('Item S6-0B-09', 'S6-3F'): MorphBall, + ('Item S6-0B-09', 'S6-40'): MorphBall, + ('Item S6-0B-09', 'S6-42'): Impossible, + ('S6-40', 'Item S6-0C-08'): Impossible, + ('S6-40', 'Item S6-0B-09'): WallJump, + ('S6-42', 'Item S6-0B-09'): MorphBall, + ('S6-4C', 'Item S6-08-03'): UseBombs, + ('Item S6-08-03', 'S6-4C'): SpringBall, + ('S6-56', 'Item S6-0E-04'): SpeedBooster, + ('Item S6-0E-04', 'S6-56'): SpeedBooster, + ('S6-5A', 'Item S6-03-04'): SpeedBooster, + ('S6-5A', 'Item S6-01-06'): SpaceJump, + ('Item S6-03-04', 'S6-5A'): SpeedBooster, + ('Item S6-01-06', 'S6-5A'): SpeedBooster, + ('S5-4D', 'S5-50'): YellowDoors, + ('S5-0A', 'S5-0C'): YellowDoors, + ('S5-03', 'S5-0B'): WaveBeam, + ('S5-55', 'S5-1F'): YellowDoors, + ('S5-37', 'S5-39'): YellowDoors, + ('S5-24', 'S5-1C'): YellowDoors, + ('S5-15', 'S5-1D'): YellowDoors, + ('S5-64', 'S5-46'): WaveBeam, + ('S5-56', 'S5-5C'): WaveBeam } + + +def find_available_areas(graph): + check = int(StartLocation[1:2]) + AreaOpen[check] = StartLocation + if AreaOpen[0] == None: + check = 'S0-32' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[0] = check + if AreaOpen[1] == None: + check = 'S1-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[1] = check + if ScrewAttack: + if AreaOpen[1] == None: + check = 'S1-6B' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[1] = check + if AreaOpen[1] == None: + check = 'S1-68' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[1] = check + if AreaOpen[2] == None: + check = 'S2-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[2] = check + if ScrewAttack: + if AreaOpen[2] == None: + check = 'S2-7F' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[2] = check + if AreaOpen[2] == None: + check = 'S2-82' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[2] = check + if AreaOpen[3] == None: + check = 'S3-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[3] = check + if ScrewAttack: + if AreaOpen[3] == None: + check = 'S3-56' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[3] = check + if AreaOpen[3] == None: + check = 'S3-59' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[3] = check + if AreaOpen[4] == None: + check = 'S4-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[4] = check + if ScrewAttack: + if AreaOpen[4] == None: + check = 'S4-6A' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[4] = check + if AreaOpen[4] == None: + check = 'S4-6C' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[4] = check + if AreaOpen[5] == None: + check = 'S5-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[5] = check + if ScrewAttack and AreaOpen[5] == None: + check = 'S5-53' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[5] = check + if AreaOpen[6] == None: + check = 'S6-00' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[6] = check + if ScrewAttack: + if AreaOpen[6] == None: + check = 'S6-51' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[6] = check + if AreaOpen[6] == None: + check = 'S6-54' + path = graph.get_path(StartLocation, check) + if path != None: + path = graph.get_path(check, StartLocation) + if path != None: + AreaOpen[6] = check + if BlueDoors == False: + path = graph.get_path(StartLocation, 'Security-Level-1', 250, **('depth',)) + if path != None: + enable_item(graph, 'BlueDoors') + path = graph.get_path('Security-Level-1', StartLocation, 250, **('depth',)) + if path == None: + disable_item(graph, 'BlueDoors') + if GreenDoors == False: + path = graph.get_path(StartLocation, 'Security-Level-2', 250, **('depth',)) + if path != None: + enable_item(graph, 'GreenDoors') + path = graph.get_path('Security-Level-2', StartLocation, 250, **('depth',)) + if path == None: + disable_item(graph, 'GreenDoors') + elif SeedSettings['SplitSecurity'] == False: + enable_item(graph, 'BlueDoors') + if YellowDoors == False: + path = graph.get_path(StartLocation, 'Security-Level-3', 250, **('depth',)) + if path != None: + enable_item(graph, 'YellowDoors') + path = graph.get_path('Security-Level-3', StartLocation, 250, **('depth',)) + if path == None: + disable_item(graph, 'YellowDoors') + elif SeedSettings['SplitSecurity'] == False: + enable_item(graph, 'GreenDoors') + enable_item(graph, 'BlueDoors') + if RedDoors == False: + path = graph.get_path(StartLocation, 'Security-Level-4', 250, **('depth',)) + if path != None: + enable_item(graph, 'RedDoors') + path = graph.get_path('Security-Level-4', StartLocation, 250, **('depth',)) + if path == None: + disable_item(graph, 'RedDoors') + elif SeedSettings['SplitSecurity'] == False: + enable_item(graph, 'YellowDoors') + enable_item(graph, 'GreenDoors') + enable_item(graph, 'BlueDoors') + if WaterLowered == False: + path = graph.get_path(StartLocation, 'S4-00') + if path != None: + path = graph.get_path('S4-00', 'Water Pump', True) + if path != None: + enable_item(graph, 'WaterLowered') + path = graph.get_path('Water Pump', 'S4-00', True) + if path == None: + disable_item(graph, 'WaterLowered') + + +def randomize_game(graph): + global PlacedETanks, PlacedMissiles, PlacedPowerBombs, areaLayout, areaLayout, areaLayout, PlacedETanks, PlacedMissiles, PlacedPowerBombs, MissileCount, NettoriOpen, PlacedMissiles, MissileCount, PlacedETanks, PlacedETanks, MaxETanks, PlacedETanks, PlacedMissiles, PlacedPowerBombs + update_requirements(graph) + PlacedETanks = PlacedMissiles = PlacedPowerBombs = 0 + gameBeatable = False + init = False + weightInit = False + startingWeights = list() + availableItems = list() + areaWeights = list() + MajorLocations = list() + MinorLocations = list() + PossibleMissileTanks = list() + AllItemLocations = list() + locationWeights = list() + locationsPerArea = list() + weightValue = list() + newLocations = list() + invalidItems = list() + invalidWeights = list() + oldLocations = list() + oldWeights = list() + FirstItem = None + AddETank = False + attemptedLayouts = [ + [ + 5, + 3, + 1, + 2, + 4, + 6]] + WeightedMajors = { + 'MainMissiles': 16, + 'MorphBall': 16, + 'ChargeBeam': 8, + 'Bombs': 14, + 'HiJumpBoots': 14, + 'SpeedBooster': 8, + 'SuperMissileItem': 8, + 'VariaSuit': 12, + 'IceMissileItem': 6, + 'WideBeam': 4, + 'MainPowerBombs': 6, + 'SpaceJump': 4, + 'PlasmaBeam': 2, + 'GravitySuit': 4, + 'DiffusionItem': 6, + 'WaveBeam': 4, + 'ScrewAttack': 2, + 'IceBeam': 2 } + BossHealths = { + 'Arachnus': 0, + 'Yakuza': 1000, + 'Ridley': 4500, + 'Charge Core-X': 0, + 'Zazabi': 100, + 'Nettori': 2000, + 'Data S3': 300, + 'Wide Core-X': 0, + 'Serris': 50, + 'Nightmare': 1800, + 'Mega Core-X': 0, + 'Box-2': 500 } + print('Generating, please wait...') + if gameBeatable == False: + if init == False: + if SeedSettings['SectorShuffle'] == True: + areaDoors = { + 1: [ + 'S1-6B', + 'S1-68'], + 2: [ + 'S2-7F', + 'S2-82'], + 3: [ + 'S3-59', + 'S3-56'], + 4: [ + 'S4-6C', + 'S4-6A'], + 5: [ + 'S5-02', + 'S5-53'], + 6: [ + 'S6-51', + 'S6-54'] } + areaLayout = random.sample(range(1, 7), 6) + if (SeedSettings['MajorMinor'] == True or areaLayout[2] != 1) and areaLayout[2] != 2 and areaLayout[3] != 1 and areaLayout[3] != 2: + attemptedLayouts.append(areaLayout) + if areaLayout in attemptedLayouts: + areaLayout = random.sample(range(1, 7), 6) + # continue + # continue + elif areaLayout in attemptedLayouts: + areaLayout = random.sample(range(1, 7), 6) + # continue + attemptedLayouts.append(areaLayout) + for area in areaLayout: + elevator = areaLayout.index(area) + if elevator == 0: + leftArea = areaLayout[5] + else: + leftArea = areaLayout[areaLayout.index(area) - 1] + if elevator == 5: + rightArea = areaLayout[0] + else: + rightArea = areaLayout[areaLayout.index(area) + 1] + if area == 1: + topTile = 19 + bottomTile = 35 + leftTile = 179 + rightTile = 180 + tileset = 17 + if leftArea > 2: + leftTube = 226 + leftArea + else: + leftTube = 235 + leftArea + if rightArea > 2: + rightTube = 9 + rightArea + elif rightArea == 2: + rightTube = 4 + else: + rightTube = 1 + graph.patcher.update({ + 4857211: leftTube }) + graph.patcher.update({ + 4857224: leftTube + 16 }) + graph.patcher.update({ + 4856958: rightTube }) + graph.patcher.update({ + 4856975: rightTube + 16 }) + elif area == 2: + topTile = 20 + bottomTile = 36 + leftTile = 181 + rightTile = 182 + tileset = 35 + if leftArea > 2: + leftTube = 9 + leftArea + elif leftArea == 2: + leftTube = 4 + else: + leftTube = 1 + if rightArea > 2: + rightTube = 226 + rightArea + else: + rightTube = 235 + rightArea + graph.patcher.update({ + 5091931: leftTube }) + graph.patcher.update({ + 5091944: leftTube + 16 }) + graph.patcher.update({ + 5092202: rightTube }) + graph.patcher.update({ + 5092219: rightTube + 16 }) + elif area == 3: + topTile = 21 + bottomTile = 37 + leftTile = 183 + rightTile = 184 + tileset = 36 + if leftArea > 2: + leftTube = 226 + leftArea + else: + leftTube = 235 + leftArea + if rightArea > 2: + rightTube = 9 + rightArea + elif rightArea == 2: + rightTube = 4 + else: + rightTube = 1 + graph.patcher.update({ + 5254431: leftTube }) + graph.patcher.update({ + 5254447: leftTube + 16 }) + graph.patcher.update({ + 5254714: rightTube }) + graph.patcher.update({ + 5254731: rightTube + 16 }) + elif area == 4: + topTile = 51 + bottomTile = 67 + leftTile = 195 + rightTile = 196 + tileset = 37 + if leftArea > 2: + leftTube = 9 + leftArea + elif leftArea == 2: + leftTube = 4 + else: + leftTube = 1 + if rightArea > 2: + rightTube = 226 + rightArea + else: + rightTube = 235 + rightArea + graph.patcher.update({ + 5512395: leftTube }) + graph.patcher.update({ + 5512408: leftTube + 16 }) + graph.patcher.update({ + 5512134: rightTube }) + graph.patcher.update({ + 5512151: rightTube + 16 }) + elif area == 5: + topTile = 52 + bottomTile = 68 + leftTile = 197 + rightTile = 198 + tileset = 38 + if leftArea > 2: + leftTube = 226 + leftArea + else: + leftTube = 235 + leftArea + if rightArea > 2: + rightTube = 226 + rightArea + else: + rightTube = 235 + rightArea + graph.patcher.update({ + 5358711: leftTube }) + graph.patcher.update({ + 5358724: leftTube + 16 }) + graph.patcher.update({ + 5361542: rightTube }) + graph.patcher.update({ + 5361559: rightTube + 16 }) + elif area == 6: + topTile = 24 + bottomTile = 40 + leftTile = 199 + rightTile = 200 + tileset = 39 + if leftArea > 2: + leftTube = 226 + leftArea + else: + leftTube = 235 + leftArea + if rightArea > 2: + rightTube = 226 + rightArea + else: + rightTube = 235 + rightArea + graph.patcher.update({ + 5598427: leftTube }) + graph.patcher.update({ + 5598440: leftTube + 16 }) + graph.patcher.update({ + 5598706: rightTube }) + graph.patcher.update({ + 5598723: rightTube + 16 }) + if elevator == 0: + graph.patcher.update({ + 4669078: leftTile }) + graph.patcher.update({ + 4669079: rightTile }) + graph.patcher.update({ + 4669026: leftTile }) + graph.patcher.update({ + 4669027: rightTile }) + graph.patcher.update({ + 4670120: leftTile }) + graph.patcher.update({ + 4670121: rightTile }) + graph.patcher.update({ + 4670922: leftTile }) + graph.patcher.update({ + 4670923: rightTile }) + graph.patcher.update({ + 4671720: leftTile }) + graph.patcher.update({ + 4671721: rightTile }) + graph.patcher.update({ + 4672508: leftTile }) + graph.patcher.update({ + 4672509: rightTile }) + graph.patcher.update({ + 4673296: leftTile }) + graph.patcher.update({ + 4673297: rightTile }) + graph.patcher.update({ + 4674087: topTile }) + graph.patcher.update({ + 4674099: bottomTile }) + graph.patcher.update({ + 3945300: tileset }) + graph.patcher.update({ + 5713644: 171 + area }) + source = 'S0-47' + elif elevator == 1: + graph.patcher.update({ + 4669038: leftTile }) + graph.patcher.update({ + 4669039: rightTile }) + graph.patcher.update({ + 4669028: leftTile }) + graph.patcher.update({ + 4669029: rightTile }) + graph.patcher.update({ + 4670106: leftTile }) + graph.patcher.update({ + 4670107: rightTile }) + graph.patcher.update({ + 4670908: leftTile }) + graph.patcher.update({ + 4670909: rightTile }) + graph.patcher.update({ + 4671708: leftTile }) + graph.patcher.update({ + 4671709: rightTile }) + graph.patcher.update({ + 4672494: leftTile }) + graph.patcher.update({ + 4672495: rightTile }) + graph.patcher.update({ + 4674067: leftTile }) + graph.patcher.update({ + 4674068: rightTile }) + graph.patcher.update({ + 4673301: topTile }) + graph.patcher.update({ + 4673315: bottomTile }) + graph.patcher.update({ + 3945240: tileset }) + graph.patcher.update({ + 5713617: 171 + area }) + source = 'S0-45' + elif elevator == 2: + graph.patcher.update({ + 4669001: leftTile }) + graph.patcher.update({ + 4669002: rightTile }) + graph.patcher.update({ + 4669030: leftTile }) + graph.patcher.update({ + 4669031: rightTile }) + graph.patcher.update({ + 4670094: leftTile }) + graph.patcher.update({ + 4670095: rightTile }) + graph.patcher.update({ + 4670896: leftTile }) + graph.patcher.update({ + 4670897: rightTile }) + graph.patcher.update({ + 4671696: leftTile }) + graph.patcher.update({ + 4671697: rightTile }) + graph.patcher.update({ + 4673279: leftTile }) + graph.patcher.update({ + 4673280: rightTile }) + graph.patcher.update({ + 4674079: leftTile }) + graph.patcher.update({ + 4674080: rightTile }) + graph.patcher.update({ + 4672499: topTile }) + graph.patcher.update({ + 4672513: bottomTile }) + graph.patcher.update({ + 3945180: tileset }) + graph.patcher.update({ + 5713597: 171 + area }) + source = 'S0-43' + elif elevator == 3: + graph.patcher.update({ + 4669012: leftTile }) + graph.patcher.update({ + 4669013: rightTile }) + graph.patcher.update({ + 4669057: leftTile }) + graph.patcher.update({ + 4669058: rightTile }) + graph.patcher.update({ + 4670884: leftTile }) + graph.patcher.update({ + 4670885: rightTile }) + graph.patcher.update({ + 4671684: leftTile }) + graph.patcher.update({ + 4671685: rightTile }) + graph.patcher.update({ + 4672489: leftTile }) + graph.patcher.update({ + 4672490: rightTile }) + graph.patcher.update({ + 4673291: leftTile }) + graph.patcher.update({ + 4673292: rightTile }) + graph.patcher.update({ + 4674091: leftTile }) + graph.patcher.update({ + 4674092: rightTile }) + graph.patcher.update({ + 4670111: topTile }) + graph.patcher.update({ + 4670125: bottomTile }) + graph.patcher.update({ + 3945000: tileset }) + graph.patcher.update({ + 5713600: 171 + area }) + source = 'S0-44' + elif elevator == 4: + graph.patcher.update({ + 4669049: leftTile }) + graph.patcher.update({ + 4669050: rightTile }) + graph.patcher.update({ + 4669059: leftTile }) + graph.patcher.update({ + 4669060: rightTile }) + graph.patcher.update({ + 4670115: leftTile }) + graph.patcher.update({ + 4670116: rightTile }) + graph.patcher.update({ + 4671672: leftTile }) + graph.patcher.update({ + 4671673: rightTile }) + graph.patcher.update({ + 4672503: leftTile }) + graph.patcher.update({ + 4672504: rightTile }) + graph.patcher.update({ + 4673305: leftTile }) + graph.patcher.update({ + 4673306: rightTile }) + graph.patcher.update({ + 4674103: leftTile }) + graph.patcher.update({ + 4674104: rightTile }) + graph.patcher.update({ + 4670913: topTile }) + graph.patcher.update({ + 4670927: bottomTile }) + graph.patcher.update({ + 3945060: tileset }) + graph.patcher.update({ + 5713621: 171 + area }) + source = 'S0-46' + elif elevator == 5: + graph.patcher.update({ + 4669089: leftTile }) + graph.patcher.update({ + 4669090: rightTile }) + graph.patcher.update({ + 4669061: leftTile }) + graph.patcher.update({ + 4669062: rightTile }) + graph.patcher.update({ + 4670129: leftTile }) + graph.patcher.update({ + 4670130: rightTile }) + graph.patcher.update({ + 4670917: leftTile }) + graph.patcher.update({ + 4670918: rightTile }) + graph.patcher.update({ + 4672517: leftTile }) + graph.patcher.update({ + 4672518: rightTile }) + graph.patcher.update({ + 4673319: leftTile }) + graph.patcher.update({ + 4673320: rightTile }) + graph.patcher.update({ + 4674115: leftTile }) + graph.patcher.update({ + 4674116: rightTile }) + graph.patcher.update({ + 4671701: topTile }) + graph.patcher.update({ + 4671713: bottomTile }) + graph.patcher.update({ + 3945120: tileset }) + graph.patcher.update({ + 5713647: 171 + area }) + source = 'S0-48' + destination = 'S{}-00'.format(area) + graph.UpdateDoorConnection(source, destination) + graph.UpdateDoorConnection(destination, source) + source = areaDoors.get(area)[0] + destination = areaDoors.get(leftArea)[1] + graph.UpdateDoorConnection(source, destination) + source = areaDoors.get(area)[1] + destination = areaDoors.get(rightArea)[0] + graph.UpdateDoorConnection(source, destination) + graph.ConnectAllNodes() + PlacedETanks = PlacedMissiles = PlacedPowerBombs = 0 + if SeedSettings['DamageRuns']: + Energy = PlacedETanks * 100 + 99 + MissileCount = 10 + locationWeights.clear() + locationsPerArea.clear() + areaWeights.clear() + weightValue.clear() + MajorLocations.clear() + MinorLocations.clear() + AllItemLocations.clear() + newLocations.clear() + AccessibleLocations.clear() + UsedLocations.clear() + PlacedItems.clear() + NettoriOpen = False + invalidItems.clear() + invalidWeights.clear() + oldLocations.clear() + oldWeights.clear() + MajorLocations.extend(graph.majorItemLocations) + if SeedSettings['MajorMinor'] == False: + MajorLocations.extend(graph.minorItemLocations) + MinorLocations.extend(graph.minorItemLocations) + AllItemLocations.extend(graph.majorItemLocations) + AllItemLocations.extend(graph.minorItemLocations) + random.shuffle(MajorLocations) + random.shuffle(MinorLocations) + random.shuffle(AllItemLocations) + for item in MajorItems: + disable_item(graph, item) + disable_item(graph, 'BlueDoors') + disable_item(graph, 'GreenDoors') + disable_item(graph, 'YellowDoors') + disable_item(graph, 'RedDoors') + disable_item(graph, 'WaterLowered') + for area in range(0, 7): + AreaOpen[area] = None + locationsPerArea.append(list()) + areaWeights.append(1) + weightValue.append(1) + MajorList = list(WeightedMajors.keys()) + if SeedSettings['MissilesWithoutMainData']: + WeightedMajors.update({ + 'MainMissiles': 8 }) + WeightedMajors.update({ + 'SuperMissileItem': 8 }) + WeightedMajors.update({ + 'IceMissileItem': 8 }) + WeightedMajors.update({ + 'DiffusionItem': 8 }) + if SeedSettings['PowerBombsWithoutBombs']: + WeightedMajors.update({ + 'Bombs': 10 }) + WeightedMajors.update({ + 'MainPowerBombs': 10 }) + if SeedSettings['DamageRuns']: + WeightedMajors.update({ + 'VariaSuit': 4 }) + MajorWeights = list(WeightedMajors.values()) + MajorWeights.pop(MajorList.index('Bombs')) + MajorList.remove('Bombs') + MajorWeights.pop(MajorList.index('MainPowerBombs')) + MajorList.remove('MainPowerBombs') + if SeedSettings['MissilesWithoutMainData'] == False: + MajorWeights.pop(MajorList.index('IceMissileItem')) + MajorList.remove('IceMissileItem') + MajorWeights.pop(MajorList.index('SuperMissileItem')) + MajorList.remove('SuperMissileItem') + MajorWeights.pop(MajorList.index('DiffusionItem')) + MajorList.remove('DiffusionItem') + if weightInit == False: + availableItems.clear() + path = None + for location in MajorLocations: + path = graph.get_path(StartLocation, location) + if path != None: + pass + + if path == None: + print('No accessible locations found with this start, try changing your game settings.') + sys.exit(1) + else: + for item in MajorItems: + enable_item(graph, item) + currentItemWeight = 0 + find_available_areas(graph) + for location in MajorLocations: + path = graph.get_path(StartLocation, location) + if path != None: + currentItemWeight += 1 + if currentItemWeight > 1: + availableItems.append(item) + + for area in range(0, 7): + AreaOpen[area] = None + disable_item(graph, item) + disable_item(graph, 'WaterLowered') + disable_item(graph, 'BlueDoors') + disable_item(graph, 'GreenDoors') + disable_item(graph, 'YellowDoors') + disable_item(graph, 'RedDoors') + continue + weightInit = True + if len(availableItems) < 1: + print('No accessible locations found with this start, try changing your game settings.') + sys.exit(1) + find_available_areas(graph) + for location in MajorLocations: + path = graph.get_path(StartLocation, location) + if path != None: + AccessibleLocations.append(location) + for area in range(0, 7): + if location in AreaItemLocations[area] and location not in locationsPerArea[area]: + locationsPerArea[area].append(location) + continue + continue + for area in range(0, 7): + if len(locationsPerArea[area]) > 0: + areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) + continue + for location in AccessibleLocations: + for area in range(0, 7): + if location in AreaItemLocations[area]: + locationWeights.append(areaWeights[area]) + continue + continue + if FirstItem == None: + FirstItem = random.choice(availableItems) + MajorWeights.pop(MajorList.index(FirstItem)) + MajorList.remove(FirstItem) + enable_item(graph, FirstItem) + path = None + if SeedSettings['DamageRuns']: + Energy = Energy / 2 + if path == None: + location = random.choice(AccessibleLocations) + path = graph.get_path(location, StartLocation) + if path != None: + locationWeights.pop(AccessibleLocations.index(location)) + AccessibleLocations.remove(location) + UsedLocations.append(location) + PlacedItems.append(FirstItem) + for area in range(0, 7): + if location not in AreaItemLocations[area]: + weightValue[area] += 1 + continue + continue + if FirstItem == 'MainMissiles' or SeedSettings['MissilesWithoutMainData'] == False: + MajorList.append('IceMissileItem') + MajorWeights.append(WeightedMajors.get('IceMissileItem')) + MajorList.append('SuperMissileItem') + MajorWeights.append(WeightedMajors.get('SuperMissileItem')) + MajorList.append('DiffusionItem') + MajorWeights.append(WeightedMajors.get('DiffusionItem')) + elif FirstItem == 'MorphBall': + MajorList.append('Bombs') + MajorWeights.append(WeightedMajors.get('Bombs')) + if SeedSettings['PowerBombsWithoutBombs'] == True: + MajorList.append('MainPowerBombs') + MajorWeights.append(WeightedMajors.get('MainPowerBombs')) + elif FirstItem == 'Bombs' and SeedSettings['PowerBombsWithoutBombs'] == False: + MajorList.append('MainPowerBombs') + MajorWeights.append(WeightedMajors.get('MainPowerBombs')) + init = True + if SeedSettings['DamageRuns']: + Energy = PlacedETanks * 100 + 99 + find_available_areas(graph) + path = graph.get_path(StartLocation, 'End-of-Game') + if path != None: + path = graph.get_path('End-of-Game', 'S0-00') + if path != None: + gameBeatable = True + if gameBeatable == False: + newLocations.clear() + locationWeights.clear() + for location in MajorLocations: + path = None + if location not in UsedLocations and location not in AccessibleLocations or location == 'Data S0' or location == 'Item S0-05-16': + path = graph.get_path(location, StartLocation, 250, **('depth',)) + else: + for area in range(0, 7): + if location in AreaItemLocations[area] and AreaOpen[area]: + path = graph.get_path(AreaOpen[area], location, True) + + if path != None: + AccessibleLocations.append(location) + MajorLocations.remove(location) + newLocations.append(location) + for area in range(0, 7): + if location in AreaItemLocations[area] and location not in locationsPerArea[area]: + locationsPerArea[area].append(location) + continue + continue + for area in range(0, 7): + if len(locationsPerArea[area]) > 0 or SeedSettings['MajorMinor']: + areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) + else: + areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) + area + for location in AccessibleLocations: + for area in range(0, 7): + if location in AreaItemLocations[area] or location in newLocations: + locationWeights.append(areaWeights[area] * 1.8) + elif location in BossLocations and SeedSettings['MajorMinor'] == False: + locationWeights.append(areaWeights[area] * 1.5) + else: + locationWeights.append(areaWeights[area]) + if len(MajorList) > 0: + itemLocation = None + path = None + item = random.choices(MajorList, MajorWeights, 1, **('weights', 'k'))[0] + currentItemWeight = MajorWeights.pop(MajorList.index(item)) + MajorList.remove(item) + enable_item(graph, item) + if SeedSettings['DamageRuns']: + Energy = Energy / 2 + if path == None and len(AccessibleLocations) > 0: + itemLocation = random.choices(AccessibleLocations, locationWeights, 1, **('weights', 'k'))[0] + oldLocationWeight = locationWeights.pop(AccessibleLocations.index(itemLocation)) + AccessibleLocations.remove(itemLocation) + if itemLocation == 'Data S0' or itemLocation == 'Item S0-05-16': + path = graph.get_path(itemLocation, StartLocation, 250, **('depth',)) + else: + for area in range(0, 7): + if itemLocation in AreaItemLocations[area] and AreaOpen[area]: + path = graph.get_path(itemLocation, AreaOpen[area], True) + + if itemLocation in BossLocations and path != None: + disable_item(graph, item) + if ChargeBeam == False and SeedSettings['Difficulty'] > 0: + healthCheck = BossHealths.get(itemLocation) + if SeedSettings['Difficulty'] > 4: + healthCheck = healthCheck * 1.02 + elif SeedSettings['Difficulty'] > 2: + healthCheck = healthCheck * 1.05 + else: + healthCheck = healthCheck * 1.1 + healthCheck = healthCheck - MissileDamage * MissileCount + if healthCheck > 0: + if MissileDamage > 0: + tankCheck = math.ceil(healthCheck / MissileDamage / 5) + PossibleMissileTanks.clear() + if SeedSettings['MajorMinor']: + for missileLocation in MinorLocations: + if missileLocation not in UsedLocations: + missilePath = None + if missileLocation == 'Item S0-05-16': + missilePath = graph.get_path(StartLocation, missileLocation, 250, **('depth',)) + if missilePath != None: + missilePath = graph.get_path(missileLocation, StartLocation, 250, **('depth',)) + else: + for area in range(0, 7): + if missileLocation in AreaItemLocations[area] and AreaOpen[area]: + missilePath = graph.get_path(AreaOpen[area], missileLocation, True) + if missilePath != None: + missilePath = graph.get_path(missileLocation, AreaOpen[area], True) + + if missilePath != None: + PossibleMissileTanks.append(missileLocation) + continue + else: + for missileLocation in AccessibleLocations: + missilePath = None + if missileLocation == 'Data S0' or missileLocation == 'Item S0-05-16': + missilePath = graph.get_path(missileLocation, StartLocation, 250, **('depth',)) + else: + for area in range(0, 7): + if missileLocation in AreaItemLocations[area] and AreaOpen[area]: + missilePath = graph.get_path(missileLocation, AreaOpen[area], True) + + if missilePath != None and missileLocation not in BossLocations: + PossibleMissileTanks.append(missileLocation) + continue + if len(PossibleMissileTanks) > int(tankCheck): + for x in range(0, int(tankCheck)): + missileLocation = random.choice(PossibleMissileTanks) + PossibleMissileTanks.remove(missileLocation) + if SeedSettings['MajorMinor'] == False: + locationWeights.pop(AccessibleLocations.index(missileLocation)) + AccessibleLocations.remove(missileLocation) + UsedLocations.append(missileLocation) + PlacedItems.append('Missile Tank') + PlacedMissiles += 1 + MissileCount = 10 + PlacedMissiles * 5 + update_items(graph) + else: + path = None + else: + path = None + enable_item(graph, item) + if path == None: + oldLocations.append(itemLocation) + oldWeights.append(oldLocationWeight) + continue + if path == None: + if len(MajorList) > 0 and len(PlacedItems) > 4: + invalidItems.append(item) + invalidWeights.append(currentItemWeight) + AccessibleLocations.extend(oldLocations) + oldLocations.clear() + locationWeights.extend(oldWeights) + oldWeights.clear() + disable_item(graph, item) + else: + for item in MajorItems: + disable_item(graph, item) + print("Couldn't find a path forward, trying again") + init = False + else: + UsedLocations.append(itemLocation) + PlacedItems.append(item) + MajorList.extend(invalidItems) + invalidItems.clear() + MajorWeights.extend(invalidWeights) + invalidWeights.clear() + AccessibleLocations.extend(oldLocations) + oldLocations.clear() + locationWeights.extend(oldWeights) + oldWeights.clear() + for area in range(0, 7): + if itemLocation in locationsPerArea[area]: + locationsPerArea[area].remove(itemLocation) + if itemLocation not in AreaItemLocations[area]: + weightValue[area] += 1 + continue + if item == 'MainMissiles' or SeedSettings['MissilesWithoutMainData'] == False: + MajorList.append('IceMissileItem') + MajorWeights.append(WeightedMajors.get('IceMissileItem')) + MajorList.append('SuperMissileItem') + MajorWeights.append(WeightedMajors.get('SuperMissileItem')) + MajorList.append('DiffusionItem') + MajorWeights.append(WeightedMajors.get('DiffusionItem')) + elif item == 'MorphBall': + MajorList.append('Bombs') + MajorWeights.append(WeightedMajors.get('Bombs')) + if SeedSettings['PowerBombsWithoutBombs'] == True: + MajorList.append('MainPowerBombs') + MajorWeights.append(WeightedMajors.get('MainPowerBombs')) + elif item == 'Bombs' and SeedSettings['PowerBombsWithoutBombs'] == False: + MajorList.append('MainPowerBombs') + MajorWeights.append(WeightedMajors.get('MainPowerBombs')) + if SeedSettings['MajorMinor'] == False and len(AccessibleLocations) > 3 and PlacedETanks < MaxETanks: + itemLocation = random.choice(AccessibleLocations) + locationWeights.pop(AccessibleLocations.index(itemLocation)) + AccessibleLocations.remove(itemLocation) + UsedLocations.append(itemLocation) + PlacedItems.append('Energy Tank') + PlacedETanks += 1 + else: + for item in MajorItems: + disable_item(graph, item) + print("Couldn't find a path forward, trying again") + init = False + # continue + print('Game is beatable, placing remaining items (no logic)') + for item in MajorItems: + if item not in PlacedItems and item not in MajorList: + MajorList.append(item) + MajorWeights.append(WeightedMajors.get(item)) + continue + MajorLocations.extend(AccessibleLocations) + for item in MajorList: + if item not in PlacedItems: + location = random.choice(MajorLocations) + if location in UsedLocations: + MajorLocations.remove(location) + location = random.choice(MajorLocations) + continue + UsedLocations.append(location) + PlacedItems.append(item) + if SeedSettings['MajorMinor']: + for location in MajorLocations: + if PlacedETanks < MaxETanks and location not in UsedLocations: + UsedLocations.append(location) + PlacedItems.append(MinorItems[0]) + PlacedETanks += 1 + continue + MaxETanks = PlacedETanks + if PlacedETanks >= MaxETanks: + MinorItems.remove('Energy Tank') + if PlacedMissiles >= MaxMissiles: + MinorItems.remove('Missile Tank') + if PlacedPowerBombs >= MaxPowerBombs: + MinorItems.remove('Power Bomb Tank') + for location in AllItemLocations: + if len(MinorItems) > 0 and location not in UsedLocations: + item = random.choice(MinorItems) + UsedLocations.append(location) + PlacedItems.append(item) + if item == 'Energy Tank': + PlacedETanks += 1 + if PlacedETanks >= MaxETanks: + MinorItems.remove('Energy Tank') + elif item == 'Missile Tank': + PlacedMissiles += 1 + if PlacedMissiles >= MaxMissiles: + MinorItems.remove('Missile Tank') + elif item == 'Power Bomb Tank': + PlacedPowerBombs += 1 + if PlacedPowerBombs >= MaxPowerBombs: + MinorItems.remove('Power Bomb Tank') + continue + patch_game() + continue + return None + + +def patch_game(): + global FileName, FileName, FileName + CreditsOffsets = { + 'ChargeBeam': 7655617, + 'WideBeam': 7655725, + 'PlasmaBeam': 7655833, + 'WaveBeam': 7655941, + 'IceBeam': 7656049, + 'MainMissiles': 7656157, + 'SuperMissileItem': 7656265, + 'IceMissileItem': 7656373, + 'DiffusionItem': 7656481, + 'Bombs': 7656589, + 'MainPowerBombs': 7656697, + 'MorphBall': 7656805, + 'HiJumpBoots': 7656913, + 'SpeedBooster': 7657021, + 'SpaceJump': 7657129, + 'ScrewAttack': 7657237, + 'VariaSuit': 7657345, + 'GravitySuit': 7657453, + 'GreenDoors': 7657561, + 'BlueDoors': 7657669, + 'YellowDoors': 7657777, + 'RedDoors': 7657885 } + print('Patching game, please wait') + HashValue = random.sample(HashList, 4) + FileName = 'MFOR -' + if Debug: + FileName = 'Debug -' + for x in HashValue: + FileName = FileName + ' {}'.format(x) + if Debug: + os.system('.\\armips\\armips.exe "Metroid Fusion Open Randomizer.asm" -root ".\\data\\asm" -sym ".\\temp.sym"') + os.replace('.\\data\\MFOR.gba', '.\\seeds\\{}.gba'.format(FileName)) + else: + # FIXME: windows? + os.system(os.path.join('.', 'flips', 'flips') + ' --apply ' + os.path.join('.', 'data', 'MFOR.bps') + ' "' + BaseName + '" "'+ os.path.join('.', 'seeds', '{}.gba'.format(FileName)) + '"') + checksum = fileHash(os.path.join('.', 'seeds', '{}.gba'.format(FileName))) + # if checksum != 0x92561217L: + if checksum != 0: + os.remove(os.path.join('.', 'seeds', '{}.gba'.format(FileName))) + print('Error: Base patch file has been modified. Please go to https://metroidconstruction.com/ and re-download MFOR.') + sys.exit(1) +# WARNING: Decompyle incomplete + + +def initialize(): + global HashList, HashList + HashList = list() +# WARNING: Decompyle incomplete + + +def start_randomizer(rom, settings): + global BaseGame, Debug, SeedValue, SeedValue, Patch, Patch, SeedSettings, SeedValue, Difficulty, DamageRuns, World, AreaItemLocations, RoomNodes + print('DEBUG: entered start_randomizer') + BaseGame = rom + print(BaseGame) + if BaseGame == None or BaseGame == '': + print('Error: no base game provided.') + sys.exit(1) + checksum = fileHash(BaseGame) + # if checksum != 1819625372: + if checksum != 0: + print('Only Metroid Fusion (U) is supported. Check the CRC32 value: it should be 6C75479C') + sys.exit(1) + Debug = settings['Debug'] + settings.pop('Debug') + if Debug == False: + checksum = fileHash(os.path.join('.', 'data', 'MFOR.bps')) + # if checksum != 558161692: + if checksum != 0: + print('Error: Base patch file has been modified. Please go to https://metroidconstruction.com/ and re-download MFOR.') + sys.exit(1) + totalRandoTime = time.time() + if settings['Seed']: + SeedValue = str(settings['Seed']).strip(' \n') + else: + SeedValue = str(random.randrange(sys.maxsize)) + print(SeedValue) + settings.pop('Seed') + repeat = 1 + if settings['Num'] and settings['Num'] > repeat: + repeat = settings['Num'] + settings.pop('Num') + if settings['Patch']: + Patch = True + else: + Patch = False + settings.pop('Patch') + patch_game() + +# WARNING: Decompyle incomplete + diff --git a/data/MFOR.bps b/data/MFOR.bps new file mode 100644 index 0000000000000000000000000000000000000000..795f2191c9e264c118696ec339783e9b23454050 GIT binary patch literal 15877 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