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

64 lines
2.6 KiB
Python

import utils.log, random
from logic.smboolmanager import SMBoolManager
from utils.parameters import infinity
class MiniSolver(object):
def __init__(self, startAP, areaGraph, restrictions):
self.startAP = startAP
self.areaGraph = areaGraph
self.restrictions = restrictions
self.settings = restrictions.settings
self.smbm = SMBoolManager()
self.log = utils.log.get('MiniSolver')
# if True, does not mean it is actually beatable, unless you're sure of it from another source of information
# if False, it is certain it is not beatable
def isBeatable(self, itemLocations, maxDiff=None):
if maxDiff is None:
maxDiff = self.settings.maxDiff
minDiff = self.settings.minDiff
locations = []
for il in itemLocations:
loc = il.Location
if loc.restricted:
continue
loc.itemName = il.Item.Type
loc.difficulty = None
locations.append(loc)
self.smbm.resetItems()
ap = self.startAP
onlyBossesLeft = -1
hasOneLocAboveMinDiff = False
while True:
if not locations:
return hasOneLocAboveMinDiff
# only two loops to collect all remaining locations in only bosses left mode
if onlyBossesLeft >= 0:
onlyBossesLeft += 1
if onlyBossesLeft > 2:
return False
self.areaGraph.getAvailableLocations(locations, self.smbm, maxDiff, ap)
post = [loc for loc in locations if loc.PostAvailable and loc.difficulty.bool == True]
for loc in post:
self.smbm.addItem(loc.itemName)
postAvailable = loc.PostAvailable(self.smbm)
self.smbm.removeItem(loc.itemName)
loc.difficulty = self.smbm.wand(loc.difficulty, postAvailable)
toCollect = [loc for loc in locations if loc.difficulty.bool == True and loc.difficulty.difficulty <= maxDiff]
if not toCollect:
# mini onlyBossesLeft
if maxDiff < infinity:
maxDiff = infinity
onlyBossesLeft = 0
continue
return False
if not hasOneLocAboveMinDiff:
hasOneLocAboveMinDiff = any(loc.difficulty.difficulty >= minDiff for loc in locations)
self.smbm.addItems([loc.itemName for loc in toCollect])
for loc in toCollect:
locations.remove(loc)
# if len(locations) > 0:
# ap = random.choice([loc.accessPoint for loc in locations])