Beispiel #1
0
    def on_transition_day_begin(self, evt, var):
        ps = get_players()
        for p in ps:
            if get_main_role(p) in Wolfteam:
                continue # wolf shamans can't starve

            if self.totem_tracking[p] > 0:
                # if sustenance totem made it through, fully feed player
                self.hunger_levels[p] = 0
            elif self.totem_tracking[p] < 0:
                # if hunger totem made it through, fast-track player to starvation
                if self.hunger_levels[p] < 3:
                    self.hunger_levels[p] = 3

            # apply natural hunger
            self.hunger_levels[p] += 1

            if self.hunger_levels[p] >= 5:
                # if they hit 5, they die of starvation
                # if there are less VGs than alive wolf shamans, they become a wendigo as well
                self.maybe_make_wendigo(var, p)
                add_dying(var, p, killer_role="villager", reason="boreal_starvation")
            elif self.hunger_levels[p] >= 3:
                # if they are at 3 or 4, alert them that they are hungry
                p.send(messages["boreal_hungry"])

        self.totem_tracking.clear()
Beispiel #2
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    for h, v in list(KILLS.items()):
        if v is player:
            h.send(messages["hunter_discard"])
            del KILLS[h]
        elif h is player:
            del KILLS[h]
    if death_triggers and "dullahan" in all_roles:
        pl = get_players()
        with TARGETS[player].intersection(pl) as targets:
            if targets:
                target = random.choice(list(targets))
                protected = try_protection(var, target, player, "dullahan", "dullahan_die")
                if protected is not None:
                    channels.Main.send(*protected)
                    return

                if var.ROLE_REVEAL in ("on", "team"):
                    role = get_reveal_role(target)
                    an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
                    channels.Main.send(messages["dullahan_die_success"].format(player, target, an, role))
                else:
                    channels.Main.send(messages["dullahan_die_success_noreveal"].format(player, target))
                debuglog("{0} (dullahan) DULLAHAN ASSASSINATE: {1} ({2})".format(player, target, get_main_role(target)))
                add_dying(var, target, "dullahan", "dullahan_die")
Beispiel #3
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    if player in TARGETED.values():
        for x, y in list(TARGETED.items()):
            if y is player:
                del TARGETED[x]
                PREV_ACTED.discard(x)

    if death_triggers and "assassin" in all_roles and player in TARGETED:
        target = TARGETED[player]
        del TARGETED[player]
        PREV_ACTED.discard(player)
        if target in get_players():
            protected = try_protection(var, target, player, "assassin", "assassin_fail")
            if protected is not None:
                channels.Main.send(*protected)
                return
            if var.ROLE_REVEAL in ("on", "team"):
                role = get_reveal_role(target)
                an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
                message = messages["assassin_success"].format(player, target, an, role)
            else:
                message = messages["assassin_success_no_reveal"].format(player, target)
            channels.Main.send(message)
            debuglog("{0} (assassin) ASSASSINATE: {1} ({2})".format(player, target, get_main_role(target)))
            add_dying(var, target, killer_role=evt.params.main_role, reason="assassin")
Beispiel #4
0
def on_chk_decision_lynch5(evt, var, voters):
    votee = evt.data["votee"]
    if votee in DESPERATION:
        # Also kill the very last person to vote them, unless they voted themselves last in which case nobody else dies
        target = voters[-1]
        if target is not votee:
            protected = try_protection(var,
                                       target,
                                       attacker=votee,
                                       attacker_role="shaman",
                                       reason="totem_desperation")
            if protected is not None:
                channels.Main.send(*protected)
                return

            if var.ROLE_REVEAL in ("on", "team"):
                r1 = get_reveal_role(target)
                an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["totem_desperation"].format(
                    votee, target, an1, r1)
            else:
                tmsg = messages["totem_desperation_no_reveal"].format(
                    votee, target)
            channels.Main.send(tmsg)
            add_dying(var,
                      target,
                      killer_role="shaman",
                      reason="totem_desperation")
Beispiel #5
0
def on_remove_protection(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if attacker_role == "fallen angel" and protector_role == "guardian angel":
        evt.data["remove"] = True
        protector.send(messages[reason + "_success"].format(target))
        target.send(messages[reason + "_deprotect"])
        if random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
            add_dying(var, protector, killer_role="fallen angel", reason=reason)
Beispiel #6
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    for h, v in list(KILLS.items()):
        if v is player:
            h.send(messages["hunter_discard"])
            del KILLS[h]
        elif h is player:
            del KILLS[h]
    if death_triggers and "dullahan" in all_roles:
        pl = get_players()
        with TARGETS[player].intersection(pl) as targets:
            if targets:
                target = random.choice(list(targets))
                protected = try_protection(var, target, player, "dullahan",
                                           "dullahan_die")
                if protected is not None:
                    channels.Main.send(*protected)
                    return

                if var.ROLE_REVEAL in ("on", "team"):
                    role = get_reveal_role(target)
                    channels.Main.send(messages["dullahan_die_success"].format(
                        player, target, role))
                else:
                    channels.Main.send(
                        messages["dullahan_die_success_noreveal"].format(
                            player, target))
                debuglog(
                    "{0} (dullahan) DULLAHAN ASSASSINATE: {1} ({2})".format(
                        player, target, get_main_role(target)))
                add_dying(var, target, "dullahan", "dullahan_die")
Beispiel #7
0
def on_transition_day(evt, var):
    for vigilante, target in list(KILLS.items()):
        evt.data["victims"].append(target)
        evt.data["killers"][target].append(vigilante)
        # important, otherwise our del_player listener lets hunter kill again
        del KILLS[vigilante]

        if get_main_role(target) not in Wolf | Win_Stealer:
            add_dying(var, vigilante, "vigilante", "night_kill")
Beispiel #8
0
def on_transition_day(evt, var):
    for vigilante, target in list(KILLS.items()):
        evt.data["victims"].append(target)
        evt.data["killers"][target].append(vigilante)
        # important, otherwise our del_player listener lets hunter kill again
        del KILLS[vigilante]

        if get_main_role(target) not in Wolf | Win_Stealer:
            add_dying(var, vigilante, "vigilante", "night_kill")
Beispiel #9
0
def on_remove_protection(evt, var, target, attacker, attacker_role, protector,
                         protector_role, reason):
    if attacker_role == "fallen angel" and protector_role == "guardian angel":
        evt.data["remove"] = True
        protector.send(messages[reason + "_success"].format(target))
        target.send(messages[reason + "_deprotect"])
        if random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
            status.add_dying(var,
                             protector,
                             killer_role="fallen angel",
                             reason=reason)
Beispiel #10
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    if not death_triggers or "mad scientist" not in all_roles:
        return

    target1, target2 = _get_targets(var, get_players(), player)

    prots1 = try_protection(var, target1, player, "mad scientist",
                            "mad_scientist_fail")
    prots2 = try_protection(var, target2, player, "mad scientist",
                            "mad_scientist_fail")
    if prots1:
        channels.Main.send(*prots1)
    if prots2:
        channels.Main.send(*prots2)

    kill1 = prots1 is None and add_dying(
        var, target1, killer_role="mad scientist", reason="mad_scientist")
    kill2 = prots2 is None and target1 is not target2 and add_dying(
        var, target2, killer_role="mad scientist", reason="mad_scientist")

    role1 = kill1 and get_reveal_role(target1)
    role2 = kill2 and get_reveal_role(target2)
    if kill1 and kill2:
        to_send = "mad_scientist_kill"
        debuglog(
            player.nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(
                target1, get_main_role(target1), target2,
                get_main_role(target2)))
    elif kill1:
        to_send = "mad_scientist_kill_single"
        debuglog(
            player.nick,
            "(mad scientist) KILL: {0} ({1})".format(target1,
                                                     get_main_role(target1)))
    elif kill2:
        to_send = "mad_scientist_kill_single"
        debuglog(
            player.nick,
            "(mad scientist) KILL: {0} ({1})".format(target2,
                                                     get_main_role(target2)))
        # swap the targets around to show the proper target
        target1, target2 = target2, target1
        role1, role2 = role2, role1
    else:
        to_send = "mad_scientist_fail"
        debuglog(player.nick, "(mad scientist) KILL FAIL")

    if to_send != "mad_scientist_fail" and var.ROLE_REVEAL not in ("on",
                                                                   "team"):
        to_send += "_no_reveal"

    channels.Main.send(messages[to_send].format(player, target1, role1,
                                                target2, role2))
Beispiel #11
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    if not death_triggers or "mad scientist" not in all_roles:
        return

    target1, target2 = _get_targets(var, get_players(), player)

    prots1 = try_protection(var, target1, player, "mad scientist", "mad_scientist_fail")
    prots2 = try_protection(var, target2, player, "mad scientist", "mad_scientist_fail")
    if prots1:
        channels.Main.send(*prots1)
    if prots2:
        channels.Main.send(*prots2)

    kill1 = prots1 is None and add_dying(var, target1, killer_role="mad scientist", reason="mad_scientist")
    kill2 = prots2 is None and target1 is not target2 and add_dying(var, target2, killer_role="mad scientist", reason="mad_scientist")

    if kill1:
        if kill2:
            if var.ROLE_REVEAL in ("on", "team"):
                r1 = get_reveal_role(target1)
                an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
                r2 = get_reveal_role(target2)
                an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill"].format(player, target1, an1, r1, target2, an2, r2)
            else:
                tmsg = messages["mad_scientist_kill_no_reveal"].format(player, target1, target2)
            channels.Main.send(tmsg)
            debuglog(player.nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_main_role(target1), target2, get_main_role(target2)))
        else:
            if var.ROLE_REVEAL in ("on", "team"):
                r1 = get_reveal_role(target1)
                an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill_single"].format(player, target1, an1, r1)
            else:
                tmsg = messages["mad_scientist_kill_single_no_reveal"].format(player, target1)
            channels.Main.send(tmsg)
            debuglog(player.nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_main_role(target1)))
    else:
        if kill2:
            if var.ROLE_REVEAL in ("on", "team"):
                r2 = get_reveal_role(target2)
                an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill_single"].format(player, target2, an2, r2)
            else:
                tmsg = messages["mad_scientist_kill_single_no_reveal"].format(player, target2)
            channels.Main.send(tmsg)
            debuglog(player.nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_main_role(target2)))
        else:
            tmsg = messages["mad_scientist_fail"].format(player)
            channels.Main.send(tmsg)
            debuglog(player.nick, "(mad scientist) KILL FAIL")
