diff --git a/src/roles/detective.py b/src/roles/detective.py new file mode 100644 index 0000000..3ae7817 --- /dev/null +++ b/src/roles/detective.py @@ -0,0 +1,100 @@ +import math +import re +import random + +import src.settings as var +from src.utilities import * +from src import debuglog, errlog, plog +from src.decorators import cmd, event_listener +from src.messages import messages +from src.events import Event + +INVESTIGATED = set() + +@cmd("id", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("detective",)) +def investigate(cli, nick, chan, rest): + """Investigate a player to determine their exact role.""" + if nick in INVESTIGATED: + pm(cli, nick, messages["already_investigated"]) + return + victim = get_victim(cli, nick, re.split(" +",rest)[0], False) + if not victim: + return + + if victim == nick: + pm(cli, nick, messages["no_investigate_self"]) + return + + evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) + evt.dispatch(cli, var, "see", nick, victim, frozenset({"info", "immediate"})) + if evt.prevent_default: + return + victim = evt.data["target"] + vrole = get_role(victim) + if vrole == "amnesiac": + vrole = var.AMNESIAC_ROLES[victim] + + evt = Event("investigate", {"role": vrole}) + evt.dispatch(cli, var, nick, victim) + vrole = evt.data["role"] + + INVESTIGATED.add(nick) + pm(cli, nick, (messages["investigate_success"]).format(victim, vrole)) + debuglog("{0} ({1}) ID: {2} ({3})".format(nick, get_role(nick), victim, vrole)) + + if random.random() < var.DETECTIVE_REVEALED_CHANCE: # a 2/5 chance (should be changeable in settings) + # The detective's identity is compromised! + wcroles = var.WOLFCHAT_ROLES + if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: + if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: + wcroles = var.WOLF_ROLES + else: + wcroles = var.WOLF_ROLES | {"traitor"} + + mass_privmsg(cli, list_players(wcroles), messages["investigator_reveal"].format(nick)) + debuglog("{0} ({1}) PAPER DROP".format(nick, get_role(nick))) + +@event_listener("rename_player") +def on_rename(evt, cli, var, prefix, nick): + if prefix in INVESTIGATED: + INVESTIGATED.remove(prefix) + INVESTIGATED.add(nick) + +@event_listener("del_player") +def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers): + INVESTIGATED.discard(nick) + +@event_listener("exchange_roles") +def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role): + if actor_role == "detective" and nick_role != "detective": + INVESTIGATED.discard(actor) + elif nick_role == "detective" and actor_role != "detective": + INVESTIGATED.discard(nick) + +@event_listener("transition_night_end", priority=2) +def on_transition_night_end(evt, cli, var): + ps = list_players() + for dttv in var.ROLES["detective"]: + pl = ps[:] + random.shuffle(pl) + pl.remove(dttv) + chance = math.floor(var.DETECTIVE_REVEALED_CHANCE * 100) + warning = "" + if chance > 0: + warning = messages["detective_chance"].format(chance) + if dttv in var.PLAYERS and not is_user_simple(dttv): + pm(cli, dttv, messages["detective_notify"].format(warning)) + else: + pm(cli, dttv, messages["detective_simple"]) # !simple + pm(cli, dttv, "Players: " + ", ".join(pl)) + + +@event_listener("transition_night_begin") +def on_transition_night_begin(evt, cli, var): + INVESTIGATED.clear() + +@event_listener("reset") +def on_reset(evt, var): + INVESTIGATED.clear() + +# vim: set sw=4 expandtab: diff --git a/src/roles/seer.py b/src/roles/seer.py index d4b52eb..48eef8a 100644 --- a/src/roles/seer.py +++ b/src/roles/seer.py @@ -32,9 +32,16 @@ def see(cli, nick, chan, rest): victim = evt.data["target"] victimrole = get_role(victim) - evt = Event("see", {"role": victimrole}) - evt.dispatch(cli, var, nick, victim) - victimrole = evt.data["role"] + if role != "augur": + evt = Event("see", {"role": victimrole}) + evt.dispatch(cli, var, nick, victim) + victimrole = evt.data["role"] + else: + evt = Event("investigate", {"role": victimrole}) + evt.dispatch(cli, var, nick, victim) + victimrole = evt.data["role"] + if victimrole == "amnesiac": + victimrole = var.AMNESIAC_ROLES[victim] vrole = victimrole # keep a copy for logging if role == "seer": @@ -63,8 +70,6 @@ def see(cli, nick, chan, rest): pm(cli, nick, (messages["oracle_success"]).format(victim, "" if iswolf else "\u0002not\u0002 ", "\u0002" if iswolf else "")) debuglog("{0} ({1}) SEE: {2} ({3}) (Wolf: {4})".format(nick, role, victim, vrole, str(iswolf))) elif role == "augur": - if victimrole == "amnesiac": - victimrole = var.AMNESIAC_ROLES[victim] aura = "blue" if victimrole in var.WOLFTEAM_ROLES: aura = "red" diff --git a/src/wolfgame.py b/src/wolfgame.py index a70b8c7..44a9004 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -5336,35 +5336,6 @@ def observe(cli, nick, chan, rest): debuglog("{0} ({1}) OBSERVE: {2} ({3})".format(nick, role, victim, get_role(victim))) chk_nightdone(cli) -@cmd("id", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("detective",)) -def investigate(cli, nick, chan, rest): - """Investigate a player to determine their exact role.""" - if nick in var.INVESTIGATED: - pm(cli, nick, messages["already_investigated"]) - return - victim = get_victim(cli, nick, re.split(" +",rest)[0], False) - if not victim: - return - - if victim == nick: - pm(cli, nick, messages["no_investigate_self"]) - return - if is_safe(nick, victim): - pm(cli, nick, messages["no_acting_on_succubus"].format("investigate")) - return - victim = choose_target(nick, victim) - var.INVESTIGATED.add(nick) - vrole = get_role(victim) - if vrole == "amnesiac": - vrole = var.AMNESIAC_ROLES[victim] - pm(cli, nick, (messages["investigate_success"]).format(victim, vrole)) - debuglog("{0} ({1}) ID: {2} ({3})".format(nick, get_role(nick), victim, vrole)) - if random.random() < var.DETECTIVE_REVEALED_CHANCE: # a 2/5 chance (should be changeable in settings) - # The detective's identity is compromised! - for badguy in list_players(var.WOLFCHAT_ROLES): - pm(cli, badguy, (messages["investigator_reveal"]).format(nick)) - debuglog("{0} ({1}) PAPER DROP".format(nick, get_role(nick))) - @cmd("pray", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("prophet",)) def pray(cli, nick, chan, rest): """Receive divine visions of who has a role.""" @@ -6327,20 +6298,6 @@ def transition_night(cli): pm(cli, gangel, messages["guardian_simple"]) # !simple pm(cli, gangel, "Players: " + ", ".join(pl)) - for dttv in var.ROLES["detective"]: - pl = ps[:] - random.shuffle(pl) - pl.remove(dttv) - chance = math.floor(var.DETECTIVE_REVEALED_CHANCE * 100) - warning = "" - if chance > 0: - warning = messages["detective_chance"].format(chance) - if dttv in var.PLAYERS and not is_user_simple(dttv): - pm(cli, dttv, messages["detective_notify"].format(warning)) - else: - pm(cli, dttv, messages["detective_simple"]) # !simple - pm(cli, dttv, "Players: " + ", ".join(pl)) - for pht in var.ROLES["prophet"]: chance1 = math.floor(var.PROPHET_REVEALED_CHANCE[0] * 100) chance2 = math.floor(var.PROPHET_REVEALED_CHANCE[1] * 100)