Add game structure

This commit is contained in:
Yohann D'ANELLO 2021-11-05 11:12:02 +01:00
parent 47aa7ace33
commit 0699c0f474
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 143 additions and 0 deletions

1
.gitignore vendored
View File

@ -5,4 +5,5 @@ __pycache__/
venv/ venv/
config.yml config.yml
game.save
*.log *.log

View File

@ -1,3 +1,8 @@
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import pickle
import disnake import disnake
from disnake import CategoryChannel, PermissionOverwrite, TextChannel from disnake import CategoryChannel, PermissionOverwrite, TextChannel
from disnake.ext import commands from disnake.ext import commands
@ -6,10 +11,134 @@ import logging
from orochi.config import Config from orochi.config import Config
bot = commands.Bot(command_prefix='!') bot = commands.Bot(command_prefix='!')
GAME: "Game"
class Room(Enum):
A = 'A'
B = 'B'
C = 'C'
class Vote(Enum):
ALLY = 'A'
BETRAY = 'B'
@dataclass(frozen=True)
class Player:
name: str
private_channel_id: int = field(hash=False)
@property
def round_votes(self):
for r in GAME.rounds:
for room in r.rooms:
for vote in room.votes:
if self in vote.players:
yield vote
@property
def score(self):
s = 3
for vote in self.round_votes:
room = vote.room
other_vote = room.vote1 if room.vote1 is not vote else room.vote2
match vote.vote, other_vote.vote:
case Vote.ALLY, Vote.ALLY:
s += 2
case Vote.ALLY, Vote.BETRAY:
s -= 2
case Vote.BETRAY, Vote.ALLY:
s += 3
case Vote.BETRAY, Vote.BETRAY:
pass
return s
@dataclass
class RoundVote:
player1: Player
player2: Player | None
vote: Vote
timestamp: datetime
@property
def players(self):
return self.player1, self.player2
@property
def room(self):
for r in GAME.rounds:
for room in r.rooms:
if self in room.votes:
return room
@dataclass
class RoundRoom:
room: Room
vote1: RoundVote
vote2: RoundVote
@property
def votes(self):
return self.vote1, self.vote2
@property
def round(self):
for r in GAME.rounds:
if self in r.rooms:
return r
@dataclass
class Round:
round: int
room_a: RoundRoom
room_b: RoundRoom
room_c: RoundRoom
@property
def rooms(self):
return self.room_a, self.room_b, self.room_c
@dataclass
class Game:
rounds: list[Round] = field(default_factory=list)
players: dict[str, Player] = field(default_factory=dict)
def register_player(self, name: str, vote_channel_id: int) -> Player:
player = Player(name, vote_channel_id)
self.players[name] = player
return player
def save(self, filename: str) -> None:
"""
Uses pickle to save the current state of the game.
"""
with open(filename, 'wb') as f:
pickle.dump(self, f)
@classmethod
def load(cls, filename: str) -> "Game | None":
"""
Reload the game from a saved file.
"""
try:
with open(filename, 'rb') as f:
return pickle.load(f)
except FileNotFoundError:
return None
@bot.event @bot.event
async def on_ready(): async def on_ready():
global GAME
config: Config = bot.config config: Config = bot.config
logger = bot.logger logger = bot.logger
@ -85,6 +214,19 @@ async def on_ready():
role, overwrite=PermissionOverwrite(read_message_history=True, read_messages=True) role, overwrite=PermissionOverwrite(read_message_history=True, read_messages=True)
) )
GAME = Game.load('game.save')
if not GAME:
GAME = Game()
for player in config.PLAYERS:
GAME.register_player(player, config.vote_channels[player.lower()])
GAME.save('game.save')
# Update private channel id if necessary
for player in list(GAME.players.values()):
if player.private_channel_id != config.vote_channels[player.name.lower()]:
GAME.register_player(player.name, config.vote_channels[player.name.lower()])
GAME.save('game.save')
if not config.telepathy_channel: if not config.telepathy_channel:
channel: TextChannel = await secret_category.create_text_channel("bigbrain") channel: TextChannel = await secret_category.create_text_channel("bigbrain")
config.telepathy_channel = channel.id config.telepathy_channel = channel.id