Compare commits
	
		
			5 Commits
		
	
	
		
			cbb85e3baa
			...
			d65898994a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d65898994a | |||
| 2e972d876f | |||
| b95fef681f | |||
| ab089feb6e | |||
| 6194d555b8 | 
							
								
								
									
										151
									
								
								Fusion_Graph.py
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								Fusion_Graph.py
									
									
									
									
									
								
							| @ -12,6 +12,7 @@ | ||||
| 
 | ||||
| import struct | ||||
| import sys | ||||
| import time | ||||
| 
 | ||||
| class Game: | ||||
| 
 | ||||
| @ -26,20 +27,11 @@ class Game: | ||||
|         self.queue = list() | ||||
|         self.majorItemLocations = list() | ||||
|         self.minorItemLocations = list() | ||||
|         self.itemLocations = list() | ||||
|         self.itemLocations = set() | ||||
|         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() | ||||
|         self.oldtime = 0.0 | ||||
|         self.bfstime = 0.0 | ||||
|         self.dfstime = 0.0 | ||||
| 
 | ||||
|         # print('DEBUG: Opening ROM to pick stuff') | ||||
| 
 | ||||
| @ -96,6 +88,8 @@ class Game: | ||||
|             sys.exit(1) | ||||
| 
 | ||||
| 
 | ||||
|     def print_stats(self): | ||||
|         print("Path search time: old search = {}s, bfs time = {}s, dfs time = {}s".format(self.oldtime, self.bfstime, self.dfstime)) | ||||
| 
 | ||||
|     def set_setting(self, setting, value): | ||||
|         self.settings[setting] = value | ||||
| @ -182,29 +176,25 @@ class Game: | ||||
| 
 | ||||
| 
 | ||||
|     def add_to_majors(self, item): | ||||
|         if item not in self.itemLocations: | ||||
|             self.itemLocations.append(item) | ||||
|         self.itemLocations.add(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) | ||||
|             self.itemLocations.add(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) | ||||
|         self.itemLocations.add(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) | ||||
|             self.itemLocations.add(item) | ||||
|             if item not in self.minorItemLocations: | ||||
|                 self.minorItemLocations.append(item) | ||||
| 
 | ||||
| @ -213,6 +203,15 @@ class Game: | ||||
|         return self.requirements.get(checkRequirement) | ||||
| 
 | ||||
|     def get_path(self, start, end, LimitArea=False, path=None, depth=100): | ||||
|         #return [start,end] if self.has_path(start,end,LimitArea, depth) else None | ||||
| 
 | ||||
|         t = time.perf_counter() | ||||
|         path = self._get_path(start, end, LimitArea, path, depth) | ||||
|         self.oldtime += time.perf_counter() - t | ||||
| 
 | ||||
|         return path | ||||
| 
 | ||||
|     def _get_path(self, start, end, LimitArea, path, depth): | ||||
|         if path == None: | ||||
|             self.visited.clear() | ||||
|             self.queue.clear() | ||||
| @ -244,12 +243,118 @@ class Game: | ||||
|                     node = edge[1] | ||||
|                     pathReqs = self.get_requirements(start, node) | ||||
|                     if pathReqs == None: | ||||
|                         newpath = self.get_path(node, end, LimitArea, path, depth) | ||||
|                         newpath = self._get_path(node, end, LimitArea, path, depth) | ||||
|                         if newpath: | ||||
|                             path = path + [node] | ||||
|                             return newpath | ||||
|                     elif pathReqs == True: | ||||
|                         newpath = self.get_path(node, end, LimitArea, path, depth) | ||||
|                         newpath = self._get_path(node, end, LimitArea, path, depth) | ||||
|                         if newpath: | ||||
|                             path = path + [node] | ||||
|                             return newpath | ||||
| 
 | ||||
|     def has_path(self, start, end, LimitArea=False, depth=100): | ||||
|         if LimitArea: | ||||
|             area = self.itemArea.get(start) | ||||
|             if area == None: | ||||
|                 for n in range(0, 7): | ||||
|                     if 'S{}'.format(n) in start: | ||||
|                         area = n | ||||
|             if area == None: | ||||
|                 for n in range(0, 7): | ||||
|                     if 'S{}'.format(n) in end: | ||||
|                         area = n | ||||
|         else: | ||||
|             area = None | ||||
|         t = time.perf_counter() | ||||
|         result = self.has_path_bfs(start, end, area=area, max_depth=depth) | ||||
|         self.bfstime += time.perf_counter() - t | ||||
|         t = time.perf_counter() | ||||
|         r2 =self.has_path_dfs(start, end, area=area) | ||||
|         assert result == r2, (start, end, result, r2, area) | ||||
|         self.dfstime += time.perf_counter() - t | ||||
|         return result | ||||
| 
 | ||||