Beispiel #12
0
def on_lynch(evt, var, votee, voters):
    if votee in DESPERATION:
        # Also kill the very last person to vote them, unless they voted themselves last in which case nobody else dies
        target = voters[-1]
        if target is not votee:
            protected = try_protection(var, target, attacker=votee, attacker_role="shaman", reason="totem_desperation")
            if protected is not None:
                channels.Main.send(*protected)
                return

            to_send = "totem_desperation_no_reveal"
            if var.ROLE_REVEAL in ("on", "team"):
                to_send = "totem_desperation"
            channels.Main.send(messages[to_send].format(votee, target, get_reveal_role(target)))
            status.add_dying(var, target, killer_role="shaman", reason="totem_desperation")
Beispiel #13
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    MATCHMAKERS.discard(player)
    if death_triggers and player in LOVERS:
        lovers = set(LOVERS[player])
        for lover in lovers:
            if lover not in get_players():
                continue # already died somehow
            if var.ROLE_REVEAL in ("on", "team"):
                role = get_reveal_role(lover)
                an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
                message = messages["lover_suicide"].format(lover, an, role)
            else:
                message = messages["lover_suicide_no_reveal"].format(lover)
            channels.Main.send(message)
            debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format(lover, get_main_role(lover), player, evt.params.main_role))
            add_dying(var, lover, killer_role=evt.params.killer_role, reason="lover_suicide")
Beispiel #14
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    MATCHMAKERS.discard(player)
    ACTED.discard(player)
    if death_triggers and player in LOVERS:
        lovers = set(LOVERS[player])
        for lover in lovers:
            if lover not in get_players():
                continue  # already died somehow
            to_send = "lover_suicide_no_reveal"
            if var.ROLE_REVEAL in ("on", "team"):
                to_send = "lover_suicide"
            channels.Main.send(messages[to_send].format(
                lover, get_reveal_role(lover)))
            debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format(
                lover, get_main_role(lover), player, evt.params.main_role))
            add_dying(var,
                      lover,
                      killer_role=evt.params.killer_role,
                      reason="lover_suicide")
