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 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)
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 = []
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
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))
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)
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