251 lines
9.3 KiB
Python
251 lines
9.3 KiB
Python
# Source Generated with Decompyle++
|
|
# File: Fusion_Graph.pyc (Python 3.8)
|
|
|
|
import struct
|
|
import sys
|
|
|
|
class Game:
|
|
|
|
def __init__(self, vanillaGame, randoSettings = (None,)):
|
|
self.graph = dict()
|
|
self.areaConnections = dict()
|
|
self.areaConnectionOffsets = dict()
|
|
self.doorConnections = dict()
|
|
self.rooms = dict()
|
|
self.requirements = dict()
|
|
self.visited = list()
|
|
self.queue = list()
|
|
self.majorItemLocations = list()
|
|
self.minorItemLocations = list()
|
|
self.itemLocations = list()
|
|
self.patcher = dict()
|
|
self.graph.clear()
|
|
self.areaConnections.clear()
|
|
self.areaConnectionOffsets.clear()
|
|
self.doorConnections.clear()
|
|
self.rooms.clear()
|
|
self.requirements.clear()
|
|
self.visited.clear()
|
|
self.queue.clear()
|
|
self.majorItemLocations.clear()
|
|
self.minorItemLocations.clear()
|
|
self.itemLocations.clear()
|
|
self.patcher.clear()
|
|
|
|
print('DEBUG: Opening ROM to pick stuff')
|
|
|
|
try:
|
|
with open(vanillaGame, 'rb') as sourceRom:
|
|
sourceRom.seek(3967888, 0)
|
|
sourceArea = int.from_bytes(sourceRom.read(1), 'little')
|
|
sourceDoor = int.from_bytes(sourceRom.read(1), 'little')
|
|
targetOffset = sourceRom.tell()
|
|
targetArea = int.from_bytes(sourceRom.read(1), 'little')
|
|
if sourceArea != 255:
|
|
self.areaConnections.update({
|
|
'S{}-{:02X}'.format(sourceArea, sourceDoor): targetArea })
|
|
self.areaConnectionOffsets.update({
|
|
'S{}-{:02X}'.format(sourceArea, sourceDoor): targetOffset })
|
|
sourceArea = int.from_bytes(sourceRom.read(1), 'little')
|
|
sourceDoor = int.from_bytes(sourceRom.read(1), 'little')
|
|
targetOffset = sourceRom.tell()
|
|
targetArea = int.from_bytes(sourceRom.read(1), 'little')
|
|
for currentArea in range(7):
|
|
sourceRom.seek(7977108 + currentArea * 4, 0)
|
|
data = sourceRom.read(4)
|
|
unpacked = struct.unpack('<L', data)
|
|
doorData = unpacked[0] - 134217728
|
|
sourceRom.seek(doorData, 0)
|
|
doorNumber = 0
|
|
connectionType = int.from_bytes(sourceRom.read(1), 'little')
|
|
roomNumber = int.from_bytes(sourceRom.read(1), 'little')
|
|
sourceRom.seek(4, 1)
|
|
connectedDoor = int.from_bytes(sourceRom.read(1), 'little')
|
|
sourceRom.seek(5, 1)
|
|
if connectionType == 0 and connectedDoor == 0:
|
|
continue
|
|
sourceNode = 'S{}-{:02X}'.format(currentArea, doorNumber)
|
|
connectedArea = self.areaConnections.get(sourceNode, currentArea)
|
|
targetNode = 'S{}-{:02X}'.format(connectedArea, connectedDoor)
|
|
self.doorConnections.update({
|
|
sourceNode: targetNode })
|
|
roomNumber = format(roomNumber, '02X')
|
|
roomString = 'Room-S{}-{}'.format(currentArea, roomNumber)
|
|
doorString = 'S{}-{:02X}'.format(currentArea, doorNumber)
|
|
print('DEBUG: Adding door {} to S{}-{:02X}'.format(doorNumber, currentArea, roomNumber))
|
|
if roomString in self.rooms:
|
|
self.rooms[roomString].append(doorString)
|
|
else:
|
|
self.rooms[roomString] = [
|
|
doorString]
|
|
doorNumber += 1
|
|
print('DEBUG: Parsing seemingly done?')
|
|
except:
|
|
sys.exit('Error:', vanillaGame, 'could not be opened.')
|
|
|
|
|
|
|
|
def set_setting(self, setting, value):
|
|
self.settings[setting] = value
|
|
|
|
|
|
def get_setting(self, setting):
|
|
return self.settings[setting]
|
|
|
|
|
|
def AddNodeToRoom(self, room, node):
|
|
nodeList = self.rooms.get(room)
|
|
nodeList.append(node)
|
|
nodeList.sort()
|
|
self.rooms.update({
|
|
room: nodeList })
|
|
|
|
|
|
def RemoveNodeFromRoom(self, room, node):
|
|
nodeList = self.rooms.get(room)
|
|
if node in nodeList:
|
|
nodeList.remove(node)
|
|
nodeList.sort()
|
|
self.rooms.update({
|
|
room: nodeList })
|
|
|
|
|
|
def ClearGraph(self):
|
|
self.graph.clear()
|
|
|
|
|
|
def ConnectAllNodes(self):
|
|
self.ClearGraph()
|
|
self.ConnectNodesInRooms()
|
|
self.ConnectNodesBetweenRooms()
|
|
|
|
|
|
def ConnectNodesInRooms(self):
|
|
for room in self.rooms:
|
|
for start in self.rooms[room]:
|
|
for end in self.rooms[room]:
|
|
if start != end:
|
|
self.add_edges(start, end)
|
|
|
|
|
|
def ConnectNodesBetweenRooms(self):
|
|
for connection in self.doorConnections.items():
|
|
if len(connection) == 2:
|
|
self.add_directed_edge(connection[0], connection[1])
|
|
|
|
def UpdateDoorConnection(self, source, destination):
|
|
self.doorConnections.update({
|
|
source: destination })
|
|
connectedArea = self.areaConnections.get(source)
|
|
if connectedArea != None:
|
|
self.areaConnections.update({
|
|
source: int(destination[1:2]) })
|
|
return self.areaConnectionOffsets.get(source)
|
|
|
|
|
|
def AddConnectedNodesToRoom(self, targetRoom, *nodes):
|
|
for currentNode in nodes:
|
|
if targetRoom in self.rooms:
|
|
self.rooms[targetRoom].append(currentNode)
|
|
for targetNode in self.rooms[targetRoom]:
|
|
if currentNode != targetNode:
|
|
self.add_edges(currentNode, targetNode)
|
|
continue
|
|
continue
|
|
self.rooms[targetRoom] = [
|
|
currentNode]
|
|
continue
|
|
return None
|
|
|
|
|
|
def add_directed_edge(self, start, end):
|
|
if start != end:
|
|
if start in self.graph or end not in self.graph[start]:
|
|
self.graph[start].append(end)
|
|
else:
|
|
self.graph[start] = [
|
|
end]
|
|
|
|
def add_edges(self, start, *nodes):
|
|
for end in nodes:
|
|
self.add_directed_edge(start, end)
|
|
self.add_directed_edge(end, start)
|
|
|
|
|
|
def add_to_majors(self, item):
|
|
if item not in self.itemLocations:
|
|
self.itemLocations.append(item)
|
|
if item not in self.majorItemLocations:
|
|
self.majorItemLocations.append(item)
|
|
|
|
|
|
def add_list_to_majors(self, locations):
|
|
for item in locations:
|
|
if item not in self.itemLocations:
|
|
self.itemLocations.append(item)
|
|
if item not in self.majorItemLocations:
|
|
self.majorItemLocations.append(item)
|
|
|
|
def add_to_minors(self, item):
|
|
if item not in self.itemLocations:
|
|
self.itemLocations.append(item)
|
|
if item not in self.minorItemLocations:
|
|
self.minorItemLocations.append(item)
|
|
|
|
def add_list_to_minors(self, locations):
|
|
for item in locations:
|
|
if item not in self.itemLocations:
|
|
self.itemLocations.append(item)
|
|
if item not in self.minorItemLocations:
|
|
self.minorItemLocations.append(item)
|
|
|
|
def get_requirements(self, start, end):
|
|
checkRequirement = (start, end)
|
|
return self.requirements.get(checkRequirement)
|
|
|
|
def get_path(self, start, end, LimitArea, path, depth = (False, None, 100)):
|
|
if path == None:
|
|
self.visited.clear()
|
|
self.queue.clear()
|
|
path = list()
|
|
path = path + [
|
|
start]
|
|
if start not in self.graph:
|
|
return None
|
|
if None == end:
|
|
return path
|
|
# if None(path) >= depth:
|
|
if path >= depth:
|
|
return None
|
|
for point in None.graph[start]:
|
|
if point in self.itemLocations and point not in end:
|
|
continue
|
|
if point in path:
|
|
continue
|
|
if LimitArea:
|
|
for area in range(0, 7):
|
|
if 'S{}'.format(area) in start and 'S{}'.format(area) not in point:
|
|
return None
|
|
edge = (start, point)
|
|
self.queue.append(edge)
|
|
if self.queue:
|
|
edge = self.queue.pop()
|
|
if edge not in self.visited:
|
|
self.visited.append(edge)
|
|
node = edge[1]
|
|
pathReqs = self.get_requirements(start, node)
|
|
if pathReqs == None:
|
|
newpath = self.get_path(node, end, LimitArea, path, depth)
|
|
if newpath:
|
|
path = path + [
|
|
node]
|
|
return newpath
|
|
if pathReqs == True:
|
|
newpath = self.get_path(node, end, LimitArea, path, depth)
|
|
if newpath:
|
|
path = path + [
|
|
node]
|
|
return newpath
|
|
|
|
|