Beispiel #15
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    MATCHMAKERS.discard(player)
    if death_triggers and player in LOVERS:
        lovers = set(LOVERS[player])
        for lover in lovers:
            if lover not in get_players():
                continue  # already died somehow
            if var.ROLE_REVEAL in ("on", "team"):
                role = get_reveal_role(lover)
                an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
                message = messages["lover_suicide"].format(lover, an, role)
            else:
                message = messages["lover_suicide_no_reveal"].format(lover)
            channels.Main.send(message)
            debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format(
                lover, get_main_role(lover), player, evt.params.main_role))
            add_dying(var,
                      lover,
                      killer_role=evt.params.killer_role,
                      reason="lover_suicide")
Beispiel #16
0
    def on_transition_day_begin(self, evt, var):
        from src.roles import vengefulghost
        num_wendigos = len(vengefulghost.GHOSTS)
        num_wolf_shamans = len(get_players(("wolf shaman", )))
        ps = get_players()
        for p in ps:
            if get_main_role(p) in Wolfteam:
                continue  # wolf shamans can't starve

            if self.totem_tracking[p] > 0:
                # if sustenance totem made it through, fully feed player
                self.hunger_levels[p] = 0
            elif self.totem_tracking[p] < 0:
                # if hunger totem made it through, fast-track player to starvation
                if self.hunger_levels[p] < 3:
                    self.hunger_levels[p] = 3

            # apply natural hunger
            self.hunger_levels[p] += 1

            if self.hunger_levels[p] >= 5:
                # if they hit 5, they die of starvation
                # if there are less VGs than alive wolf shamans, they become a wendigo as well
                if num_wendigos < num_wolf_shamans:
                    num_wendigos += 1
                    change_role(var,
                                p,
                                get_main_role(p),
                                "vengeful ghost",
                                message=None)
                add_dying(var,
                          p,
                          killer_role="villager",
                          reason="boreal_starvation")
            elif self.hunger_levels[p] >= 3:
                # if they are at 3 or 4, alert them that they are hungry
                p.send(messages["boreal_hungry"])

        self.totem_tracking.clear()
Beispiel #17
0
def on_player_protected(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if protector_role == "bodyguard":
        evt.data["messages"].append(messages[reason + "_bodyguard"].format(attacker, target, protector))
        add_dying(var, protector, killer_role=attacker_role, reason="bodyguard")
        if var.PHASE == "night" and var.GAMEPHASE == "day": # currently transitioning
            DYING.add(protector)
Beispiel #18
0
    def shoot(var, wrapper, message):
        """Use this to fire off a bullet at someone in the day if you have bullets."""
        if not GUNNERS[wrapper.source]:
            wrapper.pm(messages["no_bullets"])
            return

        target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="gunner_target_self")
        if not target:
            return

        target = try_misdirection(var, wrapper.source, target)
        if try_exchange(var, wrapper.source, target):
            return

        GUNNERS[wrapper.source] -= 1

        gun_evt = Event("gun_chances", {"hit": 0, "miss": 0, "headshot": 0})
        gun_evt.dispatch(var, wrapper.source, rolename)

        rand = random.random() # need to save it

        shoot_evt = Event("gun_shoot", {"hit": rand <= gun_evt.data["hit"], "kill": random.random() <= gun_evt.data["headshot"]})
        shoot_evt.dispatch(var, wrapper.source, target)

        realrole = get_main_role(target)
        targrole = get_reveal_role(target)

        if shoot_evt.data["hit"]:
            wrapper.send(messages["shoot_success"].format(wrapper.source, target))
            an = "n" if targrole.startswith(("a", "e", "i", "o", "u")) else ""
            if realrole in Wolf:
                if var.ROLE_REVEAL == "on":
                    wrapper.send(messages["gunner_victim_wolf_death"].format(target, an, targrole))
                else: # off and team
                    wrapper.send(messages["gunner_victim_wolf_death_no_reveal"].format(target))
                add_dying(var, target, killer_role=get_main_role(wrapper.source), reason="gunner_victim")
                if kill_players(var):
                    return
            elif shoot_evt.data["kill"]:
                accident = "accidentally "
                if gun_evt.data["headshot"] == 1: # would always headshot
                    accident = ""
                wrapper.send(messages["gunner_victim_villager_death"].format(target, accident))
                if var.ROLE_REVEAL in ("on", "team"):
                    wrapper.send(messages["gunner_victim_role"].format(an, targrole))
                add_dying(var, target, killer_role=get_main_role(wrapper.source), reason="gunner_victim")
                if kill_players(var):
                    return
            else:
                wrapper.send(messages["gunner_victim_injured"].format(target))
                add_absent(var, target, "wounded")
                from src.wolfgame import chk_decision, chk_win
                chk_decision()
                chk_win()

        elif rand <= gun_evt.data["hit"] + gun_evt.data["miss"]:
            wrapper.send(messages["gunner_miss"].format(wrapper.source))
        else: # BOOM! your gun explodes, you're dead
            if var.ROLE_REVEAL in ("on", "team"):
                wrapper.send(messages["gunner_suicide"].format(wrapper.source, get_reveal_role(wrapper.source)))
            else:
                wrapper.send(messages["gunner_suicide_no_reveal"].format(wrapper.source))
            add_dying(var, wrapper.source, killer_role="villager", reason="gunner_suicide") # blame explosion on villager's shoddy gun construction or something
            kill_players(var)
