Succubus fixes

This commit is contained in:
Vgr E. Barry 2015-10-29 17:44:34 -04:00
parent da9a6f5b62
commit c4029d826d

View File

@ -2179,6 +2179,8 @@ def chk_decision(cli, force = ""):
cli.msg(botconfig.CHANNEL, "The villagers have agreed not to lynch anybody today.") cli.msg(botconfig.CHANNEL, "The villagers have agreed not to lynch anybody today.")
if var.ROLES["succubus"] & var.NO_LYNCH: if var.ROLES["succubus"] & var.NO_LYNCH:
var.ENTRANCED_DYING.update(var.ENTRANCED - var.NO_LYNCH - var.DEAD) var.ENTRANCED_DYING.update(var.ENTRANCED - var.NO_LYNCH - var.DEAD)
else:
var.ENTRANCED_DYING.update(var.ENTRANCED & var.NO_LYNCH)
var.ABSTAINED = True var.ABSTAINED = True
transition_night(cli) transition_night(cli)
return return
@ -2280,6 +2282,10 @@ def chk_decision(cli, force = ""):
if votee in var.ROLES["jester"]: if votee in var.ROLES["jester"]:
var.JESTERS.add(votee) var.JESTERS.add(votee)
# this checks if any succubus have voted the current votee
# if it is NOT the case, then it checks if any succubus voted at all
# it does so by joining together all the values from var.VOTES and casting them all into a single set
# if any succubus voted for anyone else and nobody for the current votee, then proceed to block
if not var.ROLES["succubus"] & set(var.VOTES[votee]) and var.ROLES["succubus"] & set(itertools.chain(*var.VOTES.values())): if not var.ROLES["succubus"] & set(var.VOTES[votee]) and var.ROLES["succubus"] & set(itertools.chain(*var.VOTES.values())):
voted_along = set() voted_along = set()
for person, all_voters in var.VOTES.items(): for person, all_voters in var.VOTES.items():
@ -2290,6 +2296,9 @@ def chk_decision(cli, force = ""):
var.ENTRANCED_DYING.update(var.ENTRANCED - voted_along - var.DEAD) # can be the empty set var.ENTRANCED_DYING.update(var.ENTRANCED - voted_along - var.DEAD) # can be the empty set
elif var.ROLES["succubus"] & var.NO_LYNCH: # any succubus abstained
var.ENTRANCED_DYING.update(var.ENTRANCED - var.NO_LYNCH - var.DEAD)
if var.ROLE_REVEAL in ("on", "team"): if var.ROLE_REVEAL in ("on", "team"):
rrole = var.get_reveal_role(votee) rrole = var.get_reveal_role(votee)
an = "n" if rrole.startswith(("a", "e", "i", "o", "u")) else "" an = "n" if rrole.startswith(("a", "e", "i", "o", "u")) else ""
@ -2562,6 +2571,8 @@ def stop_game(cli, winner = "", abort = False, additional_winners = None):
won = True won = True
elif var.DEFAULT_ROLE == "cultist" and winner == "wolves": elif var.DEFAULT_ROLE == "cultist" and winner == "wolves":
won = True won = True
elif winner != "succubi" and splr in var.ENTRANCED:
won = False
elif winner == "villagers": elif winner == "villagers":
won = True won = True
elif winner == "succubi" and rol == "succubus": elif winner == "succubi" and rol == "succubus":
@ -2611,7 +2622,10 @@ def stop_game(cli, winner = "", abort = False, additional_winners = None):
iwon = True iwon = True
elif rol == "vengeful ghost": elif rol == "vengeful ghost":
if not winner.startswith("@") and winner not in ("monsters", "demoniacs", "pipers"): if not winner.startswith("@") and winner not in ("monsters", "demoniacs", "pipers"):
if won and splr in survived: if winner != "succubi" and splr in var.ENTRANCED:
won = False
iwon = False
elif won and splr in survived:
iwon = True iwon = True
elif splr in var.VENGEFUL_GHOSTS and var.VENGEFUL_GHOSTS[splr] == "villagers" and winner == "wolves": elif splr in var.VENGEFUL_GHOSTS and var.VENGEFUL_GHOSTS[splr] == "villagers" and winner == "wolves":
won = True won = True
@ -2631,16 +2645,8 @@ def stop_game(cli, winner = "", abort = False, additional_winners = None):
iwon = False iwon = False
elif rol == "jester" and splr in var.JESTERS: elif rol == "jester" and splr in var.JESTERS:
iwon = True iwon = True
elif winner == "succubi": elif winner == "succubi" and splr in var.ENTRANCED | var.ROLES["succubus"]:
if splr in var.ENTRANCED: iwon = True
won = False
iwon = True
elif rol == "succubus":
won = True
if splr in survived:
iwon = True
elif winner != "succubi" and splr in var.ENTRANCED:
won = False
elif not iwon: elif not iwon:
iwon = won and splr in survived # survived, team won = individual win iwon = won and splr in survived # survived, team won = individual win
@ -2716,7 +2722,7 @@ def chk_win(cli, end_game=True, winner=None):
ltraitors = len(var.ROLES.get("traitor", ())) ltraitors = len(var.ROLES.get("traitor", ()))
lpipers = len(var.ROLES.get("piper", ())) lpipers = len(var.ROLES.get("piper", ()))
lsuccubi = len(var.ROLES.get("succubus", ())) lsuccubi = len(var.ROLES.get("succubus", ()))
lentranced = len(var.ENTRANCED) lentranced = len(var.ENTRANCED - var.DEAD)
if var.PHASE == "day": if var.PHASE == "day":
for p in var.WOUNDED | var.ASLEEP | var.CONSECRATING | var.SICK: for p in var.WOUNDED | var.ASLEEP | var.CONSECRATING | var.SICK:
try: try:
@ -2741,7 +2747,7 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs,
elif lpl < 1: elif lpl < 1:
message = "Game over! There are no players remaining. Nobody wins." message = "Game over! There are no players remaining. Nobody wins."
winner = "none" winner = "none"
elif var.PHASE == "day" and lpl - lsuccubi <= lentranced: # entranced people elif var.PHASE == "day" and lpl - lsuccubi == lentranced:
winner = "succubi" winner = "succubi"
message = ("Game over! The succub{0} ha{1} won! The succub{0} then take{2} all of the " message = ("Game over! The succub{0} ha{1} won! The succub{0} then take{2} all of the "
"entranced players with them, and go{3} out of the village, never to return" "entranced players with them, and go{3} out of the village, never to return"
@ -3212,7 +3218,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
if nickrole == "succubus" and not var.ROLES["succubus"]: if nickrole == "succubus" and not var.ROLES["succubus"]:
while var.ENTRANCED: while var.ENTRANCED:
entranced = var.ENTRANCED.pop() entranced = var.ENTRANCED.pop()
pm(cli, entranced, "With the succubus now dead, you are no longer entranced.") pm(cli, entranced, "With all of the succubi dead, you are no longer entranced. \u0002Your win conditions have reset to normal.\u0002")
var.ENTRANCED_DYING.clear() # for good measure var.ENTRANCED_DYING.clear() # for good measure
if var.PHASE == "night": if var.PHASE == "night":
# remove players from night variables # remove players from night variables
@ -4020,18 +4026,19 @@ def transition_day(cli, gameid=0):
# that isn't going to be dying today, meaning we need to know who is dying first :) # that isn't going to be dying today, meaning we need to know who is dying first :)
# Select a random target for vengeful ghost if they didn't kill # Select a random target for vengeful ghost if they didn't kill
wolves = var.list_players(var.WOLFTEAM_ROLES) wolves = set(var.list_players(var.WOLFTEAM_ROLES))
villagers = var.list_players() villagers = set(var.list_players()) - wolves
for wolf in wolves:
villagers.remove(wolf)
for ghost, target in var.VENGEFUL_GHOSTS.items(): for ghost, target in var.VENGEFUL_GHOSTS.items():
if target[0] == "!" or ghost in var.SILENCED: if target[0] == "!" or ghost in var.SILENCED:
continue continue
if ghost not in var.OTHER_KILLS: if ghost not in var.OTHER_KILLS:
if target == "wolves": if target == "wolves":
var.OTHER_KILLS[ghost] = random.choice(wolves) choice = wolves.copy()
else: else:
var.OTHER_KILLS[ghost] = random.choice(villagers) choice = villagers.copy()
if ghost in var.ENTRANCED:
choice -= var.ROLES["succubus"]
var.OTHER_KILLS[ghost] = random.choice(list(choice))
# Select random totem recipients if shamans didn't act # Select random totem recipients if shamans didn't act
shamans = var.list_players(var.TOTEM_ORDER) shamans = var.list_players(var.TOTEM_ORDER)
@ -4261,7 +4268,6 @@ def transition_day(cli, gameid=0):
for player in var.ENTRANCED_DYING: for player in var.ENTRANCED_DYING:
victims.append(player) victims.append(player)
onlybywolves.discard(player) onlybywolves.discard(player)
killers[player].append("@succubus")
# remove duplicates # remove duplicates
victims_set = set(victims) victims_set = set(victims)
@ -4332,7 +4338,7 @@ def transition_day(cli, gameid=0):
pl = var.list_players() pl = var.list_players()
for v in pl: for v in pl:
if v in victims_set: if v in victims_set:
if "@succubus" in killers[v]: if v in var.ENTRANCED_DYING:
continue # bypass protections continue # bypass protections
numkills = victims.count(v) numkills = victims.count(v)
numtotems = var.PROTECTED.count(v) numtotems = var.PROTECTED.count(v)
@ -4532,10 +4538,6 @@ def transition_day(cli, gameid=0):
if victim not in bitten: if victim not in bitten:
message.append("The wolves' selected victim was not home last night, and avoided the attack.") message.append("The wolves' selected victim was not home last night, and avoided the attack.")
novictmsg = False novictmsg = False
elif victim in var.ENTRANCED_DYING:
message.append("\u0002{0}\u0002 seems to have died of a lack of faithfulness...".format(victim))
dead.append(victim)
novictmsg = False
elif protected.get(victim) == "totem": elif protected.get(victim) == "totem":
message.append(("\u0002{0}\u0002 was attacked last night, but their totem " + message.append(("\u0002{0}\u0002 was attacked last night, but their totem " +
"emitted a brilliant flash of light, blinding the attacker and " + "emitted a brilliant flash of light, blinding the attacker and " +
@ -5014,6 +5016,8 @@ def check_exchange(cli, actor, nick):
#some roles can act on themselves, ignore this #some roles can act on themselves, ignore this
if actor == nick: if actor == nick:
return False return False
if nick in var.ROLES["succubus"]:
return False # succubus cannot be affected by exchange totem, at least for now
if nick in var.EXCHANGED: if nick in var.EXCHANGED:
var.EXCHANGED.remove(nick) var.EXCHANGED.remove(nick)
actor_role = var.get_role(actor) actor_role = var.get_role(actor)
@ -5388,15 +5392,16 @@ def shoot(cli, nick, chan, rest):
var.GUNNERS[nick] -= 1 var.GUNNERS[nick] -= 1
rand = random.random() rand = random.random()
if victim in var.ROLES["succubus"]: # hardcoded chances for entranced targetting succubus if nick in var.ROLES["village drunk"]:
chances = (1, 0, 0, 0)
elif nick in var.ROLES["village drunk"]:
chances = var.DRUNK_GUN_CHANCES chances = var.DRUNK_GUN_CHANCES
elif nick in var.ROLES["sharpshooter"]: elif nick in var.ROLES["sharpshooter"]:
chances = var.SHARPSHOOTER_GUN_CHANCES chances = var.SHARPSHOOTER_GUN_CHANCES
else: else:
chances = var.GUN_CHANCES chances = var.GUN_CHANCES
if victim in var.ROLES["succubus"]:
chances = chances[:2] + (0,)
wolfvictim = victim in var.list_players(var.WOLF_ROLES) wolfvictim = victim in var.list_players(var.WOLF_ROLES)
realrole = var.get_role(victim) realrole = var.get_role(victim)
victimrole = var.get_reveal_role(victim) victimrole = var.get_reveal_role(victim)
@ -5514,7 +5519,7 @@ def kill(cli, nick, chan, rest):
victim2 = get_victim(cli, nick, victim2, False) victim2 = get_victim(cli, nick, victim2, False)
if not victim2: if not victim2:
return return
if is_safe(nick, victim): if is_safe(nick, victim2):
pm(cli, nick, "You may not target a succubus.") pm(cli, nick, "You may not target a succubus.")
return return
@ -5717,6 +5722,9 @@ def observe(cli, nick, chan, rest):
else: else:
pm(cli, nick, "Observing another wolf is a waste of time.") pm(cli, nick, "Observing another wolf is a waste of time.")
return return
if is_safe(nick, victim):
pm(cli, nick, "You may not observe a succubus.")
return
victim = choose_target(nick, victim) victim = choose_target(nick, victim)
if check_exchange(cli, nick, victim): if check_exchange(cli, nick, victim):
return return
@ -5771,7 +5779,9 @@ def investigate(cli, nick, chan, rest):
if victim == nick: if victim == nick:
pm(cli, nick, "Investigating yourself would be a waste.") pm(cli, nick, "Investigating yourself would be a waste.")
return return
if is_safe(nick, victim):
pm(cli, nick, "You may not investigate a succubus.")
return
victim = choose_target(nick, victim) victim = choose_target(nick, victim)
var.INVESTIGATED.add(nick) var.INVESTIGATED.add(nick)
vrole = var.get_role(victim) vrole = var.get_role(victim)
@ -5894,8 +5904,11 @@ def hvisit(cli, nick, chan, rest):
role = var.get_role(nick) role = var.get_role(nick)
if var.HVISITED.get(nick): if var.HVISITED.get(nick):
pm(cli, nick, ("You are already spending the night "+ if role == "harlot":
"with \u0002{0}\u0002.").format(var.HVISITED[nick])) pm(cli, nick, ("You are already spending the night "+
"with \u0002{0}\u0002.").format(var.HVISITED[nick]))
else:
pm(cli, nick, "You are already entrancing \u0002{0}\u0002 tonight.".format(var.HVISITED[nick]))
return return
victim = get_victim(cli, nick, re.split(" +",rest)[0], False, True) victim = get_victim(cli, nick, re.split(" +",rest)[0], False, True)
if not victim: if not victim:
@ -5916,9 +5929,12 @@ def hvisit(cli, nick, chan, rest):
pm(cli, victim, ("You are spending the night with \u0002{0}"+ pm(cli, victim, ("You are spending the night with \u0002{0}"+
"\u0002. Have a good time!").format(nick)) "\u0002. Have a good time!").format(nick))
if var.get_role(victim) == "succubus": if var.get_role(victim) == "succubus":
pm(cli, nick, "You have become entranced by \u0002{0}\u0002!".format(victim)) pm(cli, nick, ("You have become entranced by \u0002{0}\u0002. From this point on, "
pm(cli, victim, "You have entranced \u0002{0}\u0002.".format(nick)) "you must vote along with them or risk dying. For as long as they "
var.ENTRANCED.add(nick) "are alive, you \u0002cannot win with your own team\u0002, but you "
"will win if \u0002{0}\u0002 wins as well.").format(victim))
pm(cli, victim, "You have entranced \u0002{0}\u0002.".format(nick))
var.ENTRANCED.add(nick)
else: else:
if var.get_role(victim) != "succubus": if var.get_role(victim) != "succubus":
var.ENTRANCED.add(victim) var.ENTRANCED.add(victim)
@ -5927,33 +5943,38 @@ def hvisit(cli, nick, chan, rest):
pm(cli, victim, ("You are being entranced by \u0002{0}\u0002. From this point on, " pm(cli, victim, ("You are being entranced by \u0002{0}\u0002. From this point on, "
"you must vote along with them or risk dying. For as long as they " "you must vote along with them or risk dying. For as long as they "
"are alive, you \u0002cannot win with your own team\u0002, but you " "are alive, you \u0002cannot win with your own team\u0002, but you "
"will win along them if they are alive.").format(nick)) "will win if \u0002{0}\u0002 wins as well.").format(nick))
if var.OTHER_KILLS.get(victim) in var.ROLES["succubus"]: if var.OTHER_KILLS.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, "You have retracted your kill on \u0002{0}\u0002, a succubus.".format(nick)) # placeholder pm(cli, victim, "You discover that \u0002{0}\u0002 is a succubus and have retracted your kill as a result.".format(var.OTHER_KILLS[victim]))
del var.OTHER_KILLS[victim] del var.OTHER_KILLS[victim]
var.HUNTERS.discard(victim)
if var.TARGETED.get(victim) in var.ROLES["succubus"]: if var.TARGETED.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, "You have retracted your targetting on \u0002{0}\u0002, a succubus.".format(nick)) msg = "You discover that \u0002{0}\u0002 is a succubus and must now target someone else.".format(var.TARGETED[victim])
del var.TARGETED[victim] del var.TARGETED[victim]
if victim in var.ROLES["village drunk"]: if victim in var.ROLES["village drunk"]:
target = random.choice(list(set(var.list_players()) - var.ROLES["succubus"])) target = random.choice(list(set(var.list_players()) - var.ROLES["succubus"] - {victim}))
pm(cli, victim, "In your drunken stupor, you have selected \u0002{0}\u0002 as your target.".format(target)) msg += " In your drunken stupor, you have selected \u0002{0}\u0002 as your target.".format(target)
var.TARGETED[victim] = target var.TARGETED[victim] = target
if var.SHAMANS.get(victim, (None, None))[1] in var.ROLES["succubus"] and (var.get_role(victim) == "crazed shaman" or var.TOTEMS[victim] not in var.BENEFICIAL_TOTEMS): pm(cli, victim, nick)
pm(cli, victim, "You have retracted your totem on \u0002{0}\u0002, a succubus.".format(nick)) if (var.SHAMANS.get(victim, (None, None))[1] in var.ROLES["succubus"] and
(var.get_role(victim) == "crazed shaman" or var.TOTEMS[victim] not in var.BENEFICIAL_TOTEMS)):
pm(cli, victim, "You discover that \u0002{0}\u0002 is a succubus and have retracted your totem as a result.".format(var.SHAMANS[victim]))
del var.SHAMANS[victim] del var.SHAMANS[victim]
if victim in var.HEXED and var.LASTHEXED[victim] in var.ROLES["succubus"]: if victim in var.HEXED and var.LASTHEXED[victim] in var.ROLES["succubus"]:
pm(cli, victim, "You have retracted your hex on \u0002{0}\u0002, a succubus.".format(nick)) pm(cli, victim, "You discover that \u0002{0}\u0002 is a succubus and have retracted your hex as a result.".format(var.LASTHEXED[victim]))
var.TOBESILENCED.remove(nick) var.TOBESILENCED.remove(nick)
var.HEXED.remove(victim) var.HEXED.remove(victim)
del var.LASTHEXED[victim] del var.LASTHEXED[victim]
if set(var.KILLS.get(victim, ())) & var.ROLES["succubus"]: if set(var.KILLS.get(victim, ())) & var.ROLES["succubus"]:
pm(cli, victim, "You have retracted your kill on \u0002{0}\u0002, a succubus.".format(nick)) for s in var.ROLES["succubus"]:
var.KILLS[victim].remove(nick) if s in var.KILLS[victim]:
pm(cli, victim, "You discover that \u0002{0}\u0002 is a succubus and have retracted your kill as a result.".format(nick))
var.KILLS[victim].remove(s)
if not var.KILLS[victim]: if not var.KILLS[victim]:
del var.KILLS[victim] del var.KILLS[victim]
if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]: if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, "You are retracted your bite on \u0002{0}\u0002, a succubus.".format(nick)) pm(cli, victim, "You discover that \u0002{0}\u0002 is a succubus and have retracted your kill as a result.".format(var.BITE_PREFERENCES[victim]))
del var.BITE_PREFERENCES[victim] del var.BITE_PREFERENCES[victim]
debuglog("{0} ({1}) VISIT: {2} ({3})".format(nick, role, victim, var.get_role(victim))) debuglog("{0} ({1}) VISIT: {2} ({3})".format(nick, role, victim, var.get_role(victim)))
@ -5976,10 +5997,10 @@ def see(cli, nick, chan, rest):
if victim == nick: if victim == nick:
pm(cli, nick, "Seeing yourself would be a waste.") pm(cli, nick, "Seeing yourself would be a waste.")
return return
victim = choose_target(nick, victim) if is_safe(nick, victim):
if role == "doomsayer" and is_safe(nick, victim):
pm(cli, nick, "You may not see a succubus.") pm(cli, nick, "You may not see a succubus.")
return return
victim = choose_target(nick, victim)
if check_exchange(cli, nick, victim): if check_exchange(cli, nick, victim):
return return
victimrole = var.get_role(victim) victimrole = var.get_role(victim)
@ -6209,7 +6230,7 @@ def bite_cmd(cli, nick, chan, rest):
debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, var.get_role(nick), actual, var.get_role(actual))) debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, var.get_role(nick), actual, var.get_role(actual)))
chk_nightdone(cli) chk_nightdone(cli)
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("hunter","harlot","bodyguard","guardian angel","turncoat","warlock","piper")) @cmd("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("hunter","harlot","bodyguard","guardian angel","turncoat","warlock","piper","succubus","vigilante"))
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 = var.get_role(nick) nickrole = var.get_role(nick)
@ -6239,6 +6260,12 @@ def pass_cmd(cli, nick, chan, rest):
return return
var.HVISITED[nick] = None var.HVISITED[nick] = None
pm(cli, nick, "You have chosen to stay home for the night.") pm(cli, nick, "You have chosen to stay home for the night.")
elif nickrole == "succubus":
if var.HVISITED.get(nick):
pm(cli, nick, "You are already entrancing \u0002{0}\u0002 tonight.".format(var.HVISITED[nick]))
return
var.HVISITED[nick] = None
pm(cli, nick, "You have chosen to not entrance anyone tonight.")
elif nickrole == "bodyguard" or nickrole == "guardian angel": elif nickrole == "bodyguard" or nickrole == "guardian angel":
if var.GUARDED.get(nick): if var.GUARDED.get(nick):
pm(cli, nick, "You are already protecting someone tonight.") pm(cli, nick, "You are already protecting someone tonight.")
@ -6540,8 +6567,9 @@ def charm(cli, nick, chan, rest):
victim2 = get_victim(cli, nick, victim2, False, True) victim2 = get_victim(cli, nick, victim2, False, True)
if not victim2: if not victim2:
return return
if is_safe(nick, victim): if is_safe(nick, victim2):
pm(cli, nick, "You may not charm a succubus.") pm(cli, nick, "You may not charm a succubus.")
return
if victim == victim2: if victim == victim2:
pm(cli, nick, "You must choose two different people.") pm(cli, nick, "You must choose two different people.")