def findStartupProgItemPair(self, ap, container): self.log.debug("findStartupProgItemPair") (itemLocDict, isProg) = self.getPossiblePlacements(ap, container, ComebackCheckType.NoCheck) assert not isProg items = list(itemLocDict.keys()) random.shuffle(items) for item in items: cont = copy.copy(container) loc = random.choice(itemLocDict[item]) itemLoc1 = ItemLocation(item, loc) self.log.debug("itemLoc1 attempt: "+getItemLocStr(itemLoc1)) newAP = self.collect(ap, cont, itemLoc1) if self.cache is not None: self.cache.reset() (ild, isProg) = self.getPossiblePlacements(newAP, cont, ComebackCheckType.NoCheck) if isProg: item2 = random.choice(list(ild.keys())) itemLoc2 = ItemLocation(item2, random.choice(ild[item2])) self.log.debug("itemLoc2: "+getItemLocStr(itemLoc2)) return (itemLoc1, itemLoc2) return None
def generateItem(self): itemLocDict, possibleProg = self.services.getPossiblePlacements(self.ap, self.container, self.getComebackCheck()) if self.isEarlyGame() and possibleProg == True: # cheat a little bit if non-standard start: place early # progression away from crateria/blue brin if possible startAp = getAccessPoint(self.startAP) if startAp.GraphArea != "Crateria": newItemLocDict = {} for w, locs in itemLocDict.items(): filtered = [loc for loc in locs if loc['GraphArea'] != 'Crateria'] if len(filtered) > 0: newItemLocDict[w] = filtered if len(newItemLocDict) > 0: itemLocDict = newItemLocDict itemLoc = self.chooseItemLoc(itemLocDict, possibleProg) self.log.debug("generateItem. itemLoc="+"None" if itemLoc is None else getItemLocStr(itemLoc)) return itemLoc
def escapeTrigger(self, emptyContainer, graph, maxDiff, escapeTrigger): container = emptyContainer sm = container.sm allItemLocs,progItemLocs,split = escapeTrigger[0],escapeTrigger[1],escapeTrigger[2] # check if crateria is connected, if not replace Tourian # connection with Climb and add special escape patch to Climb if not any(il.Location.GraphArea == "Crateria" for il in allItemLocs): escapeAttr = graph.EscapeAttributes if "patches" not in escapeAttr: escapeAttr['patches'] = [] escapeAttr['patches'] += ['climb_disable_bomb_blocks.ips', "Climb_Asleep"] src, _ = next(t for t in graph.InterAreaTransitions if t[1].Name == "Golden Four") graph.removeTransitions("Golden Four") graph.addTransition(src.Name, "Climb Bottom Left") # disconnect the other side of G4 graph.addTransition("Golden Four", "Golden Four") # remove vanilla escape transition graph.addTransition('Tourian Escape Room 4 Top Right', 'Tourian Escape Room 4 Top Right') # filter garbage itemLocs ilCheck = lambda il: not il.Location.isBoss() and not il.Location.restricted and il.Item.Category != "Nothing" # update item% objectives accessibleItems = [il.Item for il in allItemLocs if ilCheck(il)] majorUpgrades = [item.Type for item in accessibleItems if item.BeamBits != 0 or item.ItemBits != 0] sm.objectives.setItemPercentFuncs(len(accessibleItems), majorUpgrades) if split == "Scavenger": # update escape access for scav with last scav loc lastScavItemLoc = progItemLocs[-1] sm.objectives.updateScavengerEscapeAccess(lastScavItemLoc.Location.accessPoint) sm.objectives.setScavengerHuntFunc(lambda sm, ap: sm.haveItem(lastScavItemLoc.Item.Type)) else: # update "collect all items in areas" funcs availLocsByArea=defaultdict(list) for itemLoc in allItemLocs: if ilCheck(itemLoc) and (split.startswith("Full") or itemLoc.Location.isClass(split)): availLocsByArea[itemLoc.Location.GraphArea].append(itemLoc.Location.Name) self.log.debug("escapeTrigger. availLocsByArea="+str(availLocsByArea)) sm.objectives.setAreaFuncs({area:lambda sm,ap:SMBool(len(container.getLocs(lambda loc: loc.Name in availLocsByArea[area]))==0) for area in availLocsByArea}) self.log.debug("escapeTrigger. collect locs until G4 access") # collect all item/locations up until we can pass G4 (the escape triggers) itemLocs = allItemLocs[:] ap = "Landing Site" # dummy value it'll be overwritten at first collection while len(itemLocs) > 0 and not (sm.canPassG4() and graph.canAccess(sm, ap, "Landing Site", maxDiff)): il = itemLocs.pop(0) if il.Location.restricted: continue self.log.debug("collecting " + getItemLocStr(il)) container.collect(il) ap = il.Location.accessPoint # final update of item% obj collectedLocsAccessPoints = {il.Location.accessPoint for il in container.itemLocations} sm.objectives.updateItemPercentEscapeAccess(list(collectedLocsAccessPoints)) possibleTargets = self._getTargets(sm, graph, maxDiff) # try to escape from all the possible objectives APs possiblePaths = [] for goal in Objectives.activeGoals: n, possibleAccessPoints = goal.escapeAccessPoints count = 0 for ap in possibleAccessPoints: self.log.debug("escapeTrigger. testing AP " + ap) path = graph.accessPath(sm, ap, 'Landing Site', maxDiff) if path is not None: self.log.debug("escapeTrigger. add path from "+ap) possiblePaths.append(path) count += 1 if count < n: # there is a goal we cannot escape from self.log.debug("escapeTrigger. goal %s: found %d/%d possible escapes, abort" % (goal.name, count, n)) return (None, None) # try and get a path from all possible areas self.log.debug("escapeTrigger. completing paths") allAreas = {il.Location.GraphArea for il in allItemLocs if not il.Location.restricted and not il.Location.GraphArea in ["Tourian", "Ceres"]} def getStartArea(path): return path[0].GraphArea def apCheck(ap): nonlocal graph, possiblePaths apObj = graph.accessPoints[ap] return apObj.GraphArea not in [getStartArea(path) for path in possiblePaths] escapeAPs = [ap for ap in collectedLocsAccessPoints if apCheck(ap)] for ap in escapeAPs: path = graph.accessPath(sm, ap, 'Landing Site', maxDiff) if path is not None: self.log.debug("escapeTrigger. add path from "+ap) possiblePaths.append(path) def areaPathCheck(): nonlocal allAreas, possiblePaths startAreas = {getStartArea(path) for path in possiblePaths} return len(allAreas - startAreas) == 0 while not areaPathCheck() and len(itemLocs) > 0: il = itemLocs.pop(0) if il.Location.restricted: continue self.log.debug("collecting " + getItemLocStr(il)) container.collect(il) ap = il.Location.accessPoint if apCheck(ap): path = graph.accessPath(sm, ap, 'Landing Site', maxDiff) if path is not None: self.log.debug("escapeTrigger. add path from "+ap) possiblePaths.append(path) return (possibleTargets, possiblePaths)