Beispiel #19
0
def chk_decision(var, *, timeout=False):
    with var.GRAVEYARD_LOCK:
        players = set(get_players()) - get_absent(var)
        avail = len(players)
        needed = avail // 2 + 1

        to_vote = []

        for votee, voters in VOTES.items():
            votes = (set(voters)
                     | get_forced_votes(var, votee)) - get_forced_abstains(var)
            if sum(get_vote_weight(var, x) for x in votes) >= needed:
                to_vote.append(votee)
                break

        behaviour_evt = Event("lynch_behaviour", {
            "num_lynches": 1,
            "kill_ties": False,
            "force": timeout
        },
                              votes=VOTES,
                              players=avail)
        behaviour_evt.dispatch(var)

        num_lynches = behaviour_evt.data["num_lynches"]
        kill_ties = behaviour_evt.data["kill_ties"]
        force = behaviour_evt.data["force"]

        abstaining = False
        if not to_vote:
            if len(ABSTAINS | get_forced_abstains(var)) >= avail / 2:
                abstaining = True
            elif force:
                voting = []
                if VOTES:
                    plurality = [(x, len(y)) for x, y in VOTES.items()]
                    plurality.sort(key=lambda x: x[1])
                    votee, value = plurality.pop()
                    max_value = value
                    # Fetch all of the highest ties, exit out if we find someone lower
                    # If everyone is tied, then at some point plurality will be empty,
                    # but the values will still be at the max. Everything's fine, just break
                    while value == max_value:
                        voting.append(votee)
                        if not plurality:
                            break
                        votee, value = plurality.pop()

                if len(voting) == 1:
                    to_vote.append(voting[0])
                elif voting and kill_ties:
                    if set(voting) == set(
                            get_players()
                    ):  # killing everyone off? have you considered not doing that
                        abstaining = True
                    else:
                        to_vote.extend(voting)
                else:
                    abstaining = True

        if abstaining:
            for forced_abstainer in get_forced_abstains(var):
                if forced_abstainer not in ABSTAINS:  # did not explicitly abstain
                    channels.Main.send(messages["player_meek_abstain"].format(
                        forced_abstainer))

            abstain_evt = Event("abstain", {})
            abstain_evt.dispatch(var, ABSTAINS | get_forced_abstains(var))

            global ABSTAINED
            ABSTAINED = True
            channels.Main.send(messages["village_abstain"])

            from src.wolfgame import transition_night
            transition_night()

        if to_vote:
            global LYNCHED
            LYNCHED += len(
                to_vote)  # track how many people we've lynched today

            if timeout:
                channels.Main.send(messages["sunset_lynch"])

            for votee in to_vote:
                voters = list(VOTES[votee])
                for forced_voter in get_forced_votes(var, votee):
                    if forced_voter not in voters:  # did not explicitly vote
                        channels.Main.send(messages["impatient_vote"].format(
                            forced_voter, votee))
                        voters.append(
                            forced_voter
                        )  # they need to be counted as voting for them still

                if not try_lynch_immunity(var, votee):
                    lynch_evt = Event("lynch", {}, players=avail)
                    if lynch_evt.dispatch(var, votee, voters):
                        if var.ROLE_REVEAL in ("on", "team"):
                            rrole = get_reveal_role(votee)
                            an = "n" if rrole.startswith(
                                ("a", "e", "i", "o", "u")) else ""
                            lmsg = random.choice(
                                messages["lynch_reveal"]).format(
                                    votee, an, rrole)
                        else:
                            lmsg = random.choice(
                                messages["lynch_no_reveal"]).format(votee)
                        channels.Main.send(lmsg)
                        add_dying(var, votee, "villager", "lynch")

            kill_players(var, end_game=False)  # FIXME

        elif timeout:
            channels.Main.send(messages["sunset"])

        from src.wolfgame import chk_win
        if chk_win():
            return  # game ended, just exit out

        if timeout or LYNCHED >= num_lynches:
            from src.wolfgame import transition_night
            transition_night()
