diff --git a/src/channels.py b/src/channels.py index b173fab..c45cd12 100644 --- a/src/channels.py +++ b/src/channels.py @@ -303,3 +303,5 @@ class FakeChannel(Channel): targets.append(target) self.update_modes(users.Bot.rawnick, "".join(modes), targets) + +# vim: set sw=4 expandtab: diff --git a/src/context.py b/src/context.py index 57007bf..5fc96da 100644 --- a/src/context.py +++ b/src/context.py @@ -224,3 +224,5 @@ class IRCContext: if sep is None: sep = " " _send(data, first, sep, self.client, send_type, name) + +# vim: set sw=4 expandtab: diff --git a/src/decorators.py b/src/decorators.py index cee0d9c..b604526 100644 --- a/src/decorators.py +++ b/src/decorators.py @@ -287,7 +287,7 @@ class command: return for role in self.roles: - if user.nick in var.ROLES[role]: # FIXME: Need to change this once var.ROLES[role] holds User instances + if user in var.ROLES[role]: break else: if (self.users is not None and user not in self.users) or self.roles: @@ -434,7 +434,7 @@ class cmd: return for role in self.roles: - if nick in var.ROLES[role]: + if users._get(nick) in var.ROLES[role]: break else: if (self.nicks is not None and nick not in self.nicks) or self.roles: diff --git a/src/dispatcher.py b/src/dispatcher.py index 1e102ec..bc25229 100644 --- a/src/dispatcher.py +++ b/src/dispatcher.py @@ -46,3 +46,5 @@ class MessageDispatcher: else: kwargs.setdefault("first", first) self.target.send(*messages, **kwargs) + +# vim: set sw=4 expandtab: diff --git a/src/functions.py b/src/functions.py index e6281c9..8bd6854 100644 --- a/src/functions.py +++ b/src/functions.py @@ -21,13 +21,15 @@ def get_players(roles=None, *, mainroles=None): return list(pl) return [p for p in var.ALL_PLAYERS if p in pl] -def get_all_players(roles=None): +def get_all_players(roles=None, *, rolemap=None): + if rolemap is None: + rolemap = var.ROLES if roles is None: - roles = var.ROLES + roles = set(rolemap.keys()) pl = set() for role in roles: - for nick in var.ROLES[role]: - pl.add(users._get(nick)) # FIXME + for user in rolemap[role]: + pl.add(user) return pl @@ -73,4 +75,6 @@ def get_main_role(user): return role def get_all_roles(user): - return {role for role, nicks in var.ROLES.items() if user.nick in nicks} + return {role for role, users in var.ROLES.items() if user in users} + +# vim: set sw=4 expandtab: diff --git a/src/gamemodes.py b/src/gamemodes.py index 4919452..ef62875 100644 --- a/src/gamemodes.py +++ b/src/gamemodes.py @@ -215,7 +215,7 @@ class VillagergameMode(GameMode): evt.data["transition_day"] = lambda cli, gameid=0: self.prolong_night(cli, var, gameid, transition_day) def prolong_night(self, cli, var, gameid, transition_day): - nspecials = len(var.ROLES["seer"] | var.ROLES["harlot"] | var.ROLES["shaman"] | var.ROLES["crazed shaman"]) + nspecials = len(get_players(("seer", "harlot", "shaman", "crazed shaman"))) rand = random.gauss(5, 1.5) if rand <= 0 and nspecials > 0: transition_day(cli, gameid=gameid) @@ -227,7 +227,7 @@ class VillagergameMode(GameMode): # 30% chance we kill a safe, otherwise kill at random # when killing safes, go after seer, then harlot, then shaman self.delaying_night = False - pl = list_players() + pl = get_players() tgt = None seer = None hlt = None @@ -238,10 +238,9 @@ class VillagergameMode(GameMode): if len(var.ROLES["harlot"]) == 1: hlt = list(var.ROLES["harlot"])[0] from src.roles import harlot - hvst = harlot.VISITED.get(users._get(hlt)) # FIXME + hvst = harlot.VISITED.get(hlt) if hvst is not None: pl.remove(hlt) - hvst = hvst.nick # FIXME if len(var.ROLES["shaman"]) == 1: shmn = list(var.ROLES["shaman"])[0] if random.random() < 0.3: @@ -256,7 +255,7 @@ class VillagergameMode(GameMode): if not tgt: tgt = random.choice(pl) from src.roles import wolf - wolf.KILLS[botconfig.NICK] = [tgt] + wolf.KILLS[botconfig.NICK] = [tgt.nick] def on_retribution_kill(self, evt, var, victim, orig_target): # There are no wolves for this totem to kill @@ -914,7 +913,7 @@ class SleepyMode(GameMode): def dullahan_targets(self, evt, cli, var, dullahans, max_targets): for dull in dullahans: - evt.data["targets"][dull] = {users._get(x) for x in var.ROLES["priest"]} + evt.data["targets"][dull] = set(var.ROLES["priest"]) def setup_nightmares(self, evt, cli, var): if random.random() < 1/5: @@ -1225,7 +1224,7 @@ class MaelstromMode(GameMode): from src import hooks, channels role = random.choice(self.roles) rolemap = copy.deepcopy(var.ROLES) - rolemap[role].add(wrapper.source.nick) # FIXME: add user instead of nick (can only be done once var.ROLES itself uses users) + rolemap[role].add(wrapper.source) mainroles = copy.deepcopy(var.MAIN_ROLES) mainroles[wrapper.source] = role @@ -1238,9 +1237,9 @@ class MaelstromMode(GameMode): cmodes.append(("-" + mode, wrapper.source)) var.OLD_MODES[wrapper.source].add(mode) channels.Main.mode(*cmodes) - var.ROLES[role].add(wrapper.source.nick) # FIXME: add user instead of nick - var.ORIGINAL_ROLES[role].add(wrapper.source.nick) - var.FINAL_ROLES[wrapper.source.nick] = role + var.ROLES[role].add(wrapper.source) + var.ORIGINAL_ROLES[role].add(wrapper.source) + var.FINAL_ROLES[wrapper.source.nick] = role # FIXME: once FINAL_ROLES stores users var.MAIN_ROLES[wrapper.source] = role var.LAST_SAID_TIME[wrapper.source.nick] = datetime.now() if wrapper.source.nick in var.USERS: @@ -1258,19 +1257,19 @@ class MaelstromMode(GameMode): relay_wolfchat_command(wrapper.source.client, wrapper.source.nick, messages["wolfchat_new_member"].format(wrapper.source.nick, role), var.WOLFCHAT_ROLES, is_wolf_command=True, is_kill_command=True) # TODO: make this part of !myrole instead, no reason we can't give out wofllist in that wolves = list_players(var.WOLFCHAT_ROLES) - pl = list_players() + pl = get_players() random.shuffle(pl) - pl.remove(wrapper.source.nick) + pl.remove(wrapper.source) for i, player in enumerate(pl): - prole = get_role(player) + prole = get_main_role(player) if prole in var.WOLFCHAT_ROLES: cursed = "" if player in var.ROLES["cursed villager"]: cursed = "cursed " pl[i] = "\u0002{0}\u0002 ({1}{2})".format(player, cursed, prole) elif player in var.ROLES["cursed villager"]: - pl[i] = player + " (cursed)" - wrapper.pm("Players: " + ", ".join(pl)) + pl[i] = player.nick + " (cursed)" + wrapper.pm("Players: " + ", ".join(p.nick for p in pl)) def role_attribution(self, evt, cli, var, chk_win_conditions, villagers): self.chk_win_conditions = chk_win_conditions @@ -1280,7 +1279,7 @@ class MaelstromMode(GameMode): # don't do this n1 if var.FIRST_NIGHT: return - villagers = list_players() + villagers = get_players() lpl = len(villagers) addroles = self._role_attribution(cli, var, villagers, False) @@ -1293,7 +1292,7 @@ class MaelstromMode(GameMode): # Handle roles that need extra help for doctor in var.ROLES["doctor"]: - var.DOCTORS[doctor] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * lpl) + var.DOCTORS[doctor.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * lpl) # Clear totem tracking; this would let someone that gets shaman twice in a row to give # out a totem to the same person twice in a row, but oh well @@ -1312,8 +1311,8 @@ class MaelstromMode(GameMode): continue var.ORIGINAL_ROLES[r].discard(p) var.ORIGINAL_ROLES[role].add(p) - var.FINAL_ROLES[p] = role - var.MAIN_ROLES[users._get(p)] = role # FIXME + var.FINAL_ROLES[p.nick] = role # FIXME + var.MAIN_ROLES[p] = role def _role_attribution(self, cli, var, villagers, do_templates): lpl = len(villagers) - 1 @@ -1349,7 +1348,7 @@ class MaelstromMode(GameMode): if count > 0: for j in range(count): u = users.FakeUser.from_nick(str(i + j)) - rolemap[role].add(u.nick) + rolemap[role].add(u) if role not in var.TEMPLATE_RESTRICTIONS: mainroles[u] = role i += count diff --git a/src/roles/angel.py b/src/roles/angel.py index d659d94..ebdc9aa 100644 --- a/src/roles/angel.py +++ b/src/roles/angel.py @@ -146,10 +146,10 @@ def on_transition_day(evt, var): var.ACTIVE_PROTECTIONS[v.nick].append("bodyguard") else: for g in var.ROLES["guardian angel"]: - if GUARDED.get(g) == v.nick: + if GUARDED.get(g.nick) == v.nick: var.ACTIVE_PROTECTIONS[v.nick].append("angel") for g in var.ROLES["bodyguard"]: - if GUARDED.get(g) == v.nick: + if GUARDED.get(g.nick) == v.nick: var.ACTIVE_PROTECTIONS[v.nick].append("bodyguard") @event_listener("fallen_angel_guard_break") @@ -277,10 +277,10 @@ def on_assassinate(evt, var, killer, target, prot): evt.prevent_default = True evt.stop_processing = True for bg in var.ROLES["bodyguard"]: - if GUARDED.get(bg) == target.nick: + if GUARDED.get(bg.nick) == target.nick: channels.Main.send(messages[evt.params.message_prefix + "bodyguard"].format(killer, target, bg)) # redirect the assassination to the bodyguard - evt.data["target"] = users._get(bg) # FIXME + evt.data["target"] = bg break @event_listener("begin_day") diff --git a/src/roles/blessed.py b/src/roles/blessed.py index 669bd83..4c2f46d 100644 --- a/src/roles/blessed.py +++ b/src/roles/blessed.py @@ -75,7 +75,7 @@ def on_assassinate(evt, var, killer, target, prot): @event_listener("myrole") def on_myrole(evt, var, user): - if user.nick in var.ROLES["blessed villager"]: + if user in var.ROLES["blessed villager"]: evt.data["messages"].append(messages["blessed_simple"]) # vim: set sw=4 expandtab: diff --git a/src/roles/cursed.py b/src/roles/cursed.py index 0e6fcd4..0a90adb 100644 --- a/src/roles/cursed.py +++ b/src/roles/cursed.py @@ -14,12 +14,12 @@ from src.events import Event @event_listener("see") def on_see(evt, cli, var, nick, victim): - if victim in var.ROLES["cursed villager"]: + if users._get(victim) in var.ROLES["cursed villager"]: # FIXME evt.data["role"] = "wolf" @event_listener("wolflist") def on_wolflist(evt, var, player, wolf): - if player.nick in var.ROLES["cursed villager"]: + if player in var.ROLES["cursed villager"]: evt.data["tags"].add("cursed") # vim: set sw=4 expandtab: diff --git a/src/roles/detective.py b/src/roles/detective.py index d8111a9..03b031e 100644 --- a/src/roles/detective.py +++ b/src/roles/detective.py @@ -79,7 +79,7 @@ def on_exchange(evt, var, actor, target, actor_role, target_role): @event_listener("transition_night_end", priority=2) def on_transition_night_end(evt, var): ps = get_players() - for dttv in get_all_players(("detective",)): + for dttv in var.ROLES["detective"]: pl = ps[:] random.shuffle(pl) pl.remove(dttv) diff --git a/src/roles/dullahan.py b/src/roles/dullahan.py index cdbce90..6178b48 100644 --- a/src/roles/dullahan.py +++ b/src/roles/dullahan.py @@ -179,9 +179,9 @@ def on_role_assignment(evt, cli, var, gamemode, pl, restart): if var.ROLES["dullahan"]: max_targets = math.ceil(8.1 * math.log(len(pl), 10) - 5) for dull in var.ROLES["dullahan"]: - TARGETS[users._get(dull)] = set() # FIXME + TARGETS[dull] = set() dull_targets = Event("dullahan_targets", {"targets": TARGETS}) # support sleepy - dull_targets.dispatch(cli, var, {users._get(x) for x in var.ROLES["dullahan"]}, max_targets) # FIXME + dull_targets.dispatch(cli, var, var.ROLES["dullahan"], max_targets) players = [users._get(x) for x in pl] # FIXME @@ -199,19 +199,19 @@ def on_succubus_visit(evt, cli, var, nick, victim): if user in TARGETS: succ_target = False for target in set(TARGETS[user]): - if target.nick in var.ROLES["succubus"]: + if target in var.ROLES["succubus"]: TARGETS[user].remove(target) succ_target = True if succ_target: pm(cli, victim, messages["dullahan_no_kill_succubus"]) - if user in KILLS and KILLS[user].nick in var.ROLES["succubus"]: + if user in KILLS and KILLS[user] in var.ROLES["succubus"]: pm(cli, victim, messages["no_kill_succubus"].format(KILLS[user])) del KILLS[user] @event_listener("myrole") def on_myrole(evt, var, user): # Remind dullahans of their targets - if user.nick in var.ROLES["dullahan"]: + if user in var.ROLES["dullahan"]: targets = list(TARGETS[user]) for target in list(targets): if target.nick in var.DEAD: @@ -250,8 +250,7 @@ def on_get_role_metadata(evt, var, kind): if kind == "night_kills": num = 0 for dull in var.ROLES["dullahan"]: - user = users._get(dull) # FIXME - for target in TARGETS[user]: + for target in TARGETS[dull]: if target.nick not in var.DEAD: num += 1 break diff --git a/src/roles/harlot.py b/src/roles/harlot.py index 648f3dd..d1dd979 100644 --- a/src/roles/harlot.py +++ b/src/roles/harlot.py @@ -59,7 +59,7 @@ def pass_cmd(var, wrapper, message): @event_listener("bite") def on_bite(evt, var, alpha, target): - if target.nick not in var.ROLES["harlot"] or target not in VISITED: + if target not in var.ROLES["harlot"] or target not in VISITED: return hvisit = VISITED[target] if get_main_role(hvisit) not in var.WOLFCHAT_ROLES and (hvisit not in evt.params.bywolves or hvisit in evt.params.protected): @@ -67,7 +67,7 @@ def on_bite(evt, var, alpha, target): @event_listener("transition_day_resolve", priority=1) def on_transition_day_resolve(evt, var, victim): - if victim.nick in var.ROLES["harlot"] and VISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]: + if victim in var.ROLES["harlot"] and VISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]: if victim not in evt.data["bitten"]: evt.data["message"].append(messages["target_not_home"]) evt.data["novictmsg"] = False diff --git a/src/roles/hunter.py b/src/roles/hunter.py index cb167f0..dde0454 100644 --- a/src/roles/hunter.py +++ b/src/roles/hunter.py @@ -140,7 +140,7 @@ def on_transition_night_end(evt, var): @event_listener("succubus_visit") def on_succubus_visit(evt, cli, var, nick, victim): user = users._get(victim) # FIXME - if user in KILLS and KILLS[user].nick in var.ROLES["succubus"]: # FIXME + if user in KILLS and KILLS[user] in var.ROLES["succubus"]: user.send(messages["no_kill_succubus"].format(KILLS[user])) del KILLS[user] HUNTERS.discard(user) @@ -161,7 +161,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 = ({users._get(h) for h in var.ROLES["hunter"]} - HUNTERS) | set(KILLS.keys()) # FIXME + hunters = (var.ROLES["hunter"] - HUNTERS) | set(KILLS.keys()) evt.data["hunter"] = len(hunters) # vim: set sw=4 expandtab: diff --git a/src/roles/madscientist.py b/src/roles/madscientist.py index b6a6880..d44ee5b 100644 --- a/src/roles/madscientist.py +++ b/src/roles/madscientist.py @@ -163,7 +163,7 @@ def on_transition_night_end(evt, var): @event_listener("myrole") def on_myrole(evt, var, user): - if user.nick in var.ROLES["mad scientist"]: + if user in var.ROLES["mad scientist"]: pl = get_players() target1, target2 = _get_targets(var, pl, user) evt.data["messages"].append(messages["mad_scientist_myrole_targets"].format(target1, target2)) diff --git a/src/roles/mayor.py b/src/roles/mayor.py index 18584ae..2362e5f 100644 --- a/src/roles/mayor.py +++ b/src/roles/mayor.py @@ -23,7 +23,7 @@ def on_rename_player(evt, cli, var, prefix, nick): @event_listener("chk_decision_lynch", priority=3) def on_chk_decision_lynch(evt, cli, var, voters): votee = evt.data["votee"] - if votee in var.ROLES["mayor"] and votee not in REVEALED_MAYORS: + if users._get(votee) in var.ROLES["mayor"] and votee not in REVEALED_MAYORS: # FIXME cli.msg(botconfig.CHANNEL, messages["mayor_reveal"].format(votee)) REVEALED_MAYORS.add(votee) evt.data["votee"] = None diff --git a/src/roles/shaman.py b/src/roles/shaman.py index 954c336..1f269e7 100644 --- a/src/roles/shaman.py +++ b/src/roles/shaman.py @@ -455,7 +455,7 @@ def on_transition_day_resolve6(evt, var, victim): # that will not be an issue once everything is using the event if evt.data["protected"].get(victim): return - if victim.nick in var.ROLES["lycan"] and victim in evt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED: + if victim in var.ROLES["lycan"] and victim in evt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED: return # END checks to remove @@ -540,7 +540,7 @@ def on_transition_night_end(evt, var): shaman.send(messages["totem_simple"].format(TOTEMS[shaman.nick])) # FIXME else: if role not in var.WOLFCHAT_ROLES: - shaman.send(messages["shaman_notify"].format(role, "random " if shaman.nick in var.ROLES["crazed shaman"] else "")) # FIXME + shaman.send(messages["shaman_notify"].format(role, "random " if shaman in var.ROLES["crazed shaman"] else "")) if role != "crazed shaman": totem = TOTEMS[shaman.nick] # FIXME tmsg = messages["shaman_totem"].format(totem) @@ -587,7 +587,7 @@ def on_assassinate(evt, var, killer, target, prot): @event_listener("succubus_visit") def on_succubus_visit(evt, cli, var, nick, victim): - if (SHAMANS.get(victim, (None, None))[1] in var.ROLES["succubus"] and + if (users._get(SHAMANS.get(victim, (None, None))[1]) in var.ROLES["succubus"] and # FIXME (psst Vgr: this probably breaks now if the shaman didn't give out totems when succ visits) (get_role(victim) == "crazed shaman" or TOTEMS[victim] not in var.BENEFICIAL_TOTEMS)): pm(cli, victim, messages["retract_totem_succubus"].format(SHAMANS[victim])) del SHAMANS[victim] diff --git a/src/roles/vigilante.py b/src/roles/vigilante.py index 825bcff..488cf35 100644 --- a/src/roles/vigilante.py +++ b/src/roles/vigilante.py @@ -125,7 +125,7 @@ def on_transition_night_end(evt, var): def on_succubus_visit(evt, cli, var, nick, victim): for vigilante, target in set(KILLS.items()): if vigilante.nick == victim: - if target.nick in var.ROLES["succubus"]: + if target in var.ROLES["succubus"]: vigilante.send(messages["no_kill_succubus"].format(target)) del KILLS[vigilante] diff --git a/src/roles/wildchild.py b/src/roles/wildchild.py index 31db765..bb71728 100644 --- a/src/roles/wildchild.py +++ b/src/roles/wildchild.py @@ -92,7 +92,7 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): child.send(messages["idol_died"]) WILD_CHILDREN.add(child.nick) change_role(child, get_main_role(child), "wolf") - var.ROLES["wild child"].discard(child.nick) + var.ROLES["wild child"].discard(child) wcroles = var.WOLFCHAT_ROLES if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: diff --git a/src/roles/wolf.py b/src/roles/wolf.py index 1c53021..8367a19 100644 --- a/src/roles/wolf.py +++ b/src/roles/wolf.py @@ -102,7 +102,7 @@ def wolf_retract(cli, nick, chan, rest): del KILLS[nick] pm(cli, nick, messages["retracted_kill"]) relay_wolfchat_command(cli, nick, messages["wolfchat_retracted_kill"].format(nick), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True) - if nick in var.ROLES["alpha wolf"] and nick in var.BITE_PREFERENCES: + if users._get(nick) in var.ROLES["alpha wolf"] and nick in var.BITE_PREFERENCES: # FIXME del var.BITE_PREFERENCES[nick] var.ALPHA_WOLVES.remove(nick) pm(cli, nick, messages["no_bite"]) @@ -414,7 +414,7 @@ def on_transition_night_end(evt, var): elif role == "warlock": # warlock specifically only sees cursed if they're not in wolfchat for player in pl: - if player.nick in var.ROLES["cursed villager"]: # FIXME: Once var.ROLES holds User instances + if player in var.ROLES["cursed villager"]: players.append(player.nick + " (cursed)") else: players.append(player.nick) @@ -428,11 +428,11 @@ def on_transition_night_end(evt, var): @event_listener("succubus_visit") def on_succubus_visit(evt, cli, var, nick, victim): - if var.ROLES["succubus"].intersection(KILLS.get(victim, ())): + if var.ROLES["succubus"].intersection(users._get(x) for x in KILLS.get(victim, ())): # FIXME: once KILLS holds User instances for s in var.ROLES["succubus"]: - if s in KILLS[victim]: + if s.nick in KILLS[victim]: # FIXME pm(cli, victim, messages["no_kill_succubus"].format(nick)) - KILLS[victim].remove(s) + KILLS[victim].remove(s.nick) # FIXME if not KILLS[victim]: del KILLS[victim] diff --git a/src/users.py b/src/users.py index a735185..ea06524 100644 --- a/src/users.py +++ b/src/users.py @@ -642,3 +642,5 @@ class BotUser(User): # TODO: change all the 'if x is Bot' for 'if isinstance(x, if nick is None: nick = self.nick self.client.send("NICK", nick) + +# vim: set sw=4 expandtab: diff --git a/src/utilities.py b/src/utilities.py index 2c9f3ad..42ffac7 100644 --- a/src/utilities.py +++ b/src/utilities.py @@ -211,7 +211,7 @@ def irc_lower(nick): def irc_equals(nick1, nick2): return irc_lower(nick1) == irc_lower(nick2) -is_role = lambda plyr, rol: rol in var.ROLES and plyr in var.ROLES[rol] +is_role = lambda plyr, rol: rol in var.ROLES and users._get(plyr) in var.ROLES[rol] def match_hostmask(hostmask, nick, ident, host): # support n!u@h, u@h, or just h by itself @@ -344,7 +344,7 @@ def get_roles(*roles, rolemap=None): all_roles = [] for role in roles: all_roles.append(rolemap[role]) - return list(itertools.chain(*all_roles)) + return [u.nick for u in itertools.chain(*all_roles)] def get_reveal_role(nick): # FIXME: make the arg a user instead of a nick @@ -371,18 +371,18 @@ def get_reveal_role(nick): return "village member" def get_templates(nick): - # FIXME: make the arg a user instead of a nick mainrole = get_role(nick) tpl = [] - for role, nicks in var.ROLES.items(): - if nick in nicks and role != mainrole: + for role, users in var.ROLES.items(): + if users._get(nick) in users and role != mainrole: tpl.append(role) return tpl +# TODO: move this to functions.py def change_role(user, oldrole, newrole, set_final=True): - var.ROLES[oldrole].remove(user.nick) - var.ROLES[newrole].add(user.nick) + var.ROLES[oldrole].remove(user) + var.ROLES[newrole].add(user) # only adjust MAIN_ROLES/FINAL_ROLES if we're changing the user's actual role if var.MAIN_ROLES[user] == oldrole: var.MAIN_ROLES[user] = newrole diff --git a/src/wolfgame.py b/src/wolfgame.py index d452226..45c4a77 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -73,6 +73,7 @@ var.USERS = {} var.ADMIN_PINGING = False var.ORIGINAL_ROLES = {} +var.DCED_LOSERS = set() # type: Set[users.User] var.PLAYERS = {} var.DCED_PLAYERS = {} var.ADMIN_TO_PING = None @@ -297,7 +298,7 @@ def reset(): var.GAME_ID = 0 var.RESTART_TRIES = 0 var.DEAD = set() - var.ROLES = {"person" : set()} + var.ROLES = {"person" : set()} # type: Dict[str, Set[users.User]] var.MAIN_ROLES = {} # type: Dict[users.User, str] var.ALL_PLAYERS = [] var.JOINED_THIS_GAME = set() # keeps track of who already joined this game at least once (hostmasks) @@ -318,6 +319,7 @@ def reset(): var.PLAYERS.clear() var.DCED_PLAYERS.clear() var.DISCONNECTED.clear() + var.DCED_LOSERS.clear() var.SPECTATING_WOLFCHAT = set() var.SPECTATING_DEADCHAT = set() @@ -596,6 +598,11 @@ def replace(var, wrapper, message): def swap_player(evt, var, old_user, user): var.ALL_PLAYERS[var.ALL_PLAYERS.index(old_user)] = user var.MAIN_ROLES[user] = var.MAIN_ROLES.pop(old_user) + for role, players in var.ROLES.items(): + if old_user in players: + players.remove(old_user) + players.add(user) + @command("pingif", "pingme", "pingat", "pingpref", pm=True) def altpinger(var, wrapper, message): @@ -863,7 +870,7 @@ def join_player(var, wrapper, who=None, forced=False, *, sanity=True): for mode in var.AUTO_TOGGLE_MODES & wrapper.source.channels[channels.Main]: cmodes.append(("-" + mode, wrapper.source)) var.OLD_MODES[wrapper.source].add(mode) - var.ROLES["person"].add(wrapper.source.nick) # FIXME: Need to store Users, not nicks + var.ROLES["person"].add(wrapper.source) var.MAIN_ROLES[wrapper.source] = "person" var.ALL_PLAYERS.append(wrapper.source) var.PHASE = "join" @@ -922,7 +929,7 @@ def join_player(var, wrapper, who=None, forced=False, *, sanity=True): var.SPECTATING_DEADCHAT.discard(wrapper.source) var.SPECTATING_WOLFCHAT.discard(wrapper.source) return True - var.ROLES["person"].add(wrapper.source.nick) + var.ROLES["person"].add(wrapper.source) var.MAIN_ROLES[wrapper.source] = "person" if not wrapper.source.is_fake: if wrapper.source.userhost not in var.JOINED_THIS_GAME and wrapper.source.account not in var.JOINED_THIS_GAME_ACCS: @@ -1091,10 +1098,6 @@ def fleave(var, wrapper, message): wrapper.send(*msg) if var.PHASE != "join": - for roleset in var.ORIGINAL_ROLES.values(): - if target.nick in roleset: - roleset.remove(target.nick) - roleset.add("(dced)" + target.nick) if target.nick in var.PLAYERS: var.DCED_PLAYERS[target.nick] = var.PLAYERS.pop(target.nick) @@ -1173,7 +1176,7 @@ def stats(cli, nick, chan, rest): elif role == "warlock": # warlock not in wolfchat explicitly only sees cursed for i, player in enumerate(pl): - if player in var.ROLES["cursed villager"]: + if player in get_roles("cursed villager"): # FIXME ps[i] = player + " (cursed)" msg = "\u0002{0}\u0002 players: {1}".format(len(pl), ", ".join(ps)) elif len(pl) > 1: @@ -1216,9 +1219,7 @@ def stats(cli, nick, chan, rest): start_roles.add(r) rolecounts[r] = [len(v), len(v)] for p in v: - if p.startswith("(dced)"): - p = p[6:] - orig_roles[p] = r + orig_roles[p.nick] = r if var.CURRENT_GAMEMODE.name == "villagergame": # hacky hacks that hack @@ -1862,7 +1863,7 @@ def chk_decision(cli, force=""): if vote_evt.dispatch(cli, var, voters): votee = vote_evt.data["votee"] # roles that end the game upon being lynched - if votee in var.ROLES["fool"]: + if votee in get_roles("fool"): # FIXME # ends game immediately, with fool as only winner # hardcode "fool" as the role since game is ending due to them being lynched, # so we want to show "fool" even if it's a template @@ -1872,7 +1873,7 @@ def chk_decision(cli, force=""): return deadlist.append(votee) # Other - if votee in var.ROLES["jester"]: + if votee in get_roles("jester"): # FIXME var.JESTERS.add(votee) if var.ROLE_REVEAL in ("on", "team"): @@ -1994,19 +1995,16 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): roles_msg = [] - origroles = {} #nick based list of original roles + origroles = {} # user-based list of original roles rolelist = copy.deepcopy(var.ORIGINAL_ROLES) for role, playerlist in var.ORIGINAL_ROLES.items(): if role in var.TEMPLATE_RESTRICTIONS.keys(): continue for p in playerlist: - player = p #with (dced) still in - if p.startswith("(dced)"): - p = p[6:] - final = var.FINAL_ROLES.get(p, role) + final = var.FINAL_ROLES.get(p.nick, role) if role != final: origroles[p] = role - rolelist[role].remove(player) + rolelist[role].remove(p) rolelist[final].add(p) prev = False for role in role_order(): @@ -2014,8 +2012,6 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): continue playersformatted = [] for p in rolelist[role]: - if p.startswith("(dced)"): - p = p[6:] if p in origroles and role not in var.TEMPLATE_RESTRICTIONS.keys(): playersformatted.append("\u0002{0}\u0002 ({1}{2})".format(p, "" if prev else "was ", origroles[p])) @@ -2065,7 +2061,7 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): player_list = [] if additional_winners is not None: winners.update(additional_winners) - for role,ppl in var.ORIGINAL_ROLES.items(): + for role, ppl in var.ORIGINAL_ROLES.items(): if role in var.TEMPLATE_RESTRICTIONS.keys(): for x in ppl: if x is not None: @@ -2074,12 +2070,12 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): for x in ppl: if x is not None: if x in var.FINAL_ROLES: - plrl[x] = var.FINAL_ROLES[x] + plrl[x] = var.FINAL_ROLES[x.nick] else: plrl[x] = role for plr, rol in plrl.items(): orol = rol # original role, since we overwrite rol in case of clone - splr = plr # plr stripped of the (dced) bit at the front, since other dicts don't have that + splr = plr.nick # FIXME: for backwards-compat pentry = {"nick": None, "account": None, "ident": None, @@ -2090,21 +2086,13 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): "won": False, "iwon": False, "dced": False} - if plr.startswith("(dced)"): + if plr in var.DCED_LOSERS: pentry["dced"] = True - splr = plr[6:] - if users.exists(splr): - if not var.DISABLE_ACCOUNTS: - pentry["account"] = users.get(splr).account - pentry["nick"] = splr - pentry["ident"] = users.get(splr).ident - pentry["host"] = users.get(splr).host - elif plr in var.USERS: - if not var.DISABLE_ACCOUNTS: - pentry["account"] = users.get(plr).account - pentry["nick"] = plr - pentry["ident"] = users.get(plr).ident - pentry["host"] = users.get(plr).host + if not var.DISABLE_ACCOUNTS: + pentry["account"] = plr.account + pentry["nick"] = plr.nick + pentry["ident"] = plr.ident + pentry["host"] = plr.host pentry["role"] = rol pentry["templates"] = pltp[plr] @@ -2113,10 +2101,10 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): won = False iwon = False - survived = list_players() + survived = get_players() if not pentry["dced"]: evt = Event("player_win", {"won": won, "iwon": iwon, "special": pentry["special"]}) - evt.dispatch(var, users._get(splr), rol, winner, splr in survived) # FIXME + evt.dispatch(var, plr, rol, winner, plr in survived) won = evt.data["won"] iwon = evt.data["iwon"] # ensure that it is a) a list, and b) a copy (so it can't be mutated out from under us later) @@ -2143,15 +2131,16 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): iwon = False elif rol == "fool" and "@" + splr == winner: iwon = True - elif winner != "lovers" and splr in var.LOVERS and splr in survived and len([x for x in var.LOVERS[splr] if x in survived]) > 0: + elif winner != "lovers" and splr in var.LOVERS and plr in survived and len([x for x in var.LOVERS[splr] if users._get(x) in survived]) > 0: # FIXME for lvr in var.LOVERS[splr]: - if lvr not in survived: + lvuser = users._get(lvr) # FIXME + if lvuser not in survived: # cannot win with dead lover (if splr in survived and lvr is not, that means lvr idled out) continue lvrrol = "" #somehow lvrrol wasn't set and caused a crash once - if lvr in plrl: - lvrrol = plrl[lvr] + if lvuser in plrl: + lvrrol = plrl[lvuser] if not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES: iwon = True @@ -2169,18 +2158,18 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): elif winner == "pipers" and lvrrol == "piper": iwon = True break - elif rol == "monster" and splr in survived and winner == "monsters": + elif rol == "monster" and plr in survived and winner == "monsters": iwon = True - elif rol == "demoniac" and splr in survived and winner == "demoniacs": + elif rol == "demoniac" and plr in survived and winner == "demoniacs": iwon = True elif rol == "clone": # this means they ended game while being clone and not some other role - if splr in survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES: + if plr in survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES: iwon = True elif rol == "jester" and splr in var.JESTERS: iwon = True elif not iwon: - iwon = won and splr in survived # survived, team won = individual win + iwon = won and plr in survived # survived, team won = individual win if winner == "": pentry["won"] = False @@ -2189,9 +2178,9 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True): pentry["won"] = won pentry["iwon"] = iwon if won or iwon: - winners.add(splr) + winners.add(plr.nick) - if pentry["nick"] is not None: + if not plr.is_fake: # don't record fjoined fakes player_list.append(pentry) @@ -2393,7 +2382,7 @@ def del_player(player, *, devoice=True, end_game=True, death_triggers=True, kill allroles = get_all_roles(player) del var.MAIN_ROLES[player] for r in allroles: - var.ROLES[r].remove(player.nick) # FIXME + var.ROLES[r].remove(player) if player.nick in var.BITTEN_ROLES: del var.BITTEN_ROLES[player.nick] # FIXME pl.discard(player) @@ -2760,10 +2749,7 @@ def reaper(cli, gameid): cli.msg(chan, messages["idle_death"].format(nck, get_reveal_role(nck))) else: cli.msg(chan, (messages["idle_death_no_reveal"]).format(nck)) - for r,rlist in var.ORIGINAL_ROLES.items(): - if nck in rlist: - var.ORIGINAL_ROLES[r].remove(nck) - var.ORIGINAL_ROLES[r].add("(dced)"+nck) + users._get(nck).disconnected = True # FIXME if var.IDLE_PENALTY: add_warning(cli, nck, var.IDLE_PENALTY, botconfig.NICK, messages["idle_warning"], expires=var.IDLE_EXPIRY) del_player(users._get(nck), end_game=False, death_triggers=False) # FIXME @@ -2910,10 +2896,7 @@ def return_to_village(var, target, *, show_message, new_user=None): new_user = target var.LAST_SAID_TIME[target.nick] = datetime.now() - for roleset in var.ORIGINAL_ROLES.values(): - if "(dced)" + target.nick in roleset: - roleset.remove("(dced)" + target.nick) - roleset.add(target.nick) + var.DCED_LOSERS.discard(target) if target.nick in var.DCED_PLAYERS: var.PLAYERS[target.nick] = var.DCED_PLAYERS.pop(target.nick) @@ -2954,19 +2937,7 @@ def rename_player(var, user, prefix): event.dispatch(user.client, var, prefix, nick) # FIXME: Need to update all the callbacks if user in var.ALL_PLAYERS: - for role, nicks in var.ROLES.items(): - if prefix in nicks: - nicks.remove(prefix) - nicks.add(user.nick) - if var.PHASE in var.GAME_PHASES: - for k,v in var.ORIGINAL_ROLES.items(): - if prefix in v: - var.ORIGINAL_ROLES[k].remove(prefix) - var.ORIGINAL_ROLES[k].add(nick) - if "(dced)"+prefix in v: - var.ORIGINAL_ROLES[k].remove("(dced)"+prefix) - var.ORIGINAL_ROLES[k].add(nick) for k,v in list(var.PLAYERS.items()): if prefix == k: var.PLAYERS[nick] = var.PLAYERS.pop(k) @@ -3139,13 +3110,7 @@ def leave(var, what, user, why=None): ps = get_players() # Only mark living players as disconnected, unless they were kicked if user.nick in var.PLAYERS and (what == "kick" or user in ps): # FIXME: Convert var.PLAYERS - # Prevent duplicate entry in var.ORIGINAL_ROLES - for roleset in var.ORIGINAL_ROLES.values(): - if user.nick in roleset: # FIXME: Need to fix this once the role sets hold User instances - roleset.remove(user.nick) - roleset.add("(dced)" + user.nick) # FIXME: Need to get rid of all the (dced) hacks - break - + var.DCED_LOSERS.add(user) var.DCED_PLAYERS[user.nick] = var.PLAYERS.pop(user.nick) # FIXME: Convert var.PLAYERS and var.DCED_PLAYERS if user not in ps or user in var.DISCONNECTED: @@ -3244,10 +3209,7 @@ def leave_game(cli, nick, chan, rest): lmsg = random.choice(messages["quit_no_reveal"]).format(nick) + population cli.msg(botconfig.CHANNEL, lmsg) if var.PHASE != "join": - for r, rset in var.ORIGINAL_ROLES.items(): - if nick in rset: - var.ORIGINAL_ROLES[r].remove(nick) - var.ORIGINAL_ROLES[r].add("(dced)"+nick) + var.DCED_LOSERS.add(users._get(nick)) # FIXME if var.LEAVE_PENALTY: add_warning(cli, nick, var.LEAVE_PENALTY, botconfig.NICK, messages["leave_warning"], expires=var.LEAVE_EXPIRY) if nick in var.PLAYERS: @@ -3346,8 +3308,8 @@ def transition_day(cli, gameid=0): if not var.START_WITH_DAY or not var.FIRST_DAY: if len(var.HEXED) < len(var.ROLES["hag"]): for hag in var.ROLES["hag"]: - if hag not in var.HEXED: - var.LASTHEXED[hag] = None + if hag.nick not in var.HEXED: # FIXME + var.LASTHEXED[hag.nick] = None # FIXME # NOTE: Random assassin selection is further down, since if we're choosing at random we pick someone # that isn't going to be dying today, meaning we need to know who is dying first :) @@ -3375,7 +3337,7 @@ def transition_day(cli, gameid=0): var.NO_LYNCH = set() for crow, target in iter(var.OBSERVED.items()): - if crow not in var.ROLES["werecrow"]: + if crow not in get_roles("werecrow"): # FIXME continue actor = users._get(crow) # FIXME user = users._get(target) # FIXME @@ -3450,7 +3412,7 @@ def transition_day(cli, gameid=0): got_bit = False bite_evt = Event("bite", { "can_bite": True, - "kill": target in var.ROLES["lycan"] or target in var.LYCANTHROPES or target in var.IMMUNIZED + "kill": user in var.ROLES["lycan"] or target in var.LYCANTHROPES or target in var.IMMUNIZED }, victims=victims, killers=killers, @@ -3516,7 +3478,7 @@ def transition_day(cli, gameid=0): for v in victims_set: if v in var.DYING: victims.append(v) - elif v.nick in var.ROLES["bodyguard"] and v.nick in angel.GUARDED and users._get(angel.GUARDED[v.nick]) in victims_set: # FIXME + elif v in var.ROLES["bodyguard"] and v.nick in angel.GUARDED and users._get(angel.GUARDED[v.nick]) in victims_set: # FIXME vappend.append(v) elif harlot.VISITED.get(v) in victims_set: vappend.append(v) @@ -3533,7 +3495,7 @@ def transition_day(cli, gameid=0): prevlen = len(vappend) for v in vappend[:]: - if v.nick in var.ROLES["bodyguard"] and users._get(angel.GUARDED.get(v.nick)) not in vappend: # FIXME + if v in var.ROLES["bodyguard"] and users._get(angel.GUARDED.get(v.nick)) not in vappend: # FIXME vappend.remove(v) victims.append(v) elif harlot.VISITED.get(v) not in vappend: @@ -3588,7 +3550,7 @@ def transition_day(cli, gameid=0): for victim in vlist: if not revt.dispatch(var, victim): continue - if (victim.nick in var.ROLES["lycan"] or victim.nick in var.LYCANTHROPES) and victim in revt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED: + if (victim in var.ROLES["lycan"] or victim.nick in var.LYCANTHROPES) and victim in revt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED: vrole = get_main_role(victim) if vrole not in var.WOLFCHAT_ROLES: revt.data["message"].append(messages["new_wolf"]) @@ -3596,7 +3558,7 @@ def transition_day(cli, gameid=0): victim.send(messages["lycan_turn"]) var.LYCAN_ROLES[victim.nick] = vrole change_role(victim, vrole, "wolf") - var.ROLES["lycan"].discard(victim.nick) # in the event lycan was a template, we want to ensure it gets purged + var.ROLES["lycan"].discard(victim) # in the event lycan was a template, we want to ensure it gets purged wolves = get_players(var.WOLFCHAT_ROLES) random.shuffle(wolves) wolves.remove(victim) # remove self from list @@ -3703,7 +3665,7 @@ def transition_day(cli, gameid=0): if guntaker.nick not in var.GUNNERS: var.GUNNERS[guntaker.nick] = 0 if guntaker not in get_all_players(("gunner", "sharpshooter")): - var.ROLES["gunner"].add(guntaker.nick) + var.ROLES["gunner"].add(guntaker) var.GUNNERS[guntaker.nick] += 1 # only transfer one bullet guntaker.send(messages["wolf_gunner"].format(victim)) except IndexError: @@ -3724,7 +3686,7 @@ def transition_day(cli, gameid=0): chump.send(messages["fallen_angel_turn"]) # fallen angels also automatically gain the assassin template if they don't already have it newrole = "fallen angel" - var.ROLES["assassin"].add(chump.nick) + var.ROLES["assassin"].add(chump) debuglog("{0} (guardian angel) TURNED FALLEN ANGEL".format(chump)) elif chumprole in ("seer", "oracle", "augur"): chump.send(messages["seer_turn"]) @@ -3797,7 +3759,7 @@ def chk_nightdone(cli): if var.ALPHA_ENABLED: # alphas both kill and bite if they're activated at night, so add them into the counts nightroles.extend(get_all_players(("alpha wolf",))) - actedcount += len([p for p in var.ALPHA_WOLVES if p in var.ROLES["alpha wolf"]]) + actedcount += len([p for p in var.ALPHA_WOLVES if p in get_roles("alpha wolf")]) # FIXME # add in turncoats who should be able to act -- if they passed they're already in var.PASSED # but if they can act they're in var.TURNCOATS where the second tuple item is the current night @@ -3825,7 +3787,7 @@ def chk_nightdone(cli): # must be handled separately because assassin only acts on nights when their target is dead # and silenced assassin shouldn't add to actedcount for ass in var.ROLES["assassin"]: - if ass not in var.TARGETED.keys() | var.SILENCED: + if ass.nick not in var.TARGETED.keys() | var.SILENCED: # FIXME return for x, t in var.TIMERS.items(): @@ -3896,7 +3858,7 @@ def lynch(cli, nick, chan, rest): if not var.SELF_LYNCH_ALLOWED: if nick == voted: - if nick in var.ROLES["fool"] | var.ROLES["jester"]: + if nick in get_roles("fool", "jester"): # FIXME cli.notice(nick, messages["no_self_lynch"]) else: cli.notice(nick, messages["save_self"]) @@ -4123,7 +4085,7 @@ def check_exchange(cli, actor, nick): random.shuffle(pl) pl.remove(actor) # remove self from list for i, player in enumerate(pl): - if player in var.ROLES["cursed villager"]: + if player in get_roles("cursed villager"): # FIXME pl[i] = player + " (cursed)" pm(cli, actor, "Players: " + ", ".join(pl)) elif nick_role == "minion": @@ -4141,7 +4103,7 @@ def check_exchange(cli, actor, nick): random.shuffle(pl) pl.remove(nick) # remove self from list for i, player in enumerate(pl): - if player in var.ROLES["cursed villager"]: + if player in get_roles("cursed villager"): # FIXME pl[i] = player + " (cursed)" pm(cli, nick, "Players: " + ", ".join(pl)) elif actor_role == "minion": @@ -4224,15 +4186,15 @@ def shoot(var, wrapper, message): var.GUNNERS[wrapper.source.nick] -= 1 rand = random.random() - if wrapper.source.nick in var.ROLES["village drunk"]: + if wrapper.source in var.ROLES["village drunk"]: chances = var.DRUNK_GUN_CHANCES - elif wrapper.source.nick in var.ROLES["sharpshooter"]: + elif wrapper.source in var.ROLES["sharpshooter"]: chances = var.SHARPSHOOTER_GUN_CHANCES else: chances = var.GUN_CHANCES # TODO: make this into an event once we split off gunner - if victim in var.ROLES["succubus"]: + if victim in get_roles("succubus"): # FIXME chances = chances[:3] + (0,) wolfvictim = victim in list_players(var.WOLF_ROLES) @@ -4255,7 +4217,7 @@ def shoot(var, wrapper, message): return elif random.random() <= chances[3]: accident = "accidentally " - if wrapper.source.nick in var.ROLES["sharpshooter"]: + if wrapper.source in var.ROLES["sharpshooter"]: accident = "" # it's an accident if the sharpshooter DOESN'T headshot :P wrapper.send(messages["gunner_victim_villager_death"].format(victim, accident)) if var.ROLE_REVEAL in ("on", "team"): @@ -4286,7 +4248,7 @@ def shoot(var, wrapper, message): def is_safe(nick, victim): # replace calls to this with targeted_command event when splitting roles from src.roles import succubus - return nick in succubus.ENTRANCED and victim in var.ROLES["succubus"] + return nick in succubus.ENTRANCED and victim in get_roles("succubus") # FIXME @cmd("bless", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",)) def bless(cli, nick, chan, rest): @@ -4308,7 +4270,7 @@ def bless(cli, nick, chan, rest): return var.PRIESTS.add(nick) - var.ROLES["blessed villager"].add(victim) + var.ROLES["blessed villager"].add(users._get(victim)) # FIXME pm(cli, nick, messages["blessed_success"].format(victim)) pm(cli, victim, messages["blessed_notify_target"]) debuglog("{0} ({1}) BLESS: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim))) @@ -4431,7 +4393,7 @@ def pray(cli, nick, chan, rest): if role in valid_roles: # this sees through amnesiac, so the amnesiac's final role counts as their role # also, if we're the only person with that role, say so and don't allow a second vision - people = set(var.ROLES[role]) | set(p for p, r in var.AMNESIAC_ROLES.items() if p in pl and r == role) + people = set(get_roles(role)) | set(p for p, r in var.AMNESIAC_ROLES.items() if p in pl and r == role) # FIXME if len(people) == 1 and nick in people: pm(cli, nick, messages["vision_only_role_self"].format(role)) var.PRAYED[nick][0] = 2 @@ -4522,13 +4484,13 @@ def immunize(cli, nick, chan, rest): lycan = False if victim in var.DISEASED: var.DISEASED.remove(victim) - if victim in var.ROLES["lycan"]: + if victim in get_roles("lycan"): # FIXME lycan = True lycan_message = (messages["lycan_cured"]) if get_role(victim) == "lycan": change_role(users._get(victim), "lycan", "villager") # FIXME else: - var.ROLES["lycan"].remove(victim) + var.ROLES["lycan"].remove(users._get(victim)) # FIXME var.CURED_LYCANS.add(victim) else: lycan_message = messages[evt.data["message"]] @@ -4779,7 +4741,7 @@ def curse(cli, nick, chan, rest): # but for now it is not allowed. If someone seems suspicious and shows as # villager across multiple nights, safes can use that as a tell that the # person is likely wolf-aligned. - if victim in var.ROLES["cursed villager"]: + if victim in get_roles("cursed villager"): # FIXME pm(cli, nick, messages["target_already_cursed"].format(victim)) return @@ -4798,7 +4760,7 @@ def curse(cli, nick, chan, rest): if not var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: wroles = var.WOLF_ROLES | {"traitor"} if vrole not in wroles: - var.ROLES["cursed villager"].add(victim) + var.ROLES["cursed villager"].add(users._get(victim)) # FIXME pm(cli, nick, messages["curse_success"].format(victim)) relay_wolfchat_command(cli, nick, messages["curse_success_wolfchat"].format(nick, victim), ("warlock",)) @@ -4942,19 +4904,20 @@ def relay(var, wrapper, message): if var.PHASE not in var.GAME_PHASES: return - pl = list_players() + pl = get_players() - if wrapper.source.nick in pl and wrapper.source.nick in getattr(var, "IDLE_WARNED_PM", ()): + # FIXME: this IDLE_WARNED_PM handling looks incredibly wrong and should be fixed + if wrapper.source in pl and wrapper.source.nick in getattr(var, "IDLE_WARNED_PM", ()): wrapper.pm(messages["privmsg_idle_warning"].format(channels.Main)) var.IDLE_WARNED_PM.add(wrapper.source) if message.startswith(botconfig.CMD_CHAR): return - badguys = list_players(var.WOLFCHAT_ROLES) - wolves = list_players(var.WOLF_ROLES) + badguys = get_players(var.WOLFCHAT_ROLES) + wolves = get_players(var.WOLF_ROLES) - if wrapper.source.nick not in pl and var.ENABLE_DEADCHAT and wrapper.source in var.DEADCHAT_PLAYERS: + if wrapper.source not in pl and var.ENABLE_DEADCHAT and wrapper.source in var.DEADCHAT_PLAYERS: to_msg = var.DEADCHAT_PLAYERS - {wrapper.source} if to_msg or var.SPECTATING_DEADCHAT: if message.startswith("\u0001ACTION"): @@ -4971,7 +4934,7 @@ def relay(var, wrapper, message): user.send_messages() - elif wrapper.source.nick in badguys and len(badguys) > 1: # FIXME: Need to fix once list_players() returns User instances + elif wrapper.source in badguys and len(badguys) > 1: # handle wolfchat toggles if not var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: wolves.extend(var.ROLES["traitor"]) @@ -4979,13 +4942,13 @@ def relay(var, wrapper, message): return elif var.PHASE == "day" and var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: return - elif wrapper.source.nick not in wolves and var.RESTRICT_WOLFCHAT & var.RW_WOLVES_ONLY_CHAT: + elif wrapper.source not in wolves and var.RESTRICT_WOLFCHAT & var.RW_WOLVES_ONLY_CHAT: return - elif wrapper.source.nick not in wolves and var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: + elif wrapper.source not in wolves and var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: return - badguys.remove(wrapper.source.nick) - to_msg = set(badguys) & var.PLAYERS.keys() + badguys.remove(wrapper.source) + to_msg = set(u.nick for u in badguys) # FIXME: replace mass_privmsg with something user-aware below if message.startswith("\u0001ACTION"): message = message[7:-1] mass_privmsg(wrapper.client, to_msg, "* \u0002{0}\u0002{1}".format(wrapper.source, message)) @@ -5063,7 +5026,7 @@ def transition_night(cli): # convert amnesiac if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS: - amns = copy.copy(var.ROLES["amnesiac"]) + amns = get_roles("amnesiac") # FIXME: not user aware, needs to eventually be a copy of var.ROLES["amnesiac"] for amn in amns: event = Event("amnesiac_turn", {}) @@ -5107,7 +5070,7 @@ def transition_night(cli): # send PMs ps = list_players() - for pht in var.ROLES["prophet"]: + for pht in get_roles("prophet"): # FIXME chance1 = math.floor(var.PROPHET_REVEALED_CHANCE[0] * 100) chance2 = math.floor(var.PROPHET_REVEALED_CHANCE[1] * 100) an1 = "n" if chance1 >= 80 and chance1 < 90 else "" @@ -5122,13 +5085,13 @@ def transition_night(cli): else: pm(cli, pht, messages["prophet_simple"]) - for drunk in var.ROLES["village drunk"]: + for drunk in get_roles("village drunk"): # FIXME if drunk in var.PLAYERS and not is_user_simple(drunk): pm(cli, drunk, messages["drunk_notification"]) else: pm(cli, drunk, messages["drunk_simple"]) - for doctor in var.ROLES["doctor"]: + for doctor in get_roles("doctor"): # FIXME if doctor in var.DOCTORS and var.DOCTORS[doctor] > 0: # has immunizations remaining pl = ps[:] random.shuffle(pl) @@ -5138,38 +5101,38 @@ def transition_night(cli): pm(cli, doctor, messages["doctor_simple"]) pm(cli, doctor, messages["doctor_immunizations"].format(var.DOCTORS[doctor], 's' if var.DOCTORS[doctor] > 1 else '')) - for fool in var.ROLES["fool"]: + for fool in get_roles("fool"): # FIXME if fool in var.PLAYERS and not is_user_simple(fool): pm(cli, fool, messages["fool_notify"]) else: pm(cli, fool, messages["fool_simple"]) - for jester in var.ROLES["jester"]: + for jester in get_roles("jester"): # FIXME if jester in var.PLAYERS and not is_user_simple(jester): pm(cli, jester, messages["jester_notify"]) else: pm(cli, jester, messages["jester_simple"]) - for monster in var.ROLES["monster"]: + for monster in get_roles("monster"): # FIXME if monster in var.PLAYERS and not is_user_simple(monster): pm(cli, monster, messages["monster_notify"]) else: pm(cli, monster, messages["monster_simple"]) - for demoniac in var.ROLES["demoniac"]: + for demoniac in get_roles("demoniac"): # FIXME if demoniac in var.PLAYERS and not is_user_simple(demoniac): pm(cli, demoniac, messages["demoniac_notify"]) else: pm(cli, demoniac, messages["demoniac_simple"]) - for lycan in var.ROLES["lycan"]: + for lycan in get_roles("lycan"): # FIXME if lycan in var.PLAYERS and not is_user_simple(lycan): pm(cli, lycan, messages["lycan_notify"]) else: pm(cli, lycan, messages["lycan_simple"]) - for ass in var.ROLES["assassin"]: + for ass in get_roles("assassin"): # FIXME if ass in var.TARGETED and var.TARGETED[ass] != None: continue # someone already targeted pl = ps[:] @@ -5189,7 +5152,7 @@ def transition_night(cli): pm(cli, ass, messages["assassin_simple"]) pm(cli, ass, "Players: " + ", ".join(pl)) - for turncoat in var.ROLES["turncoat"]: + for turncoat in get_roles("turncoat"): # FIXME # they start out as unsided, but can change n1 if turncoat not in var.TURNCOATS: var.TURNCOATS[turncoat] = ("none", -1) @@ -5204,14 +5167,14 @@ def transition_night(cli): else: pm(cli, turncoat, messages["turncoat_simple"].format(var.TURNCOATS[turncoat][0])) - for priest in var.ROLES["priest"]: + for priest in get_roles("priest"): # FIXME if priest in var.PLAYERS and not is_user_simple(priest): pm(cli, priest, messages["priest_notify"]) else: pm(cli, priest, messages["priest_simple"]) if var.FIRST_NIGHT or var.ALWAYS_PM_ROLE: - for mm in var.ROLES["matchmaker"]: + for mm in get_roles("matchmaker"): # FIXME pl = ps[:] random.shuffle(pl) if mm in var.PLAYERS and not is_user_simple(mm): @@ -5220,7 +5183,7 @@ def transition_night(cli): pm(cli, mm, messages["matchmaker_simple"]) pm(cli, mm, "Players: " + ", ".join(pl)) - for clone in var.ROLES["clone"]: + for clone in get_roles("clone"): # FIXME pl = ps[:] random.shuffle(pl) pl.remove(clone) @@ -5230,7 +5193,7 @@ def transition_night(cli): pm(cli, clone, messages["clone_simple"]) pm(cli, clone, "Players: "+", ".join(pl)) - for minion in var.ROLES["minion"]: + for minion in get_roles("minion"): # FIXME wolves = list_players(var.WOLF_ROLES) random.shuffle(wolves) if minion in var.PLAYERS and not is_user_simple(minion): @@ -5248,7 +5211,7 @@ def transition_night(cli): continue norm_notify = g in var.PLAYERS and not is_user_simple(g) role = "gunner" - if g in var.ROLES["sharpshooter"]: + if g in get_roles("sharpshooter"): # FIXME role = "sharpshooter" if norm_notify: if role == "gunner": @@ -5473,7 +5436,7 @@ def start(cli, nick, chan, forced = False, restart = ""): for decor in (COMMANDS["join"] + COMMANDS["start"]): decor(_command_disabled) - var.ROLES = {var.DEFAULT_ROLE: set()} + var.ROLES = {var.DEFAULT_ROLE: set()} # type: Dict[str, Set[users.User]] var.GUNNERS = {} var.OBSERVED = {} var.CLONED = {} @@ -5528,12 +5491,12 @@ def start(cli, nick, chan, forced = False, restart = ""): for x in selected: var.MAIN_ROLES[users._get(x)] = role # FIXME villagers.remove(x) - var.ROLES[role] = set(selected) + var.ROLES[role] = set(users._get(x) for x in selected) # FIXME fixed_count = count - roleset_roles[role] if fixed_count > 0: for pr in possible_rolesets: pr[role] += fixed_count - var.ROLES[var.DEFAULT_ROLE].update(villagers) + var.ROLES[var.DEFAULT_ROLE].update(users._get(x) for x in villagers) # FIXME for x in villagers: var.MAIN_ROLES[users._get(x)] = var.DEFAULT_ROLE # FIXME if villagers: @@ -5558,7 +5521,7 @@ def start(cli, nick, chan, forced = False, restart = ""): if len(possible) < len(var.ROLES[template]): cli.msg(chan, messages["not_enough_targets"].format(template)) if var.ORIGINAL_SETTINGS: - var.ROLES = {"person": {x.nick for x in var.ALL_PLAYERS}} + var.ROLES = {"person": set(var.ALL_PLAYERS)} reset_settings() cli.msg(chan, messages["default_reset"].format(botconfig.CMD_CHAR)) var.PHASE = "join" @@ -5568,25 +5531,24 @@ def start(cli, nick, chan, forced = False, restart = ""): var.ROLES[template] = set() continue - var.ROLES[template] = set(random.sample(possible, len(var.ROLES[template]))) + var.ROLES[template] = set(users._get(x) for x in random.sample(possible, len(var.ROLES[template]))) # FIXME # Handle gunner - cannot_be_sharpshooter = list_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"]) - gunner_list = copy.copy(var.ROLES["gunner"]) + cannot_be_sharpshooter = get_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"]) + gunner_list = set(var.ROLES["gunner"]) # make a copy since we mutate var.ROLES["gunner"] num_sharpshooters = 0 for gunner in gunner_list: if gunner in var.ROLES["village drunk"]: - var.GUNNERS[gunner] = (var.DRUNK_SHOTS_MULTIPLIER * math.ceil(var.SHOTS_MULTIPLIER * len(pl))) + var.GUNNERS[gunner.nick] = (var.DRUNK_SHOTS_MULTIPLIER * math.ceil(var.SHOTS_MULTIPLIER * len(pl))) elif num_sharpshooters < addroles["sharpshooter"] and gunner not in cannot_be_sharpshooter and random.random() <= var.SHARPSHOOTER_CHANCE: - var.GUNNERS[gunner] = math.ceil(var.SHARPSHOOTER_MULTIPLIER * len(pl)) + var.GUNNERS[gunner.nick] = math.ceil(var.SHARPSHOOTER_MULTIPLIER * len(pl)) var.ROLES["gunner"].remove(gunner) var.ROLES["sharpshooter"].append(gunner) num_sharpshooters += 1 else: - var.GUNNERS[gunner] = math.ceil(var.SHOTS_MULTIPLIER * len(pl)) + var.GUNNERS[gunner.nick] = math.ceil(var.SHOTS_MULTIPLIER * len(pl)) var.ROLES["sharpshooter"] = set(var.ROLES["sharpshooter"]) - var.ROLES["sharpshooter"].discard(None) with var.WARNING_LOCK: # cancel timers @@ -5657,11 +5619,11 @@ def start(cli, nick, chan, forced = False, restart = ""): for nope in var.TEMPLATE_RESTRICTIONS.keys(): amnroles.discard(nope) for amnesiac in var.ROLES["amnesiac"]: - var.AMNESIAC_ROLES[amnesiac] = random.choice(list(amnroles)) + var.AMNESIAC_ROLES[amnesiac.nick] = random.choice(list(amnroles)) # FIXME # Handle doctor for doctor in var.ROLES["doctor"]: - var.DOCTORS[doctor] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(pl)) + var.DOCTORS[doctor.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(pl)) # FIXME for amn in var.AMNESIAC_ROLES: if var.AMNESIAC_ROLES[amn] == "doctor": var.DOCTORS[amn] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(pl)) @@ -5675,9 +5637,9 @@ def start(cli, nick, chan, forced = False, restart = ""): var.PLAYERS = {plr:dict(var.USERS[plr]) for plr in pl if plr in var.USERS} - debuglog("ROLES:", " | ".join("{0}: {1}".format(role, ", ".join(players)) + debuglog("ROLES:", " | ".join("{0}: {1}".format(role, ", ".join(p.nick for p in players)) for role, players in sorted(var.ROLES.items()) if players and role not in var.TEMPLATE_RESTRICTIONS.keys())) - templates = " | ".join("{0}: {1}".format(tmplt, ", ".join(players)) + templates = " | ".join("{0}: {1}".format(tmplt, ", ".join(p.nick for p in players)) for tmplt, players in sorted(var.ROLES.items()) if players and tmplt in var.TEMPLATE_RESTRICTIONS.keys()) if not templates: templates = "None" @@ -6337,7 +6299,7 @@ def myrole(var, wrapper, message): # FIXME: Need to fix !swap once this gets con wolves = [] for wolfrole in var.WOLF_ROLES: for player in var.ORIGINAL_ROLES[wolfrole]: - wolves.append(player) + wolves.append(player.nick) wrapper.pm(messages["original_wolves"] + ", ".join(wolves)) # Remind turncoats of their side @@ -6345,18 +6307,18 @@ def myrole(var, wrapper, message): # FIXME: Need to fix !swap once this gets con wrapper.pm(messages["turncoat_side"].format(var.TURNCOATS.get(wrapper.source.nick, "none")[0])) # Check for gun/bullets - if wrapper.source.nick not in var.ROLES["amnesiac"] and wrapper.source.nick in var.GUNNERS and var.GUNNERS[wrapper.source.nick]: + if wrapper.source not in var.ROLES["amnesiac"] and wrapper.source.nick in var.GUNNERS and var.GUNNERS[wrapper.source.nick]: role = "gunner" - if wrapper.source.nick in var.ROLES["sharpshooter"]: + if wrapper.source in var.ROLES["sharpshooter"]: role = "sharpshooter" wrapper.pm(messages["gunner_simple"].format(role, var.GUNNERS[wrapper.source.nick], "" if var.GUNNERS[wrapper.source.nick] == 1 else "s")) # Check assassin - if wrapper.source.nick in var.ROLES["assassin"] and wrapper.source.nick not in var.ROLES["amnesiac"]: + if wrapper.source in var.ROLES["assassin"] and wrapper.source not in var.ROLES["amnesiac"]: wrapper.pm(messages["assassin_role_info"].format(messages["assassin_targeting"].format(var.TARGETED[wrapper.source.nick]) if wrapper.source.nick in var.TARGETED else "")) # Remind prophet of their role, in sleepy mode only where it is hacked into a template instead of a role - if "prophet" in var.TEMPLATE_RESTRICTIONS and wrapper.source.nick in var.ROLES["prophet"]: + if "prophet" in var.TEMPLATE_RESTRICTIONS and wrapper.source in var.ROLES["prophet"]: wrapper.pm(messages["prophet_simple"]) # Remind lovers of each other @@ -6825,7 +6787,7 @@ def revealroles(var, wrapper, message): for role in role_order(): if var.ROLES.get(role): # make a copy since this list is modified - nicks = list(var.ROLES[role]) + nicks = [p.nick for p in var.ROLES[role]] # FIXME: convert to users # go through each nickname, adding extra info if necessary for i in range(len(nicks)): special_case = [] @@ -6847,9 +6809,10 @@ def revealroles(var, wrapper, message): evt.dispatch(var, wrapper, nickname, role) special_case = evt.data["special_case"] - if not evt.prevent_default and nickname not in var.ORIGINAL_ROLES[role] and role not in var.TEMPLATE_RESTRICTIONS: + user = users._get(nickname) # FIXME + if not evt.prevent_default and user not in var.ORIGINAL_ROLES[role] and role not in var.TEMPLATE_RESTRICTIONS: for old_role in role_order(): # order doesn't matter here, but oh well - if nickname in var.ORIGINAL_ROLES[old_role] and nickname not in var.ROLES[old_role]: + if user in var.ORIGINAL_ROLES[old_role] and user not in var.ROLES[old_role]: special_case.append("was {0}".format(old_role)) break if special_case: @@ -7018,7 +6981,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: cli.msg(chan, nick+": invalid role") return elif who == "gunner": - tgt = list(var.GUNNERS.keys()) + tgt = {users._get(g) for g in var.GUNNERS.keys()} # FIXME else: tgt = var.ROLES[who].copy() @@ -7032,10 +6995,11 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: cli.notice(nick, messages["admin_only_force"]) continue for user in tgt: + # FIXME: old command API if fn.chan: - fn.caller(cli, user, chan, " ".join(rst)) + fn.caller(cli, user.nick, chan, " ".join(rst)) else: - fn.caller(cli, user, users.Bot.nick, " ".join(rst)) + fn.caller(cli, user.nick, users.Bot.nick, " ".join(rst)) cli.msg(chan, messages["operation_successful"]) else: cli.msg(chan, messages["command_not_found"]) @@ -7069,7 +7033,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: addrem = rol[0] rol = rol[1:] is_gunner = (rol == "gunner" or rol == "sharpshooter") - if addrem == "+" and who not in var.ROLES[rol]: + if addrem == "+" and who not in get_roles(rol): # FIXME if is_gunner: if len(rolargs) == 2 and rolargs[1].isdigit(): if len(rolargs[1]) < 7: @@ -7081,18 +7045,18 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: else: var.GUNNERS[who] = math.ceil(var.SHARPSHOOTER_MULTIPLIER * len(pl)) if who not in pl: - var.ROLES[var.DEFAULT_ROLE].add(who) + var.ROLES[var.DEFAULT_ROLE].add(users._get(who)) # FIXME var.MAIN_ROLES[users._get(who)] = var.DEFAULT_ROLE # FIXME var.ALL_PLAYERS.append(users._get(who)) # FIXME if not is_fake_nick(who): cli.mode(chan, "+v", who) cli.msg(chan, messages["template_default_role"].format(var.DEFAULT_ROLE)) - var.ROLES[rol].add(who) + var.ROLES[rol].add(users._get(who)) # FIXME evt = Event("frole_template", {}) evt.dispatch(cli, var, addrem, who, rol, rolargs) - elif addrem == "-" and who in var.ROLES[rol] and get_role(who) != rol: - var.ROLES[rol].remove(who) + elif addrem == "-" and who in get_roles(rol) and get_role(who) != rol: + var.ROLES[rol].remove(users._get(who)) # FIXME evt = Event("frole_template", {}) evt.dispatch(cli, var, addrem, who, rol, rolargs) if is_gunner and who in var.GUNNERS: @@ -7110,9 +7074,9 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: change_role(users._get(who), oldrole, rol) # FIXME else: var.ALL_PLAYERS.append(users._get(who)) # FIXME - var.ROLES[rol].add(who) + var.ROLES[rol].add(users._get(who)) # FIXME var.MAIN_ROLES[users._get(who)] = rol # FIXME - var.ORIGINAL_ROLES[rol].add(who) + var.ORIGINAL_ROLES[rol].add(users._get(who)) # FIXME evt = Event("frole_role", {}) evt.dispatch(cli, var, who, rol, oldrole, rolargs) if not is_fake_nick(who):