Archived
179 lines
6.2 KiB
Python
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 = create_card_effects(card_parser)
|
|
for e in 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,
|
|
)
|