Beispiel #20
0
def on_player_protected(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if protector_role == "bodyguard":
        evt.data["messages"].append(messages[reason + "_bodyguard"].format(attacker, target, protector))
        status.add_dying(var, protector, killer_role=attacker_role, reason="bodyguard")
        DYING.add(protector)
Beispiel #21
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    if not death_triggers or "mad scientist" not in all_roles:
        return

    target1, target2 = _get_targets(var, get_players(), player)

    prots1 = try_protection(var, target1, player, "mad scientist",
                            "mad_scientist_fail")
    prots2 = try_protection(var, target2, player, "mad scientist",
                            "mad_scientist_fail")
    if prots1:
        channels.Main.send(*prots1)
    if prots2:
        channels.Main.send(*prots2)

    kill1 = prots1 is None and add_dying(
        var, target1, killer_role="mad scientist", reason="mad_scientist")
    kill2 = prots2 is None and target1 is not target2 and add_dying(
        var, target2, killer_role="mad scientist", reason="mad_scientist")

    if kill1:
        if kill2:
            if var.ROLE_REVEAL in ("on", "team"):
                r1 = get_reveal_role(target1)
                an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
                r2 = get_reveal_role(target2)
                an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill"].format(
                    player, target1, an1, r1, target2, an2, r2)
            else:
                tmsg = messages["mad_scientist_kill_no_reveal"].format(
                    player, target1, target2)
            channels.Main.send(tmsg)
            debuglog(
                player.nick,
                "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(
                    target1, get_main_role(target1), target2,
                    get_main_role(target2)))
        else:
            if var.ROLE_REVEAL in ("on", "team"):
                r1 = get_reveal_role(target1)
                an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill_single"].format(
                    player, target1, an1, r1)
            else:
                tmsg = messages["mad_scientist_kill_single_no_reveal"].format(
                    player, target1)
            channels.Main.send(tmsg)
            debuglog(
                player.nick, "(mad scientist) KILL: {0} ({1})".format(
                    target1, get_main_role(target1)))
    else:
        if kill2:
            if var.ROLE_REVEAL in ("on", "team"):
                r2 = get_reveal_role(target2)
                an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
                tmsg = messages["mad_scientist_kill_single"].format(
                    player, target2, an2, r2)
            else:
                tmsg = messages["mad_scientist_kill_single_no_reveal"].format(
                    player, target2)
            channels.Main.send(tmsg)
            debuglog(
                player.nick, "(mad scientist) KILL: {0} ({1})".format(
                    target2, get_main_role(target2)))
        else:
            tmsg = messages["mad_scientist_fail"].format(player)
            channels.Main.send(tmsg)
            debuglog(player.nick, "(mad scientist) KILL FAIL")
