General cleanup

- Expand skel.py to be more useful
- Remove circular dependency from utilities.py. It *CANNOT* globally
  import users.
- Remove unused functions from utilities.py and make some others proxy
  through to user-aware functions to ensure functionality stays the
  same.
- Remove duplicate event listener.
- Clarify some comments about stats.
This commit is contained in:
skizzerz 2017-12-29 16:10:32 -06:00
parent 15e0d9f503
commit b677400ce4
5 changed files with 78 additions and 38 deletions

View File

@ -12,7 +12,7 @@ import botconfig
import src.settings as var import src.settings as var
from src import decorators, wolfgame, events, channels, hooks, users, errlog as log, stream_handler as alog from src import decorators, wolfgame, events, channels, hooks, users, errlog as log, stream_handler as alog
from src.messages import messages from src.messages import messages
from src.utilities import reply, get_role, get_templates from src.utilities import reply
from src.functions import get_participants, get_all_roles from src.functions import get_participants, get_all_roles
from src.dispatcher import MessageDispatcher from src.dispatcher import MessageDispatcher
from src.decorators import handle_error from src.decorators import handle_error

View File

@ -154,11 +154,6 @@ def on_transition_day_begin(evt, var):
CHARMED.update(tocharm) CHARMED.update(tocharm)
TOBECHARMED.clear() TOBECHARMED.clear()
@event_listener("night_acted")
def on_night_acted(evt, var, target, actor):
if target in TOBECHARMED:
evt.data["acted"] = True
@event_listener("chk_nightdone") @event_listener("chk_nightdone")
def on_chk_nightdone(evt, var): def on_chk_nightdone(evt, var):
evt.data["actedcount"] += len(TOBECHARMED.keys()) evt.data["actedcount"] += len(TOBECHARMED.keys())

View File

@ -12,6 +12,67 @@ from src.decorators import command, event_listener
from src.messages import messages from src.messages import messages
from src.events import Event from src.events import Event
# Skeleton file for new roles, basically to get all the imports right and stuff # Skeleton file for new roles. Not all events are represented, only the most common ones.
# Add to evt.data["actedcount"] and evt.data["nightroles"] if this role can act during night
# nightroles lists all Users who have this role and are capable of acting tonight
# actedcount should be added to (via +=) with everyone who has this role and has already acted
# Used to determine when all roles have acted (and therefore night should end)
@event_listener("chk_nightdone")
def on_chk_nightdone(evt, var):
pass
# Set evt.data["acted"] = True if target acted during night and spy is able to know that info
# Used for werecrow and insomniac
@event_listener("night_acted")
def on_night_acted(evt, var, target, spy):
pass
# PM players who have this role with instructions
# Set priority=2 if this is a main role, and priority=5 if this is a secondary role
# (secondary roles are like gunner, assassin, etc. which by default stack on top of main roles)
@event_listener("transition_night_end", priority=2)
def on_transition_night_end(evt, var):
pass
# Update any role state that happens when someone with this role exchanges with someone else.
@event_listener("exchange_roles")
def on_exchange(evt, var, actor, target, actor_role, target_role):
pass
# Update evt.data["special"] with the Users who have this role as their main role,
# assuming this is some sort of special role (can act). Do *not* update this if this is a wolfteam
# special role, simply remove the event instead.
# Used by wolf mystic to determine the number of special villagers still alive.
@event_listener("get_special")
def on_get_special(evt, var):
pass
# Update any game state which happens when player dies. If this role does things upon death,
# ensure that you check death_triggers (it's a bool) before firing it.
@event_listener("del_player")
def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
pass
# Clear all game state. Called whenever the game ends.
@event_listener("reset")
def on_reset(evt, var):
pass
# Swap out a user with a different one. Update all game state to use the new User.
@event_listener("swap_player")
def on_swap_player(evt, var, old, new):
pass
# Gets metadata about this role; kind will be a str with one of the following values:
# night_kills: Add metadata about any deaths this role can cause at night which use the standard
# death message (i.e. do not have a custom death message). Set the data as follows:
# evt.data["rolename"] = N (where N is the max # of deaths that this role can cause)
# Used in !stats in order to handle interactions between roles in a generic fashion so that
# more accurate results can be reported.
@event_listener("get_role_metadata")
def on_get_role_metadata(evt, var, kind):
pass
# vim: set sw=4 expandtab: # vim: set sw=4 expandtab:

View File

@ -34,13 +34,18 @@ def on_update_stats1(evt, var, player, mainrole, revealroles, allroles):
evt.data["possible"].add("traitor") evt.data["possible"].add("traitor")
@event_listener("update_stats", priority=3) @event_listener("update_stats", priority=3)
def on_update_stats3(evt, var, player, mainrole, revealroles, allroles): def on_update_stats3(evt, var, player, mainrole, revealrole, allroles):
# if this is a night death and we know for sure that wolves (and only wolves) # if this is a night death and we know for sure that wolves (and only wolves)
# killed, then that kill cannot be traitor as long as they're in wolfchat. # killed, then that kill cannot be traitor as long as they're in wolfchat.
# ismain True = night death, False = chain death; chain deaths can be traitors # ismain True = night death, False = chain death; chain deaths can be traitors
# even if only wolves killed, so we short-circuit there as well # even if only wolves killed, so we short-circuit there as well
# TODO: an observant user will be able to determine if traitor dies due to luck/misdirection totem # TODO: luck/misdirection totem can leak info due to our short-circuit below this comment.
# redirecting a wolf kill onto traitor # If traitor dies due to one of these totems, both traitor count and villager count is reduced by
# 1. If traitor does not die, and no other roles can kill (no death totems), then traitor count is unchanged
# and villager count is reduced by 1. We should make it so that both counts are reduced when
# luck/misdirection are potentially in play.
# FIXME: this doesn't check RESTRICT_WOLFCHAT to see if traitor was removed from wolfchat. If
# they've been removed, they can be killed like normal so all this logic is meaningless.
if "traitor" not in evt.data["possible"] or not evt.params.ismain or mainrole == "traitor": if "traitor" not in evt.data["possible"] or not evt.params.ismain or mainrole == "traitor":
return return
if var.PHASE == "day" and var.GAMEPHASE == "night": if var.PHASE == "day" and var.GAMEPHASE == "night":

View File

@ -4,17 +4,17 @@ import re
import botconfig import botconfig
import src.settings as var import src.settings as var
from src import proxy, debuglog, users from src import proxy, debuglog
from src.events import Event from src.events import Event
from src.messages import messages from src.messages import messages
__all__ = ["pm", "is_fake_nick", "mass_mode", "mass_privmsg", "reply", __all__ = ["pm", "is_fake_nick", "mass_mode", "mass_privmsg", "reply",
"is_user_simple", "is_user_notice", "in_wolflist", "is_user_simple", "is_user_notice", "in_wolflist",
"relay_wolfchat_command", "chk_nightdone", "chk_decision", "relay_wolfchat_command", "chk_nightdone", "chk_decision",
"chk_win", "irc_lower", "irc_equals", "is_role", "match_hostmask", "chk_win", "irc_lower", "irc_equals", "match_hostmask",
"is_owner", "is_admin", "plural", "singular", "list_players", "is_owner", "is_admin", "plural", "singular", "list_players",
"list_players_and_roles", "get_role", "get_roles", "list_players_and_roles", "get_role", "get_roles",
"get_reveal_role", "get_templates", "change_role", "role_order", "break_long_message", "get_reveal_role", "change_role", "role_order", "break_long_message",
"complete_match","complete_one_match", "get_victim", "get_nick", "InvalidModeException"] "complete_match","complete_one_match", "get_victim", "get_nick", "InvalidModeException"]
# message either privmsg or notice, depending on user settings # message either privmsg or notice, depending on user settings
def pm(cli, target, message): def pm(cli, target, message):
@ -211,8 +211,6 @@ def irc_lower(nick):
def irc_equals(nick1, nick2): def irc_equals(nick1, nick2):
return irc_lower(nick1) == irc_lower(nick2) return irc_lower(nick1) == irc_lower(nick2)
is_role = lambda plyr, rol: rol in var.ROLES and users._get(plyr) in var.ROLES[rol]
def match_hostmask(hostmask, nick, ident, host): def match_hostmask(hostmask, nick, ident, host):
# support n!u@h, u@h, or just h by itself # support n!u@h, u@h, or just h by itself
matches = re.match('(?:(?:(.*?)!)?(.*?)@)?(.*)', hostmask) matches = re.match('(?:(?:(.*?)!)?(.*?)@)?(.*)', hostmask)
@ -322,21 +320,10 @@ def list_players_and_roles():
return {u.nick: r for u, r in var.MAIN_ROLES.items()} return {u.nick: r for u, r in var.MAIN_ROLES.items()}
def get_role(p): def get_role(p):
# FIXME: make the arg a user instead of a nick # TODO DEPRECATED: replace with get_main_role(user)
from src import users from src import users
from src.functions import get_participants from src.functions import get_main_role
user = users._get(p) return get_main_role(users._get(p))
role = var.MAIN_ROLES.get(user, None)
if role is not None:
return role
# not found in player list, see if they're a special participant
if user in get_participants():
evt = Event("get_participant_role", {"role": None})
evt.dispatch(var, user)
role = evt.data["role"]
if role is None:
raise ValueError("User {0} isn't playing and has no defined participant role".format(user))
return role
def get_roles(*roles, rolemap=None): def get_roles(*roles, rolemap=None):
if rolemap is None: if rolemap is None:
@ -370,15 +357,6 @@ def get_reveal_role(nick):
else: else:
return "village member" return "village member"
def get_templates(nick):
mainrole = get_role(nick)
tpl = []
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 # TODO: move this to functions.py
def change_role(user, oldrole, newrole, set_final=True): def change_role(user, oldrole, newrole, set_final=True):
var.ROLES[oldrole].remove(user) var.ROLES[oldrole].remove(user)
@ -425,6 +403,7 @@ def complete_one_match(string, matches):
#wrapper around complete_match() used for roles #wrapper around complete_match() used for roles
def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False): def get_victim(cli, nick, victim, in_chan, self_in_list=False, bot_in_list=False):
from src import users
chan = botconfig.CHANNEL if in_chan else nick chan = botconfig.CHANNEL if in_chan else nick
if not victim: if not victim:
reply(cli, nick, chan, messages["not_enough_parameters"], private=True) reply(cli, nick, chan, messages["not_enough_parameters"], private=True)