This repository has been archived on 2024-07-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
back-python/src/model/game.py
T
2024-04-26 16:07:57 +02:00

179 lines
6.2 KiB
Python

"""Instance of the game, with players and a market"""
import asyncio
from typing import List
import random
from model import Card, CardRole, CardParser, Player, Team, Serializable, Effect
from model.card_loader import load_cards, create_card_effects, create_card
class Game(Serializable):
"""Instance of the game, with players and a market"""
object_type = "game"
loaded_cards: List[CardParser] = load_cards()
cards: List[Card]
effects: List[Effect]
market_stack: List[Card]
market: List[Card]
gem_stack: List[Card]
players: List[Player]
teams: List[Team]
started: bool
default_health = 50
current_turn: Team
def __init__(self) -> None:
super().__init__()
self.market_stack: List[Card] = []
self.market: List[Card | None] = [None for _ in range(5)]
self.gem_stack: List[Card] = []
self.players: List[Player] = []
self.cards: List[Card] = []
self.effects: List[Effect] = []
self.teams: List[Team] = []
self.started = False
self.current_turn = None
async def init_game(self):
await self.init_cards()
await self.distribute_market_cards()
async def instanciate_card(self, card_parser: CardParser) -> Card:
effects, card_effects = create_card_effects(card_parser)
for e in card_effects:
self.effects.append(e)
await self.notify_controller("create", e.serialize())
card = create_card(card_parser, effects)
self.cards.append(card)
await self.notify_controller("create", card.serialize())
return card
async def init_cards(self):
"""Creates market cards and fire gem cards from previously loaded cards"""
market_only = [c for c in self.loaded_cards if c.role == CardRole.MARKET]
for c in market_only:
for _ in range(c.init_amount):
self.market_stack.append(await self.instanciate_card(c))
random.shuffle(self.market_stack)
fire_gems = [c for c in self.loaded_cards if c.role == CardRole.FIRE_GEM]
for c in fire_gems:
for _ in range(c.init_amount):
self.gem_stack.append(await self.instanciate_card(c))
async def create_base_deck(self, base_deck_name: str = "base") -> List[Card]:
"""Creates the starting base deck for a player.
Use base_deck_name to choose extensions characters"""
base_deck_loaded = [
c
for c in self.loaded_cards
if c.role == CardRole.PERSONAL and c.faction == base_deck_name
]
base_deck = []
for c in base_deck_loaded:
for _ in range(c.init_amount):
base_deck.append(await self.instanciate_card(c))
random.shuffle(base_deck)
return base_deck
async def create_player(self, username: str, team: Team | None = None) -> Player:
if team is None:
team = await self.create_team()
player = Player(self, username, team)
self.players.append(player)
player.stack_pile = await self.create_base_deck("base")
await self.notify_controller("create", player.turn.serialize())
await self.notify_controller("create", player.serialize_guest())
await self.notify_controller("update", self.serialize_guest())
return player
async def create_team(self) -> Team:
team = Team(health=self.default_health)
self.teams.append(team)
await self.notify_controller("create", team.serialize_guest())
return team
def get_player(self, username: str) -> Player | None:
players = [p for p in self.players if p.username == username]
if players and len(players) > 0:
return players[0]
return None
async def distribute_market_cards(self):
"""Tries to fill holes in the market with cards from the market stack"""
try:
while None in self.market:
self.market[self.market.index(None)] = self.market_stack.pop()
except IndexError:
print("no more cards in market_stack!")
finally:
await self.notify_controller("update", self.serialize_guest())
def serialize_guest(self) -> dict:
data = super().serialize_guest() | {
"cards": [card.uuid for card in self.cards],
"market_stack": [None for card in self.market_stack],
"market": [None if card is None else card.uuid for card in self.market],
"gem_stack": [card.uuid for card in self.gem_stack],
"players": [player.uuid for player in self.players],
"teams": [team.uuid for team in self.teams],
"started": self.started,
"default_health": self.default_health,
"current_turn": (
None if self.current_turn is None else self.current_turn.uuid
),
"effects": [effect.uuid for effect in self.effects],
}
return {k: data[k] for k in data.keys() - ["loaded_cards"]}
async def start_game(self):
self.started = True
self.current_turn = random.choice(self.teams)
await self.notify_controller("update", self.serialize_guest())
draws = []
for p in [p for p in self.players if p.team == self.current_turn]:
draws.append(p.draw(3))
for p in [p for p in self.players if p.team != self.current_turn]:
draws.append(p.draw(5))
await asyncio.gather(*draws)
await self.notify_controller("update", self.serialize_guest())
notifications = []
await asyncio.gather(*notifications)
print(
"start game with "
+ str(len(self.players))
+ " players : "
+ ", ".join([p.username for p in self.players])
)
async def end_turn(self):
team_index = self.teams.index(self.current_turn)
self.current_turn = self.teams[(team_index + 1) % len(self.teams)]
for p in self.players:
await p.start_turn()
await self.notify_controller("update", self.serialize_guest())
def search_card_in_pile(self, card_id: str, pile: List[Card]):
return next(
(m for m in [f for f in pile if f is not None] if str(m.uuid) == card_id),
None,
)