Split and convert amnesiac

This commit is contained in:
Vgr E. Barry 2018-04-23 20:27:00 -04:00
parent 38721fd59b
commit 1a446205ce
15 changed files with 206 additions and 150 deletions

View File

@ -441,7 +441,7 @@
"harlot_turn": "While out visiting last night, you were overpowered by a large werewolf and bitten. Shortly thereafter, you found yourself turning into a werewolf yourself!",
"bitten_turn": "You woke suddenly last night to a sharp pain, as you were bit by a large werewolf. Shortly thereafter, you found yourself turning into a werewolf yourself!",
"wolfchat_new_member": "\u0002{0}\u0002 is now a \u0002{1}\u0002!",
"amnesia_clear": "Your amnesia clears and you now remember that you are a{0} \u0002{1}\u0002!",
"amnesia_clear": "Your amnesia clears and you now remember that you are {0} \u0002{1}\u0002!",
"amnesia_wolfchat": "\u0002{0}\u0002 is now a \u0002{1}\u0002!",
"wolf_notify": "You are a \u0002{0}wolf\u0002. It is your job to kill all the villagers. Use \"kill <nick>\" to kill a villager.",
"cursed_traitor_notify": "You are a \u0002{0}cursed traitor\u0002. Normally, you would be seen as a villager by the seer and oracle, but since you're cursed, you are seen as a wolf.",

View File

@ -83,13 +83,10 @@ def get_all_roles(user):
return {role for role, users in var.ROLES.items() if user in users}
def get_reveal_role(user):
# FIXME: when amnesiac and clone are split, move this into an event
if var.HIDDEN_AMNESIAC and user in var.ORIGINAL_ROLES["amnesiac"]:
role = "amnesiac"
elif var.HIDDEN_CLONE and user in var.ORIGINAL_ROLES["clone"]:
# FIXME: when clone is split, move this into an event
role = get_main_role(user)
if var.HIDDEN_CLONE and user in var.ORIGINAL_ROLES["clone"]:
role = "clone"
else:
role = get_main_role(user)
evt = Event("get_reveal_role", {"role": role})
evt.dispatch(var, user)

View File

@ -81,7 +81,7 @@ class GameMode:
elif val == "team" and not hasattr(self, "STATS_TYPE"):
self.STATS_TYPE = "team"
elif key in ("stats type", "stats"):
if val not in ("default", "accurate", "team", "disabled"):
if val not in ("default", "accurate", "team", "disabled", "experimental"):
raise InvalidModeException(messages["invalid_stats"].format(val))
self.STATS_TYPE = val
elif key == "abstain":
@ -184,7 +184,7 @@ class DefaultMode(GameMode):
if len(evt.data["votelist"][users.Bot]) == len(set(evt.params.voters) - evt.data["not_lynching"]):
channels.Main.send(messages["villagergame_nope"])
from src.wolfgame import stop_game
stop_game("wolves")
stop_game(var, "wolves")
evt.prevent_default = True
else:
del evt.data["votelist"][users.Bot]
@ -289,7 +289,7 @@ class VillagergameMode(GameMode):
if len(evt.data["votelist"][users.Bot]) == len(set(evt.params.voters) - evt.data["not_lynching"]):
channels.Main.send(messages["villagergame_win"])
from src.wolfgame import stop_game
stop_game("everyone")
stop_game(var, "everyone")
evt.prevent_default = True
else:
del evt.data["votelist"][users.Bot]

View File

@ -66,7 +66,7 @@ def setup_variables(rolename, *, knows_totem, get_tags):
SHAMANS.clear()
@event_listener("revealroles_role")
def on_revealroles(evt, var, wrapper, user, role):
def on_revealroles(evt, var, user, role):
if role == rolename and user in TOTEMS:
if user in SHAMANS:
evt.data["special_case"].append("giving {0} totem to {1}".format(TOTEMS[user], SHAMANS[user][0]))
@ -302,17 +302,6 @@ def on_chk_decision_lynch3(evt, var, voters):
rev_evt = Event("revealing_totem", {"role": role})
rev_evt.dispatch(var, votee)
role = rev_evt.data["role"]
# TODO: once amnesiac is split, roll this into the revealing_totem event
if role == "amnesiac":
role = var.AMNESIAC_ROLES[votee.nick]
change_role(votee, "amnesiac", role)
var.AMNESIACS.add(votee.nick)
votee.send(messages["totem_amnesia_clear"])
# 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
# If turncoat, set their initial starting side to "none" just in case game ends before they can set it themselves
if role == "turncoat":
var.TURNCOATS[votee.nick] = ("none", -1)
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
channels.Main.send(messages["totem_reveal"].format(votee, an, role))

