Пример #1
0
def generateHistory(fineMap, racialMap, civilLocMap, generalLocMap, historyLen,
                    eventCellSize, maxCellEvents):

    unprocessedEvents = []
    historyMap = HistoryMap(fineMap.getMapSize())
    context = HistoricMapContext(fineMap, racialMap, civilLocMap,
                                 generalLocMap, historyMap)

    locCount = {}
    for civilLoc in civilLocMap.getNodes() + generalLocMap.getNodes():
        name = civilLoc.getObject().getName() + str(
            locCount.setdefault(civilLoc.getObject().getName(), 0))
        histLoc = HistoryLocation(civilLoc, context, r.random() < 0.3, name)
        historyMap.addLocation(histLoc)
        locCount[civilLoc.getObject().getName()] += 1

    for year in range(historyLen):
        cCount = 0
        for c in historyMap.getCharacters():
            if c.getCurrentState().alive:
                cCount += 1

        for x in range(round((fineMap.getMapSize() / eventCellSize).a)):
            for y in range(round((fineMap.getMapSize() / eventCellSize).b)):
                pos = Vector2.random(eventCellSize) + Vector2(
                    x, y) * eventCellSize
                eventCount = r.randint(
                    0,
                    min(maxCellEvents,
                        math.ceil(maxCellEvents * (cCount / 200) + 0.01)))
                i = 0
                while i < eventCount:

                    eventIndex = r.random() * sum(
                        HISTORIC_EVENT_CHANCES.values())

                    Event = None
                    for ev in HISTORIC_EVENTS:
                        eventIndex -= HISTORIC_EVENT_CHANCES[ev]
                        if eventIndex <= 0:
                            Event = ev
                            break

                    event = Event(pos, year, context)

                    while event.getAlternateEvent():
                        event = event.getAlternateEvent()

                    if not event.getSuccessful():
                        continue

                    historyMap.addEvent(event)

                    i += 1

    for loc in historyMap.getLocations():
        if not loc.getCurrentState().existing:
            loc.destroy(context)

    return historyMap
Пример #2
0
    def __init__(self, pos, time, context):
        characters = context.getHistoryMap().getCharacters()
        r.shuffle(characters)

        for char in characters:

            if not (char.getAge(time) >=
                    char.getCurrentState().getRace().adultAge
                    and char.getCurrentState().alive
                    and len(char.getCurrentState().items) < r.randint(1, 3)
                    and not (not char.getCurrentState().occupation.warrior
                             and r.random() < 0.5)):
                continue

            boughtItem = None
            seller = None
            for c in char.getCurrentState().livingPlace.getCurrentCharacters(
                    time):
                if (c.getCurrentState().itemsOnSale and c != char
                        and c.getCurrentState().alive):

                    boughtItem = None
                    for item in c.getCurrentState().itemsOnSale:

                        if item.quality > char.getCurrentState(
                        ).occupationLevel + r.randint(-1, 1):
                            continue
                        if item.art and char.getCurrentState(
                        ).occupation.warrior:
                            continue

                        boughtItem = item
                        break

                    if boughtItem:
                        seller = c
                        break

            if not seller:
                continue
            self.seller = seller
            self.buyer = char
            self.item = boughtItem
            self.importantItem = r.random() < 0.5

            super().__init__(
                self.seller.getCurrentState().livingPlace.getPos(), time,
                [self.seller, self.buyer], context)
            self.updateCharacters()
            return

        self.setSuccessful(False)
        return
Пример #3
0
    def __init__(self, pos, time, context):
        newCharacter = HistoricCharacter(self)

        self.attributes = CharacterAttributes.generateRandom(r.randint(17, 20))
        if r.random() >= 0.1:
            self.race = context.getRacialMap().getClosest(
                pos).getObject().getName()
        else:
            self.race = r.choice(
                context.getRacialMap().getNodes()).getObject().getName()

        self.livingPlace = context.getClosestLocation(
            pos,
            sort=lambda n: n.getAttachedContext(HistoryLocation).
            getLocationType().livable).getAttachedContext(HistoryLocation)

        super().__init__(self.livingPlace.getPos(), time, [newCharacter],
                         context, [self.livingPlace])
        context.getHistoryMap().addCharacter(newCharacter)

        self.name = "Person" + str(
            context.getHistoryMap().getCharacters().index(newCharacter))
        self.personality = CharacterState.generatePersonality()

        self.updateCharacters()
        self.updateLocations()
Пример #4
0
 def getRandomObjects(self, number, failChance=0.5):
     ret = []
     for i in range(number):
         if r.random() < failChance:
             continue
         else:
             ret.append(self.getRandomObject())
     return ret
Пример #5
0
 def getRandomObject(self):
     index = r.random() * sum(self.weights.values())
     for t in self.items:
         index -= self.weights[t]
         if index <= 0:
             if t.__class__ == LootTable:
                 return t.getRandomObject()
             return t
Пример #6
0
    def generateRandom(proficiency=20):
        values = [0, 0, 0]
        for i in range(proficiency):
            n = r.randint(0, 2)
            while values[n] >= 8 and not r.random() < 0.1:
                n = r.randint(0, 2)

            values[n] += 1

        return CharacterAttributes(*values)