|     # NOTE: both the start and end node need to be excluded from | ||||
|     # area checks because they can be things like bosses or the Water Pump | ||||
|     # that aren't associated with an area. all the intermediate nodes | ||||
|     # should be doors, and doors all have their sector number in their names. | ||||
| 
 | ||||
|     def has_path_bfs(self, start, end, area=None, max_depth=100): | ||||
|         if start not in self.graph: | ||||
|             return False | ||||
|         if start == end: | ||||
|             return True | ||||
|         if area != None: | ||||
|             areaStr = 'S{}'.format(area) | ||||
|         seen = {start} | ||||
|         frontier = [start] | ||||
|         next_frontier = [] | ||||
|         depth = 0 | ||||
|         while frontier: | ||||
|             depth += 1 | ||||
|             #if depth > max_depth: break | ||||
|             for node in frontier: | ||||
|                 for neighbor in self.graph[node]: | ||||
|                     if neighbor in seen: | ||||
|                         continue | ||||
|                     if neighbor in self.itemLocations: | ||||
|                         if neighbor == end: | ||||
|                             pathReqs = self.get_requirements(node, neighbor) | ||||
|                             if pathReqs == None or pathReqs == True: | ||||
|                                 return True | ||||
|                         #seen.add(neighbor) | ||||
|                         continue | ||||
|                     if area is not None: | ||||
|                         if areaStr not in neighbor and neighbor != end: | ||||
|                             continue | ||||
|                     pathReqs = self.get_requirements(node, neighbor) | ||||
|                     if pathReqs != None and pathReqs != True: | ||||
|                         continue    | ||||
|                     if neighbor == end: | ||||
|                         return True | ||||
| 
 | ||||
|                     next_frontier.append(neighbor) | ||||
| 
 | ||||
|                     # since this is a breadth-first search on an unweighted graph, | ||||
|                     # we know that no other paths can be shorter than this one, | ||||
|                     # so we can immediately mark the node as seen to prevent | ||||
|                     # adding it to the frontier again | ||||
|                     seen.add(neighbor) | ||||
| 
 | ||||
|             frontier.clear() | ||||
|             frontier, next_frontier = next_frontier, frontier | ||||
| 
 | ||||
|         return False | ||||
| 
 | ||||
|     def has_path_dfs(self, start, end, area=None): | ||||
|         if start not in self.graph: | ||||
|             return False | ||||
|         if start == end: | ||||
|             return True | ||||
|         visited = set() | ||||
|         stack = [start] | ||||
|         if area != None: | ||||
|             areaStr = 'S{}'.format(area) | ||||
|         while stack: | ||||
|             node = stack.pop() | ||||
|             if node in visited: | ||||
|                 continue | ||||
|             visited.add(node) | ||||
|             if node == end: | ||||
|                 return True | ||||
|             if node is not start: | ||||
|                 if node in self.itemLocations: | ||||
|                     continue | ||||
|                 if area is not None: | ||||
|                     if areaStr not in node: | ||||
|                         continue | ||||
| 
 | ||||
|             for neighbor in reversed(self.graph[node]): | ||||
|                 if neighbor in visited: | ||||
|                     continue | ||||
|                 pathReqs = self.get_requirements(node, neighbor) | ||||
|                 if pathReqs != None and pathReqs != True: | ||||
|                     continue | ||||
|                 stack.append(neighbor) | ||||
|         return False | ||||
|  | ||||
							
								
								
									
										150
									
								
								Randomizer.py
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								Randomizer.py
									
									
									
									
									
								
							| @ -1624,8 +1624,8 @@ def update_requirements(graph): | ||||
| 
 | ||||
| 
 | ||||
| def find_available_areas(graph): | ||||
|     check = int(StartLocation[1:2]) | ||||
|     AreaOpen[check] = StartLocation | ||||
|     AreaOpen[int(StartLocation[1:2])] = StartLocation | ||||
| 
 | ||||
|     if AreaOpen[0] == None: | ||||
|         check = 'S0-32' | ||||
|         path = graph.get_path(StartLocation, check) | ||||
| @ -1633,94 +1633,33 @@ def find_available_areas(graph): | ||||
|             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) | ||||
| 
 | ||||
