Make the bot re-attribute roles before sending PMs if the game ends on first night.

This commit is contained in:
Vgr E.Barry 2015-03-08 11:08:01 -04:00
parent 3857954d9e
commit 28f4e0a2dd

View File

@ -332,6 +332,7 @@ def reset_modes_timers(cli):
def reset(): def reset():
var.PHASE = "none" # "join", "day", or "night" var.PHASE = "none" # "join", "day", or "night"
var.GAME_ID = 0 var.GAME_ID = 0
var.RESTART_TRIES = 0
var.DEAD = [] var.DEAD = []
var.ROLES = {"person" : []} var.ROLES = {"person" : []}
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)
@ -1800,8 +1801,10 @@ def chk_traitor(cli):
'frightened as they hear a loud howl. The wolves are '+ 'frightened as they hear a loud howl. The wolves are '+
'not gone!\u0002')) 'not gone!\u0002'))
def stop_game(cli, winner = ""): def stop_game(cli, winner = "", abort = False):
chan = botconfig.CHANNEL chan = botconfig.CHANNEL
if abort:
cli.msg(chan, "The role attribution failed 3 times. Game was canceled.")
if var.DAY_START_TIME: if var.DAY_START_TIME:
now = datetime.now() now = datetime.now()
td = now - var.DAY_START_TIME td = now - var.DAY_START_TIME
@ -1820,7 +1823,9 @@ def stop_game(cli, winner = ""):
"\u0002{4:0>2}:{5:0>2}\u0002 was night. ").format(tmin, tsec, "\u0002{4:0>2}:{5:0>2}\u0002 was night. ").format(tmin, tsec,
daymin, daysec, daymin, daysec,
nitemin, nitesec) nitemin, nitesec)
cli.msg(chan, gameend_msg)
if not abort:
cli.msg(chan, gameend_msg)
roles_msg = [] roles_msg = []
@ -1863,24 +1868,25 @@ def stop_game(cli, winner = ""):
var.plural(role))) var.plural(role)))
message = "" message = ""
count = 0 count = 0
cli.msg(chan, var.break_long_message(roles_msg)) if not abort:
cli.msg(chan, var.break_long_message(roles_msg))
done = {} done = {}
lovers = [] lovers = []
for lover1, llist in var.ORIGINAL_LOVERS.items(): for lover1, llist in var.ORIGINAL_LOVERS.items():
for lover2 in llist: for lover2 in llist:
# check if already said the pairing # check if already said the pairing
if (lover1 in done and lover2 in done[lover1]) or (lover2 in done and lover1 in done[lover2]): if (lover1 in done and lover2 in done[lover1]) or (lover2 in done and lover1 in done[lover2]):
continue continue
lovers.append("\u0002{0}\u0002/\u0002{1}\u0002".format(lover1, lover2)) lovers.append("\u0002{0}\u0002/\u0002{1}\u0002".format(lover1, lover2))
if lover1 in done: if lover1 in done:
done[lover1].append(lover2) done[lover1].append(lover2)
else: else:
done[lover1] = [lover2] done[lover1] = [lover2]
if len(lovers) == 1 or len(lovers) == 2: if len(lovers) == 1 or len(lovers) == 2:
cli.msg(chan, "The lovers were {0}.".format(" and ".join(lovers))) cli.msg(chan, "The lovers were {0}.".format(" and ".join(lovers)))
elif len(lovers) > 2: elif len(lovers) > 2:
cli.msg(chan, "The lovers were {0}, and {1}".format(", ".join(lovers[0:-1]), lovers[-1])) cli.msg(chan, "The lovers were {0}, and {1}".format(", ".join(lovers[0:-1]), lovers[-1]))
# Only update if someone actually won, "" indicates everyone died or abnormal game stop # Only update if someone actually won, "" indicates everyone died or abnormal game stop
if winner != "": if winner != "":
@ -5142,6 +5148,10 @@ def transition_night(cli):
var.DYING.append(elder) var.DYING.append(elder)
debuglog(elder, "ELDER DEATH") debuglog(elder, "ELDER DEATH")
if var.FIRST_NIGHT and chk_win(cli, end_game=False): # prevent game from ending as soon as it begins (useful for the random game mode)
start(cli, botconfig.NICK, botconfig.CHANNEL, restart=var.CURRENT_GAMEMODE)
return
# game ended from bitten / amnesiac turning, narcolepsy totem expiring, or other weirdness # game ended from bitten / amnesiac turning, narcolepsy totem expiring, or other weirdness
if chk_win(cli): if chk_win(cli):
return return
@ -5669,15 +5679,22 @@ def fstart(cli, nick, chan, rest):
"""Starts a game of Werewolf.""" """Starts a game of Werewolf."""
start(cli, nick, chan) start(cli, nick, chan)
def start(cli, nick, chan, forced = False): def start(cli, nick, chan, forced = False, restart = ""):
if (not forced and var.LAST_START and nick in var.LAST_START and if (not forced and var.LAST_START and nick in var.LAST_START and
var.LAST_START[nick] + timedelta(seconds=var.START_RATE_LIMIT) > var.LAST_START[nick] + timedelta(seconds=var.START_RATE_LIMIT) >
datetime.now()): datetime.now() and not restart):
cli.notice(nick, ("This command is rate-limited. Please wait a while " cli.notice(nick, ("This command is rate-limited. Please wait a while "
"before using it again.")) "before using it again."))
return return
var.LAST_START[nick] = datetime.now() if restart:
var.RESTART_TRIES += 1
if var.RESTART_TRIES > 3:
stop_game(cli, abort=True)
return
if not restart:
var.LAST_START[nick] = datetime.now()
if chan != botconfig.CHANNEL: if chan != botconfig.CHANNEL:
return return
@ -5685,46 +5702,51 @@ def start(cli, nick, chan, forced = False):
villagers = var.list_players() villagers = var.list_players()
pl = villagers[:] pl = villagers[:]
if var.PHASE == "none": if not restart:
cli.notice(nick, "No game is currently running.") if var.PHASE == "none":
return cli.notice(nick, "No game is currently running.")
if var.PHASE != "join": return
cli.notice(nick, "Werewolf is already in play.") if var.PHASE != "join":
return cli.notice(nick, "Werewolf is already in play.")
if nick not in villagers and nick != chan and not forced: return
cli.notice(nick, "You're currently not playing.") if nick not in villagers and nick != chan and not forced:
return cli.notice(nick, "You're currently not playing.")
return
now = datetime.now() now = datetime.now()
var.GAME_START_TIME = now # Only used for the idler checker var.GAME_START_TIME = now # Only used for the idler checker
dur = int((var.CAN_START_TIME - now).total_seconds()) dur = int((var.CAN_START_TIME - now).total_seconds())
if dur > 0 and not forced: if dur > 0 and not forced:
plural = "" if dur == 1 else "s" plural = "" if dur == 1 else "s"
cli.msg(chan, "Please wait at least {0} more second{1}.".format(dur, plural)) cli.msg(chan, "Please wait at least {0} more second{1}.".format(dur, plural))
return return
if len(villagers) < var.MIN_PLAYERS: if len(villagers) < var.MIN_PLAYERS:
cli.msg(chan, "{0}: \u0002{1}\u0002 or more players are required to play.".format(nick, var.MIN_PLAYERS)) cli.msg(chan, "{0}: \u0002{1}\u0002 or more players are required to play.".format(nick, var.MIN_PLAYERS))
return return
if len(villagers) > var.MAX_PLAYERS: if len(villagers) > var.MAX_PLAYERS:
cli.msg(chan, "{0}: At most \u0002{1}\u0002 players may play.".format(nick, var.MAX_PLAYERS)) cli.msg(chan, "{0}: At most \u0002{1}\u0002 players may play.".format(nick, var.MAX_PLAYERS))
return return
if not var.FGAMED: if not var.FGAMED:
votes = {} #key = gamemode, not cloak votes = {} #key = gamemode, not cloak
for gamemode in var.GAMEMODE_VOTES.values(): for gamemode in var.GAMEMODE_VOTES.values():
if len(villagers) >= var.GAME_MODES[gamemode][1] and len(villagers) <= var.GAME_MODES[gamemode][2]: if len(villagers) >= var.GAME_MODES[gamemode][1] and len(villagers) <= var.GAME_MODES[gamemode][2]:
votes[gamemode] = votes.get(gamemode, 0) + 1 votes[gamemode] = votes.get(gamemode, 0) + 1
voted = [gamemode for gamemode in votes if votes[gamemode] == max(votes.values()) and votes[gamemode] >= len(villagers)/2] voted = [gamemode for gamemode in votes if votes[gamemode] == max(votes.values()) and votes[gamemode] >= len(villagers)/2]
if len(voted): if len(voted):
cgamemode(cli, random.choice(voted)) cgamemode(cli, random.choice(voted))
else: else:
possiblegamemodes = [] possiblegamemodes = []
for gamemode in var.GAME_MODES.keys(): for gamemode in var.GAME_MODES.keys():
if len(villagers) >= var.GAME_MODES[gamemode][1] and len(villagers) <= var.GAME_MODES[gamemode][2] and var.GAME_MODES[gamemode][3] > 0: if len(villagers) >= var.GAME_MODES[gamemode][1] and len(villagers) <= var.GAME_MODES[gamemode][2] and var.GAME_MODES[gamemode][3] > 0:
possiblegamemodes += [gamemode]*(var.GAME_MODES[gamemode][3]+votes.get(gamemode, 0)*15) possiblegamemodes += [gamemode]*(var.GAME_MODES[gamemode][3]+votes.get(gamemode, 0)*15)
cgamemode(cli, random.choice(possiblegamemodes)) cgamemode(cli, random.choice(possiblegamemodes))
else:
cgamemode(cli, restart)
var.GAME_ID = time.time() # restart reaper timer
for index in range(len(var.ROLE_INDEX) - 1, -1, -1): for index in range(len(var.ROLE_INDEX) - 1, -1, -1):
if var.ROLE_INDEX[index] <= len(villagers): if var.ROLE_INDEX[index] <= len(villagers):
@ -5734,7 +5756,7 @@ def start(cli, nick, chan, forced = False):
cli.msg(chan, "{0}: No game settings are defined for \u0002{1}\u0002 player games.".format(nick, len(villagers))) cli.msg(chan, "{0}: No game settings are defined for \u0002{1}\u0002 player games.".format(nick, len(villagers)))
return return
if var.ORIGINAL_SETTINGS: # Custom settings if var.ORIGINAL_SETTINGS and not restart: # Custom settings
while True: while True:
wvs = sum(addroles[r] for r in var.WOLFCHAT_ROLES) wvs = sum(addroles[r] for r in var.WOLFCHAT_ROLES)
if len(villagers) < (sum(addroles.values()) - sum([addroles[r] for r in var.TEMPLATE_RESTRICTIONS.keys()])): if len(villagers) < (sum(addroles.values()) - sum([addroles[r] for r in var.TEMPLATE_RESTRICTIONS.keys()])):
@ -5752,7 +5774,7 @@ def start(cli, nick, chan, forced = False):
return return
if var.ADMIN_TO_PING: if var.ADMIN_TO_PING and not restart:
if "join" in COMMANDS.keys(): if "join" in COMMANDS.keys():
COMMANDS["join"] = [lambda *spam: cli.msg(chan, "This command has been disabled by an admin.")] COMMANDS["join"] = [lambda *spam: cli.msg(chan, "This command has been disabled by an admin.")]
if "j" in COMMANDS.keys(): if "j" in COMMANDS.keys():
@ -5760,7 +5782,8 @@ def start(cli, nick, chan, forced = False):
if "start" in COMMANDS.keys(): if "start" in COMMANDS.keys():
COMMANDS["start"] = [lambda *spam: cli.msg(chan, "This command has been disabled by an admin.")] COMMANDS["start"] = [lambda *spam: cli.msg(chan, "This command has been disabled by an admin.")]
var.ALL_PLAYERS = copy.copy(var.ROLES["person"]) if not restart: # will already be stored if restarting
var.ALL_PLAYERS = copy.copy(var.ROLES["person"])
var.ROLES = {} var.ROLES = {}
var.GUNNERS = {} var.GUNNERS = {}
var.WOLF_GUNNERS = {} var.WOLF_GUNNERS = {}
@ -5879,9 +5902,10 @@ def start(cli, nick, chan, forced = False):
except ValueError: except ValueError:
break break
var.SPECIAL_ROLES["goat herder"] = [] if not restart:
if var.GOAT_HERDER: var.SPECIAL_ROLES["goat herder"] = []
var.SPECIAL_ROLES["goat herder"] = [ nick ] if var.GOAT_HERDER:
var.SPECIAL_ROLES["goat herder"] = [ nick ]
with var.WARNING_LOCK: # cancel timers with var.WARNING_LOCK: # cancel timers
for name in ("join", "join_pinger"): for name in ("join", "join_pinger"):
@ -5889,9 +5913,10 @@ def start(cli, nick, chan, forced = False):
var.TIMERS[name][0].cancel() var.TIMERS[name][0].cancel()
del var.TIMERS[name] del var.TIMERS[name]
cli.msg(chan, ("{0}: Welcome to Werewolf, the popular detective/social party "+ if not restart:
"game (a theme of Mafia). Using the \002{1}\002 game mode.").format(", ".join(pl), var.CURRENT_GAMEMODE)) cli.msg(chan, ("{0}: Welcome to Werewolf, the popular detective/social party "+
cli.mode(chan, "+m") "game (a theme of Mafia). Using the \002{1}\002 game mode.").format(", ".join(pl), var.CURRENT_GAMEMODE))
cli.mode(chan, "+m")
var.ORIGINAL_ROLES = copy.deepcopy(var.ROLES) # Make a copy var.ORIGINAL_ROLES = copy.deepcopy(var.ROLES) # Make a copy
@ -5940,6 +5965,8 @@ def start(cli, nick, chan, forced = False):
templates = "None" templates = "None"
debuglog("TEMPLATES:", templates) debuglog("TEMPLATES:", templates)
if restart:
var.PHASE = None # allow transition_* to run properly if game was restarted on first night
var.FIRST_NIGHT = True var.FIRST_NIGHT = True
if not var.START_WITH_DAY: if not var.START_WITH_DAY:
var.GAMEPHASE = "night" var.GAMEPHASE = "night"