Merge pull request #146 from lykoss/fallen
New roles, protection semantics, and alpha fixes
This commit is contained in:
commit
fdd1fc5c12
@ -103,6 +103,7 @@ GUARDIAN_ANGEL_DIES_CHANCE = 0
|
||||
BODYGUARD_DIES_CHANCE = 0
|
||||
DETECTIVE_REVEALED_CHANCE = 2/5
|
||||
SHARPSHOOTER_CHANCE = 1/5 # if sharpshooter is enabled, chance that a gunner will become a sharpshooter instead
|
||||
FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE = 1/2
|
||||
|
||||
AMNESIAC_NIGHTS = 3 # amnesiac gets to know their actual role on this night
|
||||
ALPHA_WOLF_NIGHTS = 3 # alpha wolf turns the target into a wolf after this many nights (note the night they are bitten is considered night 1)
|
||||
@ -160,6 +161,7 @@ ROLE_GUIDE = {# village roles
|
||||
"hunter" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"shaman" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"doctor" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"mystic" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
# wolf roles
|
||||
"wolf" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 ),
|
||||
"traitor" : ( 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
@ -172,6 +174,8 @@ ROLE_GUIDE = {# village roles
|
||||
"alpha wolf" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"werekitten" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"warlock" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"wolf mystic" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"fallen angel" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
# neutral roles
|
||||
"lycan" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
"vengeful ghost" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
|
||||
@ -194,7 +198,7 @@ ROLE_GUIDE = {# village roles
|
||||
|
||||
# Harlot dies when visiting, seer sees as wolf, gunner kills when shooting, GA and bodyguard have a chance at dying when guarding
|
||||
# If every wolf role dies, and there are no remaining traitors, the game ends and villagers win (monster may steal win)
|
||||
WOLF_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub", "werekitten"]
|
||||
WOLF_ROLES = ["wolf", "alpha wolf", "werecrow", "wolf cub", "werekitten", "wolf mystic", "fallen angel"]
|
||||
# Access to wolfchat, and counted towards the # of wolves vs villagers when determining if a side has won
|
||||
WOLFCHAT_ROLES = WOLF_ROLES + ["traitor", "hag", "sorcerer", "warlock"]
|
||||
# Wins with the wolves, even if the roles are not necessarily wolves themselves
|
||||
@ -202,7 +206,7 @@ WOLFTEAM_ROLES = WOLFCHAT_ROLES + ["minion", "cultist"]
|
||||
# These roles never win as a team, only ever individually (either instead of or in addition to the regular winners)
|
||||
TRUE_NEUTRAL_ROLES = ["crazed shaman", "fool", "jester", "monster", "clone", "piper"]
|
||||
# These are the roles that will NOT be used for when amnesiac turns, everything else is fair game! (var.DEFAULT_ROLE is also appended if not in this list)
|
||||
AMNESIAC_BLACKLIST = ["monster", "minion", "matchmaker", "clone", "doctor", "villager", "cultist", "piper"]
|
||||
AMNESIAC_BLACKLIST = ["monster", "minion", "matchmaker", "clone", "doctor", "villager", "cultist", "piper", "village elder"]
|
||||
# These roles are seen as wolf by the seer/oracle
|
||||
SEEN_WOLF = WOLF_ROLES + ["monster", "mad scientist"]
|
||||
# These are seen as the default role (or villager) when seen by seer (this overrides SEEN_WOLF)
|
||||
@ -218,6 +222,8 @@ TEMPLATE_RESTRICTIONS = {"cursed villager" : WOLF_ROLES + ["seer", "oracle", "fo
|
||||
"assassin" : WOLF_ROLES + ["traitor", "seer", "augur", "oracle", "harlot", "detective", "bodyguard", "guardian angel", "lycan"],
|
||||
"bureaucrat" : [],
|
||||
}
|
||||
# fallen angel can be assassin even though they are a wolf role
|
||||
TEMPLATE_RESTRICTIONS["assassin"].remove("fallen angel")
|
||||
|
||||
# Roles listed here cannot be used in !fgame roles=blah. If they are defined in ROLE_GUIDE they may still be used.
|
||||
DISABLED_ROLES = []
|
||||
@ -690,15 +696,15 @@ class NoRevealMode(GameMode):
|
||||
self.ROLE_GUIDE = reset_roles(self.ROLE_INDEX)
|
||||
self.ROLE_GUIDE.update({# village roles
|
||||
"seer" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"guardian angel" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"guardian angel" : ( 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"shaman" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"village elder" : ( 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"mystic" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"detective" : ( 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ),
|
||||
"hunter" : ( 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ),
|
||||
# wolf roles
|
||||
"wolf" : ( 1 , 1 , 2 , 2 , 2 , 2 , 2 , 3 ),
|
||||
"wolf" : ( 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 ),
|
||||
"wolf mystic" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"traitor" : ( 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ),
|
||||
"minion" : ( 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ),
|
||||
"werecrow" : ( 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ),
|
||||
# neutral roles
|
||||
"clone" : ( 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ),
|
||||
|
375
src/wolfgame.py
375
src/wolfgame.py
@ -1305,6 +1305,10 @@ def stats(cli, nick, chan, rest):
|
||||
count += bitten_roles["time lord"]
|
||||
elif role == "wolf":
|
||||
count -= sum(bitten_roles.values())
|
||||
# GAs turn into FAs, not wolves
|
||||
count += bitten_roles["guardian angel"]
|
||||
elif role == "fallen angel":
|
||||
count -= bitten_roles["guardian angel"]
|
||||
else:
|
||||
count += bitten_roles[role]
|
||||
|
||||
@ -1370,8 +1374,8 @@ def hurry_up(cli, gameid, change):
|
||||
voters.append(v)
|
||||
for v in voters:
|
||||
weight = 1
|
||||
imp_count = sum(1 if p == v else 0 for p in var.IMPATIENT)
|
||||
pac_count = sum(1 if p == v else 0 for p in var.PACIFISTS)
|
||||
imp_count = var.IMPATIENT.count(v)
|
||||
pac_count = var.PACIFISTS.count(v)
|
||||
if pac_count > imp_count:
|
||||
weight = 0 # more pacifists than impatience totems
|
||||
elif imp_count == pac_count and v not in var.VOTES[votee]:
|
||||
@ -1451,8 +1455,8 @@ def chk_decision(cli, force = ""):
|
||||
if v in pl and v not in voters and v != votee and v not in var.WOUNDED and v not in var.ASLEEP:
|
||||
# don't add them in if they have the same number or more of pacifism totems
|
||||
# this matters for desperation totem on the votee
|
||||
imp_count = sum(1 if p == v else 0 for p in var.IMPATIENT)
|
||||
pac_count = sum(1 if p == v else 0 for p in var.PACIFISTS)
|
||||
imp_count = var.IMPATIENT.count(v)
|
||||
pac_count = var.PACIFISTS.count(v)
|
||||
if pac_count >= imp_count:
|
||||
continue
|
||||
|
||||
@ -1462,8 +1466,8 @@ def chk_decision(cli, force = ""):
|
||||
impatient_voters.append(v)
|
||||
for v in voters[:]:
|
||||
weight = 1
|
||||
imp_count = sum(1 if p == v else 0 for p in var.IMPATIENT)
|
||||
pac_count = sum(1 if p == v else 0 for p in var.PACIFISTS)
|
||||
imp_count = var.IMPATIENT.count(v)
|
||||
pac_count = var.PACIFISTS.count(v)
|
||||
if pac_count > imp_count:
|
||||
weight = 0 # more pacifists than impatience totems
|
||||
elif imp_count == pac_count and v not in var.VOTES[votee]:
|
||||
@ -2126,20 +2130,20 @@ def del_player(cli, nick, forced_death = False, devoice = True, end_game = True,
|
||||
target = var.TARGETED[nick]
|
||||
del var.TARGETED[nick]
|
||||
if target != None and target in pl:
|
||||
if target in var.PROTECTED:
|
||||
if "totem" in var.ACTIVE_PROTECTIONS[target] and nickrole != "fallen angel":
|
||||
var.ACTIVE_PROTECTIONS[target].remove("totem")
|
||||
message = ("Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; " +
|
||||
"however, {1}'s totem emits a brilliant flash of light, causing the attempt to miss.").format(nick, target)
|
||||
cli.msg(botconfig.CHANNEL, message)
|
||||
elif target in var.GUARDED.values() and var.GAMEPHASE == "night":
|
||||
for bg in var.ROLES["guardian angel"]:
|
||||
if bg in var.GUARDED and var.GUARDED[bg] == target:
|
||||
elif "angel" in var.ACTIVE_PROTECTIONS[target] and nickrole != "fallen angel":
|
||||
var.ACTIVE_PROTECTIONS[target].remove("angel")
|
||||
message = ("Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; " +
|
||||
"however, a guardian angel was on duty and able to foil the attempt.").format(nick, target)
|
||||
cli.msg(botconfig.CHANNEL, message)
|
||||
break
|
||||
else:
|
||||
elif "bodyguard" in var.ACTIVE_PROTECTIONS[target] and nickrole != "fallen angel":
|
||||
var.ACTIVE_PROTECTIONS[target].remove("bodyguard")
|
||||
for ga in var.ROLES["bodyguard"]:
|
||||
if ga in var.GUARDED and var.GUARDED[ga] == target:
|
||||
if var.GUARDED.get(ga) == target:
|
||||
message = ("Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; " +
|
||||
"however, \u0002{2}\u0002, a bodyguard, sacrificed their life to protect them.").format(nick, target, ga)
|
||||
cli.msg(botconfig.CHANNEL, message)
|
||||
@ -2668,7 +2672,13 @@ def on_nick(cli, oldnick, nick):
|
||||
if prefix in var.DESPERATE:
|
||||
var.DESPERATE.remove(prefix)
|
||||
var.DESPERATE.append(nick)
|
||||
if prefix in var.PROTECTED:
|
||||
for k, d in list(var.DEATH_TOTEM):
|
||||
if k == prefix or d == prefix:
|
||||
var.DEATH_TOTEM.remove((k, d))
|
||||
nk = nick if k == prefix else k
|
||||
nd = nick if d == prefix else d
|
||||
var.DEATH_TOTEM.append((nk, nd))
|
||||
while prefix in var.PROTECTED:
|
||||
var.PROTECTED.remove(prefix)
|
||||
var.PROTECTED.append(nick)
|
||||
if prefix in var.REVEALED:
|
||||
@ -2972,6 +2982,7 @@ def begin_day(cli):
|
||||
var.DISEASED = copy.copy(var.TOBEDISEASED)
|
||||
var.MISDIRECTED = copy.copy(var.TOBEMISDIRECTED)
|
||||
var.EXCHANGED = copy.copy(var.TOBEEXCHANGED)
|
||||
var.ACTIVE_PROTECTIONS = defaultdict(list)
|
||||
|
||||
msg = ('The villagers must now vote for whom to lynch. '+
|
||||
'Use "{0}lynch <nick>" to cast your vote. {1} votes '+
|
||||
@ -3069,7 +3080,7 @@ def transition_day(cli, gameid=0):
|
||||
var.NO_LYNCH = []
|
||||
var.DAY_COUNT += 1
|
||||
var.FIRST_DAY = (var.DAY_COUNT == 1)
|
||||
havetotem = copy.copy(var.LASTGIVEN)
|
||||
havetotem = list(var.LASTGIVEN.values())
|
||||
|
||||
if var.START_WITH_DAY and var.FIRST_DAY:
|
||||
# TODO: need to message everyone their roles and give a short thing saying "it's daytime"
|
||||
@ -3134,6 +3145,112 @@ def transition_day(cli, gameid=0):
|
||||
onlybywolves.add(victim)
|
||||
killers[victim].append("@wolves") # special key to let us know to randomly select a wolf
|
||||
|
||||
if len(var.ROLES["fallen angel"]) == 0:
|
||||
for monster in var.ROLES["monster"]:
|
||||
if monster in victims:
|
||||
victims.remove(monster)
|
||||
bywolves.discard(monster)
|
||||
onlybywolves.discard(monster)
|
||||
|
||||
wolfghostvictims = []
|
||||
for ghost, target in var.VENGEFUL_GHOSTS.items():
|
||||
if target == "villagers":
|
||||
victim = var.OTHER_KILLS[ghost]
|
||||
killers[victim].append(ghost)
|
||||
if victim not in var.DYING: # wolf ghost killing ghost will take precedence over everything except elder
|
||||
wolfghostvictims.append(victim)
|
||||
|
||||
for k, d in var.OTHER_KILLS.items():
|
||||
victims.append(d)
|
||||
onlybywolves.discard(d)
|
||||
killers[d].append(k)
|
||||
|
||||
for k, d in var.DEATH_TOTEM:
|
||||
victims.append(d)
|
||||
onlybywolves.discard(d)
|
||||
killers[d].append(k)
|
||||
|
||||
# handle elder and other auto-deaths
|
||||
for d in var.DYING:
|
||||
victims.append(d)
|
||||
onlybywolves.discard(d)
|
||||
|
||||
victims_set = set(victims) # remove duplicates
|
||||
victims_set.discard(None) # in the event that ever happens
|
||||
vappend = []
|
||||
# this keeps track of the protections active on each nick, stored in var since del_player needs to access it for sake of assassin
|
||||
protected = {}
|
||||
var.ACTIVE_PROTECTIONS = defaultdict(list)
|
||||
|
||||
# Logic out stacked kills and protections. If we get down to 1 kill remaining that is valid and the victim is in bywolves,
|
||||
# we re-add them to onlybywolves to indicate that the other kill attempts were guarded against (and the wolf kill is what went through)
|
||||
# If protections >= kills, we keep track of which protection message to show (prot totem > GA > bodyguard)
|
||||
for v in victims_set:
|
||||
if v in var.DYING:
|
||||
# this person is dying no matter what
|
||||
continue
|
||||
numkills = victims.count(v)
|
||||
numtotems = var.PROTECTED.count(v)
|
||||
if numtotems >= numkills:
|
||||
protected[v] = "totem"
|
||||
if numtotems > numkills:
|
||||
for i in range(0, numtotems - numkills):
|
||||
var.ACTIVE_PROTECTIONS[v].append("totem")
|
||||
numkills -= numtotems
|
||||
for g in var.ROLES["guardian angel"]:
|
||||
if var.GUARDED.get(g) == v:
|
||||
numkills -= 1
|
||||
if numkills <= 0 and v not in protected:
|
||||
protected[v] = "angel"
|
||||
elif numkills <= 0:
|
||||
var.ACTIVE_PROTECTIONS[v].append("angel")
|
||||
for g in var.ROLES["bodyguard"]:
|
||||
if var.GUARDED.get(g) == v:
|
||||
numkills -= 1
|
||||
if numkills <= 0 and v not in protected:
|
||||
protected[v] = "bodyguard"
|
||||
elif numkills <= 0:
|
||||
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
|
||||
numkills -= 1
|
||||
if numkills == 1 and v in bywolves:
|
||||
onlybywolves.add(v)
|
||||
|
||||
fallenkills = set()
|
||||
brokentotem = set()
|
||||
if len(var.ROLES["fallen angel"]) > 0:
|
||||
for p, t in list(protected.items()):
|
||||
if p in bywolves:
|
||||
if t == "angel":
|
||||
for g in var.ROLES["guardian angel"]:
|
||||
if var.GUARDED.get(g) == p and random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
|
||||
if g in protected:
|
||||
del protected[g]
|
||||
bywolves.add(g)
|
||||
victims.append(g)
|
||||
fallenkills.add(g)
|
||||
if g not in victims_set:
|
||||
victims_set.add(g)
|
||||
onlybywolves.add(g)
|
||||
elif t == "bodyguard":
|
||||
for g in var.ROLES["bodyguard"]:
|
||||
if var.GUARDED.get(g) == p:
|
||||
if g in protected:
|
||||
del protected[g]
|
||||
bywolves.add(g)
|
||||
victims.append(g)
|
||||
fallenkills.add(g)
|
||||
if g not in victims_set:
|
||||
victims_set.add(g)
|
||||
onlybywolves.add(g)
|
||||
elif t == "totem":
|
||||
# we'll never end up killing a shaman who gave out protection, but delete the totem since
|
||||
# story-wise it gets demolished at night by the FA
|
||||
while p in havetotem:
|
||||
havetotem.remove(p)
|
||||
brokentotem.add(p)
|
||||
if p in protected:
|
||||
del protected[p]
|
||||
|
||||
if var.ALPHA_ENABLED: # check for bites
|
||||
for (alpha, desired) in var.BITE_PREFERENCES.items():
|
||||
if len(bywolves) == 0:
|
||||
@ -3146,57 +3263,38 @@ def transition_day(cli, gameid=0):
|
||||
target = desired
|
||||
else:
|
||||
target = random.choice(tuple(bywolves))
|
||||
pm(cli, alpha, "You have bitten \u0002{0}\u0002.".format(target))
|
||||
targetrole = var.get_role(target)
|
||||
# do the usual checks; we can only bite those that would otherwise die
|
||||
# (e.g. block it on visiting harlot, GA/bodyguard, and protection totem)
|
||||
# also if a lycan is bitten, just turn them into a wolf immediately
|
||||
if (target not in var.PROTECTED
|
||||
and target not in var.GUARDED.values()
|
||||
if (target not in protected
|
||||
and (target not in var.ROLES["harlot"] or not var.HVISITED.get(target))
|
||||
and target not in var.ROLES["lycan"]
|
||||
and target not in var.LYCANTHROPES
|
||||
and target not in var.IMMUNIZED):
|
||||
var.BITTEN[target] = var.ALPHA_WOLF_NIGHTS
|
||||
bitten.append(target)
|
||||
victims.remove(target)
|
||||
bywolves.remove(target)
|
||||
onlybywolves.remove(target)
|
||||
killers[target].remove("@wolves")
|
||||
if target not in victims:
|
||||
victims_set.discard(target)
|
||||
var.BITTEN[target] = var.ALPHA_WOLF_NIGHTS
|
||||
bitten.append(target)
|
||||
else:
|
||||
# someone else also killed them, mark bite unsuccessful
|
||||
var.ALPHA_WOLVES.remove(alpha)
|
||||
else:
|
||||
# bite was unsuccessful, let them try again
|
||||
var.ALPHA_WOLVES.remove(alpha)
|
||||
|
||||
if alpha in var.ALPHA_WOLVES:
|
||||
pm(cli, alpha, "You have bitten \u0002{0}\u0002.".format(target))
|
||||
else:
|
||||
pm(cli, alpha, "You tried to bite \u0002{0}\u0002, but it didn't work. Better luck next time!".format(target))
|
||||
|
||||
|
||||
var.BITE_PREFERENCES = {}
|
||||
|
||||
for monster in var.ROLES["monster"]:
|
||||
if monster in victims:
|
||||
victims.remove(monster)
|
||||
bywolves.discard(monster)
|
||||
onlybywolves.discard(monster)
|
||||
|
||||
wolfghostvictims = []
|
||||
for ghost, target in var.VENGEFUL_GHOSTS.items():
|
||||
if target == "villagers":
|
||||
victim = var.OTHER_KILLS[ghost]
|
||||
killers[victim].append(ghost)
|
||||
if victim not in var.DYING: # wolf ghost killing ghost will take precedence over everything except death totem and elder
|
||||
wolfghostvictims.append(victim)
|
||||
|
||||
for k, d in var.OTHER_KILLS.items():
|
||||
victims.append(d)
|
||||
onlybywolves.discard(d)
|
||||
killers[d].append(k)
|
||||
for d in var.DYING:
|
||||
victims.append(d)
|
||||
onlybywolves.discard(d)
|
||||
for s, v in var.LASTGIVEN.items():
|
||||
if v == d and var.TOTEMS[s] == "death":
|
||||
killers[d].append(s)
|
||||
victims_set = set(victims) # remove duplicates
|
||||
victims_set.discard(None) # in the event that ever happens
|
||||
victims = []
|
||||
vappend = []
|
||||
# Ensures that special events play for bodyguard and harlot-visiting-victim so that kill can
|
||||
# be correctly attributed to wolves (for vengeful ghost lover), and that any gunner events
|
||||
# can play. Harlot visiting wolf doesn't play special events if they die via other means since
|
||||
@ -3226,6 +3324,37 @@ def transition_day(cli, gameid=0):
|
||||
vappend.remove(v)
|
||||
victims.append(v)
|
||||
|
||||
# If FA is killing through a guard, let them as well as the victim know so they don't
|
||||
# try to report the extra kills as a bug
|
||||
fallenmsg = set()
|
||||
if len(var.ROLES["fallen angel"]) > 0:
|
||||
for v in fallenkills:
|
||||
t = var.GUARDED.get(v)
|
||||
if v not in fallenmsg:
|
||||
fallenmsg.add(v)
|
||||
if v != t:
|
||||
pm(cli, v, ("A fell wind starts blowing through the village and you catch the flurry of blackened wings out of the corner of your eye. " +
|
||||
"No longer caring for \u0002{0}\u0002's safety, you attempt to get away before your own life is taken...").format(t))
|
||||
else:
|
||||
pm(cli, v, "A fell wind blows through you and chills you to the bone. You no longer feel safe or protected...")
|
||||
if v != t and t not in fallenmsg:
|
||||
fallenmsg.add(t)
|
||||
pm(cli, t, "A fell wind blows through you and chills you to the bone. You no longer feel safe or protected...")
|
||||
# Also message GAs that don't die and their victims
|
||||
for g in var.ROLES["guardian angel"]:
|
||||
v = var.GUARDED.get(g)
|
||||
if v in bywolves and g not in fallenkills:
|
||||
if g not in fallenmsg:
|
||||
fallenmsg.add(g)
|
||||
if g != v:
|
||||
pm(cli, g, ("A fell wind starts blowing through the village and you catch the flurry of blackened wings out of the corner of your eye. " +
|
||||
"No longer caring for \u0002{0}\u0002's safety, you attempt to get away before your own life is taken...").format(v))
|
||||
else:
|
||||
pm(cli, g, "A fell wind blows through you and chills you to the bone. You no longer feel safe or protected...")
|
||||
if g != v and v not in fallenmsg:
|
||||
fallenmsg.add(g)
|
||||
pm(cli, v, "A fell wind blows through you and chills you to the bone. You no longer feel safe or protected...")
|
||||
|
||||
# Select a random target for assassin that isn't already going to die if they didn't target
|
||||
pl = var.list_players()
|
||||
for ass in var.ROLES["assassin"]:
|
||||
@ -3284,18 +3413,15 @@ def transition_day(cli, gameid=0):
|
||||
if victim in var.ROLES["harlot"] and var.HVISITED.get(victim) and victim not in var.DYING and victim not in dead and victim in onlybywolves:
|
||||
message.append("The wolves' selected victim was a harlot, who was not at home last night.")
|
||||
novictmsg = False
|
||||
elif victim in var.PROTECTED and victim not in var.DYING:
|
||||
elif protected.get(victim) == "totem":
|
||||
message.append(("\u0002{0}\u0002 was attacked last night, but their totem " +
|
||||
"emitted a brilliant flash of light, blinding the attacker and " +
|
||||
"allowing them to escape.").format(victim))
|
||||
novictmsg = False
|
||||
elif victim in var.GUARDED.values() and victim not in var.DYING:
|
||||
for gangel in var.ROLES["guardian angel"]:
|
||||
if var.GUARDED.get(gangel) == victim:
|
||||
elif protected.get(victim) == "angel":
|
||||
message.append(("\u0002{0}\u0002 was attacked last night, but luckily, the guardian angel was on duty.").format(victim))
|
||||
novictmsg = False
|
||||
break
|
||||
else:
|
||||
elif protected.get(victim) == "bodyguard":
|
||||
for bodyguard in var.ROLES["bodyguard"]:
|
||||
if var.GUARDED.get(bodyguard) == victim:
|
||||
dead.append(bodyguard)
|
||||
@ -3455,10 +3581,14 @@ def transition_day(cli, gameid=0):
|
||||
if var.WOLF_STEALS_GUN and victim in bywolves and victim in var.GUNNERS.keys() and var.GUNNERS[victim] > 0:
|
||||
# victim has bullets
|
||||
try:
|
||||
while True:
|
||||
guntaker = random.choice(var.list_players(var.WOLFCHAT_ROLES)) # random looter
|
||||
looters = var.list_players(var.WOLFCHAT_ROLES)
|
||||
while len(looters) > 0:
|
||||
guntaker = random.choice(looters) # random looter
|
||||
if guntaker not in dead:
|
||||
break
|
||||
else:
|
||||
looters.remove(guntaker)
|
||||
if guntaker not in dead:
|
||||
numbullets = var.GUNNERS[victim]
|
||||
if guntaker not in var.WOLF_GUNNERS:
|
||||
var.WOLF_GUNNERS[guntaker] = 0
|
||||
@ -3493,9 +3623,11 @@ def transition_day(cli, gameid=0):
|
||||
del_player(cli, deadperson, end_game = False, killer_role = "wolf" if deadperson in onlybywolves or deadperson in wolfghostvictims else "villager", deadlist = dead, original = deadperson)
|
||||
|
||||
message = []
|
||||
for havetotem in havetotem.values():
|
||||
for havetotem in havetotem:
|
||||
if havetotem:
|
||||
message.append("\u0002{0}\u0002 seem{1} to be in possession of a mysterious totem...".format(havetotem, "ed" if havetotem in dead else "s"))
|
||||
for brokentotem in brokentotem:
|
||||
message.append("Broken totem pieces were found next to \u0002{0}\u0002's body...".format(brokentotem))
|
||||
cli.msg(chan, "\n".join(message))
|
||||
|
||||
if chk_win(cli): # if after the last person is killed, one side wins, then actually end the game here
|
||||
@ -3514,13 +3646,13 @@ def chk_nightdone(cli):
|
||||
var.ROLES["werecrow"] + var.ROLES["alpha wolf"] + var.ROLES["sorcerer"] + var.ROLES["hunter"] +
|
||||
list(var.VENGEFUL_GHOSTS.keys()) + var.ROLES["hag"] + var.ROLES["shaman"] +
|
||||
var.ROLES["crazed shaman"] + var.ROLES["augur"] + var.ROLES["werekitten"] +
|
||||
var.ROLES["warlock"] + var.ROLES["piper"])
|
||||
var.ROLES["warlock"] + var.ROLES["piper"] + var.ROLES["wolf mystic"] + var.ROLES["fallen angel"])
|
||||
if var.FIRST_NIGHT:
|
||||
actedcount += len(var.MATCHMAKERS + list(var.CLONED.keys()))
|
||||
nightroles += var.ROLES["matchmaker"] + var.ROLES["clone"]
|
||||
|
||||
if var.DISEASED_WOLVES:
|
||||
nightroles = [p for p in nightroles if p not in (var.ROLES["wolf"] + var.ROLES["alpha wolf"] + var.ROLES["werekitten"])]
|
||||
nightroles = [p for p in nightroles if p not in var.list_players(("wolf", "alpha wolf", "werekitten", "wolf mystic", "fallen angel"))]
|
||||
|
||||
for p in var.HUNTERS:
|
||||
# only remove one instance of their name if they have used hunter ability, in case they have templates
|
||||
@ -3718,7 +3850,7 @@ def check_exchange(cli, actor, nick):
|
||||
var.SHAMANS.remove(actor)
|
||||
if actor in var.LASTGIVEN:
|
||||
del var.LASTGIVEN[actor]
|
||||
elif actor_role == "wolf" or actor_role == "werekitten":
|
||||
elif actor_role in ("wolf", "werekitten", "wolf mystic", "fallen angel"):
|
||||
if actor in var.KILLS:
|
||||
del var.KILLS[actor]
|
||||
elif actor_role == "hunter":
|
||||
@ -3785,7 +3917,7 @@ def check_exchange(cli, actor, nick):
|
||||
var.SHAMANS.remove(nick)
|
||||
if nick in var.LASTGIVEN:
|
||||
del var.LASTGIVEN[nick]
|
||||
elif nick_role == "wolf" or nick_role == "werekitten":
|
||||
elif nick_role in ("wolf", "werekitten", "wolf mystic", "fallen angel"):
|
||||
if nick in var.KILLS:
|
||||
del var.KILLS[nick]
|
||||
elif nick_role == "hunter":
|
||||
@ -3870,6 +4002,9 @@ def check_exchange(cli, actor, nick):
|
||||
if nick_role == "shaman":
|
||||
pm(cli, actor, "You have a \u0002{0}\u0002 totem.".format(nick_totem))
|
||||
var.TOTEMS[actor] = nick_totem
|
||||
elif nick_role == "mystic":
|
||||
numevil = len(var.list_players(var.WOLFTEAM_ROLES))
|
||||
pm(cli, actor, "There are \u0002{0}\u0002 evil villager{1} still alive.".format(numevil, "s" if numevil != 1 else ""))
|
||||
elif nick_role in var.WOLFCHAT_ROLES and actor_role not in var.WOLFCHAT_ROLES:
|
||||
pl = var.list_players()
|
||||
random.shuffle(pl)
|
||||
@ -3886,15 +4021,17 @@ def check_exchange(cli, actor, nick):
|
||||
pl[i] = player + " (cursed)"
|
||||
|
||||
pm(cli, actor, "Players: " + ", ".join(pl))
|
||||
angry_alpha = ''
|
||||
if actor_role == "wolf mystic":
|
||||
# # of special villagers = # of players - # of villagers - # of wolves - # of neutrals
|
||||
numvills = len(ps) - len(var.list_players(var.WOLFTEAM_ROLES)) - len(var.list_players(("villager", "vengeful ghost", "time lord", "amnesiac", "village elder", "lycan"))) - len(var.list_players(var.TRUE_NEUTRAL_ROLES))
|
||||
pm(cli, actor, "There are \u0002{0}\u0002 special villager{1} still alive.".format(numvills, "s" if numvills != 1 else ""))
|
||||
if var.DISEASED_WOLVES:
|
||||
pm(cli, actor, 'You are feeling ill tonight, and are unable to kill anyone.')
|
||||
elif var.ANGRY_WOLVES and actor_role in ("wolf", "werecrow", "alpha wolf", "werekitten"):
|
||||
elif var.ANGRY_WOLVES and actor_role in var.WOLF_ROLES and actor_role != "wolf cub":
|
||||
pm(cli, actor, 'You are \u0002angry\u0002 tonight, and may kill two targets by using "kill <nick1> and <nick2>".')
|
||||
angry_alpha = ' <nick>'
|
||||
if var.ALPHA_ENABLED and actor_role == "alpha wolf" and actor not in var.ALPHA_WOLVES:
|
||||
pm(cli, actor, ('You may use "bite{0}" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {1} night{2}.').format(angry_alpha, var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
pm(cli, actor, ('You may use "bite <nick>" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {0} night{1}.').format(var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
elif nick_role == "minion":
|
||||
wolves = var.list_players(var.WOLF_ROLES)
|
||||
random.shuffle(wolves)
|
||||
@ -3906,6 +4043,9 @@ def check_exchange(cli, actor, nick):
|
||||
if actor_role == "shaman":
|
||||
pm(cli, nick, "You have a \u0002{0}\u0002 totem.".format(actor_totem))
|
||||
var.TOTEMS[nick] = actor_totem
|
||||
elif actor_role == "mystic":
|
||||
numevil = len(var.list_players(var.WOLFTEAM_ROLES))
|
||||
pm(cli, nick, "There are \u0002{0}\u0002 evil villager{1} still alive.".format(numevil, "s" if numevil != 1 else ""))
|
||||
elif actor_role in var.WOLFCHAT_ROLES and nick_role not in var.WOLFCHAT_ROLES:
|
||||
pl = var.list_players()
|
||||
random.shuffle(pl)
|
||||
@ -3922,15 +4062,17 @@ def check_exchange(cli, actor, nick):
|
||||
pl[i] = player + " (cursed)"
|
||||
|
||||
pm(cli, nick, "Players: " + ", ".join(pl))
|
||||
angry_alpha = ''
|
||||
if nick_role == "wolf mystic":
|
||||
# # of special villagers = # of players - # of villagers - # of wolves - # of neutrals
|
||||
numvills = len(ps) - len(var.list_players(var.WOLFTEAM_ROLES)) - len(var.list_players(("villager", "vengeful ghost", "time lord", "amnesiac", "village elder", "lycan"))) - len(var.list_players(var.TRUE_NEUTRAL_ROLES))
|
||||
pm(cli, nick, "There are \u0002{0}\u0002 special villager{1} still alive.".format(numvills, "s" if numvills != 1 else ""))
|
||||
if var.DISEASED_WOLVES:
|
||||
pm(cli, nick, 'You are feeling ill tonight, and are unable to kill anyone.')
|
||||
elif var.ANGRY_WOLVES and nick_role in ("wolf", "werecrow", "alpha wolf", "werekitten"):
|
||||
pm(cli, nick, 'You are \u0002angry\u0002 tonight, and may kill two targets by using "kill <nick1> and <nick2>".')
|
||||
angry_alpha = ' <nick>'
|
||||
if var.ALPHA_ENABLED and nick_role == "alpha wolf" and nick not in var.ALPHA_WOLVES:
|
||||
pm(cli, nick, ('You may use "bite{0}" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {1} night{2}.').format(angry_alpha, var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
pm(cli, nick, ('You may use "bite <nick>" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {0} night{1}.').format(var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
elif actor_role == "minion":
|
||||
wolves = var.list_players(var.WOLF_ROLES)
|
||||
random.shuffle(wolves)
|
||||
@ -3948,7 +4090,9 @@ def retract(cli, nick, chan, rest):
|
||||
|
||||
if chan == nick: # PM, use different code
|
||||
role = var.get_role(nick)
|
||||
if role not in ("wolf", "werecrow", "alpha wolf", "werekitten", "hunter") and nick not in var.VENGEFUL_GHOSTS.keys():
|
||||
if role not in var.WOLF_ROLES + ["hunter"] and nick not in var.VENGEFUL_GHOSTS.keys():
|
||||
return
|
||||
if role == "wolf cub":
|
||||
return
|
||||
if var.PHASE != "night":
|
||||
return
|
||||
@ -4446,11 +4590,9 @@ def totem(cli, nick, chan, rest):
|
||||
return
|
||||
pm(cli, nick, ("You have given a totem{0} to \u0002{1}\u0002.").format(type, victim))
|
||||
totem = var.TOTEMS[nick]
|
||||
if totem == "death":
|
||||
if victim not in var.DYING:
|
||||
var.DYING.append(victim)
|
||||
elif totem == "protection":
|
||||
if victim not in var.PROTECTED:
|
||||
if totem == "death": # this totem stacks
|
||||
var.DEATH_TOTEM.append((nick, victim))
|
||||
elif totem == "protection": # this totem stacks
|
||||
var.PROTECTED.append(victim)
|
||||
elif totem == "revealing":
|
||||
if victim not in var.REVEALED:
|
||||
@ -4508,11 +4650,12 @@ def immunize(cli, nick, chan, rest):
|
||||
if not victim:
|
||||
return
|
||||
victim = choose_target(nick, victim)
|
||||
vrole = var.get_role(victim)
|
||||
if check_exchange(cli, nick, victim):
|
||||
return
|
||||
pm(cli, nick, "You have given an immunization to \u0002{0}\u0002.".format(victim))
|
||||
lycan = False
|
||||
if var.get_role(victim) == "lycan":
|
||||
if vrole == "lycan":
|
||||
lycan = True
|
||||
lycan_message = ("You feel as if a curse has been lifted from you... It seems that your lycanthropy is cured " +
|
||||
"and you will no longer become a werewolf if targeted by the wolves!")
|
||||
@ -4528,8 +4671,9 @@ def immunize(cli, nick, chan, rest):
|
||||
# naturally, we would want to mimic that behavior here, and what better way of indicating that things got worse than
|
||||
# by making the turning happen a night earlier? :)
|
||||
var.BITTEN[victim] -= 1
|
||||
lycan_message = ("You have a brief flashback to your dream last night. " +
|
||||
"The event quickly subsides, but a lingering thought remains in your mind...")
|
||||
lycan_message = ("You have a brief flashback to {0} last night. " +
|
||||
"The event quickly subsides, but a lingering thought remains in your mind...").format(
|
||||
"the events of" if vrole == "guardian angel" else "your dream")
|
||||
else:
|
||||
lycan_message = "You don't feel any different..."
|
||||
var.IMMUNIZED.add(victim)
|
||||
@ -4540,7 +4684,25 @@ def immunize(cli, nick, chan, rest):
|
||||
|
||||
def get_bitten_message(nick):
|
||||
time_left = var.BITTEN[nick]
|
||||
role = var.get_role(nick)
|
||||
message = ""
|
||||
if role == "guardian angel":
|
||||
if time_left <= 1:
|
||||
message = ("After returning from last night's activities, you felt another wave of pain, this time on your back. " +
|
||||
"Your wings grew larger and you can now fly faster and farther than ever before. Along with " +
|
||||
"the size change, their color shifted from pure white to a midnight black. You didn't spend much " +
|
||||
"time thinking on what happened, as you were tired and went to sleep shortly thereafter.")
|
||||
elif time_left == 2:
|
||||
message = ("Despite the gloves, it seems that the villagers have been keeping their distance from you as of late. " +
|
||||
"None of them seem to know about your changes, so the change of behavior greatly angers you. You're " +
|
||||
"doing just as good a job as ever, and if anything the changes make you MORE effective and powerful. " +
|
||||
"These thoughts lingered for the rest of last night until you finally drifted off to an uneasy sleep.")
|
||||
else:
|
||||
message = ("As you were out last night, you felt a painful sensation as your hands grew very sharp claws. " +
|
||||
"You figure they are now sharp enough to cut through most anything, but to avoid alarming the village " +
|
||||
"you decide to fashion some gloves and wear them around from now on in an attempt to show nothing is " +
|
||||
"happening.")
|
||||
else:
|
||||
if time_left <= 1:
|
||||
message = ("You had the same dream again, but this time YOU were the pursuer. You smell fear from your quarry " +
|
||||
"as you give an exhilerating chase, going only half your speed in order to draw out the fun. " +
|
||||
@ -5030,6 +5192,7 @@ def transition_night(cli):
|
||||
var.REVEALED = []
|
||||
var.TOBESILENCED = []
|
||||
var.IMPATIENT = []
|
||||
var.DEATH_TOTEM = []
|
||||
var.PACIFISTS = []
|
||||
var.INFLUENTIAL = []
|
||||
var.TOBELYCANTHROPES = []
|
||||
@ -5083,18 +5246,33 @@ def transition_night(cli):
|
||||
|
||||
if var.BITTEN[chump] <= 0:
|
||||
# now a wolf
|
||||
newrole = "wolf"
|
||||
if chumprole == "guardian angel":
|
||||
pm(cli, chump, ("As the moonlight filters through your window, you think back on the past few days. " +
|
||||
"Your power has been growing, but the villagers you protect subconsciously detected " +
|
||||
"your shift and have been keeping more distant from you. Grinning with wicked resolve, " +
|
||||
"you vow to show them what fools they have been as you take to the skies once more " +
|
||||
"with an unholy vengeance. Soon they will know true fear."))
|
||||
# fallen angels also automatically gain the assassin template if they don't already have it
|
||||
# by default GA can never be assassin, but this guards against non-default cases
|
||||
newrole = "fallen angel"
|
||||
if chump not in var.ROLES["assassin"]:
|
||||
var.ROLES["assassin"].append(chump)
|
||||
debuglog("{0} ({1}) TURNED FALLEN ANGEL".format(chump, chumprole))
|
||||
else:
|
||||
pm(cli, chump, ("As you prepare for bed, you watch in horror as your body starts growing a coat of fur! " +
|
||||
"Sudden realization hits you as you grin with your now muzzled face; that mysterious bite " +
|
||||
"earlier slowly changed you into a werewolf! You feel bigger, stronger, faster, and ready to " +
|
||||
"seize the night as you stealthily exit your home and search for the rest of your pack..."))
|
||||
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
|
||||
var.BITTEN_ROLES[chump] = chumprole
|
||||
var.ROLES[chumprole].remove(chump)
|
||||
var.ROLES["wolf"].append(chump)
|
||||
var.FINAL_ROLES[chump] = "wolf"
|
||||
var.ROLES[newrole].append(chump)
|
||||
var.FINAL_ROLES[chump] = newrole
|
||||
for wolf in var.list_players(var.WOLFCHAT_ROLES):
|
||||
if wolf != chump:
|
||||
pm(cli, wolf, "\u0002{0}\u0002 is now a \u0002wolf\u0002!".format(chump))
|
||||
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
|
||||
# no need for a/an since newrole is either wolf or fallen angel
|
||||
pm(cli, wolf, "\u0002{0}\u0002 is now a \u0002{1}\u0002!".format(chump, newrole))
|
||||
|
||||
# convert amnesiac and kill village elder if necessary
|
||||
if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
|
||||
@ -5185,6 +5363,12 @@ def transition_night(cli):
|
||||
'to turn them into a cursed villager, so the seer sees them as wolf. Act quickly, as ' +
|
||||
'your curse applies as soon as you cast it! Only detectives can reveal your true identity, ' +
|
||||
'seers will see you as a regular villager.').format(cursed))
|
||||
elif role == "wolf mystic":
|
||||
pm(cli, wolf, ('You are a \u0002wolf mystic\u0002. Each night you divine the number of alive good villagers ' +
|
||||
'who have a special role. You may also use "kill <nick>" to kill a villager.'))
|
||||
elif role == "fallen angel":
|
||||
pm(cli, wolf, ('You are a \u0002fallen angel\u0002. Your sharp claws will rend any protection the villagers ' +
|
||||
'may have, and will likely kill living guardians as well. Use "kill <nick>" to kill a villager.'))
|
||||
else:
|
||||
# catchall in case we forgot something above
|
||||
an = 'n' if role.startswith(("a", "e", "i", "o", "u")) else ""
|
||||
@ -5212,17 +5396,20 @@ def transition_night(cli):
|
||||
pl[i] = player + " (cursed)"
|
||||
|
||||
pm(cli, wolf, "Players: " + ", ".join(pl))
|
||||
if role == "wolf mystic":
|
||||
# if adding this info to !myrole, you will need to save off this count so that they can't get updated info until the next night
|
||||
# # of special villagers = # of players - # of villagers - # of wolves - # of neutrals
|
||||
numvills = len(ps) - len(var.list_players(var.WOLFTEAM_ROLES)) - len(var.list_players(("villager", "vengeful ghost", "time lord", "amnesiac", "village elder", "lycan"))) - len(var.list_players(var.TRUE_NEUTRAL_ROLES))
|
||||
pm(cli, wolf, "There are \u0002{0}\u0002 special villager{1} still alive.".format(numvills, "s" if numvills != 1 else ""))
|
||||
if wolf in var.WOLF_GUNNERS.keys() and var.WOLF_GUNNERS[wolf] > 0:
|
||||
pm(cli, wolf, "You have a \u0002gun\u0002 with {0} bullet{1}.".format(var.WOLF_GUNNERS[wolf], "s" if var.WOLF_GUNNERS[wolf] > 1 else ""))
|
||||
angry_alpha = ''
|
||||
if var.DISEASED_WOLVES:
|
||||
pm(cli, wolf, 'You are feeling ill tonight, and are unable to kill anyone.')
|
||||
elif var.ANGRY_WOLVES and role in ("wolf", "werecrow", "alpha wolf", "werekitten"):
|
||||
elif var.ANGRY_WOLVES and role in var.WOLF_ROLES and role != "wolf cub":
|
||||
pm(cli, wolf, 'You are \u0002angry\u0002 tonight, and may kill two targets by using "kill <nick1> and <nick2>".')
|
||||
angry_alpha = ' <nick>'
|
||||
if var.ALPHA_ENABLED and role == "alpha wolf" and wolf not in var.ALPHA_WOLVES:
|
||||
pm(cli, wolf, ('You may use "bite{0}" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {1} night{2}.').format(angry_alpha, var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
pm(cli, wolf, ('You may use "bite <nick>" tonight in order to turn the wolves\' target into a wolf instead of killing them. ' +
|
||||
'They will turn into a wolf in {0} night{1}.').format(var.ALPHA_WOLF_NIGHTS, 's' if var.ALPHA_WOLF_NIGHTS > 1 else ''))
|
||||
|
||||
for seer in var.list_players(("seer", "oracle", "augur")):
|
||||
pl = ps[:]
|
||||
@ -5335,6 +5522,16 @@ def transition_night(cli):
|
||||
else:
|
||||
pm(cli, drunk, "You are the \u0002village drunk\u0002.")
|
||||
|
||||
for mystic in var.ROLES["mystic"]:
|
||||
if mystic in var.PLAYERS and not is_user_simple(mystic):
|
||||
pm(cli, mystic, ("You are the \u0002mystic\u0002. Each night you divine the number of evil " +
|
||||
"villagers (including wolves) that are still alive."))
|
||||
else:
|
||||
pm(cli, mystic, "You are the \u0002mystic\u0002.")
|
||||
# if adding this info to !myrole, you will need to save off this count so that they can't get updated info until the next night
|
||||
numevil = len(var.list_players(var.WOLFTEAM_ROLES))
|
||||
pm(cli, mystic, "There are \u0002{0}\u0002 evil villager{1} still alive.".format(numevil, "s" if numevil != 1 else ""))
|
||||
|
||||
max_totems = {}
|
||||
for sham in var.TOTEM_ORDER:
|
||||
max_totems[sham] = 0
|
||||
@ -5821,6 +6018,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
||||
var.FINAL_ROLES = {}
|
||||
var.ORIGINAL_LOVERS = {}
|
||||
var.IMPATIENT = []
|
||||
var.DEATH_TOTEM = []
|
||||
var.PACIFISTS = []
|
||||
var.INFLUENTIAL = []
|
||||
var.LYCANTHROPES = []
|
||||
@ -5849,6 +6047,7 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
||||
var.BITTEN_ROLES = {}
|
||||
var.CHARMERS = set()
|
||||
var.CHARMED = set()
|
||||
var.ACTIVE_PROTECTIONS = defaultdict(list)
|
||||
|
||||
for role, count in addroles.items():
|
||||
if role in var.TEMPLATE_RESTRICTIONS.keys():
|
||||
|
Loading…
x
Reference in New Issue
Block a user