def join_player(self, player: PlayerLogic, is_admin: bool) -> None: if self.get_state() != GameLogic.State.WAITROOM: raise UserError("Невозможно присоединиться к запущенной игре", error_type=UserError.ErrorType.INVALID_GAME) if is_admin: player.make_admin() self.set_dirty()
def deal_roundcompleted(self, player: PlayerLogic, avg_spend: int): player_off_cards_count = len([ x for x in player.get_hand() if x.model.type.enumType == CardTypeEnum.OFFENCE ]) self.deal(player, self.card_manager.get_type(CardTypeEnum.OFFENCE), self.params.initial_offence_cards - player_off_cards_count) player_def_cards_count = len([ x for x in player.get_hand() if x.model.type.enumType == CardTypeEnum.DEFENCE ]) def_card_count = 0 if self.params.def_card_deal == DefCardDeal.DealFixed: def_card_count = self.params.def_card_deal_size elif self.params.def_card_deal == DefCardDeal.KeepSize: def_card_count = self.params.initial_defence_cards - player_def_cards_count elif self.params.def_card_deal == DefCardDeal.RemainingPlusFixed: def_card_count = player_def_cards_count + self.params.def_card_deal_size elif self.params.def_card_deal == DefCardDeal.DealPlayerCount: def_card_count = len(self.model.players) elif self.params.def_card_deal == DefCardDeal.DealAverageSpend: def_card_count = avg_spend def_card_count = max(0, def_card_count) self.deal(player, self.card_manager.get_type(CardTypeEnum.DEFENCE), def_card_count)
def complete_battle(self, battle: BattleLogic, bypass=False): if not bypass: self.assert_running() self.set_dirty() btl_model = battle.model if not bypass and btl_model.offensiveCard is None: raise UserError("Нельзя завершить битву без карты атаки!") if not bypass: self.calculate_battle_falsics(battle) btl_model.isComplete = True if self.cur_round.isAccidentComplete: next_player = self.get_neighbour( PlayerLogic(self.db, btl_model.offendingPlayer)) if next_player != self.get_players(True)[0].model: self.start_battle(PlayerLogic(self.db, next_player)) if all(map(lambda b: b.model.isComplete, self.get_battles())): if btl_model.offensiveCard is not None and btl_model.offensiveCard.type.enumType == CardTypeEnum.ACCIDENT: print("Round", self.cur_round.roundNo, "has accident completed") self.on_accident_played() else: print("Round", self.cur_round.roundNo, "is complete") self.on_round_completed() if not self.is_complete(): self.new_round()
def leave_player(self, player: PlayerLogic): player.leave() if self.is_running(): player.model.neighbourLeft.neighbourRight = player.model.neighbourRight for battle in self.get_battles(False): if battle.model.offendingPlayer == player.model \ or battle.model.defendingPlayer == player.model \ and not battle.model.isComplete: self.complete_battle(battle, True) self.db.session.delete(battle.model)
def play_card(self, card: CardLogic, player: PlayerLogic): if not self.can_play_card(card, player): raise UserError("Сейчас нельзя сыграть эту карту") self.set_dirty() battle = self.get_player_battle(player) if battle.offendingPlayer == player.model: battle.offensiveCard = card.model else: BattleLogic(self.db, battle).add_defensive_card(card) player.drop_card(card)
def prepare_state(game: GameLogic, player: PlayerLogic) -> GameState: pm = PlayerManager(db) if player is None: return GameState(redirect_to='/') players = game.get_players(False) round_number = 0 if game.cur_round is None else game.cur_round.roundNo ui_game = UiGame( game_name=game.model.uniqueCode, self_player=player.model.id, players=[ UiPlayer( id=p.model.id, name=p.model.name, is_admin=p.model.isAdmin, is_online=p.model.isOnline, has_left=p.model.hasLeft, on_offence=False, on_defence=False, neighbour_right=p.model.neighbourId, can_attack=game.can_attack(player, p), money=p.get_money(), ) for p in players ], hand=map_opt(lambda c: make_ui(c, game, player), player.get_hand()), current_battles=[battle.to_ui() for battle in game.get_battles(True)], round_no=round_number, is_complete=game.is_complete(), ) return GameState(redirect_to='', game=ui_game)
def can_play_card(self, card: CardLogic, player: PlayerLogic) -> bool: if not self.is_running(): return False my_battle = self.get_player_battle(player) if my_battle is None: return False if my_battle.isComplete: return False if my_battle.defendingPlayer is None: return False # Can't play a card we don't have if not any(map(lambda x: x.model == card.model, player.get_hand())): return False # If we're on offence if my_battle.offendingPlayer == player.model: # Card is already played if my_battle.offensiveCard is not None: return False return card.model.type.enumType == CardTypeEnum.OFFENCE # We're on defence then if card.model.type.enumType != CardTypeEnum.DEFENCE: return False cur_damage = BattleLogic(self.db, my_battle).get_curdamage() if cur_damage is None or cur_damage <= 0: # The round is either fully played, or has no offensive card yet return False return self.params.hardcore_mode or replace_none( card.get_defence_from(my_battle.offensiveCard), 0) > 0
def calculate_battle_falsics(self, battle: BattleLogic): btl_model = battle.model if btl_model.offensiveCard.isCovid: transfer_amount = btl_model.defendingPlayer.money // 2 PlayerLogic( self.db, self.get_neighbour( PlayerLogic(self.db, btl_model.defendingPlayer))).change_money( transfer_amount) PlayerLogic( self.db, btl_model.defendingPlayer).change_money(-transfer_amount) else: PlayerLogic(self.db, btl_model.defendingPlayer).change_money( -battle.get_curdamage())
def get_players(self, only_live): all_players = [ PlayerLogic(self.db, x, self) for x in self.model.players ] if only_live: return [p for p in all_players if p.is_alive()] else: return all_players
def create_player(self, name: str, game: 'GameLogic') -> PlayerLogic: player = Player(name=name, game=game.model, money=0, isAdmin=False, isOnline=False) self.db.session.add(player) try: self.db.session.commit() except IntegrityError as e: print("Player creation problem: " + str(e)) self.db.session.rollback() raise UserError("Игрок с таким именем уже существует. Пожалуйста, измените имя.", UserError.ErrorType.INVALID_NAME) return PlayerLogic(self.db, player)
def can_attack(self, me: PlayerLogic, defender: PlayerLogic): if not self.is_running(): return False if me.model == defender.model: # Logically, the rules don't forbid attacking self... But it's nonsense, right? # We don't have tail loss here, but the player might want to get rid of defense cards?.. return False if not defender.is_alive(): return False if not self.cur_round.isAccidentComplete: return False my_battle = self.get_player_battle(me) if my_battle is None: return False if my_battle.offendingPlayer != me.model: return False return my_battle.defendingPlayer is None
def start_battle(self, offendingPlayer: PlayerLogic): self.assert_running() new_battle_no = 0 if any(self.cur_round.battles): new_battle_no = max( map(lambda x: x.creationOrder, self.cur_round.battles)) + 1 new_battle = RoundBattle( round=self.cur_round, offendingPlayer=None if offendingPlayer is None else offendingPlayer.model, isComplete=False, creationOrder=new_battle_no) self.db.session.add(new_battle) self.set_dirty() if not self.params.can_attack_anyone: self.attack( offendingPlayer, PlayerLogic(self.db, self.get_neighbour(offendingPlayer), game=self)) return new_battle
def get_player(self, id: int) -> PlayerLogic: player = Player.query.filter_by(id=id).first() if player is None: return None return PlayerLogic(self.db, player)