OpenMFOR/Randomizer.py

3143 lines
186 KiB
Python

# OpenMFOR
# credits manually reinstated due to the comments being lost from the object code decompilation
# Original release is Copyright (C) 2022 Kazuto88
# 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.
# 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 *
from bps.apply import apply_to_files
from bps.diff import diff_bytearrays
from bps.io import write_bps
from bps.util import bps_progress
version = '0.11.6'
# FIXME: Debug should not be set here
# Debug = False
def ceiling(num, denom):
return -(num // -denom)
def fileHash(file):
checksum = 0
try:
with open(file, 'rb') as source:
while True:
s = source.read(65536)
if not s:
break
checksum = zlib.crc32(s, checksum)
except FileNotFoundError:
sys.exit('Error:', file, 'could not be opened.')
return checksum & 0xFFFFFFFF
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 BombJump
global Diffusion
global HiJump
global IBJ
global Ice
global IceMissiles
global MissileDamage
global Missiles
global PowerBombs
global SpringBall
global SuperMissiles
global UseBombs
global WallJump
if SeedSettings['MissilesWithoutMainData'] == True:
Missiles = MainMissiles or SuperMissileItem or IceMissileItem or DiffusionItem
else:
Missiles = MainMissiles
SuperMissiles = Missiles and SuperMissileItem
IceMissiles = Missiles and IceMissileItem
Diffusion = Missiles and DiffusionItem
Ice = IceMissiles or IceBeam
HiJump = HiJumpBoots or SpaceJump
SpringBall = HiJumpBoots
WallJump = SpaceJump or WallJumpSetting
if SeedSettings['PowerBombsWithoutBombs'] == True:
PowerBombs = MorphBall and MainPowerBombs
else:
PowerBombs = MorphBall and Bombs and MainPowerBombs
UseBombs = MorphBall and (Bombs or PowerBombs)
BombJump = MorphBall and (Bombs or SpringBall)
IBJ = MorphBall and Bombs and 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):
graph.requirements = {
('S0-06', 'S0-0B'): GreenDoors,
('S0-08', 'S0-0A'): Impossible,
('S0-08', 'S0-0C'): Impossible,
('S0-08', 'S0-0D'): MorphBall and 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'): MorphBall and PowerBombs,
('S0-0D', 'S0-0A'): Impossible,
('S0-0D', 'S0-0C'): Impossible,
('S0-0D', 'S0-0F'): MorphBall and PowerBombs and RedDoors,
('S0-0D', 'S0-11'): MorphBall and PowerBombs,
('S0-0F', 'S0-0A'): Impossible,
('S0-0F', 'S0-0C'): Impossible,
('S0-0F', 'S0-0D'): MorphBall and PowerBombs,
('S0-11', 'S0-0A'): Impossible,
('S0-11', 'S0-0C'): Impossible,
('S0-11', 'S0-0D'): MorphBall and PowerBombs,
('S0-11', 'S0-0F'): RedDoors,
('S0-0E', 'S0-6C'): MorphBall and PowerBombs,
('S0-6C', 'S0-0E'): MorphBall and PowerBombs or SpeedBooster,
('S0-6C', 'S0-13'): MorphBall and PowerBombs or SpeedBooster,
('S0-13', 'S0-6C'): MorphBall and PowerBombs,
('S0-53', 'S0-56'): Missiles or ChargeBeam,
('S0-54', 'S0-56'): Missiles or ChargeBeam,
('S0-55', 'S0-56'): Missiles or ChargeBeam,
('S0-16', 'S0-1B'): Missiles,
('S0-16', 'S0-41'): Missiles,
('S0-16', 'S0-8D'): Missiles,
('S0-16', 'S0-C1'): Missiles and RedDoors and (HiJump or WallJump or IBJ),
('S0-1B', 'S0-16'): Missiles,
('S0-1B', 'S0-C1'): RedDoors and (HiJump or WallJump or IBJ),
('S0-41', 'S0-16'): Missiles,
('S0-41', 'S0-C1'): RedDoors and (HiJump or WallJump or IBJ),
('S0-8D', 'S0-16'): Missiles,
('S0-8D', 'S0-C1'): RedDoors and (HiJump or WallJump or 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'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-1E', 'S0-9E'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-1F', 'S0-1E'): GreenDoors,
('S0-1F', 'S0-9D'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-1F', 'S0-9E'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-9D', 'S0-1E'): GreenDoors,
('S0-9D', 'S0-1F'): GreenDoors,
('S0-9D', 'S0-9E'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-9E', 'S0-1E'): GreenDoors,
('S0-9E', 'S0-1F'): GreenDoors,
('S0-9E', 'S0-9D'): GreenDoors and (HiJump and Ice or Missiles or ChargeBeam) and (SpaceJump or WallJump or IBJ),
('S0-15', 'S0-84'): PowerBombs and GreenDoors,
('S0-15', 'S0-CB'): MorphBall and (UseBombs or ScrewAttack),
('S0-24', 'S0-15'): GreenDoors,
('S0-24', 'S0-84'): PowerBombs and GreenDoors,
('S0-24', 'S0-CB'): MorphBall and (UseBombs or ScrewAttack),
('S0-26', 'S0-15'): GreenDoors,
('S0-26', 'S0-84'): PowerBombs and GreenDoors,
('S0-26', 'S0-CB'): MorphBall and (UseBombs or ScrewAttack),
('S0-27', 'S0-15'): GreenDoors,
('S0-27', 'S0-84'): PowerBombs and GreenDoors,
('S0-27', 'S0-CB'): MorphBall and (UseBombs or ScrewAttack),
('S0-84', 'S0-15'): GreenDoors,
('S0-84', 'S0-CB'): MorphBall and (UseBombs or ScrewAttack),
('S0-CB', 'S0-15'): MorphBall and UseBombs and GreenDoors,
('S0-CB', 'S0-24'): MorphBall and UseBombs,
('S0-CB', 'S0-26'): MorphBall and UseBombs,
('S0-CB', 'S0-27'): MorphBall and UseBombs,
('S0-CB', 'S0-84'): MorphBall and PowerBombs and GreenDoors,
('S0-2A', 'S0-A8'): MorphBall,
('S0-2A', 'S0-CA'): MorphBall and ScrewAttack and BombJump and (HiJump or WallJump or IBJ),
('S0-A8', 'S0-2A'): MorphBall,
('S0-A8', 'S0-CA'): MorphBall and ScrewAttack and BombJump and (HiJump or WallJump or IBJ),
('S0-A8', 'S0-2B'): MorphBall,
('S0-A8', 'S0-68'): MorphBall,
('S0-CA', 'S0-2A'): MorphBall and ScrewAttack and BombJump,
('S0-CA', 'S0-A8'): MorphBall and ScrewAttack and BombJump,
('S0-CA', 'S0-2B'): MorphBall and ScrewAttack and BombJump,
('S0-CA', 'S0-68'): MorphBall and ScrewAttack and BombJump,
('S0-2B', 'S0-A8'): MorphBall,
('S0-2B', 'S0-CA'): MorphBall and ScrewAttack and BombJump and (HiJump or WallJump or IBJ),
('S0-68', 'S0-A8'): MorphBall,
('S0-68', 'S0-CA'): MorphBall and ScrewAttack and BombJump and (HiJump or WallJump or IBJ),
('S0-1D', 'S0-2C'): Missiles or PowerBombs or ScrewAttack,
('S0-1D', 'S0-2D'): Missiles or PowerBombs or ScrewAttack,
('S0-1D', 'S0-5B'): Missiles or PowerBombs or ScrewAttack,
('S0-2C', 'S0-1D'): Missiles or PowerBombs or ScrewAttack,
('S0-2D', 'S0-1D'): Missiles or PowerBombs or ScrewAttack,
('S0-5B', 'S0-1D'): Missiles or PowerBombs or ScrewAttack,
('S0-2F', 'S0-2E'): Ice or ((Missiles or ChargeBeam or ScrewAttack) and (SpaceJump or WallJump or IBJ)),
('S0-30', 'S0-4A'): MorphBall or (SpeedBooster and Difficulty >= 2),
('S0-4A', 'S0-30'): MorphBall or SpeedBooster,
('S0-4A', 'S0-A6'): MorphBall or SpeedBooster,
('S0-A6', 'S0-4A'): MorphBall or (SpeedBooster and 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'): (Missiles or ChargeBeam) and MorphBall and BombJump,
('S0-69', 'S0-40'): Impossible,
('S0-4E', 'S0-4F'): Impossible,
('S0-4F', 'S0-4E'): Missiles or PowerBombs or ScrewAttack,
('S0-4F', 'S0-65'): Missiles or PowerBombs or 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'): Missiles or ChargeBeam,
('S0-6D', 'S0-6F'): MorphBall and RedDoors,
('S0-6E', 'S0-6D'): RedDoors,
('S0-6E', 'S0-6F'): MorphBall and PowerBombs,
('S0-6F', 'S0-6D'): MorphBall and RedDoors,
('S0-6F', 'S0-6E'): MorphBall and PowerBombs,
('S0-70', 'S0-7D'): MorphBall and UseBombs and (SpaceJump or WallJump or IBJ),
('S0-7D', 'S0-70'): MorphBall and UseBombs,
('S0-7D', 'S0-71'): MorphBall and UseBombs,
('S0-7D', 'S0-7C'): MorphBall and UseBombs,
('S0-7D', 'S0-82'): MorphBall and UseBombs,
('S0-71', 'S0-7D'): MorphBall and UseBombs and (SpaceJump or WallJump or IBJ),
('S0-7C', 'S0-7D'): MorphBall and UseBombs and (SpaceJump or WallJump or IBJ),
('S0-82', 'S0-7D'): MorphBall and UseBombs and (SpaceJump or WallJump or IBJ),
('S0-77', 'S0-76'): WaveBeam,
('S0-7E', 'S0-7F'): MorphBall and UseBombs,
('S0-7F', 'S0-7E'): MorphBall and UseBombs,
('S0-86', 'S0-87'): MorphBall and (SpaceJump or IBJ),
('S0-87', 'S0-86'): MorphBall and (SpaceJump or IBJ),
('S0-87', 'S0-88'): MorphBall and UseBombs,
('S0-87', 'S0-89'): MorphBall and UseBombs,
('S0-87', 'S0-8A'): MorphBall and UseBombs,
('S0-88', 'S0-86'): SpaceJump or IBJ,
('S0-88', 'S0-87'): MorphBall and (SpaceJump or IBJ),
('S0-89', 'S0-86'): SpaceJump or IBJ,
('S0-89', 'S0-87'): MorphBall and (SpaceJump or IBJ),
('S0-8A', 'S0-86'): SpaceJump or IBJ,
('S0-8A', 'S0-87'): MorphBall and (SpaceJump or IBJ),
('S0-8F', 'S0-90'): MorphBall and RedDoors,
('S0-90', 'S0-8F'): MorphBall and ScrewAttack and (SpaceJump or 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'): SpeedBooster or 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'): SpeedBooster or 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'): Missiles and ChargeBeam and PlasmaBeam,
('S0-CC', 'S0-92'): Missiles and ChargeBeam and PlasmaBeam and RedDoors and (HiJump or WallJump or 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'): Missiles or SpeedBooster or PowerBombs or ScrewAttack,
('S1-0A', 'S1-09'): Missiles or SpeedBooster or PowerBombs or ScrewAttack,
('S1-0B', 'S1-0C'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 3),
('S1-0C', 'S1-0B'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 3),
('S1-17', 'S1-58'): Missiles and MorphBall or ChargeBeam or PowerBombs or ScrewAttack,
('S1-58', 'S1-17'): Missiles and MorphBall or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 3),
('S1-18', 'S1-5C'): Missiles and MorphBall,
('S1-5C', 'S1-18'): Missiles and MorphBall,
('S1-5C', 'S1-54'): Missiles and MorphBall,
('S1-54', 'S1-5C'): Missiles and MorphBall,
('S1-1D', 'S1-1E'): Missiles or ChargeBeam or PowerBombs or ScrewAttack,
('S1-1E', 'S1-1D'): Missiles or ChargeBeam or PowerBombs or ScrewAttack,
('S1-16', 'S1-59'): WaveBeam,
('S1-20', 'S1-21'): Missiles or ChargeBeam or PowerBombs or ScrewAttack,
('S1-20', 'S1-4B'): Missiles or ChargeBeam or PowerBombs or ScrewAttack,
('S1-21', 'S1-20'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 4),
('S1-21', 'S1-4B'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 4),
('S1-4B', 'S1-20'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 4),
('S1-4B', 'S1-21'): Missiles or ChargeBeam or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 4),
('S1-22', 'S1-23'): ScrewAttack,
('S1-23', 'S1-22'): SpaceJump and ScrewAttack,
('S1-23', 'S1-5E'): SpaceJump and ScrewAttack,
('S1-5E', 'S1-23'): ScrewAttack,
('S1-24', 'S1-25'): DamageRuns and Energy >= 199 or GravitySuit,
('S1-25', 'S1-24'): (DamageRuns and Energy >= 99 or GravitySuit) and GreenDoors,
('S1-26', 'S1-27'): MorphBall and ScrewAttack,
('S1-27', 'S1-26'): MorphBall and ScrewAttack,
('S1-2A', 'S1-2B'): (DamageRuns and Energy >= 99 or GravitySuit) and GreenDoors,
('S1-2A', 'S1-6A'): MorphBall and ScrewAttack,
('S1-2B', 'S1-2A'): (DamageRuns and Energy >= 99 or GravitySuit) and BlueDoors,
('S1-2B', 'S1-6A'): (DamageRuns and Energy >= 99 or GravitySuit) and MorphBall and ScrewAttack,
('S1-6A', 'S1-2A'): MorphBall and ScrewAttack and BlueDoors,
('S1-6A', 'S1-2B'): (DamageRuns and Energy >= 99 or GravitySuit) and MorphBall and ScrewAttack and GreenDoors,
('S1-2D', 'S1-2E'): Missiles and MorphBall and UseBombs,
('S1-2D', 'S1-2F'): MorphBall and UseBombs,
('S1-2D', 'S1-5F'): MorphBall and UseBombs,
('S1-2D', 'S1-6E'): MorphBall and UseBombs,
('S1-2E', 'S1-2D'): Missiles and MorphBall and UseBombs,
('S1-2E', 'S1-2F'): Missiles and MorphBall,
('S1-2E', 'S1-5F'): Missiles and MorphBall,
('S1-2E', 'S1-6E'): Missiles and MorphBall,
('S1-2F', 'S1-2D'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-2F', 'S1-2E'): Missiles and MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-5F', 'S1-2D'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-5F', 'S1-2E'): Missiles and MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-6E', 'S1-2D'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-6E', 'S1-2E'): Missiles and MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S1-30', 'S1-31'): MorphBall and UseBombs and (PowerBombs or WaveBeam) and (Missiles or ChargeBeam or ScrewAttack),
('S1-31', 'S1-30'): MorphBall and UseBombs,
('S1-38', 'S1-39'): Missiles or ChargeBeam,
('S1-3B', 'S1-29'): WaveBeam,
('S1-3E', 'S1-3F'): MorphBall and ScrewAttack and (SpaceJump or WallJump),
('S1-3F', 'S1-3E'): MorphBall and ScrewAttack and (SpaceJump or 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'): MorphBall and UseBombs,
('S1-49', 'S1-48'): Missiles or ChargeBeam,
('S1-07', 'S1-08'): MorphBall and SpaceJump and ScrewAttack,
('S1-08', 'S1-07'): MorphBall and WaveBeam and SpaceJump and ScrewAttack,
('S1-19', 'S1-4D'): MorphBall,
('S1-19', 'S1-53'): (Missiles or ChargeBeam) and MorphBall,
('S1-19', 'S1-64'): MorphBall and UseBombs,
('S1-4D', 'S1-19'): Impossible,
('S1-4D', 'S1-53'): Missiles or ChargeBeam,
('S1-4D', 'S1-64'): MorphBall and UseBombs,
('S1-53', 'S1-19'): Impossible,
('S1-53', 'S1-64'): MorphBall and UseBombs,
('S1-64', 'S1-19'): Impossible,
('S1-64', 'S1-4D'): MorphBall and UseBombs,
('S1-64', 'S1-53'): (Missiles or ChargeBeam) and MorphBall and UseBombs,
('S1-4F', 'S1-50'): MorphBall,
('S1-50', 'S1-4F'): MorphBall,
('S1-6F', 'S1-70'): (ChargeBeam and WaveBeam or PowerBombs) and (Missiles or ScrewAttack),
('S1-70', 'S1-6F'): HiJump,
('S2-01', 'S2-03'): MorphBall and PowerBombs,
('S2-01', 'S2-04'): BlueDoors,
('S2-01', 'S2-20'): MorphBall and UseBombs,
('S2-03', 'S2-01'): MorphBall and PowerBombs,
('S2-03', 'S2-04'): MorphBall and PowerBombs and BlueDoors,
('S2-03', 'S2-20'): MorphBall and PowerBombs,
('S2-03', 'S2-02'): MorphBall and PowerBombs,
('S2-03', 'S2-05'): MorphBall and PowerBombs,
('S2-03', 'S2-0F'): MorphBall and PowerBombs,
('S2-04', 'S2-03'): MorphBall and PowerBombs,
('S2-04', 'S2-20'): MorphBall and UseBombs,
('S2-20', 'S2-01'): MorphBall and UseBombs,
('S2-20', 'S2-03'): MorphBall and PowerBombs,
('S2-20', 'S2-04'): MorphBall and UseBombs and BlueDoors,
('S2-20', 'S2-02'): MorphBall and UseBombs,
('S2-20', 'S2-05'): MorphBall and UseBombs,
('S2-20', 'S2-0F'): MorphBall and UseBombs,
('S2-02', 'S2-03'): MorphBall and PowerBombs,
('S2-02', 'S2-04'): BlueDoors,
('S2-02', 'S2-20'): MorphBall and UseBombs,
('S2-05', 'S2-03'): MorphBall and PowerBombs,
('S2-05', 'S2-04'): BlueDoors,
('S2-05', 'S2-20'): MorphBall and UseBombs,
('S2-0F', 'S2-03'): MorphBall and PowerBombs,
('S2-0F', 'S2-04'): BlueDoors,
('S2-0F', 'S2-20'): MorphBall and 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'): ScrewAttack and BlueDoors,
('S2-80', 'S2-3C'): ScrewAttack,
('S2-3C', 'S2-3A'): BlueDoors,
('S2-3C', 'S2-80'): ScrewAttack,
('S2-14', 'S2-15'): MorphBall and UseBombs,
('S2-15', 'S2-14'): MorphBall and UseBombs and SpringBall and ScrewAttack,
('S2-16', 'S2-17'): MorphBall and UseBombs or ScrewAttack,
('S2-17', 'S2-16'): MorphBall and UseBombs and SpringBall or ScrewAttack,
('S2-18', 'S2-1B'): MorphBall and (UseBombs or WaveBeam or HiJump or WallJump or IBJ),
('S2-1B', 'S2-18'): MorphBall and (HiJump or WallJump or 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'): Missiles or ChargeBeam,
('S2-29', 'S2-46'): MorphBall and PowerBombs,
('S2-29', 'S2-6C'): MorphBall and PowerBombs,
('S2-46', 'S2-29'): MorphBall and PowerBombs,
('S2-46', 'S2-2A'): MorphBall and PowerBombs,
('S2-46', 'S2-58'): MorphBall and PowerBombs,
('S2-6C', 'S2-29'): MorphBall and PowerBombs,
('S2-6C', 'S2-2A'): MorphBall and PowerBombs,
('S2-6C', 'S2-58'): MorphBall and PowerBombs,
('S2-2A', 'S2-46'): MorphBall and PowerBombs,
('S2-2A', 'S2-6C'): MorphBall and PowerBombs,
('S2-58', 'S2-46'): MorphBall and PowerBombs,
('S2-58', 'S2-6C'): MorphBall and PowerBombs,
('S2-2E', 'S2-30'): Missiles or ChargeBeam,
('S2-2F', 'S2-30'): Missiles or 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'): SpaceJump or IBJ,
('S2-3B', 'S2-83'): ScrewAttack and (SpaceJump or WallJump or IBJ),
('S2-3D', 'S2-3B'): BlueDoors,
('S2-3D', 'S2-83'): ScrewAttack and (SpaceJump or WallJump or IBJ),
('S2-83', 'S2-3B'): ScrewAttack and BlueDoors,
('S2-83', 'S2-3D'): ScrewAttack and (SpaceJump or IBJ),
('S2-3E', 'S2-3F'): MorphBall,
('S2-3F', 'S2-3E'): MorphBall,
('S2-10', 'S2-12'): MorphBall and (UseBombs or ScrewAttack),
('S2-10', 'S2-45'): BlueDoors,
('S2-10', 'S2-54'): MorphBall and (UseBombs or ScrewAttack),
('S2-12', 'S2-10'): MorphBall and (UseBombs and SpringBall or (UseBombs and ScrewAttack) or (SpringBall and ScrewAttack)),
('S2-12', 'S2-45'): MorphBall and (UseBombs and SpringBall or (UseBombs and ScrewAttack) or (SpringBall and ScrewAttack)) and BlueDoors,
('S2-45', 'S2-12'): MorphBall and (UseBombs or ScrewAttack),
('S2-45', 'S2-54'): MorphBall and (UseBombs or ScrewAttack),
('S2-54', 'S2-10'): MorphBall and (UseBombs and SpringBall or (UseBombs and ScrewAttack) or (SpringBall and ScrewAttack)),
('S2-54', 'S2-45'): MorphBall and (UseBombs and SpringBall or (UseBombs and ScrewAttack) or (SpringBall and ScrewAttack)) and 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'): SpeedBooster or SpaceJump or IBJ,
('S2-50', 'S2-7A'): MorphBall and (SpeedBooster or SpaceJump or IBJ),
('S2-50', 'S2-4E'): SpeedBooster or SpaceJump or IBJ,
('S2-50', 'S2-4F'): SpeedBooster or SpaceJump or IBJ,
('S2-50', 'S2-79'): SpeedBooster or SpaceJump or IBJ,
('S2-51', 'S2-4D'): SpeedBooster or SpaceJump or IBJ,
('S2-51', 'S2-7A'): MorphBall and (SpeedBooster or SpaceJump or IBJ),
('S2-51', 'S2-4E'): SpeedBooster or SpaceJump or IBJ,
('S2-51', 'S2-4F'): SpeedBooster or SpaceJump or IBJ,
('S2-51', 'S2-79'): SpeedBooster or SpaceJump or 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'): MorphBall and (SpeedBooster or SpaceJump or WallJump or IBJ),
('S2-4E', 'S2-7A'): MorphBall,
('S2-4F', 'S2-7A'): MorphBall,
('S2-79', 'S2-7A'): MorphBall and (SpeedBooster or SpaceJump or WallJump or IBJ),
('S2-53', 'S2-91'): MorphBall,
('S2-91', 'S2-53'): MorphBall and (Ice or SpaceJump or IBJ),
('S2-38', 'S2-5F'): MorphBall and (UseBombs or WaveBeam or GravitySuit),
('S2-5F', 'S2-38'): MorphBall and (Ice or UseBombs or WaveBeam or (GravitySuit and (HiJump or WallJump or IBJ))),
('S2-64', 'S2-65'): MorphBall and UseBombs or ScrewAttack,
('S2-65', 'S2-64'): Impossible,
('S2-67', 'S2-66'): Impossible,
('S2-1E', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-1E', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-1F', 'S2-1E'): MorphBall and UseBombs,
('S2-1F', 'S2-68'): MorphBall and UseBombs,
('S2-1F', 'S2-69'): MorphBall and UseBombs,
('S2-1F', 'S2-6A'): MorphBall and UseBombs,
('S2-1F', 'S2-6B'): MorphBall and UseBombs,
('S2-1F', 'S2-70'): MorphBall and UseBombs,
('S2-1F', 'S2-71'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-68', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-68', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-69', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-69', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-6A', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-6A', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-6B', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-6B', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-70', 'S2-1F'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S2-70', 'S2-71'): MorphBall and (HiJump or WallJump or IBJ),
('S2-71', 'S2-1E'): MorphBall,
('S2-71', 'S2-1F'): MorphBall and 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'): SpaceJump or WallJump or IBJ,
('S2-6E', 'S2-6D'): SpaceJump or WallJump or IBJ,
('S2-6E', 'S2-73'): SpaceJump or WallJump or IBJ,
('S2-73', 'S2-6D'): SpaceJump or WallJump or IBJ,
('S2-7B', 'S2-7C'): Impossible,
('S2-88', 'S2-89'): MorphBall and UseBombs,
('S2-89', 'S2-88'): MorphBall and UseBombs,
('S2-36', 'S2-8A'): Missiles and 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'): MorphBall or WaveBeam,
('S2-8D', 'S2-8E'): MorphBall or WaveBeam,
('S2-8F', 'S2-90'): MorphBall and UseBombs,
('S2-90', 'S2-8F'): MorphBall and UseBombs,
('S3-01', 'S3-04'): MorphBall and ScrewAttack and (SpeedBooster or Ice or 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'): MorphBall and ScrewAttack and (SpeedBooster or Ice or SpaceJump),
('S3-03', 'S3-04'): MorphBall and ScrewAttack and (SpeedBooster or Ice or SpaceJump),
('S3-35', 'S3-04'): MorphBall and ScrewAttack and (SpeedBooster or Ice or SpaceJump),
('S3-08', 'S3-09'): SpeedBooster and GreenDoors,
('S3-08', 'S3-4C'): MorphBall and UseBombs and BombJump and SpeedBooster,
('S3-09', 'S3-08'): SpeedBooster,
('S3-09', 'S3-4C'): MorphBall and UseBombs and BombJump and SpeedBooster,
('S3-4C', 'S3-08'): Impossible,
('S3-4C', 'S3-09'): Impossible,
('S3-0A', 'S3-4D'): Impossible,
('S3-4D', 'S3-0A'): MorphBall and GreenDoors,
('S3-0B', 'S3-0C'): GreenDoors,
('S3-3D', 'S3-0C'): GreenDoors,
('S3-0D', 'S3-0E'): (SuperMissiles or PowerBombs or ScrewAttack) and GreenDoors,
('S3-0D', 'S3-0F'): MorphBall and (SuperMissiles or PowerBombs or ScrewAttack),
('S3-0D', 'S3-3C'): MorphBall and (ScrewAttack or (UseBombs and (SuperMissiles or PowerBombs))),
('S3-0E', 'S3-0D'): (SuperMissiles or PowerBombs or ScrewAttack) and GreenDoors,
('S3-0E', 'S3-0F'): MorphBall,
('S3-0E', 'S3-3C'): MorphBall and (UseBombs or ScrewAttack),
('S3-0F', 'S3-0D'): MorphBall and (SpringBall and ScrewAttack or (BombJump and PowerBombs) or (UseBombs and (SuperMissiles or PowerBombs or ScrewAttack))) and GreenDoors,
('S3-0F', 'S3-0E'): MorphBall and (UseBombs or (SpringBall and ScrewAttack) or (BombJump and PowerBombs)) and GreenDoors,
('S3-0F', 'S3-3C'): MorphBall and (UseBombs or ScrewAttack),
('S3-3C', 'S3-0D'): Impossible,
('S3-3C', 'S3-0E'): Impossible,
('S3-3C', 'S3-0F'): Impossible,
('S3-11', 'S3-12'): MorphBall and UseBombs and (HiJump or WallJump or IBJ),
('S3-12', 'S3-11'): MorphBall and (UseBombs and SpringBall or ScrewAttack),
('S3-13', 'S3-53'): ScrewAttack,
('S3-13', 'S3-54'): (SpeedBooster or SpaceJump or IBJ) and ScrewAttack,
('S3-53', 'S3-13'): ScrewAttack,
('S3-53', 'S3-54'): (SpeedBooster or SpaceJump or IBJ) and 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'): (SpeedBooster or SpaceJump or IBJ) and 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'): VariaSuit and GreenDoors,
('S3-18', 'S3-19'): (Missiles or ChargeBeam or Ice or ScrewAttack) and VariaSuit,
('S3-19', 'S3-18'): VariaSuit,
('S3-1A', 'S3-1B'): VariaSuit,
('S3-1B', 'S3-1A'): VariaSuit,
('S3-1C', 'S3-1D'): Ice or SpaceJump or ((Missiles or ChargeBeam or ScrewAttack) and IBJ),
('S3-1E', 'S3-1F'): (Missiles or ChargeBeam or ScrewAttack) and VariaSuit,
('S3-1F', 'S3-1E'): (Missiles or ChargeBeam or ScrewAttack) and VariaSuit,
('S3-20', 'S3-21'): VariaSuit,
('S3-21', 'S3-20'): VariaSuit,
('S3-22', 'S3-31'): Missiles or ChargeBeam,
('S3-24', 'S3-2B'): GreenDoors,
('S3-28', 'S3-4B'): VariaSuit and WaveBeam,
('S3-28', 'S3-4E'): GravitySuit and WaveBeam and ScrewAttack,
('S3-4B', 'S3-28'): VariaSuit,
('S3-4B', 'S3-4E'): GravitySuit and ScrewAttack,
('S3-4E', 'S3-28'): GravitySuit and ScrewAttack,
('S3-4E', 'S3-4B'): GravitySuit and ScrewAttack,
('S3-2D', 'S3-10'): GreenDoors,
('S3-40', 'S3-10'): GreenDoors,
('S3-25', 'S3-2B'): (ChargeBeam or Difficulty > 0) and GreenDoors,
('S3-25', 'S3-2E'): ChargeBeam or Difficulty > 0,
('S3-2B', 'S3-25'): SpaceJump or ((ChargeBeam or Difficulty > 0) and GreenDoors),
('S3-2B', 'S3-2E'): ChargeBeam or Difficulty > 0,
('S3-2E', 'S3-25'): SpaceJump or ((ChargeBeam or Difficulty > 0) and GreenDoors),
('S3-2E', 'S3-2B'): (ChargeBeam or Difficulty > 0) and GreenDoors,
('S3-2F', 'S3-30'): MorphBall and (SuperMissiles or PowerBombs or ScrewAttack),
('S3-2F', 'S3-3F'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack),
('S3-30', 'S3-2F'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack) and GreenDoors,
('S3-30', 'S3-3F'): MorphBall and UseBombs,
('S3-3F', 'S3-2F'): Impossible,
('S3-3F', 'S3-30'): Impossible,
('S3-36', 'S3-37'): VariaSuit or (DamageRuns and (Energy >= 199 or SpeedBooster)),
('S3-37', 'S3-36'): VariaSuit or (DamageRuns and (Energy >= 199 or (SpeedBooster and (UseBombs or 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'): (MorphBall and UseBombs or ScrewAttack) and GreenDoors,
('S3-27', 'S3-4A'): HiJump and Ice or SpaceJump or IBJ or (MorphBall and UseBombs and Missiles and SpeedBooster and (Difficulty >= 4)),
('S3-47', 'S3-27'): MorphBall and UseBombs or ScrewAttack,
('S3-47', 'S3-4A'): (MorphBall and UseBombs or ScrewAttack) and (HiJump and Ice or SpaceJump or IBJ or (Missiles and SpeedBooster and (Difficulty >= 4))),
('S3-4A', 'S3-47'): (MorphBall and UseBombs or ScrewAttack) and GreenDoors,
('S3-4F', 'S3-50'): GravitySuit and SpeedBooster,
('S3-50', 'S3-4F'): Impossible,
('S4-08', 'S4-09'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and RedDoors,
('S4-08', 'S4-1B'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)) and RedDoors,
('S4-08', 'S4-54'): WaterLowered or DamageRuns,
('S4-09', 'S4-08'): MorphBall and (Diffusion or (WaveBeam and IceBeam)),
('S4-09', 'S4-1B'): RedDoors and (WaterLowered or DamageRuns),
('S4-09', 'S4-54'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)),
('S4-1B', 'S4-08'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)),
('S4-1B', 'S4-09'): RedDoors and (WaterLowered or DamageRuns),
('S4-1B', 'S4-54'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)),
('S4-54', 'S4-08'): WaterLowered or DamageRuns,
('S4-54', 'S4-09'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)) and RedDoors,
('S4-54', 'S4-1B'): MorphBall and (WaterLowered or DamageRuns) and (Diffusion or (WaveBeam and IceBeam)) and RedDoors,
('S4-0D', 'S4-0E'): MorphBall and UseBombs,
('S4-0D', 'S4-12'): MorphBall and UseBombs and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-0D', 'S4-41'): MorphBall and UseBombs,
('S4-0E', 'S4-0D'): SpeedBooster or (MorphBall and (UseBombs or PowerBombs) and (SpaceJump or WallJump or IBJ)),
('S4-0E', 'S4-12'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-12', 'S4-0D'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-12', 'S4-0E'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-12', 'S4-41'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-41', 'S4-0D'): SpeedBooster or (MorphBall and (UseBombs or PowerBombs) and (SpaceJump or WallJump or IBJ)),
('S4-41', 'S4-12'): SpeedBooster and (WaterLowered or (DamageRuns and 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'): Missiles or ChargeBeam,
('S4-40', 'S4-16'): Impossible,
('S4-40', 'S4-3F'): GravitySuit,
('S4-58', 'S4-5F'): GravitySuit and (SpeedBooster or SpaceJump),
('S4-59', 'S4-5F'): GravitySuit and (SpeedBooster or SpaceJump),
('S4-1E', 'S4-1D'): Impossible,
('S4-75', 'S4-1D'): Impossible,
('S4-1F', 'S4-4F'): MorphBall,
('S4-21', 'S4-1F'): GravitySuit and (SpaceJump or IBJ),
('S4-21', 'S4-4F'): MorphBall and GravitySuit and (SpaceJump or IBJ),
('S4-21', 'S4-20'): GravitySuit and (SpaceJump or IBJ),
('S4-21', 'S4-60'): GravitySuit and (SpaceJump or IBJ),
('S4-22', 'S4-1F'): GravitySuit and (SpaceJump or IBJ),
('S4-22', 'S4-4F'): MorphBall and GravitySuit and (SpaceJump or IBJ),
('S4-22', 'S4-20'): GravitySuit and (SpaceJump or IBJ),
('S4-22', 'S4-60'): GravitySuit and (SpaceJump or 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'): GravitySuit and RedDoors,
('S4-29', 'S4-28'): RedDoors,
('S4-2A', 'S4-37'): MorphBall and GravitySuit and ScrewAttack,
('S4-2A', 'S4-5A'): MorphBall and (GravitySuit and ScrewAttack or (Ice and (BombJump and GravitySuit or SpringBall))),
('S4-2A', 'S4-74'): MorphBall,
('S4-37', 'S4-2A'): MorphBall and GravitySuit and ScrewAttack,
('S4-37', 'S4-5A'): GravitySuit and ScrewAttack,
('S4-37', 'S4-74'): GravitySuit and ScrewAttack,
('S4-5A', 'S4-2A'): MorphBall and (GravitySuit and ScrewAttack or (Diffusion and (BombJump and GravitySuit or SpringBall))),
('S4-5A', 'S4-37'): GravitySuit and (SpeedBooster or ScrewAttack),
('S4-5A', 'S4-74'): MorphBall and (GravitySuit and ScrewAttack or (Diffusion and (BombJump and GravitySuit or SpringBall))),
('S4-74', 'S4-2A'): MorphBall,
('S4-74', 'S4-37'): GravitySuit and ScrewAttack,
('S4-74', 'S4-5A'): MorphBall and Ice and (UseBombs and GravitySuit or SpringBall) or (GravitySuit and ScrewAttack),
('S4-11', 'S4-2B'): MorphBall and (UseBombs or ((HiJump or SpeedBooster) and (WaterLowered or (DamageRuns and GravitySuit)))),
('S4-11', 'S4-3B'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-11', 'S4-47'): MorphBall and (UseBombs or (ScrewAttack and (HiJump or SpeedBooster) and (WaterLowered or (DamageRuns and GravitySuit)))),
('S4-2B', 'S4-11'): MorphBall and (UseBombs or WaterLowered or DamageRuns),
('S4-2B', 'S4-3B'): MorphBall and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-2B', 'S4-47'): MorphBall and UseBombs or ScrewAttack,
('S4-3B', 'S4-11'): SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-3B', 'S4-2B'): MorphBall and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-3B', 'S4-47'): MorphBall and (UseBombs or ScrewAttack) and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-47', 'S4-11'): MorphBall and (UseBombs or (ScrewAttack and (WaterLowered or DamageRuns))),
('S4-47', 'S4-2B'): MorphBall and UseBombs or ScrewAttack,
('S4-47', 'S4-3B'): MorphBall and (UseBombs or ScrewAttack) and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-2C', 'S4-2D'): (WaterLowered or DamageRuns) and RedDoors,
('S4-2C', 'S4-2E'): MorphBall,
('S4-2C', 'S4-4B'): BlueDoors,
('S4-2D', 'S4-2C'): WaterLowered or DamageRuns,
('S4-2D', 'S4-2E'): MorphBall and (WaterLowered or DamageRuns),
('S4-2D', 'S4-4B'): (WaterLowered or DamageRuns) and BlueDoors,
('S4-2E', 'S4-2D'): (WaterLowered or DamageRuns) and RedDoors,
('S4-2E', 'S4-4B'): BlueDoors,
('S4-4B', 'S4-2D'): (WaterLowered or DamageRuns) and RedDoors,
('S4-4B', 'S4-2E'): MorphBall,
('S4-2F', 'S4-45'): MorphBall,
('S4-45', 'S4-2F'): MorphBall and UseBombs,
('S4-30', 'S4-35'): SpeedBooster and GravitySuit,
('S4-30', 'S4-4E'): MorphBall and GravitySuit and ScrewAttack,
('S4-35', 'S4-30'): Impossible,
('S4-35', 'S4-4D'): Impossible,
('S4-35', 'S4-4E'): Impossible,
('S4-4D', 'S4-30'): (HiJump or GravitySuit) and RedDoors,
('S4-4D', 'S4-35'): SpeedBooster and GravitySuit,
('S4-4D', 'S4-4E'): MorphBall and GravitySuit and ScrewAttack,
('S4-4E', 'S4-30'): MorphBall and GravitySuit and ScrewAttack and RedDoors,
('S4-4E', 'S4-35'): MorphBall and SpeedBooster and GravitySuit and ScrewAttack,
('S4-4E', 'S4-4D'): MorphBall and GravitySuit and ScrewAttack,
('S4-31', 'S4-50'): Missiles and MorphBall and (UseBombs and (SpringBall or GravitySuit) or (GravitySuit and ScrewAttack)),
('S4-36', 'S4-31'): RedDoors,
('S4-36', 'S4-50'): Missiles and MorphBall and (UseBombs and (SpringBall or GravitySuit) or (GravitySuit and ScrewAttack)),
('S4-50', 'S4-31'): Missiles and MorphBall and (UseBombs or (GravitySuit and ScrewAttack)) and RedDoors,
('S4-50', 'S4-36'): Missiles and MorphBall and (UseBombs or (GravitySuit and ScrewAttack)),
('S4-32', 'S4-33'): RedDoors,
('S4-32', 'S4-64'): MorphBall and (SpringBall or (UseBombs and GravitySuit)),
('S4-33', 'S4-32'): GravitySuit and RedDoors,
('S4-33', 'S4-53'): GravitySuit,
('S4-33', 'S4-64'): MorphBall and GravitySuit and BombJump,
('S4-53', 'S4-32'): RedDoors,
('S4-53', 'S4-33'): RedDoors,
('S4-53', 'S4-64'): MorphBall and (SpringBall or (UseBombs and GravitySuit)),
('S4-64', 'S4-32'): MorphBall and GravitySuit and RedDoors,
('S4-64', 'S4-33'): MorphBall and RedDoors,
('S4-64', 'S4-53'): MorphBall and GravitySuit,
('S4-34', 'S4-62'): Impossible,
('S4-62', 'S4-34'): RedDoors,
('S4-42', 'S4-43'): MorphBall and UseBombs,
('S4-42', 'S4-44'): Impossible,
('S4-42', 'S4-71'): Impossible,
('S4-43', 'S4-42'): MorphBall and 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'): HiJumpBoots or GravitySuit,
('S4-49', 'S4-46'): HiJumpBoots or GravitySuit,
('S4-48', 'S4-51'): Impossible,
('S4-48', 'S4-52'): Impossible,
('S4-51', 'S4-48'): MorphBall and (UseBombs or (GravitySuit and ScrewAttack)),
('S4-51', 'S4-52'): MorphBall and UseBombs or (GravitySuit and ScrewAttack),
('S4-52', 'S4-48'): MorphBall and (UseBombs or (GravitySuit and ScrewAttack)),
('S4-52', 'S4-51'): GravitySuit and ScrewAttack,
('S4-1C', 'S4-38'): MorphBall and Diffusion,
('S4-1C', 'S4-6D'): MorphBall and Diffusion and GravitySuit and ScrewAttack,
('S4-1C', 'S4-70'): MorphBall and Diffusion,
('S4-38', 'S4-1C'): Missiles and MorphBall and GravitySuit and (SpaceJump or (HiJump and Ice)),
('S4-38', 'S4-6D'): GravitySuit and ScrewAttack,
('S4-38', 'S4-70'): Missiles and MorphBall and GravitySuit and (SpaceJump or (HiJump and Ice)),
('S4-6D', 'S4-1C'): Missiles and MorphBall and GravitySuit and ScrewAttack and (SpaceJump or WallJump),
('S4-6D', 'S4-38'): GravitySuit and ScrewAttack and (SpaceJump or WallJump),
('S4-6D', 'S4-70'): Missiles and MorphBall and GravitySuit and ScrewAttack and (SpaceJump or WallJump),
('S4-70', 'S4-1C'): Missiles and MorphBall,
('S4-70', 'S4-38'): Missiles and MorphBall,
('S4-70', 'S4-6D'): Missiles and MorphBall and GravitySuit and ScrewAttack,
('S4-56', 'S4-57'): MorphBall and UseBombs,
('S4-57', 'S4-56'): MorphBall and UseBombs and RedDoors,
('S4-5D', 'S4-5E'): MorphBall and GravitySuit and ScrewAttack,
('S4-5E', 'S4-5D'): MorphBall and GravitySuit and ScrewAttack,
('S4-65', 'S4-66'): MorphBall and (PowerBombs or WaveBeam or (ChargeBeam and Difficulty >= 1)) and (Missiles or (ChargeBeam and 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'): Missiles and MorphBall,
('S5-01', 'S5-51'): YellowDoors,
('S5-42', 'S5-4D'): Missiles and MorphBall,
('S5-42', 'S5-51'): YellowDoors,
('S5-4D', 'S5-01'): Missiles and MorphBall,
('S5-4D', 'S5-42'): Missiles and MorphBall and YellowDoors,
('S5-4D', 'S5-51'): Missiles and MorphBall and YellowDoors,
('S5-51', 'S5-42'): YellowDoors,
('S5-51', 'S5-4D'): Missiles and MorphBall and YellowDoors,
('S5-07', 'S5-08'): HiJump and Ice or SpaceJump or IBJ,
('S5-08', 'S5-07'): YellowDoors,
('S5-09', 'S5-07'): YellowDoors,
('S5-09', 'S5-08'): HiJump and Ice or SpaceJump or IBJ,
('S5-4E', 'S5-07'): YellowDoors,
('S5-4E', 'S5-08'): HiJump and Ice or SpaceJump or IBJ,
('S5-34', 'S5-59'): YellowDoors,
('S5-59', 'S5-34'): YellowDoors,
('S5-0B', 'S5-0C'): HiJump and Ice or SpaceJump or IBJ,
('S5-0C', 'S5-0B'): YellowDoors,
('S5-0D', 'S5-0B'): YellowDoors,
('S5-0D', 'S5-0C'): HiJump and Ice or SpaceJump or IBJ,
('S5-50', 'S5-0B'): YellowDoors,
('S5-50', 'S5-0C'): HiJump and Ice or SpaceJump or IBJ,
('S5-0E', 'S5-0F'): VariaSuit,
('S5-0E', 'S5-10'): MorphBall and UseBombs and SpeedBooster and VariaSuit,
('S5-0E', 'S5-1E'): VariaSuit,
('S5-0E', 'S5-38'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-0E', 'S5-63'): SpeedBooster and VariaSuit and YellowDoors,
('S5-0F', 'S5-0E'): VariaSuit,
('S5-0F', 'S5-10'): MorphBall and UseBombs and SpeedBooster and VariaSuit,
('S5-0F', 'S5-1E'): VariaSuit,
('S5-0F', 'S5-38'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-0F', 'S5-63'): SpeedBooster and VariaSuit and YellowDoors,
('S5-10', 'S5-0E'): MorphBall and UseBombs and VariaSuit,
('S5-10', 'S5-0F'): MorphBall and UseBombs and VariaSuit,
('S5-10', 'S5-1E'): MorphBall and UseBombs and VariaSuit,
('S5-10', 'S5-38'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-10', 'S5-63'): MorphBall and UseBombs and VariaSuit and YellowDoors,
('S5-1E', 'S5-0E'): VariaSuit,
('S5-1E', 'S5-0F'): VariaSuit,
('S5-1E', 'S5-10'): MorphBall and UseBombs and SpeedBooster and VariaSuit,
('S5-1E', 'S5-38'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-1E', 'S5-63'): SpeedBooster and VariaSuit and YellowDoors,
('S5-38', 'S5-0E'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-38', 'S5-0F'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-38', 'S5-10'): MorphBall and SpeedBooster and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-38', 'S5-1E'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-38', 'S5-63'): MorphBall and SpeedBooster and VariaSuit and YellowDoors and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-63', 'S5-0E'): MorphBall and VariaSuit,
('S5-63', 'S5-0F'): MorphBall and VariaSuit,
('S5-63', 'S5-10'): MorphBall and UseBombs and VariaSuit,
('S5-63', 'S5-1E'): MorphBall and VariaSuit,
('S5-63', 'S5-38'): MorphBall and VariaSuit and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-24', 'S5-40'): VariaSuit and WaveBeam,
('S5-40', 'S5-24'): VariaSuit,
('S5-12', 'S5-14'): VariaSuit and YellowDoors,
('S5-14', 'S5-12'): VariaSuit and YellowDoors,
('S5-28', 'S5-13'): YellowDoors,
('S5-15', 'S5-16'): MorphBall and UseBombs and VariaSuit,
('S5-16', 'S5-15'): MorphBall and UseBombs and VariaSuit,
('S5-18', 'S5-31'): VariaSuit and YellowDoors,
('S5-18', 'S5-4F'): MorphBall and BombJump and VariaSuit,
('S5-18', 'S5-5A'): VariaSuit and SpaceJump and YellowDoors,
('S5-31', 'S5-18'): VariaSuit and (Ice or SpaceJump),
('S5-31', 'S5-4F'): MorphBall and BombJump and VariaSuit,
('S5-31', 'S5-5A'): VariaSuit and SpaceJump and YellowDoors,
('S5-4F', 'S5-18'): MorphBall and VariaSuit and (Ice or SpaceJump),
('S5-4F', 'S5-31'): MorphBall and VariaSuit and YellowDoors,
('S5-4F', 'S5-5A'): MorphBall and VariaSuit and SpaceJump and YellowDoors,
('S5-5A', 'S5-18'): VariaSuit and (Ice or SpaceJump),
('S5-5A', 'S5-31'): VariaSuit and YellowDoors,
('S5-5A', 'S5-4F'): MorphBall and BombJump and VariaSuit,
('S5-1B', 'S5-1D'): MorphBall and UseBombs and SpeedBooster and GravitySuit,
('S5-1B', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-1B', 'S5-46'): SpeedBooster and GravitySuit and YellowDoors,
('S5-1C', 'S5-1B'): HiJump or GravitySuit,
('S5-1C', 'S5-1D'): MorphBall and UseBombs and SpeedBooster and GravitySuit,
('S5-1C', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)) and (HiJump or GravitySuit),
('S5-1C', 'S5-46'): SpeedBooster and GravitySuit and YellowDoors,
('S5-1C', 'S5-1F'): HiJump or GravitySuit,
('S5-1C', 'S5-35'): HiJump or GravitySuit,
('S5-1D', 'S5-1B'): MorphBall and UseBombs and GravitySuit,
('S5-1D', 'S5-1C'): MorphBall and UseBombs and GravitySuit,
('S5-1D', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)) and GravitySuit,
('S5-1D', 'S5-46'): MorphBall and UseBombs and YellowDoors,
('S5-1D', 'S5-1F'): MorphBall and UseBombs and GravitySuit,
('S5-1D', 'S5-35'): MorphBall and UseBombs and GravitySuit,
('S5-39', 'S5-1B'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-39', 'S5-1C'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-39', 'S5-1D'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)) and SpeedBooster and GravitySuit,
('S5-39', 'S5-46'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)) and SpeedBooster and GravitySuit and YellowDoors,
('S5-39', 'S5-1F'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-39', 'S5-35'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-46', 'S5-1B'): MorphBall and GravitySuit,
('S5-46', 'S5-1C'): MorphBall and GravitySuit,
('S5-46', 'S5-1D'): MorphBall and UseBombs,
('S5-46', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)) and GravitySuit,
('S5-46', 'S5-1F'): MorphBall and GravitySuit,
('S5-46', 'S5-35'): MorphBall and GravitySuit,
('S5-1F', 'S5-1D'): MorphBall and UseBombs and SpeedBooster and GravitySuit,
('S5-1F', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-1F', 'S5-46'): SpeedBooster and GravitySuit and YellowDoors,
('S5-35', 'S5-1D'): MorphBall and UseBombs and SpeedBooster and GravitySuit,
('S5-35', 'S5-39'): MorphBall and (PowerBombs or (UseBombs and ScrewAttack)),
('S5-35', 'S5-46'): SpeedBooster and GravitySuit and YellowDoors,
('S5-5B', 'S5-5C'): YellowDoors,
('S5-5C', 'S5-5B'): SpaceJump or IBJ,
('S5-5C', 'S5-5D'): SpaceJump or IBJ,
('S5-5D', 'S5-5C'): YellowDoors,
('S5-22', 'S5-78'): MorphBall and PowerBombs,
('S5-3D', 'S5-22'): HiJump or IBJ,
('S5-3D', 'S5-78'): MorphBall and PowerBombs and (HiJump or IBJ),
('S5-3D', 'S5-23'): HiJump or IBJ,
('S5-3D', 'S5-77'): HiJump or IBJ,
('S5-3E', 'S5-22'): HiJump or IBJ,
('S5-3E', 'S5-78'): MorphBall and PowerBombs and (HiJump or IBJ),
('S5-3E', 'S5-23'): HiJump or IBJ,
('S5-3E', 'S5-77'): HiJump or IBJ,
('S5-78', 'S5-22'): MorphBall and UseBombs,
('S5-78', 'S5-3D'): MorphBall and UseBombs,
('S5-78', 'S5-3E'): MorphBall and UseBombs,
('S5-78', 'S5-23'): MorphBall and UseBombs,
('S5-78', 'S5-77'): MorphBall and UseBombs,
('S5-23', 'S5-78'): MorphBall and PowerBombs,
('S5-77', 'S5-78'): MorphBall and PowerBombs,
('S5-25', 'S5-26'): Missiles or ChargeBeam,
('S5-2A', 'S5-6C'): VariaSuit,
('S5-2A', 'S5-6D'): MorphBall and PowerBombs and VariaSuit,
('S5-2A', 'S5-6E'): MorphBall and PowerBombs and VariaSuit and (Ice or SpaceJump or WallJump),
('S5-6C', 'S5-2A'): VariaSuit,
('S5-6C', 'S5-6D'): MorphBall and PowerBombs and VariaSuit,
('S5-6C', 'S5-6E'): MorphBall and PowerBombs and VariaSuit and (Ice or SpaceJump or WallJump),
('S5-6D', 'S5-2A'): MorphBall and PowerBombs and VariaSuit,
('S5-6D', 'S5-6C'): MorphBall and PowerBombs and VariaSuit,
('S5-6D', 'S5-6E'): MorphBall and PowerBombs and VariaSuit and (Ice or SpaceJump or WallJump),
('S5-6E', 'S5-2A'): MorphBall and PowerBombs and VariaSuit,
('S5-6E', 'S5-6C'): MorphBall and PowerBombs and VariaSuit,
('S5-6E', 'S5-6D'): MorphBall and PowerBombs and VariaSuit,
('S5-19', 'S5-30'): YellowDoors,
('S5-19', 'S5-69'): MorphBall and PowerBombs,
('S5-30', 'S5-19'): SpaceJump or IBJ,
('S5-30', 'S5-68'): HiJump and Ice or SpaceJump or IBJ,
('S5-30', 'S5-69'): MorphBall and PowerBombs,
('S5-61', 'S5-19'): SpaceJump or IBJ,
('S5-61', 'S5-30'): YellowDoors,
('S5-61', 'S5-68'): HiJump and Ice or SpaceJump or IBJ,
('S5-61', 'S5-69'): MorphBall and PowerBombs,
('S5-68', 'S5-19'): SpaceJump or IBJ,
('S5-68', 'S5-30'): YellowDoors,
('S5-68', 'S5-69'): MorphBall and 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'): SpeedBooster and GravitySuit,
('S5-3C', 'S5-3B'): SpeedBooster and GravitySuit,
('S5-41', 'S5-11'): YellowDoors,
('S5-43', 'S5-49'): ScrewAttack,
('S5-49', 'S5-43'): ScrewAttack and 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'): SpeedBooster and VariaSuit and YellowDoors,
('S5-6A', 'S5-6B'): MorphBall and UseBombs,
('S5-6B', 'S5-6A'): MorphBall and UseBombs,
('S5-5E', 'S5-5F'): VariaSuit and YellowDoors,
('S5-5E', 'S5-60'): MorphBall and BombJump and VariaSuit,
('S5-5F', 'S5-5E'): VariaSuit and (Ice or SpaceJump),
('S5-5F', 'S5-60'): MorphBall and BombJump and VariaSuit,
('S5-60', 'S5-5E'): MorphBall and VariaSuit and (Ice or SpaceJump),
('S5-60', 'S5-5F'): MorphBall and VariaSuit and YellowDoors,
('S5-36', 'S5-44'): Missiles and MorphBall and Ice,
('S5-44', 'S5-36'): Missiles and MorphBall and GravitySuit and ScrewAttack and (SpaceJump or WallJump),
('S5-44', 'S5-70'): Missiles and MorphBall,
('S5-70', 'S5-36'): GravitySuit and ScrewAttack and (SpaceJump or WallJump),
('S5-70', 'S5-44'): Missiles and MorphBall and Ice,
('S5-73', 'S5-7B'): SpeedBooster and GravitySuit,
('S5-7B', 'S5-73'): SpeedBooster and 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'): SuperMissiles or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 1),
('S6-07', 'S6-32'): MorphBall and UseBombs,
('S6-07', 'S6-4B'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack or (SpeedBooster and Difficulty >= 1)),
('S6-08', 'S6-07'): SuperMissiles or PowerBombs or ScrewAttack,
('S6-08', 'S6-32'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack),
('S6-08', 'S6-4B'): MorphBall and UseBombs,
('S6-32', 'S6-07'): MorphBall and UseBombs,
('S6-32', 'S6-08'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack),
('S6-32', 'S6-4B'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack),
('S6-4B', 'S6-07'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or ScrewAttack),
('S6-4B', 'S6-08'): MorphBall and UseBombs,
('S6-4B', 'S6-32'): MorphBall and UseBombs and (SuperMissiles or PowerBombs or 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'): SpeedBooster and 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'): SpeedBooster and ScrewAttack and (VariaSuit or Energy > 499),
('S6-0E', 'S6-52'): ScrewAttack,
('S6-0E', 'S6-55'): Impossible,
('S6-20', 'S6-30'): VariaSuit or Energy > 499,
('S6-30', 'S6-20'): VariaSuit or Energy > 499,
('S6-03', 'S6-21'): MorphBall and PowerBombs and (VariaSuit or Energy > 499),
('S6-21', 'S6-03'): MorphBall and PowerBombs and RedDoors and (VariaSuit or Energy > 499),
('S6-0F', 'S6-47'): MorphBall and ScrewAttack,
('S6-47', 'S6-0F'): MorphBall,
('S6-47', 'S6-10'): MorphBall,
('S6-10', 'S6-47'): MorphBall and 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'): MorphBall and UseBombs,
('S6-1B', 'S6-15'): MorphBall and UseBombs,
('S6-1B', 'S6-3D'): MorphBall and UseBombs,
('S6-15', 'S6-1B'): MorphBall,
('S6-3D', 'S6-1B'): MorphBall,
('S6-17', 'S6-18'): Missiles or (ChargeBeam and GreenDoors),
('S6-1A', 'S6-59'): SpeedBooster and ScrewAttack,
('S6-1C', 'S6-1A'): RedDoors,
('S6-1C', 'S6-59'): Impossible,
('S6-59', 'S6-1A'): MorphBall and RedDoors,
('S6-59', 'S6-1C'): MorphBall,
('S6-25', 'S6-58'): HiJump and ScrewAttack,
('S6-58', 'S6-25'): ScrewAttack,
('S6-28', 'S6-2A'): RedDoors,
('S6-29', 'S6-28'): HiJump or WallJump or IBJ,
('S6-29', 'S6-2A'): RedDoors,
('S6-2A', 'S6-28'): HiJump or WallJump or IBJ,
('S6-2C', 'S6-2D'): MorphBall and WaveBeam,
('S6-2D', 'S6-2C'): MorphBall and RedDoors,
('S6-35', 'S6-3E'): GreenDoors,
('S6-3E', 'S6-35'): GreenDoors,
('S6-13', 'S6-36'): MorphBall and UseBombs,
('S6-36', 'S6-13'): MorphBall and PowerBombs,
('S6-37', 'S6-38'): MorphBall and PowerBombs,
('S6-38', 'S6-37'): MorphBall and 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'): VariaSuit or Energy >= 599,
('S6-41', 'S6-44'): VariaSuit or Energy >= 599,
('S6-43', 'S6-41'): VariaSuit or Energy > 599,
('S6-43', 'S6-4D'): VariaSuit or Energy > 599,
('S6-44', 'S6-41'): VariaSuit or Energy > 599,
('S6-44', 'S6-4D'): VariaSuit or Energy > 599,
('S6-4D', 'S6-43'): VariaSuit or Energy > 599,
('S6-4D', 'S6-44'): VariaSuit or 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'): SpeedBooster and RedDoors and BackwardsLabs,
('S0-20', 'S0-22'): SpeedBooster and RedDoors and BackwardsLabs,
('Item S0-05-16', 'S0-20'): SpeedBooster and RedDoors,
('Item S0-05-16', 'S0-22'): SpeedBooster and RedDoors and BackwardsLabs,
('S0-22', 'S0-20'): SpeedBooster and RedDoors,
('S0-22', 'Item S0-05-16'): SpeedBooster and 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'): Missiles and MorphBall and ScrewAttack,
('Arachnus', 'Item S0-18-06'): MorphBall and ScrewAttack,
('Arachnus', 'S0-59'): MorphBall,
('Arachnus', 'S0-C8'): Missiles and MorphBall and ScrewAttack,
('S0-59', 'S0-58'): Missiles and MorphBall and ScrewAttack,
('S0-59', 'Item S0-18-06'): MorphBall and ScrewAttack,
('S0-59', 'Arachnus'): Missiles and MorphBall,
('S0-59', 'S0-C8'): Missiles and MorphBall and ScrewAttack,
('S0-C8', 'S0-58'): Missiles,
('S0-C8', 'Item S0-18-06'): Missiles,
('S0-C8', 'Arachnus'): Missiles,
('S0-C8', 'S0-59'): Missiles and MorphBall,
('S0-6B', 'Item S0-08-0B'): MorphBall and PowerBombs and (BombJump or SpringBall),
('Item S0-08-0B', 'S0-6B'): MorphBall and PowerBombs,
('Item S0-08-0B', 'S0-C4'): Impossible,
('S0-C4', 'Item S0-08-0B'): MorphBall and PowerBombs and (BombJump or SpringBall),
('S0-74', 'Item S0-16-12'): MorphBall,
('S0-74', 'S0-75'): (Missiles or ChargeBeam) and MorphBall and UseBombs,
('Item S0-16-12', 'S0-74'): MorphBall,
('Item S0-16-12', 'S0-75'): (Missiles or ChargeBeam) and MorphBall and UseBombs,
('S0-75', 'S0-74'): Impossible,
('S0-75', 'Item S0-16-12'): Impossible,
('S0-83', 'Item S0-0E-07'): MorphBall and BombJump,
('Item S0-0E-07', 'S0-83'): MorphBall and UseBombs and 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'): Missiles and ChargeBeam and PlasmaBeam,
('End-of-Game', 'S0-C2'): RedDoors,
('S0-03', 'Yakuza'): Missiles and (ChargeBeam or Difficulty > 0),
('S0-03', 'S0-79'): SpaceJump or IBJ,
('Yakuza', 'S0-03'): SpaceJump or IBJ,
('Yakuza', 'S0-79'): SpaceJump or IBJ,
('S0-79', 'S0-03'): SpaceJump or IBJ,
('S0-79', 'Yakuza'): Missiles and (ChargeBeam or 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'): GravitySuit and (SpaceJump or (SpeedBooster and Difficulty > 0)) or (DamageRuns and Energy >= 199),
('S1-24', 'Item S1-06-03'): GravitySuit or (DamageRuns and Energy >= 199),
('S1-24', 'Item S1-07-04'): MorphBall and (GravitySuit or (DamageRuns and (Energy >= 299 and VariaSuit or Energy >= 399))),
('Item S1-05-03', 'S1-24'): GreenDoors and (GravitySuit or (DamageRuns and Energy >= 199)),
('Item S1-05-03', 'S1-25'): GravitySuit or SpaceJump or (DamageRuns and 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'): SpaceJump or (SpeedBooster and Difficulty > 0),
('S1-25', 'Item S1-07-04'): MorphBall and (GravitySuit or (DamageRuns and (Energy >= 199 and VariaSuit or Energy >= 299))),
('Item S1-06-03', 'S1-24'): GreenDoors and (GravitySuit or (DamageRuns and 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'): MorphBall and GreenDoors and (GravitySuit or (DamageRuns and (Energy >= 299 and VariaSuit or Energy >= 399))),
('Item S1-07-04', 'Item S1-05-03'): Impossible,
('Item S1-07-04', 'S1-25'): MorphBall and (GravitySuit or (DamageRuns and (Energy >= 199 and VariaSuit or Energy >= 299))),
('Item S1-07-04', 'Item S1-06-03'): Impossible,
('S1-3A', 'Ridley'): Missiles and (Difficulty > 4 or (Difficulty > 3 and ChargeBeam) or (ChargeBeam and PlasmaBeam)),
('Ridley', 'S1-3A'): SpaceJump or WallJump or IBJ,
('S1-3E', 'Item S1-03-0A'): Missiles and MorphBall and Diffusion and (Ice or ScrewAttack),
('Item S1-03-0A', 'S1-3E'): Missiles and MorphBall and Diffusion and (Ice or ScrewAttack),
('Item S1-03-0A', 'S1-3F'): Missiles and MorphBall and Diffusion and (Ice or ScrewAttack),
('Item S1-03-0A', '3E'): MorphBall and BombJump,
('Item S1-03-0A', '3F'): MorphBall and BombJump,
('S1-3F', 'Item S1-03-0A'): Missiles and MorphBall and Diffusion and (Ice or ScrewAttack),
('3E', 'Item S1-03-0A'): MorphBall and BombJump,
('3F', 'Item S1-03-0A'): MorphBall and BombJump,
('S1-51', 'Item S1-07-00'): HiJump and ScrewAttack,
('S1-51', 'S1-66'): MorphBall and (SpaceJump or (HiJump and WallJump)) and ScrewAttack,
('Item S1-07-00', 'S1-51'): ScrewAttack and GreenDoors,
('Item S1-07-00', 'S1-66'): MorphBall,
('S1-66', 'S1-51'): MorphBall and BombJump and ScrewAttack and GreenDoors,
('S1-66', 'Item S1-07-00'): MorphBall and BombJump,
('S1-52', 'Item S1-09-04'): (Missiles or ChargeBeam) and 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'): Missiles and 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'): MorphBall and BombJump and SpeedBooster and GravitySuit,
('Item S1-0C-07', 'S1-65'): MorphBall and BombJump and SpeedBooster and GravitySuit,
('S1-6D', 'Item S1-11-02'): MorphBall,
('Item S1-11-02', 'S1-6D'): MorphBall,
('S2-0E', 'Item S2-09-03'): MorphBall and UseBombs,
('Item S2-09-03', 'S2-0E'): MorphBall and UseBombs and BlueDoors,
('Data S2', 'S2-13'): BlueDoors,
('S2-14', 'Item S2-00-05'): MorphBall and UseBombs,
('Item S2-00-05', 'S2-14'): MorphBall,
('Item S2-00-05', 'S2-15'): MorphBall and UseBombs,
('S2-15', 'Item S2-00-05'): MorphBall and UseBombs and HiJump,
('S2-16', 'Item S2-02-0E'): MorphBall and UseBombs,
('Item S2-02-0E', 'S2-16'): MorphBall and UseBombs and SpringBall,
('Item S2-02-0E', 'S2-17'): MorphBall and UseBombs,
('S2-17', 'Item S2-02-0E'): MorphBall and UseBombs,
('S2-26', 'Item S2-0C-0B'): Impossible,
('Item S2-0C-0B', 'S2-26'): Impossible,
('Item S2-0C-0B', 'S2-27'): Missiles or ChargeBeam,
('S2-28', 'Zazabi'): Missiles,
('S2-28', 'S2-85'): (Missiles or ChargeBeam) and ScrewAttack and (SpaceJump or WallJump or IBJ),
('Zazabi', 'S2-28'): HiJump or WallJump or IBJ,
('Zazabi', 'S2-85'): ScrewAttack and (SpaceJump or WallJump or IBJ),
('S2-85', 'S2-28'): (Missiles or ChargeBeam) and ScrewAttack and (HiJump or WallJump or IBJ),
('S2-85', 'Zazabi'): Missiles and 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'): Missiles and (ChargeBeam or Difficulty > 0),
('S2-33', 'Nettori'): Missiles and (ChargeBeam or Difficulty > 0),
('S2-39', 'Item S2-03-0C'): MorphBall and (UseBombs and (SpringBall or GravitySuit) or PowerBombs),
('Item S2-03-0C', 'S2-39'): MorphBall and (UseBombs and (SpringBall or GravitySuit) or PowerBombs),
('S2-83', 'Security-Level-1'): ScrewAttack,
('Security-Level-1', 'S2-83'): ScrewAttack and (SpaceJump or WallJump or IBJ),
('Security-Level-1', 'S2-3B'): BlueDoors,
('Security-Level-1', 'S2-3D'): SpaceJump or IBJ,
('S2-3E', 'Item S2-09-05'): MorphBall and UseBombs,
('Item S2-09-05', 'S2-3E'): MorphBall and UseBombs,
('Item S2-09-05', 'S2-3F'): MorphBall and UseBombs,
('S2-3F', 'Item S2-09-05'): MorphBall and UseBombs,
('S2-10', 'Item S2-04-04'): MorphBall and UseBombs,
('S2-12', 'Item S2-04-04'): MorphBall and UseBombs and (BombJump or ScrewAttack),
('Item S2-04-04', 'S2-10'): MorphBall and UseBombs,
('Item S2-04-04', 'S2-12'): MorphBall and (UseBombs or ScrewAttack),
('Item S2-04-04', 'S2-45'): MorphBall and UseBombs and BlueDoors,
('Item S2-04-04', 'S2-54'): MorphBall and (UseBombs or ScrewAttack),
('S2-45', 'Item S2-04-04'): MorphBall and UseBombs,
('S2-54', 'Item S2-04-04'): MorphBall and UseBombs and (BombJump or ScrewAttack),
('S2-49', 'Item S2-04-03'): HiJump or IBJ or Ice or SpeedBooster or ScrewAttack,
('Item S2-04-03', 'S2-7D'): ScrewAttack,
('S2-7D', 'Item S2-04-03'): ScrewAttack,
('S2-38', 'Item S2-04-0B'): MorphBall and ((UseBombs or WaveBeam) and (HiJump or SpaceJump) or (GravitySuit and (Ice or SpaceJump or WallJump or IBJ))),
('Item S2-04-0B', 'S2-38'): MorphBall and (Ice or UseBombs or WaveBeam or (GravitySuit and (HiJump or IBJ or WallJump))),
('S2-5F', 'Item S2-04-0B'): HiJump or SpaceJump or (GravitySuit and (Ice or IBJ or WallJump)),
('S2-6D', 'Item S2-08-08'): SpaceJump or WallJump or IBJ,
('Item S2-08-08', 'S2-6D'): SpaceJump or WallJump or IBJ,
('Item S2-08-08', 'S2-73'): SpaceJump or WallJump or IBJ,
('S2-6E', 'Item S2-08-08'): SpaceJump or WallJump or IBJ,
('S2-73', 'Item S2-08-08'): SpaceJump or WallJump or IBJ,
('S2-72', 'Item S2-05-08'): MorphBall and Ice,
('S2-72', 'Item S2-05-0A'): MorphBall and Ice,
('Item S2-05-08', 'S2-72'): MorphBall and UseBombs,
('Item S2-05-0A', 'S2-72'): MorphBall and UseBombs,
('S2-84', 'Item S2-05-00'): SpaceJump,
('S2-84', 'Item S2-05-01'): SpaceJump,
('Item S2-05-00', 'S2-84'): MorphBall and 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'): MorphBall and UseBombs and BombJump and 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'): MorphBall and (SuperMissiles or ScrewAttack),
('Item S3-0B-04', 'S3-0D'): MorphBall and UseBombs and (SuperMissiles or ScrewAttack) and GreenDoors,
('Item S3-0B-04', 'S3-0E'): MorphBall and UseBombs and GreenDoors,
('Item S3-0B-04', 'S3-0F'): MorphBall and UseBombs,
('Item S3-0B-04', 'S3-3C'): MorphBall and (UseBombs or ScrewAttack),
('S3-0E', 'Item S3-0B-04'): MorphBall,
('S3-0F', 'Item S3-0B-04'): MorphBall and (UseBombs or ScrewAttack),
('S3-3C', 'Item S3-0B-04'): Impossible,
('S3-11', 'Item S3-0A-01'): MorphBall and PowerBombs,
('S3-11', 'Item S3-0B-02'): MorphBall and UseBombs,
('Item S3-0A-01', 'S3-11'): MorphBall,
('Item S3-0A-01', 'S3-12'): MorphBall and UseBombs and HiJump,
('Item S3-0B-02', 'S3-11'): MorphBall and UseBombs and SpringBall or ScrewAttack,
('Item S3-0B-02', 'S3-12'): MorphBall and UseBombs and HiJump,
('S3-12', 'Item S3-0A-01'): MorphBall and PowerBombs,
('S3-12', 'Item S3-0B-02'): MorphBall and UseBombs,
('S3-13', 'Item S3-0F-00'): SpeedBooster,
('Item S3-0F-00', 'S3-53'): ScrewAttack,
('Item S3-0F-00', 'S3-54'): (SpeedBooster or SpaceJump or IBJ) and ScrewAttack,
('S3-26', 'Item S3-0F-00'): SpeedBooster,
('S3-53', 'Item S3-0F-00'): SpeedBooster and ScrewAttack,
('S3-54', 'Item S3-0F-00'): SpeedBooster and ScrewAttack,
('S3-18', 'Item S3-07-0B'): MorphBall and PowerBombs and (GravitySuit or (DamageRuns and (Energy >= 399 and VariaSuit or Energy >= 599))),
('Item S3-07-0B', 'S3-18'): MorphBall and PowerBombs and (GravitySuit or (DamageRuns and Energy >= 199)),
('Item S3-07-0B', 'S3-19'): MorphBall and PowerBombs and (Missiles or ChargeBeam or Ice or ScrewAttack) and (GravitySuit or (DamageRuns and (Energy >= 199 and VariaSuit or Energy >= 299))),
('S3-19', 'Item S3-07-0B'): MorphBall and PowerBombs and (GravitySuit or (DamageRuns and (Energy >= 399 and VariaSuit or Energy >= 599))),
('S3-28', 'Item S3-11-0A'): MorphBall and BombJump and (Ice or SpaceJump) and VariaSuit and WaveBeam,
('S3-28', 'Item S3-12-09'): MorphBall and (Ice or SpaceJump) and VariaSuit and WaveBeam,
('Item S3-11-0A', 'S3-28'): MorphBall and VariaSuit,
('Item S3-11-0A', 'Item S3-12-09'): MorphBall and VariaSuit,
('Item S3-11-0A', 'S3-4B'): MorphBall and VariaSuit,
('Item S3-11-0A', 'S3-4E'): MorphBall and GravitySuit and ScrewAttack,
('Item S3-12-09', 'S3-28'): MorphBall and (UseBombs or SpringBall or SpaceJump) and VariaSuit,
('Item S3-12-09', 'Item S3-11-0A'): MorphBall and VariaSuit,
('Item S3-12-09', 'S3-4B'): MorphBall and (UseBombs or SpringBall or SpaceJump) and VariaSuit,
('Item S3-12-09', 'S3-4E'): MorphBall and GravitySuit and ScrewAttack,
('S3-4B', 'Item S3-11-0A'): MorphBall and BombJump and (Ice or SpaceJump) and VariaSuit,
('S3-4B', 'Item S3-12-09'): MorphBall and (Ice or SpaceJump) and VariaSuit,
('S3-4E', 'Item S3-11-0A'): MorphBall and BombJump and (Ice or SpaceJump) and GravitySuit and ScrewAttack,
('S3-4E', 'Item S3-12-09'): MorphBall and (Ice or SpaceJump) and GravitySuit and ScrewAttack,
('Data S3', 'S3-2C'): GreenDoors,
('S3-32', 'Wide Core-X'): Missiles,
('S3-38', 'Item S3-01-02'): SpeedBooster and (MorphBall and UseBombs or ScrewAttack),
('S3-38', 'S3-57'): ScrewAttack,
('Item S3-01-02', 'S3-38'): MorphBall and UseBombs or ScrewAttack,
('Item S3-01-02', 'Item S3-03-04'): MorphBall and UseBombs or ScrewAttack,
('Item S3-01-02', 'S3-57'): ScrewAttack,
('Item S3-03-04', 'Item S3-01-02'): SpeedBooster and (MorphBall and UseBombs or ScrewAttack),
('Item S3-03-04', 'S3-57'): ScrewAttack,
('S3-57', 'S3-38'): ScrewAttack,
('S3-57', 'Item S3-01-02'): SpeedBooster and ScrewAttack,
('S3-57', 'Item S3-03-04'): ScrewAttack,
('S3-3A', 'Item S3-0B-06'): MorphBall and PowerBombs and (HiJump or Ice or IBJ),
('Item S3-0B-06', 'S3-3A'): MorphBall and PowerBombs and (HiJump or WallJump or IBJ),
('Item S3-0B-06', 'S3-3B'): Impossible,
('Item S3-0B-06', 'S3-3E'): Impossible,
('S3-3B', 'Item S3-0B-06'): MorphBall and PowerBombs and SpeedBooster and (HiJump or Ice or IBJ),
('S3-3E', 'Item S3-0B-06'): MorphBall and PowerBombs and SpeedBooster and (HiJump or Ice or IBJ),
('S3-45', 'Item S3-11-04'): SuperMissiles or PowerBombs or ScrewAttack,
('Item S3-11-04', 'S3-45'): SuperMissiles or PowerBombs or ScrewAttack,
('S3-27', 'Item S3-0E-0A'): MorphBall and UseBombs or ScrewAttack,
('Item S3-0E-0A', 'S3-27'): MorphBall and UseBombs or ScrewAttack,
('Item S3-0E-0A', 'S3-47'): GreenDoors,
('Item S3-0E-0A', 'S3-4A'): (MorphBall and UseBombs or ScrewAttack) and (HiJump and Ice or SpaceJump or IBJ),
('S3-4A', 'Item S3-0E-0A'): MorphBall and UseBombs or ScrewAttack,
('S3-4F', 'Item S3-14-03'): SpeedBooster and GravitySuit and ScrewAttack,
('S3-4F', 'Item S3-14-09'): SpeedBooster and GravitySuit,
('Item S3-14-03', 'S3-4F'): Impossible,
('Item S3-14-03', 'S3-50'): SpeedBooster and GravitySuit and ScrewAttack,
('Item S3-14-09', 'S3-4F'): Impossible,
('Item S3-14-09', 'S3-50'): SpeedBooster and GravitySuit,
('S3-50', 'Item S3-14-03'): Impossible,
('S3-50', 'Item S3-14-09'): Impossible,
('S3-58', 'Item S3-00-05'): MorphBall and UseBombs and (SpringBall or IBJ) or ScrewAttack,
('Item S3-00-05', 'S3-58'): MorphBall and UseBombs and (SpringBall or IBJ) or ScrewAttack,
('Item S3-00-05', 'S3-59'): MorphBall and UseBombs and (SpringBall or IBJ) or ScrewAttack,
('S3-59', 'Item S3-00-05'): MorphBall and UseBombs and (SpringBall or IBJ) or ScrewAttack,
('Data S4', 'S4-0A'): RedDoors,
('S4-0D', 'Item S4-0C-06'): MorphBall and PowerBombs and (WaterLowered or DamageRuns),
('Item S4-0C-06', 'S4-0D'): MorphBall and PowerBombs and (WaterLowered or DamageRuns),
('Item S4-0C-06', 'S4-0E'): MorphBall and PowerBombs and (WaterLowered or DamageRuns),
('Item S4-0C-06', 'S4-12'): MorphBall and PowerBombs and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('Item S4-0C-06', 'S4-41'): MorphBall and PowerBombs and (WaterLowered or DamageRuns),
('S4-0E', 'Item S4-0C-06'): MorphBall and PowerBombs and (WaterLowered or DamageRuns) and (SpaceJump or WallJump or IBJ or (SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)))),
('S4-12', 'Item S4-0C-06'): MorphBall and PowerBombs and SpeedBooster and (WaterLowered or (DamageRuns and GravitySuit)),
('S4-41', 'Item S4-0C-06'): MorphBall and PowerBombs and (SpaceJump or WallJump or IBJ or (SpeedBooster and (WaterLowered or (DamageRuns and 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'): MorphBall and UseBombs,
('S4-1D', 'Item S4-0E-02'): Missiles and MorphBall and UseBombs,
('Item S4-0D-01', 'S4-1D'): Impossible,
('Item S4-0D-01', 'S4-1E'): MorphBall and UseBombs,
('Item S4-0D-01', 'S4-75'): MorphBall and UseBombs,
('Item S4-0E-02', 'S4-1D'): Impossible,
('S4-1E', 'Item S4-0D-01'): MorphBall and UseBombs,
('S4-1E', 'Item S4-0E-02'): Missiles and MorphBall and UseBombs,
('S4-75', 'Item S4-0D-01'): MorphBall and UseBombs,
('S4-75', 'Item S4-0E-02'): Missiles and MorphBall and UseBombs,
('S4-23', 'Item S4-0B-08'): None,
('Item S4-0B-08', 'S4-23'): None,
('S4-26', 'Item S4-0A-0C'): MorphBall and PowerBombs,
('Item S4-0A-0C', 'S4-26'): GravitySuit and (SpaceJump or IBJ),
('Item S4-0A-0C', 'S4-27'): GravitySuit and (SpaceJump or IBJ),
('S4-27', 'Item S4-0A-0C'): MorphBall and PowerBombs,
('S4-30', 'Item S4-07-08'): GravitySuit and ScrewAttack,
('Item S4-07-08', 'S4-30'): GravitySuit and ScrewAttack and RedDoors,
('Item S4-07-08', 'S4-35'): SpeedBooster and GravitySuit and ScrewAttack,
('Item S4-07-08', 'S4-4D'): GravitySuit and ScrewAttack,
('Item S4-07-08', 'S4-4E'): MorphBall,
('S4-35', 'Item S4-07-08'): Impossible,
('S4-4D', 'Item S4-07-08'): GravitySuit and ScrewAttack,
('S4-4E', 'Item S4-07-08'): MorphBall,
('S4-31', 'Item S4-07-0A'): Missiles and MorphBall and (UseBombs and (SpringBall or GravitySuit) or (GravitySuit and ScrewAttack)),
('Item S4-07-0A', 'S4-31'): Missiles and MorphBall and (UseBombs or (GravitySuit and ScrewAttack)) and RedDoors,
('Item S4-07-0A', 'S4-36'): Missiles and MorphBall and (UseBombs or (GravitySuit and ScrewAttack)),
('Item S4-07-0A', 'S4-50'): MorphBall,
('S4-36', 'Item S4-07-0A'): Missiles and MorphBall and (UseBombs and (SpringBall or GravitySuit) or (GravitySuit and 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'): MorphBall and (SpeedBooster or (HiJump and (WaterLowered or (GravitySuit and DamageRuns)))),
('S4-4C', 'Water Pump'): SpeedBooster or (MorphBall and HiJump and GravitySuit and DamageRuns),
('Item S4-00-06', 'S4-4C'): MorphBall and BlueDoors and (WaterLowered and BombJump or (DamageRuns and (SpringBall or (UseBombs and GravitySuit)))),
('Item S4-00-06', 'Water Pump'): MorphBall and DamageRuns and (SpringBall or (UseBombs and GravitySuit)),
('Water Pump', 'S4-4C'): MorphBall and BombJump and BlueDoors and WaterLowered,
('Water Pump', 'Item S4-00-06'): MorphBall and WaterLowered,
('S4-55', 'Item S4-0F-06'): MorphBall and (WaterLowered and (SuperMissiles or PowerBombs or WaveBeam or ScrewAttack) or (DamageRuns and (SuperMissiles or PowerBombs or WaveBeam or (GravitySuit and ScrewAttack)))),
('S4-55', 'S4-5B'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('S4-55', 'S4-5C'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('Item S4-0F-06', 'S4-55'): MorphBall and (WaterLowered or (DamageRuns and Energy >= 199)),
('Item S4-0F-06', 'S4-5B'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('Item S4-0F-06', 'S4-5C'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('S4-5B', 'S4-55'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('S4-5B', 'Item S4-0F-06'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered and (SuperMissiles or PowerBombs or WaveBeam or ScrewAttack) or (DamageRuns and Energy >= 199 and (SuperMissiles or PowerBombs or WaveBeam or (GravitySuit and ScrewAttack)))),
('S4-5B', 'S4-5C'): WaterLowered or DamageRuns,
('S4-5C', 'S4-55'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered or (DamageRuns and Energy >= 199)),
('S4-5C', 'Item S4-0F-06'): MorphBall and (Diffusion or (WaveBeam and IceBeam)) and (WaterLowered and (SuperMissiles or PowerBombs or WaveBeam or ScrewAttack) or (DamageRuns and Energy >= 199 and (SuperMissiles or PowerBombs or WaveBeam or (GravitySuit and ScrewAttack)))),
('S4-5C', 'S4-5B'): WaterLowered or DamageRuns,
('S4-5D', 'Item S4-13-07'): MorphBall and SpeedBooster and GravitySuit and ScrewAttack,
('Item S4-12-07', 'Item S4-13-07'): Impossible,
('Item S4-12-07', 'S4-5E'): MorphBall and GravitySuit and ScrewAttack,
('Item S4-13-07', 'S4-5D'): MorphBall and SpeedBooster and GravitySuit and ScrewAttack,
('Item S4-13-07', 'Item S4-12-07'): MorphBall and GravitySuit and ScrewAttack,
('Item S4-13-07', 'S4-5E'): MorphBall and SpeedBooster and GravitySuit,
('S4-5E', 'Item S4-12-07'): MorphBall and GravitySuit and ScrewAttack,
('S4-5E', 'Item S4-13-07'): MorphBall and SpeedBooster and GravitySuit,
('S4-67', 'Item S4-06-0E'): MorphBall and UseBombs and (SpringBall or (BombJump and GravitySuit)),
('Item S4-06-0E', 'S4-67'): MorphBall and 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'): SpeedBooster and (GravitySuit or (WaveBeam and HiJump and 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'): MorphBall and UseBombs and BombJump,
('Item S5-0C-07', 'S5-17'): MorphBall and UseBombs and BombJump,
('S5-45', 'Item S5-0F-07'): MorphBall and BombJump and VariaSuit,
('Item S5-0F-07', 'S5-45'): MorphBall,
('S5-22', 'Item S5-12-04'): MorphBall and PowerBombs,
('Item S5-12-04', 'S5-22'): MorphBall and UseBombs,
('Item S5-12-04', 'S5-23'): MorphBall and UseBombs,
('Item S5-12-04', 'S5-3D'): MorphBall and UseBombs,
('Item S5-12-04', 'S5-3E'): MorphBall and UseBombs,
('Item S5-12-04', 'S5-77'): MorphBall and UseBombs,
('Item S5-12-04', 'S5-78'): MorphBall and UseBombs,
('S5-23', 'Item S5-12-04'): MorphBall and PowerBombs,
('S5-3D', 'Item S5-12-04'): MorphBall and PowerBombs and (HiJump or IBJ),
('S5-3E', 'Item S5-12-04'): MorphBall and PowerBombs and (HiJump or IBJ),
('S5-77', 'Item S5-12-04'): MorphBall and PowerBombs,
('S5-78', 'Item S5-12-04'): MorphBall and UseBombs,
('S5-3A', 'Nightmare'): Missiles and (ChargeBeam or Difficulty > 0) and (HiJump or SpaceJump),
('S5-3A', 'S5-54'): Impossible,
('Nightmare', 'S5-54'): Impossible,
('S5-54', 'S5-3A'): Missiles and (ChargeBeam or Difficulty > 0) and (HiJump or SpaceJump),
('S5-54', 'Nightmare'): Missiles and (ChargeBeam or Difficulty > 0) and (HiJump or SpaceJump),
('S5-2A', 'Item S5-07-0B'): MorphBall and PowerBombs and VariaSuit,
('S5-6C', 'Item S5-07-0B'): MorphBall and PowerBombs and VariaSuit,
('Item S5-07-0B', 'S5-2A'): MorphBall and PowerBombs and VariaSuit,
('Item S5-07-0B', 'S5-6C'): MorphBall and PowerBombs and VariaSuit,
('Item S5-07-0B', 'S5-6D'): MorphBall and UseBombs and VariaSuit,
('Item S5-07-0B', 'S5-6E'): MorphBall and PowerBombs and VariaSuit and (Ice or SpaceJump or WallJump),
('S5-6D', 'Item S5-07-0B'): MorphBall and UseBombs and VariaSuit,
('S5-6E', 'Item S5-07-0B'): MorphBall and PowerBombs and VariaSuit,
('S5-37', 'Item S5-06-05'): MorphBall and BombJump and Ice and 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'): MorphBall and (UseBombs and SpringBall or ScrewAttack),
('Item S5-05-04', 'S5-03'): MorphBall and UseBombs and YellowDoors,
('Item S5-05-04', 'S5-52'): MorphBall and UseBombs and YellowDoors,
('S5-52', 'Item S5-05-04'): MorphBall and (UseBombs and SpringBall or ScrewAttack),
('S5-1A', 'Item S5-16-04'): Impossible,
('Item S5-16-04', 'S5-1A'): MorphBall and Missiles and ChargeBeam and SpaceJump,
('Item S5-16-04', 'S5-27'): Impossible,
('S5-27', 'Item S5-16-04'): MorphBall and UseBombs,
('S5-4B', 'Item S5-0B-01'): Missiles and MorphBall and (PowerBombs or ScrewAttack),
('Item S5-0B-01', 'S5-4B'): Missiles and MorphBall and (UseBombs or ScrewAttack),
('Item S5-0B-01', 'S5-57'): Missiles and MorphBall and (UseBombs or ScrewAttack),
('Item S5-0B-01', 'S5-58'): Missiles and MorphBall and (UseBombs or ScrewAttack),
('S5-57', 'Item S5-0B-01'): Missiles and MorphBall and (PowerBombs or ScrewAttack),
('S5-58', 'Item S5-0B-01'): Missiles and MorphBall and (PowerBombs or ScrewAttack),
('S5-76', 'Item S5-11-05'): MorphBall and PowerBombs,
('Item S5-11-05', 'S5-76'): MorphBall and PowerBombs,
('S5-73', 'Item S5-14-07'): SpeedBooster and GravitySuit,
('Item S5-14-07', 'S5-7B'): SpeedBooster and GravitySuit,
('S5-7B', 'Item S5-14-07'): SpeedBooster and GravitySuit,
('S5-2F', 'Item S5-0E-08'): MorphBall and VariaSuit and (Ice or SpaceJump),
('Item S5-0E-08', 'S5-2F'): MorphBall and 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'): Missiles and ChargeBeam,
('Mega Core-X', 'S6-19'): GreenDoors,
('S6-34', 'S6-19'): GreenDoors,
('S6-34', 'Mega Core-X'): Missiles and ChargeBeam,
('S6-1D', 'Item S6-05-0B'): MorphBall and UseBombs and (SpringBall or Ice or IBJ),
('Item S6-05-0B', 'S6-1D'): MorphBall and UseBombs,
('S6-1E', 'Wave Core-X'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-1E', 'S6-1F'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-1E', 'S6-24'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-1E', 'S6-57'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit and ScrewAttack,
('Wave Core-X', 'S6-1E'): Impossible,
('Wave Core-X', 'S6-57'): Impossible,
('S6-1F', 'S6-1E'): Impossible,
('S6-1F', 'Wave Core-X'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-1F', 'S6-24'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-1F', 'S6-57'): Impossible,
('S6-24', 'S6-1E'): Impossible,
('S6-24', 'Wave Core-X'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-24', 'S6-1F'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit,
('S6-24', 'S6-57'): Impossible,
('S6-57', 'S6-1E'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit and ScrewAttack,
('S6-57', 'Wave Core-X'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit and ScrewAttack,
('S6-57', 'S6-1F'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit and ScrewAttack,
('S6-57', 'S6-24'): Missiles and (ChargeBeam or Difficulty > 0) and MorphBall and UseBombs and (SpringBall or PowerBombs) and GravitySuit and ScrewAttack,
('S6-25', 'Item S6-09-05'): MorphBall and UseBombs and HiJump and ScrewAttack and (Diffusion or (WaveBeam and IceBeam)),
('S6-25', 'Item S6-0A-06'): WaveBeam,
('Item S6-09-05', 'S6-25'): MorphBall and UseBombs and ScrewAttack,
('Item S6-09-05', 'S6-58'): MorphBall and UseBombs,
('Item S6-0A-06', 'S6-25'): WaveBeam,
('Item S6-0A-06', 'S6-58'): HiJump and ScrewAttack,
('S6-58', 'Item S6-09-05'): MorphBall and UseBombs and (Diffusion or (WaveBeam and IceBeam)),
('S6-58', 'Item S6-0A-06'): WaveBeam and ScrewAttack,
('S6-31', 'Item S6-0E-03'): MorphBall and UseBombs,
('Item S6-0E-03', 'S6-31'): MorphBall and UseBombs,
('Data S6', 'S6-35'): GreenDoors,
('Data S6', 'S6-3E'): GreenDoors,
('Item S6-06-08', 'S6-36'): MorphBall and UseBombs,
('S6-36', 'Item S6-06-08'): MorphBall and PowerBombs,
('S6-3F', 'Item S6-0C-08'): Impossible,
('S6-3F', 'Item S6-0B-09'): MorphBall and (SpaceJump or IBJ or 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'): MorphBall and (SpaceJump or IBJ or WallJump),
('S6-42', 'Item S6-0B-09'): MorphBall,
('S6-4C', 'Item S6-08-03'): MorphBall and UseBombs,
('Item S6-08-03', 'S6-4C'): MorphBall and UseBombs and SpringBall,
('S6-56', 'Item S6-0E-04'): MorphBall and Bombs and SpeedBooster,
('Item S6-0E-04', 'S6-56'): MorphBall and Bombs and SpeedBooster,
('S6-5A', 'Item S6-03-04'): SpeedBooster,
('S6-5A', 'Item S6-01-06'): SpeedBooster and SpaceJump,
('Item S6-03-04', 'S6-5A'): SpeedBooster,
('Item S6-01-06', 'S6-5A'): SpeedBooster,
('S5-4D', 'S5-50'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-0A', 'S5-0C'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-03', 'S5-0B'): YellowDoors and SpeedBooster and GravitySuit or (HiJump and WaveBeam),
('S5-55', 'S5-1F'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-37', 'S5-39'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-24', 'S5-1C'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-15', 'S5-1D'): SpeedBooster and GravitySuit or (HiJump and WaveBeam and YellowDoors),
('S5-64', 'S5-46'): YellowDoors and SpeedBooster and GravitySuit or (HiJump and WaveBeam),
('S5-56', 'S5-5C'): YellowDoors and SpeedBooster and GravitySuit or (HiJump and 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:
if 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', depth=250)
if path != None:
enable_item(graph, 'BlueDoors')
path = graph.get_path('Security-Level-1', StartLocation, depth=250)
if path == None:
disable_item(graph, 'BlueDoors')
if GreenDoors == False:
path = graph.get_path(StartLocation, 'Security-Level-2', depth=250)
if path != None:
enable_item(graph, 'GreenDoors')
path = graph.get_path('Security-Level-2', StartLocation, depth=250)
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', depth=250)
if path != None:
enable_item(graph, 'YellowDoors')
path = graph.get_path('Security-Level-3', StartLocation, depth=250)
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', depth=250)
if path != None:
enable_item(graph, 'RedDoors')
path = graph.get_path('Security-Level-4', StartLocation, depth=250)
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 MaxETanks
global MissileCount
global NettoriOpen
global PlacedETanks
global PlacedMissiles
global PlacedPowerBombs
global areaLayout
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...')
while 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:
while areaLayout[2] != 1 and areaLayout[2] != 2 and areaLayout[3] != 1 and areaLayout[3] != 2:
attemptedLayouts.append(areaLayout)
while areaLayout in attemptedLayouts:
areaLayout = random.sample(range(1, 7), 6)
else:
while areaLayout in attemptedLayouts:
areaLayout = random.sample(range(1, 7), 6)
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:
break
if path == None:
sys.exit('No accessible locations found with this start, try changing your game settings.')
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)
break
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')
weightInit = True
if len(availableItems) < 1:
sys.exit('No accessible locations found with this start, try changing your game settings.')
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]:
if location not in locationsPerArea[area]:
locationsPerArea[area].append(location)
for area in range(0, 7):
if len(locationsPerArea[area]) > 0:
areaWeights[area] = weightValue[area] / len(locationsPerArea[area])
for location in AccessibleLocations:
for area in range(0, 7):
if location in AreaItemLocations[area]:
locationWeights.append(areaWeights[area])
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
while 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
if FirstItem == 'MainMissiles':
if 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':
if 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:
if location not in AccessibleLocations:
if location == 'Data S0' or location == 'Item S0-05-16':
path = graph.get_path(location, StartLocation, depth=250)
else:
for area in range(0, 7):
if location in AreaItemLocations[area]:
if AreaOpen[area]:
path = graph.get_path(AreaOpen[area], location, True)
break
if path != None:
AccessibleLocations.append(location)
MajorLocations.remove(location)
newLocations.append(location)
for area in range(0, 7):
if location in AreaItemLocations[area]:
if location not in locationsPerArea[area]:
locationsPerArea[area].append(location)
for area in range(0, 7):
if len(locationsPerArea[area]) > 0:
if 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]:
if 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, weights=MajorWeights, k=1)[0]
currentItemWeight = MajorWeights.pop(MajorList.index(item))
MajorList.remove(item)
enable_item(graph, item)
if SeedSettings['DamageRuns']:
Energy = Energy / 2
while path == None and len(AccessibleLocations) > 0:
itemLocation = random.choices(AccessibleLocations, weights=locationWeights, k=1)[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, depth=250)
else:
for area in range(0, 7):
if itemLocation in AreaItemLocations[area]:
if AreaOpen[area]:
path = graph.get_path(itemLocation, AreaOpen[area], True)
break
if itemLocation in BossLocations:
if 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, depth=250)
if missilePath != None:
missilePath = graph.get_path(missileLocation, StartLocation, depth=250)
else:
for area in range(0, 7):
if missileLocation in AreaItemLocations[area]:
if AreaOpen[area]:
missilePath = graph.get_path(AreaOpen[area], missileLocation, True)
if missilePath != None:
missilePath = graph.get_path(missileLocation, AreaOpen[area], True)
break
if missilePath != None:
PossibleMissileTanks.append(missileLocation)
else:
for missileLocation in AccessibleLocations:
missilePath = None
if missileLocation == 'Data S0' or missileLocation == 'Item S0-05-16':
missilePath = graph.get_path(missileLocation, StartLocation, depth=250)
else:
for area in range(0, 7):
if missileLocation in AreaItemLocations[area]:
if AreaOpen[area]:
missilePath = graph.get_path(missileLocation, AreaOpen[area], True)
break
if missilePath != None:
if missileLocation not in BossLocations:
PossibleMissileTanks.append(missileLocation)
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)
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
if item == 'MainMissiles':
if 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':
if SeedSettings['PowerBombsWithoutBombs'] == False:
MajorList.append('MainPowerBombs')
MajorWeights.append(WeightedMajors.get('MainPowerBombs'))
if SeedSettings['MajorMinor'] == False:
if len(AccessibleLocations) > 3:
if 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
print('Game is beatable, placing remaining items (no logic)')
for item in MajorItems:
if item not in PlacedItems:
if item not in MajorList:
MajorList.append(item)
MajorWeights.append(WeightedMajors.get(item))
MajorLocations.extend(AccessibleLocations)
for item in MajorList:
if item not in PlacedItems:
location = random.choice(MajorLocations)
while location in UsedLocations:
MajorLocations.remove(location)
location = random.choice(MajorLocations)
UsedLocations.append(location)
PlacedItems.append(item)
if SeedSettings['MajorMinor']:
for location in MajorLocations:
if PlacedETanks < MaxETanks:
if location not in UsedLocations:
UsedLocations.append(location)
PlacedItems.append(MinorItems[0])
PlacedETanks += 1
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:
if 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')
patch_game()
def patch_game():
global FileName, BaseGame
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:
# FIXME: whenever Kazuto decides to drop the original ASM reintroduce debug mode
# armips is FOSS and further documentation should be provided on how to build it
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:
error = False
with open(BaseGame, 'rb') as source:
with open(os.path.join('.', 'seeds', '{}.gba'.format(FileName)), 'wb') as target:
with open(os.path.join('.', 'data', 'MFOR.bps'), 'rb') as patch:
try:
apply_to_files(patch, source, target)
except Exception:
error = True
if error:
os.remove(os.path.join('.', 'seeds', '{}.gba'.format(FileName)))
print('Error: failed to patch game with base patch!')
sys.exit(1)
checksum = fileHash(os.path.join('.', 'seeds', '{}.gba'.format(FileName)))
if checksum != 2455114263:
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)
with open(os.path.join('.', 'seeds', '{}.gba'.format(FileName)), 'rb+') as patchedGame:
if Debug:
sym = dict()
sym.clear()
with open(os.path.join('.', 'data', 'asm', 'temp.sym'), 'r') as symFile:
for line in symFile:
x = line.split()
if len(x) > 1 and re.search('^[a-zA-Z]', x[1]):
sym.update({ x[1]: x[0][2:] })
os.remove(os.path.join('.', 'data', 'asm', 'temp.sym'))
roomEventOffset = int(sym.get('t_bossanddownloadevents'), 16)
itemEventOffset = int(sym.get('t_obtainitemevents'), 16)
securityOffset = int(sym.get('b_unlocklowerlevels'), 16)
print('roomEventOffset: 0x{:06X}'.format(roomEventOffset))
print('itemEventOffset: 0x{:06X}'.format(itemEventOffset))
print('securityOffset: 0x{:06X}'.format(securityOffset))
else:
roomEventOffset = 8326320
itemEventOffset = 5726112
securityOffset = 479192
for area in RoomNodes:
areaIndex = list(RoomNodes.keys()).index(area)
for node in RoomNodes[area]:
name = node.get('Name')
nodeType = node.get('Type')
if nodeType != None:
itemName = ''
if 'Tank' in nodeType:
itemName = PlacedItems[UsedLocations.index(name)]
bg1 = int(node.get('BG1'), 16)
clipdata = int(node.get('Clipdata'), 16)
tileset = int(node.get('Tileset'), 16)
if SeedSettings['HideItems']:
if tileset == 33:
blockValue = 7
elif tileset == 34:
blockValue = 7
elif tileset == 40:
blockValue = 7
elif tileset == 42:
blockValue = 7
else:
blockValue = 3
else:
blockValue = ItemList.index(itemName)
if blockValue < 2:
blockValue = blockValue ^ 1
elif blockValue > 2:
if tileset == 33:
blockValue = 7
elif tileset == 34:
blockValue = 7
elif tileset == 40:
blockValue = 7
elif tileset == 42:
blockValue = 7
else:
blockValue = 3
blockValue += 70
if tileset == 9:
blockValue += 1
elif tileset == 11:
blockValue += 1
elif tileset == 25:
blockValue += 1
elif tileset >= 30 and tileset <= 34:
blockValue += 1
elif tileset == 40:
blockValue += 1
elif tileset == 42:
blockValue += 1
elif tileset == 48:
blockValue += 1
elif tileset == 49:
blockValue += 1
elif tileset == 52:
blockValue += 1
elif tileset == 56:
blockValue += 1
elif tileset == 61:
blockValue += 1
elif tileset == 62:
blockValue += 1
elif tileset == 64:
blockValue += 1
elif tileset == 67:
blockValue += 1
elif tileset == 72:
blockValue += 1
clipValue = ItemList.index(itemName)
if clipValue < 2:
# Energy Tank or Missile Tank
clipValue = clipValue ^ 99
if 'Hidden' in nodeType:
clipValue += 2
elif 'Underwater' in nodeType:
clipValue += 4
elif clipValue == 2:
clipValue = 104
if 'Hidden' in nodeType:
clipValue += 1
elif 'Underwater' in nodeType:
clipValue += 2
elif clipValue >= 3:
clipValue = (clipValue - 3)*3 + 120
if 'Hidden' in nodeType:
clipValue += 1
elif 'Underwater' in nodeType:
clipValue += 2
if 'Hidden' not in nodeType:
patchedGame.seek(bg1)
patchedGame.write(blockValue.to_bytes(1, 'little'))
patchedGame.seek(clipdata)
patchedGame.write(clipValue.to_bytes(1, 'little'))
elif 'Boss' in nodeType or 'Data' in nodeType:
itemName = PlacedItems[UsedLocations.index(name)]
itemValue = ItemList.index(itemName)
slot = BossDataList.index(name)
roomEvent = roomEventOffset
if roomEvent != None:
roomEvent = roomEvent + 3 + slot*4
if itemValue < 3:
itemValue += 1
else:
itemValue -= 3
itemEvent = itemEventOffset
if itemEvent != None:
itemEvent = itemEvent + 1 + itemValue
patchedGame.seek(itemEvent)
itemValue = int.from_bytes(patchedGame.read(1), 'little')
patchedGame.seek(roomEvent)
patchedGame.write(itemValue.to_bytes(1, 'little'))
if name == 'Data S5':
roomEvent = roomEventOffset
roomEvent = roomEvent + 3 + (slot + 1)*4
patchedGame.seek(roomEvent)
patchedGame.write(itemValue.to_bytes(1, 'little'))
if itemName in MajorItems:
offset = CreditsOffsets.get(itemName)
if 'Boss' in nodeType:
location = name
else:
if 'S0' in name:
location = 'Main Deck : '
else:
location = 'Sector {} : '.format(name[6:7])
if 'Tank' in nodeType:
location = location + name[8:]
else:
location = location + nodeType + ' Room'
spaces = ceiling(30 - len(location), 2)
location = ' '*spaces + location
patchedGame.seek(offset)
patchedGame.write(location.encode('ascii'))
for x in range(len(location), 35):
patchedGame.write((0).to_bytes(1, 'little'))
if SeedSettings['HideItems']:
patchedGame.seek(3926048)
patchedGame.write((76).to_bytes(2, 'little'))
patchedGame.write((77).to_bytes(2, 'little'))
patchedGame.write((78).to_bytes(2, 'little'))
patchedGame.write((79).to_bytes(2, 'little'))
patchedGame.write((76).to_bytes(2, 'little'))
patchedGame.write((77).to_bytes(2, 'little'))
patchedGame.write((78).to_bytes(2, 'little'))
patchedGame.write((79).to_bytes(2, 'little'))
patchedGame.write((76).to_bytes(2, 'little'))
patchedGame.write((77).to_bytes(2, 'little'))
patchedGame.write((78).to_bytes(2, 'little'))
patchedGame.write((79).to_bytes(2, 'little'))
if SeedSettings['SplitSecurity'] == True:
security = securityOffset
patchedGame.seek(security)
patchedGame.write((0).to_bytes(2, 'little'))
if SeedSettings['MissilesWithoutMainData']:
patchedGame.seek(24828)
patchedGame.write((15).to_bytes(1, 'little'))
patchedGame.seek(395742)
patchedGame.write((15).to_bytes(1, 'little'))
patchedGame.seek(465582)
patchedGame.write((15).to_bytes(1, 'little'))
if SeedSettings['PowerBombsWithoutBombs']:
patchedGame.seek(24756)
patchedGame.write((32).to_bytes(1, 'little'))
patchedGame.seek(465672)
patchedGame.write((32).to_bytes(1, 'little'))
if SeedSettings['SectorShuffle'] == True:
for currentArea in range(7):
patchedGame.seek(7977108 + currentArea * 4, 0)
data = patchedGame.read(4)
unpacked = struct.unpack('<L', data)
doorData = unpacked[0] - 134217728
patchedGame.seek(doorData, 0)
doorNumber = 0
while True:
connectionType = int.from_bytes(patchedGame.read(1), 'little')
patchedGame.seek(5, 1)
offset = patchedGame.tell()
connectedDoor = int.from_bytes(patchedGame.read(1), 'little')
patchedGame.seek(5, 1)
resume = patchedGame.tell()
if connectionType == 0 and connectedDoor == 0:
break
sourceDoor = 'S{}-{:02X}'.format(currentArea, doorNumber)
targetDoorStr = World.doorConnections.get(sourceDoor)
connectedArea = World.areaConnections.get(sourceDoor, currentArea)
connectedDoorStr = 'S{}-{:02X}'.format(connectedArea, connectedDoor)
if connectedDoorStr != targetDoorStr:
targetDoor = int(targetDoorStr[-2:], 16)
patchedGame.seek(offset)
patchedGame.write(targetDoor.to_bytes(1, 'little'))
patchedGame.seek(resume)
doorNumber += 1
for door, targetArea in World.areaConnections.items():
offset = World.areaConnectionOffsets.get(door)
patchedGame.seek(offset)
areaByte = int.from_bytes(patchedGame.read(1), 'little')
if areaByte != targetArea:
patchedGame.seek(offset)
patchedGame.write(targetArea.to_bytes(1, 'little'))
for target in World.patcher:
value = World.patcher.get(target)
patchedGame.seek(target)
patchedGame.write(value.to_bytes(1, 'little'))
if Patch:
with open(BaseGame, 'rb') as source:
sourcedata = source.read()
with open(os.path.join('.', 'seeds', '{}.gba'.format(FileName)), 'rb') as target:
targetdata = target.read()
blocksize = (len(sourcedata) + len(targetdata)) // 1000000 + 1
print("Using blocks of {0} bytes".format(blocksize))
iterable = diff_bytearrays(blocksize, sourcedata, targetdata)
with open(os.path.join('.', 'seeds', '{}.bps'.format(FileName)), 'wb') as patch:
write_bps(bps_progress(iterable), patch)
print('')
ItemNames = [
'Missile Data',
'Morph Ball',
'Charge Beam',
'Bombs',
'Hi-Jump Boots',
'Speed Booster',
'Super Missile Data',
'Varia Suit',
'Ice Missile Data',
'Wide Beam',
'Power Bomb Data',
'Space Jump',
'Plasma Beam',
'Gravity Suit',
'Diffusion Data',
'Wave Beam',
'Screw Attack',
'Ice Beam']
if SeedSettings['RaceSeed'] == False:
spoilerLog = dict()
spoilerLog.update({ 'MFOR Version': version })
spoilerLog.update({ 'Seed': SeedValue })
settingsDict = dict()
settingsDict.update({ 'Difficulty': SeedSettings['Difficulty'] })
if SeedSettings['MajorMinor'] == False:
settingsDict.update({ 'Item pool': 'Major items anywhere' })
else:
settingsDict.update({ 'Item pool': 'Limited major item locations' })
settingsDict.update({ 'Missile upgrades enable Missiles': SeedSettings['MissilesWithoutMainData'] })
settingsDict.update({ 'Power Bombs without normal Bombs': SeedSettings['PowerBombsWithoutBombs'] })
settingsDict.update({ 'Allow logical damage runs': SeedSettings['DamageRuns'] })
settingsDict.update({ 'Separated security levels': SeedSettings['SplitSecurity'] })
settingsDict.update({ 'Sector shuffle': SeedSettings['SectorShuffle'] })
if SeedSettings['SectorShuffle'] == True:
sectorLayout = str()
for x in areaLayout:
sectorLayout = sectorLayout.strip() + ' {}'.format(x)
settingsDict.update({ 'Sector layout:': sectorLayout })
settingsDict.update({ 'Hide item graphics': SeedSettings['HideItems'] })
settingsDict.update({ 'E-Tanks': PlacedETanks })
settingsDict.update({ 'Missile Tanks': PlacedMissiles })
settingsDict.update({ 'Power Bomb Tanks': PlacedPowerBombs })
spoilerLog.update({ 'Settings': settingsDict })
itemProgression = dict()
for x in range(len(PlacedItems)):
if PlacedItems[x] in MajorItems:
namedItem = ItemNames[MajorItems.index(PlacedItems[x])]
PlacedItems[x] = namedItem
itemProgression.update({ UsedLocations[x]: PlacedItems[x] })
spoilerLog.update({ 'Item order': itemProgression })
itemDict = dict()
World.itemLocations.sort()
for x in range(0, len(World.itemLocations)):
itemDict.update({ World.itemLocations[x]: 0 })
for x in range(0, len(PlacedItems)):
itemDict.update({ UsedLocations[x]: PlacedItems[x] })
spoilerLog.update({ 'Items': itemDict })
with open(os.path.join('.', 'spoilers', '{}.json'.format(FileName)), 'w') as spoiler:
json.dump(spoilerLog, spoiler, indent=4)
def initialize():
global AccessibleLocations
global AreaOpen
global BackwardsLabs
global BossDataList
global BossLocations
global Energy
global HashList
global InfiniteBombJump
global ItemList
global MajorItems
global MaxETanks
global MaxMissiles
global MaxPowerBombs
global MinorItems
global MissileCount
global MissileDamage
global PlacedETanks
global PlacedItems
global PlacedMissiles
global PlacedPowerBombs
global UsedLocations
global WallJumpSetting
HashList = list()
with open(os.path.join('.', 'data', 'SeedHash.json')) as jsonFile:
HashList = json.load(jsonFile)
HashList.sort()
AreaOpen = list()
for area in range(0, 7):
AreaOpen.append(None)
Energy = 0
WallJumpSetting = False
InfiniteBombJump = False
BackwardsLabs = False
MaxETanks = 20
MaxMissiles = 48
MaxPowerBombs = 32
PlacedETanks = PlacedMissiles = PlacedPowerBombs = 0
MissileDamage = 0
MissileCount = 10
MajorItems = [
'MainMissiles',
'MorphBall',
'ChargeBeam',
'Bombs',
'HiJumpBoots',
'SpeedBooster',
'SuperMissileItem',
'VariaSuit',
'IceMissileItem',
'WideBeam',
'MainPowerBombs',
'SpaceJump',
'PlasmaBeam',
'GravitySuit',
'DiffusionItem',
'WaveBeam',
'ScrewAttack',
'IceBeam']
MinorItems = [
'Energy Tank', 'Missile Tank', 'Power Bomb Tank']
BossDataList = ['Data S0',
'Arachnus',
'Charge Core-X',
'Data S2',
'Zazabi',
'Serris',
'Data S3',
'Mega Core-X',
'Data S5',
'Data S5',
'Wide Core-X',
'Data S6',
'Yakuza',
'Nettori',
'Nightmare',
'Data S4',
'Box-2',
'Ridley',
'Omega Metroid']
ItemList = MinorItems + MajorItems
PlacedItems = list()
BossLocations = list()
AccessibleLocations = list()
UsedLocations = list()
def start_randomizer(rom, settings):
global AreaItemLocations
global BaseGame
global DamageRuns
global Debug
global Difficulty
global Patch
global RoomNodes
global SeedSettings
global SeedValue
global StartLocation
global World
BaseGame = rom
if BaseGame == None or BaseGame == '':
print('Error: no base game provided.')
sys.exit(1)
checksum = fileHash(BaseGame)
if checksum != 1819625372:
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:
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))
settings.pop('Seed')
repeat = 1
if settings['Num']:
if settings['Num'] > repeat:
repeat = settings['Num']
settings.pop('Num')
if settings['Patch']:
Patch = True
else:
Patch = False
settings.pop('Patch')
for loop in range(repeat):
initialize()
SeedSettings = settings.copy()
if Debug:
print('Debug generation enabled')
if loop > 0:
SeedValue = str(random.randrange(sys.maxsize))
Difficulty = SeedSettings['Difficulty']
DamageRuns = SeedSettings['DamageRuns']
random.seed(SeedValue + str(SeedSettings))
World = Graph.Game(BaseGame)
World.RemoveNodeFromRoom('Room-S2-07', 'S2-10')
World.RemoveNodeFromRoom('Room-S2-0D', 'S2-1E')
World.RemoveNodeFromRoom('Room-S3-07', 'S3-10')
World.RemoveNodeFromRoom('Room-S3-12', 'S3-2B')
World.RemoveNodeFromRoom('Room-S5-15', 'S5-2A')
World.AddNodeToRoom('Room-S2-1F', 'S2-10')
World.AddNodeToRoom('Room-S2-2E', 'S2-1E')
World.AddNodeToRoom('Room-S3-16', 'S3-10')
World.AddNodeToRoom('Room-S3-17', 'S3-2B')
World.AddNodeToRoom('Room-S5-16', 'S5-2A')
World.UpdateDoorConnection('S0-4A', 'S0-61')
World.UpdateDoorConnection('S0-96', 'S0-22')
World.UpdateDoorConnection('S0-98', 'S0-20')
World.UpdateDoorConnection('S2-13', 'S2-45')
World.UpdateDoorConnection('S2-19', 'S2-2F')
World.UpdateDoorConnection('S2-1B', 'S2-68')
World.UpdateDoorConnection('S2-23', 'S2-69')
World.UpdateDoorConnection('S2-5F', 'S2-6A')
World.UpdateDoorConnection('S2-6E', 'S2-70')
World.UpdateDoorConnection('S3-2D', 'S3-2E')
World.UpdateDoorConnection('S5-28', 'S5-6C')
AreaItemLocations = list()
for area in range(7):
AreaItemLocations.append(list())
with open(os.path.join('.', 'data', 'NodeData.json')) as jsonFile:
RoomNodes = json.load(jsonFile)
for area in RoomNodes:
areaIndex = list(RoomNodes.keys()).index(area)
for node in RoomNodes[area]:
name = node.get('Name')
room = node.get('Room')
item = node.get('Item')
nodeType = node.get('Type')
World.AddNodeToRoom('Room-S{}-{:02X}'.format(areaIndex, int(room, 16)), name)
if item == 'Missile' or item == 'Power Bomb':
World.add_to_minors(name)
elif nodeType == 'Boss':
World.add_to_majors(name)
BossLocations.append(name)
elif nodeType == 'Data' or item == 'E-Tank':
World.add_to_majors(name)
if name == 'Data S3':
BossLocations.append(name)
if 'Item' in name or nodeType == 'Boss' or nodeType == 'Data':
AreaItemLocations[areaIndex].append(name)
World.ConnectAllNodes()
StartLocation = 'S0-00'
startTime = time.time()
randomize_game(World)
seedTime = time.time() - startTime
print(str(FileName))
print('Randomized in:', seedTime)
totalRandoTime = time.time() - totalRandoTime
print('All seeds took:', totalRandoTime)
return FileName