Add game structure
This commit is contained in:
parent
47aa7ace33
commit
0699c0f474
|
@ -5,4 +5,5 @@ __pycache__/
|
|||
venv/
|
||||
|
||||
config.yml
|
||||
game.save
|
||||
*.log
|
||||
|
|
142
orochi/bot.py
142
orochi/bot.py
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue