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