moar bugfixes

This commit is contained in:
Ryan Schmidt 2014-07-15 23:39:20 -05:00
parent 48553663d6
commit 9fde1ca0a2
2 changed files with 218 additions and 77 deletions

View File

@ -93,15 +93,18 @@ var.LOGGER = WolfgameLogger(var.LOG_FILENAME, var.BARE_LOG_FILENAME)
var.JOINED_THIS_GAME = [] # keeps track of who already joined this game at least once (cloaks) var.JOINED_THIS_GAME = [] # keeps track of who already joined this game at least once (cloaks)
if botconfig.DEBUG_MODE: if botconfig.DEBUG_MODE:
var.NIGHT_TIME_LIMIT = 240 # 90 var.NIGHT_TIME_LIMIT = 120 # 90
var.NIGHT_TIME_WARN = 180 var.NIGHT_TIME_WARN = 90
var.DAY_TIME_LIMIT_WARN = 780 var.DAY_TIME_LIMIT_WARN = 600
var.DAY_TIME_LIMIT_CHANGE = 120 var.DAY_TIME_LIMIT_CHANGE = 120
var.SHORT_DAY_LIMIT_WARN = 780 var.SHORT_DAY_LIMIT_WARN = 400
var.SHORT_DAY_LIMIT_CHANGE = 120 var.SHORT_DAY_LIMIT_CHANGE = 120
var.KILL_IDLE_TIME = 0 #300 var.KILL_IDLE_TIME = 0 #300
var.WARN_IDLE_TIME = 0 #180 var.WARN_IDLE_TIME = 0 #180
var.JOIN_TIME_LIMIT = 0 var.JOIN_TIME_LIMIT = 0
var.LEAVE_STASIS_PENALTY = 0
var.IDLE_STASIS_PENALTY = 0
var.PART_STASIS_PENALTY = 0
def connect_callback(cli): def connect_callback(cli):
@ -615,6 +618,9 @@ def stats(cli, nick, chan, rest):
if "wolf" in rs: if "wolf" in rs:
rs.remove("wolf") rs.remove("wolf")
rs.insert(0, "wolf") rs.insert(0, "wolf")
if "augur" in rs:
rs.remove("augur")
rs.insert(1, "augur")
if "oracle" in rs: if "oracle" in rs:
rs.remove("oracle") rs.remove("oracle")
rs.insert(1, "oracle") rs.insert(1, "oracle")
@ -623,7 +629,7 @@ def stats(cli, nick, chan, rest):
rs.insert(1, "seer") rs.insert(1, "seer")
if var.DEFAULT_ROLE in rs: if var.DEFAULT_ROLE in rs:
rs.remove(var.DEFAULT_ROLE) rs.remove(var.DEFAULT_ROLE)
rs.append(var.DEFAULT_ROLE) rs.append(var.DEFAULT_ROLE)
firstcount = len(var.ROLES[rs[0]]) firstcount = len(var.ROLES[rs[0]])
@ -760,9 +766,11 @@ def chk_decision(cli):
var.LOGGER.logBare(votee, "MAYOR REVEALED") var.LOGGER.logBare(votee, "MAYOR REVEALED")
votee = None votee = None
elif votee in var.REVEALED: elif votee in var.REVEALED:
role = var.get_reveal_role(votee)
an = "n" if role[0] in ("a", "e", "i", "o", "u") else ""
lmsg = ("Before the rope is pulled, \u0002{0}\u0002's totem emits a brilliant flash of light. " + lmsg = ("Before the rope is pulled, \u0002{0}\u0002's totem emits a brilliant flash of light. " +
"When the villagers are able to see again, they discover that {0} has escaped! " + "When the villagers are able to see again, they discover that {0} has escaped! " +
"The left-behind totem seems to have taken on the shape of a(n) \u0002{1}\u0002.").format(votee, var.get_reveal_role(votee)) "The left-behind totem seems to have taken on the shape of a{1} \u0002{2}\u0002.").format(votee, an, role)
var.LOGGER.logBare(votee, "ACTIVATED REVEALING TOTEM") var.LOGGER.logBare(votee, "ACTIVATED REVEALING TOTEM")
votee = None votee = None
else: else:
@ -796,8 +804,8 @@ def chk_decision(cli):
var.LOGGER.logBare(votee, "ACTIVATED DESPERATION TOTEM") var.LOGGER.logBare(votee, "ACTIVATED DESPERATION TOTEM")
var.LOGGER.logBare(target, "DESPERATION TOTEM TARGET") var.LOGGER.logBare(target, "DESPERATION TOTEM TARGET")
cli.msg(botconfig.CHANNEL, tmsg) cli.msg(botconfig.CHANNEL, tmsg)
del_player(cli, target, end_game = False) # do not end game just yet, we have more killin's to do! del_player(cli, target, True, end_game = False) # do not end game just yet, we have more killin's to do!
elif votee in var.ROLES["mad scientist"]: if votee in var.ROLES["mad scientist"]:
# kills the 2 players adjacent to them in the original players listing (in order of !joining) # kills the 2 players adjacent to them in the original players listing (in order of !joining)
# if those players are already dead, nothing happens # if those players are already dead, nothing happens
index = var.ALL_PLAYERS.index(votee) index = var.ALL_PLAYERS.index(votee)
@ -820,8 +828,8 @@ def chk_decision(cli):
var.LOGGER.logBare(target1, "DIED FROM SCIENTIST") var.LOGGER.logBare(target1, "DIED FROM SCIENTIST")
var.LOGGER.logBare(target2, "DIED FROM SCIENTIST") var.LOGGER.logBare(target2, "DIED FROM SCIENTIST")
cli.msg(botconfig.CHANNEL, tmsg) cli.msg(botconfig.CHANNEL, tmsg)
del_player(cli, target1, end_game = False) del_player(cli, target1, True, end_game = False)
del_player(cli, target2, end_game = False) del_player(cli, target2, True, end_game = False)
else: else:
if var.ROLE_REVEAL: if var.ROLE_REVEAL:
tmsg = ("While being dragged off, mad scientist \u0002{0}\u0002 throws " + tmsg = ("While being dragged off, mad scientist \u0002{0}\u0002 throws " +
@ -835,7 +843,7 @@ def chk_decision(cli):
var.LOGGER.logBare(votee, "MAD SCIENTIST") var.LOGGER.logBare(votee, "MAD SCIENTIST")
var.LOGGER.logBare(target1, "DIED FROM SCIENTIST") var.LOGGER.logBare(target1, "DIED FROM SCIENTIST")
cli.msg(botconfig.CHANNEL, tmsg) cli.msg(botconfig.CHANNEL, tmsg)
del_player(cli, target1, end_game = False) del_player(cli, target1, True, end_game = False)
else: else:
if target2 in var.list_players(): if target2 in var.list_players():
if var.ROLE_REVEAL: if var.ROLE_REVEAL:
@ -850,7 +858,7 @@ def chk_decision(cli):
var.LOGGER.logBare(votee, "MAD SCIENTIST") var.LOGGER.logBare(votee, "MAD SCIENTIST")
var.LOGGER.logBare(target2, "DIED FROM SCIENTIST") var.LOGGER.logBare(target2, "DIED FROM SCIENTIST")
cli.msg(botconfig.CHANNEL, tmsg) cli.msg(botconfig.CHANNEL, tmsg)
del_player(cli, target2, end_game = False) del_player(cli, target2, True, end_game = False)
else: else:
tmsg = ("While being dragged off, mad scientist \u0002{0}\u0002 throws " + tmsg = ("While being dragged off, mad scientist \u0002{0}\u0002 throws " +
"a potent chemical concoction into the crowd. Thankfully, " + "a potent chemical concoction into the crowd. Thankfully, " +
@ -1025,7 +1033,8 @@ def stop_game(cli, winner = ""):
plrl = [] plrl = []
for role,ppl in var.ORIGINAL_ROLES.items(): for role,ppl in var.ORIGINAL_ROLES.items():
for x in ppl: for x in ppl:
plrl.append((x, role)) if x != None:
plrl.append((x, role))
var.LOGGER.saveToFile() var.LOGGER.saveToFile()
@ -1054,16 +1063,11 @@ def stop_game(cli, winner = ""):
else: else:
won = False won = False
elif plr in [p for r in var.TRUE_NEUTRAL_ROLES for p in var.ORIGINAL_ROLES[r]]: elif plr in [p for r in var.TRUE_NEUTRAL_ROLES for p in var.ORIGINAL_ROLES[r]]:
# true neutral roles never have a team win, only individual wins # true neutral roles never have a team win (with exception of monsters), only individual wins
if winner == "": if winner == "":
break break
else: elif winner == "monsters" and plr in var.ORIGINAL_ROLES["monster"]:
won = False
elif plr in var.ORIGINAL_ROLES["monster"]:
if winner == "monsters":
won = True won = True
elif winner == "":
break
else: else:
won = False won = False
else: else:
@ -1135,7 +1139,7 @@ def chk_win(cli, end_game = True):
lwolves = len(var.list_players(var.WOLFCHAT_ROLES)) lwolves = len(var.list_players(var.WOLFCHAT_ROLES))
lrealwolves = len(var.list_players(var.WOLF_ROLES)) lrealwolves = len(var.list_players(var.WOLF_ROLES)) - len(var.ROLES["wolf cub"])
if var.PHASE == "day": if var.PHASE == "day":
for p in var.WOUNDED: for p in var.WOUNDED:
if p in var.WOLFCHAT_ROLES: if p in var.WOLFCHAT_ROLES:
@ -1232,14 +1236,16 @@ def del_player(cli, nick, forced_death = False, devoice = True, end_game = True)
continue # already died somehow continue # already died somehow
var.LOVERS[other].remove(nick) var.LOVERS[other].remove(nick)
if var.ROLE_REVEAL: if var.ROLE_REVEAL:
role = var.get_reveal_role(other)
an = "n" if role[0] in ("a", "e", "i", "o", "u") else ""
message = ("Saddened by the loss of their lover, \u0002{0}\u0002, " + message = ("Saddened by the loss of their lover, \u0002{0}\u0002, " +
"a \u0002{1}\u0002, commits suicide.").format(other, var.get_reveal_role(other)) "a{1} \u0002{2}\u0002, commits suicide.").format(other, an, role)
else: else:
message = "Saddened by the loss of their lover, \u0002{0}\u0002 commits suicide".format(other) message = "Saddened by the loss of their lover, \u0002{0}\u0002 commits suicide".format(other)
cli.msg(botconfig.CHANNEL, message) cli.msg(botconfig.CHANNEL, message)
var.LOGGER.logMessage(message.replace("\02", "")) var.LOGGER.logMessage(message.replace("\02", ""))
var.LOGGER.logBare(other, "DEAD LOVER") var.LOGGER.logBare(other, "DEAD LOVER")
del_player(cli, other, end_game = False) del_player(cli, other, True, end_game = False)
if nick in var.ROLES["assassin"]: if nick in var.ROLES["assassin"]:
target = var.TARGETED[nick] target = var.TARGETED[nick]
if target != None and target in var.list_players(): if target != None and target in var.list_players():
@ -1250,14 +1256,16 @@ def del_player(cli, nick, forced_death = False, devoice = True, end_game = True)
var.LOGGER.logMessage(message.replace("\02", "")) var.LOGGER.logMessage(message.replace("\02", ""))
else: else:
if var.ROLE_REVEAL: if var.ROLE_REVEAL:
role = var.get_reveal_role(target)
an = "n" if role[0] in ("a", "e", "i", "o", "u") else ""
message = ("Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat. " + message = ("Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat. " +
"The village mourns the loss of a \u0002{2}\u0002.").format(nick, target, var.get_reveal_role(target)) "The village mourns the loss of a{2} \u0002{3}\u0002.").format(nick, target, an, role)
else: else:
message = "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat.".format(nick, target) message = "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat.".format(nick, target)
cli.msg(botconfig.CHANNEL, message) cli.msg(botconfig.CHANNEL, message)
var.LOGGER.logMessage(message.replace("\02", "")) var.LOGGER.logMessage(message.replace("\02", ""))
var.LOGGER.logBare(target, "ASSASSINATED") var.LOGGER.logBare(target, "ASSASSINATED")
del_player(cli, target, end_game = False) del_player(cli, target, True, end_game = False)
if nick in var.CLONED: if nick in var.CLONED:
# clone is cloning nick, so clone becomes nick's role # clone is cloning nick, so clone becomes nick's role
clone = var.CLONED[nick] clone = var.CLONED[nick]
@ -1274,9 +1282,9 @@ def del_player(cli, nick, forced_death = False, devoice = True, end_game = True)
pm(cli, clone, "You will now be cloning \u0002{0}\u0002 if they die.".format(k)) pm(cli, clone, "You will now be cloning \u0002{0}\u0002 if they die.".format(k))
break break
if nick in var.ROLES["vengeful ghost"]: if nick in var.ROLES["vengeful ghost"]:
if var.PHASE == "night": if var.GHOSTPHASE == "night":
var.VENGEFUL_GHOSTS[nick] = "wolves" var.VENGEFUL_GHOSTS[nick] = "wolves"
elif var.PHASE == "day": elif var.GHOSTPHASE == "day":
var.VENGEFUL_GHOSTS[nick] = "villagers" var.VENGEFUL_GHOSTS[nick] = "villagers"
pm(cli, nick, ("OOOooooOOOOooo! You are the \u0002vengeful ghost\u0002. It is now your job " + pm(cli, nick, ("OOOooooOOOOooo! You are the \u0002vengeful ghost\u0002. It is now your job " +
"to exact your revenge on the \u0002{0}\u0002 that you believed killed you").format(var.VENGEFUL_GHOSTS[nick])) "to exact your revenge on the \u0002{0}\u0002 that you believed killed you").format(var.VENGEFUL_GHOSTS[nick]))
@ -1305,21 +1313,13 @@ def del_player(cli, nick, forced_death = False, devoice = True, end_game = True)
del var.KILLS[a] del var.KILLS[a]
elif a == nick: elif a == nick:
del var.KILLS[a] del var.KILLS[a]
for x in (var.OBSERVED, var.HVISITED, var.GUARDED, var.TARGETED): for x in (var.OBSERVED, var.HVISITED, var.GUARDED, var.TARGETED, var.LASTGUARDED, var.LASTGIVEN):
keys = list(x.keys()) keys = list(x.keys())
for k in keys: for k in keys:
if k == nick: if k == nick:
del x[k] del x[k]
elif x[k] == nick: elif x[k] == nick:
del x[k] del x[k]
lg = list(var.LASTGIVEN.items())
for k,v in lg:
if nick == v:
del var.LASTGIVEN[k]
lg = list(var.LASTGUARDED.items())
for k,v in lg:
if nick == v:
del var.LASTGUARDED[k]
if nick in var.DISCONNECTED: if nick in var.DISCONNECTED:
del var.DISCONNECTED[nick] del var.DISCONNECTED[nick]
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
@ -1556,7 +1556,7 @@ def on_nick(cli, prefix, nick):
dictvar.update(kvp) dictvar.update(kvp)
if prefix in dictvar.keys(): if prefix in dictvar.keys():
del dictvar[prefix] del dictvar[prefix]
for dictvar in (var.VENGEFUL_GHOSTS, var.TOTEM): for dictvar in (var.VENGEFUL_GHOSTS, var.TOTEMS):
if prefix in dictvar.keys(): if prefix in dictvar.keys():
dictvar[nick] = dictvar[prefix] dictvar[nick] = dictvar[prefix]
del dictvar[prefix] del dictvar[prefix]
@ -1749,11 +1749,12 @@ def begin_day(cli):
chan = botconfig.CHANNEL chan = botconfig.CHANNEL
# Reset nighttime variables # Reset nighttime variables
var.PHASE = "day" var.ANGRY_WOLVES = False
var.GHOSTPHASE = "day"
var.KILLS = {} # nicknames of kill victims (wolves only) var.KILLS = {} # nicknames of kill victims (wolves only)
var.OTHER_KILLS = {} # other kill victims (hunter/vengeful ghost/death totem) var.OTHER_KILLS = {} # other kill victims (hunter/vengeful ghost/death totem)
var.KILLER = "" # nickname of who chose the victim var.KILLER = "" # nickname of who chose the victim
var.SEEN = [] # list of seers/oracles that have had visions var.SEEN = [] # list of seers/oracles/augurs that have had visions
var.HEXED = [] # list of hags that have silenced others var.HEXED = [] # list of hags that have silenced others
var.SHAMANS = [] # list of shamans/crazed shamans that have acted var.SHAMANS = [] # list of shamans/crazed shamans that have acted
var.OBSERVED = {} # those whom werecrows/sorcerers have observed var.OBSERVED = {} # those whom werecrows/sorcerers have observed
@ -1800,6 +1801,7 @@ def transition_day(cli, gameid=0):
if var.PHASE == "day": if var.PHASE == "day":
return return
var.PHASE = "day"
var.GOATED = False var.GOATED = False
chan = botconfig.CHANNEL chan = botconfig.CHANNEL
@ -1836,12 +1838,12 @@ def transition_day(cli, gameid=0):
var.WOUNDED = [] var.WOUNDED = []
var.SILENCED = copy.copy(var.TOBESILENCED) var.SILENCED = copy.copy(var.TOBESILENCED)
var.DAY_START_TIME = datetime.now() var.DAY_START_TIME = datetime.now()
var.ANGRY_WOLVES = False
var.DAY_COUNT += 1 var.DAY_COUNT += 1
var.FIRST_DAY = (var.DAY_COUNT == 1) var.FIRST_DAY = (var.DAY_COUNT == 1)
havetotem = copy.copy(var.LASTGIVEN)
if (not len(var.SEEN)+len(var.KILLS)+len(var.OBSERVED) # neither seer nor wolf acted if (not len(var.SEEN)+len(var.KILLS)+len(var.OBSERVED) # neither seer nor wolf acted
and not var.START_WITH_DAY and var.FIRST_NIGHT and (var.ROLES["seer"] or var.ROLES["oracle"]) and not botconfig.DEBUG_MODE): and not var.START_WITH_DAY and var.FIRST_NIGHT and (var.ROLES["seer"] or var.ROLES["oracle"] or var.ROLES["augur"]) and not botconfig.DEBUG_MODE):
cli.msg(botconfig.CHANNEL, "\02The wolves all die of a mysterious plague.\02") cli.msg(botconfig.CHANNEL, "\02The wolves all die of a mysterious plague.\02")
for x in var.ROLES["traitor"] + var.list_players(var.WOLF_ROLES): for x in var.ROLES["traitor"] + var.list_players(var.WOLF_ROLES):
if not del_player(cli, x, True): if not del_player(cli, x, True):
@ -1914,6 +1916,8 @@ def transition_day(cli, gameid=0):
for victim in victims: for victim in victims:
var.LOGGER.logBare(victim, "VICTIM", *[y for x,y in var.KILLS.items() if x == victim]) var.LOGGER.logBare(victim, "VICTIM", *[y for x,y in var.KILLS.items() if x == victim])
for crow, target in iter(var.OBSERVED.items()): for crow, target in iter(var.OBSERVED.items()):
if crow not in var.ROLES["werecrow"]:
continue
if ((target in list(var.HVISITED.keys()) and var.HVISITED[target]) or # if var.HVISITED[target] is None, harlot visited self if ((target in list(var.HVISITED.keys()) and var.HVISITED[target]) or # if var.HVISITED[target] is None, harlot visited self
target in var.SEEN or target in var.SHAMANS or (target in list(var.GUARDED.keys()) and var.GUARDED[target])): target in var.SEEN or target in var.SHAMANS or (target in list(var.GUARDED.keys()) and var.GUARDED[target])):
pm(cli, crow, ("As the sun rises, you conclude that \u0002{0}\u0002 was not in "+ pm(cli, crow, ("As the sun rises, you conclude that \u0002{0}\u0002 was not in "+
@ -1968,8 +1972,10 @@ def transition_day(cli, gameid=0):
novictmsg = False novictmsg = False
else: else:
if var.ROLE_REVEAL: if var.ROLE_REVEAL:
message.append(("The dead body of \u0002{0}\u0002, a(n) \u0002{1}\u0002, is found. " + role = var.get_reveal_role(victim)
"Those remaining mourn the tragedy.").format(victim, var.get_reveal_role(victim))) an = "n" if role[0] in ("a", "e", "i", "o", "u") else ""
message.append(("The dead body of \u0002{0}\u0002, a{1} \u0002{2}\u0002, is found. " +
"Those remaining mourn the tragedy.").format(victim, an, role))
else: else:
message.append(("The dead body of \u0002{0}\u0002 is found. " + message.append(("The dead body of \u0002{0}\u0002 is found. " +
"Those remaining mourn the tragedy.").format(victim)) "Those remaining mourn the tragedy.").format(victim))
@ -2050,7 +2056,7 @@ def transition_day(cli, gameid=0):
"last night, and is now dead.").format(bodyguard)) "last night, and is now dead.").format(bodyguard))
var.LOGGER.logBare(bodyguard, "KILLEDWHENGUARDINGWOLF") var.LOGGER.logBare(bodyguard, "KILLEDWHENGUARDINGWOLF")
dead.append(bodyguard) dead.append(bodyguard)
for havetotem in var.LASTGIVEN.values(): for havetotem in havetotem.values():
message.append("\u0002{0}\u0002 seem{1} to be in possession of a mysterious totem...".format(havetotem, "ed" if havetotem in dead else "s")) message.append("\u0002{0}\u0002 seem{1} to be in possession of a mysterious totem...".format(havetotem, "ed" if havetotem in dead else "s"))
cli.msg(chan, "\n".join(message)) cli.msg(chan, "\n".join(message))
for msg in message: for msg in message:
@ -2081,6 +2087,7 @@ def transition_day(cli, gameid=0):
def chk_nightdone(cli): def chk_nightdone(cli):
# TODO: alphabetize and/or arrange sensibly
actedcount = len(var.SEEN + list(var.HVISITED.keys()) + list(var.GUARDED.keys()) + actedcount = len(var.SEEN + list(var.HVISITED.keys()) + list(var.GUARDED.keys()) +
list(var.KILLS.keys()) + list(var.OTHER_KILLS.keys()) + list(var.KILLS.keys()) + list(var.OTHER_KILLS.keys()) +
list(var.OBSERVED.keys()) + var.PASSED + var.HEXED + var.SHAMANS + list(var.OBSERVED.keys()) + var.PASSED + var.HEXED + var.SHAMANS +
@ -2089,7 +2096,7 @@ def chk_nightdone(cli):
var.ROLES["guardian angel"] + var.ROLES["bodyguard"] + var.ROLES["wolf"] + var.ROLES["guardian angel"] + var.ROLES["bodyguard"] + var.ROLES["wolf"] +
var.ROLES["werecrow"] + var.ROLES["sorcerer"] + var.ROLES["hunter"] + var.ROLES["werecrow"] + var.ROLES["sorcerer"] + var.ROLES["hunter"] +
list(var.VENGEFUL_GHOSTS.keys()) + var.ROLES["hag"] + var.ROLES["shaman"] + list(var.VENGEFUL_GHOSTS.keys()) + var.ROLES["hag"] + var.ROLES["shaman"] +
var.ROLES["crazed shaman"] + var.ROLES["assassin"]) var.ROLES["crazed shaman"] + var.ROLES["assassin"] + var.ROLES["augur"])
if var.FIRST_NIGHT: if var.FIRST_NIGHT:
actedcount += len(var.MATCHMAKERS + list(var.CLONED.keys())) actedcount += len(var.MATCHMAKERS + list(var.CLONED.keys()))
nightroles += var.ROLES["matchmaker"] + var.ROLES["clone"] nightroles += var.ROLES["matchmaker"] + var.ROLES["clone"]
@ -2440,6 +2447,11 @@ def kill(cli, nick, rest):
"you are physically unable to kill a villager.")) "you are physically unable to kill a villager."))
return return
pl = var.list_players() pl = var.list_players()
allwolves = var.list_players(var.WOLFTEAM_ROLES)
allvills = []
for p in pl:
if p not in allwolves:
allvills.append(p)
pll = [x.lower() for x in pl] pll = [x.lower() for x in pl]
matches = 0 matches = 0
@ -2478,6 +2490,14 @@ def kill(cli, nick, rest):
pm(cli, nick, "Suicide is bad. Don't do it.") pm(cli, nick, "Suicide is bad. Don't do it.")
return return
if nick in var.VENGEFUL_GHOSTS.keys():
if var.VENGEFUL_GHOSTS[nick] == "wolves" and victim not in allwolves:
pm(cli, nick, "You must target a wolf.")
return
elif var.VENGEFUL_GHOSTS[nick] == "villagers" and victim not in allvills:
pm(cli, nick, "You must target a villager.")
return
if role in ("wolf", "werecrow"): if role in ("wolf", "werecrow"):
if victim in var.list_players(var.WOLFCHAT_ROLES) or victim2 in var.list_players(var.WOLFCHAT_ROLES): if victim in var.list_players(var.WOLFCHAT_ROLES) or victim2 in var.list_players(var.WOLFCHAT_ROLES):
pm(cli, nick, "You may only kill villagers, not other wolves.") pm(cli, nick, "You may only kill villagers, not other wolves.")
@ -2642,7 +2662,7 @@ def observe(cli, nick, rest):
"to \u0002{0}'s\u0002 house. You will return after "+ "to \u0002{0}'s\u0002 house. You will return after "+
"collecting your observations when day begins.").format(victim)) "collecting your observations when day begins.").format(victim))
elif role == "sorcerer": elif role == "sorcerer":
if var.get_role(victim) in ("seer", "oracle"): if var.get_role(victim) in ("seer", "oracle", "augur"):
pm(cli, nick, ("After casting your ritual, you determine that \u0002{0}\u0002 " + pm(cli, nick, ("After casting your ritual, you determine that \u0002{0}\u0002 " +
"is a \u0002{1}\u0002!").format(victim, var.get_reveal_role(victim))) "is a \u0002{1}\u0002!").format(victim, var.get_reveal_role(victim)))
else: else:
@ -2774,8 +2794,8 @@ def see(cli, nick, rest):
cli.notice(nick, "You're not currently playing.") cli.notice(nick, "You're not currently playing.")
return return
role = var.get_role(nick) role = var.get_role(nick)
if role not in ("seer", "oracle"): if role not in ("seer", "oracle", "augur"):
pm(cli, nick, "Only a seer or an oracle may use this command.") pm(cli, nick, "Only a seer, oracle, or augur may use this command.")
return return
if var.PHASE != "night": if var.PHASE != "night":
pm(cli, nick, "You may only have visions at night.") pm(cli, nick, "You may only have visions at night.")
@ -2809,15 +2829,25 @@ def see(cli, nick, rest):
pm(cli, nick, "Seeing yourself would be a waste.") pm(cli, nick, "Seeing yourself would be a waste.")
return return
victimrole = var.get_role(victim) victimrole = var.get_role(victim)
if victimrole in ("wolf", "werecrow", "monster", "mad scientist", "wolf cub") or victim in var.ROLES["cursed villager"]: if role in ("seer", "oracle"):
victimrole = "wolf" if victimrole in ("wolf", "werecrow", "monster", "mad scientist", "wolf cub") or victim in var.ROLES["cursed villager"]:
elif victimrole in ("traitor", "hag", "sorcerer", "village elder", "time lord", "matchmaker", "villager", "cultist", "minion", "vengeful ghost", "lycan", "clone", "fool"): victimrole = "wolf"
victimrole = var.DEFAULT_ROLE elif victimrole in ("traitor", "hag", "sorcerer", "village elder", "time lord", "matchmaker", "villager", "cultist", "minion", "vengeful ghost", "lycan", "clone", "fool"):
elif role == "oracle": # Oracles never see specific roles, only generalizations victimrole = var.DEFAULT_ROLE
victimrole = var.DEFAULT_ROLE elif role == "oracle": # Oracles never see specific roles, only generalizations
pm(cli, nick, ("You have a vision; in this vision, "+ victimrole = var.DEFAULT_ROLE
"you see that \u0002{0}\u0002 is a "+ pm(cli, nick, ("You have a vision; in this vision, "+
"\u0002{1}\u0002!").format(victim, victimrole)) "you see that \u0002{0}\u0002 is a "+
"\u0002{1}\u0002!").format(victim, victimrole))
elif role == "augur":
aura = "blue"
if victimrole in var.WOLFTEAM_ROLES:
aura = "red"
elif victimrole in var.TRUE_NEUTRAL_ROLES:
aura = "grey"
pm(cli, nick, ("You have a vision; in this vision, " +
"you see that \u0002{0}\u0002 exudes " +
"a \u0002{1}\u0002 aura!").format(victim, aura))
var.SEEN.append(nick) var.SEEN.append(nick)
var.LOGGER.logBare(victim, "SEEN", nick) var.LOGGER.logBare(victim, "SEEN", nick)
chk_nightdone(cli) chk_nightdone(cli)
@ -3021,11 +3051,111 @@ def choose(cli, nick, rest):
@pmcmd("target") @pmcmd("target")
def target(cli, nick, rest): def target(cli, nick, rest):
pass if var.PHASE in ("none", "join"):
cli.notice(nick, "No game is currently running.")
return
elif nick not in var.list_players() or nick in var.DISCONNECTED.keys():
cli.notice(nick, "You're not currently playing.")
return
if nick not in var.ROLES["assassin"]:
pm(cli, nick, "Only an assassin may use this command.")
return
if nick in var.TARGETED and var.TARGETED[nick] != None:
pm(cli, nick, "You have already chosen a target.")
return
if nick in var.SILENCED:
pm(cli, nick, "You have been silenced, and are unable to use any special powers")
return
pieces = [p.strip().lower() for p in re.split(" +",rest)]
victim = pieces[0]
if not victim:
pm(cli, nick, "Not enough parameters")
return
pl = var.list_players()
pll = [x.lower() for x in pl]
matches = 0
for player in pll:
if victim == player:
target = player
break
if player.startswith(victim):
target = player
matches += 1
else:
if matches != 1:
pm(cli, nick, "\u0002{0}\u0002 is currently not playing.".format(victim))
return
victim = pl[pll.index(target)]
if nick == victim:
pm(cli, nick, "You may not target yourself.")
return
var.TARGETED[nick] = victim
pm(cli, nick, "You have selected \u0002{0}\u0002 as your target.".format(victim))
var.LOGGER.logBare(nick, "TARGETED", victim)
chk_nightdone(cli)
@pmcmd("hex") @pmcmd("hex")
def hex(cli, nick, rest): def hex(cli, nick, rest):
pass if var.PHASE in ("none", "join"):
cli.notice(nick, "No game is currently running.")
return
elif nick not in var.list_players() or nick in var.DISCONNECTED.keys():
cli.notice(nick, "You're not currently playing.")
return
if nick not in var.ROLES["hag"]:
pm(cli, nick, "Only a hag may use this command.")
return
if nick in var.HEXED:
pm(cli, nick, "You have already hexed someone tonight.")
return
if nick in var.SILENCED:
pm(cli, nick, "You have been silenced, and are unable to use any special powers")
return
pieces = [p.strip().lower() for p in re.split(" +",rest)]
victim = pieces[0]
if not victim:
pm(cli, nick, "Not enough parameters")
return
pl = var.list_players()
pll = [x.lower() for x in pl]
matches = 0
for player in pll:
if victim == player:
target = player
break
if player.startswith(victim):
target = player
matches += 1
else:
if matches != 1:
pm(cli, nick, "\u0002{0}\u0002 is currently not playing.".format(victim))
return
victim = pl[pll.index(target)]
if nick == victim:
pm(cli, nick, "You may not target yourself.")
return
vrole = var.get_role(victim)
if vrole in var.WOLFCHAT_ROLES:
pm(cli, nick, "Hexing another wolf would be a waste.")
return
var.HEXED.append(nick)
var.TOBESILENCED.append(victim)
pm(cli, nick, "You have cast a hex on \u0002{0}\u0002.".format(victim))
var.LOGGER.logBare(nick, "HEXED", victim)
chk_nightdone(cli)
@pmcmd("clone") @pmcmd("clone")
def clone(cli, nick, rest): def clone(cli, nick, rest):
@ -3158,7 +3288,7 @@ def transition_night(cli):
pm(cli, amn, "Your amnesia clears and you now remember what you are!") pm(cli, amn, "Your amnesia clears and you now remember what you are!")
numwolves = len(var.list_players(var.WOLF_ROLES)) numwolves = len(var.list_players(var.WOLF_ROLES))
if var.NIGHT_COUNT >= numwolves: if var.NIGHT_COUNT >= numwolves + 1:
for elder in var.ROLES["village elder"]: for elder in var.ROLES["village elder"]:
var.OTHER_KILLS[elder] = elder var.OTHER_KILLS[elder] = elder
@ -3190,7 +3320,7 @@ def transition_night(cli):
'your true identity, seers will see you as a regular villager.')) 'your true identity, seers will see you as a regular villager.'))
elif role == "sorcerer": elif role == "sorcerer":
pm(cli, wolf, ('You are a \u0002sorcerer\u0002. You can use "observe <nick>" to ' + pm(cli, wolf, ('You are a \u0002sorcerer\u0002. You can use "observe <nick>" to ' +
'observe someone and determine if they are the seer or the oracle. ' + 'observe someone and determine if they are the seer, oracle, or augur. ' +
'Only detectives can reveal your true identity, seers will see you ' + 'Only detectives can reveal your true identity, seers will see you ' +
'as a regular villager.')) 'as a regular villager.'))
elif role == "wolf cub": elif role == "wolf cub":
@ -3224,21 +3354,25 @@ def transition_night(cli):
pm(cli, wolf, "Players: "+", ".join(pl)) pm(cli, wolf, "Players: "+", ".join(pl))
if wolf in var.WOLF_GUNNERS.keys(): if wolf in var.WOLF_GUNNERS.keys():
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 "")) 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 ""))
if var.ANGRY_WOLVES and role in ("wolf", "werecrow"):
pm(cli, wolf, 'You are \u0002angry\u0002 tonight, and may kill two targets by using "kill <nick1> and <nick2>"')
for seer in var.list_players(["seer", "oracle"]): for seer in var.list_players(["seer", "oracle", "augur"]):
pl = ps[:] pl = ps[:]
random.shuffle(pl) random.shuffle(pl)
role = var.get_role(seer) role = var.get_role(seer)
pl.remove(seer) # remove self from list pl.remove(seer) # remove self from list
a = "a" a = "a"
if role == "oracle": if role in ("oracle", "augur"):
a = "an" a = "an"
if role == "seer": if role == "seer":
what = "the role of a player" what = "the role of a player"
elif role == "oracle": elif role == "oracle":
what = "whether or not a player is a wolf" what = "whether or not a player is a wolf"
elif role == "augur":
what = "which team a player is on"
else: else:
what = "??? (this is a bug, please report to admins)" what = "??? (this is a bug, please report to admins)"
@ -3425,7 +3559,7 @@ def transition_night(cli):
pm(cli, v_ghost, who.capitalize() + ": " + ", ".join(pl)) pm(cli, v_ghost, who.capitalize() + ": " + ", ".join(pl))
for ass in var.ROLES["assassin"]: for ass in var.ROLES["assassin"]:
if ass in var.TARGETED: if ass in var.TARGETED and var.TARGETED[ass] != None:
continue # someone already targeted continue # someone already targeted
pl = ps[:] pl = ps[:]
random.shuffle(pl) random.shuffle(pl)
@ -3688,6 +3822,8 @@ def start(cli, nick, chann_, rest):
for x in selected: for x in selected:
villagers.remove(x) villagers.remove(x)
var.ROLES[var.DEFAULT_ROLE] = villagers
# Now for the templates # Now for the templates
for template, restrictions in var.TEMPLATE_RESTRICTIONS.items(): for template, restrictions in var.TEMPLATE_RESTRICTIONS.items():
if template == "sharpshooter": if template == "sharpshooter":
@ -3699,7 +3835,8 @@ def start(cli, nick, chann_, rest):
# Handle gunner # Handle gunner
cannot_be_sharpshooter = var.list_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"]) cannot_be_sharpshooter = var.list_players(var.TEMPLATE_RESTRICTIONS["sharpshooter"])
for gunner in var.ROLES["gunner"]: gunner_list = copy.copy(var.ROLES["gunner"])
for gunner in gunner_list:
if gunner in var.ROLES["village drunk"]: if gunner in var.ROLES["village drunk"]:
var.GUNNERS[gunner] = (var.DRUNK_SHOTS_MULTIPLIER * math.ceil(var.SHOTS_MULTIPLIER * len(pl))) var.GUNNERS[gunner] = (var.DRUNK_SHOTS_MULTIPLIER * math.ceil(var.SHOTS_MULTIPLIER * len(pl)))
elif gunner not in cannot_be_sharpshooter and random.random() <= var.SHARPSHOOTER_CHANCE: elif gunner not in cannot_be_sharpshooter and random.random() <= var.SHARPSHOOTER_CHANCE:
@ -3714,8 +3851,6 @@ def start(cli, nick, chann_, rest):
if var.GOAT_HERDER: if var.GOAT_HERDER:
var.SPECIAL_ROLES["goat herder"] = [ nick ] var.SPECIAL_ROLES["goat herder"] = [ nick ]
var.ROLES[var.DEFAULT_ROLE] = villagers
cli.msg(chan, ("{0}: Welcome to Werewolf, the popular detective/social party "+ cli.msg(chan, ("{0}: Welcome to Werewolf, the popular detective/social party "+
"game (a theme of Mafia).").format(", ".join(pl))) "game (a theme of Mafia).").format(", ".join(pl)))
cli.mode(chan, "+m") cli.mode(chan, "+m")
@ -3724,11 +3859,11 @@ def start(cli, nick, chann_, rest):
# Handle amnesiac # Handle amnesiac
for amnesiac in var.ROLES["amnesiac"]: for amnesiac in var.ROLES["amnesiac"]:
role = var.get_role(amnesiac) for role in var.ROLES.keys():
tpls = var.get_templates(amnesiac) if role == "amnesiac":
var.ROLES[role].remove(amnesiac) continue
for tpl in tpls: if amnesiac in var.ROLES[role]:
var.ROLES[tpl].remove(amnesiac) var.ROLES[role].remove(amnesiac)
var.DAY_TIMEDELTA = timedelta(0) var.DAY_TIMEDELTA = timedelta(0)
var.NIGHT_TIMEDELTA = timedelta(0) var.NIGHT_TIMEDELTA = timedelta(0)
@ -3768,9 +3903,11 @@ def start(cli, nick, chann_, rest):
var.FIRST_NIGHT = True var.FIRST_NIGHT = True
if not var.START_WITH_DAY: if not var.START_WITH_DAY:
var.GHOSTPHASE = "night"
transition_night(cli) transition_night(cli)
else: else:
var.FIRST_DAY = True var.FIRST_DAY = True
var.GHOSTPHASE = "day"
transition_day(cli) transition_day(cli)
for cloak in list(var.STASISED.keys()): for cloak in list(var.STASISED.keys()):
@ -4204,7 +4341,8 @@ def myrole(cli, nick, chan, rest):
role = var.DEFAULT_ROLE role = var.DEFAULT_ROLE
elif role == "vengeful ghost" and nick not in var.VENGEFUL_GHOSTS.keys(): elif role == "vengeful ghost" and nick not in var.VENGEFUL_GHOSTS.keys():
role = var.DEFAULT_ROLE role = var.DEFAULT_ROLE
pm(cli, nick, "You are a(n) \02{0}{1}\02.".format(role, " assassin" if nick in var.ROLES["assassin"] and nick not in var.ROLES["amnesiac"] else "")) an = "n" if role[0] in ("a", "e", "i", "o", "u") else ""
pm(cli, nick, "You are a{0} \02{1}{2}\02.".format(an, role, " assassin" if nick in var.ROLES["assassin"] and nick not in var.ROLES["amnesiac"] else ""))
# Check for gun/bullets # Check for gun/bullets
if nick not in ps: if nick not in ps:
@ -4639,6 +4777,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
if who == botconfig.NICK or not who: if who == botconfig.NICK or not who:
cli.msg(chan, "No.") cli.msg(chan, "No.")
return return
pl = var.list_players()
if rol in var.ROLES.keys() or rol.startswith("gunner") or rol.startswith("sharpshooter"): if rol in var.ROLES.keys() or rol.startswith("gunner") or rol.startswith("sharpshooter"):
if rol.startswith("gunner") or rol.startswith("sharpshooter"): if rol.startswith("gunner") or rol.startswith("sharpshooter"):
rolargs = re.split(" +",rol, 1) rolargs = re.split(" +",rol, 1)
@ -4656,7 +4795,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS:
else: else:
cli.msg(chan, "Not a valid role.") cli.msg(chan, "Not a valid role.")
return return
if who in var.list_players(): if who in pl:
var.del_player(who) var.del_player(who)
var.ROLES[rol].append(who) var.ROLES[rol].append(who)
cli.msg(chan, "Operation successful.") cli.msg(chan, "Operation successful.")