Beispiel #22
0
 def nightmare_kill(self, evt, var):
     if self.having_nightmare and self.having_nightmare[0] in get_players():
         add_dying(var, self.having_nightmare[0], "bot", "night_kill")
         self.having_nightmare[0].send(messages["sleepy_nightmare_death"])
         del self.having_nightmare[0]
Beispiel #23
0
def on_remove_protection(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if attacker_role == "fallen angel" and protector_role == "bodyguard":
        evt.data["remove"] = True
        add_dying(var, protector, killer_role="fallen angel", reason=reason)
        protector.send(messages[reason + "_success"].format(target))
        target.send(messages[reason + "_deprotect"])
Beispiel #24
0
    def shoot(var, wrapper, message):
        """Use this to fire off a bullet at someone in the day if you have bullets."""
        if not GUNNERS[wrapper.source]:
            wrapper.pm(messages["no_bullets"])
            return

        target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="gunner_target_self")
        if not target:
            return

        target = try_misdirection(var, wrapper.source, target)
        if try_exchange(var, wrapper.source, target):
            return

        GUNNERS[wrapper.source] -= 1

        gun_evt = Event("gun_chances", {"hit": 0, "miss": 0, "headshot": 0})
        gun_evt.dispatch(var, wrapper.source, rolename)

        rand = random.random() # need to save it

        shoot_evt = Event("gun_shoot", {"hit": rand <= gun_evt.data["hit"], "kill": random.random() <= gun_evt.data["headshot"]})
        shoot_evt.dispatch(var, wrapper.source, target)

        realrole = get_main_role(target)
        targrole = get_reveal_role(target)

        if shoot_evt.data["hit"]:
            wrapper.send(messages["shoot_success"].format(wrapper.source, target))
            an = "n" if targrole.startswith(("a", "e", "i", "o", "u")) else ""
            if realrole in Wolf:
                if var.ROLE_REVEAL == "on":
                    wrapper.send(messages["gunner_victim_wolf_death"].format(target, an, targrole))
                else: # off and team
                    wrapper.send(messages["gunner_victim_wolf_death_no_reveal"].format(target))
                add_dying(var, target, killer_role=get_main_role(wrapper.source), reason="gunner_victim")
                if kill_players(var):
                    return
            elif shoot_evt.data["kill"]:
                accident = "accidentally "
                if gun_evt.data["headshot"] == 1: # would always headshot
                    accident = ""
                wrapper.send(messages["gunner_victim_villager_death"].format(target, accident))
                if var.ROLE_REVEAL in ("on", "team"):
                    wrapper.send(messages["gunner_victim_role"].format(an, targrole))
                add_dying(var, target, killer_role=get_main_role(wrapper.source), reason="gunner_victim")
                if kill_players(var):
                    return
            else:
                wrapper.send(messages["gunner_victim_injured"].format(target))
                add_absent(var, target, "wounded")
                from src.votes import chk_decision
                from src.wolfgame import chk_win
                if not chk_win():
                    # game didn't immediately end due to injury, see if we should force through a vote
                    chk_decision(var)

        elif rand <= gun_evt.data["hit"] + gun_evt.data["miss"]:
            wrapper.send(messages["gunner_miss"].format(wrapper.source))
        else: # BOOM! your gun explodes, you're dead
            if var.ROLE_REVEAL in ("on", "team"):
                wrapper.send(messages["gunner_suicide"].format(wrapper.source, get_reveal_role(wrapper.source)))
            else:
                wrapper.send(messages["gunner_suicide_no_reveal"].format(wrapper.source))
            add_dying(var, wrapper.source, killer_role="villager", reason="gunner_suicide") # blame explosion on villager's shoddy gun construction or something
            kill_players(var)