Пример #7
0
    def __init__(self, pos, time, context):
        characters = context.getHistoryMap().getCharacters()
        r.shuffle(characters)

        char = None
        for c in characters:
            if (c.getAge(time) >= c.getCurrentState().getRace().adultAge
                    and c.getCurrentState().alive
                    and c.getCurrentState().traveling >= r.randint(1, 21)
                    and c.getCurrentState().getPersonality().determination >=
                    r.randint(1, 15)
                    and (not c.getCurrentState().leadershipPos)):

                char = c
                break

        if not char:
            self.setSuccessful(False)
            return

        possible = None
        if c.getCurrentState().traveling >= r.randint(1, 31):
            possible = context.getCloseLocations(
                pos,
                5,
                sort=lambda n: n.getAttachedContext(
                    HistoryLocation).getLocationType().livable)
        else:
            possible = context.getCloseLocations(
                pos,
                5,
                sort=lambda n: n.getAttachedContext(
                    HistoryLocation).getLocationType().independant)

        possibleLocs = []
        for p in possible:
            possibleLocs.append(p.getAttachedContext(HistoryLocation))

        if r.random() < 0.3:
            self.target = r.choice(possibleLocs)
        else:
            popCount = []
            self.target = max(possibleLocs,
                              key=lambda p: len(p.getCurrentCharacters(time)))

        self.prevLoc = char.getCurrentState().livingPlace
        super().__init__(self.target.getPos(), time, [char], context,
                         [self.target, self.prevLoc])
        self.updateCharacters()
        self.updateLocations()
Пример #8
0
    def __init__(self,node,context,existing = False,name=""):
        self.node = node
        self.context = context
        node.attachContext(self)
        self.events = []
        self.state = LocationState(existing,name)
        self.ancient = existing
        self.locationType = HISTORIC_LOCATION_TYPE[node.getObject().getName()]
        if not self.locationType.foundable:
            self.state.existing = True
            self.ancient = True

        self.localRace = context.getRacialMap().getClosest(self.node.getPos())
        self.state.race = self.localRace.getObject().getName()
        self.localRace = CHARACTER_RACES[self.localRace.getObject().getName()]

        if self.localRace.imperial and self.state.existing and self.locationType.independant:
            for locNode in (context.getCivilLocMap().getMultipleClosest(self.node.getPos(),5)
                            +context.getGeneralLocMap().getMultipleClosest(self.node.getPos(),5)):

                if locNode == self.node:
                    continue
                loc = None
                try:
                    loc = locNode.getAttachedContext(HistoryLocation)
                except:
                    continue

                if (loc.getLocationType().foundable
                    and (loc.getLocalRace().imperial or (not loc.getLocationType().independant))
                    and loc.getLocalRace()==self.localRace
                    and (not loc.getCurrentState().adminLocation)
                    and loc.getCurrentState().existing):
                    if loc.getLocationType().size < self.getLocationType().size:
                        loc.setAdminLocation(self)
                    elif loc.getLocationType().size > self.getLocationType().size:
                        self.setAdminLocation(loc)
                        break
                    else:
                        if r.random()<0.5:
                            loc.setAdminLocation(self)
                        else:
                            self.setAdminLocation(loc)
                            break
