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/Game.py

210 lines
5.4 KiB

import asyncio
import discord
from datetime import datetime,timedelta
7 years ago
from random import shuffle
from .builder import parse_code
class Game:
"""
Base class to run a single game of Werewolf
"""
7 years ago
def __new__(cls, game_code):
game_code = ["DefaultWerewolf", "Villager", "Villager""]
return Game(game_code)
7 years ago
def __init__(self, game_code):
self.roles = []
7 years ago
self.game_code = game_code
7 years ago
if self.game_code:
self.get_roles()
self.players = []
7 years ago
self.day_vote = {} # ID, votes
self.started = False
7 years ago
self.game_over = False
self.village_channel = None
self.secret_channels = {}
self.loop = asyncio.get_event_loop()
async def setup(self, ctx):
"""
Runs the initial setup
7 years ago
1. Assign Roles
2. Create Channels
2a. Channel Permissions :eyes:
3. Check Initial role setup (including alerts)
4. Start game
"""
7 years ago
if len(self.players) != self.roles:
ctx.send("Players does not match roles, cannot start")
return False
7 years ago
async def _cycle(self):
"""
Each event calls the next event
_at_start()
_at_day_start()
7 years ago
_at_voted()
7 years ago
_at_kill()
_at_day_end()
_at_night_begin()
_at_night_end()
and repeat with _at_morning_start() again
"""
await self._at_start():
7 years ago
async def _at_game_start(self): # ID 0
if self.game_over:
return
await self._notify(0)
asyncio.sleep(60)
await self._at_day_start()
7 years ago
async def _at_day_start(self): # ID 1
if self.game_over:
return
await self._notify(1)
asyncio.sleep(240) # 4 minute days
await self._at_day_end()
7 years ago
async def _at_voted(self, target): # ID 2
7 years ago
if self.game_over:
return
await self._notify(2, target)
async def _at_kill(self, target): # ID 3
if self.game_over:
return
await self._notify(3, target)
7 years ago
7 years ago
async def _at_hang(self, target): # ID 4
if self.game_over:
return
await self._notify(4, target)
async def _at_day_end(self): # ID 5
if self.game_over:
return
await self._notify(5)
asyncio.sleep(60)
await self._at_night_start()
7 years ago
async def _at_night_start(self): # ID 6
if self.game_over:
return
await self._notify(6)
asyncio.sleep(120) # 2 minutes
asyncio.sleep(90) # 1.5 minutes
asyncio.sleep(30) # .5 minutes
7 years ago
await self._at_night_end()
7 years ago
async def _at_night_end(self): # ID 7
if self.game_over:
return
await self._notify(7)
asyncio.sleep(15)
await self._at_day_start()
async def _notify(self, event, data=None):
for i in range(10):
tasks = []
7 years ago
role_order = [role for role in self.roles if role.action_list[event][1]==i]
for role in role_order:
tasks.append(asyncio.ensure_future(role.on_event(event, data))
# self.loop.create_task(role.on_event(event))
self.loop.run_until_complete(asyncio.gather(*tasks))
7 years ago
# Run same-priority task simultaneously
async def _generate_targets(self):
async def register_channel(self, channel_id):
7 years ago
async def join(self, member: discord.Member, channel: discord.Channel):
"""
7 years ago
Have a member join a game
"""
if self.started:
return "**Game has already started!**"
if member in self.players:
return "{} is already in the game!".format(member.mention)
self.started.append(member)
7 years ago
channel.send("{} has been added to the game, total players is **{}**".format(member.mention, len(self.players)))
7 years ago
async def quit(self, member: discord.Member):
"""
Have a member quit a game
"""
player = await self.get_player_by_member(member)
if not player:
return "You're not in a game!"
7 years ago
7 years ago
if self.started:
await self.kill()
if member in self.players:
return "{} is already in the game!".format(member.mention)
self.started.append(member)
7 years ago
channel.send("{} has been added to the game, total players is **{}**".format(member.mention, len(self.players)))
async def vote(self, author, id, channel):
"""
Member attempts to cast a vote (usually to lynch)
"""
player = self._get_player(author)
7 years ago
7 years ago
if player is None:
channel.send("You're not in this game!")
if not player.alive:
channel.send("Corpses can't vote")
try:
target = self.players[id]
except IndexError
7 years ago
7 years ago
async def get_roles(self, game_code=None):
if game_code:
self.game_code=game_code
7 years ago
if not self.game_code:
return False
7 years ago
self.roles = await parse_code(self.game_code)
if not self.roles:
7 years ago
return False