diff --git a/Fusion_Graph.py b/Fusion_Graph.py index 9e76284..2c5404e 100644 --- a/Fusion_Graph.py +++ b/Fusion_Graph.py @@ -32,7 +32,7 @@ class Game: self.itemLocations.clear() self.patcher.clear() - print('DEBUG: Opening ROM to pick stuff') + # print('DEBUG: Opening ROM to pick stuff') try: with open(vanillaGame, 'rb') as sourceRom: @@ -51,37 +51,40 @@ class Game: targetOffset = sourceRom.tell() targetArea = int.from_bytes(sourceRom.read(1), 'little') for currentArea in range(7): + # print('DEBUG: Parsing sector {}'.format(currentArea)) sourceRom.seek(7977108 + currentArea * 4, 0) data = sourceRom.read(4) unpacked = struct.unpack(' 2: - leftTube = 226 + leftArea - else: - leftTube = 235 + leftArea - if rightArea > 2: - rightTube = 9 + rightArea - elif rightArea == 2: - rightTube = 4 - else: - rightTube = 1 - graph.patcher.update({ - 4857211: leftTube }) - graph.patcher.update({ - 4857224: leftTube + 16 }) - graph.patcher.update({ - 4856958: rightTube }) - graph.patcher.update({ - 4856975: rightTube + 16 }) - elif area == 2: - topTile = 20 - bottomTile = 36 - leftTile = 181 - rightTile = 182 - tileset = 35 - if leftArea > 2: - leftTube = 9 + leftArea - elif leftArea == 2: - leftTube = 4 - else: - leftTube = 1 - if rightArea > 2: - rightTube = 226 + rightArea - else: - rightTube = 235 + rightArea - graph.patcher.update({ - 5091931: leftTube }) - graph.patcher.update({ - 5091944: leftTube + 16 }) - graph.patcher.update({ - 5092202: rightTube }) - graph.patcher.update({ - 5092219: rightTube + 16 }) - elif area == 3: - topTile = 21 - bottomTile = 37 - leftTile = 183 - rightTile = 184 - tileset = 36 - if leftArea > 2: - leftTube = 226 + leftArea - else: - leftTube = 235 + leftArea - if rightArea > 2: - rightTube = 9 + rightArea - elif rightArea == 2: - rightTube = 4 - else: - rightTube = 1 - graph.patcher.update({ - 5254431: leftTube }) - graph.patcher.update({ - 5254447: leftTube + 16 }) - graph.patcher.update({ - 5254714: rightTube }) - graph.patcher.update({ - 5254731: rightTube + 16 }) - elif area == 4: - topTile = 51 - bottomTile = 67 - leftTile = 195 - rightTile = 196 - tileset = 37 - if leftArea > 2: - leftTube = 9 + leftArea - elif leftArea == 2: - leftTube = 4 - else: - leftTube = 1 - if rightArea > 2: - rightTube = 226 + rightArea - else: - rightTube = 235 + rightArea - graph.patcher.update({ - 5512395: leftTube }) - graph.patcher.update({ - 5512408: leftTube + 16 }) - graph.patcher.update({ - 5512134: rightTube }) - graph.patcher.update({ - 5512151: rightTube + 16 }) - elif area == 5: - topTile = 52 - bottomTile = 68 - leftTile = 197 - rightTile = 198 - tileset = 38 - if leftArea > 2: - leftTube = 226 + leftArea - else: - leftTube = 235 + leftArea - if rightArea > 2: - rightTube = 226 + rightArea - else: - rightTube = 235 + rightArea - graph.patcher.update({ - 5358711: leftTube }) - graph.patcher.update({ - 5358724: leftTube + 16 }) - graph.patcher.update({ - 5361542: rightTube }) - graph.patcher.update({ - 5361559: rightTube + 16 }) - elif area == 6: - topTile = 24 - bottomTile = 40 - leftTile = 199 - rightTile = 200 - tileset = 39 - if leftArea > 2: - leftTube = 226 + leftArea - else: - leftTube = 235 + leftArea - if rightArea > 2: - rightTube = 226 + rightArea - else: - rightTube = 235 + rightArea - graph.patcher.update({ - 5598427: leftTube }) - graph.patcher.update({ - 5598440: leftTube + 16 }) - graph.patcher.update({ - 5598706: rightTube }) - graph.patcher.update({ - 5598723: rightTube + 16 }) - if elevator == 0: - graph.patcher.update({ - 4669078: leftTile }) - graph.patcher.update({ - 4669079: rightTile }) - graph.patcher.update({ - 4669026: leftTile }) - graph.patcher.update({ - 4669027: rightTile }) - graph.patcher.update({ - 4670120: leftTile }) - graph.patcher.update({ - 4670121: rightTile }) - graph.patcher.update({ - 4670922: leftTile }) - graph.patcher.update({ - 4670923: rightTile }) - graph.patcher.update({ - 4671720: leftTile }) - graph.patcher.update({ - 4671721: rightTile }) - graph.patcher.update({ - 4672508: leftTile }) - graph.patcher.update({ - 4672509: rightTile }) - graph.patcher.update({ - 4673296: leftTile }) - graph.patcher.update({ - 4673297: rightTile }) - graph.patcher.update({ - 4674087: topTile }) - graph.patcher.update({ - 4674099: bottomTile }) - graph.patcher.update({ - 3945300: tileset }) - graph.patcher.update({ - 5713644: 171 + area }) - source = 'S0-47' - elif elevator == 1: - graph.patcher.update({ - 4669038: leftTile }) - graph.patcher.update({ - 4669039: rightTile }) - graph.patcher.update({ - 4669028: leftTile }) - graph.patcher.update({ - 4669029: rightTile }) - graph.patcher.update({ - 4670106: leftTile }) - graph.patcher.update({ - 4670107: rightTile }) - graph.patcher.update({ - 4670908: leftTile }) - graph.patcher.update({ - 4670909: rightTile }) - graph.patcher.update({ - 4671708: leftTile }) - graph.patcher.update({ - 4671709: rightTile }) - graph.patcher.update({ - 4672494: leftTile }) - graph.patcher.update({ - 4672495: rightTile }) - graph.patcher.update({ - 4674067: leftTile }) - graph.patcher.update({ - 4674068: rightTile }) - graph.patcher.update({ - 4673301: topTile }) - graph.patcher.update({ - 4673315: bottomTile }) - graph.patcher.update({ - 3945240: tileset }) - graph.patcher.update({ - 5713617: 171 + area }) - source = 'S0-45' - elif elevator == 2: - graph.patcher.update({ - 4669001: leftTile }) - graph.patcher.update({ - 4669002: rightTile }) - graph.patcher.update({ - 4669030: leftTile }) - graph.patcher.update({ - 4669031: rightTile }) - graph.patcher.update({ - 4670094: leftTile }) - graph.patcher.update({ - 4670095: rightTile }) - graph.patcher.update({ - 4670896: leftTile }) - graph.patcher.update({ - 4670897: rightTile }) - graph.patcher.update({ - 4671696: leftTile }) - graph.patcher.update({ - 4671697: rightTile }) - graph.patcher.update({ - 4673279: leftTile }) - graph.patcher.update({ - 4673280: rightTile }) - graph.patcher.update({ - 4674079: leftTile }) - graph.patcher.update({ - 4674080: rightTile }) - graph.patcher.update({ - 4672499: topTile }) - graph.patcher.update({ - 4672513: bottomTile }) - graph.patcher.update({ - 3945180: tileset }) - graph.patcher.update({ - 5713597: 171 + area }) - source = 'S0-43' - elif elevator == 3: - graph.patcher.update({ - 4669012: leftTile }) - graph.patcher.update({ - 4669013: rightTile }) - graph.patcher.update({ - 4669057: leftTile }) - graph.patcher.update({ - 4669058: rightTile }) - graph.patcher.update({ - 4670884: leftTile }) - graph.patcher.update({ - 4670885: rightTile }) - graph.patcher.update({ - 4671684: leftTile }) - graph.patcher.update({ - 4671685: rightTile }) - graph.patcher.update({ - 4672489: leftTile }) - graph.patcher.update({ - 4672490: rightTile }) - graph.patcher.update({ - 4673291: leftTile }) - graph.patcher.update({ - 4673292: rightTile }) - graph.patcher.update({ - 4674091: leftTile }) - graph.patcher.update({ - 4674092: rightTile }) - graph.patcher.update({ - 4670111: topTile }) - graph.patcher.update({ - 4670125: bottomTile }) - graph.patcher.update({ - 3945000: tileset }) - graph.patcher.update({ - 5713600: 171 + area }) - source = 'S0-44' - elif elevator == 4: - graph.patcher.update({ - 4669049: leftTile }) - graph.patcher.update({ - 4669050: rightTile }) - graph.patcher.update({ - 4669059: leftTile }) - graph.patcher.update({ - 4669060: rightTile }) - graph.patcher.update({ - 4670115: leftTile }) - graph.patcher.update({ - 4670116: rightTile }) - graph.patcher.update({ - 4671672: leftTile }) - graph.patcher.update({ - 4671673: rightTile }) - graph.patcher.update({ - 4672503: leftTile }) - graph.patcher.update({ - 4672504: rightTile }) - graph.patcher.update({ - 4673305: leftTile }) - graph.patcher.update({ - 4673306: rightTile }) - graph.patcher.update({ - 4674103: leftTile }) - graph.patcher.update({ - 4674104: rightTile }) - graph.patcher.update({ - 4670913: topTile }) - graph.patcher.update({ - 4670927: bottomTile }) - graph.patcher.update({ - 3945060: tileset }) - graph.patcher.update({ - 5713621: 171 + area }) - source = 'S0-46' - elif elevator == 5: - graph.patcher.update({ - 4669089: leftTile }) - graph.patcher.update({ - 4669090: rightTile }) - graph.patcher.update({ - 4669061: leftTile }) - graph.patcher.update({ - 4669062: rightTile }) - graph.patcher.update({ - 4670129: leftTile }) - graph.patcher.update({ - 4670130: rightTile }) - graph.patcher.update({ - 4670917: leftTile }) - graph.patcher.update({ - 4670918: rightTile }) - graph.patcher.update({ - 4672517: leftTile }) - graph.patcher.update({ - 4672518: rightTile }) - graph.patcher.update({ - 4673319: leftTile }) - graph.patcher.update({ - 4673320: rightTile }) - graph.patcher.update({ - 4674115: leftTile }) - graph.patcher.update({ - 4674116: rightTile }) - graph.patcher.update({ - 4671701: topTile }) - graph.patcher.update({ - 4671713: bottomTile }) - graph.patcher.update({ - 3945120: tileset }) - graph.patcher.update({ - 5713647: 171 + area }) - source = 'S0-48' - destination = 'S{}-00'.format(area) - graph.UpdateDoorConnection(source, destination) - graph.UpdateDoorConnection(destination, source) - source = areaDoors.get(area)[0] - destination = areaDoors.get(leftArea)[1] - graph.UpdateDoorConnection(source, destination) - source = areaDoors.get(area)[1] - destination = areaDoors.get(rightArea)[0] - graph.UpdateDoorConnection(source, destination) - graph.ConnectAllNodes() - PlacedETanks = PlacedMissiles = PlacedPowerBombs = 0 - if SeedSettings['DamageRuns']: - Energy = PlacedETanks * 100 + 99 - MissileCount = 10 - locationWeights.clear() - locationsPerArea.clear() - areaWeights.clear() - weightValue.clear() - MajorLocations.clear() - MinorLocations.clear() - AllItemLocations.clear() - newLocations.clear() - AccessibleLocations.clear() - UsedLocations.clear() - PlacedItems.clear() - NettoriOpen = False - invalidItems.clear() - invalidWeights.clear() - oldLocations.clear() - oldWeights.clear() - MajorLocations.extend(graph.majorItemLocations) - if SeedSettings['MajorMinor'] == False: - MajorLocations.extend(graph.minorItemLocations) - MinorLocations.extend(graph.minorItemLocations) - AllItemLocations.extend(graph.majorItemLocations) - AllItemLocations.extend(graph.minorItemLocations) - random.shuffle(MajorLocations) - random.shuffle(MinorLocations) - random.shuffle(AllItemLocations) - for item in MajorItems: - disable_item(graph, item) - disable_item(graph, 'BlueDoors') - disable_item(graph, 'GreenDoors') - disable_item(graph, 'YellowDoors') - disable_item(graph, 'RedDoors') - disable_item(graph, 'WaterLowered') - for area in range(0, 7): - AreaOpen[area] = None - locationsPerArea.append(list()) - areaWeights.append(1) - weightValue.append(1) - MajorList = list(WeightedMajors.keys()) - if SeedSettings['MissilesWithoutMainData']: - WeightedMajors.update({ - 'MainMissiles': 8 }) - WeightedMajors.update({ - 'SuperMissileItem': 8 }) - WeightedMajors.update({ - 'IceMissileItem': 8 }) - WeightedMajors.update({ - 'DiffusionItem': 8 }) - if SeedSettings['PowerBombsWithoutBombs']: - WeightedMajors.update({ - 'Bombs': 10 }) - WeightedMajors.update({ - 'MainPowerBombs': 10 }) - if SeedSettings['DamageRuns']: - WeightedMajors.update({ - 'VariaSuit': 4 }) - MajorWeights = list(WeightedMajors.values()) - MajorWeights.pop(MajorList.index('Bombs')) - MajorList.remove('Bombs') - MajorWeights.pop(MajorList.index('MainPowerBombs')) - MajorList.remove('MainPowerBombs') - if SeedSettings['MissilesWithoutMainData'] == False: - MajorWeights.pop(MajorList.index('IceMissileItem')) - MajorList.remove('IceMissileItem') - MajorWeights.pop(MajorList.index('SuperMissileItem')) - MajorList.remove('SuperMissileItem') - MajorWeights.pop(MajorList.index('DiffusionItem')) - MajorList.remove('DiffusionItem') - if weightInit == False: - availableItems.clear() - path = None - for location in MajorLocations: - path = graph.get_path(StartLocation, location) - if path != None: - pass - - if path == None: - print('No accessible locations found with this start, try changing your game settings.') - sys.exit(1) - else: + while True: + if not gameBeatable == False: + if not init == False: + if not 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: + if areaLayout[2] != 1: + if areaLayout[2] != 2: + if areaLayout[3] != 1: + if areaLayout[3] != 2: + attemptedLayouts.append(areaLayout) + while True: + if areaLayout in attemptedLayouts: + areaLayout = random.sample(range(1, 7), 6) + + while True: + pass + + 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: - enable_item(graph, item) - currentItemWeight = 0 - find_available_areas(graph) + 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: - currentItemWeight += 1 - if currentItemWeight > 1: - availableItems.append(item) - + break + + if path == None: + print('Path: 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') - continue - weightInit = True - if len(availableItems) < 1: - print('No accessible locations found with this start, try changing your game settings.') - sys.exit(1) - find_available_areas(graph) - for location in MajorLocations: - path = graph.get_path(StartLocation, location) - if path != None: - AccessibleLocations.append(location) - for area in range(0, 7): - if location in AreaItemLocations[area] and location not in locationsPerArea[area]: - locationsPerArea[area].append(location) - continue - continue + + weightInit = True + if len(availableItems) < 1: + print('Items: 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 len(locationsPerArea[area]) > 0: - areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) - continue - for location in AccessibleLocations: - for area in range(0, 7): - if location in AreaItemLocations[area]: - locationWeights.append(areaWeights[area]) - continue - continue - if FirstItem == None: - FirstItem = random.choice(availableItems) - MajorWeights.pop(MajorList.index(FirstItem)) - MajorList.remove(FirstItem) - enable_item(graph, FirstItem) - path = None - if SeedSettings['DamageRuns']: - Energy = Energy / 2 - if path == None: - location = random.choice(AccessibleLocations) - path = graph.get_path(location, StartLocation) - if path != None: - locationWeights.pop(AccessibleLocations.index(location)) - AccessibleLocations.remove(location) - UsedLocations.append(location) - PlacedItems.append(FirstItem) - for area in range(0, 7): - if location not in AreaItemLocations[area]: - weightValue[area] += 1 - continue - continue - if FirstItem == 'MainMissiles' or SeedSettings['MissilesWithoutMainData'] == False: - MajorList.append('IceMissileItem') - MajorWeights.append(WeightedMajors.get('IceMissileItem')) - MajorList.append('SuperMissileItem') - MajorWeights.append(WeightedMajors.get('SuperMissileItem')) - MajorList.append('DiffusionItem') - MajorWeights.append(WeightedMajors.get('DiffusionItem')) + 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 True: + if not 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' and SeedSettings['PowerBombsWithoutBombs'] == False: + 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 and location not in AccessibleLocations or location == 'Data S0' or location == 'Item S0-05-16': - path = graph.get_path(location, StartLocation, 250, **('depth',)) - else: - for area in range(0, 7): - if location in AreaItemLocations[area] and AreaOpen[area]: - path = graph.get_path(AreaOpen[area], location, True) - + 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: - AccessibleLocations.append(location) - MajorLocations.remove(location) - newLocations.append(location) - for area in range(0, 7): - if location in AreaItemLocations[area] and location not in locationsPerArea[area]: + gameBeatable = True + if not gameBeatable == False: + newLocations.clear() + locationWeights.clear() + for location in MajorLocations: + path = None + if location not in UsedLocations: + if location not in AccessibleLocations: + if not location == 'Data S0' or location == 'Item S0-05-16': + path = graph.get_path(location, StartLocation, depth=250) + 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) - continue - continue + + 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) + else: + if location in BossLocations: + if SeedSettings['MajorMinor'] == False: + locationWeights.append(areaWeights[area] * 1.5) + locationWeights.append(areaWeights[area]) + + if not 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 True: + if not path == None: + if not 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 len(locationsPerArea[area]) > 0 or SeedSettings['MajorMinor']: - areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) + if itemLocation in AreaItemLocations[area]: + if AreaOpen[area]: + path = graph.get_path(itemLocation, AreaOpen[area], True) + break + + if not itemLocation in BossLocations: + if not path != None: + disable_item(graph, item) + if ChargeBeam == False: + if SeedSettings['Difficulty'] > 0: + healthCheck = BossHealths.get(itemLocation) + if SeedSettings['Difficulty'] > 4: + healthCheck = healthCheck * 1.02 + elif SeedSettings['Difficulty'] > 2: + healthCheck = healthCheck * 1.05 else: - areaWeights[area] = weightValue[area] / len(locationsPerArea[area]) + area - for location in AccessibleLocations: - for area in range(0, 7): - if location in AreaItemLocations[area] or location in newLocations: - locationWeights.append(areaWeights[area] * 1.8) - elif location in BossLocations and SeedSettings['MajorMinor'] == False: - locationWeights.append(areaWeights[area] * 1.5) - else: - locationWeights.append(areaWeights[area]) - if len(MajorList) > 0: - itemLocation = None - path = None - item = random.choices(MajorList, MajorWeights, 1, **('weights', 'k'))[0] - currentItemWeight = MajorWeights.pop(MajorList.index(item)) - MajorList.remove(item) - enable_item(graph, item) - if SeedSettings['DamageRuns']: - Energy = Energy / 2 - if path == None and len(AccessibleLocations) > 0: - itemLocation = random.choices(AccessibleLocations, locationWeights, 1, **('weights', 'k'))[0] - oldLocationWeight = locationWeights.pop(AccessibleLocations.index(itemLocation)) - AccessibleLocations.remove(itemLocation) - if itemLocation == 'Data S0' or itemLocation == 'Item S0-05-16': - path = graph.get_path(itemLocation, StartLocation, 250, **('depth',)) - else: - for area in range(0, 7): - if itemLocation in AreaItemLocations[area] and AreaOpen[area]: - path = graph.get_path(itemLocation, AreaOpen[area], True) - - if itemLocation in BossLocations and path != None: - disable_item(graph, item) - if ChargeBeam == False and SeedSettings['Difficulty'] > 0: - healthCheck = BossHealths.get(itemLocation) - if SeedSettings['Difficulty'] > 4: - healthCheck = healthCheck * 1.02 - elif SeedSettings['Difficulty'] > 2: - healthCheck = healthCheck * 1.05 + 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: - healthCheck = healthCheck * 1.1 - healthCheck = healthCheck - MissileDamage * MissileCount - if healthCheck > 0: - if MissileDamage > 0: - tankCheck = math.ceil(healthCheck / MissileDamage / 5) - PossibleMissileTanks.clear() - if SeedSettings['MajorMinor']: - for missileLocation in MinorLocations: - if missileLocation not in UsedLocations: - missilePath = None - if missileLocation == 'Item S0-05-16': - missilePath = graph.get_path(StartLocation, missileLocation, 250, **('depth',)) - if missilePath != None: - missilePath = graph.get_path(missileLocation, StartLocation, 250, **('depth',)) - else: - for area in range(0, 7): - if missileLocation in AreaItemLocations[area] and AreaOpen[area]: - missilePath = graph.get_path(AreaOpen[area], missileLocation, True) - if missilePath != None: - missilePath = graph.get_path(missileLocation, AreaOpen[area], True) - - if missilePath != None: - PossibleMissileTanks.append(missileLocation) - continue - else: - for missileLocation in AccessibleLocations: - missilePath = None - if missileLocation == 'Data S0' or missileLocation == 'Item S0-05-16': - missilePath = graph.get_path(missileLocation, StartLocation, 250, **('depth',)) - else: - for area in range(0, 7): - if missileLocation in AreaItemLocations[area] and AreaOpen[area]: - missilePath = graph.get_path(missileLocation, AreaOpen[area], True) - - if missilePath != None and missileLocation not in BossLocations: - PossibleMissileTanks.append(missileLocation) - continue - if len(PossibleMissileTanks) > int(tankCheck): - for x in range(0, int(tankCheck)): - missileLocation = random.choice(PossibleMissileTanks) - PossibleMissileTanks.remove(missileLocation) - if SeedSettings['MajorMinor'] == False: - locationWeights.pop(AccessibleLocations.index(missileLocation)) - AccessibleLocations.remove(missileLocation) - UsedLocations.append(missileLocation) - PlacedItems.append('Missile Tank') - PlacedMissiles += 1 - MissileCount = 10 + PlacedMissiles * 5 - update_items(graph) - else: - path = None - else: - path = None - enable_item(graph, item) - if path == None: - oldLocations.append(itemLocation) - oldWeights.append(oldLocationWeight) - continue - if path == None: - if len(MajorList) > 0 and len(PlacedItems) > 4: - invalidItems.append(item) - invalidWeights.append(currentItemWeight) - AccessibleLocations.extend(oldLocations) - oldLocations.clear() - locationWeights.extend(oldWeights) - oldWeights.clear() - disable_item(graph, item) - else: - for item in MajorItems: - disable_item(graph, item) - print("Couldn't find a path forward, trying again") - init = False + 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: - UsedLocations.append(itemLocation) - PlacedItems.append(item) - MajorList.extend(invalidItems) - invalidItems.clear() - MajorWeights.extend(invalidWeights) - invalidWeights.clear() - AccessibleLocations.extend(oldLocations) - oldLocations.clear() - locationWeights.extend(oldWeights) - oldWeights.clear() - for area in range(0, 7): - if itemLocation in locationsPerArea[area]: - locationsPerArea[area].remove(itemLocation) - if itemLocation not in AreaItemLocations[area]: - weightValue[area] += 1 - continue - if item == 'MainMissiles' or SeedSettings['MissilesWithoutMainData'] == False: - MajorList.append('IceMissileItem') - MajorWeights.append(WeightedMajors.get('IceMissileItem')) - MajorList.append('SuperMissileItem') - MajorWeights.append(WeightedMajors.get('SuperMissileItem')) - MajorList.append('DiffusionItem') - MajorWeights.append(WeightedMajors.get('DiffusionItem')) - elif item == 'MorphBall': - MajorList.append('Bombs') - MajorWeights.append(WeightedMajors.get('Bombs')) - if SeedSettings['PowerBombsWithoutBombs'] == True: - MajorList.append('MainPowerBombs') - MajorWeights.append(WeightedMajors.get('MainPowerBombs')) - elif item == 'Bombs' and SeedSettings['PowerBombsWithoutBombs'] == False: - MajorList.append('MainPowerBombs') - MajorWeights.append(WeightedMajors.get('MainPowerBombs')) - if SeedSettings['MajorMinor'] == False and len(AccessibleLocations) > 3 and PlacedETanks < MaxETanks: - itemLocation = random.choice(AccessibleLocations) - locationWeights.pop(AccessibleLocations.index(itemLocation)) - AccessibleLocations.remove(itemLocation) - UsedLocations.append(itemLocation) - PlacedItems.append('Energy Tank') - PlacedETanks += 1 - else: - for item in MajorItems: - disable_item(graph, item) - print("Couldn't find a path forward, trying again") - init = False - # continue - print('Game is beatable, placing remaining items (no logic)') - for item in MajorItems: - if item not in PlacedItems and item not in MajorList: + for missileLocation in AccessibleLocations: + missilePath = None + if not missileLocation == 'Data S0' or missileLocation == 'Item S0-05-16': + missilePath = graph.get_path(missileLocation, StartLocation, depth=250) + 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 + + elif 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 not 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 + 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)) - continue - MajorLocations.extend(AccessibleLocations) - for item in MajorList: - if item not in PlacedItems: - location = random.choice(MajorLocations) - if location in UsedLocations: - MajorLocations.remove(location) - location = random.choice(MajorLocations) - continue + 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(item) - if SeedSettings['MajorMinor']: - for location in MajorLocations: - if PlacedETanks < MaxETanks and location not in UsedLocations: - UsedLocations.append(location) - PlacedItems.append(MinorItems[0]) - PlacedETanks += 1 - continue - MaxETanks = PlacedETanks - if PlacedETanks >= MaxETanks: - MinorItems.remove('Energy Tank') + 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 and location not in UsedLocations: - item = random.choice(MinorItems) - UsedLocations.append(location) - PlacedItems.append(item) - if item == 'Energy Tank': - PlacedETanks += 1 - if PlacedETanks >= MaxETanks: - MinorItems.remove('Energy Tank') - elif item == 'Missile Tank': - PlacedMissiles += 1 - if PlacedMissiles >= MaxMissiles: - MinorItems.remove('Missile Tank') - elif item == 'Power Bomb Tank': - PlacedPowerBombs += 1 - if PlacedPowerBombs >= MaxPowerBombs: - MinorItems.remove('Power Bomb Tank') - continue - patch_game() - continue - return None + 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') + else: + if item == 'Missile Tank': + PlacedMissiles += 1 + if not PlacedMissiles >= MaxMissiles: + MinorItems.remove('Missile Tank') + if item == 'Power Bomb Tank': + PlacedPowerBombs += 1 + if PlacedPowerBombs >= MaxPowerBombs: + MinorItems.remove('Power Bomb Tank') + patch_game() def patch_game(): - global FileName, FileName, FileName + global FileName, BaseName CreditsOffsets = { 'ChargeBeam': 7655617, 'WideBeam': 7655725, @@ -4910,10 +4788,10 @@ def patch_game(): patchedGame.seek(offset) patchedGame.write(targetArea.to_bytes(1, 'little')) continue - for target in World.patcher: - value = World.patcher.get(target) - patchedGame.seek(target) - patchedGame.write(value.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: @@ -4997,106 +4875,136 @@ def patch_game(): itemProgression.update({ UsedLocations[x]: PlacedItems[x] }) continue - 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) - return None + 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 HashList, HashList, AreaOpen, Energy, WallJumpSetting, InfiniteBombJump, BackwardsLabs, MaxETanks, MaxMissiles, MaxPowerBombs, PlacedETanks, PlacedMissiles, PlacedPowerBombs, MissileDamage, MissileCount, MajorItems, MinorItems, BossDataList, ItemList, PlacedItems, BossLocations, AccessibleLocations, UsedLocations + 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() - return None + 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 BaseGame, Debug, SeedValue, SeedValue, Patch, Patch, SeedSettings, SeedValue, Difficulty, DamageRuns, World, AreaItemLocations, RoomNodes, StartLocation + 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 == '': - sys.exit('Error: no base game provided.') + print('Error: no base game provided.') + sys.exit(1) checksum = fileHash(BaseGame) if checksum != 1819625372: - sys.exit('Only Metroid Fusion (U) is supported. Check the CRC32 value: it should be 6C75479C') + 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: - sys.exit('Error: Base patch file has been modified. Please go to https://metroidconstruction.com/ and re-download MFOR.') + 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') @@ -5104,52 +5012,53 @@ def start_randomizer(rom, settings): SeedValue = str(random.randrange(sys.maxsize)) settings.pop('Seed') repeat = 1 - if settings['Num'] and settings['Num'] > repeat: - repeat = settings['Num'] - settings.pop('Num') - if settings['Patch']: - Patch = True - else: - Patch = False - settings.pop('Patch') - 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)) - print('DEBUG: Calling Graph creation') - 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) + 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]: @@ -5163,24 +5072,26 @@ def start_randomizer(rom, settings): 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 not 'Item' in name and nodeType == 'Boss': - if nodeType == 'Data': - AreaItemLocations[areaIndex].append(name) - continue - continue - World.ConnectAllNodes() - StartLocation = 'S0-00' - startTime = time.time() - randomize_game(World) - seedTime = time.time() - startTime - print(str(FileName)) - print('Randomized in:', seedTime) - continue - totalRandoTime = time.time() - totalRandoTime - print('All seeds took:', totalRandoTime) - return FileName + else: + if nodeType == 'Data' or item == 'E-Tank': + World.add_to_majors(name) + if name == 'Data S3': + BossLocations.append(name) + if not 'Item' in name: + if not nodeType == 'Boss': + if nodeType == 'Data': + pass + 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