View File

@ -87,6 +87,7 @@ ROLE_GUIDE = {# village roles
"villager" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), "villager" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
"seer" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ), "seer" : ( 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"oracle" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), "oracle" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
"augur" : ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ),
"village drunk" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ), "village drunk" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"harlot" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ), "harlot" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ),
"guardian angel" : ( 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ), "guardian angel" : ( 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 ),
@ -133,15 +134,15 @@ WOLFCHAT_ROLES = ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer"]
# Wins with the wolves, even if the roles are not necessarily wolves themselves # Wins with the wolves, even if the roles are not necessarily wolves themselves
WOLFTEAM_ROLES = ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist"] WOLFTEAM_ROLES = ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist"]
# These roles never win as a team, only ever individually (either instead of or in addition to the regular winners) # These roles never win as a team, only ever individually (either instead of or in addition to the regular winners)
TRUE_NEUTRAL_ROLES = ["vengeful ghost", "crazed shaman", "fool"] TRUE_NEUTRAL_ROLES = ["vengeful ghost", "crazed shaman", "fool", "monster", "clone"]
# 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 # 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 list. Templates not listed here are considered full roles instead # NB: if you want a template to apply to everyone, list it here but make the restrictions an empty list. Templates not listed here are considered full roles instead
TEMPLATE_RESTRICTIONS = {"cursed villager" : ["wolf", "wolf cub", "werecrow", "seer", "oracle", "fool"], TEMPLATE_RESTRICTIONS = {"cursed villager" : ["wolf", "wolf cub", "werecrow", "seer", "oracle", "augur", "fool"],
"gunner" : ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist", "fool", "lycan"], "gunner" : ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist", "fool", "lycan"],
"sharpshooter" : ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist", "fool", "lycan"], "sharpshooter" : ["wolf", "traitor", "werecrow", "hag", "wolf cub", "sorcerer", "minion", "cultist", "fool", "lycan"],
"mayor" : ["fool"], "mayor" : ["fool"],
"assassin" : ["seer", "harlot", "detective", "bodyguard", "guardian angel", "village drunk", "hunter", "shaman", "crazed shaman", "fool", "mayor", "wolf", "werecrow", "wolf cub", "traitor", "lycan"], "assassin" : ["seer", "augur", "oracle", "harlot", "detective", "bodyguard", "guardian angel", "village drunk", "hunter", "shaman", "crazed shaman", "fool", "mayor", "wolf", "werecrow", "wolf cub", "traitor", "lycan"],
"amnesiac" : ["villager", "cultist", "wolf", "wolf cub", "werecrow", "minion", "matchmaker", "village elder", "time lord", "clone", "mad scientist"], "amnesiac" : ["villager", "cultist", "wolf", "wolf cub", "werecrow", "minion", "matchmaker", "village elder", "time lord", "clone", "mad scientist"],
"bureaucrat" : [], "bureaucrat" : [],
} }
@ -270,6 +271,7 @@ class EvilVillageMode(object):
"villager" : ( 0 , 0 ), "villager" : ( 0 , 0 ),
"seer" : ( 0 , 0 ), "seer" : ( 0 , 0 ),
"oracle" : ( 1 , 1 ), "oracle" : ( 1 , 1 ),
"augur" : ( 0 , 0 ),
"village drunk" : ( 0 , 0 ), "village drunk" : ( 0 , 0 ),
"harlot" : ( 0 , 0 ), "harlot" : ( 0 , 0 ),
"guardian angel" : ( 0 , 0 ), "guardian angel" : ( 0 , 0 ),