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/
config.yml
game.save
*.log

View File

@ -1,3 +1,8 @@
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import pickle
import disnake
from disnake import CategoryChannel, PermissionOverwrite, TextChannel
from disnake.ext import commands
@ -6,10 +11,134 @@ import logging
from orochi.config import Config
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
async def on_ready():
global GAME
config: Config = bot.config
logger = bot.logger
@ -85,6 +214,19 @@ async def on_ready():
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:
channel: TextChannel = await secret_category.create_text_channel("bigbrain")
config.telepathy_channel = channel.id