134
src/roles/amnesiac.py Normal file
View File

@ -0,0 +1,134 @@
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]
@event_listener("role_assignment")
def on_role_assignment(evt, var, gamemode, pl):
# 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)
roles = var.ROLE_GUIDE.keys() - var.TEMPLATE_RESTRICTIONS.keys() - var.AMNESIAC_BLACKLIST - {var.DEFAULT_ROLE, "amnesiac", "clone", "traitor"}
if var.AMNESIAC_NIGHTS > 1 and "matchmaker" in roles:
roles.remove("matchmaker")
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):
if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
amnesiacs = get_all_players(("amnesiac",))
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):
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"] == "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 user in var.ORIGINAL_ROLES["amnesiac"]:
evt.data["role"] = "amnesiac"
@event_listener("get_endgame_message")
def on_get_endgame_message(evt, var, role, players, original_roles):
if role == "amnesiac":
for player in players:
evt.data["message"].append("\u0002{0}\u0002 (would be {1})".format(player, ROLES[player]))
evt.stop_processing = True
@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 not var.HIDDEN_AMNESIAC and var.NIGHT_COUNT >= var.AMNESIAC_NIGHTS:
if not var.AMNESIAC_BLACKLIST & {mainrole, revealrole}: # make sure roles aren't blacklisted
evt.data["possible"].add("amnesiac")
@event_listener("reset")
def on_reset(evt, var):
ROLES.clear()
# vim: set sw=4 expandtab:

View File

@ -33,9 +33,6 @@ def see(var, wrapper, message):
targrole = get_main_role(target)
trole = targrole # keep a copy for logging
if targrole == "amnesiac":
targrole = var.AMNESIAC_ROLES[target.nick]
evt = Event("investigate", {"role": targrole})
evt.dispatch(var, wrapper.source, target)
targrole = evt.data["role"]

View File

@ -31,9 +31,6 @@ def investigate(var, wrapper, message):
target = evt.data["target"]
targrole = get_main_role(target)
if targrole == "amnesiac":
targrole = var.AMNESIAC_ROLES[target.nick]
evt = Event("investigate", {"role": targrole})
evt.dispatch(var, wrapper.source, target)
targrole = evt.data["role"]

View File

@ -199,7 +199,7 @@ def on_myrole(evt, var, user):
evt.data["messages"].append(messages["dullahan_targets_dead"])
@event_listener("revealroles_role")
def on_revealroles_role(evt, var, wrapper, user, role):
def on_revealroles_role(evt, var, user, role):
if role == "dullahan" and user in TARGETS:
targets = set(TARGETS[user])
for target in TARGETS[user]:

View File

@ -51,11 +51,6 @@ def investigate(var, wrapper, message):
t1role = get_main_role(target1)
t2role = get_main_role(target2)
# FIXME: split into amnesiac via investigate event once amnesiac is split
if t1role == "amnesiac":
t1role = var.AMNESIAC_ROLES[target1.nick]
if t2role == "amnesiac":
t2role = var.AMNESIAC_ROLES[target2.nick]
evt = Event("investigate", {"role": t1role})
evt.dispatch(var, wrapper.source, target1)

View File

@ -169,7 +169,7 @@ def on_myrole(evt, var, user):
evt.data["messages"].append(messages["mad_scientist_myrole_targets"].format(target1, target2))
@event_listener("revealroles_role")
def on_revealroles(evt, var, wrapper, user, role):
def on_revealroles(evt, var, user, role):
if role == "mad scientist":
pl = get_players()
target1, target2 = _get_targets(var, pl, user)

View File

@ -316,6 +316,12 @@ def on_vg_kill(evt, var, ghost, target):
if ghost in ENTRANCED:
evt.data["pl"] -= get_all_players(("succubus",))
@event_listener("new_role")
def on_new_role(evt, var, user, role):
if role == "succubus" and user in ENTRANCED:
ENTRANCED.remove(user)
user.send(messages["no_longer_entranced"])
@event_listener("reset")
def on_reset(evt, var):
global ALL_SUCC_IDLE

View File

@ -22,7 +22,7 @@ def on_get_reveal_role(evt, var, user):
evt.data["role"] = var.DEFAULT_ROLE
@event_listener("get_final_role")
def on_get_final_role(evt, cli, var, nick, role):
def on_get_final_role(evt, var, user, role):
# if a traitor turns we want to show them as traitor in the end game readout
# instead of "wolf (was traitor)"
if role == "traitor" and evt.data["role"] == "wolf":

View File

@ -68,4 +68,18 @@ def on_chk_win(evt, var, rolemap, mainroles, lpl, lwolves, lrealwolves):
evt.data["winner"] = "wolves"
evt.data["message"] = messages["wolf_win_greater"]
@event_listener("get_final_role", priority=0)
def on_get_final_role(evt, var, user, role):
if user.nick in var.FINAL_ROLES:
evt.data["role"] = var.FINAL_ROLES[user.nick]
@event_listener("get_endgame_message", priority=10)
def on_get_endgame_message(evt, var, role, players, original_roles):
for player in players:
if player in original_roles and role not in var.TEMPLATE_RESTRICTIONS:
evt.data["message"].append("\u0002{0}\u0002 ({1}{2})".format(player, "" if evt.data["done"] else "was ", original_roles[player]))
evt.data["done"] = True
else:
evt.data["message"].append("\u0002{0}\u0002".format(player))
# vim: set sw=4 expandtab:

View File

@ -148,7 +148,7 @@ def on_transition_night_end(evt, var):
child.send(messages[to_send])
@event_listener("revealroles_role")
def on_revealroles_role(evt, var, wrapper, user, role):
def on_revealroles_role(evt, var, user, role):
if role == "wild child":
if user.nick in IDOLS:
evt.data["special_case"].append("picked {0} as idol".format(IDOLS[user.nick]))

View File

