From d174fc4d89003bafa46b99f32d7a4e8c5f4e9284 Mon Sep 17 00:00:00 2001 From: jacob1 Date: Sun, 16 Nov 2014 00:29:55 -0500 Subject: [PATCH] rolesets are randomly picked with varying frequencies / add a !game command to make certain rolesets more likely Not done, even if this is final it still needs more good rolesets to choose from --- modules/wolfgame.py | 86 +++++++++++++++++++++++++++++++++----------- settings/wolfgame.py | 34 ++++++++---------- 2 files changed, 81 insertions(+), 39 deletions(-) diff --git a/modules/wolfgame.py b/modules/wolfgame.py index bcd8d97..41edb10 100644 --- a/modules/wolfgame.py +++ b/modules/wolfgame.py @@ -69,10 +69,7 @@ var.PLAYERS = {} var.DCED_PLAYERS = {} var.ADMIN_TO_PING = None var.AFTER_FLASTGAME = None -var.PHASE = "none" # "join", "day", or "night" var.TIMERS = {} -var.DEAD = [] -var.NO_LYNCH = [] var.ORIGINAL_SETTINGS = {} @@ -81,15 +78,12 @@ var.LAST_SAID_TIME = {} var.GAME_START_TIME = datetime.now() # for idle checker only var.CAN_START_TIME = 0 var.GRAVEYARD_LOCK = threading.RLock() -var.GAME_ID = 0 var.STARTED_DAY_PLAYERS = 0 var.DISCONNECTED = {} # players who got disconnected 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.OPPED = False # Keeps track of whether the bot is opped if botconfig.DEBUG_MODE: @@ -207,13 +201,16 @@ def reset_modes_timers(cli): cmodes.append(("-q", deadguy+"!*@*")) mass_mode(cli, cmodes) -def reset(cli): - var.PHASE = "none" +def reset(): + var.PHASE = "none" # "join", "day", or "night" var.GAME_ID = 0 var.DEAD = [] var.ROLES = {"person" : []} - var.JOINED_THIS_GAME = [] + var.JOINED_THIS_GAME = [] # keeps track of who already joined this game at least once (cloaks) var.NO_LYNCH = [] + var.FGAMED = False + var.CURRENT_ROLESET = "default" + var.ROLESET_VOTES = {} #list of players who have used !game reset_settings() @@ -221,6 +218,7 @@ def reset(cli): dict.clear(var.PLAYERS) dict.clear(var.DCED_PLAYERS) dict.clear(var.DISCONNECTED) +reset() def make_stasis(nick, penalty): try: @@ -244,7 +242,7 @@ def forced_exit(cli, nick, *rest): # Admin Only stop_game(cli) else: reset_modes_timers(cli) - reset(cli) + reset() cli.quit("Forced quit from "+nick) @@ -259,7 +257,7 @@ def restart_program(cli, nick, *rest): stop_game(cli) else: reset_modes_timers(cli) - reset(cli) + reset() cli.quit("Forced restart from "+nick) raise SystemExit @@ -531,7 +529,7 @@ def kill_join(cli, chan): pl.sort(key=lambda x: x.lower()) msg = 'PING! {0}'.format(", ".join(pl)) reset_modes_timers(cli) - reset(cli) + reset() cli.msg(chan, msg) cli.msg(chan, 'The current game took too long to start and ' + 'has been canceled. If you are still active, ' + @@ -1265,9 +1263,9 @@ def stop_game(cli, winner = ""): var.PHASE = "writing files" var.LOGGER.saveToFile() - reset(cli) + reset() - # This must be after reset(cli) + # This must be after reset() if var.AFTER_FLASTGAME: var.AFTER_FLASTGAME() var.AFTER_FLASTGAME = None @@ -1286,7 +1284,7 @@ def chk_win(cli, end_game = True): if lpl == 0: #cli.msg(chan, "No more players remaining. Game ended.") reset_modes_timers(cli) - reset(cli) + reset() return True return False @@ -4802,13 +4800,14 @@ def cgamemode(cli, arg): if modeargs[0] in var.GAME_MODES.keys(): md = modeargs.pop(0) try: - gm = var.GAME_MODES[md](*modeargs) + gm = var.GAME_MODES[md][0](*modeargs) for attr in dir(gm): val = getattr(gm, attr) if (hasattr(var, attr) and not callable(val) and not attr.startswith("_")): var.ORIGINAL_SETTINGS[attr] = getattr(var, attr) setattr(var, attr, val) + var.CURRENT_ROLESET = md return True except var.InvalidModeException as e: cli.msg(botconfig.CHANNEL, "Invalid mode: "+str(e)) @@ -4849,9 +4848,20 @@ def start(cli, nick, chann_, rest): return if len(villagers) > var.MAX_PLAYERS: - cli.msg(chan, "{0}: At most \u0002{1}\u0002 players may play in this game mode.".format(nick, var.MAX_PLAYERS)) + cli.msg(chan, "{0}: At most \u0002{1}\u0002 players may play.".format(nick, var.MAX_PLAYERS)) return + if not var.FGAMED: + possiblerolesets = [] + for roleset in var.GAME_MODES.keys(): + if len(villagers) >= var.GAME_MODES[roleset][1] and len(villagers) <= var.GAME_MODES[roleset][2]: + possiblerolesets += [roleset]*var.GAME_MODES[roleset][3] + for roleset in var.ROLESET_VOTES.values(): + if roleset in possiblerolesets: #valid roleset for this number of players + possiblerolesets += [roleset]*5 + print(possiblerolesets) + cgamemode(cli, random.choice(possiblerolesets)) + for index in range(len(var.ROLE_INDEX) - 1, -1, -1): if var.ROLE_INDEX[index] <= len(villagers): addroles = {k:v[index] for k,v in var.ROLE_GUIDE.items()} @@ -5352,7 +5362,7 @@ def reset_game(cli, nick, chan, rest): stop_game(cli) else: reset_modes_timers(cli) - reset(cli) + reset() @pmcmd("rules") @@ -5586,12 +5596,14 @@ def listroles(cli, nick, chan, rest): #prepend player count if called without any arguments if not len(rest[0]) and pl > 0: txt += " {0}: There {1} \u0002{2}\u0002 playing.".format(nick, "is" if pl == 1 else "are", pl) + if var.PHASE in ["night", "day"]: + txt += " Using the {0} roleset.".format(var.CURRENT_ROLESET) #read game mode to get roles for if len(rest[0]) and not rest[0].isdigit(): #check for valid roleset ("roles" roleset is treated as invalid) if rest[0] != "roles" and rest[0] in var.GAME_MODES.keys(): - mode = var.GAME_MODES[rest[0]]() + mode = var.GAME_MODES[rest[0]][0]() if hasattr(mode, "ROLE_INDEX"): roleindex = getattr(mode, "ROLE_INDEX") if hasattr(mode, "ROLE_GUIDE"): @@ -5893,6 +5905,36 @@ def player_stats(cli, nick, chan, rest): def player_stats_pm(cli, nick, rest): player_stats(cli, nick, nick, rest) +@cmd('game', raw_nick = True) +def game(cli, nick, chan, rest): + """Votes to make a specific roleset more likely.""" + + nick, _, __, cloak = parse_nick(nick) + if var.PHASE == "none": + cli.notice(nick, "No game is currently running.") + return + if var.PHASE != "join": + cli.notice(nick, "Werewolf is already in play.") + return + if nick not in var.list_players(): + cli.notice(nick, "You're currently not playing.") + return + + if rest: + roleset = rest.split(' ')[0] + else: + cli.notice(nick, "No roleset specified.") + return + + if roleset in var.GAME_MODES.keys(): + if var.GAME_MODES[roleset][3] > 0: + var.ROLESET_VOTES[cloak] = roleset + cli.msg(chan, "{0} votes for the {1} roleset.".format(nick, roleset)) + else: + cli.notice(nick, "You can't vote for that roleset.") + else: + cli.notice(nick, "{0} isn't a valid roleset.".format(roleset)) + @cmd("fpull", admin_only=True) def fpull(cli, nick, chan, rest): @@ -6052,6 +6094,7 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: if cgamemode(cli, rest): cli.msg(chan, ('\u0002{}\u0002 has changed the game settings ' 'successfully.').format(nick)) + var.FGAMED = True def fgame_help(args=''): @@ -6060,7 +6103,10 @@ if botconfig.DEBUG_MODE or botconfig.ALLOWED_NORMAL_MODE_COMMANDS: if not args: return 'Available game mode setters: ' + ', '.join(var.GAME_MODES.keys()) elif args in var.GAME_MODES.keys(): - return var.GAME_MODES[args].__doc__ + if hasattr(var.GAME_MODES[args][0], "__doc__"): + return var.GAME_MODES[args][0].__doc__ + else: + return "Game mode {0} has no doc string".format(args) else: return 'Game mode setter \u0002{}\u0002 not found.'.format(args) diff --git a/settings/wolfgame.py b/settings/wolfgame.py index e4b117e..439adcc 100644 --- a/settings/wolfgame.py +++ b/settings/wolfgame.py @@ -283,9 +283,9 @@ def break_long_message(phrases, joinstr = " "): return message class InvalidModeException(Exception): pass -def game_mode(name): +def game_mode(name, minp, maxp, likelihood = 0): def decor(c): - GAME_MODES[name] = c + GAME_MODES[name] = (c, minp, maxp, likelihood) return c return decor @@ -296,7 +296,7 @@ def reset_roles(index): return newguide # TODO: implement more game modes -@game_mode("roles") +@game_mode("roles", 4, 30) class ChangedRolesMode(object): """Example: !fgame roles=wolf:1,seer:0,guardian angel:1""" @@ -338,19 +338,19 @@ class ChangedRolesMode(object): except ValueError: raise InvalidModeException("A bad value was used in mode roles.") -@game_mode("default") +@game_mode("default", 4, 24, 7) class DefaultMode(object): + """Default roleset.""" def __init__(self): # No extra settings, just an explicit way to revert to default settings pass # evilvillage is broken, disable for now -#@game_mode("evilvillage") +#@game_mode("evilvillage", 6, 18) class EvilVillageMode(object): + """Majority of the village is wolf aligned, safes must secretly try to kill the wolves.""" def __init__(self): - self.MIN_PLAYERS = 6 - self.MAX_PLAYERS = 18 self.DEFAULT_ROLE = "cultist" self.ROLE_INDEX = ( 6 , 10 , 15 ) self.ROLE_GUIDE = reset_roles(self.ROLE_INDEX) @@ -368,11 +368,10 @@ class EvilVillageMode(object): "fool" : ( 0 , 1 , 1 ), }) -@game_mode("classic") +@game_mode("classic", 4, 21, 3) class ClassicMode(object): + """Classic roleset from before all the changes.""" def __init__(self): - self.MIN_PLAYERS = 4 - self.MAX_PLAYERS = 21 self.ROLE_INDEX = ( 4 , 6 , 8 , 10 , 12 , 15 , 17 , 18 , 20 ) self.ROLE_GUIDE = reset_roles(self.ROLE_INDEX) self.ROLE_GUIDE.update({# village roles @@ -390,11 +389,10 @@ class ClassicMode(object): "gunner" : ( 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ), }) -@game_mode("rapidfire") +@game_mode("rapidfire", 6, 24, 2) class RapidFireMode(object): + """Many roles that lead to multiple chain deaths.""" def __init__(self): - self.MIN_PLAYERS = 6 - self.MAX_PLAYERS = 25 self.SHARPSHOOTER_CHANCE = 1 self.DAY_TIME_LIMIT = 480 self.DAY_TIME_WARN = 360 @@ -423,11 +421,10 @@ class RapidFireMode(object): "sharpshooter" : ( 0 , 0 , 1 , 1 , 1 , 1 , 1 ), }) -@game_mode("noreveal") +@game_mode("noreveal", 4, 21, 2) class NoRevealMode(object): + """Roles are not normally revealed when players are lynched or die.""" def __init__(self): - self.MIN_PLAYERS = 4 - self.MAX_PLAYERS = 21 self.ROLE_REVEAL = False self.ROLE_INDEX = ( 4 , 6 , 8 , 10 , 12 , 15 , 17 , 19 ) self.ROLE_GUIDE = reset_roles(self.ROLE_INDEX) @@ -452,11 +449,10 @@ class NoRevealMode(object): "cursed villager" : ( 0 , 1 , 1 , 1 , 1 , 1 , 2 , 2 ), }) -@game_mode("amnesia") +@game_mode("amnesia", 10, 24) class AmnesiaMode(object): + """Everyone gets assigned a random role on night 3.""" def __init__(self): - self.MIN_PLAYERS = 10 - self.MAX_PLAYERS = 24 self.DEFAULT_ROLE = "cultist" self.HIDDEN_AMNESIAC = False self.ROLE_INDEX = range(self.MIN_PLAYERS, self.MAX_PLAYERS + 1)