def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    probKill = Event.DieOrEscapeProb1v1(
        mainActor,
        victims[0],
        state["settings"],
        defenseStat=(victims[0].getCombatAbility(mainActor) * 0.25 +
                     victims[0].stats['cleverness'] * 0.15))
    tempList = [mainActor, state["items"]["Bow and Arrow"], victims[0]]
    # Deteriorate relationship of victim toward participant
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -2)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -3)
    lootDict = None
    destroyedList = None
    if random.random() < probKill:
        victims[0].kill()
        deadList = [victims[0].name]
        desc = mainActor.name + ' shot an arrow at ' + \
            victims[0].name + " and killed " + \
            Event.parseGenderObject(victims[0]) + "."
        lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
    else:
        deadList = []
        desc = mainActor.name + ' shot an arrow at ' + \
            victims[0].name + ", but missed."
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc,
                       tempList,
                       deadList,
                       loot_table=lootDict,
                       destroyed_loot_table=destroyedList)
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):

    eventPeople = [mainActor] + participants
    numItems = random.randint(1, 2)
    itemsFound = [
        ItemInstance.takeOrMakeInstance(v)
        for v in random.sample(list(state['items'].values()), 2)
    ]
    descList = eventPeople + itemsFound
    fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.fight(
        eventPeople, state["allRelationships"], preexistingLoot=itemsFound)
    if fightDesc is None:
        return None
    desc = Event.englishList(
        eventPeople) + " stumbled across " + Event.englishList(
            itemsFound) + " at the same time. A fight broke out. " + fightDesc

    return EventOutput(desc,
                       descList, [x.name for x in fightDead],
                       allKillers,
                       loot_table=lootDict,
                       injuries=injuries,
                       list_killers=True,
                       destroyed_loot_table=destroyedList)
Exemple #3
0
def func(self: Event, mainActor: Contestant, state, participants: Optional[List[Contestant]], victims: List[Contestant], sponsors: Optional[List[Contestant]]=None):
    probKill = Event.DieOrEscapeProb1v1(mainActor, victims[0], state["settings"], defenseStat=(
        victims[0].getCombatAbility(mainActor) * 0.75 + victims[0].stats['cleverness'] * 0.25))
    spearBroken = random.randint(0, 1)
    tempList = [mainActor, state["items"]["Spear"], victims[0]]
    # Deteriorate relationship of victim toward participant
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -2)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -3)
    lootDict = None
    destroyedList = None
    if random.random() < probKill:
        victims[0].kill()
        deadList = [victims[0].name]
        desc = mainActor.name + ' threw a spear through ' + \
            victims[0].name + "'s neck and killed " + \
            Event.parseGenderObject(victims[0]) + "."
        lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
    else:
        deadList = []
        desc = mainActor.name + ' threw a spear at ' + \
            victims[0].name + ", but missed."
        # 50/50 chance the victim gets the spear, if not broken.
        if not spearBroken and random.randint(0, 1):
            desc += " " + victims[0].name + " was able to steal the spear!"
            lootref = mainActor.removeAndGet(state["items"]["Spear"])
            victims[0].addItem(lootref)
            lootDict = {victims[0].name: [lootref]}
    if spearBroken:
        desc += " The spear was broken in the process."
        mainActor.removeItem(state["items"]["Spear"])
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc, tempList, deadList, loot_table=lootDict, destroyed_loot_table=destroyedList)
Exemple #4
0
def func(self, mainActor, state=None, participants=None, victims=None, sponsors=None):
    desc = CLIFF_DESCRIPTIONS[random.randint(0, len(CLIFF_DESCRIPTIONS) - 1)](mainActor, victims[0])
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -4)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -6)
    victims[0].kill()
    if mainActor.stats["stability"] < 3:
        desc += ' ' + Event.parseGenderSubject(mainActor).capitalize() + ' smiled as ' + Event.parseGenderSubject(
            mainActor) + ' watched ' + Event.parseGenderObject(victims[0]) + ' die.'
        mainActor.permStatChange({'stability': -1})
    tempList = [mainActor, victims[0]]
    lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc, tempList, [victims[0].name], loot_table=lootDict, destroyed_loot_table=destroyedList)
