Add the new User containers (#316)
- Add the new User containers for easier handling of users throughout the codebase - Remove the swap_player event (replaced by User.swap, made possible thanks to the containers) - Remove the cli argument from several events - Remove !frole (a replacement will follow) - Remove the ALLOWED_NORMAL_MODE_COMMANDS config option Plus a couple of small fixes here and there.
This commit is contained in:
parent
c121c0f08f
commit
28f26e181b
@ -41,7 +41,6 @@ OWNERS_ACCOUNTS = ("1owner_acc",)
|
|||||||
|
|
||||||
#RULES = "https://werewolf.chat/Freenode:Rules"
|
#RULES = "https://werewolf.chat/Freenode:Rules"
|
||||||
|
|
||||||
ALLOWED_NORMAL_MODE_COMMANDS = [] # Debug mode commands to be allowed in normal mode
|
|
||||||
OWNERS_ONLY_COMMANDS = [] # Commands that should only be allowed for owners, regardless of their original permissions
|
OWNERS_ONLY_COMMANDS = [] # Commands that should only be allowed for owners, regardless of their original permissions
|
||||||
|
|
||||||
DISABLE_DEBUG_MODE_REAPER = True
|
DISABLE_DEBUG_MODE_REAPER = True
|
||||||
|
@ -621,11 +621,6 @@
|
|||||||
"invalid_target": "This can only be done on players in the channel or fake nicks.",
|
"invalid_target": "This can only be done on players in the channel or fake nicks.",
|
||||||
"admin_only_force": "Only full admins can force an admin-only command.",
|
"admin_only_force": "Only full admins can force an admin-only command.",
|
||||||
"operation_successful": "Operation successful.",
|
"operation_successful": "Operation successful.",
|
||||||
"template_default_role": "Added default role ({0}) because only a template was specified for a new player.",
|
|
||||||
"improper_template_mod": "Improper template modification.",
|
|
||||||
"template_mod_syntax": "Please specify \u0002+{0}\u0002 or \u0002-{0}\u0002 to add/remove this template.",
|
|
||||||
"invalid_role": "Not a valid role.",
|
|
||||||
"stats_accurate": "{0}stats type changed to accurate due to use of {0}frole.",
|
|
||||||
"not_owner": "You are not the owner.",
|
"not_owner": "You are not the owner.",
|
||||||
"invalid_permissions": "You do not have permission to use that command.",
|
"invalid_permissions": "You do not have permission to use that command.",
|
||||||
"player_joined_deadchat": "\u0002{0}\u0002 has joined the deadchat.",
|
"player_joined_deadchat": "\u0002{0}\u0002 has joined the deadchat.",
|
||||||
|
341
src/containers.py
Normal file
341
src/containers.py
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
from src.users import User
|
||||||
|
|
||||||
|
__all__ = ["UserList", "UserSet", "UserDict"]
|
||||||
|
|
||||||
|
""" * Important *
|
||||||
|
|
||||||
|
The containers present here should always follow these rules:
|
||||||
|
|
||||||
|
- Once a global variable has been set to one of the containers, it *must not* be overwritten;
|
||||||
|
|
||||||
|
- The proper way to empty a container is with the 'container.clear()' method. The 'UserDict.clear' method
|
||||||
|
also takes care of calling the '.clear()' method of nested containers (if any), so you needn't do that;
|
||||||
|
|
||||||
|
- If any local variable points to a container, the 'container.clear()' method
|
||||||
|
*must* be called before the variable goes out of scope;
|
||||||
|
|
||||||
|
- Copying a container for mutation purpose in a local context should make use of context managers,
|
||||||
|
e.g. 'with copy.deepcopy(var.ROLES) as rolelist:' instead of 'rolelist = copy.deepcopy(var.ROLES)',
|
||||||
|
with all operations on 'rolelist' being done inside the block. Once the 'with' block is exited (be it
|
||||||
|
through exceptions or normal execution), the copied contained ('rolelist' in this case) is automatically cleared.
|
||||||
|
|
||||||
|
- If fetching a container from a 'UserDict' with the intent to keep it around separate from the dictionary,
|
||||||
|
a copy is advised, as 'UserDict.clear' is recursive and will clear all nested containers, even if they
|
||||||
|
are being used outside (as the function has no way to know).
|
||||||
|
|
||||||
|
Role files should use User containers as their global variables without ever overwriting them. It is advised to
|
||||||
|
pay close attention to where the variables get touched, to keep the above rules enforced. Refer to existing role
|
||||||
|
files to get an idea of how those containers should be used.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
class UserList(list):
|
||||||
|
def __init__(self, iterable=()):
|
||||||
|
super().__init__()
|
||||||
|
try:
|
||||||
|
for item in iterable:
|
||||||
|
self.append(item)
|
||||||
|
except:
|
||||||
|
self.clear()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, tb):
|
||||||
|
self.clear()
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if not isinstance(other, list):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self.extend(other)
|
||||||
|
|
||||||
|
def __setitem__(self, index, value):
|
||||||
|
if not isinstance(value, User):
|
||||||
|
raise TypeError("UserList may only contain User instances")
|
||||||
|
|
||||||
|
item = self[index]
|
||||||
|
super().__setitem__(index, value)
|
||||||
|
if item not in self:
|
||||||
|
item.lists.remove(self)
|
||||||
|
|
||||||
|
if self not in value.lists:
|
||||||
|
value.lists.append(self)
|
||||||
|
|
||||||
|
def __delitem__(self, index):
|
||||||
|
item = self[index]
|
||||||
|
|
||||||
|
super().__delitem__(index)
|
||||||
|
|
||||||
|
if item not in self: # there may have been multiple instances
|
||||||
|
item.lists.remove(self)
|
||||||
|
|
||||||
|
def append(self, item):
|
||||||
|
if not isinstance(item, User):
|
||||||
|
raise TypeError("UserList may only contain User instances")
|
||||||
|
|
||||||
|
if self not in item.lists:
|
||||||
|
item.lists.append(self)
|
||||||
|
|
||||||
|
super().append(item)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
for item in self:
|
||||||
|
if self in item.lists:
|
||||||
|
item.lists.remove(self)
|
||||||
|
|
||||||
|
super().clear()
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return type(self)(self)
|
||||||
|
|
||||||
|
def extend(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
self.append(item)
|
||||||
|
|
||||||
|
def insert(self, index, item):
|
||||||
|
if not isinstance(item, User):
|
||||||
|
raise TypeError("UserList may only contain User instances")
|
||||||
|
|
||||||
|
super().insert(index, item)
|
||||||
|
|
||||||
|
# If it didn't work, we don't get here
|
||||||
|
|
||||||
|
if self not in item.lists:
|
||||||
|
item.lists.append(self)
|
||||||
|
|
||||||
|
def pop(self, index=-1):
|
||||||
|
item = super().pop(index)
|
||||||
|
|
||||||
|
if item not in self:
|
||||||
|
item.lists.remove(self)
|
||||||
|
|
||||||
|
return item
|
||||||
|
|
||||||
|
def remove(self, item):
|
||||||
|
super().remove(item)
|
||||||
|
|
||||||
|
if item not in self:
|
||||||
|
item.lists.remove(self)
|
||||||
|
|
||||||
|
class UserSet(set):
|
||||||
|
def __init__(self, iterable=()):
|
||||||
|
super().__init__()
|
||||||
|
try:
|
||||||
|
for item in iterable:
|
||||||
|
self.add(item)
|
||||||
|
except:
|
||||||
|
self.clear()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, tb):
|
||||||
|
self.clear()
|
||||||
|
|
||||||
|
# Comparing UserSet instances for equality doesn't make much sense in our context
|
||||||
|
# However, if there are identical instances in a list, we only want to remove ourselves
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self is other
|
||||||
|
|
||||||
|
# Operators are not overloaded - 'user_set & other_set' will return a regular set
|
||||||
|
# This is a deliberate design decision. To get a UserSet out of them, use the named ones
|
||||||
|
|
||||||
|
# Augmented assignment method overrides
|
||||||
|
|
||||||
|
def __iand__(self, other):
|
||||||
|
res = super().__iand__(other)
|
||||||
|
if not isinstance(other, set):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self.intersection_update(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ior__(self, other):
|
||||||
|
if not isinstance(other, set):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self.update(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __isub__(self, other):
|
||||||
|
if not isinstance(other, set):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self.difference_update(other)
|
||||||
|
return
|
||||||
|
|
||||||
|
def __ixor__(self, other):
|
||||||
|
if not isinstance(other, set):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
self.symmetric_difference_update(other)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add(self, item):
|
||||||
|
if item not in self:
|
||||||
|
if not isinstance(item, User):
|
||||||
|
raise TypeError("UserSet may only contain User instances")
|
||||||
|
|
||||||
|
item.sets.append(self)
|
||||||
|
super().add(item)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
for item in self:
|
||||||
|
item.sets.remove(self)
|
||||||
|
|
||||||
|
super().clear()
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return type(self)(self)
|
||||||
|
|
||||||
|
def difference(self, iterable):
|
||||||
|
return type(self)(super().difference(iterable))
|
||||||
|
|
||||||
|
def difference_update(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
if item in self:
|
||||||
|
self.remove(item)
|
||||||
|
|
||||||
|
def discard(self, item):
|
||||||
|
if item in self:
|
||||||
|
item.sets.remove(self)
|
||||||
|
|
||||||
|
super().discard(item)
|
||||||
|
|
||||||
|
def intersection(self, iterable):
|
||||||
|
return type(self)(super().intersection(iterable))
|
||||||
|
|
||||||
|
def intersection_update(self, iterable):
|
||||||
|
for item in set(self):
|
||||||
|
if item not in iterable:
|
||||||
|
self.remove(item)
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
item = super().pop()
|
||||||
|
item.sets.remove(self)
|
||||||
|
return item
|
||||||
|
|
||||||
|
def remove(self, item):
|
||||||
|
super().remove(item)
|
||||||
|
|
||||||
|
item.sets.remove(self)
|
||||||
|
|
||||||
|
def symmetric_difference(self, iterable):
|
||||||
|
return type(self)(super().symmetric_difference(iterable))
|
||||||
|
|
||||||
|
def symmetric_difference_update(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
if item in self:
|
||||||
|
self.remove(item)
|
||||||
|
else:
|
||||||
|
self.add(item)
|
||||||
|
|
||||||
|
def union(self, iterable):
|
||||||
|
return type(self)(super().union(iterable))
|
||||||
|
|
||||||
|
def update(self, iterable):
|
||||||
|
for item in iterable:
|
||||||
|
if item not in self:
|
||||||
|
self.add(item)
|
||||||
|
|
||||||
|
class UserDict(dict):
|
||||||
|
def __init__(_self, _it=(), **kwargs):
|
||||||
|
super().__init__()
|
||||||
|
if hasattr(_it, "items"):
|
||||||
|
_it = _it.items()
|
||||||
|
try:
|
||||||
|
for key, value in _it:
|
||||||
|
self[key] = value
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
self[key] = value
|
||||||
|
except:
|
||||||
|
while self:
|
||||||
|
self.popitem() # don't clear, as it's recursive (we might not want that)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, tb):
|
||||||
|
self.clear()
|
||||||
|
|
||||||
|
def __setitem__(self, item, value):
|
||||||
|
old = self.get(item)
|
||||||
|
super().__setitem__(item, value)
|
||||||
|
if isinstance(old, User):
|
||||||
|
if old not in self.values():
|
||||||
|
old.dict_values.remove(self)
|
||||||
|
|
||||||
|
if isinstance(item, User):
|
||||||
|
if self not in item.dict_keys:
|
||||||
|
item.dict_keys.append(self)
|
||||||
|
|
||||||
|
if isinstance(value, User):
|
||||||
|
if self not in value.dict_values:
|
||||||
|
value.dict_values.append(self)
|
||||||
|
|
||||||
|
def __delitem__(self, item):
|
||||||
|
value = self[item]
|
||||||
|
super().__delitem__(item)
|
||||||
|
if isinstance(item, User):
|
||||||
|
item.dict_keys.remove(self)
|
||||||
|
|
||||||
|
if isinstance(value, User):
|
||||||
|
if value not in self.values():
|
||||||
|
value.dict_values.remove(self)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
for key, value in self.items():
|
||||||
|
if isinstance(key, User):
|
||||||
|
key.dict_keys.remove(self)
|
||||||
|
if isinstance(value, User):
|
||||||
|
if self in value.dict_values:
|
||||||
|
value.dict_values.remove(self)
|
||||||
|
|
||||||
|
if isinstance(key, (UserList, UserSet, UserDict)):
|
||||||
|
key.clear()
|
||||||
|
if isinstance(value, (UserList, UserSet, UserDict)):
|
||||||
|
value.clear()
|
||||||
|
|
||||||
|
super().clear()
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return type(self)(self.items())
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromkeys(cls, iterable, value=None):
|
||||||
|
return cls(dict.fromkeys(iterable, value))
|
||||||
|
|
||||||
|
def pop(self, key, *default):
|
||||||
|
value = super().pop(key, *default)
|
||||||
|
if isinstance(key, User):
|
||||||
|
if self in key.dict_keys:
|
||||||
|
key.dict_keys.remove(self)
|
||||||
|
if isinstance(value, User):
|
||||||
|
if value not in self.values():
|
||||||
|
value.dict_values.remove(self)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def popitem(self):
|
||||||
|
key, value = super().popitem()
|
||||||
|
if isinstance(key, User):
|
||||||
|
key.dict_keys.remove(self)
|
||||||
|
if isinstance(value, User):
|
||||||
|
if value not in self.values():
|
||||||
|
value.dict_values.remove(self)
|
||||||
|
return key, value
|
||||||
|
|
||||||
|
def setdefault(self, key, default=None):
|
||||||
|
if key not in self:
|
||||||
|
self[key] = default
|
||||||
|
return self[key]
|
||||||
|
|
||||||
|
def update(self, iterable):
|
||||||
|
if hasattr(iterable, "items"):
|
||||||
|
iterable = iterable.items()
|
||||||
|
for key, value in iterable:
|
||||||
|
self[key] = value
|
@ -12,6 +12,7 @@ from src.utilities import *
|
|||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.functions import get_players, get_all_players, get_main_role
|
from src.functions import get_players, get_all_players, get_main_role
|
||||||
from src.decorators import handle_error, command
|
from src.decorators import handle_error, command
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src import events, channels, users
|
from src import events, channels, users
|
||||||
|
|
||||||
def game_mode(name, minp, maxp, likelihood = 0):
|
def game_mode(name, minp, maxp, likelihood = 0):
|
||||||
@ -601,7 +602,7 @@ class RandomMode(GameMode):
|
|||||||
events.remove_listener("role_attribution", self.role_attribution)
|
events.remove_listener("role_attribution", self.role_attribution)
|
||||||
events.remove_listener("chk_win", self.lovers_chk_win)
|
events.remove_listener("chk_win", self.lovers_chk_win)
|
||||||
|
|
||||||
def role_attribution(self, evt, cli, var, chk_win_conditions, villagers):
|
def role_attribution(self, evt, var, chk_win_conditions, villagers):
|
||||||
lpl = len(villagers) - 1
|
lpl = len(villagers) - 1
|
||||||
addroles = evt.data["addroles"]
|
addroles = evt.data["addroles"]
|
||||||
for role in var.ROLE_GUIDE:
|
for role in var.ROLE_GUIDE:
|
||||||
@ -629,8 +630,8 @@ class RandomMode(GameMode):
|
|||||||
mainroles[u] = role
|
mainroles[u] = role
|
||||||
i += count
|
i += count
|
||||||
|
|
||||||
if chk_win_conditions(cli, rolemap, mainroles, end_game=False):
|
if chk_win_conditions(rolemap, mainroles, end_game=False):
|
||||||
return self.role_attribution(evt, cli, var, chk_win_conditions, villagers)
|
return self.role_attribution(evt, var, chk_win_conditions, villagers)
|
||||||
|
|
||||||
evt.prevent_default = True
|
evt.prevent_default = True
|
||||||
|
|
||||||
@ -875,20 +876,19 @@ class SleepyMode(GameMode):
|
|||||||
# disable wolfchat
|
# disable wolfchat
|
||||||
#self.RESTRICT_WOLFCHAT = 0x0f
|
#self.RESTRICT_WOLFCHAT = 0x0f
|
||||||
|
|
||||||
self.having_nightmare = None
|
|
||||||
|
|
||||||
def startup(self):
|
def startup(self):
|
||||||
events.add_listener("dullahan_targets", self.dullahan_targets)
|
events.add_listener("dullahan_targets", self.dullahan_targets)
|
||||||
events.add_listener("transition_night_begin", self.setup_nightmares)
|
events.add_listener("transition_night_begin", self.setup_nightmares)
|
||||||
events.add_listener("chk_nightdone", self.prolong_night)
|
events.add_listener("chk_nightdone", self.prolong_night)
|
||||||
events.add_listener("transition_day_begin", self.nightmare_kill)
|
events.add_listener("transition_day_begin", self.nightmare_kill)
|
||||||
events.add_listener("del_player", self.happy_fun_times)
|
events.add_listener("del_player", self.happy_fun_times)
|
||||||
events.add_listener("rename_player", self.rename_player)
|
|
||||||
self.north_cmd = command("north", "n", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "n"))
|
self.north_cmd = command("north", "n", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "n"))
|
||||||
self.east_cmd = command("east", "e", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "e"))
|
self.east_cmd = command("east", "e", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "e"))
|
||||||
self.south_cmd = command("south", "s", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "s"))
|
self.south_cmd = command("south", "s", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "s"))
|
||||||
self.west_cmd = command("west", "w", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "w"))
|
self.west_cmd = command("west", "w", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "w"))
|
||||||
|
|
||||||
|
self.having_nightmare = UserList()
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
from src import decorators
|
from src import decorators
|
||||||
events.remove_listener("dullahan_targets", self.dullahan_targets)
|
events.remove_listener("dullahan_targets", self.dullahan_targets)
|
||||||
@ -896,7 +896,6 @@ class SleepyMode(GameMode):
|
|||||||
events.remove_listener("chk_nightdone", self.prolong_night)
|
events.remove_listener("chk_nightdone", self.prolong_night)
|
||||||
events.remove_listener("transition_day_begin", self.nightmare_kill)
|
events.remove_listener("transition_day_begin", self.nightmare_kill)
|
||||||
events.remove_listener("del_player", self.happy_fun_times)
|
events.remove_listener("del_player", self.happy_fun_times)
|
||||||
events.remove_listener("rename_player", self.rename_player)
|
|
||||||
def remove_command(name, command):
|
def remove_command(name, command):
|
||||||
if len(decorators.COMMANDS[name]) > 1:
|
if len(decorators.COMMANDS[name]) > 1:
|
||||||
decorators.COMMANDS[name].remove(command)
|
decorators.COMMANDS[name].remove(command)
|
||||||
@ -911,23 +910,18 @@ class SleepyMode(GameMode):
|
|||||||
remove_command("west", self.west_cmd)
|
remove_command("west", self.west_cmd)
|
||||||
remove_command("w", self.west_cmd)
|
remove_command("w", self.west_cmd)
|
||||||
|
|
||||||
def dullahan_targets(self, evt, cli, var, dullahans, max_targets):
|
self.having_nightmare.clear()
|
||||||
|
|
||||||
|
def dullahan_targets(self, evt, var, dullahans, max_targets):
|
||||||
for dull in dullahans:
|
for dull in dullahans:
|
||||||
evt.data["targets"][dull] = set(var.ROLES["priest"])
|
evt.data["targets"][dull] = UserSet(var.ROLES["priest"])
|
||||||
|
|
||||||
def setup_nightmares(self, evt, cli, var):
|
def setup_nightmares(self, evt, cli, var):
|
||||||
if random.random() < 1/5:
|
if random.random() < 1/5:
|
||||||
self.having_nightmare = True
|
|
||||||
with var.WARNING_LOCK:
|
with var.WARNING_LOCK:
|
||||||
t = threading.Timer(60, self.do_nightmare, (var, random.choice(get_players()), var.NIGHT_COUNT))
|
t = threading.Timer(60, self.do_nightmare, (var, random.choice(get_players()), var.NIGHT_COUNT))
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
else:
|
|
||||||
self.having_nightmare = None
|
|
||||||
|
|
||||||
def rename_player(self, evt, cli, var, prefix, nick):
|
|
||||||
if self.having_nightmare == prefix:
|
|
||||||
self.having_nightmare = nick
|
|
||||||
|
|
||||||
@handle_error
|
@handle_error
|
||||||
def do_nightmare(self, var, target, night):
|
def do_nightmare(self, var, target, night):
|
||||||
@ -935,7 +929,8 @@ class SleepyMode(GameMode):
|
|||||||
return
|
return
|
||||||
if target not in get_players():
|
if target not in get_players():
|
||||||
return
|
return
|
||||||
self.having_nightmare = target
|
self.having_nightmare.clear()
|
||||||
|
self.having_nightmare.append(target)
|
||||||
target.send(messages["sleepy_nightmare_begin"])
|
target.send(messages["sleepy_nightmare_begin"])
|
||||||
target.send(messages["sleepy_nightmare_navigate"])
|
target.send(messages["sleepy_nightmare_navigate"])
|
||||||
self.correct = [None, None, None]
|
self.correct = [None, None, None]
|
||||||
@ -976,30 +971,30 @@ class SleepyMode(GameMode):
|
|||||||
directions = "north, south, and west"
|
directions = "north, south, and west"
|
||||||
|
|
||||||
if self.step == 0:
|
if self.step == 0:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_0"].format(directions))
|
self.having_nightmare[0].send(messages["sleepy_nightmare_0"].format(directions))
|
||||||
elif self.step == 1:
|
elif self.step == 1:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_1"].format(directions))
|
self.having_nightmare[0].send(messages["sleepy_nightmare_1"].format(directions))
|
||||||
elif self.step == 2:
|
elif self.step == 2:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_2"].format(directions))
|
self.having_nightmare[0].send(messages["sleepy_nightmare_2"].format(directions))
|
||||||
elif self.step == 3:
|
elif self.step == 3:
|
||||||
if "correct" in self.on_path:
|
if "correct" in self.on_path:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_wake"])
|
self.having_nightmare[0].send(messages["sleepy_nightmare_wake"])
|
||||||
self.having_nightmare = None
|
del self.having_nightmare[0]
|
||||||
elif "fake1" in self.on_path:
|
elif "fake1" in self.on_path:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_fake_1"])
|
self.having_nightmare[0].send(messages["sleepy_nightmare_fake_1"])
|
||||||
self.step = 0
|
self.step = 0
|
||||||
self.on_path = set()
|
self.on_path = set()
|
||||||
self.prev_direction = self.start_direction
|
self.prev_direction = self.start_direction
|
||||||
self.nightmare_step()
|
self.nightmare_step()
|
||||||
elif "fake2" in self.on_path:
|
elif "fake2" in self.on_path:
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_fake_2"])
|
self.having_nightmare[0].send(messages["sleepy_nightmare_fake_2"])
|
||||||
self.step = 0
|
self.step = 0
|
||||||
self.on_path = set()
|
self.on_path = set()
|
||||||
self.prev_direction = self.start_direction
|
self.prev_direction = self.start_direction
|
||||||
self.nightmare_step()
|
self.nightmare_step()
|
||||||
|
|
||||||
def move(self, direction, var, wrapper, message):
|
def move(self, direction, var, wrapper, message):
|
||||||
if self.having_nightmare is not wrapper.source:
|
if self.having_nightmare[0] is not wrapper.source:
|
||||||
return
|
return
|
||||||
opposite = {"n": "s", "e": "w", "s": "n", "w": "e"}
|
opposite = {"n": "s", "e": "w", "s": "n", "w": "e"}
|
||||||
if self.prev_direction == opposite[direction]:
|
if self.prev_direction == opposite[direction]:
|
||||||
@ -1032,14 +1027,14 @@ class SleepyMode(GameMode):
|
|||||||
self.nightmare_step()
|
self.nightmare_step()
|
||||||
|
|
||||||
def prolong_night(self, evt, var):
|
def prolong_night(self, evt, var):
|
||||||
if self.having_nightmare is not None:
|
if self.having_nightmare:
|
||||||
evt.data["actedcount"] = -1
|
evt.data["actedcount"] = -1
|
||||||
|
|
||||||
def nightmare_kill(self, evt, var):
|
def nightmare_kill(self, evt, var):
|
||||||
# if True, it means night ended before 1 minute
|
if self.having_nightmare and self.having_nightmare[0] in get_players():
|
||||||
if self.having_nightmare is not None and self.having_nightmare in get_players():
|
var.DYING.add(self.having_nightmare[0])
|
||||||
var.DYING.add(self.having_nightmare)
|
self.having_nightmare[0].send(messages["sleepy_nightmare_death"])
|
||||||
self.having_nightmare.send(messages["sleepy_nightmare_death"])
|
del self.having_nightmare[0]
|
||||||
|
|
||||||
def happy_fun_times(self, evt, var, user, mainrole, allroles, death_triggers):
|
def happy_fun_times(self, evt, var, user, mainrole, allroles, death_triggers):
|
||||||
if death_triggers:
|
if death_triggers:
|
||||||
@ -1125,13 +1120,12 @@ class MaelstromMode(GameMode):
|
|||||||
def _on_join(self, var, wrapper):
|
def _on_join(self, var, wrapper):
|
||||||
from src import hooks, channels
|
from src import hooks, channels
|
||||||
role = random.choice(self.roles)
|
role = random.choice(self.roles)
|
||||||
rolemap = copy.deepcopy(var.ROLES)
|
with copy.deepcopy(var.ROLES) as rolemap, copy.deepcopy(var.MAIN_ROLES) as mainroles:
|
||||||
rolemap[role].add(wrapper.source)
|
rolemap[role].add(wrapper.source)
|
||||||
mainroles = copy.deepcopy(var.MAIN_ROLES)
|
mainroles[wrapper.source] = role
|
||||||
mainroles[wrapper.source] = role
|
|
||||||
|
|
||||||
if self.chk_win_conditions(wrapper.client, rolemap, mainroles, end_game=False):
|
if self.chk_win_conditions(rolemap, mainroles, end_game=False):
|
||||||
return self._on_join(var, wrapper)
|
return self._on_join(var, wrapper)
|
||||||
|
|
||||||
if not wrapper.source.is_fake or not botconfig.DEBUG_MODE:
|
if not wrapper.source.is_fake or not botconfig.DEBUG_MODE:
|
||||||
cmodes = [("+v", wrapper.source)]
|
cmodes = [("+v", wrapper.source)]
|
||||||
@ -1173,22 +1167,23 @@ class MaelstromMode(GameMode):
|
|||||||
pl[i] = player.nick + " (cursed)"
|
pl[i] = player.nick + " (cursed)"
|
||||||
wrapper.pm("Players: " + ", ".join(pl))
|
wrapper.pm("Players: " + ", ".join(pl))
|
||||||
|
|
||||||
def role_attribution(self, evt, cli, var, chk_win_conditions, villagers):
|
def role_attribution(self, evt, var, chk_win_conditions, villagers):
|
||||||
self.chk_win_conditions = chk_win_conditions
|
self.chk_win_conditions = chk_win_conditions
|
||||||
evt.data["addroles"] = self._role_attribution(cli, var, villagers, True)
|
evt.data["addroles"] = self._role_attribution(var, villagers, True)
|
||||||
|
|
||||||
def transition_night_begin(self, evt, cli, var):
|
def transition_night_begin(self, evt, var):
|
||||||
# don't do this n1
|
# don't do this n1
|
||||||
if var.FIRST_NIGHT:
|
if var.FIRST_NIGHT:
|
||||||
return
|
return
|
||||||
villagers = get_players()
|
villagers = get_players()
|
||||||
lpl = len(villagers)
|
lpl = len(villagers)
|
||||||
addroles = self._role_attribution(cli, var, villagers, False)
|
addroles = self._role_attribution(var, villagers, False)
|
||||||
|
|
||||||
# shameless copy/paste of regular role attribution
|
# shameless copy/paste of regular role attribution
|
||||||
for role, count in addroles.items():
|
for role, count in addroles.items():
|
||||||
selected = random.sample(villagers, count)
|
selected = random.sample(villagers, count)
|
||||||
var.ROLES[role] = set(selected)
|
var.ROLES[role].clear()
|
||||||
|
var.ROLES[role].update(selected)
|
||||||
for x in selected:
|
for x in selected:
|
||||||
villagers.remove(x)
|
villagers.remove(x)
|
||||||
|
|
||||||
@ -1216,7 +1211,7 @@ class MaelstromMode(GameMode):
|
|||||||
var.FINAL_ROLES[p.nick] = role # FIXME
|
var.FINAL_ROLES[p.nick] = role # FIXME
|
||||||
var.MAIN_ROLES[p] = role
|
var.MAIN_ROLES[p] = role
|
||||||
|
|
||||||
def _role_attribution(self, cli, var, villagers, do_templates):
|
def _role_attribution(self, var, villagers, do_templates):
|
||||||
lpl = len(villagers) - 1
|
lpl = len(villagers) - 1
|
||||||
addroles = {}
|
addroles = {}
|
||||||
for role in var.ROLE_GUIDE:
|
for role in var.ROLE_GUIDE:
|
||||||
@ -1255,8 +1250,8 @@ class MaelstromMode(GameMode):
|
|||||||
mainroles[u] = role
|
mainroles[u] = role
|
||||||
i += count
|
i += count
|
||||||
|
|
||||||
if self.chk_win_conditions(cli, rolemap, mainroles, end_game=False):
|
if self.chk_win_conditions(rolemap, mainroles, end_game=False):
|
||||||
return self._role_attribution(cli, var, villagers, do_templates)
|
return self._role_attribution(var, villagers, do_templates)
|
||||||
|
|
||||||
return addroles
|
return addroles
|
||||||
|
|
||||||
@ -1375,7 +1370,7 @@ class MudkipMode(GameMode):
|
|||||||
def daylight_warning(self, evt, var):
|
def daylight_warning(self, evt, var):
|
||||||
evt.data["message"] = "daylight_warning_killtie"
|
evt.data["message"] = "daylight_warning_killtie"
|
||||||
|
|
||||||
def transition_night_begin(self, evt, cli, var):
|
def transition_night_begin(self, evt, var):
|
||||||
if var.FIRST_NIGHT:
|
if var.FIRST_NIGHT:
|
||||||
# ensure shaman gets death totem on the first night
|
# ensure shaman gets death totem on the first night
|
||||||
var.TOTEM_CHANCES["pestilence"] = (0, 1, 0)
|
var.TOTEM_CHANCES["pestilence"] = (0, 1, 0)
|
||||||
|
@ -10,6 +10,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ def pass_cmd(cli, nick, chan, rest):
|
|||||||
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
|
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
for dictvar in (GUARDED, LASTGUARDED):
|
for dictvar in (GUARDED, LASTGUARDED):
|
||||||
kvp = {}
|
kvp = {}
|
||||||
for a,b in dictvar.items():
|
for a,b in dictvar.items():
|
||||||
@ -223,7 +224,7 @@ def on_transition_day_resolve_end(evt, var, victims):
|
|||||||
evt.data["dead"].append(gangel)
|
evt.data["dead"].append(gangel)
|
||||||
|
|
||||||
@event_listener("transition_night_begin")
|
@event_listener("transition_night_begin")
|
||||||
def on_transition_night_begin(evt, cli, var):
|
def on_transition_night_begin(evt, var):
|
||||||
# needs to be here in order to allow bodyguard protections to work during the daytime
|
# needs to be here in order to allow bodyguard protections to work during the daytime
|
||||||
# (right now they don't due to other reasons, but that may change)
|
# (right now they don't due to other reasons, but that may change)
|
||||||
GUARDED.clear()
|
GUARDED.clear()
|
||||||
|
@ -10,6 +10,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ def on_transition_night_end(evt, var):
|
|||||||
blessed.send(messages[to_send])
|
blessed.send(messages[to_send])
|
||||||
|
|
||||||
@event_listener("desperation_totem")
|
@event_listener("desperation_totem")
|
||||||
def on_desperation(evt, cli, var, votee, target, prot):
|
def on_desperation(evt, var, votee, target, prot):
|
||||||
if prot == "blessing":
|
if prot == "blessing":
|
||||||
var.ACTIVE_PROTECTIONS[target].remove("blessing")
|
var.ACTIVE_PROTECTIONS[target].remove("blessing")
|
||||||
evt.prevent_default = True
|
evt.prevent_default = True
|
||||||
|
@ -9,11 +9,12 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@event_listener("see")
|
@event_listener("see")
|
||||||
def on_see(evt, cli, var, nick, victim):
|
def on_see(evt, var, nick, victim):
|
||||||
if users._get(victim) in var.ROLES["cursed villager"]: # FIXME
|
if users._get(victim) in var.ROLES["cursed villager"]: # FIXME
|
||||||
evt.data["role"] = "wolf"
|
evt.data["role"] = "wolf"
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ def investigate(cli, nick, chan, rest):
|
|||||||
debuglog("{0} ({1}) PAPER DROP".format(nick, get_role(nick)))
|
debuglog("{0} ({1}) PAPER DROP".format(nick, get_role(nick)))
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
if prefix in INVESTIGATED:
|
if prefix in INVESTIGATED:
|
||||||
INVESTIGATED.remove(prefix)
|
INVESTIGATED.remove(prefix)
|
||||||
INVESTIGATED.add(nick)
|
INVESTIGATED.add(nick)
|
||||||
@ -96,7 +97,7 @@ def on_transition_night_end(evt, var):
|
|||||||
dttv.send(messages[to_send].format(warning), "Players: " + ", ".join(p.nick for p in pl), sep="\n")
|
dttv.send(messages[to_send].format(warning), "Players: " + ", ".join(p.nick for p in pl), sep="\n")
|
||||||
|
|
||||||
@event_listener("transition_night_begin")
|
@event_listener("transition_night_begin")
|
||||||
def on_transition_night_begin(evt, cli, var):
|
def on_transition_night_begin(evt, var):
|
||||||
INVESTIGATED.clear()
|
INVESTIGATED.clear()
|
||||||
|
|
||||||
@event_listener("reset")
|
@event_listener("reset")
|
||||||
|
@ -6,6 +6,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ def see(cli, nick, chan, rest):
|
|||||||
SEEN.add(nick)
|
SEEN.add(nick)
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
if prefix in SEEN:
|
if prefix in SEEN:
|
||||||
SEEN.remove(prefix)
|
SEEN.remove(prefix)
|
||||||
SEEN.add(nick)
|
SEEN.add(nick)
|
||||||
@ -97,7 +98,7 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
del dictvar[k]
|
del dictvar[k]
|
||||||
|
|
||||||
@event_listener("doctor_immunize")
|
@event_listener("doctor_immunize")
|
||||||
def on_doctor_immunize(evt, cli, var, doctor, target):
|
def on_doctor_immunize(evt, var, doctor, target):
|
||||||
if target in SICK.values():
|
if target in SICK.values():
|
||||||
for n, v in list(SICK.items()):
|
for n, v in list(SICK.items()):
|
||||||
if v == target:
|
if v == target:
|
||||||
@ -161,7 +162,7 @@ def on_begin_day(evt, var):
|
|||||||
LYCANS.clear()
|
LYCANS.clear()
|
||||||
|
|
||||||
@event_listener("transition_night_begin")
|
@event_listener("transition_night_begin")
|
||||||
def on_transition_night_begin(evt, cli, var):
|
def on_transition_night_begin(evt, var):
|
||||||
SICK.clear()
|
SICK.clear()
|
||||||
|
|
||||||
@event_listener("reset")
|
@event_listener("reset")
|
||||||
|
@ -7,12 +7,13 @@ from src.utilities import *
|
|||||||
from src.functions import get_players, get_all_players, get_target, get_main_role, get_reveal_role
|
from src.functions import get_players, get_all_players, get_target, get_main_role, get_reveal_role
|
||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
import botconfig
|
import botconfig
|
||||||
|
|
||||||
KILLS = {} # type: Dict[users.User, users.User]
|
KILLS = UserDict() # type: Dict[users.User, users.User]
|
||||||
TARGETS = {} # type: Dict[users.User, Set[users.User]]
|
TARGETS = UserDict() # type: Dict[users.User, Set[users.User]]
|
||||||
|
|
||||||
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("dullahan",))
|
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("dullahan",))
|
||||||
def dullahan_kill(var, wrapper, message):
|
def dullahan_kill(var, wrapper, message):
|
||||||
@ -62,66 +63,50 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
del KILLS[h]
|
del KILLS[h]
|
||||||
if death_triggers and "dullahan" in allroles:
|
if death_triggers and "dullahan" in allroles:
|
||||||
pl = evt.data["pl"]
|
pl = evt.data["pl"]
|
||||||
targets = TARGETS[user].intersection(pl)
|
with TARGETS[user].intersection(pl) as targets:
|
||||||
if targets:
|
if targets:
|
||||||
target = random.choice(list(targets))
|
target = random.choice(list(targets))
|
||||||
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||||
aevt = Event("assassinate", {"pl": evt.data["pl"], "target": target},
|
aevt = Event("assassinate", {"pl": evt.data["pl"], "target": target},
|
||||||
del_player=evt.params.del_player,
|
del_player=evt.params.del_player,
|
||||||
deadlist=evt.params.deadlist,
|
deadlist=evt.params.deadlist,
|
||||||
original=evt.params.original,
|
original=evt.params.original,
|
||||||
refresh_pl=evt.params.refresh_pl,
|
refresh_pl=evt.params.refresh_pl,
|
||||||
message_prefix="dullahan_die_",
|
message_prefix="dullahan_die_",
|
||||||
source="dullahan",
|
source="dullahan",
|
||||||
killer=user,
|
killer=user,
|
||||||
killer_mainrole=mainrole,
|
killer_mainrole=mainrole,
|
||||||
killer_allroles=allroles,
|
killer_allroles=allroles,
|
||||||
prots=prots)
|
prots=prots)
|
||||||
while len(prots) > 0:
|
while len(prots) > 0:
|
||||||
# an event can read the current active protection and cancel or redirect the assassination
|
# an event can read the current active protection and cancel or redirect the assassination
|
||||||
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
||||||
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
||||||
if not aevt.dispatch(var, user, target, prots[0]):
|
if not aevt.dispatch(var, user, target, prots[0]):
|
||||||
evt.data["pl"] = aevt.data["pl"]
|
evt.data["pl"] = aevt.data["pl"]
|
||||||
if target is not aevt.data["target"]:
|
if target is not aevt.data["target"]:
|
||||||
target = aevt.data["target"]
|
target = aevt.data["target"]
|
||||||
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||||
aevt.params.prots = prots
|
aevt.params.prots = prots
|
||||||
continue
|
continue
|
||||||
return
|
return
|
||||||
prots.popleft()
|
prots.popleft()
|
||||||
|
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
role = get_reveal_role(target)
|
role = get_reveal_role(target)
|
||||||
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
|
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
channels.Main.send(messages["dullahan_die_success"].format(user, target, an, role))
|
channels.Main.send(messages["dullahan_die_success"].format(user, target, an, role))
|
||||||
else:
|
else:
|
||||||
channels.Main.send(messages["dullahan_die_success_noreveal"].format(user, target))
|
channels.Main.send(messages["dullahan_die_success_noreveal"].format(user, target))
|
||||||
debuglog("{0} (dullahan) DULLAHAN ASSASSINATE: {1} ({2})".format(user, target, get_main_role(target)))
|
debuglog("{0} (dullahan) DULLAHAN ASSASSINATE: {1} ({2})".format(user, target, get_main_role(target)))
|
||||||
evt.params.del_player(target, end_game=False, killer_role="dullahan", deadlist=evt.params.deadlist, original=evt.params.original, ismain=False)
|
evt.params.del_player(target, end_game=False, killer_role="dullahan", deadlist=evt.params.deadlist, original=evt.params.original, ismain=False)
|
||||||
evt.data["pl"] = evt.params.refresh_pl(pl)
|
evt.data["pl"] = evt.params.refresh_pl(pl)
|
||||||
|
|
||||||
@event_listener("night_acted")
|
@event_listener("night_acted")
|
||||||
def on_acted(evt, var, user, actor):
|
def on_acted(evt, var, user, actor):
|
||||||
if user in KILLS:
|
if user in KILLS:
|
||||||
evt.data["acted"] = True
|
evt.data["acted"] = True
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
if old_user in KILLS:
|
|
||||||
KILLS[user] = KILLS.pop(old_user)
|
|
||||||
if old_user in TARGETS:
|
|
||||||
TARGETS[user] = TARGETS.pop(old_user)
|
|
||||||
|
|
||||||
for dullahan, target in KILLS.items():
|
|
||||||
if target is old_user:
|
|
||||||
KILLS[dullahan] = user
|
|
||||||
|
|
||||||
for dullahan, targets in TARGETS.items():
|
|
||||||
if old_user in targets:
|
|
||||||
targets.remove(old_user)
|
|
||||||
targets.add(user)
|
|
||||||
|
|
||||||
@event_listener("get_special")
|
@event_listener("get_special")
|
||||||
def on_get_special(evt, var):
|
def on_get_special(evt, var):
|
||||||
evt.data["special"].update(get_players(("dullahan",)))
|
evt.data["special"].update(get_players(("dullahan",)))
|
||||||
@ -172,19 +157,17 @@ def on_transition_night_end(evt, var):
|
|||||||
dullahan.send(messages[to_send], t + ", ".join(t.nick for t in targets), sep="\n")
|
dullahan.send(messages[to_send], t + ", ".join(t.nick for t in targets), sep="\n")
|
||||||
|
|
||||||
@event_listener("role_assignment")
|
@event_listener("role_assignment")
|
||||||
def on_role_assignment(evt, cli, var, gamemode, pl, restart):
|
def on_role_assignment(evt, var, gamemode, pl):
|
||||||
# assign random targets to dullahan to kill
|
# assign random targets to dullahan to kill
|
||||||
if var.ROLES["dullahan"]:
|
if var.ROLES["dullahan"]:
|
||||||
max_targets = math.ceil(8.1 * math.log(len(pl), 10) - 5)
|
max_targets = math.ceil(8.1 * math.log(len(pl), 10) - 5)
|
||||||
for dull in var.ROLES["dullahan"]:
|
for dull in var.ROLES["dullahan"]:
|
||||||
TARGETS[dull] = set()
|
TARGETS[dull] = UserSet()
|
||||||
dull_targets = Event("dullahan_targets", {"targets": TARGETS}) # support sleepy
|
dull_targets = Event("dullahan_targets", {"targets": TARGETS}) # support sleepy
|
||||||
dull_targets.dispatch(cli, var, var.ROLES["dullahan"], max_targets)
|
dull_targets.dispatch(var, var.ROLES["dullahan"], max_targets)
|
||||||
|
|
||||||
players = [users._get(x) for x in pl] # FIXME
|
|
||||||
|
|
||||||
for dull, ts in TARGETS.items():
|
for dull, ts in TARGETS.items():
|
||||||
ps = players[:]
|
ps = pl[:]
|
||||||
ps.remove(dull)
|
ps.remove(dull)
|
||||||
while len(ts) < max_targets:
|
while len(ts) < max_targets:
|
||||||
target = random.choice(ps)
|
target = random.choice(ps)
|
||||||
|
@ -9,6 +9,7 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
@ -10,11 +10,12 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
VISITED = {} # type: Dict[users.User, users.User]
|
VISITED = UserDict() # type: Dict[users.User, users.User]
|
||||||
PASSED = set() # type: Set[users.User]
|
PASSED = UserSet() # type: Set[users.User]
|
||||||
|
|
||||||
@command("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("harlot",))
|
@command("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("harlot",))
|
||||||
def hvisit(var, wrapper, message):
|
def hvisit(var, wrapper, message):
|
||||||
@ -134,18 +135,6 @@ def on_begin_day(evt, var):
|
|||||||
VISITED.clear()
|
VISITED.clear()
|
||||||
PASSED.clear()
|
PASSED.clear()
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
for harlot, target in set(VISITED.items()):
|
|
||||||
if target is old_user:
|
|
||||||
VISITED[harlot] = user
|
|
||||||
if harlot is old_user:
|
|
||||||
VISITED[user] = VISITED.pop(harlot)
|
|
||||||
|
|
||||||
if old_user in PASSED:
|
|
||||||
PASSED.remove(old_user)
|
|
||||||
PASSED.add(user)
|
|
||||||
|
|
||||||
@event_listener("get_special")
|
@event_listener("get_special")
|
||||||
def on_get_special(evt, var):
|
def on_get_special(evt, var):
|
||||||
evt.data["special"].update(get_players(("harlot",)))
|
evt.data["special"].update(get_players(("harlot",)))
|
||||||
|
@ -7,12 +7,13 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_target, get_main_role
|
from src.functions import get_players, get_all_players, get_target, get_main_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
KILLS = {} # type: Dict[users.User, users.User]
|
KILLS = UserDict() # type: Dict[users.User, users.User]
|
||||||
HUNTERS = set()
|
HUNTERS = UserSet()
|
||||||
PASSED = set()
|
PASSED = UserSet()
|
||||||
|
|
||||||
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",))
|
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",))
|
||||||
def hunter_kill(var, wrapper, message):
|
def hunter_kill(var, wrapper, message):
|
||||||
@ -74,20 +75,6 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
h.send(messages["hunter_discard"])
|
h.send(messages["hunter_discard"])
|
||||||
del KILLS[h]
|
del KILLS[h]
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
for a, b in list(KILLS.items()):
|
|
||||||
if a is old_user:
|
|
||||||
KILLS[user] = KILLS.pop(old_user)
|
|
||||||
if b is old_user:
|
|
||||||
KILLS[user] = KILLS.pop(old_user)
|
|
||||||
if old_user in HUNTERS:
|
|
||||||
HUNTERS.discard(old_user)
|
|
||||||
HUNTERS.add(user)
|
|
||||||
if old_user in PASSED:
|
|
||||||
PASSED.discard(old_user)
|
|
||||||
PASSED.add(user)
|
|
||||||
|
|
||||||
@event_listener("night_acted")
|
@event_listener("night_acted")
|
||||||
def on_acted(evt, var, user, actor):
|
def on_acted(evt, var, user, actor):
|
||||||
if user in KILLS:
|
if user in KILLS:
|
||||||
|
@ -10,10 +10,11 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
INVESTIGATED = set()
|
INVESTIGATED = UserSet()
|
||||||
|
|
||||||
@command("id", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("investigator",))
|
@command("id", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("investigator",))
|
||||||
def investigate(var, wrapper, message):
|
def investigate(var, wrapper, message):
|
||||||
@ -97,12 +98,6 @@ def investigate(var, wrapper, message):
|
|||||||
wrapper.source, target1, get_main_role(target1), target2, get_main_role(target2),
|
wrapper.source, target1, get_main_role(target1), target2, get_main_role(target2),
|
||||||
"same" if same else "different"))
|
"same" if same else "different"))
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
if old_user in INVESTIGATED:
|
|
||||||
INVESTIGATED.discard(old_user)
|
|
||||||
INVESTIGATED.add(user)
|
|
||||||
|
|
||||||
@event_listener("del_player")
|
@event_listener("del_player")
|
||||||
def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
||||||
INVESTIGATED.discard(user)
|
INVESTIGATED.discard(user)
|
||||||
@ -116,7 +111,7 @@ def on_exchange(evt, var, actor, target, actor_role, target_role):
|
|||||||
if actor_role == "investigator" and target_role != "investigator":
|
if actor_role == "investigator" and target_role != "investigator":
|
||||||
INVESTIGATED.discard(actor)
|
INVESTIGATED.discard(actor)
|
||||||
elif target_role == "investigator" and actor_role != "investigator":
|
elif target_role == "investigator" and actor_role != "investigator":
|
||||||
INVESTIGATED.discard(targe)
|
INVESTIGATED.discard(target)
|
||||||
|
|
||||||
@event_listener("transition_night_end", priority=2)
|
@event_listener("transition_night_end", priority=2)
|
||||||
def on_transition_night_end(evt, var):
|
def on_transition_night_end(evt, var):
|
||||||
@ -131,7 +126,7 @@ def on_transition_night_end(evt, var):
|
|||||||
inv.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n")
|
inv.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n")
|
||||||
|
|
||||||
@event_listener("transition_night_begin")
|
@event_listener("transition_night_begin")
|
||||||
def on_transition_night_begin(evt, cli, var):
|
def on_transition_night_begin(evt, var):
|
||||||
INVESTIGATED.clear()
|
INVESTIGATED.clear()
|
||||||
|
|
||||||
@event_listener("reset")
|
@event_listener("reset")
|
||||||
|
@ -10,6 +10,7 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
|
@ -9,13 +9,14 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
REVEALED_MAYORS = set()
|
REVEALED_MAYORS = set()
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename_player(evt, cli, var, prefix, nick):
|
def on_rename_player(evt, var, prefix, nick):
|
||||||
if prefix in REVEALED_MAYORS:
|
if prefix in REVEALED_MAYORS:
|
||||||
REVEALED_MAYORS.remove(prefix)
|
REVEALED_MAYORS.remove(prefix)
|
||||||
REVEALED_MAYORS.add(nick)
|
REVEALED_MAYORS.add(nick)
|
||||||
|
@ -6,6 +6,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players
|
from src.functions import get_players, get_all_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
|
@ -10,11 +10,12 @@ from src.utilities import *
|
|||||||
from src.functions import get_players, get_all_players, get_target, get_main_role
|
from src.functions import get_players, get_all_players, get_target, get_main_role
|
||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
TOBECHARMED = {} # type: Dict[users.User, Set[users.User]]
|
TOBECHARMED = UserDict() # type: Dict[users.User, Set[users.User]]
|
||||||
CHARMED = set() # type: Set[users.User]
|
CHARMED = UserSet() # type: Set[users.User]
|
||||||
|
|
||||||
@command("charm", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("piper",))
|
@command("charm", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("piper",))
|
||||||
def charm(var, wrapper, message):
|
def charm(var, wrapper, message):
|
||||||
@ -69,8 +70,12 @@ def charm(var, wrapper, message):
|
|||||||
wrapper.send(messages["target_already_charmed"].format(orig2))
|
wrapper.send(messages["target_already_charmed"].format(orig2))
|
||||||
return
|
return
|
||||||
|
|
||||||
TOBECHARMED[wrapper.source] = {target1, target2}
|
if wrapper.source in TOBECHARMED:
|
||||||
TOBECHARMED[wrapper.source].discard(None)
|
TOBECHARMED[wrapper.source].clear()
|
||||||
|
else:
|
||||||
|
TOBECHARMED[wrapper.source] = UserSet()
|
||||||
|
|
||||||
|
TOBECHARMED[wrapper.source].update({target1, target2} - {None})
|
||||||
|
|
||||||
if orig2:
|
if orig2:
|
||||||
debuglog("{0} (piper) CHARM {1} ({2}) && {3} ({4})".format(wrapper.source,
|
debuglog("{0} (piper) CHARM {1} ({2}) && {3} ({4})".format(wrapper.source,
|
||||||
@ -109,7 +114,9 @@ def on_player_win(evt, var, player, mainrole, winner, survived):
|
|||||||
@event_listener("del_player")
|
@event_listener("del_player")
|
||||||
def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
|
def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
|
||||||
CHARMED.discard(player)
|
CHARMED.discard(player)
|
||||||
TOBECHARMED.pop(player, None)
|
x = TOBECHARMED.pop(player, None)
|
||||||
|
if x is not None:
|
||||||
|
x.clear()
|
||||||
|
|
||||||
@event_listener("transition_day_begin")
|
@event_listener("transition_day_begin")
|
||||||
def on_transition_day_begin(evt, var):
|
def on_transition_day_begin(evt, var):
|
||||||
@ -196,18 +203,4 @@ def on_revealroles(evt, var, wrapper):
|
|||||||
if CHARMED:
|
if CHARMED:
|
||||||
evt.data["output"].append("\u0002charmed players\u0002: {0}".format(", ".join(p.nick for p in CHARMED)))
|
evt.data["output"].append("\u0002charmed players\u0002: {0}".format(", ".join(p.nick for p in CHARMED)))
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap_player(evt, var, old, new):
|
|
||||||
if old in CHARMED:
|
|
||||||
CHARMED.remove(old)
|
|
||||||
CHARMED.add(new)
|
|
||||||
|
|
||||||
if old in TOBECHARMED:
|
|
||||||
TOBECHARMED[new] = TOBECHARMED.pop(old)
|
|
||||||
|
|
||||||
for s in TOBECHARMED.values():
|
|
||||||
if old in s:
|
|
||||||
s.remove(old)
|
|
||||||
s.add(new)
|
|
||||||
|
|
||||||
# vim: set sw=4 expandtab:
|
# vim: set sw=4 expandtab:
|
||||||
|
@ -5,6 +5,7 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.functions import get_players, get_all_players, get_main_role
|
from src.functions import get_players, get_all_players, get_main_role
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
@ -47,7 +48,7 @@ def see(cli, nick, chan, rest):
|
|||||||
victimrole = "villager"
|
victimrole = "villager"
|
||||||
|
|
||||||
evt = Event("see", {"role": victimrole})
|
evt = Event("see", {"role": victimrole})
|
||||||
evt.dispatch(cli, var, nick, victim)
|
evt.dispatch(var, nick, victim)
|
||||||
victimrole = evt.data["role"]
|
victimrole = evt.data["role"]
|
||||||
else:
|
else:
|
||||||
if victimrole == "amnesiac":
|
if victimrole == "amnesiac":
|
||||||
@ -78,7 +79,7 @@ def see(cli, nick, chan, rest):
|
|||||||
SEEN.add(nick)
|
SEEN.add(nick)
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
if prefix in SEEN:
|
if prefix in SEEN:
|
||||||
SEEN.remove(prefix)
|
SEEN.remove(prefix)
|
||||||
SEEN.add(nick)
|
SEEN.add(nick)
|
||||||
|
@ -9,6 +9,7 @@ from src.utilities import *
|
|||||||
from src import debuglog, errlog, plog, users, channels
|
from src import debuglog, errlog, plog, users, channels
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ def totem(cli, nick, chan, rest, prefix="You"): # XXX: The transition_day_begin
|
|||||||
return
|
return
|
||||||
|
|
||||||
original_victim = victim
|
original_victim = victim
|
||||||
role = get_role(nick) # FIXME: this is bad, check if nick is in var.ROLES[thingy] instead once split
|
role = get_role(nick) # FIXME: this is bad, check if user is in var.ROLES[thingy] instead once converted
|
||||||
totem = ""
|
totem = ""
|
||||||
if role != "crazed shaman":
|
if role != "crazed shaman":
|
||||||
totem = " of " + TOTEMS[nick]
|
totem = " of " + TOTEMS[nick]
|
||||||
@ -92,7 +93,7 @@ def totem(cli, nick, chan, rest, prefix="You"): # XXX: The transition_day_begin
|
|||||||
debuglog("{0} ({1}) TOTEM: {2} ({3})".format(nick, role, victim, TOTEMS[nick]))
|
debuglog("{0} ({1}) TOTEM: {2} ({3})".format(nick, role, victim, TOTEMS[nick]))
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
if prefix in TOTEMS:
|
if prefix in TOTEMS:
|
||||||
TOTEMS[nick] = TOTEMS.pop(prefix)
|
TOTEMS[nick] = TOTEMS.pop(prefix)
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ def on_rename(evt, cli, var, prefix, nick):
|
|||||||
setvar.add(nick)
|
setvar.add(nick)
|
||||||
|
|
||||||
@event_listener("see", priority=10)
|
@event_listener("see", priority=10)
|
||||||
def on_see(evt, cli, var, nick, victim):
|
def on_see(evt, var, nick, victim):
|
||||||
if (victim in DECEIT) ^ (nick in DECEIT):
|
if (victim in DECEIT) ^ (nick in DECEIT):
|
||||||
if evt.data["role"] in var.SEEN_WOLF and evt.data["role"] not in var.SEEN_DEFAULT:
|
if evt.data["role"] in var.SEEN_WOLF and evt.data["role"] not in var.SEEN_DEFAULT:
|
||||||
evt.data["role"] = "villager"
|
evt.data["role"] = "villager"
|
||||||
@ -282,7 +283,7 @@ def on_chk_decision_lynch5(evt, cli, var, voters):
|
|||||||
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
||||||
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
||||||
desp_evt = Event("desperation_totem", {})
|
desp_evt = Event("desperation_totem", {})
|
||||||
if not desp_evt.dispatch(cli, var, votee, target, prots[0]):
|
if not desp_evt.dispatch(var, votee, target, prots[0]):
|
||||||
return
|
return
|
||||||
prots.popleft()
|
prots.popleft()
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
@ -627,26 +628,6 @@ def on_reset(evt, var):
|
|||||||
MISDIRECTION.clear()
|
MISDIRECTION.clear()
|
||||||
DECEIT.clear()
|
DECEIT.clear()
|
||||||
|
|
||||||
@event_listener("frole_role")
|
|
||||||
def on_frole_role(evt, cli, var, who, role, oldrole, args):
|
|
||||||
if role in var.TOTEM_ORDER:
|
|
||||||
if len(args) == 2:
|
|
||||||
TOTEMS[who] = args[1]
|
|
||||||
else:
|
|
||||||
max_totems = defaultdict(int)
|
|
||||||
for ix in range(len(var.TOTEM_ORDER)):
|
|
||||||
for c in var.TOTEM_CHANCES.values():
|
|
||||||
max_totems[var.TOTEM_ORDER[ix]] += c[ix]
|
|
||||||
for shaman in list_players(var.TOTEM_ORDER):
|
|
||||||
indx = var.TOTEM_ORDER.index(role)
|
|
||||||
target = 0
|
|
||||||
rand = random.random() * max_totems[var.TOTEM_ORDER[indx]]
|
|
||||||
for t in var.TOTEM_CHANCES.keys():
|
|
||||||
target += var.TOTEM_CHANCES[t][indx]
|
|
||||||
if rand <= target:
|
|
||||||
TOTEMS[shaman] = t
|
|
||||||
break
|
|
||||||
|
|
||||||
@event_listener("get_role_metadata")
|
@event_listener("get_role_metadata")
|
||||||
def on_get_role_metadata(evt, var, kind):
|
def on_get_role_metadata(evt, var, kind):
|
||||||
if kind == "night_kills":
|
if kind == "night_kills":
|
||||||
|
@ -10,11 +10,15 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
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. Not all events are represented, only the most common ones.
|
# Skeleton file for new roles. Not all events are represented, only the most common ones.
|
||||||
|
|
||||||
|
# Instead of using list, set or dict, please use UserList, UserSet or UserDict respectively
|
||||||
|
# Please refer to the notes in src/containers.py for proper use
|
||||||
|
|
||||||
# Add to evt.data["actedcount"] and evt.data["nightroles"] if this role can act during night
|
# 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
|
# 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
|
# actedcount should be added to (via +=) with everyone who has this role and has already acted
|
||||||
@ -60,11 +64,6 @@ def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
|
|||||||
def on_reset(evt, var):
|
def on_reset(evt, var):
|
||||||
pass
|
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:
|
# 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
|
# 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:
|
# death message (i.e. do not have a custom death message). Set the data as follows:
|
||||||
|
@ -10,13 +10,14 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
ENTRANCED = set() # type: Set[users.User]
|
ENTRANCED = UserSet() # type: Set[users.User]
|
||||||
ENTRANCED_DYING = set() # type: Set[users.User]
|
ENTRANCED_DYING = UserSet() # type: Set[users.User]
|
||||||
VISITED = {} # type: Dict[users.User, users.User]
|
VISITED = UserDict() # type: Dict[users.User, users.User]
|
||||||
PASSED = set() # type: Set[users.User]
|
PASSED = UserSet() # type: Set[users.User]
|
||||||
ALL_SUCC_IDLE = True
|
ALL_SUCC_IDLE = True
|
||||||
|
|
||||||
@command("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",))
|
@command("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",))
|
||||||
@ -319,25 +320,6 @@ def on_vg_kill(evt, var, ghost, target):
|
|||||||
if ghost in ENTRANCED:
|
if ghost in ENTRANCED:
|
||||||
evt.data["pl"] -= get_all_players(("succubus",))
|
evt.data["pl"] -= get_all_players(("succubus",))
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
if old_user in ENTRANCED:
|
|
||||||
ENTRANCED.remove(old_user)
|
|
||||||
ENTRANCED.add(user)
|
|
||||||
if old_user in ENTRANCED_DYING:
|
|
||||||
ENTRANCED_DYING.remove(old_user)
|
|
||||||
ENTRANCED_DYING.add(user)
|
|
||||||
|
|
||||||
for succubus, target in set(VISITED.items()):
|
|
||||||
if old_user is succubus:
|
|
||||||
VISITED[user] = VISITED.pop(succubus)
|
|
||||||
if old_user is target:
|
|
||||||
VISITED[succubus] = user
|
|
||||||
|
|
||||||
if old_user in PASSED:
|
|
||||||
PASSED.remove(old_user)
|
|
||||||
PASSED.add(user)
|
|
||||||
|
|
||||||
@event_listener("reset")
|
@event_listener("reset")
|
||||||
def on_reset(evt, var):
|
def on_reset(evt, var):
|
||||||
global ALL_SUCC_IDLE
|
global ALL_SUCC_IDLE
|
||||||
|
@ -9,6 +9,7 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import debuglog, errlog, plog, users, channels
|
from src import debuglog, errlog, plog, users, channels
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
|
@ -7,14 +7,15 @@ from src.utilities import *
|
|||||||
from src import channels, users, debuglog, errlog, plog
|
from src import channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_target, get_main_role
|
from src.functions import get_players, get_target, get_main_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
KILLS = {} # type: Dict[users.User, users.User]
|
KILLS = UserDict() # type: Dict[users.User, users.User]
|
||||||
GHOSTS = {} # type: Dict[users.User, str]
|
GHOSTS = UserDict() # type: Dict[users.User, str]
|
||||||
|
|
||||||
# temporary holding variable, only non-empty during transition_day
|
# temporary holding variable, only non-empty during transition_day
|
||||||
drivenoff = {} # type: Dict[users.User, str]
|
drivenoff = UserDict() # type: Dict[users.User, str]
|
||||||
|
|
||||||
@command("kill", chan=False, pm=True, playing=False, silenced=True, phases=("night",), users=GHOSTS)
|
@command("kill", chan=False, pm=True, playing=False, silenced=True, phases=("night",), users=GHOSTS)
|
||||||
def vg_kill(var, wrapper, message):
|
def vg_kill(var, wrapper, message):
|
||||||
|
@ -7,11 +7,12 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_target
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
KILLS = {} # type: Dict[users.User, users.User]
|
KILLS = UserDict() # type: Dict[users.User, users.User]
|
||||||
PASSED = set() # type: Set[users.User]
|
PASSED = UserSet() # type: Set[users.User]
|
||||||
|
|
||||||
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("vigilante",))
|
@command("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("vigilante",))
|
||||||
def vigilante_kill(var, wrapper, message):
|
def vigilante_kill(var, wrapper, message):
|
||||||
@ -61,18 +62,6 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
vigilante.send(messages["hunter_discard"])
|
vigilante.send(messages["hunter_discard"])
|
||||||
del KILLS[vigilante]
|
del KILLS[vigilante]
|
||||||
|
|
||||||
@event_listener("swap_player")
|
|
||||||
def on_swap(evt, var, old_user, user):
|
|
||||||
for vigilante, target in set(KILLS.items()):
|
|
||||||
if vigilante is old_user:
|
|
||||||
KILLS[user] = KILLS.pop(vigilante)
|
|
||||||
if target is old_user:
|
|
||||||
KILLS[vigilante] = user
|
|
||||||
|
|
||||||
if old_user in PASSED:
|
|
||||||
PASSED.remove(old_user)
|
|
||||||
PASSED.add(user)
|
|
||||||
|
|
||||||
@event_listener("night_acted")
|
@event_listener("night_acted")
|
||||||
def on_acted(evt, var, target, spy):
|
def on_acted(evt, var, target, spy):
|
||||||
if target in KILLS:
|
if target in KILLS:
|
||||||
|
@ -3,6 +3,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players
|
from src.functions import get_players
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from src.utilities import *
|
|||||||
from src import users, channels, debuglog, errlog, plog
|
from src import users, channels, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role
|
from src.functions import get_players, get_all_players, get_main_role
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -35,12 +36,12 @@ def choose_idol(cli, nick, chan, rest):
|
|||||||
debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(nick, victim, get_role(victim)))
|
debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(nick, victim, get_role(victim)))
|
||||||
|
|
||||||
@event_listener("see")
|
@event_listener("see")
|
||||||
def on_see(evt, cli, var, seer, victim):
|
def on_see(evt, var, seer, victim):
|
||||||
if victim in WILD_CHILDREN:
|
if victim in WILD_CHILDREN:
|
||||||
evt.data["role"] = "wild child"
|
evt.data["role"] = "wild child"
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
if prefix in WILD_CHILDREN:
|
if prefix in WILD_CHILDREN:
|
||||||
WILD_CHILDREN.remove(prefix)
|
WILD_CHILDREN.remove(prefix)
|
||||||
WILD_CHILDREN.add(nick)
|
WILD_CHILDREN.add(nick)
|
||||||
|
@ -7,6 +7,7 @@ from src.utilities import *
|
|||||||
from src.functions import get_players, get_all_players, get_main_role, get_all_roles
|
from src.functions import get_players, get_all_players, get_main_role, get_all_roles
|
||||||
from src import debuglog, errlog, plog, users, channels
|
from src import debuglog, errlog, plog, users, channels
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
del KILLS[a]
|
del KILLS[a]
|
||||||
|
|
||||||
@event_listener("rename_player")
|
@event_listener("rename_player")
|
||||||
def on_rename(evt, cli, var, prefix, nick):
|
def on_rename(evt, var, prefix, nick):
|
||||||
kvp = []
|
kvp = []
|
||||||
for a,b in KILLS.items():
|
for a,b in KILLS.items():
|
||||||
nl = []
|
nl = []
|
||||||
|
@ -7,6 +7,7 @@ from src.utilities import *
|
|||||||
from src.functions import get_players
|
from src.functions import get_players
|
||||||
from src import debuglog, errlog, plog, users, channels
|
from src import debuglog, errlog, plog, users, channels
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
from src.roles import wolf
|
from src.roles import wolf
|
||||||
|
@ -3,8 +3,6 @@ import re
|
|||||||
import threading
|
import threading
|
||||||
from collections import defaultdict, OrderedDict
|
from collections import defaultdict, OrderedDict
|
||||||
|
|
||||||
import botconfig
|
|
||||||
|
|
||||||
LANGUAGE = 'en'
|
LANGUAGE = 'en'
|
||||||
|
|
||||||
MINIMUM_WAIT = 60
|
MINIMUM_WAIT = 60
|
||||||
|
42
src/users.py
42
src/users.py
@ -194,17 +194,10 @@ def _reset(evt, var):
|
|||||||
_users.discard(user)
|
_users.discard(user)
|
||||||
_ghosts.clear()
|
_ghosts.clear()
|
||||||
|
|
||||||
def _swap_player(evt, var, old_user, user):
|
|
||||||
"""Mark the user as no longer being a ghost, if they are one."""
|
|
||||||
_ghosts.discard(old_user)
|
|
||||||
if not old_user.channels:
|
|
||||||
_users.discard(old_user)
|
|
||||||
|
|
||||||
# Can't use @event_listener decorator since src/decorators.py imports us
|
# Can't use @event_listener decorator since src/decorators.py imports us
|
||||||
# (meaning decorator isn't defined at the point in time we are run)
|
# (meaning decorator isn't defined at the point in time we are run)
|
||||||
events.add_listener("cleanup_user", _cleanup_user)
|
events.add_listener("cleanup_user", _cleanup_user)
|
||||||
events.add_listener("reset", _reset)
|
events.add_listener("reset", _reset)
|
||||||
events.add_listener("swap_player", _swap_player, priority=1)
|
|
||||||
|
|
||||||
class User(IRCContext):
|
class User(IRCContext):
|
||||||
|
|
||||||
@ -220,6 +213,10 @@ class User(IRCContext):
|
|||||||
self.account = account
|
self.account = account
|
||||||
self.channels = {}
|
self.channels = {}
|
||||||
self.timestamp = time.time()
|
self.timestamp = time.time()
|
||||||
|
self.sets = []
|
||||||
|
self.lists = []
|
||||||
|
self.dict_keys = []
|
||||||
|
self.dict_values = []
|
||||||
|
|
||||||
if Bot is not None and Bot.nick == nick and {Bot.ident, Bot.host, Bot.realname, Bot.account} == {None}:
|
if Bot is not None and Bot.nick == nick and {Bot.ident, Bot.host, Bot.realname, Bot.account} == {None}:
|
||||||
self = Bot
|
self = Bot
|
||||||
@ -314,6 +311,35 @@ class User(IRCContext):
|
|||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def swap(self, new):
|
||||||
|
"""Swap yourself out with the new user everywhere."""
|
||||||
|
if self is new:
|
||||||
|
return # as far as the caller is aware, we've swapped
|
||||||
|
|
||||||
|
_ghosts.discard(self)
|
||||||
|
if not self.channels:
|
||||||
|
_users.discard(self) # Goodbye, my old friend
|
||||||
|
|
||||||
|
for l in self.lists[:]:
|
||||||
|
while self in l:
|
||||||
|
l[l.index(self)] = new
|
||||||
|
|
||||||
|
for s in self.sets[:]:
|
||||||
|
s.remove(self)
|
||||||
|
s.add(new)
|
||||||
|
|
||||||
|
for dk in self.dict_keys[:]:
|
||||||
|
dk[new] = dk.pop(self)
|
||||||
|
|
||||||
|
for dv in self.dict_values[:]:
|
||||||
|
for key in dv:
|
||||||
|
if dv[key] is self:
|
||||||
|
dv[key] = new
|
||||||
|
|
||||||
|
# It is the containers' reponsibility to properly remove themself from the users
|
||||||
|
# So if any list is non-empty, something went terribly wrong
|
||||||
|
assert not self.lists + self.sets + self.dict_keys + self.dict_values
|
||||||
|
|
||||||
def lower(self):
|
def lower(self):
|
||||||
temp = type(self)(self.client, lower(self.nick), lower(self.ident), lower(self.host, casemapping="ascii"), lower(self.realname), lower(self.account))
|
temp = type(self)(self.client, lower(self.nick), lower(self.ident), lower(self.host, casemapping="ascii"), lower(self.realname), lower(self.account))
|
||||||
if temp is not self: # If everything is already lowercase, we'll get back the same instance
|
if temp is not self: # If everything is already lowercase, we'll get back the same instance
|
||||||
@ -613,7 +639,7 @@ class FakeUser(User):
|
|||||||
|
|
||||||
@rawnick.setter
|
@rawnick.setter
|
||||||
def rawnick(self, rawnick):
|
def rawnick(self, rawnick):
|
||||||
self.nick = parse_rawnick_as_dict(rawnick)["nick"]
|
raise ValueError("may not change the raw nick of a fake user")
|
||||||
|
|
||||||
class BotUser(User): # TODO: change all the 'if x is Bot' for 'if isinstance(x, BotUser)'
|
class BotUser(User): # TODO: change all the 'if x is Bot' for 'if isinstance(x, BotUser)'
|
||||||
|
|
||||||
|
274
src/wolfgame.py
274
src/wolfgame.py
@ -49,6 +49,7 @@ import src.settings as var
|
|||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import db, events, dispatcher, channels, users, hooks, logger, debuglog, errlog, plog
|
from src import db, events, dispatcher, channels, users, hooks, logger, debuglog, errlog, plog
|
||||||
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
|
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
|
||||||
|
from src.containers import UserList, UserSet, UserDict
|
||||||
from src.functions import get_players, get_all_players, get_participants, get_main_role, get_all_roles, get_reveal_role
|
from src.functions import get_players, get_all_players, get_participants, get_main_role, get_all_roles, get_reveal_role
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.warnings import *
|
from src.warnings import *
|
||||||
@ -72,8 +73,8 @@ var.LAST_GOAT = {}
|
|||||||
var.USERS = {}
|
var.USERS = {}
|
||||||
|
|
||||||
var.ADMIN_PINGING = False
|
var.ADMIN_PINGING = False
|
||||||
var.ORIGINAL_ROLES = {} # type: Dict[str, Set[users.User]]
|
var.ORIGINAL_ROLES = UserDict() # type: Dict[str, Set[users.User]]
|
||||||
var.DCED_LOSERS = set() # type: Set[users.User]
|
var.DCED_LOSERS = UserSet() # type: Set[users.User]
|
||||||
var.PLAYERS = {}
|
var.PLAYERS = {}
|
||||||
var.DCED_PLAYERS = {}
|
var.DCED_PLAYERS = {}
|
||||||
var.ADMIN_TO_PING = None
|
var.ADMIN_TO_PING = None
|
||||||
@ -82,6 +83,16 @@ var.PINGING_IFS = False
|
|||||||
var.TIMERS = {}
|
var.TIMERS = {}
|
||||||
var.OLD_MODES = defaultdict(set)
|
var.OLD_MODES = defaultdict(set)
|
||||||
|
|
||||||
|
var.ROLES = UserDict() # type: Dict[str, Set[users.User]]
|
||||||
|
var.MAIN_ROLES = UserDict() # type: Dict[users.User, str]
|
||||||
|
var.ALL_PLAYERS = UserList()
|
||||||
|
|
||||||
|
var.DYING = UserSet()
|
||||||
|
var.DEADCHAT_PLAYERS = UserSet()
|
||||||
|
|
||||||
|
var.SPECTATING_WOLFCHAT = UserSet()
|
||||||
|
var.SPECTATING_DEADCHAT = UserSet()
|
||||||
|
|
||||||
var.ORIGINAL_SETTINGS = {}
|
var.ORIGINAL_SETTINGS = {}
|
||||||
var.CURRENT_GAMEMODE = var.GAME_MODES["default"][0]()
|
var.CURRENT_GAMEMODE = var.GAME_MODES["default"][0]()
|
||||||
|
|
||||||
@ -297,11 +308,9 @@ def reset_modes_timers(var):
|
|||||||
def reset():
|
def reset():
|
||||||
var.PHASE = "none" # "join", "day", or "night"
|
var.PHASE = "none" # "join", "day", or "night"
|
||||||
var.GAME_ID = 0
|
var.GAME_ID = 0
|
||||||
|
var.ALL_PLAYERS.clear()
|
||||||
var.RESTART_TRIES = 0
|
var.RESTART_TRIES = 0
|
||||||
var.DEAD = set()
|
var.DEAD = 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)
|
var.JOINED_THIS_GAME = set() # keeps track of who already joined this game at least once (hostmasks)
|
||||||
var.JOINED_THIS_GAME_ACCS = set() # same, except accounts
|
var.JOINED_THIS_GAME_ACCS = set() # same, except accounts
|
||||||
var.PINGED_ALREADY = set()
|
var.PINGED_ALREADY = set()
|
||||||
@ -321,8 +330,13 @@ def reset():
|
|||||||
var.DCED_PLAYERS.clear()
|
var.DCED_PLAYERS.clear()
|
||||||
var.DISCONNECTED.clear()
|
var.DISCONNECTED.clear()
|
||||||
var.DCED_LOSERS.clear()
|
var.DCED_LOSERS.clear()
|
||||||
var.SPECTATING_WOLFCHAT = set()
|
var.SPECTATING_WOLFCHAT.clear()
|
||||||
var.SPECTATING_DEADCHAT = set()
|
var.SPECTATING_DEADCHAT.clear()
|
||||||
|
|
||||||
|
var.ROLES.clear()
|
||||||
|
var.ORIGINAL_ROLES.clear()
|
||||||
|
var.ROLES["person"] = UserSet()
|
||||||
|
var.MAIN_ROLES.clear()
|
||||||
|
|
||||||
evt = Event("reset", {})
|
evt = Event("reset", {})
|
||||||
evt.dispatch(var)
|
evt.dispatch(var)
|
||||||
@ -582,9 +596,8 @@ def replace(var, wrapper, message):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if users.equals(target.account, wrapper.source.account) and target is not wrapper.source:
|
if users.equals(target.account, wrapper.source.account) and target is not wrapper.source:
|
||||||
evt = Event("swap_player", {})
|
|
||||||
evt.dispatch(var, target, wrapper.source)
|
|
||||||
rename_player(var, wrapper.source, target.nick)
|
rename_player(var, wrapper.source, target.nick)
|
||||||
|
target.swap(wrapper.source)
|
||||||
if var.PHASE in var.GAME_PHASES:
|
if var.PHASE in var.GAME_PHASES:
|
||||||
return_to_village(var, target, show_message=False)
|
return_to_village(var, target, show_message=False)
|
||||||
|
|
||||||
@ -594,19 +607,6 @@ def replace(var, wrapper, message):
|
|||||||
channels.Main.send(messages["player_swap"].format(wrapper.source, target))
|
channels.Main.send(messages["player_swap"].format(wrapper.source, target))
|
||||||
myrole.caller(wrapper.source.client, wrapper.source.nick, wrapper.target.name, "") # FIXME: Old API
|
myrole.caller(wrapper.source.client, wrapper.source.nick, wrapper.target.name, "") # FIXME: Old API
|
||||||
|
|
||||||
@event_listener("swap_player", priority=0)
|
|
||||||
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)
|
|
||||||
for role, players in var.ORIGINAL_ROLES.items():
|
|
||||||
if old_user in players:
|
|
||||||
players.remove(old_user)
|
|
||||||
players.add(user)
|
|
||||||
|
|
||||||
|
|
||||||
@command("pingif", "pingme", "pingat", "pingpref", pm=True)
|
@command("pingif", "pingme", "pingat", "pingpref", pm=True)
|
||||||
def altpinger(var, wrapper, message):
|
def altpinger(var, wrapper, message):
|
||||||
@ -2006,41 +2006,41 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True):
|
|||||||
roles_msg = []
|
roles_msg = []
|
||||||
|
|
||||||
origroles = {} # user-based list of original roles
|
origroles = {} # user-based list of original roles
|
||||||
rolelist = copy.deepcopy(var.ORIGINAL_ROLES)
|
with copy.deepcopy(var.ORIGINAL_ROLES) as rolelist:
|
||||||
for role, playerlist in var.ORIGINAL_ROLES.items():
|
for role, playerlist in var.ORIGINAL_ROLES.items():
|
||||||
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
||||||
continue
|
continue
|
||||||
for p in playerlist:
|
for p in playerlist:
|
||||||
final = var.FINAL_ROLES.get(p.nick, role)
|
final = var.FINAL_ROLES.get(p.nick, role)
|
||||||
if role != final:
|
if role != final:
|
||||||
origroles[p] = role
|
origroles[p] = role
|
||||||
rolelist[role].remove(p)
|
rolelist[role].remove(p)
|
||||||
rolelist[final].add(p)
|
rolelist[final].add(p)
|
||||||
prev = False
|
prev = False
|
||||||
for role in role_order():
|
for role in role_order():
|
||||||
if len(rolelist[role]) == 0:
|
if len(rolelist[role]) == 0:
|
||||||
continue
|
continue
|
||||||
playersformatted = []
|
playersformatted = []
|
||||||
for p in rolelist[role]:
|
for p in rolelist[role]:
|
||||||
if p in origroles and role not in var.TEMPLATE_RESTRICTIONS.keys():
|
if p in origroles and role not in var.TEMPLATE_RESTRICTIONS.keys():
|
||||||
playersformatted.append("\u0002{0}\u0002 ({1}{2})".format(p,
|
playersformatted.append("\u0002{0}\u0002 ({1}{2})".format(p,
|
||||||
"" if prev else "was ", origroles[p]))
|
"" if prev else "was ", origroles[p]))
|
||||||
prev = True
|
prev = True
|
||||||
elif role == "amnesiac":
|
elif role == "amnesiac":
|
||||||
playersformatted.append("\u0002{0}\u0002 (would be {1})".format(p,
|
playersformatted.append("\u0002{0}\u0002 (would be {1})".format(p,
|
||||||
var.AMNESIAC_ROLES[p.nick]))
|
var.AMNESIAC_ROLES[p.nick]))
|
||||||
|
else:
|
||||||
|
playersformatted.append("\u0002{0}\u0002".format(p))
|
||||||
|
if len(rolelist[role]) == 2:
|
||||||
|
msg = "The {1} were {0[0]} and {0[1]}."
|
||||||
|
roles_msg.append(msg.format(playersformatted, plural(role)))
|
||||||
|
elif len(rolelist[role]) == 1:
|
||||||
|
roles_msg.append("The {1} was {0[0]}.".format(playersformatted, role))
|
||||||
else:
|
else:
|
||||||
playersformatted.append("\u0002{0}\u0002".format(p))
|
msg = "The {2} were {0}, and {1}."
|
||||||
if len(rolelist[role]) == 2:
|
roles_msg.append(msg.format(", ".join(playersformatted[0:-1]),
|
||||||
msg = "The {1} were {0[0]} and {0[1]}."
|
playersformatted[-1],
|
||||||
roles_msg.append(msg.format(playersformatted, plural(role)))
|
plural(role)))
|
||||||
elif len(rolelist[role]) == 1:
|
|
||||||
roles_msg.append("The {1} was {0[0]}.".format(playersformatted, role))
|
|
||||||
else:
|
|
||||||
msg = "The {2} were {0}, and {1}."
|
|
||||||
roles_msg.append(msg.format(", ".join(playersformatted[0:-1]),
|
|
||||||
playersformatted[-1],
|
|
||||||
plural(role)))
|
|
||||||
message = ""
|
message = ""
|
||||||
count = 0
|
count = 0
|
||||||
if not abort:
|
if not abort:
|
||||||
@ -2919,8 +2919,7 @@ def return_to_village(var, target, *, show_message, new_user=None):
|
|||||||
|
|
||||||
if new_user is not target:
|
if new_user is not target:
|
||||||
# different users, perform a swap. This will clean up disconnected users.
|
# different users, perform a swap. This will clean up disconnected users.
|
||||||
evt = Event("swap_player", {})
|
target.swap(new_user)
|
||||||
evt.dispatch(var, target, new_user)
|
|
||||||
|
|
||||||
if target.nick != new_user.nick:
|
if target.nick != new_user.nick:
|
||||||
# have a nickchange, update tracking vars
|
# have a nickchange, update tracking vars
|
||||||
@ -2950,7 +2949,7 @@ def rename_player(var, user, prefix):
|
|||||||
nick = user.nick
|
nick = user.nick
|
||||||
|
|
||||||
event = Event("rename_player", {})
|
event = Event("rename_player", {})
|
||||||
event.dispatch(user.client, var, prefix, nick) # FIXME: Need to update all the callbacks
|
event.dispatch(var, prefix, nick)
|
||||||
|
|
||||||
if user in var.ALL_PLAYERS:
|
if user in var.ALL_PLAYERS:
|
||||||
if var.PHASE in var.GAME_PHASES:
|
if var.PHASE in var.GAME_PHASES:
|
||||||
@ -3247,7 +3246,7 @@ def begin_day(cli):
|
|||||||
var.LUCKY = set()
|
var.LUCKY = set()
|
||||||
var.DISEASED = set()
|
var.DISEASED = set()
|
||||||
var.MISDIRECTED = set()
|
var.MISDIRECTED = set()
|
||||||
var.DYING = set()
|
var.DYING.clear()
|
||||||
var.LAST_GOAT.clear()
|
var.LAST_GOAT.clear()
|
||||||
msg = messages["villagers_lynch"].format(botconfig.CMD_CHAR, len(list_players()) // 2 + 1)
|
msg = messages["villagers_lynch"].format(botconfig.CMD_CHAR, len(list_players()) // 2 + 1)
|
||||||
cli.msg(chan, msg)
|
cli.msg(chan, msg)
|
||||||
@ -4488,7 +4487,7 @@ def immunize(cli, nick, chan, rest):
|
|||||||
if check_exchange(cli, nick, victim):
|
if check_exchange(cli, nick, victim):
|
||||||
return
|
return
|
||||||
evt = Event("doctor_immunize", {"success": True, "message": "villager_immunized"})
|
evt = Event("doctor_immunize", {"success": True, "message": "villager_immunized"})
|
||||||
if evt.dispatch(cli, var, nick, victim):
|
if evt.dispatch(var, nick, victim):
|
||||||
pm(cli, nick, messages["doctor_success"].format(victim))
|
pm(cli, nick, messages["doctor_success"].format(victim))
|
||||||
lycan = False
|
lycan = False
|
||||||
if victim in var.DISEASED:
|
if victim in var.DISEASED:
|
||||||
@ -4544,8 +4543,7 @@ def bite_cmd(cli, nick, chan, rest):
|
|||||||
relay_wolfchat_command(cli, nick, messages["alpha_bite_wolfchat"].format(nick, victim), ("alpha wolf",), is_wolf_command=True)
|
relay_wolfchat_command(cli, nick, messages["alpha_bite_wolfchat"].format(nick, victim), ("alpha wolf",), is_wolf_command=True)
|
||||||
debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, get_role(nick), actual, get_role(actual)))
|
debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, get_role(nick), actual, get_role(actual)))
|
||||||
|
|
||||||
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
|
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("turncoat", "warlock"))
|
||||||
roles=("turncoat", "warlock"))
|
|
||||||
def pass_cmd(cli, nick, chan, rest):
|
def pass_cmd(cli, nick, chan, rest):
|
||||||
"""Decline to use your special power for that night."""
|
"""Decline to use your special power for that night."""
|
||||||
nickrole = get_role(nick)
|
nickrole = get_role(nick)
|
||||||
@ -4976,7 +4974,7 @@ def transition_night(cli):
|
|||||||
var.FIRST_NIGHT = (var.NIGHT_COUNT == 1)
|
var.FIRST_NIGHT = (var.NIGHT_COUNT == 1)
|
||||||
|
|
||||||
event_begin = Event("transition_night_begin", {})
|
event_begin = Event("transition_night_begin", {})
|
||||||
event_begin.dispatch(cli, var)
|
event_begin.dispatch(var)
|
||||||
|
|
||||||
if var.DEVOICE_DURING_NIGHT:
|
if var.DEVOICE_DURING_NIGHT:
|
||||||
modes = []
|
modes = []
|
||||||
@ -5381,7 +5379,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
addroles = {}
|
addroles = {}
|
||||||
|
|
||||||
event = Event("role_attribution", {"addroles": addroles})
|
event = Event("role_attribution", {"addroles": addroles})
|
||||||
if event.dispatch(cli, var, chk_win_conditions, villagers):
|
if event.dispatch(var, chk_win_conditions, villagers):
|
||||||
addroles = event.data["addroles"]
|
addroles = event.data["addroles"]
|
||||||
for index in range(len(var.ROLE_INDEX) - 1, -1, -1):
|
for index in range(len(var.ROLE_INDEX) - 1, -1, -1):
|
||||||
if var.ROLE_INDEX[index] <= len(villagers):
|
if var.ROLE_INDEX[index] <= len(villagers):
|
||||||
@ -5438,7 +5436,9 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
for decor in (COMMANDS["join"] + COMMANDS["start"]):
|
for decor in (COMMANDS["join"] + COMMANDS["start"]):
|
||||||
decor(_command_disabled)
|
decor(_command_disabled)
|
||||||
|
|
||||||
var.ROLES = {var.DEFAULT_ROLE: set()} # type: Dict[str, Set[users.User]]
|
var.ROLES.clear()
|
||||||
|
var.ROLES[var.DEFAULT_ROLE] = UserSet()
|
||||||
|
var.MAIN_ROLES.clear()
|
||||||
var.GUNNERS = {}
|
var.GUNNERS = {}
|
||||||
var.OBSERVED = {}
|
var.OBSERVED = {}
|
||||||
var.CLONED = {}
|
var.CLONED = {}
|
||||||
@ -5453,7 +5453,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.DAY_COUNT = 0
|
var.DAY_COUNT = 0
|
||||||
var.DISEASED_WOLVES = False
|
var.DISEASED_WOLVES = False
|
||||||
var.TRAITOR_TURNED = False
|
var.TRAITOR_TURNED = False
|
||||||
var.MAIN_ROLES = {}
|
|
||||||
var.FINAL_ROLES = {}
|
var.FINAL_ROLES = {}
|
||||||
var.ORIGINAL_LOVERS = {}
|
var.ORIGINAL_LOVERS = {}
|
||||||
var.LYCANTHROPES = set()
|
var.LYCANTHROPES = set()
|
||||||
@ -5478,22 +5477,23 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.EXTRA_WOLVES = 0
|
var.EXTRA_WOLVES = 0
|
||||||
var.PRIESTS = set()
|
var.PRIESTS = set()
|
||||||
var.CONSECRATING = set()
|
var.CONSECRATING = set()
|
||||||
var.DYING = set()
|
var.DYING.clear()
|
||||||
var.PRAYED = {}
|
var.PRAYED = {}
|
||||||
|
|
||||||
var.DEADCHAT_PLAYERS = set()
|
var.DEADCHAT_PLAYERS.clear()
|
||||||
var.SPECTATING_WOLFCHAT = set()
|
var.SPECTATING_WOLFCHAT.clear()
|
||||||
var.SPECTATING_DEADCHAT = set()
|
var.SPECTATING_DEADCHAT.clear()
|
||||||
|
|
||||||
for role, count in addroles.items():
|
for role, count in addroles.items():
|
||||||
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
||||||
var.ROLES[role] = [None] * count
|
var.ROLES[role] = [None] * count
|
||||||
continue # We deal with those later, see below
|
continue # We deal with those later, see below
|
||||||
|
|
||||||
selected = random.sample(villagers, count)
|
selected = random.sample(villagers, count)
|
||||||
for x in selected:
|
for x in selected:
|
||||||
var.MAIN_ROLES[users._get(x)] = role # FIXME
|
var.MAIN_ROLES[users._get(x)] = role # FIXME
|
||||||
villagers.remove(x)
|
villagers.remove(x)
|
||||||
var.ROLES[role] = set(users._get(x) for x in selected) # FIXME
|
var.ROLES[role] = UserSet(users._get(x) for x in selected) # FIXME
|
||||||
fixed_count = count - roleset_roles[role]
|
fixed_count = count - roleset_roles[role]
|
||||||
if fixed_count > 0:
|
if fixed_count > 0:
|
||||||
for pr in possible_rolesets:
|
for pr in possible_rolesets:
|
||||||
@ -5523,17 +5523,18 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
if len(possible) < len(var.ROLES[template]):
|
if len(possible) < len(var.ROLES[template]):
|
||||||
cli.msg(chan, messages["not_enough_targets"].format(template))
|
cli.msg(chan, messages["not_enough_targets"].format(template))
|
||||||
if var.ORIGINAL_SETTINGS:
|
if var.ORIGINAL_SETTINGS:
|
||||||
var.ROLES = {"person": set(var.ALL_PLAYERS)}
|
var.ROLES.clear()
|
||||||
|
var.ROLES["person"] = UserSet(var.ALL_PLAYERS)
|
||||||
reset_settings()
|
reset_settings()
|
||||||
cli.msg(chan, messages["default_reset"].format(botconfig.CMD_CHAR))
|
cli.msg(chan, messages["default_reset"].format(botconfig.CMD_CHAR))
|
||||||
var.PHASE = "join"
|
var.PHASE = "join"
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["role_skipped"])
|
cli.msg(chan, messages["role_skipped"])
|
||||||
var.ROLES[template] = set()
|
var.ROLES[template] = UserSet()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var.ROLES[template] = set(users._get(x) for x in random.sample(possible, len(var.ROLES[template]))) # FIXME
|
var.ROLES[template] = UserSet(users._get(x) for x in random.sample(possible, len(var.ROLES[template]))) # FIXME
|
||||||
|
|
||||||
# Handle gunner
|
# Handle gunner
|
||||||
cannot_be_sharpshooter = get_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"])
|
cannot_be_sharpshooter = get_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"])
|
||||||
@ -5550,8 +5551,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
else:
|
else:
|
||||||
var.GUNNERS[gunner.nick] = 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"] = UserSet(p for p in var.ROLES["sharpshooter"] if p is not None)
|
||||||
var.ROLES["sharpshooter"].discard(None)
|
|
||||||
|
|
||||||
with var.WARNING_LOCK: # cancel timers
|
with var.WARNING_LOCK: # cancel timers
|
||||||
for name in ("join", "join_pinger", "start_votes"):
|
for name in ("join", "join_pinger", "start_votes"):
|
||||||
@ -5564,7 +5564,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.LAST_VOTES = None
|
var.LAST_VOTES = None
|
||||||
|
|
||||||
event = Event("role_assignment", {})
|
event = Event("role_assignment", {})
|
||||||
event.dispatch(cli, var, var.CURRENT_GAMEMODE.name, pl[:], restart)
|
event.dispatch(var, var.CURRENT_GAMEMODE.name, get_players())
|
||||||
|
|
||||||
if not restart:
|
if not restart:
|
||||||
gamemode = var.CURRENT_GAMEMODE.name
|
gamemode = var.CURRENT_GAMEMODE.name
|
||||||
@ -5605,7 +5605,9 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
cli.msg(chan, messages["welcome"].format(", ".join(pl), gamemode, options))
|
cli.msg(chan, messages["welcome"].format(", ".join(pl), gamemode, options))
|
||||||
cli.mode(chan, "+m")
|
cli.mode(chan, "+m")
|
||||||
|
|
||||||
var.ORIGINAL_ROLES = copy.deepcopy(var.ROLES) # Make a copy
|
var.ORIGINAL_ROLES.clear()
|
||||||
|
for role, players in var.ROLES.items():
|
||||||
|
var.ORIGINAL_ROLES[role] = players.copy()
|
||||||
|
|
||||||
# Handle amnesiac;
|
# Handle amnesiac;
|
||||||
# matchmaker is blacklisted if AMNESIAC_NIGHTS > 1 due to only being able to act night 1
|
# matchmaker is blacklisted if AMNESIAC_NIGHTS > 1 due to only being able to act night 1
|
||||||
@ -6921,9 +6923,6 @@ if botconfig.DEBUG_MODE:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
wrapper.send("{e.__class__.__name__}: {e}".format(e=e))
|
wrapper.send("{e.__class__.__name__}: {e}".format(e=e))
|
||||||
|
|
||||||
|
|
||||||
if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|
||||||
|
|
||||||
# DO NOT MAKE THIS A PMCOMMAND ALSO
|
# DO NOT MAKE THIS A PMCOMMAND ALSO
|
||||||
@cmd("force", flag="d")
|
@cmd("force", flag="d")
|
||||||
def force(cli, nick, chan, rest):
|
def force(cli, nick, chan, rest):
|
||||||
@ -6987,7 +6986,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
elif who == "gunner":
|
elif who == "gunner":
|
||||||
tgt = {users._get(g) for g in var.GUNNERS.keys()} # FIXME
|
tgt = {users._get(g) for g in var.GUNNERS.keys()} # FIXME
|
||||||
else:
|
else:
|
||||||
tgt = var.ROLES[who].copy()
|
tgt = set(var.ROLES[who])
|
||||||
|
|
||||||
comm = rst.pop(0).lower().replace(botconfig.CMD_CHAR, "", 1)
|
comm = rst.pop(0).lower().replace(botconfig.CMD_CHAR, "", 1)
|
||||||
if comm in COMMANDS and not COMMANDS[comm][0].owner_only:
|
if comm in COMMANDS and not COMMANDS[comm][0].owner_only:
|
||||||
@ -7008,113 +7007,4 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
|
|||||||
else:
|
else:
|
||||||
cli.msg(chan, messages["command_not_found"])
|
cli.msg(chan, messages["command_not_found"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@cmd("frole", flag="d", phases=("day", "night"))
|
|
||||||
def frole(cli, nick, chan, rest):
|
|
||||||
"""Change the role or template of a player."""
|
|
||||||
rst = re.split(" +",rest)
|
|
||||||
if len(rst) < 2:
|
|
||||||
cli.msg(chan, messages["incorrect_syntax"])
|
|
||||||
return
|
|
||||||
who = rst.pop(0).strip()
|
|
||||||
rol = " ".join(rst).strip()
|
|
||||||
ul = list(var.USERS.keys())
|
|
||||||
ull = [u.lower() for u in ul]
|
|
||||||
if who.lower() not in ull:
|
|
||||||
if not is_fake_nick(who):
|
|
||||||
cli.msg(chan, messages["invalid_target"])
|
|
||||||
return
|
|
||||||
if not is_fake_nick(who):
|
|
||||||
who = ul[ull.index(who.lower())]
|
|
||||||
if who == users.Bot.nick or not who:
|
|
||||||
cli.msg(chan, messages["invalid_target"])
|
|
||||||
return
|
|
||||||
pl = list_players()
|
|
||||||
rolargs = re.split("\s*=\s*", rol, 1)
|
|
||||||
rol = rolargs[0]
|
|
||||||
if rol[0] in ("+", "-"):
|
|
||||||
addrem = rol[0]
|
|
||||||
rol = rol[1:]
|
|
||||||
is_gunner = (rol == "gunner" or rol == "sharpshooter")
|
|
||||||
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:
|
|
||||||
var.GUNNERS[who] = int(rolargs[1])
|
|
||||||
else:
|
|
||||||
var.GUNNERS[who] = 999
|
|
||||||
elif rol == "gunner":
|
|
||||||
var.GUNNERS[who] = math.ceil(var.SHOTS_MULTIPLIER * len(pl))
|
|
||||||
else:
|
|
||||||
var.GUNNERS[who] = math.ceil(var.SHARPSHOOTER_MULTIPLIER * len(pl))
|
|
||||||
if who not in pl:
|
|
||||||
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(users._get(who)) # FIXME
|
|
||||||
evt = Event("frole_template", {})
|
|
||||||
evt.dispatch(cli, var, addrem, who, rol, rolargs)
|
|
||||||
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:
|
|
||||||
del var.GUNNERS[who]
|
|
||||||
else:
|
|
||||||
cli.msg(chan, messages["improper_template_mod"])
|
|
||||||
return
|
|
||||||
elif rol in var.TEMPLATE_RESTRICTIONS.keys():
|
|
||||||
cli.msg(chan, messages["template_mod_syntax"].format(rol))
|
|
||||||
return
|
|
||||||
elif rol in var.ROLES:
|
|
||||||
oldrole = None
|
|
||||||
if who in pl:
|
|
||||||
oldrole = get_role(who)
|
|
||||||
change_role(users._get(who), oldrole, rol) # FIXME
|
|
||||||
else:
|
|
||||||
var.ALL_PLAYERS.append(users._get(who)) # FIXME
|
|
||||||
var.ROLES[rol].add(users._get(who)) # FIXME
|
|
||||||
var.MAIN_ROLES[users._get(who)] = rol # FIXME
|
|
||||||
var.ORIGINAL_ROLES[rol].add(users._get(who)) # FIXME
|
|
||||||
evt = Event("frole_role", {})
|
|
||||||
evt.dispatch(cli, var, who, rol, oldrole, rolargs)
|
|
||||||
if rol == "amnesiac":
|
|
||||||
if len(rolargs) == 2 and rolargs[1] in var.ROLES:
|
|
||||||
var.AMNESIAC_ROLES[who] = rolargs[1]
|
|
||||||
else:
|
|
||||||
# Pick amnesiac role like normal
|
|
||||||
amnroles = var.ROLE_GUIDE.keys() - {var.DEFAULT_ROLE, "amnesiac", "clone", "traitor"}
|
|
||||||
if var.AMNESIAC_NIGHTS > 1 and "matchmaker" in amnroles:
|
|
||||||
amnroles.remove("matchmaker")
|
|
||||||
for nope in var.AMNESIAC_BLACKLIST:
|
|
||||||
amnroles.discard(nope)
|
|
||||||
for nope in var.TEMPLATE_RESTRICTIONS.keys():
|
|
||||||
amnroles.discard(nope)
|
|
||||||
var.AMNESIAC_ROLES[who] = random.choice(list(amnroles))
|
|
||||||
if not is_fake_nick(who):
|
|
||||||
cli.mode(chan, "+v", who)
|
|
||||||
else:
|
|
||||||
cli.msg(chan, messages["invalid_role"])
|
|
||||||
return
|
|
||||||
cli.msg(chan, messages["operation_successful"])
|
|
||||||
# default stats determination does not work if we're mucking with !frole
|
|
||||||
if var.STATS_TYPE == "default":
|
|
||||||
var.ORIGINAL_SETTINGS["STATS_TYPE"] = var.STATS_TYPE
|
|
||||||
var.STATS_TYPE = "accurate"
|
|
||||||
|
|
||||||
cli.msg(chan, messages["stats_accurate"].format(botconfig.CMD_CHAR))
|
|
||||||
chk_win()
|
|
||||||
|
|
||||||
|
|
||||||
if botconfig.ALLOWED_NORMAL_MODE_COMMANDS and not botconfig.DEBUG_MODE:
|
|
||||||
for comd in list(COMMANDS.keys()):
|
|
||||||
if (comd not in before_debug_mode_commands and
|
|
||||||
comd not in botconfig.ALLOWED_NORMAL_MODE_COMMANDS):
|
|
||||||
del COMMANDS[comd]
|
|
||||||
|
|
||||||
# vim: set sw=4 expandtab:
|
# vim: set sw=4 expandtab:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user