Пример #9
0
def generateHydraulicMap(mapSize, fineBiomes, sourceCellSize, sourceChance, iterationCount, smallStepLength, largeStepLength, mergeDistance):
    fineBiomeNodes = fineBiomes.getNodes()

    hydroGraph = MapGraph(0,mapSize)

    streamsInProcess = []

    #generate stream sources
    usedFineBiomes = []
    
    for x in range(sourceCellSize.a//2, mapSize.a, sourceCellSize.a):
        for y in range(sourceCellSize.b//2, mapSize.b, sourceCellSize.b):
            if r.random()<sourceChance:
                source = fineBiomes.getClosest(Vector2(x,y))
                
                if source in usedFineBiomes:
                    continue
                
                tags = source.getCollectiveTags()
                acceptable = False
                for tag in tags:
                    if tag.getName()=="mountainous" and tag.getWeight()>=1:
                        acceptable = True
                        break
                    if tag.getName()=="hilly" and tag.getWeight()>=0.5:
                        acceptable = True
                        break
                    if tag.getName()=="forested" and tag.getWeight()>=1:
                        acceptable = True
                        break
                    
                if not acceptable:
                    continue
                
                usedFineBiomes.append(source)
                streamsInProcess.append(HydraulicNode(source.getPos(),1, evaluateRiverTarget(source), isSource=True))

    #iterate stream extension

    for i in range(iterationCount):
        
        newStreams = []

        for stream in streamsInProcess:

            #try twice, once with large step, once with small step
            stepLength = smallStepLength
            for j in range(2):
                #ignore streams outside map
                posDiff = mapSize - stream.getPos()
                if posDiff.a<0 or posDiff.b<0 or posDiff.a>mapSize.a or posDiff.b>mapSize.b:
                    break

                #assign direction if not present
                if not stream.getDirection():
                    angles = []
                    angle = 0
                    while angle<1:
                        angles.append(angle)
                        angle+=0.1

                    r.shuffle(angles)
                    minScore = 1000
                    for angle in angles:
                        direction = Vector2.UNIT.rotate(angle).floatMultiply(stepLength)
                        pos = direction + stream.pos
                        score = evaluateRiverTarget(fineBiomes.getClosest(pos))
                        if score<stream.score and score<minScore :
                            stream.setDirection(direction)
                            minScore = score

                #generate possible next positions
                possiblePos = []

                angleStep = 0.02
                angleRange = 0.2

                angle = -angleRange
                while angle <=angleRange:
                    possAngle = angle + r.random()*angleStep

                    possPos = Vector2.UNIT.rotate(possAngle).floatMultiply(stepLength) + stream.getPos()

                    possiblePos.append(possPos)
                    angle += angleStep

                streamParents = stream.getParents()
                riverScore = {}
                for pos in possiblePos:
                    closest = fineBiomes.getClosest(pos)
                    riverScore[pos] = evaluateRiverTarget(closest)*(0.8+r.random()*0.4)
                    if closest in usedFineBiomes:
                        riverScore[pos] = 100

                #get highest scoring positions
                targetPos = max( possiblePos,key= lambda pos: stream.score-riverScore[pos] )

                #merge streams if close enough
                closestStream = hydroGraph.getClosest(targetPos)
                if closestStream:
                    closestDist = abs(closestStream.getPos() - targetPos)
                    for nstream in newStreams:
                        if abs(nstream.getPos() - targetPos) < closestDist:
                            closestStream = nstream
                            closestDist = abs(nstream.getPos() - targetPos)

                if (not closestStream in streamParents) and closestStream and (
                    abs(closestStream.getPos() - targetPos) < mergeDistance if not closestStream.stagnant else mergeDistance * max(1,min(1.7,1.7*closestStream.getPower()/5))):
                    
                    closestStream.addStreamInput(stream)
                    break

                #maybe set stream as stagnant if difference isn't large enough
##                if (stream.score-riverScore[pos])<r.random()*0.2-0.3 and (stream.length-2)%5==0 and r.random()<0.7:
##                    stream.stagnant = True

                if (stream.score-riverScore[pos])<r.random()*0.2-0.4 and stream.length>r.randint(3,8):
                    if j==0:
                        stepLength = largeStepLength
                        continue
                    else:
                        stream.stagnant = True
                        break

                #create next node
                newStream = HydraulicNode(targetPos, 0.05, riverScore[pos], targetPos-stream.getPos() )
                stream.addStreamOutput(newStream)
                newStreams.append(newStream)
                usedFineBiomes.append(fineBiomes.getClosest(targetPos))
                break
            
        for stream in streamsInProcess:
            hydroGraph.addNode(stream)
        streamsInProcess = newStreams


    #generate map graph data
    hydraulicObjects = {}
    for hydroObj in GetLoadedObjectClass("hydraulics"):
        hydraulicObjects[hydroObj.getName()] = hydroObj
        
    for node in hydroGraph.getNodes():
        node.generateMapGraphData(hydraulicObjects)
        

    return hydroGraph
Пример #10
0
def fillMap(mapGraph, objectClass, superInfluence=1, nothingThreshold=0):
    templates = GetLoadedObjectClass(objectClass)

    objectSuggestions = []
    for template in templates+templates:
        objectSuggestions.append(template.instantiate())

    nodesToRemove = []
    for node in mapGraph.getNodes():
        r.shuffle(objectSuggestions)
        
        scoredSuggs = {}
        for obj in objectSuggestions:
            score = 0
            connCount = 0
            for conn in node.getConnections():
                if conn.getObject():
                    score += obj.compare(conn.getObject()) / abs(node.getPos()-conn.getPos())
                    connCount+=1

            superScore = 0
            for superConn in node.getSuperConnections():
                superScore += obj.compare(superConn.getObject())
            
            finalScore = 0
            if connCount>0:
                finalScore += score/connCount

            if node.getSuperConnections():    
                finalScore += superScore/len(node.getSuperConnections())*superInfluence

            scoredSuggs[obj] = finalScore
            obj.score = finalScore

        order = objectSuggestions[:]
        order.sort(key = lambda obj: scoredSuggs[obj])
        order = order[2*len(order)//3:]
        for obj in objectSuggestions:
            if not obj in order:
                scoredSuggs.pop(obj)
        
            
        targetVal = r.random()*sum(scoredSuggs.values())
        usedObject = r.choice(order)
        for obj in order:
            targetVal -= scoredSuggs[obj]
            if targetVal <= 0:
                usedObject = obj
                break
        

        objectSuggestions = []
        for template in templates+templates:
            objectSuggestions.append(template.instantiate())

        if scoredSuggs[obj] < nothingThreshold:
            nodesToRemove.append(node)
        else:
            node.setObject(usedObject)

    for node in nodesToRemove:
        mapGraph.removeNode(node)
Пример #11
0
 def random(bounds):
     return Vector2(r.random() * bounds.a, r.random() * bounds.b)