Exemple #5
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    probKill = Event.DieOrEscapeProb1v1(
        mainActor,
        victims[0],
        state["settings"],
        defenseStat=(victims[0].getCombatAbility(mainActor) * 0.15 +
                     victims[0].stats['cleverness'] * 0.10))
    tempList = [mainActor, state["items"]["Rifle"], victims[0]]
    # Deteriorate relationship of victim toward participant
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -2)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -3)
    # RNG ammo use, this is unique to the rifle.
    actualItem = mainActor.hasThing("Rifle")[0]
    currentAmmo = actualItem.data.get("currentammo",
                                      actualItem.rawData["ammo"])
    ammoUsed = min(
        random.randint(actualItem.rawData["ammouse"][0],
                       actualItem.rawData["ammouse"][1]), currentAmmo)
    currentAmmo -= ammoUsed
    lootDict = None
    destroyedList = None
    if random.random() < probKill:
        victims[0].kill()
        deadList = [victims[0].name]
        desc = mainActor.name + ' fired at ' + \
            victims[0].name + " from long range and killed " + \
            Event.parseGenderObject(victims[0]) + "."
        lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
    else:
        deadList = []
        desc = mainActor.name + ' fired at ' + \
            victims[0].name + " from long range, but missed."
    if currentAmmo > 0:
        desc += "\nAmmo remaining: " + str(currentAmmo) + " (" + str(
            ammoUsed) + " used)"
        actualItem.data["currentammo"] = currentAmmo
    else:
        desc += "\nThe Rifle belonging to " + mainActor.name + " exhausted its ammo."
        mainActor.removeItem("Rifle")
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc,
                       tempList,
                       deadList,
                       loot_table=lootDict,
                       destroyed_loot_table=destroyedList)
Exemple #6
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    desc = mainActor.name + ', ' + \
        participants[0].name + ', and ' + participants[1].name + ' fought.'
    descList = [mainActor, participants[0], participants[1]]
    fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.fight(
        descList, state['allRelationships'])
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc + fightDesc,
                       descList, [x.name for x in fightDead],
                       allKillers,
                       loot_table=lootDict,
                       injuries=injuries,
                       list_killers=True,
                       destroyed_loot_table=destroyedList)
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    theDead = [x for x in state["contestants"].values() if not x.alive]

    # if no one dead, then no body to find, so need new event
    if not theDead:
        return None

    # encounter random body… this might be a problem if bodies ever get incinerated or something?
    body = random.choice(theDead)
    mainActor.permStatChange({'stability': -1})

    # initialize some stuff
    lootDict = None
    destroyedList = None
    descBeginning = mainActor.name + ' found ' + body.name + "'s body"
    descNoLoot = descBeginning + ', but searching it turned up nothing useful'
    descEnd = '.'

    # generate appropriate message
    if body.inventory:
        lootDict, destroyedList = self.lootForOne(mainActor,
                                                  body,
                                                  chanceDestroyedOverride=0)
        if lootDict:
            # if there's any loot, a separate message will be generated for it, so we don't need to describe it here
            desc = descBeginning
        else:
            desc = descNoLoot
    else:
        desc = descNoLoot
    desc += descEnd

    # Second entry is the contestants named in desc, in order. Third is anyone who died… but no one died.
    return EventOutput(desc, [mainActor, body], [],
                       loot_table=lootDict,
                       destroyed_loot_table=destroyedList)
Exemple #8
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    attackers = [mainActor] + participants
    desc = Event.englishList(
        attackers
    ) + " worked together to ambush and attack " + victims[0].name + "."
    descList = attackers + victims
    fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.factionFight(
        attackers, victims, state["allRelationships"])
    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc + fightDesc,
                       descList,
                       sorted([x.name for x in fightDead]),
                       allKillers,
                       loot_table=lootDict,
                       injuries=injuries,
                       destroyed_loot_table=destroyedList)