@ -403,7 +403,7 @@ def forced_exit(var, wrapper, message):
if var.PHASE in var.GAME_PHASES:
if var.PHASE == "join" or force or wrapper.source.nick == "<console>":
stop_game(log=False)
stop_game(var, log=False)
else:
wrapper.pm(messages["stop_bot_ingame_safeguard"].format(
what="stop", cmd="fdie", prefix=botconfig.CMD_CHAR))
@ -448,7 +448,7 @@ def restart_program(var, wrapper, message):
if var.PHASE in var.GAME_PHASES:
if var.PHASE == "join" or force:
stop_game(log=False)
stop_game(var, log=False)
else:
wrapper.pm(messages["stop_bot_ingame_safeguard"].format(
what="restart", cmd="frestart", prefix=botconfig.CMD_CHAR))
@ -1963,7 +1963,7 @@ def show_votes(cli, nick, chan, rest):
reply(cli, nick, chan, the_message)
def stop_game(winner="", abort=False, additional_winners=None, log=True):
def stop_game(var, winner="", abort=False, additional_winners=None, log=True):
if abort:
channels.Main.send(messages["role_attribution_failed"])
if var.DAY_START_TIME:
@ -1994,36 +1994,31 @@ def stop_game(winner="", abort=False, additional_winners=None, log=True):
if role in var.TEMPLATE_RESTRICTIONS.keys():
continue
for p in playerlist:
final = var.FINAL_ROLES.get(p.nick, role)
if role != final:
# The final role is set at priority 0, other roles can override that
evt = Event("get_final_role", {"role": role})
evt.dispatch(var, p, role)
if role != evt.data["role"]:
origroles[p] = role
rolelist[role].remove(p)
rolelist[final].add(p)
prev = False
rolelist[evt.data["role"]].add(p)
done = False
for role in role_order():
if len(rolelist[role]) == 0:
continue
playersformatted = []
for p in rolelist[role]:
if p in origroles and role not in var.TEMPLATE_RESTRICTIONS.keys():
playersformatted.append("\u0002{0}\u0002 ({1}{2})".format(p,
"" if prev else "was ", origroles[p]))
prev = True
elif role == "amnesiac":
playersformatted.append("\u0002{0}\u0002 (would be {1})".format(p,
var.AMNESIAC_ROLES[p.nick]))
else:
playersformatted.append("\u0002{0}\u0002".format(p))
evt = Event("get_endgame_message", {"message": [], "done": done})
evt.dispatch(var, role, rolelist[role], origroles)
msg = evt.data["message"]
done = evt.data["done"]
if len(rolelist[role]) == 2:
msg = "The {1} were {0[0]} and {0[1]}."
roles_msg.append(msg.format(playersformatted, plural(role)))
roles_msg.append("The {1} were {0[0]} and {0[1]}.".format(msg, plural(role)))
elif len(rolelist[role]) == 1:
roles_msg.append("The {1} was {0[0]}.".format(playersformatted, role))
roles_msg.append("The {1} was {0[0]}.".format(msg, role))
else:
msg = "The {2} were {0}, and {1}."
roles_msg.append(msg.format(", ".join(playersformatted[0:-1]),
playersformatted[-1],
plural(role)))
roles_msg.append("The {2} were {0}, and {1}.".format(", ".join(msg[0:-1]), msg[-1], plural(role)))
message = ""
count = 0
if not abort:
@ -2339,7 +2334,7 @@ def chk_win_conditions(rolemap, mainroles, end_game=True, winner=None):
if end_game:
debuglog("WIN:", winner)
channels.Main.send(message)
stop_game(winner, additional_winners=event.data["additional_winners"])
stop_game(var, winner, additional_winners=event.data["additional_winners"])
return True
@handle_error
@ -2390,8 +2385,9 @@ def del_player(player, *, devoice=True, end_game=True, death_triggers=True, kill
# clone does NOT get any of nick's templates (gunner/assassin/etc.)
del var.CLONED[clone.nick]
if mainrole == "amnesiac":
from src.roles.amnesiac import ROLES
# clone gets the amnesiac's real role
sayrole = var.AMNESIAC_ROLES[player.nick]
sayrole = ROLES[player]
else:
sayrole = mainrole
change_role(clone, "clone", sayrole)
@ -2970,7 +2966,7 @@ def rename_player(var, user, prefix):
if prefix in dictvar.keys():
del dictvar[prefix]
for dictvar in (var.FINAL_ROLES, var.TURNCOATS,
var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES, var.AMNESIAC_ROLES):
var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES):
if prefix in dictvar.keys():
dictvar[nick] = dictvar.pop(prefix)
# defaultdict(list), where keys are nicks and items in list do not matter
@ -2999,7 +2995,7 @@ def rename_player(var, user, prefix):
b = nick
var.EXCHANGED_ROLES[idx] = (a, b)
for setvar in (var.HEXED, var.SILENCED, var.MATCHMAKERS, var.PASSED,
var.JESTERS, var.AMNESIACS, var.LYCANTHROPES, var.LUCKY, var.DISEASED,
var.JESTERS, var.LYCANTHROPES, var.LUCKY, var.DISEASED,
var.MISDIRECTED, var.EXCHANGED, var.IMMUNIZED, var.CURED_LYCANS,
var.ALPHA_WOLVES, var.CURSED, var.PRIESTS):
if prefix in setvar:
@ -3919,15 +3915,7 @@ def check_exchange(cli, actor, nick):
# var.PASSED is used by many roles
var.PASSED.discard(actor)
if actor_role == "amnesiac":
actor_role = var.AMNESIAC_ROLES[actor]
if nick in var.AMNESIAC_ROLES:
var.AMNESIAC_ROLES[actor] = var.AMNESIAC_ROLES[nick]
var.AMNESIAC_ROLES[nick] = actor_role
else:
del var.AMNESIAC_ROLES[actor]
var.AMNESIAC_ROLES[nick] = actor_role
elif actor_role == "clone":
if actor_role == "clone":
if actor in var.CLONED:
actor_target = var.CLONED.pop(actor)
elif actor_role in ("werecrow", "sorcerer"):
@ -3955,14 +3943,7 @@ def check_exchange(cli, actor, nick):
# var.PASSED is used by many roles
var.PASSED.discard(nick)
if nick_role == "amnesiac":
if actor not in var.AMNESIAC_ROLES:
nick_role = var.AMNESIAC_ROLES[nick]
var.AMNESIAC_ROLES[actor] = nick_role
del var.AMNESIAC_ROLES[nick]
else: # we swapped amnesiac_roles earlier on, get our version back
nick_role = var.AMNESIAC_ROLES[actor]
elif nick_role == "clone":
if nick_role == "clone":
if nick in var.CLONED:
nick_target = var.CLONED.pop(nick)
elif nick_role in ("werecrow", "sorcerer"):
@ -3985,9 +3966,12 @@ def check_exchange(cli, actor, nick):
elif nick_role == "turncoat":
del var.TURNCOATS[nick]
evt = Event("exchange_roles", {"actor_messages": [], "target_messages": []})
evt = Event("exchange_roles", {"actor_messages": [], "target_messages": [], "actor_role": actor_role, "target_role": nick_role})
evt.dispatch(var, user, target, actor_role, nick_role)
actor_role = evt.data["actor_role"]
nick_role = evt.data["target_role"]
change_role(user, actor_role, nick_role)
change_role(target, nick_role, actor_role)
if actor in var.BITTEN_ROLES.keys():
@ -4300,7 +4284,8 @@ def observe(cli, nick, chan, rest):
elif role == "sorcerer":
vrole = get_role(victim)
if vrole == "amnesiac":
vrole = var.AMNESIAC_ROLES[victim]
from src.roles.amnesiac import ROLES
vrole = ROLES[users._get(victim)] # FIXME
if vrole in ("seer", "oracle", "augur", "sorcerer"):
an = "n" if vrole.startswith(("a", "e", "i", "o", "u")) else ""
pm(cli, nick, (messages["sorcerer_success"]).format(victim, an, vrole))
@ -4341,12 +4326,13 @@ def pray(cli, nick, chan, rest):
# (amnesiacs are special since they're also listed as amnesiac; that way a prophet can see both who the
# amnesiacs themselves are as well as what they'll become)
pl = list_players()
valid_roles = set(r for r, p in var.ROLES.items() if p) | set(r for p, r in var.AMNESIAC_ROLES.items() if p in pl)
from src.roles.amnesiac import ROLES
valid_roles = {r for r, p in var.ROLES.items() if p} | {r for p, r in ROLES.items() if p.nick in pl} # FIXME
if role in valid_roles:
# this sees through amnesiac, so the amnesiac's final role counts as their role
# also, if we're the only person with that role, say so and don't allow a second vision
people = set(get_roles(role)) | set(p for p, r in var.AMNESIAC_ROLES.items() if p in pl and r == role) # FIXME
people = set(get_roles(role)) | {p.nick for p, r in ROLES.items() if p.nick in pl and r == role} # FIXME
if len(people) == 1 and nick in people:
pm(cli, nick, messages["vision_only_role_self"].format(role))
var.PRAYED[nick][0] = 2
@ -4963,42 +4949,6 @@ def transition_night():
t2.daemon = True
t2.start()
# convert amnesiac
if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
amns = get_roles("amnesiac") # FIXME: not user aware, needs to eventually be a copy of var.ROLES["amnesiac"]
for amn in amns:
event = Event("amnesiac_turn", {})
if event.dispatch(var, amn, var.AMNESIAC_ROLES[amn]):
amnrole = var.AMNESIAC_ROLES[amn]
amnuser = users._get(amn) # FIXME
change_role(amnuser, "amnesiac", amnrole)
var.AMNESIACS.add(amn)
# TODO: turn into event when amnesiac is split
from src.roles import succubus
if amnrole == "succubus" and amnuser in succubus.ENTRANCED:
succubus.ENTRANCED.remove(amnuser)
amnuser.send(messages["no_longer_entranced"])
if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away
continue
showrole = amnrole
if showrole in var.HIDDEN_VILLAGERS:
showrole = "villager"
elif showrole in var.HIDDEN_ROLES:
showrole = var.DEFAULT_ROLE
n = ""
if showrole.startswith(("a", "e", "i", "o", "u")):
n = "n"
amnuser.send(messages["amnesia_clear"].format(n, showrole))
if in_wolflist(amn, amn):
if amnrole in var.WOLF_ROLES:
relay_wolfchat_command(amnuser.client, amn, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
else:
relay_wolfchat_command(amnuser.client, amn, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLFCHAT_ROLES)
elif amnrole == "turncoat":
var.TURNCOATS[amn] = ("none", -1)
debuglog("{0} REMEMBER: {1} as {2}".format(amn, amnrole, showrole))
if var.FIRST_NIGHT and chk_win(end_game=False): # prevent game from ending as soon as it begins (useful for the random game mode)
start(channels.Main.client, users.Bot.nick, channels.Main.name, restart=var.CURRENT_GAMEMODE.name)
return
@ -5227,7 +5177,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
if restart:
var.RESTART_TRIES += 1
if var.RESTART_TRIES > 3:
stop_game(abort=True)
stop_game(var, abort=True)
return
if not restart:
@ -5390,7 +5340,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.SILENCED = set()
var.TOBESILENCED = set()
var.JESTERS = set()
var.AMNESIACS = set()
var.NIGHT_COUNT = 0
var.DAY_COUNT = 0
var.DISEASED_WOLVES = False
@ -5412,7 +5361,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.BITE_PREFERENCES = {}
var.BITTEN_ROLES = {}
var.LYCAN_ROLES = {}
var.AMNESIAC_ROLES = {}
var.ACTIVE_PROTECTIONS = defaultdict(list)
var.TURNCOATS = {}
var.EXCHANGED_ROLES = []
@ -5566,28 +5514,9 @@ def start(cli, nick, chan, forced = False, restart = ""):
for role, players in var.ROLES.items():
var.ORIGINAL_ROLES[role] = players.copy()
# Handle amnesiac;
# 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)
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)
for amnesiac in var.ROLES["amnesiac"]:
var.AMNESIAC_ROLES[amnesiac.nick] = random.choice(list(amnroles)) # FIXME
# Handle doctor
for doctor in var.ROLES["doctor"]:
var.DOCTORS[doctor.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(pl)) # FIXME
for amn in var.AMNESIAC_ROLES:
if var.AMNESIAC_ROLES[amn] == "doctor":
var.DOCTORS[amn] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(pl))
var.DAY_TIMEDELTA = timedelta(0)
var.NIGHT_TIMEDELTA = timedelta(0)
@ -5861,7 +5790,7 @@ def reset_game(cli, nick, chan, rest):
else:
cli.msg(botconfig.CHANNEL, messages["fstop_success"].format(nick))
if var.PHASE != "join":
stop_game(log=False)
stop_game(var, log=False)
else:
pl = [p for p in list_players() if not is_fake_nick(p)]
reset_modes_timers(var)
@ -6599,7 +6528,7 @@ def update(var, wrapper, message):
if var.PHASE in var.GAME_PHASES:
if var.PHASE == "join" or force:
stop_game(log=False)
stop_game(var, log=False)
else:
wrapper.pm(messages["stop_bot_ingame_safeguard"].format(
what="restart", cmd="update", prefix=botconfig.CMD_CHAR), private=True)
@ -6759,8 +6688,6 @@ def revealroles(var, wrapper, message):
special_case.append("targeting {0}".format(var.TARGETED[user.nick]))
elif role == "clone" and user.nick in var.CLONED:
special_case.append("cloning {0}".format(var.CLONED[user.nick]))
elif role == "amnesiac" and user.nick in var.AMNESIAC_ROLES:
special_case.append("will become {0}".format(var.AMNESIAC_ROLES[user.nick]))
# print how many bullets normal gunners have
elif (role == "gunner" or role == "sharpshooter") and user in var.GUNNERS:
special_case.append("{0} bullet{1}".format(var.GUNNERS[user], "" if var.GUNNERS[user] == 1 else "s"))
@ -6769,7 +6696,7 @@ def revealroles(var, wrapper, message):
if var.TURNCOATS[user.nick][0] != "none" else "not currently on any side")
evt = Event("revealroles_role", {"special_case": special_case})
evt.dispatch(var, wrapper, user, role)
evt.dispatch(var, user, role)
special_case = evt.data["special_case"]
if not evt.prevent_default and user not in var.ORIGINAL_ROLES[role] and role not in var.TEMPLATE_RESTRICTIONS: