From bc63f2be4f9470590eebb06a057a77c02e733fea Mon Sep 17 00:00:00 2001 From: "Vgr E. Barry" Date: Tue, 17 Jan 2017 14:43:28 -0500 Subject: [PATCH] Mad scientist fixes Also stats fix --- src/roles/dullahan.py | 142 ++++++++++++++++++++---------------------- src/wolfgame.py | 31 ++++----- 2 files changed, 82 insertions(+), 91 deletions(-) diff --git a/src/roles/dullahan.py b/src/roles/dullahan.py index d5502b4..8aadbaa 100644 --- a/src/roles/dullahan.py +++ b/src/roles/dullahan.py @@ -5,78 +5,75 @@ from collections import defaultdict, deque import src.settings as var from src.utilities import * -from src import debuglog, errlog, plog -from src.decorators import cmd, event_listener +from src.functions import get_players, get_target +from src import users, debuglog, errlog, plog +from src.decorators import command, event_listener from src.messages import messages from src.events import Event import botconfig -KILLS = {} # type: Dict[str, str] -TARGETS = {} # type: Dict[str, Set[str]] +KILLS = {} # type: Dict[users.User, users.User] +TARGETS = {} # type: Dict[users.User, Set[users.User]] -@cmd("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("dullahan",)) -def dullahan_kill(cli, nick, chan, rest): +@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("dullahan",)) +def dullahan_kill(var, wrapper, message): """Kill someone at night as a dullahan until everyone on your list is dead.""" - if not TARGETS[nick] & set(list_players()): - pm(cli, nick, messages["dullahan_targets_dead"]) + if not TARGETS[wrapper.source] & set(get_players()): + wrapper.pm(messages["dullahan_targets_dead"]) 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 target is wrapper.source: + 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"] + target = evt.data["target"] - KILLS[nick] = victim + KILLS[wrapper.source] = target - msg = messages["wolf_target"].format(orig) - pm(cli, nick, messages["player"].format(msg)) + wrapper.pm(messages["player"].format(messages["wolf_target"].format(orig))) - debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim))) + debuglog("{0} ({1}) KILL: {2} ({3})".format(wrapper.source, get_role(wrapper.source.nick), target, get_role(target.nick))) - chk_nightdone(cli) + chk_nightdone(wrapper.client) -@cmd("retract", "r", chan=False, pm=True, playing=True, phases=("night",), roles=("dullahan",)) -def dullahan_retract(cli, nick, chan, rest): +@command("retract", "r", chan=False, pm=True, playing=True, phases=("night",), roles=("dullahan",)) +def dullahan_retract(var, wrapper, message): """Removes a dullahan's kill selection.""" - if nick not in KILLS: - return - if nick in KILLS: - del KILLS[nick] - pm(cli, nick, messages["retracted_kill"]) + if KILLS.pop(wrapper.source, None): + wrapper.pm(messages["retracted_kill"]) @event_listener("player_win") def on_player_win(evt, var, user, role, winner, survived): if role != "dullahan": return - alive = set(list_players()) + alive = set(get_players()) if user.nick in var.ENTRANCED: - alive -= var.ROLES["succubus"] - if not TARGETS[user.nick] & alive: + alive.difference_update(users._get(x) for x in var.ROLES["succubus"]) # FIXME + if not TARGETS[user] & alive: evt.data["iwon"] = True @event_listener("del_player") def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers): - for h,v in list(KILLS.items()): - if v == nick: - pm(cli, h, messages["hunter_discard"]) + for h, v in list(KILLS.items()): + if v.nick == nick: + h.send(messages["hunter_discard"]) del KILLS[h] - elif h == nick: + elif h.nick == nick: del KILLS[h] if death_triggers and nickrole == "dullahan": pl = evt.data["pl"] - targets = TARGETS[nick] & set(pl) + targets = TARGETS[users._get(nick)].union(users._get(x) for x in pl) # FIXME if targets: - target = random.choice(list(targets)) + target = random.choice(list(targets)).nick prots = deque(var.ACTIVE_PROTECTIONS[target]) aevt = Event("assassinate", {"pl": evt.data["pl"]}, del_player=evt.params.del_player, @@ -105,6 +102,15 @@ def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers): evt.params.del_player(cli, target, True, end_game=False, killer_role=nickrole, deadlist=evt.params.deadlist, original=evt.params.original, ismain=False) evt.data["pl"] = evt.params.refresh_pl(pl) +@event_listener("night_acted") +def on_acted(evt, cli, var, nick, sender): + if users._get(nick) in KILLS: # FIXME + evt.data["acted"] = True + +@event_listener("get_special") +def on_get_special(evt, cli, var): + evt.data["special"].update(list_players(("dullahan",))) + @event_listener("rename_player") def on_rename(evt, cli, var, prefix, nick): kvp = [] @@ -131,61 +137,45 @@ def on_rename(evt, cli, var, prefix, nick): if prefix in TARGETS: del TARGETS[prefix] -@event_listener("night_acted") -def on_acted(evt, cli, var, nick, sender): - if nick in KILLS: - evt.data["acted"] = True - -@event_listener("get_special") -def on_get_special(evt, cli, var): - evt.data["special"].update(list_players(("dullahan",))) - @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) - del KILLS[k] + while KILLS: + k, d = KILLS.popitem() + evt.data["victims"].append(d.nick) + evt.data["onlybywolves"].discard(d.nick) + evt.data["killers"][d.nick].append(k.nick) @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] - if actor_role == "dullahan" and nick_role != "dullahan" and actor in TARGETS: - TARGETS[nick] = TARGETS[actor] - {nick} - del TARGETS[actor] - elif nick_role == "dullahan" and actor_role != "dullahan" and nick in TARGETS: - TARGETS[actor] = TARGETS[nick] - {actor} - del TARGETS[nick] + for k in set(KILLS): + if k.nick == actor or k.nick == nick: + del KILLS[k] + + for k in set(TARGETS): + if actor_role == "dullahan" and nick_role != "dullahan" and k.nick == actor: + TARGETS[users._get(nick)] = TARGETS.pop(k) - {users._get(nick)} # FIXME + elif nick_role == "dullahan" and actor_role != "dullahan" and k.nick == nick: + TARGET[users._get(actor)] = TARGETS.pop(k) - {users._get(actor)} # FIXME @event_listener("chk_nightdone") def on_chk_nightdone(evt, cli, var): - spl = set(list_players()) + spl = set(get_players()) evt.data["actedcount"] += len(KILLS) - for p in var.ROLES["dullahan"]: - if TARGETS[p] & spl: - evt.data["nightroles"].append(p) + for d, targets in TARGETS.items(): + if targets & spl: + evt.data["nightroles"].append(d.nick) @event_listener("transition_night_end", priority=2) def on_transition_night_end(evt, cli, var): - for dullahan in var.ROLES["dullahan"]: - targets = list(TARGETS[dullahan]) - for target in var.DEAD: - if target in targets: - targets.remove(target) + for dullahan, targets in TARGETS.items(): + targets = (targets - var.DEAD) if not targets: # already all dead - pm(cli, dullahan, "{0} {1}".format(messages["dullahan_simple"], messages["dullahan_targets_dead"])) + dullahan.send("{0} {1}".format(messages["dullahan_simple"], messages["dullahan_targets_dead"])) continue random.shuffle(targets) - if dullahan in var.PLAYERS and not is_user_simple(dullahan): - pm(cli, dullahan, messages["dullahan_notify"]) - else: - pm(cli, dullahan, messages["dullahan_simple"]) + dullahan.send(messages["dullahan_" + ("simple" if dullahan.prefers_simple() else "notify")]) t = messages["dullahan_targets"] if var.FIRST_NIGHT else messages["dullahan_remaining_targets"] - pm(cli, dullahan, t + ", ".join(targets)) + dullahan.send(t + ", ".join([t.nick for t in targets])) @event_listener("role_assignment") def on_role_assignment(evt, cli, var, gamemode, pl, restart): diff --git a/src/wolfgame.py b/src/wolfgame.py index c8b067d..b0da107 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -1624,6 +1624,7 @@ def stats(cli, nick, chan, rest): vb = "are" for role in rs: + count = len(var.ROLES[role]) # only show actual roles if role in var.TEMPLATE_RESTRICTIONS.keys(): continue @@ -2689,47 +2690,47 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death if target2.nick in var.ROLES["blessed villager"]: target2 = None - if target1 in pl: - if target2 in pl and target1 != target2: + if target1.nick in pl: + if target2.nick in pl and target1 is not target2: if var.ROLE_REVEAL in ("on", "team"): - r1 = get_reveal_role(target1) + r1 = get_reveal_role(target1.nick) an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else "" - r2 = get_reveal_role(target2) + r2 = get_reveal_role(target2.nick) an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill"].format(nick, target1, an1, r1, target2, an2, r2) else: tmsg = messages["mad_scientist_kill_no_reveal"].format(nick, target1, target2) cli.msg(botconfig.CHANNEL, tmsg) - debuglog(nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_role(target1), target2, get_role(target2))) + debuglog(nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_role(target1.nick), target2, get_role(target2.nick))) deadlist1 = copy.copy(deadlist) deadlist1.append(target2) deadlist2 = copy.copy(deadlist) deadlist2.append(target1) - del_player(cli, target1, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist1, original = original, ismain = False) - del_player(cli, target2, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist2, original = original, ismain = False) + del_player(cli, target1.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist1, original = original, ismain = False) + del_player(cli, target2.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist2, original = original, ismain = False) pl = refresh_pl(pl) else: if var.ROLE_REVEAL in ("on", "team"): - r1 = get_reveal_role(target1) + r1 = get_reveal_role(target1.nick) an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill_single"].format(nick, target1, an1, r1) else: tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target1) cli.msg(botconfig.CHANNEL, tmsg) - debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_role(target1))) - del_player(cli, target1, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False) + debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_role(target1.nick))) + del_player(cli, target1.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False) pl = refresh_pl(pl) else: - if target2 in pl: + if target2.nick in pl: if var.ROLE_REVEAL in ("on", "team"): - r2 = get_reveal_role(target2) + r2 = get_reveal_role(target2.nick) an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill_single"].format(nick, target2, an2, r2) else: tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target2) cli.msg(botconfig.CHANNEL, tmsg) - debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_role(target2))) - del_player(cli, target2, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False) + debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_role(target2.nick))) + del_player(cli, target2.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False) pl = refresh_pl(pl) else: tmsg = messages["mad_scientist_fail"].format(nick) @@ -5379,7 +5380,7 @@ def relay(var, wrapper, message): return elif wrapper.source.nick not in wolves and var.RESTRICT_WOLFCHAT & var.RW_WOLVES_ONLY_CHAT: return - elif nick not in wolves and var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: + elif wrapper.source.nick not in wolves and var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: return badguys.remove(wrapper.source.nick)