Exemple #9
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    # they shouldn't be practicing combat if injured
    if state["callbackStore"].setdefault('InjuredDict', defaultdict(bool)):
        return None
    desc = mainActor.name + ' practiced combat'
    practiceAbility = mainActor.stats['combat ability']
    injuries = None
    if random.random() > 1 / (1 + 1.3**practiceAbility):
        desc += ' but hurt ' + \
            Event.parseGenderReflexive(mainActor) + ' doing so.'
        mainActor.addStatus(state["statuses"]["Injury"])
        injuries = [str(mainActor)]
    else:
        desc += ' and was successfully able to improve ' + \
            Event.parseGenderPossessive(mainActor) + ' skills'
        mainActor.permStatChange({'combat ability': 1})
    return EventOutput(desc, [mainActor], [], injuries=injuries)
Exemple #10
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    probSurvival = (1 - Event.DieOrEscapeProb1v1(
        mainActor,
        victims[0],
        state["settings"],
        defenseStat=(victims[0].getCombatAbility(mainActor) * 0.75 +
                     victims[0].stats['cleverness'] * 0.25))
                    ) * 0.5  # This event is rigged against defender
    tempList = [mainActor, state["items"]["MolotovCocktail"], victims[0]]
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -4)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -6)
    if random.random() < probSurvival:
        desc = mainActor.name + ' threw a molotov cocktail at ' + \
            victims[0].name + " but " + \
            Event.parseGenderSubject(victims[0]) + " escaped!"
        return (desc, tempList, [])
    else:
        victims[0].kill()
        desc = mainActor.name + ' threw a molotov cocktail at ' + \
            victims[0].name + " and burned " + \
            Event.parseGenderObject(victims[0]) + " alive."
        mainActor.permStatChange({'stability': -2})
        if mainActor.stats["stability"] < 3:
            desc += " " + mainActor.name + " laughed at " + \
                Event.parseGenderPossessive(victims[0]) + " agony."
        mainActor.removeItem(state["items"]["MolotovCocktail"])
        lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
        if victims[0].removeStatus(state["statuses"]["Hypothermia"]):
            desc += " " + victims[0].name + " is no longer hypothermic."
        # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
        return EventOutput(desc,
                           tempList, [victims[0].name],
                           loot_table=lootDict,
                           destroyed_loot_table=destroyedList)
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    # Deteriorate relationship of victim toward participant
    state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor, -2)
    state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor, -3)
    probKill = Event.DieOrEscapeProb1v1(
        mainActor,
        victims[0],
        state["settings"],
        defenseStat=(victims[0].getCombatAbility(mainActor) * 0.5 +
                     victims[0].stats['cleverness']
                     ))  # this event is mildly rigged against attacker
    descList = [mainActor, victims[0]]
    if random.random() < probKill:
        victims[0].kill()
        if mainActor.stats['ruthlessness'] > 6:
            desc = mainActor.name + ' lay in wait for ' + \
                victims[0].name + ', surprising and gutting ' + \
                Event.parseGenderObject(victims[0]) + '.'
        else:
            desc = mainActor.name + ' lay in wait for ' + \
                victims[0].name + ', surprising and killing ' + \
                Event.parseGenderObject(victims[0]) + '.'
        lootDict, destroyedList = self.lootForOne(mainActor, victims[0])
        return EventOutput(desc,
                           descList, [victims[0].name],
                           loot_table=lootDict,
                           destroyed_loot_table=destroyedList)
    else:
        desc = mainActor.name + ' lay in wait for ' + \
            victims[0].name + ', but ' + \
            Event.parseGenderSubject(victims[0]) + ' managed to see it coming.'
        # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
        return (desc, descList, [])
Exemple #12
0
def func(self: Event,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    desc = str(mainActor) + " offered to cook for " + \
        str(victims[0]) + ", who gladly accepted."
    descList = [mainActor, victims[0]]

    # Roll for failure to actually poison
    notFailure = (victims[0].stats["cleverness"] +
                  victims[0].stats["survivalism"]) / 15
    if random.random() > notFailure:
        desc += " However, " + \
            str(mainActor) + " tried to secretly poison the dish, but failed, using the wrong mushrooms. The dish was delicious."
        state["allRelationships"].IncreaseFriendLevel(victims[0], mainActor,
                                                      random.randint(1, 3))
        state["allRelationships"].IncreaseLoveLevel(victims[0], mainActor,
                                                    random.randint(0, 2))
        return (desc, descList, [])

    desc += " However, " + str(mainActor) + \
        " tried to secretly poison the dish! "

    # Roll for participant realizing what's going on
    detection = (victims[0].stats["cleverness"] +
                 victims[0].stats["survivalism"]) / 30

    injuries = None
    destroyedList = None
    if random.random() < detection:
        # Participant realizes what's going on
        desc += str(victims[0]) + " caught " + \
            Event.parseGenderObject(mainActor) + " in the act and attacked!"
        (fightDesc, fightDeadList, allKillers, lootDict, injuries,
         destroyedList) = self.fight(descList, state["allRelationships"])
        if fightDeadList is None:  # Event fight failed.
            return None
        # Special: if only one loser, 33% chance the loser escapes injured instead, losing loot. If they are already injured they just die (skip this segment).
        if len(fightDeadList) == 1 and random.random(
        ) < 0.33 and not fightDeadList[0].hasThing("Injury"):
            # revive the loser
            fightDeadList[0].alive = True
            fightDeadList[0].addStatus(state["statuses"]["Injury"])
            if fightDeadList[0] == mainActor:
                desc += ' In the end, ' + mainActor.name + ' was injured and forced to flee.'
            else:
                desc += ' In the end, however, ' + \
                    victims[0].name + ' was injured and forced to flee.'
            return EventOutput(desc,
                               descList, [],
                               loot_table=lootDict,
                               injuries=injuries,
                               destroyed_loot_table=destroyedList)

        if not fightDeadList:
            desc += ' The fight was a draw, and the two sides departed, friends no more.'
            return (desc, descList, [])
        desc += fightDesc
        return (desc, descList, [x.name for x in fightDeadList], allKillers)

    else:
        desc += str(victims[0]) + \
            " ate the meal, blissfully unaware, before falling over dead."
        victims[0].kill()
        lootDict, destroyedList = self.lootForOne(mainActor,
                                                  victims[0],
                                                  chanceDestroyedOverride=0)

    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc,
                       descList, [str(victims[0])],
                       loot_table=lootDict,
                       injuries=injuries,
                       destroyed_loot_table=destroyedList)
