Most of succubus
This commit is contained in:
parent
2421485875
commit
da81909162
@ -514,10 +514,12 @@ class RandomMode(GameMode):
|
||||
lcubs = addroles["wolf cub"]
|
||||
lrealwolves = sum(addroles[r] for r in var.WOLF_ROLES - {"wolf cub"})
|
||||
lmonsters = addroles["monster"]
|
||||
ldemoniacs = addroles["demoniacs"]
|
||||
ltraitors = addroles["traitor"]
|
||||
lpipers = addroles["piper"]
|
||||
lsuccubi = addroles["succubus"]
|
||||
|
||||
if chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ltraitors, lpipers, cli, end_game=False):
|
||||
if chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, 0, cli, end_game=False):
|
||||
return self.role_attribution(evt, cli, chk_win_conditions, var, villagers)
|
||||
|
||||
evt.prevent_default = True
|
||||
|
@ -260,6 +260,9 @@ SEEN_WOLF = WOLF_ROLES | {"monster", "mad scientist", "succubus"}
|
||||
SEEN_DEFAULT = frozenset({"traitor", "hag", "sorcerer", "time lord", "villager", "cultist", "minion", "turncoat", "amnesiac",
|
||||
"vengeful ghost", "lycan", "clone", "fool", "jester", "werekitten", "warlock", "piper", "doomsayer", "demoniac"})
|
||||
|
||||
# these totems are detrimental for the *receiving* person, but can be detrimental to someone else acting on the receiver!
|
||||
DETRIMENTAL_TOTEMS = frozenset({"death", "silence", "impatience", "pacifism", "narcolepsy", "exchange", "lycanthropy", "misdirection"})
|
||||
|
||||
# The roles in here are considered templates and will be applied on TOP of other roles. The restrictions are a list of roles that they CANNOT be applied to
|
||||
# NB: if you want a template to apply to everyone, list it here but make the restrictions an empty set. Templates not listed here are considered full roles instead
|
||||
TEMPLATE_RESTRICTIONS = OrderedDict([
|
||||
|
119
src/wolfgame.py
119
src/wolfgame.py
@ -2169,6 +2169,11 @@ def chk_decision(cli, force = ""):
|
||||
aftermessage = None
|
||||
votelist = copy.deepcopy(var.VOTES)
|
||||
for votee, voters in votelist.items():
|
||||
if votee in var.ROLES["succubus"]:
|
||||
for vtr in var.ENTRANCED:
|
||||
if vtr in voters:
|
||||
voters.remove(vtr)
|
||||
|
||||
impatient_voters = []
|
||||
numvotes = 0
|
||||
random.shuffle(var.IMPATIENT)
|
||||
@ -2533,6 +2538,8 @@ def stop_game(cli, winner = "", abort = False, additional_winners = None):
|
||||
won = True
|
||||
elif winner == "villagers":
|
||||
won = True
|
||||
elif winner == "succubi" and rol == "succubus":
|
||||
won = True
|
||||
|
||||
survived = var.list_players()
|
||||
if plr.startswith("(dced)"):
|
||||
@ -2598,6 +2605,8 @@ def stop_game(cli, winner = "", abort = False, additional_winners = None):
|
||||
iwon = False
|
||||
elif rol == "jester" and splr in var.JESTERS:
|
||||
iwon = True
|
||||
elif winner == "succubi" and plr in var.ROLES["succubi"] | var.ENTRANCED:
|
||||
iwon = True
|
||||
elif not iwon:
|
||||
iwon = won and splr in survived # survived, team won = individual win
|
||||
|
||||
@ -2672,6 +2681,8 @@ def chk_win(cli, end_game=True, winner=None):
|
||||
ldemoniacs = len(var.ROLES.get("demoniac", ()))
|
||||
ltraitors = len(var.ROLES.get("traitor", ()))
|
||||
lpipers = len(var.ROLES.get("piper", ()))
|
||||
lsuccubi = len(var.ROLES.get("succubus", ()))
|
||||
lentranced = len(var.ENTRANCED)
|
||||
if var.PHASE == "day":
|
||||
for p in var.WOUNDED | var.ASLEEP | var.CONSECRATING:
|
||||
try:
|
||||
@ -2683,9 +2694,9 @@ def chk_win(cli, end_game=True, winner=None):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, cli, end_game, winner)
|
||||
return chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, lentranced, cli, end_game, winner)
|
||||
|
||||
def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, cli, end_game=True, winner=None):
|
||||
def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, lentranced, cli, end_game=True, winner=None):
|
||||
"""Internal handler for the chk_win function."""
|
||||
chan = botconfig.CHANNEL
|
||||
with var.GRAVEYARD_LOCK:
|
||||
@ -2696,6 +2707,11 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs,
|
||||
elif lpl < 1:
|
||||
message = "Game over! There are no players remaining. Nobody wins."
|
||||
winner = "none"
|
||||
elif var.PHASE == "day" and lpl - lsuccubi <= lentranced: # entranced people
|
||||
winner = "succubi"
|
||||
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"
|
||||
"...").format(*(("us", "s", "s", "es") if lsuccubi == 1 else ("i", "ve", "", "")))
|
||||
elif var.PHASE == "day" and lpipers and len(var.list_players()) - lpipers == len(var.CHARMED - var.ROLES["piper"]):
|
||||
winner = "pipers"
|
||||
message = ("Game over! Everyone has fallen victim to the charms of the " +
|
||||
@ -2747,7 +2763,7 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs,
|
||||
lcubs = len(var.ROLES.get("wolf cub", ()))
|
||||
lrealwolves = len(var.list_players(var.WOLF_ROLES - {"wolf cub"}))
|
||||
ltraitors = len(var.ROLES.get("traitor", ()))
|
||||
return chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, cli, end_game)
|
||||
return chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs, ltraitors, lpipers, lsuccubi, lentranced, cli, end_game)
|
||||
|
||||
event = Event("chk_win", {"winner": winner, "message": message, "additional_winners": None})
|
||||
event.dispatch(var, lpl, lwolves, lrealwolves)
|
||||
@ -2778,6 +2794,9 @@ def chk_win_conditions(lpl, lwolves, lcubs, lrealwolves, lmonsters, ldemoniacs,
|
||||
elif winner == "pipers":
|
||||
for plr in var.ROLES["piper"]:
|
||||
players.append("{0} ({1})".format(plr, var.get_role(plr)))
|
||||
elif winner == "succubi":
|
||||
for plr in var.ROLES["succubus"] | var.ENTRANCED:
|
||||
players.append("{0} ({1})".format(plr, var.get_role(plr)))
|
||||
debuglog("WIN:", winner)
|
||||
debuglog("PLAYERS:", ", ".join(players))
|
||||
cli.msg(chan, message)
|
||||
@ -3621,6 +3640,9 @@ def rename_player(cli, prefix, nick):
|
||||
if prefix in var.CONSECRATING:
|
||||
var.CONSECRATING.remove(prefix)
|
||||
var.CONSECRATING.add(nick)
|
||||
if prefix in var.ENTRANCED:
|
||||
var.ENTRANCED.remove(prefix)
|
||||
var.ENTRANCED.add(nick)
|
||||
with var.GRAVEYARD_LOCK: # to be safe
|
||||
if prefix in var.LAST_SAID_TIME.keys():
|
||||
var.LAST_SAID_TIME[nick] = var.LAST_SAID_TIME.pop(prefix)
|
||||
@ -4677,10 +4699,11 @@ def chk_nightdone(cli):
|
||||
var.OTHER_KILLS, var.PASSED, var.OBSERVED,
|
||||
var.HEXED, var.SHAMANS, var.CURSED, var.CHARMERS)))
|
||||
|
||||
nightroles = get_roles("seer", "oracle", "harlot", "bodyguard", "guardian angel",
|
||||
"wolf", "werecrow", "alpha wolf", "sorcerer", "hunter",
|
||||
"hag", "shaman", "crazed shaman", "augur", "werekitten",
|
||||
"warlock", "piper", "wolf mystic", "fallen angel")
|
||||
nightroles = get_roles("seer", "oracle", "harlot", "succubus", "bodyguard",
|
||||
"guardian angel", "wolf", "werecrow", "alpha wolf",
|
||||
"sorcerer", "hunter", "hag", "shaman", "crazed shaman",
|
||||
"augur", "werekitten", "warlock", "piper", "wolf mystic",
|
||||
"fallen angel")
|
||||
|
||||
for ghost, against in var.VENGEFUL_GHOSTS.items():
|
||||
if not against.startswith("!"):
|
||||
@ -5335,7 +5358,8 @@ def shoot(cli, nick, chan, rest):
|
||||
if not del_player(cli, nick, killer_role = "villager"): # blame explosion on villager's shoddy gun construction or something
|
||||
return # Someone won.
|
||||
|
||||
|
||||
def is_safe(nick, victim): # helper function
|
||||
return nick in var.ENTRANCED and victim in var.ROLES["succubus"]
|
||||
|
||||
@cmd("kill", chan=False, pm=True, phases=("night",))
|
||||
def kill(cli, nick, chan, rest):
|
||||
@ -5388,10 +5412,16 @@ def kill(cli, nick, chan, rest):
|
||||
victim = get_victim(cli, nick, victim, False)
|
||||
if not victim:
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not target a succubus.")
|
||||
return
|
||||
if victim2 != None:
|
||||
victim2 = get_victim(cli, nick, victim2, False)
|
||||
if not victim2:
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not target a succubus.")
|
||||
return
|
||||
|
||||
if victim == nick or victim2 == nick:
|
||||
if nick in var.VENGEFUL_GHOSTS.keys():
|
||||
@ -5760,9 +5790,11 @@ def pray(cli, nick, chan, rest):
|
||||
|
||||
chk_nightdone(cli)
|
||||
|
||||
@cmd("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("harlot",))
|
||||
@cmd("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("harlot", "succubus"))
|
||||
def hvisit(cli, nick, chan, rest):
|
||||
"""Visit a player. You will die if you visit a wolf or a target of the wolves."""
|
||||
role = var.get_role(nick)
|
||||
|
||||
if var.HVISITED.get(nick):
|
||||
pm(cli, nick, ("You are already spending the night "+
|
||||
"with \u0002{0}\u0002.").format(var.HVISITED[nick]))
|
||||
@ -5779,12 +5811,45 @@ def hvisit(cli, nick, chan, rest):
|
||||
if check_exchange(cli, nick, victim):
|
||||
return
|
||||
var.HVISITED[nick] = victim
|
||||
pm(cli, nick, ("You are spending the night with \u0002{0}\u0002. "+
|
||||
"Have a good time!").format(victim))
|
||||
if nick != victim: #prevent luck/misdirection totem weirdness
|
||||
pm(cli, victim, ("You are spending the night with \u0002{0}"+
|
||||
"\u0002. Have a good time!").format(nick))
|
||||
debuglog("{0} ({1}) VISIT: {2} ({3})".format(nick, var.get_role(nick), victim, var.get_role(victim)))
|
||||
if role == "harlot":
|
||||
pm(cli, nick, ("You are spending the night with \u0002{0}\u0002. "+
|
||||
"Have a good time!").format(victim))
|
||||
if nick != victim: #prevent luck/misdirection totem weirdness
|
||||
pm(cli, victim, ("You are spending the night with \u0002{0}"+
|
||||
"\u0002. Have a good time!").format(nick))
|
||||
else:
|
||||
var.ENTRANCED.add(victim)
|
||||
pm(cli, nick, "You are entrancing \u0002{0}\u0002 tonight.".format(victim))
|
||||
if nick != victim:
|
||||
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 "
|
||||
"are alive, you \u0002cannot win with your own team\u0002, but you "
|
||||
"will win along them if they are alive.").format(nick))
|
||||
|
||||
if var.OTHER_KILLS.get(victim) == nick:
|
||||
pm(cli, victim, "You have retracted your kill on \u0002{0}\u0002.".format(nick)) # placeholder
|
||||
del var.OTHER_KILLS[victim]
|
||||
if var.TARGETED.get(victim) == nick:
|
||||
pm(cli, victim, "You have retracted your targetting on \u0002{0}\u0002.".format(nick))
|
||||
del var.TARGETED[victim]
|
||||
if var.SHAMANS.get(victim) == nick and var.TOTEMS[victim] in var.DETRIMENTAL_TOTEMS:
|
||||
pm(cli, victim, "You have retracted your totem on \u0002{0}\u0002.".format(nick))
|
||||
del var.SHAMANS[victim]
|
||||
if victim in var.HEXED and var.LASTHEXED[victim] == nick:
|
||||
pm(cli, victim, "You have retracted your hex on \u0002{0}\u0002.".format(nick))
|
||||
var.TOBESILENCED.remove(nick)
|
||||
var.HEXED.remove(victim)
|
||||
del var.LASTHEXED[victim]
|
||||
if nick in var.KILLS.get(victim, ()):
|
||||
pm(cli, victim, "You have retracted your kill on \u0002{0}\u0002.".format(nick))
|
||||
var.KILLS[victim].remove(nick)
|
||||
if not var.KILLS[victim]:
|
||||
del var.KILLS[victim]
|
||||
if var.BITE_PREFERENCES.get(victim) == nick:
|
||||
pm(cli, victim, "You are retracted your bite on \u0002{0}\u0002.".format(nick))
|
||||
del var.BITE_PREFERENCES[victim]
|
||||
|
||||
debuglog("{0} ({1}) VISIT: {2} ({3})".format(nick, role, victim, var.get_role(victim)))
|
||||
chk_nightdone(cli)
|
||||
|
||||
def is_fake_nick(who):
|
||||
@ -5870,6 +5935,9 @@ def totem(cli, nick, chan, rest, prefix="You"):
|
||||
role = var.get_role(nick)
|
||||
if role != "crazed shaman":
|
||||
totem = " of " + var.TOTEMS[nick]
|
||||
if is_safe(nick, victim) and var.TOTEMS[nick] in var.DETRIMENTAL_TOTEMS:
|
||||
pm(cli, nick, "You may not give a totem{0} to a succubus.".format(totem))
|
||||
return
|
||||
pm(cli, nick, ("{0} have given a totem{1} to \u0002{2}\u0002.").format(prefix, totem, original_victim))
|
||||
var.SHAMANS[nick] = (victim, original_victim)
|
||||
debuglog("{0} ({1}) TOTEM: {2} ({3})".format(nick, role, victim, totem))
|
||||
@ -5976,6 +6044,9 @@ def bite_cmd(cli, nick, chan, rest):
|
||||
if not victim:
|
||||
pm(cli, nick, "Please choose who to bite by specifying their nick.")
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not bite a succubus.")
|
||||
return
|
||||
|
||||
vrole = var.get_role(victim)
|
||||
actual = choose_target(nick, victim)
|
||||
@ -6179,6 +6250,10 @@ def target(cli, nick, chan, rest):
|
||||
pm(cli, nick, "You may not target yourself.")
|
||||
return
|
||||
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not target a succubus.")
|
||||
return
|
||||
|
||||
victim = choose_target(nick, victim)
|
||||
# assassin is a template so it will never get swapped, so don't check for exchanges with it
|
||||
var.TARGETED[nick] = victim
|
||||
@ -6205,6 +6280,10 @@ def hex_target(cli, nick, chan, rest):
|
||||
"You cannot hex the same person two nights in a row.").format(victim))
|
||||
return
|
||||
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not hex a succubus.")
|
||||
return
|
||||
|
||||
victim = choose_target(nick, victim)
|
||||
if check_exchange(cli, nick, victim):
|
||||
return
|
||||
@ -6245,6 +6324,9 @@ def curse(cli, nick, chan, rest):
|
||||
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
|
||||
if not victim:
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not curse a succubus.")
|
||||
return
|
||||
|
||||
# There may actually be valid strategy in cursing other wolfteam members,
|
||||
# but for now it is not allowed. If someone seems suspicious and shows as
|
||||
@ -6323,10 +6405,15 @@ def charm(cli, nick, chan, rest):
|
||||
victim = get_victim(cli, nick, victim, False, True)
|
||||
if not victim:
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not charm a succubus.")
|
||||
return
|
||||
if victim2 is not None:
|
||||
victim2 = get_victim(cli, nick, victim2, False, True)
|
||||
if not victim2:
|
||||
return
|
||||
if is_safe(nick, victim):
|
||||
pm(cli, nick, "You may not charm a succubus.")
|
||||
|
||||
if victim == victim2:
|
||||
pm(cli, nick, "You must choose two different people.")
|
||||
@ -7479,6 +7566,8 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
||||
var.BLESSED = set()
|
||||
var.PRIESTS = set()
|
||||
var.CONSECRATING = set()
|
||||
var.ENTRANCED = set()
|
||||
var.ENTRANCED_DYING = set()
|
||||
|
||||
var.DEADCHAT_PLAYERS = set()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user