banned/src/roles/amnesiac.py
skizzerz 56f2bacd3a Amnesiac fixes and redo stop_game readout logic
- Account for revealing totem + amnesiac in experimental !stats properly
- Fix amnesiac blacklist checks to be consistent with each other
- Remove non-events from villager.py -- these always ran before or after
  all other events, so there was no point in them being events in the
  first place
- stop_game now follows the mainroles/allroles pattern instead of
  roles/templates pattern. This also modifies the data stored in db
  stats, and fixes readouts for cases where we do goofy stuff with
  secondary roles
2018-04-23 23:11:02 -05:00

149 lines
6.2 KiB
Python

import re
import random
import itertools
import math
from collections import defaultdict
import botconfig
from src.utilities import *
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, is_known_wolf_ally
from src.decorators import command, event_listener
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
from src.messages import messages
from src.events import Event
ROLES = UserDict() # type: Dict[users.User, str]
STATS_FLAG = False # if True, we begin accounting for amnesiac in update_stats
def _get_blacklist(var):
# matchmaker is blacklisted if AMNESIAC_NIGHTS > 1 due to only being able to act night 1.
# clone and traitor are blacklisted due to assumptions made in default !stats computations.
# If you remove these from the blacklist you will need to modify the default !stats logic
# chains in order to correctly account for these. As a forewarning, such modifications are
# nontrivial and will likely require a great deal of thought (and likely new tracking vars)
# FIXME: once experimental stats become the new stats, clone and traitor will work properly
# and we can remove those from hardcoded blacklist and remove this comment block.
blacklist = var.TEMPLATE_RESTRICTIONS.keys() | var.AMNESIAC_BLACKLIST | {var.DEFAULT_ROLE, "amnesiac", "clone", "traitor"}
if var.AMNESIAC_NIGHTS > 1:
blacklist.add("matchmaker")
return blacklist
@event_listener("role_assignment")
def on_role_assignment(evt, var, gamemode, pl):
roles = var.ROLE_GUIDE.keys() - _get_blacklist(var)
for amnesiac in get_all_players(("amnesiac",)):
ROLES[amnesiac] = random.choice(list(roles))
@event_listener("transition_night_begin")
def on_transition_night_begin(evt, var):
global STATS_FLAG
if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
amnesiacs = get_all_players(("amnesiac",))
if amnesiacs and not var.HIDDEN_AMNESIAC:
STATS_FLAG = True
for amn in amnesiacs:
role = ROLES[amn]
change_role(amn, "amnesiac", role)
evt = Event("new_role", {})
evt.dispatch(var, amn, role)
if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away
continue
showrole = role
if showrole in var.HIDDEN_VILLAGERS:
showrole = "villager"
elif showrole in var.HIDDEN_ROLES:
showrole = var.DEFAULT_ROLE
a = "a"
if showrole.startswith(("a", "e", "i", "o", "u")):
a = "an"
amn.send(messages["amnesia_clear"].format(a, showrole))
if is_known_wolf_ally(amn, amn):
if role in var.WOLF_ROLES:
relay_wolfchat_command(amn.client, amn.nick, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
else:
relay_wolfchat_command(amn.client, amn.nick, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLFCHAT_ROLES)
debuglog("{0} REMEMBER: {1} as {2}".format(amn, role, showrole))
@event_listener("new_role")
def on_new_role(evt, var, user, role):
if role == "turncoat": # FIXME: Need to split into turncoat.py when split
var.TURNCOATS[user.nick] = ("none", -1)
if role == "doctor": # FIXME: Need to split into doctor.py when split
var.DOCTORS[user.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(get_players()))
@event_listener("investigate")
def on_investigate(evt, var, actor, target):
if evt.data["role"] == "amnesiac":
evt.data["role"] = ROLES[target]
@event_listener("exchange_roles")
def on_exchange_roles(evt, var, actor, target, actor_role, target_role):
# FIXME: exchange totem messes with var.HIDDEN_AMNESIAC (the new amnesiac is no longer hidden should they die)
if actor_role == "amnesiac":
actor_role = ROLES[actor]
if target in ROLES:
ROLES[actor] = ROLES[target]
ROLES[target] = actor_role
else:
del ROLES[actor]
ROLES[target] = actor_role
if target_role == "amnesiac":
if actor not in ROLES:
target_role = ROLES[target]
ROLES[actor] = target_role
del ROLES[target]
else: # we swapped amnesiac_roles earlier on, get our version back
target_role = ROLES[actor]
evt.data["actor_role"] = actor_role
evt.data["target_role"] = target_role
@event_listener("revealing_totem")
def on_revealing_totem(evt, var, votee):
if evt.data["role"] not in _get_blacklist(var) and not var.HIDDEN_AMNESIAC and len(var.ORIGINAL_ROLES["amnesiac"]):
global STATS_FLAG
STATS_FLAG = True
if evt.data["role"] == "amnesiac":
role = ROLES[votee]
change_role(votee, "amnesiac", role)
votee.send(messages["totem_amnesia_clear"])
nevt = Event("new_role", {})
nevt.dispatch(var, votee, role)
evt.data["role"] = role
# If wolfteam, don't bother giving list of wolves since night is about to start anyway
# Existing wolves also know that someone just joined their team because revealing totem says what they are
@event_listener("get_reveal_role")
def on_reveal_role(evt, var, user):
if var.HIDDEN_AMNESIAC and var.ORIGINAL_MAIN_ROLES[user] == "amnesiac":
evt.data["role"] = "amnesiac"
@event_listener("get_endgame_message")
def on_get_endgame_message(evt, var, player, role, is_mainrole):
if role == "amnesiac":
# FIXME: Harcoded English
evt.data["message"].append("would be {0}".format(ROLES[player]))
@event_listener("revealroles_role")
def on_revealroles_role(evt, var, user, role):
if role == "amnesiac":
evt.data["special_case"].append("will become {0}".format(ROLES[user]))
@event_listener("update_stats")
def on_update_stats(evt, var, player, mainrole, revealrole, allroles):
if STATS_FLAG and not _get_blacklist(var) & {mainrole, revealrole}:
evt.data["possible"].add("amnesiac")
@event_listener("reset")
def on_reset(evt, var):
global STATS_FLAG
ROLES.clear()
STATS_FLAG = False
# vim: set sw=4 expandtab: