Super Metroid: Replace random module with world random in variaRandomizer (#4429)
This commit is contained in:
		| @@ -1,5 +1,4 @@ | ||||
| import copy | ||||
| import random | ||||
| from ..logic.logic import Logic | ||||
| from ..utils.parameters import Knows | ||||
| from ..graph.location import locationsDict | ||||
| @@ -136,7 +135,8 @@ class GraphUtils: | ||||
|                 refused[apName] = cause | ||||
|         return ret, refused | ||||
|  | ||||
|     def updateLocClassesStart(startGraphArea, split, possibleMajLocs, preserveMajLocs, nLocs): | ||||
|     @staticmethod | ||||
|     def updateLocClassesStart(startGraphArea, split, possibleMajLocs, preserveMajLocs, nLocs, random): | ||||
|         locs = locationsDict | ||||
|         preserveMajLocs = [locs[locName] for locName in preserveMajLocs if locs[locName].isClass(split)] | ||||
|         possLocs = [locs[locName] for locName in possibleMajLocs][:nLocs] | ||||
| @@ -160,7 +160,8 @@ class GraphUtils: | ||||
|         ap = getAccessPoint(startApName) | ||||
|         return ap.Start['patches'] if 'patches' in ap.Start else [] | ||||
|  | ||||
|     def createBossesTransitions(): | ||||
|     @staticmethod | ||||
|     def createBossesTransitions(random): | ||||
|         transitions = vanillaBossesTransitions | ||||
|         def isVanilla(): | ||||
|             for t in vanillaBossesTransitions: | ||||
| @@ -180,13 +181,15 @@ class GraphUtils: | ||||
|                 transitions.append((src,dst)) | ||||
|         return transitions | ||||
|  | ||||
|     def createAreaTransitions(lightAreaRando=False): | ||||
|     @staticmethod | ||||
|     def createAreaTransitions(lightAreaRando=False, *, random): | ||||
|         if lightAreaRando: | ||||
|             return GraphUtils.createLightAreaTransitions() | ||||
|             return GraphUtils.createLightAreaTransitions(random=random) | ||||
|         else: | ||||
|             return GraphUtils.createRegularAreaTransitions() | ||||
|             return GraphUtils.createRegularAreaTransitions(random=random) | ||||
|  | ||||
|     def createRegularAreaTransitions(apList=None, apPred=None): | ||||
|     @staticmethod | ||||
|     def createRegularAreaTransitions(apList=None, apPred=None, *, random): | ||||
|         if apList is None: | ||||
|             apList = Logic.accessPoints | ||||
|         if apPred is None: | ||||
| @@ -239,7 +242,8 @@ class GraphUtils: | ||||
|             transitions.append((ap.Name, ap.Name)) | ||||
|  | ||||
|     # crateria can be forced in corner cases | ||||
|     def createMinimizerTransitions(startApName, locLimit, forcedAreas=None): | ||||
|     @staticmethod | ||||
|     def createMinimizerTransitions(startApName, locLimit, forcedAreas=None, *, random): | ||||
|         if forcedAreas is None: | ||||
|             forcedAreas = [] | ||||
|         if startApName == 'Ceres': | ||||
| @@ -316,7 +320,8 @@ class GraphUtils: | ||||
|         GraphUtils.log.debug("FINAL MINIMIZER areas: "+str(areas)) | ||||
|         return transitions | ||||
|  | ||||
|     def createLightAreaTransitions(): | ||||
|     @staticmethod | ||||
|     def createLightAreaTransitions(random): | ||||
|         # group APs by area | ||||
|         aps = {} | ||||
|         totalCount = 0 | ||||
| @@ -407,7 +412,8 @@ class GraphUtils: | ||||
|  | ||||
|         return rooms | ||||
|  | ||||
|     def escapeAnimalsTransitions(graph, possibleTargets, firstEscape): | ||||
|     @staticmethod | ||||
|     def escapeAnimalsTransitions(graph, possibleTargets, firstEscape, random): | ||||
|         n = len(possibleTargets) | ||||
|         assert (n < 4 and firstEscape is not None) or (n <= 4 and firstEscape is None), "Invalid possibleTargets list: " + str(possibleTargets) | ||||
|         GraphUtils.log.debug("escapeAnimalsTransitions. possibleTargets="+str(possibleTargets)+", firstEscape="+str(firstEscape)) | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import random | ||||
| from ..utils import log | ||||
| from ..utils.utils import getRangeDict, chooseFromRange | ||||
| from ..rando.ItemLocContainer import ItemLocation | ||||
| @@ -23,8 +22,9 @@ class Choice(object): | ||||
|  | ||||
| # simple random choice, that chooses an item first, then a locatio to put it in | ||||
| class ItemThenLocChoice(Choice): | ||||
|     def __init__(self, restrictions): | ||||
|     def __init__(self, restrictions, random): | ||||
|         super(ItemThenLocChoice, self).__init__(restrictions) | ||||
|         self.random = random | ||||
|  | ||||
|     def chooseItemLoc(self, itemLocDict, isProg): | ||||
|         itemList = self.getItemList(itemLocDict) | ||||
| @@ -49,7 +49,7 @@ class ItemThenLocChoice(Choice): | ||||
|         return self.chooseItemRandom(itemList) | ||||
|  | ||||
|     def chooseItemRandom(self, itemList): | ||||
|         return random.choice(itemList) | ||||
|         return self.random.choice(itemList) | ||||
|  | ||||
|     def chooseLocation(self, locList, item, isProg): | ||||
|         if len(locList) == 0: | ||||
| @@ -63,12 +63,12 @@ class ItemThenLocChoice(Choice): | ||||
|         return self.chooseLocationRandom(locList) | ||||
|  | ||||
|     def chooseLocationRandom(self, locList): | ||||
|         return random.choice(locList) | ||||
|         return self.random.choice(locList) | ||||
|  | ||||
| # Choice specialization for prog speed based filler | ||||
| class ItemThenLocChoiceProgSpeed(ItemThenLocChoice): | ||||
|     def __init__(self, restrictions, progSpeedParams, distanceProp, services): | ||||
|         super(ItemThenLocChoiceProgSpeed, self).__init__(restrictions) | ||||
|     def __init__(self, restrictions, progSpeedParams, distanceProp, services, random): | ||||
|         super(ItemThenLocChoiceProgSpeed, self).__init__(restrictions, random) | ||||
|         self.progSpeedParams = progSpeedParams | ||||
|         self.distanceProp = distanceProp | ||||
|         self.services = services | ||||
| @@ -104,7 +104,7 @@ class ItemThenLocChoiceProgSpeed(ItemThenLocChoice): | ||||
|         if self.restrictions.isLateMorph() and canRollback and len(itemLocDict) == 1: | ||||
|             item, locList = list(itemLocDict.items())[0] | ||||
|             if item.Type == 'Morph': | ||||
|                 morphLocs = self.restrictions.lateMorphCheck(container, locList) | ||||
|                 morphLocs = self.restrictions.lateMorphCheck(container, locList, self.random) | ||||
|                 if morphLocs is not None: | ||||
|                     itemLocDict[item] = morphLocs | ||||
|                 else: | ||||
| @@ -115,7 +115,7 @@ class ItemThenLocChoiceProgSpeed(ItemThenLocChoice): | ||||
|                 assert len(locs) == 1 and locs[0].Name == item.Name | ||||
|                 return ItemLocation(item, locs[0]) | ||||
|         # late doors check for random door colors | ||||
|         if self.restrictions.isLateDoors() and random.random() < self.lateDoorsProb: | ||||
|         if self.restrictions.isLateDoors() and self.random.random() < self.lateDoorsProb: | ||||
|             self.processLateDoors(itemLocDict, ap, container) | ||||
|         self.progressionItemLocs = progressionItemLocs | ||||
|         self.ap = ap | ||||
| @@ -145,14 +145,14 @@ class ItemThenLocChoiceProgSpeed(ItemThenLocChoice): | ||||
|  | ||||
|     def chooseLocationProg(self, locs, item): | ||||
|         locs = self.getLocsSpreadProgression(locs) | ||||
|         random.shuffle(locs) | ||||
|         self.random.shuffle(locs) | ||||
|         ret = self.getChooseFunc(self.chooseLocRanges, self.chooseLocFuncs)(locs) | ||||
|         self.log.debug('chooseLocationProg. ret='+ret.Name) | ||||
|         return ret | ||||
|  | ||||
|     # get choose function from a weighted dict | ||||
|     def getChooseFunc(self, rangeDict, funcDict): | ||||
|         v = chooseFromRange(rangeDict) | ||||
|         v = chooseFromRange(rangeDict, self.random) | ||||
|  | ||||
|         return funcDict[v] | ||||
|  | ||||
| @@ -209,6 +209,6 @@ class ItemThenLocChoiceProgSpeed(ItemThenLocChoice): | ||||
|         for i in range(len(availableLocations)): | ||||
|             loc = availableLocations[i] | ||||
|             d = distances[i] | ||||
|             if d == maxDist or random.random() >= self.spreadProb: | ||||
|             if d == maxDist or self.random.random() >= self.spreadProb: | ||||
|                 locs.append(loc) | ||||
|         return locs | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| import copy, time, random | ||||
| import copy, time | ||||
| from ..utils import log | ||||
| from ..logic.cache import RequestCache | ||||
| from ..rando.RandoServices import RandoServices | ||||
| @@ -15,11 +15,11 @@ from ..graph.graph_utils import GraphUtils | ||||
| # item pool is not empty). | ||||
| # entry point is generateItems | ||||
| class Filler(object): | ||||
|     def __init__(self, startAP, graph, restrictions, emptyContainer, endDate=infinity): | ||||
|     def __init__(self, startAP, graph, restrictions, emptyContainer, endDate=infinity, *, random): | ||||
|         self.startAP = startAP | ||||
|         self.cache = RequestCache() | ||||
|         self.graph = graph | ||||
|         self.services = RandoServices(graph, restrictions, self.cache) | ||||
|         self.services = RandoServices(graph, restrictions, self.cache, random=random) | ||||
|         self.restrictions = restrictions | ||||
|         self.settings = restrictions.settings | ||||
|         self.endDate = endDate | ||||
| @@ -108,9 +108,9 @@ class Filler(object): | ||||
|  | ||||
| # very simple front fill algorithm with no rollback and no "softlock checks" (== dessy algorithm) | ||||
| class FrontFiller(Filler): | ||||
|     def __init__(self, startAP, graph, restrictions, emptyContainer, endDate=infinity): | ||||
|         super(FrontFiller, self).__init__(startAP, graph, restrictions, emptyContainer, endDate) | ||||
|         self.choice = ItemThenLocChoice(restrictions) | ||||
|     def __init__(self, startAP, graph, restrictions, emptyContainer, endDate=infinity, *, random): | ||||
|         super(FrontFiller, self).__init__(startAP, graph, restrictions, emptyContainer, endDate, random=random) | ||||
|         self.choice = ItemThenLocChoice(restrictions, random) | ||||
|         self.stdStart = GraphUtils.isStandardStart(self.startAP) | ||||
|  | ||||
|     def isEarlyGame(self): | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| import random, copy | ||||
| import copy | ||||
| from ..utils import log | ||||
| from ..graph.graph_utils import GraphUtils, vanillaTransitions, vanillaBossesTransitions, escapeSource, escapeTargets, graphAreas, getAccessPoint | ||||
| from ..logic.logic import Logic | ||||
| @@ -11,13 +11,14 @@ from collections import defaultdict | ||||
|  | ||||
| # creates graph and handles randomized escape | ||||
| class GraphBuilder(object): | ||||
|     def __init__(self, graphSettings): | ||||
|     def __init__(self, graphSettings, random): | ||||
|         self.graphSettings = graphSettings | ||||
|         self.areaRando = graphSettings.areaRando | ||||
|         self.bossRando = graphSettings.bossRando | ||||
|         self.escapeRando = graphSettings.escapeRando | ||||
|         self.minimizerN = graphSettings.minimizerN | ||||
|         self.log = log.get('GraphBuilder') | ||||
|         self.random = random | ||||
|  | ||||
|     # builds everything but escape transitions | ||||
|     def createGraph(self, maxDiff): | ||||
| @@ -48,18 +49,18 @@ class GraphBuilder(object): | ||||
|                             objForced = forcedAreas.intersection(escAreas) | ||||
|                             escAreasList = sorted(list(escAreas)) | ||||
|                             while len(objForced) < n and len(escAreasList) > 0: | ||||
|                                 objForced.add(escAreasList.pop(random.randint(0, len(escAreasList)-1))) | ||||
|                                 objForced.add(escAreasList.pop(self.random.randint(0, len(escAreasList)-1))) | ||||
|                             forcedAreas = forcedAreas.union(objForced) | ||||
|                 transitions = GraphUtils.createMinimizerTransitions(self.graphSettings.startAP, self.minimizerN, sorted(list(forcedAreas))) | ||||
|                 transitions = GraphUtils.createMinimizerTransitions(self.graphSettings.startAP, self.minimizerN, sorted(list(forcedAreas)), random=self.random) | ||||
|             else: | ||||
|                 if not self.bossRando: | ||||
|                     transitions += vanillaBossesTransitions | ||||
|                 else: | ||||
|                     transitions += GraphUtils.createBossesTransitions() | ||||
|                     transitions += GraphUtils.createBossesTransitions(self.random) | ||||
|                 if not self.areaRando: | ||||
|                     transitions += vanillaTransitions | ||||
|                 else: | ||||
|                     transitions += GraphUtils.createAreaTransitions(self.graphSettings.lightAreaRando) | ||||
|                     transitions += GraphUtils.createAreaTransitions(self.graphSettings.lightAreaRando, random=self.random) | ||||
|         ret = AccessGraph(Logic.accessPoints, transitions, self.graphSettings.dotFile) | ||||
|         Objectives.objDict[self.graphSettings.player].setGraph(ret, maxDiff) | ||||
|         return ret | ||||
| @@ -100,7 +101,7 @@ class GraphBuilder(object): | ||||
|         self.escapeTimer(graph, paths, self.areaRando or escapeTrigger is not None) | ||||
|         self.log.debug("escapeGraph: ({}, {}) timer: {}".format(escapeSource, dst, graph.EscapeAttributes['Timer'])) | ||||
|         # animals | ||||
|         GraphUtils.escapeAnimalsTransitions(graph, possibleTargets, dst) | ||||
|         GraphUtils.escapeAnimalsTransitions(graph, possibleTargets, dst, self.random) | ||||
|         return True | ||||
|  | ||||
|     def _getTargets(self, sm, graph, maxDiff): | ||||
| @@ -110,7 +111,7 @@ class GraphBuilder(object): | ||||
|         if len(possibleTargets) == 0: | ||||
|             self.log.debug("Can't randomize escape, fallback to vanilla") | ||||
|             possibleTargets.append('Climb Bottom Left') | ||||
|         random.shuffle(possibleTargets) | ||||
|         self.random.shuffle(possibleTargets) | ||||
|         return possibleTargets | ||||
|  | ||||
|     def getPossibleEscapeTargets(self, emptyContainer, graph, maxDiff): | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| from ..utils.utils import randGaussBounds, getRangeDict, chooseFromRange | ||||
| from ..utils import log | ||||
| import logging, copy, random | ||||
| import logging, copy | ||||
|  | ||||
| class Item: | ||||
|     __slots__ = ( 'Category', 'Class', 'Name', 'Code', 'Type', 'BeamBits', 'ItemBits', 'Id' ) | ||||
| @@ -335,7 +335,7 @@ class ItemManager: | ||||
|         itemCode = item.Code + modifier | ||||
|         return itemCode | ||||
|  | ||||
|     def __init__(self, majorsSplit, qty, sm, nLocs, bossesItems, maxDiff): | ||||
|     def __init__(self, majorsSplit, qty, sm, nLocs, bossesItems, maxDiff, random): | ||||
|         self.qty = qty | ||||
|         self.sm = sm | ||||
|         self.majorsSplit = majorsSplit | ||||
| @@ -344,6 +344,7 @@ class ItemManager: | ||||
|         self.maxDiff = maxDiff | ||||
|         self.majorClass = 'Chozo' if majorsSplit == 'Chozo' else 'Major' | ||||
|         self.itemPool = [] | ||||
|         self.random = random | ||||
|  | ||||
|     def newItemPool(self, addBosses=True): | ||||
|         self.itemPool = [] | ||||
| @@ -386,7 +387,7 @@ class ItemManager: | ||||
|             return ItemManager.Items[itemType].withClass(itemClass) | ||||
|  | ||||
|     def createItemPool(self, exclude=None): | ||||
|         itemPoolGenerator = ItemPoolGenerator.factory(self.majorsSplit, self, self.qty, self.sm, exclude, self.nLocs, self.maxDiff) | ||||
|         itemPoolGenerator = ItemPoolGenerator.factory(self.majorsSplit, self, self.qty, self.sm, exclude, self.nLocs, self.maxDiff, self.random) | ||||
|         self.itemPool = itemPoolGenerator.getItemPool() | ||||
|  | ||||
|     @staticmethod | ||||
| @@ -402,20 +403,20 @@ class ItemPoolGenerator(object): | ||||
|     nbBosses = 9 | ||||
|  | ||||
|     @staticmethod | ||||
|     def factory(majorsSplit, itemManager, qty, sm, exclude, nLocs, maxDiff): | ||||
|     def factory(majorsSplit, itemManager, qty, sm, exclude, nLocs, maxDiff, random): | ||||
|         if majorsSplit == 'Chozo': | ||||
|             return ItemPoolGeneratorChozo(itemManager, qty, sm, maxDiff) | ||||
|             return ItemPoolGeneratorChozo(itemManager, qty, sm, maxDiff, random) | ||||
|         elif majorsSplit == 'Plando': | ||||
|             return ItemPoolGeneratorPlando(itemManager, qty, sm, exclude, nLocs, maxDiff) | ||||
|             return ItemPoolGeneratorPlando(itemManager, qty, sm, exclude, nLocs, maxDiff, random) | ||||
|         elif nLocs == ItemPoolGenerator.maxLocs: | ||||
|             if majorsSplit == "Scavenger": | ||||
|                 return ItemPoolGeneratorScavenger(itemManager, qty, sm, maxDiff) | ||||
|                 return ItemPoolGeneratorScavenger(itemManager, qty, sm, maxDiff, random) | ||||
|             else: | ||||
|                 return ItemPoolGeneratorMajors(itemManager, qty, sm, maxDiff) | ||||
|                 return ItemPoolGeneratorMajors(itemManager, qty, sm, maxDiff, random) | ||||
|         else: | ||||
|             return ItemPoolGeneratorMinimizer(itemManager, qty, sm, nLocs, maxDiff) | ||||
|             return ItemPoolGeneratorMinimizer(itemManager, qty, sm, nLocs, maxDiff, random) | ||||
|  | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff): | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff, random): | ||||
|         self.itemManager = itemManager | ||||
|         self.qty = qty | ||||
|         self.sm = sm | ||||
| @@ -423,12 +424,13 @@ class ItemPoolGenerator(object): | ||||
|         self.maxEnergy = 18 # 14E, 4R | ||||
|         self.maxDiff = maxDiff | ||||
|         self.log = log.get('ItemPool') | ||||
|         self.random = random | ||||
|  | ||||
|     def isUltraSparseNoTanks(self): | ||||
|         # if low stuff botwoon is not known there is a hard energy req of one tank, even | ||||
|         # with both suits | ||||
|         lowStuffBotwoon = self.sm.knowsLowStuffBotwoon() | ||||
|         return random.random() < 0.5 and (lowStuffBotwoon.bool == True and lowStuffBotwoon.difficulty <= self.maxDiff) | ||||
|         return self.random.random() < 0.5 and (lowStuffBotwoon.bool == True and lowStuffBotwoon.difficulty <= self.maxDiff) | ||||
|  | ||||
|     def calcMaxMinors(self): | ||||
|         pool = self.itemManager.getItemPool() | ||||
| @@ -464,7 +466,7 @@ class ItemPoolGenerator(object): | ||||
|             rangeDict = getRangeDict(ammoQty) | ||||
|             self.log.debug("rangeDict: {}".format(rangeDict)) | ||||
|             while len(self.itemManager.getItemPool()) < maxItems: | ||||
|                 item = chooseFromRange(rangeDict) | ||||
|                 item = chooseFromRange(rangeDict, self.random) | ||||
|                 self.itemManager.addMinor(item) | ||||
|         else: | ||||
|             minorsTypes = ['Missile', 'Super', 'PowerBomb'] | ||||
| @@ -522,7 +524,7 @@ class ItemPoolGeneratorChozo(ItemPoolGenerator): | ||||
|                 # no etank nor reserve | ||||
|                 self.itemManager.removeItem('ETank') | ||||
|                 self.itemManager.addItem('NoEnergy', 'Chozo') | ||||
|             elif random.random() < 0.5: | ||||
|             elif self.random.random() < 0.5: | ||||
|                 # replace only etank with reserve | ||||
|                 self.itemManager.removeItem('ETank') | ||||
|                 self.itemManager.addItem('Reserve', 'Chozo') | ||||
| @@ -535,9 +537,9 @@ class ItemPoolGeneratorChozo(ItemPoolGenerator): | ||||
|             # 4-6 | ||||
|             # already 3E and 1R | ||||
|             alreadyInPool = 4 | ||||
|             rest = randGaussBounds(2, 5) | ||||
|             rest = randGaussBounds(self.random, 2, 5) | ||||
|             if rest >= 1: | ||||
|                 if random.random() < 0.5: | ||||
|                 if self.random.random() < 0.5: | ||||
|                     self.itemManager.addItem('Reserve', 'Minor') | ||||
|                 else: | ||||
|                     self.itemManager.addItem('ETank', 'Minor') | ||||
| @@ -550,13 +552,13 @@ class ItemPoolGeneratorChozo(ItemPoolGenerator): | ||||
|             # 8-12 | ||||
|             # add up to 3 Reserves or ETanks (cannot add more than 3 reserves) | ||||
|             for i in range(3): | ||||
|                 if random.random() < 0.5: | ||||
|                 if self.random.random() < 0.5: | ||||
|                     self.itemManager.addItem('Reserve', 'Minor') | ||||
|                 else: | ||||
|                     self.itemManager.addItem('ETank', 'Minor') | ||||
|             # 7 already in the pool (3 E, 1 R, + the previous 3) | ||||
|             alreadyInPool = 7 | ||||
|             rest = 1 + randGaussBounds(4, 3.7) | ||||
|             rest = 1 + randGaussBounds(self.random, 4, 3.7) | ||||
|             for i in range(rest): | ||||
|                 self.itemManager.addItem('ETank', 'Minor') | ||||
|             # fill the rest with NoEnergy | ||||
| @@ -581,10 +583,10 @@ class ItemPoolGeneratorChozo(ItemPoolGenerator): | ||||
|         return self.itemManager.getItemPool() | ||||
|  | ||||
| class ItemPoolGeneratorMajors(ItemPoolGenerator): | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff): | ||||
|         super(ItemPoolGeneratorMajors, self).__init__(itemManager, qty, sm, maxDiff) | ||||
|         self.sparseRest = 1 + randGaussBounds(2, 5) | ||||
|         self.mediumRest = 3 + randGaussBounds(4, 3.7) | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff, random): | ||||
|         super(ItemPoolGeneratorMajors, self).__init__(itemManager, qty, sm, maxDiff, random) | ||||
|         self.sparseRest = 1 + randGaussBounds(self.random,2, 5) | ||||
|         self.mediumRest = 3 + randGaussBounds(self.random, 4, 3.7) | ||||
|         self.ultraSparseNoTanks = self.isUltraSparseNoTanks() | ||||
|  | ||||
|     def addNoEnergy(self): | ||||
| @@ -609,7 +611,7 @@ class ItemPoolGeneratorMajors(ItemPoolGenerator): | ||||
|                 # no energy at all | ||||
|                 self.addNoEnergy() | ||||
|             else: | ||||
|                 if random.random() < 0.5: | ||||
|                 if self.random.random() < 0.5: | ||||
|                     self.itemManager.addItem('ETank') | ||||
|                 else: | ||||
|                     self.itemManager.addItem('Reserve') | ||||
| @@ -620,7 +622,7 @@ class ItemPoolGeneratorMajors(ItemPoolGenerator): | ||||
|  | ||||
|         elif energyQty == 'sparse': | ||||
|             # 4-6 | ||||
|             if random.random() < 0.5: | ||||
|             if self.random.random() < 0.5: | ||||
|                 self.itemManager.addItem('Reserve') | ||||
|             else: | ||||
|                 self.itemManager.addItem('ETank') | ||||
| @@ -639,7 +641,7 @@ class ItemPoolGeneratorMajors(ItemPoolGenerator): | ||||
|             alreadyInPool = 2 | ||||
|             n = getE(3) | ||||
|             for i in range(n): | ||||
|                 if random.random() < 0.5: | ||||
|                 if self.random.random() < 0.5: | ||||
|                     self.itemManager.addItem('Reserve') | ||||
|                 else: | ||||
|                     self.itemManager.addItem('ETank') | ||||
| @@ -676,15 +678,15 @@ class ItemPoolGeneratorMajors(ItemPoolGenerator): | ||||
|         return self.itemManager.getItemPool() | ||||
|  | ||||
| class ItemPoolGeneratorScavenger(ItemPoolGeneratorMajors): | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff): | ||||
|         super(ItemPoolGeneratorScavenger, self).__init__(itemManager, qty, sm, maxDiff) | ||||
|     def __init__(self, itemManager, qty, sm, maxDiff, random): | ||||
|         super(ItemPoolGeneratorScavenger, self).__init__(itemManager, qty, sm, maxDiff, random) | ||||
|  | ||||
|     def addNoEnergy(self): | ||||
|         self.itemManager.addItem('Nothing') | ||||
|  | ||||
| class ItemPoolGeneratorMinimizer(ItemPoolGeneratorMajors): | ||||
|     def __init__(self, itemManager, qty, sm, nLocs, maxDiff): | ||||
|         super(ItemPoolGeneratorMinimizer, self).__init__(itemManager, qty, sm, maxDiff) | ||||
|     def __init__(self, itemManager, qty, sm, nLocs, maxDiff, random): | ||||
|         super(ItemPoolGeneratorMinimizer, self).__init__(itemManager, qty, sm, maxDiff, random) | ||||
|         self.maxItems = nLocs | ||||
|         self.calcMaxAmmo() | ||||
|         nMajors = len([itemName for itemName,item in ItemManager.Items.items() if item.Class == 'Major' and item.Category != 'Energy']) | ||||
| @@ -716,8 +718,8 @@ class ItemPoolGeneratorMinimizer(ItemPoolGeneratorMajors): | ||||
|         self.log.debug("maxEnergy: "+str(self.maxEnergy)) | ||||
|  | ||||
| class ItemPoolGeneratorPlando(ItemPoolGenerator): | ||||
|     def __init__(self, itemManager, qty, sm, exclude, nLocs, maxDiff): | ||||
|         super(ItemPoolGeneratorPlando, self).__init__(itemManager, qty, sm, maxDiff) | ||||
|     def __init__(self, itemManager, qty, sm, exclude, nLocs, maxDiff, random): | ||||
|         super(ItemPoolGeneratorPlando, self).__init__(itemManager, qty, sm, maxDiff, random) | ||||
|         # in exclude dict: | ||||
|         #   in alreadyPlacedItems: | ||||
|         #     dict of 'itemType: count' of items already added in the plando. | ||||
| @@ -805,7 +807,7 @@ class ItemPoolGeneratorPlando(ItemPoolGenerator): | ||||
|             if ammoQty: | ||||
|                 rangeDict = getRangeDict(ammoQty) | ||||
|                 while len(self.itemManager.getItemPool()) < maxItems and remain > 0: | ||||
|                     item = chooseFromRange(rangeDict) | ||||
|                     item = chooseFromRange(rangeDict, self.random) | ||||
|                     self.itemManager.addMinor(item) | ||||
|                     remain -= 1 | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import sys, random, time | ||||
| import sys, time | ||||
|  | ||||
| from ..utils import log | ||||
| from ..logic.logic import Logic | ||||
| @@ -14,7 +14,7 @@ from ..utils.doorsmanager import DoorsManager | ||||
|  | ||||
| # entry point for rando execution ("randomize" method) | ||||
| class RandoExec(object): | ||||
|     def __init__(self, seedName, vcr, randoSettings, graphSettings, player): | ||||
|     def __init__(self, seedName, vcr, randoSettings, graphSettings, player, random): | ||||
|         self.errorMsg = "" | ||||
|         self.seedName = seedName | ||||
|         self.vcr = vcr | ||||
| @@ -22,6 +22,7 @@ class RandoExec(object): | ||||
|         self.graphSettings = graphSettings | ||||
|         self.log = log.get('RandoExec') | ||||
|         self.player = player | ||||
|         self.random = random | ||||
|  | ||||
|     # processes settings to : | ||||
|     # - create Restrictions and GraphBuilder objects | ||||
| @@ -31,7 +32,7 @@ class RandoExec(object): | ||||
|         vcr = VCR(self.seedName, 'rando') if self.vcr == True else None | ||||
|         self.errorMsg = "" | ||||
|         split = self.randoSettings.restrictions['MajorMinor'] | ||||
|         self.graphBuilder = GraphBuilder(self.graphSettings) | ||||
|         self.graphBuilder = GraphBuilder(self.graphSettings, self.random) | ||||
|         container = None | ||||
|         i = 0 | ||||
|         attempts = 500 if self.graphSettings.areaRando or self.graphSettings.doorsColorsRando or split == 'Scavenger' else 1 | ||||
| @@ -43,10 +44,10 @@ class RandoExec(object): | ||||
|         while container is None and i < attempts and now <= endDate: | ||||
|             self.restrictions = Restrictions(self.randoSettings) | ||||
|             if self.graphSettings.doorsColorsRando == True: | ||||
|                 DoorsManager.randomize(self.graphSettings.allowGreyDoors, self.player) | ||||
|                 DoorsManager.randomize(self.graphSettings.allowGreyDoors, self.player, self.random) | ||||
|             self.areaGraph = self.graphBuilder.createGraph(self.randoSettings.maxDiff) | ||||
|             services = RandoServices(self.areaGraph, self.restrictions) | ||||
|             setup = RandoSetup(self.graphSettings, Logic.locations[:], services, self.player) | ||||
|             services = RandoServices(self.areaGraph, self.restrictions, random=self.random) | ||||
|             setup = RandoSetup(self.graphSettings, Logic.locations[:], services, self.player, self.random) | ||||
|             self.setup = setup | ||||
|             container = setup.createItemLocContainer(endDate, vcr) | ||||
|             if container is None: | ||||
| @@ -78,7 +79,7 @@ class RandoExec(object): | ||||
|                 n = nMaj | ||||
|             elif split == 'Chozo': | ||||
|                 n = nChozo | ||||
|             GraphUtils.updateLocClassesStart(startAP.GraphArea, split, possibleMajLocs, preserveMajLocs, n) | ||||
|             GraphUtils.updateLocClassesStart(startAP.GraphArea, split, possibleMajLocs, preserveMajLocs, n, self.random) | ||||
|  | ||||
|     def postProcessItemLocs(self, itemLocs, hide): | ||||
|         # hide some items like in dessy's | ||||
| @@ -89,7 +90,7 @@ class RandoExec(object): | ||||
|                 if (item.Category != "Nothing" | ||||
|                     and loc.CanHidden == True | ||||
|                     and loc.Visibility == 'Visible'): | ||||
|                     if bool(random.getrandbits(1)) == True: | ||||
|                     if bool(self.random.getrandbits(1)) == True: | ||||
|                         loc.Visibility = 'Hidden' | ||||
|         # put nothing in unfilled locations | ||||
|         filledLocNames = [il.Location.Name for il in itemLocs] | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
|  | ||||
| import copy, random, sys, logging, os | ||||
| import copy, sys, logging, os | ||||
| from enum import Enum, unique | ||||
| from ..utils import log | ||||
| from ..utils.parameters import infinity | ||||
| @@ -19,12 +18,13 @@ class ComebackCheckType(Enum): | ||||
|  | ||||
| # collection of stateless services to be used mainly by fillers | ||||
| class RandoServices(object): | ||||
|     def __init__(self, graph, restrictions, cache=None): | ||||
|     def __init__(self, graph, restrictions, cache=None, *, random): | ||||
|         self.restrictions = restrictions | ||||
|         self.settings = restrictions.settings | ||||
|         self.areaGraph = graph | ||||
|         self.cache = cache | ||||
|         self.log = log.get('RandoServices') | ||||
|         self.random = random | ||||
|  | ||||
|     @staticmethod | ||||
|     def printProgress(s): | ||||
| @@ -217,7 +217,7 @@ class RandoServices(object): | ||||
|                     # choose a morph item location in that context | ||||
|                     morphItemLoc = ItemLocation( | ||||
|                         morph, | ||||
|                         random.choice(morphLocs) | ||||
|                         self.random.choice(morphLocs) | ||||
|                     ) | ||||
|                     # acquire morph in new context and see if we can still open new locs | ||||
|                     newAP = self.collect(ap, containerCpy, morphItemLoc) | ||||
| @@ -232,7 +232,7 @@ class RandoServices(object): | ||||
|         if morphLocItem is None or len(itemLocDict) == 1: | ||||
|             # no morph, or it is the only possibility: nothing to do | ||||
|             return | ||||
|         morphLocs = self.restrictions.lateMorphCheck(container, itemLocDict[morphLocItem]) | ||||
|         morphLocs = self.restrictions.lateMorphCheck(container, itemLocDict[morphLocItem], self.random) | ||||
|         if morphLocs is not None: | ||||
|             itemLocDict[morphLocItem] = morphLocs | ||||
|         else: | ||||
| @@ -380,10 +380,10 @@ class RandoServices(object): | ||||
|         (itemLocDict, isProg) = self.getPossiblePlacements(ap, container, ComebackCheckType.NoCheck) | ||||
|         assert not isProg | ||||
|         items = list(itemLocDict.keys()) | ||||
|         random.shuffle(items) | ||||
|         self.random.shuffle(items) | ||||
|         for item in items: | ||||
|             cont = copy.copy(container) | ||||
|             loc = random.choice(itemLocDict[item]) | ||||
|             loc = self.random.choice(itemLocDict[item]) | ||||
|             itemLoc1 = ItemLocation(item, loc) | ||||
|             self.log.debug("itemLoc1 attempt: "+getItemLocStr(itemLoc1)) | ||||
|             newAP = self.collect(ap, cont, itemLoc1) | ||||
| @@ -391,8 +391,8 @@ class RandoServices(object): | ||||
|                 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])) | ||||
|                 item2 = self.random.choice(list(ild.keys())) | ||||
|                 itemLoc2 = ItemLocation(item2, self.random.choice(ild[item2])) | ||||
|                 self.log.debug("itemLoc2: "+getItemLocStr(itemLoc2)) | ||||
|                 return (itemLoc1, itemLoc2) | ||||
|         return None | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
|  | ||||
| import sys, random | ||||
| import sys | ||||
| from collections import defaultdict | ||||
| from ..rando.Items import ItemManager | ||||
| from ..utils.utils import getRangeDict, chooseFromRange | ||||
| @@ -32,11 +31,11 @@ class RandoSettings(object): | ||||
|     def isPlandoRando(self): | ||||
|         return self.PlandoOptions is not None | ||||
|  | ||||
|     def getItemManager(self, smbm, nLocs, bossesItems): | ||||
|     def getItemManager(self, smbm, nLocs, bossesItems, random): | ||||
|         if not self.isPlandoRando(): | ||||
|             return ItemManager(self.restrictions['MajorMinor'], self.qty, smbm, nLocs, bossesItems, self.maxDiff) | ||||
|             return ItemManager(self.restrictions['MajorMinor'], self.qty, smbm, nLocs, bossesItems, self.maxDiff, random) | ||||
|         else: | ||||
|             return ItemManager('Plando', self.qty, smbm, nLocs, bossesItems, self.maxDiff) | ||||
|             return ItemManager('Plando', self.qty, smbm, nLocs, bossesItems, self.maxDiff, random) | ||||
|  | ||||
|     def getExcludeItems(self, locations): | ||||
|         if not self.isPlandoRando(): | ||||
| @@ -94,7 +93,7 @@ class ProgSpeedParameters(object): | ||||
|         self.restrictions = restrictions | ||||
|         self.nLocs = nLocs | ||||
|  | ||||
|     def getVariableSpeed(self): | ||||
|     def getVariableSpeed(self, random): | ||||
|         ranges = getRangeDict({ | ||||
|             'slowest':7, | ||||
|             'slow':20, | ||||
| @@ -102,7 +101,7 @@ class ProgSpeedParameters(object): | ||||
|             'fast':27, | ||||
|             'fastest':11 | ||||
|         }) | ||||
|         return chooseFromRange(ranges) | ||||
|         return chooseFromRange(ranges, random) | ||||
|  | ||||
|     def getMinorHelpProb(self, progSpeed): | ||||
|         if self.restrictions.split != 'Major': | ||||
| @@ -134,7 +133,7 @@ class ProgSpeedParameters(object): | ||||
|     def isSlow(self, progSpeed): | ||||
|         return progSpeed == "slow" or (progSpeed == "slowest" and self.restrictions.split == "Chozo") | ||||
|  | ||||
|     def getItemLimit(self, progSpeed): | ||||
|     def getItemLimit(self, progSpeed, random): | ||||
|         itemLimit = self.nLocs | ||||
|         if self.isSlow(progSpeed): | ||||
|             itemLimit = int(self.nLocs*0.209) # 21 for 105 | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import copy, random | ||||
| import copy | ||||
|  | ||||
| from ..utils import log | ||||
| from ..utils.utils import randGaussBounds | ||||
| @@ -16,8 +16,9 @@ from ..rom.rom_patches import RomPatches | ||||
| # checks init conditions for the randomizer: processes super fun settings, graph, start location, special restrictions | ||||
| # the entry point is createItemLocContainer | ||||
| class RandoSetup(object): | ||||
|     def __init__(self, graphSettings, locations, services, player): | ||||
|     def __init__(self, graphSettings, locations, services, player, random): | ||||
|         self.sm = SMBoolManager(player, services.settings.maxDiff) | ||||
|         self.random = random | ||||
|         self.settings = services.settings | ||||
|         self.graphSettings = graphSettings | ||||
|         self.startAP = graphSettings.startAP | ||||
| @@ -31,7 +32,7 @@ class RandoSetup(object): | ||||
| #        print("nLocs Setup: "+str(len(self.locations))) | ||||
|         # in minimizer we can have some missing boss locs | ||||
|         bossesItems = [loc.BossItemType for loc in self.locations if loc.isBoss()] | ||||
|         self.itemManager = self.settings.getItemManager(self.sm, len(self.locations), bossesItems) | ||||
|         self.itemManager = self.settings.getItemManager(self.sm, len(self.locations), bossesItems, random) | ||||
|         self.forbiddenItems = [] | ||||
|         self.restrictedLocs = [] | ||||
|         self.lastRestricted = [] | ||||
| @@ -165,7 +166,7 @@ class RandoSetup(object): | ||||
|             return True | ||||
|         self.log.debug("********* PRE RANDO START") | ||||
|         container = copy.copy(self.container) | ||||
|         filler = FrontFiller(self.startAP, self.areaGraph, self.restrictions, container) | ||||
|         filler = FrontFiller(self.startAP, self.areaGraph, self.restrictions, container, random=self.random) | ||||
|         condition = filler.createStepCountCondition(4) | ||||
|         (isStuck, itemLocations, progItems) = filler.generateItems(condition) | ||||
|         self.log.debug("********* PRE RANDO END") | ||||
| @@ -345,9 +346,9 @@ class RandoSetup(object): | ||||
|     def getForbiddenItemsFromList(self, itemList): | ||||
|         self.log.debug('getForbiddenItemsFromList: ' + str(itemList)) | ||||
|         remove = [] | ||||
|         n = randGaussBounds(len(itemList)) | ||||
|         n = randGaussBounds(self.random, len(itemList)) | ||||
|         for i in range(n): | ||||
|             idx = random.randint(0, len(itemList) - 1) | ||||
|             idx = self.random.randint(0, len(itemList) - 1) | ||||
|             item = itemList.pop(idx) | ||||
|             if item is not None: | ||||
|                 remove.append(item) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import copy, random | ||||
| import copy | ||||
| from ..utils import log | ||||
| from ..graph.graph_utils import getAccessPoint | ||||
| from ..rando.ItemLocContainer import getLocListStr | ||||
| @@ -112,7 +112,7 @@ class Restrictions(object): | ||||
|             return item.Class == "Minor" | ||||
|  | ||||
|     # return True if we can keep morph as a possibility | ||||
|     def lateMorphCheck(self, container, possibleLocs): | ||||
|     def lateMorphCheck(self, container, possibleLocs, random): | ||||
|         # the closer we get to the limit the higher the chances of allowing morph | ||||
|         proba = random.randint(0, self.lateMorphLimit) | ||||
|         if self.split == 'Full': | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/usr/bin/python3 | ||||
|  | ||||
| from Utils import output_path | ||||
| import argparse, os.path, json, sys, shutil, random, copy, requests | ||||
| import argparse, os.path, json, sys, shutil, copy, requests | ||||
|  | ||||
| from .rando.RandoSettings import RandoSettings, GraphSettings | ||||
| from .rando.RandoExec import RandoExec | ||||
| @@ -39,7 +39,7 @@ objectives = defaultMultiValues['objective'] | ||||
| tourians = defaultMultiValues['tourian'] | ||||
| areaRandomizations = defaultMultiValues['areaRandomization'] | ||||
|  | ||||
| def randomMulti(args, param, defaultMultiValues): | ||||
| def randomMulti(args, param, defaultMultiValues, random): | ||||
|     value = args[param] | ||||
|  | ||||
|     isRandom = False | ||||
| @@ -250,10 +250,11 @@ class VariaRandomizer: | ||||
|     parser.add_argument('--tourianList', help="list to choose from when random", | ||||
|                         dest='tourianList', nargs='?', default=None) | ||||
|  | ||||
|     def __init__(self, options, rom, player): | ||||
|     def __init__(self, options, rom, player, seed, random): | ||||
|         # parse args        | ||||
|         self.args = copy.deepcopy(VariaRandomizer.parser.parse_args(["--logic", "varia"])) #dummy custom args to skip parsing _sys.argv while still get default values | ||||
|         self.player = player | ||||
|         self.random = random | ||||
|         args = self.args | ||||
|         args.rom = rom | ||||
|         # args.startLocation = to_pascal_case_with_space(options.startLocation.current_key) | ||||
| @@ -323,11 +324,13 @@ class VariaRandomizer: | ||||
|  | ||||
|         logger.debug("preset: {}".format(preset)) | ||||
|  | ||||
|         # if no seed given, choose one | ||||
|         if args.seed == 0: | ||||
|             self.seed = random.randrange(sys.maxsize) | ||||
|         else: | ||||
|             self.seed = args.seed | ||||
|         # Archipelago provides a seed for the multiworld. | ||||
|         self.seed = seed | ||||
|         # # if no seed given, choose one | ||||
|         # if args.seed == 0: | ||||
|         #     self.seed = random.randrange(sys.maxsize) | ||||
|         # else: | ||||
|         #     self.seed = args.seed | ||||
|         logger.debug("seed: {}".format(self.seed)) | ||||
|  | ||||
|         if args.raceMagic is not None: | ||||
| @@ -360,12 +363,12 @@ class VariaRandomizer: | ||||
|         logger.debug("maxDifficulty: {}".format(self.maxDifficulty)) | ||||
|  | ||||
|         # handle random parameters with dynamic pool of values | ||||
|         (_, progSpeed) = randomMulti(args.__dict__, "progressionSpeed", speeds) | ||||
|         (_, progDiff) = randomMulti(args.__dict__, "progressionDifficulty", progDiffs) | ||||
|         (majorsSplitRandom, args.majorsSplit) = randomMulti(args.__dict__, "majorsSplit", majorsSplits) | ||||
|         (_, self.gravityBehaviour) = randomMulti(args.__dict__, "gravityBehaviour", gravityBehaviours) | ||||
|         (_, args.tourian) = randomMulti(args.__dict__, "tourian", tourians) | ||||
|         (areaRandom, args.area) = randomMulti(args.__dict__, "area", areaRandomizations) | ||||
|         (_, progSpeed) = randomMulti(args.__dict__, "progressionSpeed", speeds, random) | ||||
|         (_, progDiff) = randomMulti(args.__dict__, "progressionDifficulty", progDiffs, random) | ||||
|         (majorsSplitRandom, args.majorsSplit) = randomMulti(args.__dict__, "majorsSplit", majorsSplits, random) | ||||
|         (_, self.gravityBehaviour) = randomMulti(args.__dict__, "gravityBehaviour", gravityBehaviours, random) | ||||
|         (_, args.tourian) = randomMulti(args.__dict__, "tourian", tourians, random) | ||||
|         (areaRandom, args.area) = randomMulti(args.__dict__, "area", areaRandomizations, random) | ||||
|         areaRandomization = args.area in ['light', 'full'] | ||||
|         lightArea = args.area == 'light' | ||||
|      | ||||
| @@ -626,7 +629,7 @@ class VariaRandomizer: | ||||
|             if args.objective: | ||||
|                 if (args.objectiveRandom): | ||||
|                     availableObjectives = [goal for goal in objectives if goal != "collect 100% items"] if "random" in args.objectiveList else args.objectiveList | ||||
|                     self.objectivesManager.setRandom(args.nbObjective, availableObjectives) | ||||
|                     self.objectivesManager.setRandom(args.nbObjective, availableObjectives, self.random) | ||||
|                 else: | ||||
|                     maxActiveGoals = Objectives.maxActiveGoals - addedObjectives | ||||
|                     if len(args.objective) > maxActiveGoals: | ||||
| @@ -660,7 +663,7 @@ class VariaRandomizer: | ||||
|         #    print("energyQty:{}".format(energyQty)) | ||||
|  | ||||
|         #try: | ||||
|         self.randoExec = RandoExec(seedName, args.vcr, randoSettings, graphSettings, self.player) | ||||
|         self.randoExec = RandoExec(seedName, args.vcr, randoSettings, graphSettings, self.player, self.random) | ||||
|         self.container = self.randoExec.randomize() | ||||
|         # if we couldn't find an area layout then the escape graph is not created either | ||||
|         # and getDoorConnections will crash if random escape is activated. | ||||
| @@ -690,7 +693,7 @@ class VariaRandomizer: | ||||
|                             'gameend.ips', 'grey_door_animals.ips', 'low_timer.ips', 'metalimals.ips', | ||||
|                             'phantoonimals.ips', 'ridleyimals.ips'] | ||||
|             if args.escapeRando == False: | ||||
|                 args.patches.append(random.choice(animalsPatches)) | ||||
|                 args.patches.append(self.random.choice(animalsPatches)) | ||||
|                 args.patches.append("Escape_Animals_Change_Event") | ||||
|             else: | ||||
|                 optErrMsgs.append("Ignored animals surprise because of escape randomization") | ||||
| @@ -760,9 +763,9 @@ class VariaRandomizer: | ||||
|                 # patch local rom | ||||
|                 # romFileName = args.rom | ||||
|                 # shutil.copyfile(romFileName, outputFilename) | ||||
|                 romPatcher = RomPatcher(settings=patcherSettings, magic=args.raceMagic, player=self.player) | ||||
|                 romPatcher = RomPatcher(settings=patcherSettings, magic=args.raceMagic, player=self.player, random=self.random) | ||||
|             else: | ||||
|                 romPatcher = RomPatcher(settings=patcherSettings, magic=args.raceMagic) | ||||
|                 romPatcher = RomPatcher(settings=patcherSettings, magic=args.raceMagic, random=self.random) | ||||
|  | ||||
|             if customPrePatchApply != None: | ||||
|                 customPrePatchApply(romPatcher) | ||||
|   | ||||
| @@ -49,7 +49,7 @@ class RomPatcher: | ||||
|         'DoorsColors': ['beam_doors_plms.ips', 'beam_doors_gfx.ips', 'red_doors.ips'] | ||||
|     } | ||||
|  | ||||
|     def __init__(self, settings=None, romFileName=None, magic=None, player=0): | ||||
|     def __init__(self, settings=None, romFileName=None, magic=None, player=0, *, random): | ||||
|         self.log = log.get('RomPatcher') | ||||
|         self.settings = settings | ||||
|         #self.romFileName = romFileName | ||||
| @@ -76,6 +76,7 @@ class RomPatcher: | ||||
|             0x93ea: self.forceRoomCRE | ||||
|         } | ||||
|         self.player = player | ||||
|         self.random = random | ||||
|  | ||||
|     def patchRom(self): | ||||
|         self.applyIPSPatches() | ||||
| @@ -496,9 +497,9 @@ class RomPatcher: | ||||
|         self.ipsPatches = [] | ||||
|  | ||||
|     def writeSeed(self, seed): | ||||
|         random.seed(seed) | ||||
|         seedInfo = random.randint(0, 0xFFFF) | ||||
|         seedInfo2 = random.randint(0, 0xFFFF) | ||||
|         r = random.Random(seed) | ||||
|         seedInfo = r.randint(0, 0xFFFF) | ||||
|         seedInfo2 = r.randint(0, 0xFFFF) | ||||
|         self.romFile.writeWord(seedInfo, snes_to_pc(0xdfff00)) | ||||
|         self.romFile.writeWord(seedInfo2) | ||||
|  | ||||
| @@ -1066,7 +1067,7 @@ class RomPatcher: | ||||
|  | ||||
|     def writeObjectives(self, itemLocs, tourian): | ||||
|         objectives = Objectives.objDict[self.player] | ||||
|         objectives.writeGoals(self.romFile) | ||||
|         objectives.writeGoals(self.romFile, self.random) | ||||
|         objectives.writeIntroObjectives(self.romFile, tourian) | ||||
|         self.writeItemsMasks(itemLocs) | ||||
|         # hack bomb_torizo.ips to wake BT in all cases if necessary, ie chozo bots objective is on, and nothing at bombs | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import random | ||||
| from enum import IntEnum,IntFlag | ||||
| import copy | ||||
| from ..logic.smbool import SMBool | ||||
| @@ -123,7 +122,7 @@ class Door(object): | ||||
|         else: | ||||
|             return [color for color in colorsList if color not in self.forbiddenColors] | ||||
|  | ||||
|     def randomize(self, allowGreyDoors): | ||||
|     def randomize(self, allowGreyDoors, random): | ||||
|         if self.canRandomize(): | ||||
|             if self.canGrey and allowGreyDoors: | ||||
|                 self.setColor(random.choice(self.filterColorList(colorsListGrey))) | ||||
| @@ -347,9 +346,9 @@ class DoorsManager(): | ||||
|             currentDoors['CrabShaftRight'].forceBlue() | ||||
|  | ||||
|     @staticmethod | ||||
|     def randomize(allowGreyDoors, player): | ||||
|     def randomize(allowGreyDoors, player, random): | ||||
|         for door in DoorsManager.doorsDict[player].values(): | ||||
|             door.randomize(allowGreyDoors) | ||||
|             door.randomize(allowGreyDoors, random) | ||||
|         # set both ends of toilet to the same color to avoid soft locking in area rando | ||||
|         toiletTop = DoorsManager.doorsDict[player]['PlasmaSparkBottom'] | ||||
|         toiletBottom = DoorsManager.doorsDict[player]['OasisTop'] | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import copy | ||||
| import random | ||||
| from ..rom.addresses import Addresses | ||||
| from ..rom.rom import pc_to_snes | ||||
| from ..logic.helpers import Bosses | ||||
| @@ -28,7 +27,7 @@ class Synonyms(object): | ||||
|     ] | ||||
|     alreadyUsed = [] | ||||
|     @staticmethod | ||||
|     def getVerb():  | ||||
|     def getVerb(random): | ||||
|         verb = random.choice(Synonyms.killSynonyms) | ||||
|         while verb in Synonyms.alreadyUsed: | ||||
|             verb = random.choice(Synonyms.killSynonyms) | ||||
| @@ -88,10 +87,10 @@ class Goal(object): | ||||
|         # not all objectives require an ap (like limit objectives) | ||||
|         return self.clearFunc(smbm, ap) | ||||
|  | ||||
|     def getText(self): | ||||
|     def getText(self, random): | ||||
|         out = "{}. ".format(self.rank) | ||||
|         if self.useSynonym: | ||||
|             out += self.text.format(Synonyms.getVerb()) | ||||
|             out += self.text.format(Synonyms.getVerb(random)) | ||||
|         else: | ||||
|             out += self.text | ||||
|         assert len(out) <= 28, "Goal text '{}' is too long: {}, max 28".format(out, len(out)) | ||||
| @@ -676,7 +675,7 @@ class Objectives(object): | ||||
|         return [goal.name for goal in _goals.values() if goal.available and (not removeNothing or goal.name != "nothing")] | ||||
|  | ||||
|     # call from rando | ||||
|     def setRandom(self, nbGoals, availableGoals): | ||||
|     def setRandom(self, nbGoals, availableGoals, random): | ||||
|         while self.nbActiveGoals < nbGoals and availableGoals: | ||||
|             goalName = random.choice(availableGoals) | ||||
|             self.addGoal(goalName) | ||||
| @@ -702,7 +701,7 @@ class Objectives(object): | ||||
|         LOG.debug("tourianRequired: {}".format(self.tourianRequired)) | ||||
|  | ||||
|     # call from rando | ||||
|     def writeGoals(self, romFile): | ||||
|     def writeGoals(self, romFile, random): | ||||
|         # write check functions | ||||
|         romFile.seek(Addresses.getOne('objectivesList')) | ||||
|         for goal in self.activeGoals: | ||||
| @@ -736,7 +735,7 @@ class Objectives(object): | ||||
|         space = 3 if self.nbActiveGoals == 5 else 4 | ||||
|         for i, goal in enumerate(self.activeGoals): | ||||
|             addr = baseAddr + i * lineLength * space | ||||
|             text = goal.getText() | ||||
|             text = goal.getText(random) | ||||
|             romFile.seek(addr) | ||||
|             for c in text: | ||||
|                 if c not in char2tile: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import io | ||||
| import os, json, re, random | ||||
| import os, json, re | ||||
| import pathlib | ||||
| import sys | ||||
| from typing import Any | ||||
| @@ -88,7 +88,7 @@ def normalizeRounding(n): | ||||
|  | ||||
| # gauss random in [0, r] range | ||||
| # the higher the slope, the less probable extreme values are. | ||||
| def randGaussBounds(r, slope=5): | ||||
| def randGaussBounds(random, r, slope=5): | ||||
|     r = float(r) | ||||
|     n = normalizeRounding(random.gauss(r/2, r/slope)) | ||||
|     if n < 0: | ||||
| @@ -111,7 +111,7 @@ def getRangeDict(weightDict): | ||||
|  | ||||
|     return rangeDict | ||||
|  | ||||
| def chooseFromRange(rangeDict): | ||||
| def chooseFromRange(rangeDict, random): | ||||
|     r = random.random() | ||||
|     val = None | ||||
|     for v in sorted(rangeDict, key=rangeDict.get): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Mysteryem
					Mysteryem