SM: failing generation fixes (#1726)
- fixed wrong condition in Collect to assign lastAP - fixed possible infinite loop in generating output when many SM worlds are present - fixed new VARIA code that changed a list used for every SM worlds and would throw if many SM worlds uses Aea rando and not AreaLayout
This commit is contained in:
		
							parent
							
								
									f6758524d5
								
							
						
					
					
						commit
						cb634fa8d4
					
				|  | @ -22,8 +22,9 @@ import Utils | |||
| from .variaRandomizer.logic.smboolmanager import SMBoolManager | ||||
| from .variaRandomizer.graph.vanilla.graph_locations import locationsDict | ||||
| from .variaRandomizer.graph.graph_utils import getAccessPoint | ||||
| from .variaRandomizer.rando.ItemLocContainer import ItemLocation | ||||
| from .variaRandomizer.rando.ItemLocContainer import ItemLocation, ItemLocContainer | ||||
| from .variaRandomizer.rando.Items import ItemManager | ||||
| from .variaRandomizer.rando.RandoServices import ComebackCheckType | ||||
| from .variaRandomizer.utils.parameters import * | ||||
| from .variaRandomizer.utils.utils import openFile | ||||
| from .variaRandomizer.logic.logic import Logic | ||||
|  | @ -169,9 +170,13 @@ class SMWorld(World): | |||
|             elif item.Category == 'Nothing': | ||||
|                 isAdvancement = False | ||||
| 
 | ||||
|             classification = ItemClassification.progression if isAdvancement else ItemClassification.filler | ||||
|             itemClass = ItemManager.Items[item.Type].Class | ||||
|             smitem = SMItem(item.Name, ItemClassification.progression if isAdvancement else ItemClassification.filler, | ||||
|                             item.Type, None if itemClass == 'Boss' else self.item_name_to_id[item.Name], player=self.player) | ||||
|             smitem = SMItem(item.Name,  | ||||
|                             classification,  | ||||
|                             item.Type, | ||||
|                             None if itemClass == 'Boss' else self.item_name_to_id[item.Name],  | ||||
|                             player=self.player) | ||||
|             if itemClass == 'Boss': | ||||
|                 self.locked_items[item.Name] = smitem | ||||
|             elif item.Category == 'Nothing': | ||||
|  | @ -645,10 +650,10 @@ class SMWorld(World): | |||
| 
 | ||||
|     def collect(self, state: CollectionState, item: Item) -> bool: | ||||
|         state.smbm[self.player].addItem(item.type) | ||||
|         if (item.location != None and item.location.player == self.player): | ||||
|             for entrance in self.multiworld.get_region(item.location.parent_region.name, self.player).entrances: | ||||
|         if item.location != None: | ||||
|             for entrance in self.multiworld.get_region(item.location.parent_region.name, item.location.player).entrances: | ||||
|                 if (entrance.parent_region.can_reach(state)): | ||||
|                     state.smbm[self.player].lastAP = entrance.parent_region.name | ||||
|                     state.smbm[item.location.player].lastAP = entrance.parent_region.name | ||||
|                     break | ||||
|         return super(SMWorld, self).collect(state, item) | ||||
| 
 | ||||
|  | @ -797,29 +802,25 @@ class SMLocation(Location): | |||
|     def can_reach(self, state: CollectionState) -> bool: | ||||
|         # self.access_rule computes faster on average, so placing it first for faster abort | ||||
|         assert self.parent_region, "Can't reach location without region" | ||||
|         return self.access_rule(state) and self.parent_region.can_reach(state) and self.can_comeback(state) | ||||
|         return self.access_rule(state) and \ | ||||
|                 self.parent_region.can_reach(state) and \ | ||||
|                 self.can_comeback(state, self.item) | ||||
|      | ||||
|     def can_comeback(self, state: CollectionState): | ||||
|         # some specific early/late game checks | ||||
|         if self.name == 'Bomb' or self.name == 'Mother Brain': | ||||
|             return True | ||||
| 
 | ||||
|     def can_comeback(self, state: CollectionState, item): | ||||
|         randoExec = state.multiworld.worlds[self.player].variaRando.randoExec | ||||
|         randoService = randoExec.setup.services | ||||
| 
 | ||||
|         comebackCheck = ComebackCheckType.JustComeback         | ||||
|         n = 2 if GraphUtils.isStandardStart(randoExec.graphSettings.startAP) else 3 | ||||
|         # is early game | ||||
|         if (len([loc for loc in state.locations_checked if loc.player == self.player]) <= n): | ||||
|             return True | ||||
| 
 | ||||
|         for key in locationsDict[self.name].AccessFrom.keys(): | ||||
|             smbm = state.smbm[self.player] | ||||
|             if (randoExec.areaGraph.canAccess(  smbm,  | ||||
|                                                 smbm.lastAP, | ||||
|                                                 key, | ||||
|                                                 smbm.maxDiff, | ||||
|                                                 None)): | ||||
|                 return True | ||||
|         return False | ||||
|   | ||||
|             comebackCheck = ComebackCheckType.NoCheck | ||||
|         container = ItemLocContainer(state.smbm[self.player], [], []) | ||||
|         return randoService.fullComebackCheck(  container,  | ||||
|                                                 state.smbm[self.player].lastAP,  | ||||
|                                                 ItemManager.Items[item.type] if item is not None and item.player == self.player else None, | ||||
|                                                 locationsDict[self.name],  | ||||
|                                                 comebackCheck)  | ||||
| 
 | ||||
| class SMItem(Item): | ||||
|     game = "Super Metroid" | ||||
|  |  | |||
|  | @ -362,7 +362,8 @@ class AccessGraph(object): | |||
| 
 | ||||
|     # test access from an access point to another, given an optional item | ||||
|     def canAccess(self, smbm, srcAccessPointName, destAccessPointName, maxDiff, item=None): | ||||
|         if item is not None: | ||||
|         addAndRemoveItem = item is not None and (smbm.isCountItem(item) or not smbm.haveItem(item)) | ||||
|         if addAndRemoveItem: | ||||
|             smbm.addItem(item) | ||||
|         #print("canAccess: item: {}, src: {}, dest: {}".format(item, srcAccessPointName, destAccessPointName)) | ||||
|         destAccessPoint = self.accessPoints[destAccessPointName] | ||||
|  | @ -371,7 +372,7 @@ class AccessGraph(object): | |||
|         can = destAccessPoint in availAccessPoints | ||||
|         # if not can: | ||||
|         #     self.log.debug("canAccess KO: avail = {}".format([ap.Name for ap in availAccessPoints.keys()])) | ||||
|         if item is not None: | ||||
|         if addAndRemoveItem: | ||||
|             smbm.removeItem(item) | ||||
|         #print("canAccess: {}".format(can)) | ||||
|         return can | ||||
|  |  | |||
|  | @ -59,9 +59,12 @@ class Location: | |||
| 
 | ||||
|     def evalPostAvailable(self, smbm): | ||||
|         if self.difficulty.bool == True and self.PostAvailable is not None: | ||||
|             smbm.addItem(self.itemName) | ||||
|             addAndRemoveItem = smbm.isCountItem(self.itemName) or not smbm.haveItem(self.itemName) | ||||
|             if addAndRemoveItem: | ||||
|                 smbm.addItem(self.itemName) | ||||
|             postAvailable = self.PostAvailable(smbm) | ||||
|             smbm.removeItem(self.itemName) | ||||
|             if addAndRemoveItem: | ||||
|                 smbm.removeItem(self.itemName) | ||||
| 
 | ||||
|             self.difficulty = self.difficulty & postAvailable | ||||
|             if self.locDifficulty is not None: | ||||
|  |  | |||
|  | @ -91,9 +91,12 @@ class SMBoolManager(object): | |||
|         return itemsDict | ||||
| 
 | ||||
|     def withItem(self, item, func): | ||||
|         self.addItem(item) | ||||
|         addAndRemoveItem = self.isCountItem(item) or not self.haveItem(item) | ||||
|         if addAndRemoveItem: | ||||
|             self.addItem(item) | ||||
|         ret = func(self) | ||||
|         self.removeItem(item) | ||||
|         if addAndRemoveItem: | ||||
|             self.removeItem(item) | ||||
|         return ret | ||||
| 
 | ||||
|     def resetItems(self): | ||||
|  |  | |||
|  | @ -279,11 +279,12 @@ class RomPatcher: | |||
| 
 | ||||
|             # apply area patches | ||||
|             if self.settings["area"] == True: | ||||
|                 areaPatches = list(RomPatcher.IPSPatches['Area']) | ||||
|                 if not self.settings["areaLayout"]: | ||||
|                     for p in ['area_rando_layout.ips', 'Sponge_Bath_Blinking_Door', 'east_ocean.ips', 'aqueduct_bomb_blocks.ips']: | ||||
|                        RomPatcher.IPSPatches['Area'].remove(p) | ||||
|                     RomPatcher.IPSPatches['Area'].append('area_rando_layout_base.ips') | ||||
|                 for patchName in RomPatcher.IPSPatches['Area']: | ||||
|                        areaPatches.remove(p) | ||||
|                     areaPatches.append('area_rando_layout_base.ips') | ||||
|                 for patchName in areaPatches: | ||||
|                     self.applyIPSPatch(patchName) | ||||
|             else: | ||||
|                 self.applyIPSPatch('area_ids_alt.ips') | ||||
|  |  | |||
|  | @ -740,7 +740,7 @@ class Objectives(object): | |||
|                 if c not in char2tile: | ||||
|                     continue | ||||
|                 romFile.writeWord(0x3800 + char2tile[c]) | ||||
| 
 | ||||
|         Synonyms.alreadyUsed = [] | ||||
|         # write goal completed positions y in sprites OAM | ||||
|         baseY = 0x40 | ||||
|         addr = Addresses.getOne('objectivesSpritesOAM') | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue