mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Super Metroid: Replace random module with world random in variaRandomizer (#4429)
This commit is contained in:
@@ -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':
|
||||
|
||||
Reference in New Issue
Block a user