Exemple #13
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    desc = "Tired of waiting, the sponsors force two of the remaining contestants to fight. "
    # Build dict of weights for various possibilities
    optionDict = collections.OrderedDict()
    optionDict['fight'] = 1
    if state['allRelationships'].friendships[str(mainActor)][str(
            participants[0])] > 3 and state['allRelationships'].friendships[
                str(participants[0])][str(mainActor)] > 3:
        optionDict['attemptEscape'] = 2
    if state['allRelationships'].loveships[str(mainActor)][str(
            participants[0])] > 3:
        optionDict['actorSuicide'] = 1
        optionDict['actorBegToKill'] = 1
    if state['allRelationships'].loveships[str(
            participants[0])][str(mainActor)] > 3:
        optionDict['participantSuicide'] = 1
        optionDict['participantBegToKill'] = 1
    chosen = weightedDictRandom(optionDict, 1)[0]

    if chosen == 'fight':
        # Keep running until only neither 0 nor all contestants are dead.
        fightDead = []  # dummy list.
        while (len(fightDead) != 1):
            fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.fight(
                [mainActor, participants[0]],
                state['allRelationships'],
                deferActualKilling=True,
                forceRelationshipFight=True)
        # We had to deny Event.fight actually killing anyone because of fact that it might be reset.
        fightDead[0].kill()
        desc += "They did so." + fightDesc
        return EventOutput(desc, [mainActor, participants[0]],
                           [str(x) for x in fightDead],
                           allKillers,
                           loot_table=lootDict,
                           injuries=injuries,
                           destroyed_loot_table=destroyedList)
    if chosen == 'attemptEscape':
        escape = bool(random.randint(0, 1))
        if escape:
            mainActor.escape()
            participants[0].escape()
            desc += 'Instead of fighting, the two contestants attempt to escape, and do so successfully!'
            # This is a hack, declaring both of them "Dead" but ending the game immediately with overriding text that suggests they survived.
            return (desc, [mainActor, participants[0]],
                    [str(mainActor),
                     str(participants[0])], {}, [mainActor,
                                                 participants[0]], True)
        dead = mainActor if random.randint(0, 1) else participants[0]
        desc += 'Instead of fighting, the two contestants attempt to escape, but ' + \
            dead.name + ' is caught and killed by the sponsors!'
        dead.kill()
        return (desc, [mainActor, participants[0]], [dead.name])
    if chosen == 'actorSuicide':
        desc += "Rather than be forced to fight " + Event.parseGenderPossessive(
            mainActor) + " loved one, " + str(
                mainActor) + " committed suicide!"
        mainActor.kill()
        return (desc, [mainActor, participants[0]], [mainActor.name])
    if chosen == 'participantSuicide':
        desc += "Rather than be forced to fight " + Event.parseGenderPossessive(
            participants[0]) + " loved one, " + str(
                participants[0]) + " committed suicide!"
        participants[0].kill()
        return (desc, [mainActor, participants[0]], [participants[0].name])
    if chosen == 'actorBegToKill':
        desc += str(mainActor) + " begged " + \
            str(participants[0]) + " to kill " + \
            Event.parseGenderObject(mainActor)
        if state['allRelationships'].loveships[str(
                participants[0])][str(mainActor)] < 4 or random.random() > 0.5:
            desc += ', forcing ' + \
                str(participants[0]) + ' to go through with it.'
            mainActor.kill()
            deadList = [mainActor.name]
        else:
            desc += ', but ' + Event.parseGenderSubject(
                participants[0]
            ) + ' refused, killing ' + Event.parseGenderReflexive(
                participants[0]) + ' instead!'
            participants[0].kill()
            deadList = [participants[0].name]
        return (desc, [mainActor, participants[0]], deadList)
    if chosen == 'participantBegToKill':
        desc += str(participants[0]) + " begged " + str(mainActor) + \
            " to kill " + Event.parseGenderObject(participants[0])
        if state['allRelationships'].loveships[str(mainActor)][str(
                participants[0])] < 4 or random.random() > 0.5:
            desc += ', forcing ' + str(mainActor) + ' to go through with it.'
            deadList = [participants[0].name]
            participants[0].kill()
        else:
            desc += ', but ' + Event.parseGenderSubject(
                mainActor) + ' refused, killing ' + Event.parseGenderReflexive(
                    mainActor) + ' instead!'
            mainActor.kill()
            deadList = [mainActor.name]
        return (desc, [mainActor, participants[0]], deadList)
    raise AssertionError("This should not happen! " + chosen)
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    success = True
    # It's okay to overwrite since we only care if it happened this turn
    self.eventStore.setdefault(
        'turnRecord',
        defaultdict(lambda: -1))[mainActor.name] = state["turnNumber"][0]

    # If mainActor has a lover, divert this into light romance.
    possible_love = mainActor.hasThing("Love")
    if possible_love and not str(possible_love[0].target) in state["sponsors"]:
        lover = possible_love[0].target
        desc = str(mainActor) + ' and ' + str(
            lover) + ' successfully started a fire together.'
        mainActor.removeStatus("Hypothermia")
        lover.removeStatus("Hypothermia")
        self.eventStore[str(lover)] = True
        self.eventStore[str(mainActor)] = True
        #Need to prevent lover from showing up in events again.
        self.eventStore["turnRecord"][lover.name] = state["turnNumber"][0]
        descList = [mainActor, lover]
        if not mainActor.hasThing("Clean Water") or not lover.hasThing(
                "Clean Water"):
            if random.random() > 0.5:
                desc += ' Using it, they were able to boil some Clean Water.'
                mainActor.addItem(state["items"]["Clean Water"], isNew=True)
                lover.addItem(state["items"]["Clean Water"], isNew=True)
                descList.append(state["items"]["Clean Water"])
        return (desc, descList, [])

    if str(mainActor
           ) not in self.eventStore or not self.eventStore[str(mainActor)]:
        # base is 50%. unless the character has already done it before in which case success is assured
        # Yes this can overload past 1
        chanceSuccess = mainActor.stats["cleverness"] * \
            0.02 + mainActor.stats["survivalism"] * 0.05 + 0.5
        if random.random() > chanceSuccess:
            desc = str(mainActor) + ' tried to start a fire, but failed.'
            descList = [mainActor, state["statuses"]["Hypothermia"]]
            mainActor.addStatus(state["statuses"]["Hypothermia"].makeInstance(
                data={"day": state["turnNumber"][0]}))
            return (desc, descList, [])

    desc = str(mainActor) + ' successfully started a fire.'
    mainActor.removeStatus("Hypothermia")
    self.eventStore[str(mainActor)] = True

    # If character has ever killed anyone, initial 1/3 chance this becomes a haunting event. (affected by stability)
    # logistic
    hauntprob = 1 / (
        1 +
        exp(3 - len(state["callbackStore"]["killCounter"][str(mainActor)]) +
            (mainActor.stats["stability"] - 5) *
            self.settings['statInfluence'] * 0.4))
    if state["callbackStore"]["killCounter"][str(
            mainActor)] and random.random() < hauntprob:
        haunter = state["contestants"][str(
            random.choice(
                state["callbackStore"]["killCounter"][str(mainActor)]))]
        desc = str(mainActor) + " f{} haunted by the ghost of " + str(
            haunter) + " and unable to sleep or make a fire."
        descList = [
            mainActor, state["statuses"]["Ghost"], haunter,
            state["statuses"]["Hypothermia"]
        ]
        mainActor.addStatus(state["statuses"]["Hypothermia"].makeInstance(
            data={"day": state["turnNumber"][0]}))
        mainActor.permStatChange({"stability": random.randint(-2, 0)})
        return EventOutput(desc, descList, [], no_contact=[haunter])

    # Unless character already has clean water, 50% chance (potentially of the remaining 2/3) this becomes a clean water event
    if not mainActor.hasThing("Clean Water"):
        if random.random() > 0.5:
            desc += f' Using it, {Event.parseGenderSubject(mainActor)} {self.getWasConjugation(mainActor)} able to boil some Clean Water.'
            mainActor.addItem(state["items"]["Clean Water"], isNew=True)
            descList = [mainActor, state["items"]["Clean Water"]]
            return (desc, descList, [])

    # 50% chance here that nothing happens, unless it just ain't possible for something to happen (other participant must not have already done this event this turn or already have a fire)
    possibleFireSharers = [
        x for x in state["contestants"].values()
        if x.alive and not self.eventStore["turnRecord"][x.name] ==
        state["turnNumber"][0] and not x.hasThing("Love")
    ]
    if not possibleFireSharers or random.random() > 0.5:
        desc += f' {Event.parseGenderSubject(mainActor).capitalize()} {self.getWasConjugation(mainActor)} able to spend the night in comfort.'
        descList = [mainActor]
        return (desc, descList, [])

    # If someone finds them. Roll random contestant.
    contestant = random.choice(possibleFireSharers)
    desc += ' ' + contestant.name + ' found the fire'
    descList = [mainActor, contestant]

    # Use friendship and the other person's aggression/ruthlessness to determine what happens
    # Do they invite them to fire? - certain above 1 friendship or love, more ambivalent from -2 to 0, no below. Ruthlessness factors in.
    if ((state["allRelationships"].friendships[str(mainActor)][str(contestant)]
         > 0 and
         state["allRelationships"].loveships[str(mainActor)][str(contestant)] >
         0) or
        (state["allRelationships"].friendships[str(mainActor)][str(contestant)]
         > -3 and
         state["allRelationships"].loveships[str(mainActor)][str(contestant)] >
         -3 and random.random() < ((min(
             state["allRelationships"].friendships[str(mainActor)][str(
                 contestant)], state["allRelationships"].loveships[str(
                     mainActor)][str(contestant)]) + 3) / 3 -
                                   mainActor.stats["ruthlessness"] / 15))):
        desc += ', and they agreed to share the fire together.'
        self.eventStore["turnRecord"][contestant.name] = state["turnNumber"][0]
        contestant.removeStatus("Hypothermia")
        state["allRelationships"].IncreaseFriendLevel(mainActor, contestant,
                                                      random.randint(0, 1))
        state["allRelationships"].IncreaseLoveLevel(mainActor, contestant,
                                                    random.randint(0, 1))
        state["allRelationships"].IncreaseFriendLevel(contestant, mainActor,
                                                      random.randint(1, 3))
        state["allRelationships"].IncreaseLoveLevel(contestant, mainActor,
                                                    random.randint(0, 2))
        return (desc, descList, [])

    desc += ', but ' + mainActor.name + ' refused to let ' + \
        Event.parseGenderObject(contestant) + ' share it.'

    # Does the other party decide to attack? Only if friendship and loveship<0
    if ((state["allRelationships"].friendships[str(contestant)][str(mainActor)]
         > 0 and
         state["allRelationships"].loveships[str(contestant)][str(mainActor)] >
         0) or random.random() >
        (contestant.stats["aggression"] * 2 + contestant.stats["ruthlessness"])
            * abs(state["allRelationships"].friendships[str(contestant)][str(
                mainActor)] + 2 * state["allRelationships"].loveships[str(
                    contestant)][str(mainActor)]) / 450):
        desc += ' After a moment, ' + contestant.name + ' left.'
        return (desc, descList, [], [], [mainActor])

    desc += ' After a moment, ' + contestant.name + ' attacked.'
    (fightDesc, fightDeadList, allKillers, lootDict, injuries,
     destroyedList) = self.fight(descList,
                                 state["allRelationships"],
                                 deferActualKilling=True)

    # We need to handle special cases because we want some chance of someone being injured and running away instead.
    # If everyone dies
    if len(fightDeadList) == 2:
        fightDeadList[0].kill()
        fightDeadList[1].kill()

    # Special: if only one loser, 33% chance the loser escapes injured instead, losing loot.
    if len(fightDeadList) == 1:
        if random.random() > 0.33:
            # kill him anyway.
            fightDeadList[0].kill()
        else:
            # Injure the loser and divert the event outcome
            fightDeadList[0].addStatus(state["statuses"]["Injury"])
            if fightDeadList[0] == mainActor:
                self.eventStore["turnRecord"][
                    contestant.name] = state["turnNumber"][0]
                desc += ' and ' + mainActor.name + ' was injured and forced to flee.'
                mainActor.addStatus(
                    state["statuses"]["Hypothermia"].makeInstance(
                        data={"day": state["turnNumber"][0]}))
                contestant.removeStatus("Hypothermia")
            else:
                desc += ' but ' + contestant.name + ' was injured and forced to flee.'
                contestant.addStatus(
                    state["statuses"]["Hypothermia"].makeInstance(
                        data={"day": state["turnNumber"][0]}))
            if fightDeadList[0] not in injuries:
                injuries.append(fightDeadList[0])
            return EventOutput(desc,
                               descList, [],
                               loot_table=lootDict,
                               injuries=injuries,
                               destroyed_loot_table=destroyedList)

    # If nobody was hurt, they just give up and use the fire together.
    if not fightDeadList:
        self.eventStore["turnRecord"][contestant.name] = state["turnNumber"][0]
        contestant.removeStatus("Hypothermia")
        desc += '\nIn the end both sides got tired and gave up, agreeing to use the fire together for one night. Neither side slept well.'
        return EventOutput(desc, descList, [], injuries=injuries)

    # need to ban contestant from turning up again in fire events if they won the fight.
    if contestant.name not in fightDeadList:
        self.eventStore["turnRecord"][contestant.name] = state["turnNumber"][0]
    desc += fightDesc
    return EventOutput(desc,
                       descList, [x.name for x in fightDeadList],
                       allKillers,
                       loot_table=lootDict,
                       injuries=injuries,
                       destroyed_loot_table=destroyedList)
