示例#1
0
    def __init__(self, game, is_ai=False, ai_deck_id=None, use_this_deck=None):
        self.uid = "ai"
        self.game = game

        if is_ai:
            self.name = "AI"
            self.deck = Deck(self)
            self.hand = Hand(self)
            self.ground = Ground(self)
            self.graveyard = Graveyard(self)
            self.turn = Turn(self)
            self.ai = AI(self)

            # TODO make deck for ai, for now user id=2 is an ai
            from server.models import Player as DbPlayerr, Deck as DBDeckk
            db_player = DbPlayerr.objects.get(pk=2)

            if use_this_deck:
                ai_deck = use_this_deck
            elif ai_deck_id:
                ai_deck = DBDeckk.objects.get(pk=ai_deck_id)
            else:
                ai_deck = db_player.first_deck

            for db_card in ai_deck.get_cards(randomize=True):
                card = db_card.to_virtual(self)
                self.deck.add(card)
示例#2
0
    def add_player(self,
                   uid,
                   deck_id=None,
                   ai_deck_id=None,
                   inspector=False,
                   websocket=None):
        if uid == "ai":
            player = AIPlayer(game=self, is_ai=True, ai_deck_id=ai_deck_id)
        else:
            db_player = Player.objects.get(pk=uid)
            player = db_player.to_virtual(game=self)
            player.websocket = websocket
            player.inspector = inspector

            player.deck = Deck(player)
            if deck_id:
                deck = db_player.user.decks.get(pk=deck_id)
            else:
                deck = db_player.first_deck

            for db_card in deck.get_cards(randomize=True):
                card = db_card.to_virtual(player)
                player.deck.add(card)

            player.hand = Hand(player)
            player.ground = Ground(player)
            player.graveyard = Graveyard(player)
            player.turn = Turn(player)
            if inspector:
                player.ai = AI(player)
        self.players.append(player)
示例#3
0
 def __init__(self):
     GlobalVar.game_mode = self
     self.game_state = GlobalVar.game_state
     self.lista_player = []
     self.replicators = [self.game_state.replicator
                         ]  # metto il replicator del game state
     for p in self.game_state.lista_player:
         self.replicators.append(
             p.replicator)  # aggiungo tutti i replicator dei public player
     self.mazzo = Deck()
     self.server_socket = None
     self.running = True
     self.pausa = False
     self.primo_in_prima = 0  # giocatore primo in prima mano (gira ogni partita)
     self.primo = 0
     self.ultimo = 3
     self.seme_giro = None
     self.questo_giro = []
     self.tutti_connessi = False  # vero sse ci sono 4 giocatori connessi
     self.g_disconnessi = []