Beispiel #25
0
def chk_decision(var, *, timeout=False):
    with var.GRAVEYARD_LOCK:
        players = set(get_players()) - get_absent(var)
        avail = len(players)
        needed = avail // 2 + 1

        to_vote = []

        for votee, voters in VOTES.items():
            votes = (set(voters) | get_forced_votes(var, votee)) - get_forced_abstains(var)
            if sum(get_vote_weight(var, x) for x in votes) >= needed:
                to_vote.append(votee)
                break

        behaviour_evt = Event("lynch_behaviour", {"num_lynches": 1, "kill_ties": False, "force": timeout}, votes=VOTES, players=avail)
        behaviour_evt.dispatch(var)

        num_lynches = behaviour_evt.data["num_lynches"]
        kill_ties = behaviour_evt.data["kill_ties"]
        force = behaviour_evt.data["force"]

        abstaining = False
        if not to_vote:
            if len(ABSTAINS | get_forced_abstains(var)) >= avail / 2:
                abstaining = True
            elif force:
                voting = []
                if VOTES:
                    plurality = [(x, len(y)) for x, y in VOTES.items()]
                    plurality.sort(key=lambda x: x[1])
                    votee, value = plurality.pop()
                    max_value = value
                    # Fetch all of the highest ties, exit out if we find someone lower
                    # If everyone is tied, then at some point plurality will be empty,
                    # but the values will still be at the max. Everything's fine, just break
                    while value == max_value:
                        voting.append(votee)
                        if not plurality:
                            break
                        votee, value = plurality.pop()

                if len(voting) == 1:
                    to_vote.append(voting[0])
                elif voting and kill_ties:
                    if set(voting) == set(get_players()): # killing everyone off? have you considered not doing that
                        abstaining = True
                    else:
                        to_vote.extend(voting)
                else:
                    abstaining = True

        if abstaining:
            for forced_abstainer in get_forced_abstains(var):
                if forced_abstainer not in ABSTAINS: # did not explicitly abstain
                    channels.Main.send(messages["player_meek_abstain"].format(forced_abstainer))

            abstain_evt = Event("abstain", {})
            abstain_evt.dispatch(var, ABSTAINS | get_forced_abstains(var))

            global ABSTAINED
            ABSTAINED = True
            channels.Main.send(messages["village_abstain"])

            from src.wolfgame import transition_night
            transition_night()

        if to_vote:
            global LYNCHED
            LYNCHED += len(to_vote) # track how many people we've lynched today

            if timeout:
                channels.Main.send(messages["sunset_lynch"])

            for votee in to_vote:
                voters = list(VOTES[votee])
                for forced_voter in get_forced_votes(var, votee):
                    if forced_voter not in voters: # did not explicitly vote
                        channels.Main.send(messages["impatient_vote"].format(forced_voter, votee))
                        voters.append(forced_voter) # they need to be counted as voting for them still

                if not try_lynch_immunity(var, votee):
                    lynch_evt = Event("lynch", {}, players=avail)
                    if lynch_evt.dispatch(var, votee, voters):
                        if var.ROLE_REVEAL in ("on", "team"):
                            rrole = get_reveal_role(votee)
                            an = "n" if rrole.startswith(("a", "e", "i", "o", "u")) else ""
                            lmsg = random.choice(messages["lynch_reveal"]).format(votee, an, rrole)
                        else:
                            lmsg = random.choice(messages["lynch_no_reveal"]).format(votee)
                        channels.Main.send(lmsg)
                        add_dying(var, votee, "villager", "lynch")

            kill_players(var, end_game=False) # FIXME

        elif timeout:
            channels.Main.send(messages["sunset"])

        from src.wolfgame import chk_win
        if chk_win():
            return # game ended, just exit out

        if timeout or LYNCHED >= num_lynches:
            from src.wolfgame import transition_night
            transition_night()
Beispiel #26
0
def on_player_protected(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if protector_role == "bodyguard":
        evt.data["messages"].append(messages[reason + "_bodyguard"].format(attacker, target, protector))
        add_dying(var, protector, killer_role=attacker_role, reason="bodyguard")
        if var.PHASE == "night" and var.GAMEPHASE == "day": # currently transitioning
            DYING.add(protector)
Beispiel #27
0
def on_remove_protection(evt, var, target, attacker, attacker_role, protector, protector_role, reason):
    if attacker_role == "fallen angel" and protector_role == "bodyguard":
        evt.data["remove"] = True
        add_dying(var, protector, killer_role="fallen angel", reason=reason)
        protector.send(messages[reason + "_success"].format(target))
        target.send(messages[reason + "_deprotect"])