mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00
Super Metroid: Replace random module with world random in variaRandomizer (#4429)
This commit is contained in:
@@ -124,7 +124,7 @@ class SMWorld(World):
|
||||
Logic.factory('vanilla')
|
||||
|
||||
dummy_rom_file = Utils.user_path(SMSettings.RomFile.copy_to) # actual rom set in generate_output
|
||||
self.variaRando = VariaRandomizer(self.options, dummy_rom_file, self.player)
|
||||
self.variaRando = VariaRandomizer(self.options, dummy_rom_file, self.player, self.multiworld.seed, self.random)
|
||||
self.multiworld.state.smbm[self.player] = SMBoolManager(self.player, self.variaRando.maxDifficulty)
|
||||
|
||||
# keeps Nothing items local so no player will ever pickup Nothing
|
||||
@@ -314,11 +314,11 @@ class SMWorld(World):
|
||||
raise KeyError(f"Item {name} for {self.player_name} is invalid.")
|
||||
|
||||
def get_filler_item_name(self) -> str:
|
||||
if self.multiworld.random.randint(0, 100) < self.options.minor_qty.value:
|
||||
if self.random.randint(0, 100) < self.options.minor_qty.value:
|
||||
power_bombs = self.options.power_bomb_qty.value
|
||||
missiles = self.options.missile_qty.value
|
||||
super_missiles = self.options.super_qty.value
|
||||
roll = self.multiworld.random.randint(1, power_bombs + missiles + super_missiles)
|
||||
roll = self.random.randint(1, power_bombs + missiles + super_missiles)
|
||||
if roll <= power_bombs:
|
||||
return "Power Bomb"
|
||||
elif roll <= power_bombs + missiles:
|
||||
@@ -340,8 +340,8 @@ class SMWorld(World):
|
||||
else:
|
||||
nonChozoLoc.append(loc)
|
||||
|
||||
self.multiworld.random.shuffle(nonChozoLoc)
|
||||
self.multiworld.random.shuffle(chozoLoc)
|
||||
self.random.shuffle(nonChozoLoc)
|
||||
self.random.shuffle(chozoLoc)
|
||||
missingCount = len(self.NothingPool) - len(nonChozoLoc)
|
||||
locations = nonChozoLoc
|
||||
if (missingCount > 0):
|
||||
|
@@ -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