Archipelago/worlds/sm/variaRandomizer/rando/RandoExec.py

94 lines
4.1 KiB
Python

import sys, random, time, utils.log
from logic.logic import Logic
from graph.graph_utils import GraphUtils, getAccessPoint
from rando.Restrictions import Restrictions
from rando.RandoServices import RandoServices
from rando.GraphBuilder import GraphBuilder
from rando.RandoSetup import RandoSetup
from rando.Items import ItemManager
from rando.ItemLocContainer import ItemLocation
from utils.vcr import VCR
from utils.doorsmanager import DoorsManager
# entry point for rando execution ("randomize" method)
class RandoExec(object):
def __init__(self, seedName, vcr, randoSettings, graphSettings, player):
self.errorMsg = ""
self.seedName = seedName
self.vcr = vcr
self.randoSettings = randoSettings
self.graphSettings = graphSettings
self.log = utils.log.get('RandoExec')
self.player = player
# processes settings to :
# - create Restrictions and GraphBuilder objects
# - create graph and item loc container using a RandoSetup instance: in area rando, if it fails, iterate on possible graph layouts
# return container
def randomize(self):
vcr = VCR(self.seedName, 'rando') if self.vcr == True else None
self.errorMsg = ""
split = self.randoSettings.restrictions['MajorMinor']
graphBuilder = GraphBuilder(self.graphSettings)
container = None
i = 0
attempts = 500 if self.graphSettings.areaRando or self.graphSettings.doorsColorsRando or split == 'Scavenger' else 1
now = time.process_time()
endDate = sys.maxsize
if self.randoSettings.runtimeLimit_s < endDate:
endDate = now + self.randoSettings.runtimeLimit_s
self.updateLocationsClass(split)
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)
self.areaGraph = graphBuilder.createGraph()
services = RandoServices(self.areaGraph, self.restrictions)
setup = RandoSetup(self.graphSettings, Logic.locations, services, self.player)
self.setup = setup
container = setup.createItemLocContainer(endDate, vcr)
if container is None:
sys.stdout.write('*')
sys.stdout.flush()
i += 1
else:
self.errorMsg += '\n'.join(setup.errorMsgs)
now = time.process_time()
if container is None:
if self.graphSettings.areaRando:
self.errorMsg += "Could not find an area layout with these settings"
else:
self.errorMsg += "Unable to process settings"
self.areaGraph.printGraph()
return container
def updateLocationsClass(self, split):
if split != 'Full' and split != 'Scavenger':
startAP = getAccessPoint(self.graphSettings.startAP)
possibleMajLocs, preserveMajLocs, nMaj, nChozo = Logic.LocationsHelper.getStartMajors(startAP.Name)
if split == 'Major':
n = nMaj
elif split == 'Chozo':
n = nChozo
GraphUtils.updateLocClassesStart(startAP.GraphArea, split, possibleMajLocs, preserveMajLocs, n)
def postProcessItemLocs(self, itemLocs, hide):
# hide some items like in dessy's
if hide == True:
for itemLoc in itemLocs:
item = itemLoc.Item
loc = itemLoc.Location
if (item.Category != "Nothing"
and loc.CanHidden == True
and loc.Visibility == 'Visible'):
if bool(random.getrandbits(1)) == True:
loc.Visibility = 'Hidden'
# put nothing in unfilled locations
filledLocNames = [il.Location.Name for il in itemLocs]
unfilledLocs = [loc for loc in Logic.locations if loc.Name not in filledLocNames]
nothing = ItemManager.getItem('Nothing')
for loc in unfilledLocs:
loc.restricted = True
itemLocs.append(ItemLocation(nothing, loc, False))