diff --git a/roles/__init__.py.example b/roles/__init__.py.example index 3a3f55c..4a70b1a 100644 --- a/roles/__init__.py.example +++ b/roles/__init__.py.example @@ -15,6 +15,12 @@ for f in glob.iglob(search): n, _ = os.path.splitext(f) if f == "__init__.py": continue - importlib.import_module(n, package="roles") + importlib.import_module("." + n, package="roles") + +# Important: if this isn't defined, built-in roles will +# be imported. Normally this isn't an issue, but if you +# are attempting to suppress the import of built-in roles +# then that might be an issue for you. +CUSTOM_ROLES_DEFINED = True # vim: set sw=4 expandtab: diff --git a/src/__init__.py b/src/__init__.py index a7e0df7..5e8882f 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -21,7 +21,8 @@ except ImportError: try: import roles -except ImportError: + roles.CUSTOM_ROLES_DEFINED +except (ImportError, AttributeError): import src.roles # Handle launch parameters diff --git a/src/decorators.py b/src/decorators.py index 55a93b8..b80cdd8 100644 --- a/src/decorators.py +++ b/src/decorators.py @@ -256,6 +256,7 @@ class event_listener: def __call__(self, *args, **kwargs): if self.func is None: + func = args[0] if isinstance(func, event_listener): func = func.func self.func = handle_error(func) diff --git a/src/roles/__init__.py b/src/roles/__init__.py index db58322..f898c77 100644 --- a/src/roles/__init__.py +++ b/src/roles/__init__.py @@ -11,6 +11,6 @@ for f in glob.iglob(search): n, _ = os.path.splitext(f) if f == "__init__.py": continue - importlib.import_module(n, package="src.roles") + importlib.import_module("." + n, package="src.roles") # vim: set sw=4 expandtab: diff --git a/src/roles/seer.py b/src/roles/seer.py index b60fe24..d3b6d70 100644 --- a/src/roles/seer.py +++ b/src/roles/seer.py @@ -1,4 +1,5 @@ import re +import random import src.settings as var from src.utilities import * @@ -25,10 +26,10 @@ def see(cli, nick, chan, rest): return evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "see", nick, victim, frozenset("info", "immediate")) + evt.dispatch(cli, var, "see", nick, victim, frozenset({"info", "immediate"})) if evt.prevent_default: return - victim = evt.data["victim"] + victim = evt.data["target"] victimrole = get_role(victim) evt = Event("see", {"role": victimrole}) @@ -121,10 +122,12 @@ def on_transition_night_end(evt, cli, var): @event_listener("begin_day") def on_begin_day(evt, cli, var): + global SEEN SEEN = set() @event_listener("reset") def on_reset(evt, var): + global SEEN SEEN = set() # vim: set sw=4 expandtab: diff --git a/src/roles/wildchild.py b/src/roles/wildchild.py index 92f2a07..fe229fb 100644 --- a/src/roles/wildchild.py +++ b/src/roles/wildchild.py @@ -1,3 +1,5 @@ +import random + import src.settings as var from src.utilities import * from src import debuglog, errlog, plog @@ -135,8 +137,14 @@ def on_revealroles_role(evt, cli, var, nick, role): else: evt.data["special_case"].append("no idol picked yet") +@event_listener("get_reveal_role") +def on_get_reveal_role(evt, var, nick): + if nick in WILD_CHILDREN: + evt.data["role"] = "wild child" + @event_listener("reset") def on_reset(evt, var): + global WILD_CHILDREN, IDOLS WILD_CHILDREN = set() IDOLS = {} diff --git a/src/utilities.py b/src/utilities.py index 8705bdf..82ba50d 100644 --- a/src/utilities.py +++ b/src/utilities.py @@ -1,9 +1,11 @@ import re import fnmatch +import itertools import botconfig import src.settings as var from src import proxy, debuglog +from src.events import Event # message either privmsg or notice, depending on user settings def pm(cli, target, message): @@ -319,6 +321,13 @@ def get_role(p): if p in pl: return role +def get_roles(*roles): + all_roles = [] + for role in roles: + all_roles.append(var.ROLES[role]) + return list(itertools.chain(*all_roles)) + + def get_reveal_role(nick): if var.HIDDEN_TRAITOR and get_role(nick) == "traitor": role = var.DEFAULT_ROLE @@ -326,11 +335,13 @@ def get_reveal_role(nick): role = "amnesiac" elif var.HIDDEN_CLONE and nick in var.ORIGINAL_ROLES["clone"]: role = "clone" - elif nick in var.WILD_CHILDREN: - role = "wild child" else: role = get_role(nick) + evt = Event("get_reveal_role", {"role": role}) + evt.dispatch(var, nick) + role = evt.data["role"] + if var.ROLE_REVEAL != "team": return role @@ -370,5 +381,53 @@ def break_long_message(phrases, joinstr = " "): message.append(phrase) return joinstr.join(message) +#completes a partial nickname or string from a list +def complete_match(string, matches): + num_matches = 0 + bestmatch = string + for possible in matches: + if string == possible: + return string, 1 + if possible.startswith(string) or possible.lstrip("[{\\^_`|}]").startswith(string): + bestmatch = possible + num_matches += 1 + if num_matches != 1: + return None, num_matches + else: + return bestmatch, 1 + +#wrapper around complete_match() used for roles +def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False): + chan = botconfig.CHANNEL if in_chan else nick + if not victim: + reply(cli, nick, chan, messages["not_enough_parameters"], private=True) + return + pl = [x for x in list_players() if x != nick or self_in_list] + pll = [x.lower() for x in pl] + + if bot_in_list: # for villagergame + pl.append(botconfig.NICK) + pll.append(botconfig.NICK.lower()) + + tempvictim, num_matches = complete_match(victim.lower(), pll) + if not tempvictim: + #ensure messages about not being able to act on yourself work + if num_matches == 0 and nick.lower().startswith(victim.lower()): + return nick + reply(cli, nick, chan, messages["not_playing"].format(victim), private=True) + return + return pl[pll.index(tempvictim)] #convert back to normal casing + +# wrapper around complete_match() used for any nick on the channel +def get_nick(cli, nick): + ul = [x for x in var.USERS] + ull = [x.lower() for x in var.USERS] + lnick, num_matches = complete_match(nick.lower(), ull) + if not lnick: + return None + return ul[ull.index(lnick)] + + class InvalidModeException(Exception): pass + # vim: set sw=4 expandtab: diff --git a/src/wolfgame.py b/src/wolfgame.py index cf71536..30b65a8 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -310,58 +310,6 @@ def check_for_modes(cli, rnick, chan, modeaction, *target): if "!" not in rnick: sync_modes(cli) -#completes a partial nickname or string from a list -def complete_match(string, matches): - num_matches = 0 - bestmatch = string - for possible in matches: - if string == possible: - return string, 1 - if possible.startswith(string) or possible.lstrip("[{\\^_`|}]").startswith(string): - bestmatch = possible - num_matches += 1 - if num_matches != 1: - return None, num_matches - else: - return bestmatch, 1 - -#wrapper around complete_match() used for roles -def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False): - chan = botconfig.CHANNEL if in_chan else nick - if not victim: - reply(cli, nick, chan, messages["not_enough_parameters"], private=True) - return - pl = [x for x in list_players() if x != nick or self_in_list] - pll = [x.lower() for x in pl] - - if bot_in_list: # for villagergame - pl.append(botconfig.NICK) - pll.append(botconfig.NICK.lower()) - - tempvictim, num_matches = complete_match(victim.lower(), pll) - if not tempvictim: - #ensure messages about not being able to act on yourself work - if num_matches == 0 and nick.lower().startswith(victim.lower()): - return nick - reply(cli, nick, chan, messages["not_playing"].format(victim), private=True) - return - return pl[pll.index(tempvictim)] #convert back to normal casing - -# wrapper around complete_match() used for any nick on the channel -def get_nick(cli, nick): - ul = [x for x in var.USERS] - ull = [x.lower() for x in var.USERS] - lnick, num_matches = complete_match(nick.lower(), ull) - if not lnick: - return None - return ul[ull.index(lnick)] - -def get_roles(*roles): - all_roles = [] - for role in roles: - all_roles.append(var.ROLES[role]) - return list(itertools.chain(*all_roles)) - def reset_settings(): var.CURRENT_GAMEMODE.teardown() var.CURRENT_GAMEMODE = var.GAME_MODES["default"][0]()