示例#4
0
class GameMode:
    def __init__(self):
        GlobalVar.game_mode = self
        self.game_state = GlobalVar.game_state
        self.lista_player = []
        self.replicators = [self.game_state.replicator
                            ]  # metto il replicator del game state
        for p in self.game_state.lista_player:
            self.replicators.append(
                p.replicator)  # aggiungo tutti i replicator dei public player
        self.mazzo = Deck()
        self.server_socket = None
        self.running = True
        self.pausa = False
        self.primo_in_prima = 0  # giocatore primo in prima mano (gira ogni partita)
        self.primo = 0
        self.ultimo = 3
        self.seme_giro = None
        self.questo_giro = []
        self.tutti_connessi = False  # vero sse ci sono 4 giocatori connessi
        self.g_disconnessi = []

    def attesa(self):
        while len(self.lista_player) < 4:
            try:
                new_socket, new_address = self.server_socket.accept()
                new_socket.settimeout(TIMEOUT)
                self.game_state.replicator.sockets.append(
                    new_socket)  # ha effetto solo lato server
                new_private = PlayerPrivate(new_socket, len(self.lista_player))
                self.lista_player.append(new_private)
                self.replicators.append(new_private.player_state.replicator
                                        )  # replicator del nuovo player state
                print('conncted', new_address)
            except timeout:
                pass
            safe_recv_var(
                self.replicators)  # comincio già a ricevere per i ceck
        self.tutti_connessi = True
        for g in self.game_state.lista_player:  # caccio una refreshata agli username
            g.username.rep_val()
        self.dai_carte()
        self.game_loop()

    def accetta_riconnessione(self):
        if len(self.g_disconnessi) > 0:
            try:
                new_socket, address = self.server_socket.accept()
                new_socket.settimeout(TIMEOUT)
                self.game_state.replicator.sockets.append(
                    new_socket
                )  # avevo rimosso il vecchio socket del disconnesso
                private = self.g_disconnessi.pop()
                private.socket = new_socket  # questo serve per poterlo ritogliere
                private.player_state.replicator.sockets = [
                    new_socket
                ]  # avevo svuotato ore metto il nuovo
                self.game_state.replicator.refresh_all(
                )  # refresh game_state a tutti, (basterebbe questo nuovo player)
                for p in self.game_state.lista_player:  # refresh tutti per tutti, non efficiente ma tanto viene
                    p.replicator.refresh_all(
                    )  # eseguito solo se uno esce e rientra
                private.player_state.replicator.refresh_all(
                )  # refresho sono per il player giusto
                if len(self.g_disconnessi) == 0:
                    self.tutti_connessi = True
            except timeout:
                pass

    def disconnetti(self, private):
        sock = private.socket
        self.game_state.replicator.sockets.remove(
            sock)  # tolgo il socket del disconnesso
        private.player_state.replicator.sockets = [
        ]  # ce ne è uno solo quindi posso fare così
        self.g_disconnessi.append(private)
        self.game_state.lista_player[
            private.player_state.index.
            val].username.val = '---'  # così gli altri lo vedono
        self.tutti_connessi = False

    def dai_carte(self):
        self.mazzo.carte = []
        self.mazzo.crea_carte()
        self.mazzo.mischia()
        for giocatore in self.lista_player:
            carte = self.mazzo.pesca_n(13)
            for c in carte:
                giocatore.player_state.mano.val.append(c)
            giocatore.player_state.mano.rep_val()

    def game_loop(self):
        self.game_state.fase_gioco.val = Fase.PASSAGGIO_CARTE
        while self.running:
            safe_recv_var(self.replicators)
            self.accetta_riconnessione()

    def carta_client(
        self, index_g, carta
    ):  # controlla in che fase siamo e se si può adoperare la carta e poi faù
        giocatore = self.lista_player[
            index_g]  # giocatore è un private player type
        if Card.contiene_carta(giocatore.player_state.mano.val,
                               carta):  # se possiede davvero questa carta
            if self.game_state.fase_gioco.val == Fase.PASSAGGIO_CARTE:  # se le stiamo passando la metto nelle scambiate
                if len(giocatore.player_state.scambiate.val
                       ) < 3:  # se non ne ho già scambiate 3
                    self.metti_in_passate(giocatore, carta)
            elif self.game_state.fase_gioco.val == Fase.GIOCO and (
                    not self.pausa):  # se stiamo giocando e non è pausa
                if index_g == self.game_state.turno.val:  # se è il suo turno
                    if (index_g == self.primo or Card.carta_permessa(
                            giocatore.player_state.mano.val, self.seme_giro,
                            carta)):
                        self.metti_in_giocata(index_g, carta)

    def metti_in_giocata(self, index, carta):
        Card.del_carta(self.lista_player[index].player_state.mano.val,
                       carta)  # tolgo la carta dalla mano
        self.lista_player[index].player_state.mano.rep_val(
        )  # non lo fa in automatico credo
        self.game_state.lista_player[
            index].carta_giocata.val = carta  # la metto nelle giocate
        self.questo_giro.append(
            carta)  # mi salvo le carte giocate nella gamemode
        if self.game_state.turno.val == self.primo:
            self.seme_giro = carta.seme  # il primo decide il seme del giro
        if self.game_state.turno.val == self.ultimo:
            self.risolvi_questo_giro()
        else:
            turno = (self.game_state.turno.val + 1) % 4
            self.game_state.turno.val = turno

    def metti_in_passate(self, giocatore, carta):
        Card.del_carta(giocatore.player_state.mano.val,
                       carta)  # tolgo la carta dalla mano
        giocatore.player_state.mano.rep_val()  # non lo fa in automatico credo
        giocatore.player_state.scambiate.val.append(
            carta)  # la metto in quelle scambiate
        giocatore.player_state.scambiate.rep_val()
        self.ceck_fine_passaggio()

    def ceck_fine_passaggio(self):
        for gioc in self.lista_player:
            state = gioc.player_state
            if len(state.scambiate.val) < 3:
                return
        self.passa_carte(
        )  # si occupa anche di fare self.game_state.fase_gioco.val = GIOCO

    def passa_carte(self):
        for gioc in self.lista_player:
            state = gioc.player_state
            index = (self.lista_player.index(gioc) -
                     1) % 4  # prendo il giocatore precedente
            for carta in state.scambiate.val:
                self.lista_player[index].player_state.mano.val.append(
                    carta)  # gli passo la carta
            self.lista_player[index].player_state.mano.rep_val()
            self.game_state.fase_gioco.val = Fase.GIOCO
            state.scambiate.val = []  # tolgo tutte le scambiate

    def calcola_punteggio(self):
        punteggio = 10  # valore di base
        for carta in self.questo_giro:  # contro punti negativi
            if carta.seme == Card.CUORI:
                punteggio -= carta.valore  # il valore della carta solo già i punti neg per i cuori
            elif carta.seme == Card.PICCHE and carta.valore == Card.DONNA:  # se è cuneconda
                punteggio -= 26
        return punteggio

    def trova_vincitore(self):
        val_max = self.questo_giro[0].valore  # trovo carta vincente
        index_max = 0
        for carta in self.questo_giro:
            if carta.seme == self.seme_giro:  # se è seme che comanda
                if carta.valore > val_max:  # se è più grande del max
                    val_max = carta.valore
                    index_max = self.questo_giro.index(carta)
        # adesso index_max è il primo ma contato a partire dal primo attuale quindi è di quanto devo spostarmi
        vincitore = (self.primo + index_max) % 4
        return vincitore

    def risolvi_questo_giro(self):
        punteggio = self.calcola_punteggio()
        vincitore = self.trova_vincitore()
        print('punteggio: ' + str(punteggio) + ' a ' + str(vincitore))
        self.primo = vincitore
        self.ultimo = (self.primo - 1) % 4
        self.pausa = True
        self.lista_player[vincitore].punteggio += punteggio  # assegno i punti
        self.lista_player[
            vincitore].carte_prese += self.questo_giro  # metto tutte le carte giocate nelle prese di vinc
        self.questo_giro = []  # svuoto copia locale
        t = Timer(5, self.fine_turno)  # lascio vedere le carte per 5 sec
        t.start()

    @staticmethod
    def ha_preso_carta(giocatore, carta):
        for c in giocatore.carte_prese:
            if c.seme == carta.seme and c.valore == carta.valore:
                return True
        return False

    def check_cappotto(self):
        for g_esaminato in self.lista_player:
            if GameMode.ha_preso_carta(g_esaminato,
                                       Card(Card.DONNA,
                                            Card.PICCHE)):  # se ha cunegonda
                for val in Card.VALORI:
                    if not GameMode.ha_preso_carta(
                            g_esaminato, Card(val,
                                              Card.CUORI)):  # manca un cuore
                        return  # se quello che ha la cune non ha un cuore allora niente cappotto
                # se arrivo qui allor aho cappotto quindi setto tutti a -20 tranne g a cui do 60
                for g_da_cambiare in self.lista_player:
                    if g_da_cambiare == g_esaminato:
                        g_da_cambiare.punteggio = 60
                    else:
                        g_da_cambiare.punteggio = -20

    def fine_turno(self):
        for g in self.game_state.lista_player:  # svuoto giocate in ogni caso
            g.carta_giocata.val = Card()
        if len(self.lista_player[0].player_state.mano.val
               ) == 0:  # se un giocatore non ha carte (tutti le hanno finite)
            self.check_cappotto()
            for i in range(len(
                    self.lista_player)):  # aggiorno punteggi totali per tutti
                g_privat = self.lista_player[i]
                g_public = self.game_state.lista_player[i]
                g_public.punteggio_tot.val = g_public.punteggio_tot.val + g_privat.punteggio
                g_privat.punteggio = 0
                g_privat.carte_prese = []
            self.game_state.fase_gioco.val = Fase.FINE_PARTITA  # così gli HUD scrivono fine partita
            t = Timer(10, self.fine_partita)
            t.start()
        else:
            self.pausa = False
            self.game_state.turno.val = self.primo

    def fine_partita(self):
        self.game_state.cont_partita.val = self.game_state.cont_partita.val + 1
        self.pausa = False
        self.primo_in_prima = (self.primo_in_prima + 1) % 4
        self.primo = self.primo_in_prima
        self.ultimo = (self.primo - 1) % 4
        self.game_state.turno.val = self.primo
        self.dai_carte()
        self.game_state.fase_gioco.val = Fase.PASSAGGIO_CARTE