|     def check_sector(area, check, tunnel1, tunnel2): | ||||
|         if AreaOpen[area] == None: | ||||
|             path = graph.get_path(StartLocation, check) | ||||
|             if path != None: | ||||
|                 AreaOpen[1] = check | ||||
|         if ScrewAttack: | ||||
|             if AreaOpen[1] == None: | ||||
|                 check = 'S1-6B' | ||||
|                 path = graph.get_path(StartLocation, check) | ||||
|                 path = graph.get_path(check, StartLocation) | ||||
|                 if path != None: | ||||
|                     path = graph.get_path(check, StartLocation) | ||||
|                     AreaOpen[area] = check | ||||
|             if ScrewAttack: | ||||
|                 if AreaOpen[area] == None: | ||||
|                     path = graph.get_path(StartLocation, tunnel1) | ||||
|                     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) | ||||
|                         path = graph.get_path(tunnel1, StartLocation) | ||||
|                         if path != None: | ||||
|                             AreaOpen[area] = tunnel1 | ||||
|                 if AreaOpen[area] == None: | ||||
|                     path = graph.get_path(StartLocation, tunnel2) | ||||
|                     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 | ||||
|                         path = graph.get_path(tunnel2, StartLocation) | ||||
|                         if path != None: | ||||
|                             AreaOpen[area] = tunnel2 | ||||
| 
 | ||||
|     check_sector(1, 'S1-00', 'S1-6B', 'S1-68') | ||||
|     check_sector(2, 'S2-00', 'S2-7F', 'S2-82') | ||||
|     check_sector(3, 'S3-00', 'S3-56', 'S3-59') | ||||
|     check_sector(4, 'S4-00', 'S4-6A', 'S4-6C') | ||||
| 
 | ||||
|     if AreaOpen[5] == None: | ||||
|         check = 'S5-00' | ||||
|         path = graph.get_path(StartLocation, check) | ||||
| @ -1736,28 +1675,9 @@ def find_available_areas(graph): | ||||
|                     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 | ||||
| 
 | ||||
|     check_sector(6, 'S6-00', 'S6-51', 'S6-54') | ||||
| 
 | ||||
|     if BlueDoors == False: | ||||
|         path = graph.get_path(StartLocation, 'Security-Level-1', depth=250) | ||||
|         if path != None: | ||||
| @ -2253,6 +2173,7 @@ def randomize_game(graph): | ||||
| 
 | ||||
|             find_available_areas(graph) | ||||
|             for location in MajorLocations: | ||||
|                 # potential find_all_available_items | ||||
|                 path = graph.get_path(StartLocation, location) | ||||
|                 if path != None: | ||||
|                     AccessibleLocations.append(location) | ||||
| @ -2329,8 +2250,9 @@ def randomize_game(graph): | ||||
|                 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) | ||||
|                             path = graph.get_path(StartLocation, location, depth=250) | ||||
|                         else: | ||||
|                             # potential find_all_available_items | ||||
|                             for area in range(0, 7): | ||||
|                                 if location in AreaItemLocations[area]: | ||||
|                                     if AreaOpen[area]: | ||||
| @ -2402,6 +2324,7 @@ def randomize_game(graph): | ||||
|                                         tankCheck = math.ceil(healthCheck / MissileDamage / 5) | ||||
|                                         PossibleMissileTanks.clear() | ||||
|                                         if SeedSettings['MajorMinor']: | ||||
|                                             # potential find_all_available_items + could probably reuse previous result | ||||
|                                             for missileLocation in MinorLocations: | ||||
|                                                 if missileLocation not in UsedLocations: | ||||
|                                                     missilePath = None | ||||
| @ -2928,9 +2851,9 @@ def patch_game(): | ||||
|                 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 }) | ||||
|         itemLocations = sorted(World.itemLocations) | ||||
|         for x in range(0, len(itemLocations)): | ||||
|             itemDict.update({ itemLocations[x]: 0 }) | ||||
|         for x in range(0, len(PlacedItems)): | ||||
|             itemDict.update({ UsedLocations[x]: PlacedItems[x] }) | ||||
|         spoilerLog.update({ 'Items': itemDict }) | ||||
| @ -3135,6 +3058,9 @@ def start_randomizer(rom, settings): | ||||
|         seedTime = time.time() - startTime | ||||
|         print(str(FileName)) | ||||
|         print('Randomized in:', seedTime) | ||||
|         World.print_stats() | ||||
|         print("water lowered:", WaterLowered) | ||||
|         print("len(world.graph) = ", len(World.graph)) | ||||
| 
 | ||||
|     totalRandoTime = time.time() - totalRandoTime | ||||
|     print('All seeds took:', totalRandoTime) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user