Exemple #15
0
def func(self,
         mainActor,
         state=None,
         participants=None,
         victims=None,
         sponsors=None):
    eventPeople = [mainActor] + participants
    relationships = state["allRelationships"]
    while True:
        whatHappens = random.randint(0, 2)  # 0 is empty, 1 is loot, 2 is trap
        descList = eventPeople.copy()
        desc = Event.englishList(
            eventPeople) + ' found an abandoned building, '
        fightDead = []
        allKillers = None
        lootDict = None
        destroyedList = None
        injuries = None
        if whatHappens == 0:
            desc += 'but it turned out to have nothing of value.'
            if len(eventPeople) > 1:
                probViolence = 0.25 - \
                    relationships.groupCohesion(eventPeople) / 200
                if random.random() < probViolence:
                    fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.fight(
                        eventPeople, relationships)
                    if fightDesc is None:
                        continue
                    desc += ' Violence broke out due to frustration.'
                    desc += fightDesc
            break
        elif whatHappens == 1:
            # get one or two random pieces of loot
            new_loot = random.sample(list(state['items'].values()),
                                     random.randint(1, 2))
            desc += ' and found sweet loot!'  # let the loot be described separately
            lootDict = {}
            destroyedList = []
            # If there is no fight, there's no reason loot would be destroyed.
            overrideLootDestructionChance = 0
            if len(eventPeople) > 1:
                probViolence = 0.5 - relationships.groupCohesion(
                    eventPeople) / 100
                if random.random() < probViolence:
                    overrideLootDestructionChange = None
                    fightDesc, fightDead, allKillers, lootDict, injuries, destroyedList = self.fight(
                        eventPeople,
                        relationships,
                        False,
                        False,
                        preexistingLoot=new_loot)
                    if fightDesc is None:
                        continue
                    desc += ' A fight broke out over the loot.'
                    desc += fightDesc
                    break  # This has separate logic than what happens if there is no fight.
            partialLoot, partialDestroyed = self.lootForMany(
                eventPeople,
                new_loot,
                chanceDestroyedOverride=overrideLootDestructionChance)
            Event.MergeLootDicts(lootDict, partialLoot)
            Event.MergeDestroyedLists(destroyedList, partialDestroyed)
            break
        elif whatHappens == 2:
            desc += ' but the building was booby-trapped! '
            for person in eventPeople:
                if person.stats['cleverness'] + person.stats[
                        'combat ability'] + random.randint(0, 21) < 21:
                    person.kill()
                    fightDead.append(person)
            if not fightDead:
                if len(eventPeople) > 1:
                    desc += 'Everyone escaped safely.'
                else:
                    desc += Event.parseGenderSubject(
                        eventPeople[0]).capitalize() + ' escaped safely.'

            # This must be done separately because it assigns no killers
            # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
            return (desc, descList, [x.name for x in fightDead],
                    collections.OrderedDict())

    # Second entry is the contestants or items named in desc, in desired display. Third is anyone who died. This is in strings.
    return EventOutput(desc,
                       descList, [x.name for x in fightDead],
                       allKillers,
                       loot_table=lootDict,
                       injuries=injuries,
                       list_killers=True,
                       destroyed_loot_table=destroyedList)