示例#5
0
    def __init__(self, players):
        self.scores = {}
        self.players = players

        for player in self.players:
            self.scores[player.id] = 0

        for i in range(0, 100):
            ''' :type: list[PlayerStub] '''
            self.deck = Deck(settings.deckrepetitions)

            self.give_cards_and_two_coins()
            self.signal_status()

            player_index = random.randint(0, len(players) - 1)

            current_player = self.players[player_index]
            ''' :type: playerstub.PlayerStub '''

            while not self.is_game_over():
                if current_player.is_alive():
                    if not Validation.check_table_correctness(self.players, self.deck):
                        print('Invalid Status!')
                        print(str([str(p) for p in self.players]))
                        raise ValueError()
                    action = current_player.play(current_player.coins >= 10, players)
                    if action.is_valid(players, player_index):
                        self.signal_new_turn(player_index)
                        if action.target:
                            self.signal_targeted_action(current_player, action, action.target)
                            if not action.target.is_alive():
                                raise ValueError()  # targeting an elimitated player
                        else:
                            self.signal_player_action(current_player, action)
                        # resolve
                        if isinstance(action, Assassinate) or isinstance(action, Extortion):
                            self.resolve_assassination_and_extortion(current_player, action)
                        elif isinstance(action, CollectTaxes) or isinstance(action, Exchange):
                            self.resolve_collect_taxes_and_exchange(current_player, action)
                        elif isinstance(action, ForeignAid):
                            self.resolve_foreign_aid(current_player, action)
                        elif isinstance(action, Investigate):
                            self.resolve_investigate(current_player, action)
                        elif isinstance(action, CoupDEtat):
                            influence = action.resolve_action(current_player)
                            self.signal_lost_influence(action.target, influence)
                        else:
                            action.resolve_action(current_player)
                        self.signal_status()
                    else:
                        # TODO invalid action
                        pass
                else:
                    pass
                player_index = (player_index + 1) % len(players)
                current_player = self.players[player_index]
            for winner in self.players:
                if len(winner.cards) > 0:
                    self.scores[winner.id] += 1
                    break
        print('SCORES: ' + str(self.scores))
