diff --git a/src/roles/hunter.py b/src/roles/hunter.py index a21e5da..6497bde 100644 --- a/src/roles/hunter.py +++ b/src/roles/hunter.py @@ -4,105 +4,100 @@ from collections import defaultdict import src.settings as var from src.utilities import * -from src import debuglog, errlog, plog -from src.decorators import cmd, event_listener +from src import users, debuglog, errlog, plog +from src.functions import get_players, get_target +from src.decorators import command, event_listener from src.messages import messages from src.events import Event -KILLS = {} # type: Dict[str, str] +KILLS = {} # type: Dict[users.User, users.User] HUNTERS = set() PASSED = set() -@cmd("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",)) -def hunter_kill(cli, nick, chan, rest): +@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",)) +def hunter_kill(var, wrapper, message): """Kill someone once per game.""" - if nick in HUNTERS and nick not in KILLS: - pm(cli, nick, messages["hunter_already_killed"]) + if wrapper.source in HUNTERS and wrapper.source not in KILLS: + wrapper.pm(messages["hunter_already_killed"]) return - victim = get_victim(cli, nick, re.split(" +",rest)[0], False) - if not victim: + target = get_target(var, wrapper, re.split(" +", message)[0]) + if not target: return - if victim == nick: - pm(cli, nick, messages["no_suicide"]) + if wrapper.source is target: + wrapper.pm(messages["no_suicide"]) return - orig = victim - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "kill", nick, victim, frozenset({"detrimental"})) + orig = target + evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": True}) + evt.dispatch(wrapper.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"})) if evt.prevent_default: return - victim = evt.data["target"] - KILLS[nick] = victim - HUNTERS.add(nick) - PASSED.discard(nick) + target = users._get(evt.data["target"]) # FIXME: Need to fix once targeted_command uses the new API - pm(cli, nick, messages["player_kill"].format(orig)) + KILLS[wrapper.source] = target + HUNTERS.add(wrapper.source) + PASSED.discard(wrapper.source) - debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim))) - chk_nightdone(cli) + wrapper.pm(messages["player_kill"].format(orig)) -@cmd("retract", "r", chan=False, pm=True, playing=True, phases=("night",), roles=("hunter",)) -def hunter_retract(cli, nick, chan, rest): + debuglog("{0} (hunter) KILL: {1} ({2})".format(wrapper.source, target, get_role(target.nick))) + chk_nightdone(wrapper.client) + +@command("retract", "r", chan=False, pm=True, playing=True, phases=("night",), roles=("hunter",)) +def hunter_retract(var, wrapper, message): """Removes a hunter's kill selection.""" - if nick not in KILLS and nick not in PASSED: + if wrapper.source not in KILLS and wrapper.source not in PASSED: return - if nick in KILLS: - del KILLS[nick] - HUNTERS.discard(nick) - PASSED.discard(nick) - pm(cli, nick, messages["retracted_kill"]) + KILLS.pop(wrapper.source, None) + HUNTERS.discard(wrapper.source) + PASSED.discard(wrapper.source) + wrapper.pm(messages["retracted_kill"]) -@cmd("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",)) -def hunter_pass(cli, nick, chan, rest): +@command("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",)) +def hunter_pass(var, wrapper, message): """Do not use hunter's once-per-game kill tonight.""" - if nick in HUNTERS and nick not in KILLS: - pm(cli, nick, messages["hunter_already_killed"]) + if wrapper.source in HUNTERS and wrapper.source not in KILLS: + wrapper.pm(messages["hunter_already_killed"]) return - if nick in KILLS: - del KILLS[nick] - HUNTERS.discard(nick) - PASSED.add(nick) - pm(cli, nick, messages["hunter_pass"]) + KILLS.pop(wrapper.source, None) + HUNTERS.discard(wrapper.source) + PASSED.add(wrapper.source) + wrapper.pm(messages["hunter_pass"]) - debuglog("{0} ({1}) PASS".format(nick, get_role(nick))) - chk_nightdone(cli) + debuglog("{0} (hunter) PASS".format(wrapper.source)) + chk_nightdone(wrapper.client) @event_listener("del_player") def on_del_player(evt, cli, var, nick, mainrole, allroles, death_triggers): - HUNTERS.discard(nick) - PASSED.discard(nick) - if nick in KILLS: - del KILLS[nick] - for h,v in list(KILLS.items()): - if v == nick: + user = users._get(nick) # FIXME + HUNTERS.discard(user) + PASSED.discard(user) + KILLS.pop(user, None) + for h, v in list(KILLS.items()): + if v is user: HUNTERS.discard(h) - pm(cli, h, messages["hunter_discard"]) + h.send(messages["hunter_discard"]) del KILLS[h] -@event_listener("rename_player") -def on_rename(evt, cli, var, prefix, nick): - kvp = [] - for a,b in KILLS.items(): - if a == prefix: - a = nick - if b == prefix: - b = nick - kvp.append((a,b)) - KILLS.update(kvp) - if prefix in KILLS: - del KILLS[prefix] - if prefix in HUNTERS: - HUNTERS.discard(prefix) - HUNTERS.add(nick) - if prefix in PASSED: - PASSED.discard(prefix) - PASSED.add(nick) +@event_listener("swap_player") +def on_swap(evt, var, old_user, user): + for a, b in list(KILLS.items()): + if a is old_user: + KILLS[user] = KILLS.pop(old_user) + if b is old_user: + KILLS[user] = KILLS.pop(old_user) + if old_user in HUNTERS: + HUNTERS.discard(old_user) + HUNTERS.add(user) + if old_user in PASSED: + PASSED.discard(old_user) + PASSED.add(user) @event_listener("night_acted") def on_acted(evt, cli, var, nick, sender): - if nick in KILLS: + if users._get(nick) in KILLS: # FIXME evt.data["acted"] = True @event_listener("get_special") @@ -112,49 +107,50 @@ def on_get_special(evt, cli, var): @event_listener("transition_day", priority=2) def on_transition_day(evt, cli, var): for k, d in list(KILLS.items()): - evt.data["victims"].append(d) - evt.data["onlybywolves"].discard(d) - evt.data["killers"][d].append(k) + evt.data["victims"].append(d.nick) + evt.data["onlybywolves"].discard(d.nick) + evt.data["killers"][d].append(k.nick) # important, otherwise our del_player listener lets hunter kill again del KILLS[k] @event_listener("exchange_roles") def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role): - if actor in KILLS: - del KILLS[actor] - if nick in KILLS: - del KILLS[nick] - HUNTERS.discard(actor) - HUNTERS.discard(nick) - PASSED.discard(actor) - PASSED.discard(nick) + user = users._get(actor) # FIXME + target = users._get(nick) # FIXME + KILLS.pop(user, None) + KILLS.pop(target, None) + HUNTERS.discard(user) + HUNTERS.discard(target) + PASSED.discard(user) + PASSED.discard(target) @event_listener("chk_nightdone") def on_chk_nightdone(evt, cli, var): evt.data["actedcount"] += len(KILLS) + len(PASSED) - evt.data["nightroles"].extend([p for p in var.ROLES["hunter"] if p not in HUNTERS or p in KILLS]) + evt.data["nightroles"].extend([p for p in var.ROLES["hunter"] if users._get(p) not in (HUNTERS | KILLS.keys())]) # FIXME @event_listener("transition_night_end", priority=2) def on_transition_night_end(evt, cli, var): - ps = list_players() + ps = get_players() for hunter in var.ROLES["hunter"]: - if hunter in HUNTERS: - continue #already killed + user = users._get(hunter) # FIXME + if user in HUNTERS: + continue # already killed pl = ps[:] random.shuffle(pl) - pl.remove(hunter) - if hunter in var.PLAYERS and not is_user_simple(hunter): - pm(cli, hunter, messages["hunter_notify"]) - else: - pm(cli, hunter, messages["hunter_simple"]) - pm(cli, hunter, "Players: " + ", ".join(pl)) + pl.remove(user) + to_send = "hunter_notify" + if user.prefers_simple(): + to_send = "hunter_simple" + user.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n") @event_listener("succubus_visit") def on_succubus_visit(evt, cli, var, nick, victim): - if KILLS.get(victim) in var.ROLES["succubus"]: - pm(cli, victim, messages["no_kill_succubus"].format(KILLS[victim])) - del KILLS[victim] - HUNTERS.discard(victim) + user = users._get(victim) # FIXME + if user in KILLS and KILLS[user].nick in var.ROLES["succubus"]: # FIXME + user.send(messages["no_kill_succubus"].format(KILLS[user])) + del KILLS[user] + HUNTERS.discard(user) @event_listener("begin_day") def on_begin_day(evt, cli, var): @@ -172,7 +168,7 @@ def on_get_role_metadata(evt, var, kind): if kind == "night_kills": # hunters is the set of all hunters that have not killed in a *previous* night # (if they're in both HUNTERS and KILLS, then they killed tonight and should be counted) - hunters = (set(var.ROLES["hunter"]) - HUNTERS) | set(KILLS.keys()) + hunters = ({users._get(h) for h in var.ROLES["hunter"]} - HUNTERS) | set(KILLS.keys()) # FIXME evt.data["hunter"] = len(hunters) # vim: set sw=4 expandtab: