You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Fox-V3/werewolf/werewolf.py

235 lines
6.8 KiB

import discord
from discord.ext import commands
from redbot.core import Config
from redbot.core import RedContext
from redbot.core.bot import Red
from werewolf.builder import GameBuilder
from werewolf.game import Game
class Werewolf:
"""
Base to host werewolf on a guild
"""
def __init__(self, bot: Red):
self.bot = bot
self.config = Config.get_conf(self, identifier=87101114101119111108102, force_registration=True)
default_global = {}
default_guild = {
"role_id": None
7 years ago
}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
7 years ago
self.games = {} # Active games stored here, id is per guild
7 years ago
7 years ago
def __unload(self):
print("Unload called")
for game in self.games.values():
del game
@commands.command()
7 years ago
async def buildgame(self, ctx: RedContext):
gb = GameBuilder()
code = await gb.build_game(ctx)
if code is not None:
await ctx.send("Your game code is **{}**".format(code))
else:
await ctx.send("No code generated")
7 years ago
@commands.group()
async def wwset(self, ctx: RedContext):
7 years ago
"""
Base command to adjust settings. Check help for command list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
@commands.guild_only()
@wwset.command(name="role")
7 years ago
async def wwset_role(self, ctx: RedContext, role: discord.Role):
7 years ago
"""
Assign the game role
This role should not be manually assigned
"""
await self.config.guild(ctx.guild).role_id.set(role.id)
7 years ago
await ctx.send("Game role has been set to **{}**".format(role.name))
@commands.group()
async def ww(self, ctx: RedContext):
"""
Base command for this cog. Check help for the commands list.
"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
7 years ago
@commands.guild_only()
@ww.command()
7 years ago
async def new(self, ctx: RedContext, game_code=None):
"""
7 years ago
Create and join a new game of Werewolf
"""
7 years ago
game = await self._get_game(ctx, game_code)
7 years ago
if not game:
await ctx.send("Failed to start a new game")
else:
await ctx.send("Game is ready to join! Use `[p]ww join`")
@commands.guild_only()
7 years ago
@ww.command()
7 years ago
async def join(self, ctx: RedContext):
7 years ago
"""
Joins a game of Werewolf
"""
7 years ago
game = await self._get_game(ctx)
7 years ago
7 years ago
if not game:
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
7 years ago
return
7 years ago
await game.join(ctx.author, ctx.channel)
7 years ago
@commands.guild_only()
@ww.command()
async def code(self, ctx: RedContext, code):
"""
Adjust game code
"""
game = await self._get_game(ctx)
if not game:
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
return
await game.set_code(ctx, code)
@commands.guild_only()
@ww.command()
7 years ago
async def quit(self, ctx: RedContext):
"""
Quit a game of Werewolf
"""
7 years ago
game = await self._get_game(ctx)
7 years ago
7 years ago
await game.quit(ctx.author, ctx.channel)
7 years ago
@commands.guild_only()
@ww.command()
7 years ago
async def start(self, ctx: RedContext):
"""
Checks number of players and attempts to start the game
"""
game = await self._get_game(ctx)
if not game:
await ctx.send("No game running, cannot start")
7 years ago
await game.setup(ctx)
7 years ago
@commands.guild_only()
7 years ago
@ww.command()
7 years ago
async def stop(self, ctx: RedContext):
7 years ago
"""
Stops the current game
"""
7 years ago
if ctx.guild is None:
# Private message, can't get guild
await ctx.send("Cannot start game from PM!")
return
if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over:
await ctx.send("No game to stop")
return
7 years ago
7 years ago
game = await self._get_game(ctx)
7 years ago
game.game_over = True
7 years ago
await ctx.send("Game has been stopped")
7 years ago
@commands.guild_only()
7 years ago
@ww.command()
7 years ago
async def vote(self, ctx: RedContext, target_id: int):
7 years ago
"""
Vote for a player by ID
"""
7 years ago
try:
target_id = int(target_id)
except ValueError:
target_id = None
7 years ago
if target_id is None:
7 years ago
await ctx.send("`id` must be an integer")
return
7 years ago
7 years ago
# if ctx.guild is None:
7 years ago
# # DM nonsense, find their game
# # If multiple games, panic
# for game in self.games.values():
# if await game.get_player_by_member(ctx.author):
# break #game = game
# else:
# await ctx.send("You're not part of any werewolf game")
# return
7 years ago
# else:
7 years ago
game = await self._get_game(ctx)
7 years ago
7 years ago
if game is None:
await ctx.send("No game running, cannot vote")
return
7 years ago
# Game handles response now
channel = ctx.channel
7 years ago
if channel == game.village_channel:
await game.vote(ctx.author, target_id, channel)
7 years ago
elif channel in (c["channel"] for c in game.p_channels.values()):
await game.vote(ctx.author, target_id, channel)
7 years ago
else:
await ctx.send("Nothing to vote for in this channel")
7 years ago
7 years ago
@ww.command()
7 years ago
async def choose(self, ctx: RedContext, data):
7 years ago
"""
Arbitrary decision making
Handled by game+role
Can be received by DM
"""
7 years ago
7 years ago
if ctx.guild is not None:
await ctx.send("This action is only available in DM's")
return
7 years ago
7 years ago
# DM nonsense, find their game
# If multiple games, panic
for game in self.games.values():
if await game.get_player_by_member(ctx.author):
break # game = game
7 years ago
else:
await ctx.send("You're not part of any werewolf game")
return
await game.choose(ctx, data)
7 years ago
async def _get_game(self, ctx: RedContext, game_code=None):
7 years ago
if ctx.guild is None:
7 years ago
# Private message, can't get guild
7 years ago
await ctx.send("Cannot start game from PM!")
7 years ago
return None
7 years ago
if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over:
await ctx.send("Starting a new game...")
role_id = await self.config.guild(ctx.guild).role_id()
role = discord.utils.get(ctx.guild.roles, id=role_id)
if role is None:
7 years ago
await ctx.send("Game role is invalid, cannot start new game")
return None
7 years ago
self.games[ctx.guild.id] = Game(ctx.guild, role, game_code)
7 years ago
return self.games[ctx.guild.id]
async def _game_start(self, game):
await game.start()