示例#6
0
class Game:
    def __init__(self, players):
        self.scores = {}
        self.players = players

        for player in self.players:
            self.scores[player.id] = 0

        for i in range(0, 100):
            ''' :type: list[PlayerStub] '''
            self.deck = Deck(settings.deckrepetitions)

            self.give_cards_and_two_coins()
            self.signal_status()

            player_index = random.randint(0, len(players) - 1)

            current_player = self.players[player_index]
            ''' :type: playerstub.PlayerStub '''

            while not self.is_game_over():
                if current_player.is_alive():
                    if not Validation.check_table_correctness(self.players, self.deck):
                        print('Invalid Status!')
                        print(str([str(p) for p in self.players]))
                        raise ValueError()
                    action = current_player.play(current_player.coins >= 10, players)
                    if action.is_valid(players, player_index):
                        self.signal_new_turn(player_index)
                        if action.target:
                            self.signal_targeted_action(current_player, action, action.target)
                            if not action.target.is_alive():
                                raise ValueError()  # targeting an elimitated player
                        else:
                            self.signal_player_action(current_player, action)
                        # resolve
                        if isinstance(action, Assassinate) or isinstance(action, Extortion):
                            self.resolve_assassination_and_extortion(current_player, action)
                        elif isinstance(action, CollectTaxes) or isinstance(action, Exchange):
                            self.resolve_collect_taxes_and_exchange(current_player, action)
                        elif isinstance(action, ForeignAid):
                            self.resolve_foreign_aid(current_player, action)
                        elif isinstance(action, Investigate):
                            self.resolve_investigate(current_player, action)
                        elif isinstance(action, CoupDEtat):
                            influence = action.resolve_action(current_player)
                            self.signal_lost_influence(action.target, influence)
                        else:
                            action.resolve_action(current_player)
                        self.signal_status()
                    else:
                        # TODO invalid action
                        pass
                else:
                    pass
                player_index = (player_index + 1) % len(players)
                current_player = self.players[player_index]
            for winner in self.players:
                if len(winner.cards) > 0:
                    self.scores[winner.id] += 1
                    break
        print('SCORES: ' + str(self.scores))

    def give_cards_and_two_coins(self):
        for player in self.players:
            player.start([self.deck.draw_card(), self.deck.draw_card()])
            player.delta_coins(2)

    def get_global_status(self):
        player_list = []
        for player in self.players:
            player_dict = {"player": player.id,
                           "cards": player.cards,
                           "coins": player.coins
                           }
            player_list += [player_dict]
        return {"players": player_list}

    def signal_status(self):
        print('status')
        for player in self.players:
            if player.is_alive():
                print(str(player))
                player.signal_status(self.get_global_status())

    def is_game_over(self):
        count = 0
        for player in self.players:
            if player.is_alive():
                count += 1
        return count <= 1

    def signal_lost_influence(self, player, card):
        print(player.id + ' lost ' + card)
        for p in self.players:
            if p.is_alive():
                player.signal_lost_influence(player.id, card)

    def signal_new_turn(self, player_index):
        print('player ' + str(player_index) + ' is playing.')
        for player in self.players:
            if player.is_alive():
                player.signal_new_turn(self.players[player_index].id)

    def signal_targeted_action(self, current_player, action, action_target):
        print(current_player.id + ' is targeting ' + action_target.id + ' with ' + action.get_identifier())
        for player in self.players:
            if player.is_alive():
                player.signal_action(current_player.id, action, action_target)

    def signal_player_action(self, current_player, action):
        print(current_player.id + ' is doing ' + action.get_identifier())
        for player in self.players:
            if player.is_alive():
                player.signal_action(current_player.id, action, None)

    def signal_blocking(self, blocked_player, action, blocker_player, card):
        print('Player %s block %s\'s %s with %s.' %
              (blocker_player.id, blocked_player.id, action.get_identifier(), card))
        for player in self.players:
            if player.is_alive():
                player.signal_blocking(blocker_player, blocked_player, action, card)

    def signal_challenge(self, challenged_player, card, challenger_player):
        print('Player %s challenges %s\'s %s' % (challenger_player.id, challenged_player.id, card))
        for player in self.players:
            if player.is_alive():
                player.signal_challenge(challenger_player, card, challenged_player)

    def random_other_players(self, player1, player2=None):
        other_players = list(self.players)
        other_players.remove(player1)
        if player2:
            other_players.remove(player2)
        return other_players

    def resolve_assassination_and_extortion(self, current_player, action):
        no_challenge = True
        challenge_won = False
        no_block = True
        card = action.card
        target = action.target

        if target.request_challenge(action, current_player, card):
            self.signal_challenge(current_player, card, target)
            no_challenge = False
            if current_player.has_card(card):
                influence = target.lose_influence()
                new_card = current_player.change_card(self.deck, card)
                current_player.request_send_new_card_after_challenge(card, new_card)
                challenge_won = True
                self.signal_lost_influence(target, influence)
            else:
                influence = current_player.lose_influence()
                self.signal_lost_influence(current_player, influence)
        else:
            for spectator in self.random_other_players(current_player, target):
                if spectator.request_challenge(action, current_player, card):
                    self.signal_challenge(current_player, card, spectator)
                    no_challenge = False
                    if current_player.has_card(card):
                        influence = spectator.lose_influence()
                        new_card = current_player.change_card(self.deck, card)
                        current_player.request_send_new_card_after_challenge(card, new_card)
                        challenge_won = True
                        self.signal_lost_influence(spectator, influence)
                    else:
                        influence = current_player.lose_influence()
                        self.signal_lost_influence(current_player, influence)
                    break
        if no_challenge:
            payload = target.request_tries_to_block(action, current_player)
            card = payload['card']
            if payload['attempt_block'] and card in action.blockers:
                self.signal_blocking(current_player, action, target, card)
                no_block = False
                if current_player.request_challenge(action, target, card):
                    self.signal_challenge(target, card, current_player)
                    if target.has_card(card):
                        influence = current_player.lose_influence()
                        new_card = target.change_card(self.deck, card)
                        target.request_send_new_card_after_challenge(card, new_card)
                        self.signal_lost_influence(current_player, influence)
                    else:
                        influence = target.lose_influence()
                        challenge_won = True
                        self.signal_lost_influence(target, influence)
                else:
                    for spectator in self.random_other_players(current_player, target):
                        if spectator.request_challenge(action, target, card):
                            self.signal_challenge(target, card, spectator)
                            if target.has_card(card):
                                influence = spectator.lose_influence()
                                new_card = target.change_card(self.deck, card)
                                target.request_send_new_card_after_challenge(card, new_card)
                                self.signal_lost_influence(spectator, influence)
                            else:
                                influence = target.lose_influence()
                                challenge_won = True
                                self.signal_lost_influence(target, influence)
                            break
        if (no_block and no_challenge) or challenge_won:
            influence = action.resolve_action(current_player)
            if influence:
                self.signal_lost_influence(target, influence)

    def resolve_investigate(self, current_player, action):
        no_challenge = True
        challenge_won = False
        card = action.card
        target = action.target
        if target.request_challenge(action, current_player, card):
            self.signal_challenge(current_player, card, target)
            no_challenge = False
            if current_player.has_card(card):
                influence = target.lose_influence()
                new_card = current_player.change_card(self.deck, card)
                current_player.request_send_new_card_after_challenge(card, new_card)
                challenge_won = True
                self.signal_lost_influence(target, influence)
            else:
                influence = current_player.lose_influence()
                self.signal_lost_influence(current_player, influence)
        else:
            for spectator in self.random_other_players(current_player, target):
                if spectator.request_challenge(action, current_player, card):
                    self.signal_challenge(current_player, card, spectator)
                    no_challenge = False
                    if current_player.has_card(card):
                        influence = spectator.lose_influence()
                        new_card = current_player.change_card(self.deck, card)
                        current_player.request_send_new_card_after_challenge(card, new_card)
                        challenge_won = True
                        self.signal_lost_influence(spectator, influence)
                    else:
                        influence = current_player.lose_influence()
                        self.signal_lost_influence(current_player, influence)
                    break
        if no_challenge or challenge_won:
            action.resolve_action(current_player, self.deck)

    def resolve_collect_taxes_and_exchange(self, current_player, action):
        no_challenge = True
        challenge_won = False
        card = action.card
        for challenger in self.random_other_players(current_player):
            if challenger.request_challenge(action, current_player, card):
                self.signal_challenge(current_player, card, challenger)
                no_challenge = False
                if current_player.has_card(card):
                    influence = challenger.lose_influence()
                    new_card = current_player.change_card(self.deck, card)
                    current_player.request_send_new_card_after_challenge(card, new_card)
                    challenge_won = True
                    self.signal_lost_influence(challenger, influence)
                else:
                    influence = current_player.lose_influence()
                    self.signal_lost_influence(current_player, influence)
                break
        if no_challenge or challenge_won:
            action.resolve_action(current_player, self.deck)

    def resolve_foreign_aid(self, current_player, action):
        no_block = True
        challenge_won = False
        for player_blocker in self.random_other_players(current_player):
            payload = player_blocker.request_tries_to_block(action, current_player)
            card = payload['card']
            if payload['attempt_block'] and card in action.blockers:
                self.signal_blocking(current_player, action, player_blocker, card)
                no_block = False
                if current_player.request_challenge(action, player_blocker, card):
                    self.signal_challenge(player_blocker, card, current_player)
                    if player_blocker.has_card(card):
                        influence = current_player.lose_influence()
                        new_card = player_blocker.change_card(self.deck, card)
                        player_blocker.request_send_new_card_after_challenge(card, new_card)
                        self.signal_lost_influence(current_player, influence)
                    else:
                        influence = player_blocker.lose_influence()
                        challenge_won = True
                        self.signal_lost_influence(player_blocker, influence)
                else:
                    for spectator in self.random_other_players(current_player, player_blocker):
                        if spectator.request_challenge(action, player_blocker, card):
                            self.signal_challenge(player_blocker, card, spectator)
                            if player_blocker.has_card(card):
                                influence = spectator.lose_influence()
                                new_card = player_blocker.change_card(self.deck, card)
                                player_blocker.request_send_new_card_after_challenge(card, new_card)
                                self.signal_lost_influence(spectator, influence)
                            else:
                                influence = player_blocker.lose_influence()
                                challenge_won = True
                                self.signal_lost_influence(player_blocker, influence)
                            break
                break
        if no_block or challenge_won:
            action.resolve_action(current_player)
示例#7
0
class Player(object):
    websocket = None
    game = None
    uid = None
    name = None
    deck = None
    hand = None
    ground = None
    graveyard = None
    turn = None
    ai = None
    hp = 30
    inspector = False

    def __init__(self, game, is_ai=False, ai_deck_id=None, use_this_deck=None):
        self.uid = "ai"
        self.game = game

        if is_ai:
            self.name = "AI"
            self.deck = Deck(self)
            self.hand = Hand(self)
            self.ground = Ground(self)
            self.graveyard = Graveyard(self)
            self.turn = Turn(self)
            self.ai = AI(self)

            # TODO make deck for ai, for now user id=2 is an ai
            from server.models import Player as DbPlayerr, Deck as DBDeckk
            db_player = DbPlayerr.objects.get(pk=2)

            if use_this_deck:
                ai_deck = use_this_deck
            elif ai_deck_id:
                ai_deck = DBDeckk.objects.get(pk=ai_deck_id)
            else:
                ai_deck = db_player.first_deck

            for db_card in ai_deck.get_cards(randomize=True):
                card = db_card.to_virtual(self)
                self.deck.add(card)

    def __str__(self):
        return "<Player.{0} {1}>".format(self.uid, self.name)

    def __repr__(self):
        return "<Player {0}>".format(self.uid)

    def __getstate__(self):
        return {
            'uid': self.uid,
            'name': self.name,
            'deck': self.deck,
            'hand': self.hand,
            'ground': self.ground,
            'graveyard': self.graveyard,
            'turn': self.turn,
            'ai': self.ai
        }

    def start_turn(self, base_command=None):
        logger.info(
            "################################################## STARTING TURN {0} FOR {1}"
            .format(self.turn.no, self.uid))

        simple_logger.debug("\nTurn {0} started for {1}".format(
            self.turn.no, self.name))

        if self.inspector and self.game.over:
            print("Game Over")
            simple_logger.debug("\nRESULT:")
            simple_logger.debug(base_command.items)
            return base_command
            # raise Exception("Game Over")

        self.turn.start()

        if base_command:
            command = base_command
        else:
            command = Command(meta={'uid': self.uid})

        command.add('turn-begin', self.turn.to_json())

        # add draw card command
        # command = self.draw_card(base_command=command)
        result = self.draw_card(return_tailored=True)
        if result:
            if "drawed" in result:
                card = self.hand.get_card_by_uuid(result['drawed']['uuid'])

                tailored = card.cast_spell('ondraw',
                                           {'provided': card})  # returns list

                if tailored:
                    result = [result]
                    result += tailored
                    command.add('list', result)

                else:
                    command.add('drawed', result['drawed'])
                    # print(command.items)
                    # import sys
                    # sys.exit(2)
            else:
                command.add('discarded', result['discarded'])

        if self.uid == "ai" or self.inspector:
            command = self.ai.play_your_turn(base_command=command)

        opponent = self.game.get_opposite_player(self.uid)
        tailored2 = self.trigger_turn_event("onplayer:turn:begin", opponent)
        if len(tailored2):
            command.add('list', tailored2)
        """
        tailored1 = []
        opponent = self.game.get_opposite_player(self.uid)
        for card in opponent.ground.cards:
            tailored1 += card.cast_spell("onplayer:turn:end")

        logger.info("Events> player({0}):turn:end {1}".format(opponent.uid, tailored1))
        if len(tailored1):
            command.add('list', tailored1)
        """

        return command

    def end_turn(self, base_command=None):
        # logger.info("############################ ENDING TURN FOR {0}".format(self.uid))
        if not base_command:
            command = Command(meta={'uid': self.uid})
        else:
            command = base_command

        opponent = self.game.get_opposite_player(self.uid)

        tailored1 = self.trigger_turn_event("onturn:end", opponent)
        if len(tailored1):
            command.add('list', tailored1)

        tailored2 = self.trigger_turn_event("onplayer:turn:end", opponent)
        if len(tailored2):
            command.add('list', tailored2)

        logger.info(
            "################################################## TURN ENDED FOR {0}"
            .format(self.uid))

        return opponent.start_turn(base_command=command)

    def draw_card(self, amount=1, base_command=None, return_tailored=False):
        command = None
        if not return_tailored:
            if base_command:
                command = base_command
            else:
                command = Command(meta={'uid': self.uid})

        if len(self.deck.cards):
            card = self.deck.cards.pop()
            """ :type card: server.Card """

            deck_count = len(self.deck.cards)

            if card:
                if len(self.hand.cards) + 1 > self.hand.limit:

                    logger.info("Player> Discard card -> hand is full")
                    if return_tailored:
                        command = {
                            'discarded': {
                                'uuid': card.uuid,
                                'uid': self.uid,
                                'ckey': card.key,
                                'deck_count': deck_count
                            }
                        }
                    else:
                        command.add(
                            'discarded', {
                                'uuid': card.uuid,
                                'uid': self.uid,
                                'ckey': card.key,
                                'deck_count': deck_count
                            })

                else:
                    self.hand.add(card)

                    draw_data = {
                        'uid': self.uid,
                        'uuid': card.uuid,
                        'ckey': card.key,
                        'deck_count': deck_count
                    }

                    if card.is_hp_increased():  # karamurat etc
                        draw_data['hp_increased'] = True
                        draw_data['hp'] = card.hp

                    if card.is_dp_increased():  # karamurat etc
                        draw_data['dp_increased'] = True
                        draw_data['dp'] = card.dp

                    if return_tailored:
                        command = {'drawed': draw_data}
                    else:
                        command.add('drawed', draw_data)

                    simple_logger.debug("{0} drawed {1}".format(
                        self.name, card.label))
                    logger.info("Player.{0}.draw_card {1}".format(
                        self.uid, card.label))

            else:
                logger.info("Player> Draw failed, no cards in deck!")
        return command

    def play_creature_card(self,
                           card_uuid,
                           target=None,
                           slot=4,
                           base_command=None):

        card = self.hand.get_card_by_uuid(card_uuid)
        if not card:
            logger.info("ERROR> play_creature_card probably double playing.")
            logger.info(
                "Player.play_creature_card uid:{0} card:{1} hand:{2}".format(
                    self.uid, card_uuid, [{
                        'uuid': c.uuid,
                        'title': c.title
                    } for c in self.hand.cards]))
            return None

        if base_command:
            command = base_command
        else:
            command = Command(meta={'uid': self.uid})

        # TODO check is playable?
        self.hand.remove(card)

        # TODO check is groundable?
        self.ground.add(card, slot=slot)  # ground_slot is defining here

        simple_logger.debug("{0} played creature {1}".format(
            self.name, card.title))

        self.turn.remaining_mana -= card.mana

        command.add(
            'creature_card_played', {
                'uid': self.uid,
                'uuid': card.uuid,
                'slot': card.slot_index,
                'remaining_mana': self.turn.remaining_mana
            })

        tailored = card.cast_spell('ondeploy', {'provided': target})

        died = None
        if tailored and len(tailored):
            died_index = -1
            for index, item in enumerate(tailored):
                try:
                    if list(item.keys())[0] == "card_died":
                        died_index = index
                        break
                except AttributeError as err:
                    print("play_creature_card AttributeError", err, item,
                          tailored)
            if died_index >= 0:
                died = list(tailored[died_index].values())[0]
                del tailored[died_index]

        if len(tailored):
            command.add('list', tailored)

        event_result = self.game.events.fire('onauraPlay', {
            'card': card,
            'target': target
        })
        if event_result and len(event_result):
            command.add('list', event_result)

        if died:
            simple_logger.debug(
                "{0} play_creature_card some card died {1}".format(
                    self.name, died))
            command.add('card_died', died)

        return command

    def play_spell_card(self,
                        attacker_uuid,
                        target_uuid=None,
                        base_command=None):
        cast_data = None
        target = None
        from_card = self.hand.get_card_by_uuid(attacker_uuid)
        if not from_card:
            logger.info("ERROR> play_spell_card probably double playing.")
            logger.info("Hand.DoesNotExist owner:{0} uuid:{1} hand{2}".format(
                self.uid, attacker_uuid, [{
                    'title': c.title,
                    'uuid': c.uuid
                } for c in self.hand.cards]))
            return None

        if target_uuid:
            if target_uuid.startswith("{0}-".format(
                    self.uid)):  # am i targeting one of my cards?
                target_player = self
            else:
                target_player = self.game.get_opposite_player(self.uid)

            target = target_player.ground.get_card_by_uuid(target_uuid)
            cast_data = {'provided': target}

        self.hand.remove(from_card)
        self.graveyard.add(from_card)

        simple_logger.debug("{0} played spell card {1}".format(
            self.name, from_card.title))

        self.turn.remaining_mana -= from_card.mana

        if base_command:
            command = base_command
        else:
            command = Command(meta={'uid': self.uid})

        result_dict = {
            'uid': self.uid,
            'uuid': from_card.uuid,
            'remaining_mana': self.turn.remaining_mana,
            'from': from_card.title
        }
        if target_uuid:
            result_dict['target'] = target_uuid
            result_dict['to'] = target.title

            # we assume spell cards has only one spell in it and it's trigger is onplay right?
            spell = from_card.spells[0]
            if spell.animation:
                result_dict['animation'] = spell.animation

        command.add('spell_card_played', result_dict)

        tailored = from_card.cast_spell(
            "onplay", cast_data
        )  # TODO put animation type (ex: fireball, freeze etc to use in client-side)
        died = None
        if tailored:

            died_index = -1
            for index, item in enumerate(tailored):
                if list(item.keys())[0] == "card_died":
                    died_index = index
                    break

            if died_index >= 0:
                died = list(tailored[died_index].values())[0]
                del tailored[died_index]

        command.add('list', tailored)

        event_result = self.game.events.fire('onauraPlay', {
            'card': from_card,
            'target': target
        })
        if event_result and len(event_result):
            command.add('list', event_result)

        if died:
            simple_logger.debug(
                "{0} play_spell_card some card died {0}".format(
                    self.name, died))
            command.add('card_died', died)

        return command

    def card_attack_from_ground(
            self,
            attacker_uuid,
            target_uuid,
            base_command=None
    ):  # TODO stop attacking multiple times in one turn
        target_player = self.game.get_opposite_player(self.uid)

        attacker = self.ground.get_card_by_uuid(attacker_uuid)
        try:
            target = target_player.ground.get_card_by_uuid(target_uuid)
        except Exception as err:
            import sys
            print("{0}.ground.get_card_by_uuid({1}) DoesNotExist {1}".format(
                self.name, target_uuid, target_player.ground.cards))
            sys.exit(1)

        attacker.attacked_this_turn = True

        defender = None
        defenders = target_player.ground.get_cards({
            'defender': True,
            'count': 1,
            'random': True,
            'exclude': target,
            'ignore-immune': True
        })
        if len(defenders):
            defender = defenders[0]
            target = defender

        if not target:
            import sys
            print(
                "card_attack_from_ground: NoTargetAtSecond me:{0} target:{1} {2}"
                .format(self.name, target_uuid, target_player.ground.cards))
            sys.exit(1)

        try:
            attacker.hp -= target.dp
        except AttributeError as err:
            print("card_attack_from_ground: AttributeError.1", err,
                  attacker.label, target, target_uuid)

        try:
            target.hp -= attacker.dp
        except AttributeError as err:
            print("card_attack_from_ground: AttributeError.2", err,
                  target.label, attacker.label, target_uuid)

        # self.turn.remaining_mana -= attacker.mana

        if base_command:
            command = base_command
        else:
            command = Command(meta={'uid': self.uid})

        if defender:
            command.add(
                'dummy', {
                    'uid': target_player.uid,
                    'uuid': defender.uuid,
                    'textanim': {
                        'text': "Defender",
                        'harmful': False
                    }
                })

        # TOGETHER
        target_total_damage = attacker.dp
        attack_together = False
        if attacker.together:
            partners = self.ground.get_cards({
                'canattack': True,
                'random': True,
                'count': 1,
                'exclude': attacker,
                'ignore-immune': True
            })
            if len(partners):
                partner = partners[0]

                if target.hp > 0:  # target must be still alive after attacker's attack

                    partner.hp -= target.dp
                    target.hp -= partner.dp

                    command.add(
                        'dummy', {
                            'uid': self.uid,
                            'uuid': partner.uuid,
                            'textanim': {
                                'text': "Together",
                                'harmful': False
                            }
                        })

                    tailored = list()

                    tailored.append({
                        'attacked': {
                            'attacker': {
                                'uid': self.uid,
                                'uuid': attacker.uuid,
                                'attacked_this_turn': True
                            },
                            'target': {
                                'uid': target_player.uid,
                                'uuid': target.uuid
                            }
                        }
                    })

                    tailored.append({
                        'attacked': {
                            'attacker': {
                                'uid': self.uid,
                                'uuid': partner.uuid
                            },
                            'target': {
                                'uid': target_player.uid,
                                'uuid': target.uuid
                            }
                        }
                    })
                    command.add('list', tailored)
                    attack_together = True
                    target_total_damage += partner.dp

        if not attack_together:
            command.add(
                'attacked', {
                    'attacker': {
                        'uid': self.uid,
                        'uuid': attacker.uuid,
                        'attacked_this_turn': True
                    },
                    'target': {
                        'uid': target_player.uid,
                        'uuid': target.uuid
                    }
                })

        simple_logger.debug("{0} attacked to {1}".format(
            attacker.label, target.label))

        tailor1 = list()
        if target.dp > 0:
            tailor1.append({
                'dummy': {
                    'uid': self.uid,
                    'uuid': attacker.uuid,
                    'textanim': {
                        'text': "-{0}".format(target.dp),
                        'harmful': True
                    }
                }
            })
        if target_total_damage > 0:
            tailor1.append({
                'dummy': {
                    'uid': target_player.uid,
                    'uuid': target.uuid,
                    'textanim': {
                        'text': "-{0}".format(target_total_damage),
                        'harmful': True
                    }
                }
            })

        command.add('list', tailor1)

        tailor2 = list()
        # if attacker.is_hp_decreased():
        if target.dp > 0:  # if its bleeding
            tailor2.append({
                "hp_decreased": {
                    'uid': self.uid,
                    'uuid': attacker.uuid,
                    'hp': attacker.hp
                }
            })

        # if target.is_hp_decreased():
        if target_total_damage > 0:  # if its bleeding
            tailor2.append({
                "hp_decreased": {
                    'uid': target_player.uid,
                    'uuid': target.uuid,
                    'hp': target.hp
                }
            })

        # victim's defense triggering
        event_result1 = self.game.events.fire('onauraDefense', {
            'triggerer': target,
            'attacker': attacker,
            'victim': target
        })
        if event_result1:
            tailor2 += event_result1

        # attacker's attack triggering
        event_result2 = self.game.events.fire('onauraAttack', {
            'triggerer': attacker,
            'attacker': attacker,
            'victim': target
        })
        if event_result2:
            tailor2 += event_result2

        # target's ondefense triggering
        event_result3 = target.cast_spell('ondefense', {'provided': attacker})
        if event_result3:
            tailor2 += event_result3

        if len(tailor2):
            command.add('list', tailor2)

        tailor3 = []
        tailor4 = []
        if target.alive and target.hp <= 0:
            card_died_dict = {
                "card_died": {
                    'uid': target_player.uid,
                    'uuid': target.uuid
                }
            }

            if target.avengeme and attacker.hp > 0 and len(
                    target_player.ground.cards
            ) - 1:  # avengeme card still on the ground
                card_died_dict['card_died']['textanim'] = {
                    'text': "Avenge Me!",
                    'harmfull': True
                }

            tailor3.append(card_died_dict)

            event_result = target.kill(
                destroyer=attacker)  # trigger game event/auras
            if event_result:
                tailor4 += event_result

        if attacker.alive and attacker.hp <= 0:
            tailor3.append(
                {"card_died": {
                    'uid': self.uid,
                    'uuid': attacker.uuid
                }})

            event_result = attacker.kill(
                destroyer=target)  # trigger game event/auras
            if event_result:
                tailor4 += event_result

        if len(tailor3):  # card_died tailors
            command.add('list', tailor3)

        if len(tailor4):  # ondestroy game event
            command.add('list', tailor4)

        # target has avenge me
        if target.avengeme and target.hp <= 0 and attacker.hp and len(
                target_player.ground.cards):
            # TODO find most powerfull ally
            cards = target_player.ground.get_cards({
                'canattack': True,
                'random': True,
                'count': 1,
                'ignore-immune': True
            })
            if len(cards):
                avenger = cards[0]
                command.add(
                    'dummy', {
                        'uid': target_player.uid,
                        'uuid': avenger.uuid,
                        'textanim': {
                            'text': "Avenger",
                            'harmful': False
                        }
                    })
                command = target_player.card_attack_from_ground(
                    avenger.uuid, attacker.uuid, base_command=command)

        # target has revenge
        if target.revenge and target.hp > 0 and target.dp > 0 and attacker.hp > 0:
            target.dp += target.revenge
            command.add(
                'dp_increased', {
                    'uid': target_player.uid,
                    'uuid': target.uuid,
                    'dp': target.dp,
                    'textanim': {
                        'text': "Revenge",
                        'harmful': False
                    }
                })
            command = target_player.card_attack_from_ground(
                target.uuid, attacker.uuid, base_command=command)

            target.dp -= target.revenge
            if target.hp > 0:  # if still alive after revenge > restore dp
                command.add('dp_restored', {
                    'uid': target_player.uid,
                    'uuid': target.uuid,
                    'dp': target.dp
                })

        return command

    def card_attack_to_player(self,
                              attacker_uuid,
                              target_uid,
                              base_command=None):
        if base_command:
            command = base_command
        else:
            command = Command(meta={'uid': self.uid})

        target_player = self.game.get_player_by_uid(target_uid)
        attacker_player = self.game.get_opposite_player(target_uid)
        attacker = attacker_player.ground.get_card_by_uuid(attacker_uuid)

        attacker.attacked_this_turn = True

        # DEFENDER
        defenders = target_player.ground.get_cards({
            'defender': True,
            'count': 1,
            'random': True,
            'ignore-immune': True
        })
        if len(defenders):
            defender = defenders[0]
            command.add(
                'dummy', {
                    'uid': target_player.uid,
                    'uuid': defender.uuid,
                    'textanim': {
                        'text': "Defender",
                        'harmful': False
                    }
                })
            return self.card_attack_from_ground(attacker_uuid,
                                                defender.uuid,
                                                base_command=command)

        # attacker.hp -= target.dp  TODO Player.dp not implemented yet
        target_player.hp -= attacker.dp

        target_total_damage = attacker.dp
        # TODO TOGETHER - shoul we implement attack together to player?

        simple_logger.debug("{0} attacked to player {1}({2})".format(
            attacker.label, target_player.name, target_player.hp))

        command.add(
            'attacked',
            {
                'attacker': {
                    'uid': self.uid,
                    'uuid': attacker.uuid,
                    'attacked_this_turn': True
                },
                'target': {
                    'uid': target_player.uid
                }  # we don't send uuid so client must understand it's an attack to a player
            })

        tailor1 = list()
        tailor1.append({
            'dummy': {
                'uid': target_player.uid,
                'textanim': {
                    'text': "-{0}".format(target_total_damage),
                    'harmful': True
                }
            }
        })
        # TODO player's cannot attack now
        # tailor1.append({'dummy': {'uid': self.uid, 'uuid': attacker.uuid, 'textanim': {'text': "-{0}".format(target.dp), 'harmful': True}}})

        tailor1.append({
            "hp_decreased": {
                'uid': target_player.uid,
                'hp': target_player.hp
            }
        })

        command.add('list', tailor1)

        # attacker's attack triggering
        event_result2 = self.game.events.fire('onauraAttack', {
            'triggerer': attacker,
            'attacker': attacker,
            'victim': target_player
        })
        if event_result2:
            command.add('list', event_result2)

        if target_player.hp <= 0:
            self.game.over = True
            command.add('player_died', {'uid': target_player.uid})

        # TODO if attacker died (player must have dp for this)

        return command

    def trigger_turn_event(self, trigger_key, opponent):
        tailored = []
        all_cards = self.ground.cards + opponent.ground.cards

        if "onplayer" in trigger_key or "onopponent" in trigger_key:
            trigger = "{0}:{1}".format(trigger_key,
                                       self.uid)  # TODO trigger with turn no
        else:
            trigger = trigger_key  # do not append uid at the end of the trigger key when it is "each turn begin/end"

        for card in all_cards:
            txt = ""
            for spl in card.spells:
                # logger.info(
                #    "Player> Card:[{0}'s {1}] Spell:{2} Trigger:{3} Required:{4}".format(card.player.uid, card.title,
                #                                                                         spl.type, spl.trigger,
                #                                                                         trigger))
                if spl.trigger == trigger:
                    txt += "\nEVREKAAAAAAAAAAAAAAAAAAAAA {0} owner: {1}".format(
                        spl.trigger, card.player.uid)
                else:
                    txt += "\nNope required:{0} has:{1} player:{2} card:{3}".format(
                        trigger, spl.trigger, card.player.uid, card.title)

            if len(card.spells):
                # logger.info("Events> Bu: {0}".format(txt))
                tailored += card.cast_spell(
                    trigger)  # my opponent's turns is ended

        # logger.info("Events> {0} {2}".format(trigger,opponent.uid, tailored))
        return tailored