less spaghetti is always better

This commit is contained in:
Alberto Xamin 2020-11-25 11:18:04 +01:00
parent 00ac77e10a
commit 363ae304f0
No known key found for this signature in database
GPG Key ID: 4F026F48309500A2
3 changed files with 264 additions and 171 deletions

View File

@ -2,12 +2,14 @@ from typing import List, Set, Dict, Tuple, Optional
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from enum import IntEnum from enum import IntEnum
class Suit(IntEnum): class Suit(IntEnum):
DIAMONDS = 0 # ♦ DIAMONDS = 0 # ♦
CLUBS = 1 # ♣ CLUBS = 1 # ♣
HEARTS = 2 # ♥ HEARTS = 2 # ♥
SPADES = 3 # ♠ SPADES = 3 # ♠
class Card(ABC): class Card(ABC):
sym = { sym = {
'A': 1, 'A': 1,
@ -15,7 +17,8 @@ class Card(ABC):
'Q': 12, 'Q': 12,
'K': 13 'K': 13
} }
def __init__(self, suit: Suit, name: str, number, is_equipment:bool=False, is_weapon:bool=False, vis_mod:int=0, sight_mod:int=0, range:int=99, desc:str=''):
def __init__(self, suit: Suit, name: str, number, is_equipment: bool = False, is_weapon: bool = False, vis_mod: int = 0, sight_mod: int = 0, range: int = 99, desc: str = ''):
super().__init__() super().__init__()
self.name = name self.name = name
self.suit = suit self.suit = suit
@ -29,39 +32,50 @@ class Card(ABC):
self.sight_mod = sight_mod self.sight_mod = sight_mod
self.range = range self.range = range
if self.range != 0 and self.range != 99: if self.range != 0 and self.range != 99:
self.alt_text = f'{self.range} 🔍' self.alt_text = f'{self.range} 🔍'
self.desc = desc self.desc = desc
self.need_target = False self.need_target = False
def __str__(self): def __str__(self):
char = ['♦️','♣️','♥️','♠️'][int(self.suit)] char = ['♦️', '♣️', '♥️', '♠️'][int(self.suit)]
return f'{self.name} {char}{self.number}' return f'{self.name} {char}{self.number}'
return super().__str__() return super().__str__()
def play_card(self, player, against):
contro = f'contro {against}' if against else ''
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name}{contro}.')
return True
class Barile(Card): class Barile(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Barile', number, is_equipment=True) super().__init__(suit, 'Barile', number, is_equipment=True)
self.icon = '🛢' self.icon = '🛢'
self.desc = "Quando sei bersagliato da un Bang puoi estrarre la prima carta dalla cima del mazzo, se la carta estratta è del seme Cuori allora vale come un Mancato" self.desc = "Quando sei bersagliato da un Bang puoi estrarre la prima carta dalla cima del mazzo, se la carta estratta è del seme Cuori allora vale come un Mancato"
class Dinamite(Card): class Dinamite(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Dinamite', number, is_equipment=True) super().__init__(suit, 'Dinamite', number, is_equipment=True)
self.icon = '🧨' self.icon = '🧨'
self.desc = "Giocando la Dinamite, posizionala davanti a te, resterà innocua per un intero giro. All'inizio del prossimo turno prima di pescare e prima di una eventuale estrazione (es. Prigione), estrai una carta dalla cima del mazzo. Se esce una carta tra il 2 il 9 di picche (compresi) allora la dinamite esplode: perdi 3 vite e scarta la carta, altrimenti passa la dinamite al giocatore successivo, il quale estrarà a sua volta dopo che tu avrai passato il tuo turno" self.desc = "Giocando la Dinamite, posizionala davanti a te, resterà innocua per un intero giro. All'inizio del prossimo turno prima di pescare e prima di una eventuale estrazione (es. Prigione), estrai una carta dalla cima del mazzo. Se esce una carta tra il 2 il 9 di picche (compresi) allora la dinamite esplode: perdi 3 vite e scarta la carta, altrimenti passa la dinamite al giocatore successivo, il quale estrarà a sua volta dopo che tu avrai passato il tuo turno"
class Mirino(Card): class Mirino(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Mirino', number, is_equipment=True, sight_mod=1) super().__init__(suit, 'Mirino', number, is_equipment=True, sight_mod=1)
self.icon = '🔎' self.icon = '🔎'
self.desc = "Tu vedi gli altri giocatori a distanza -1" self.desc = "Tu vedi gli altri giocatori a distanza -1"
class Mustang(Card): class Mustang(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Mustang', number, is_equipment=True, vis_mod=1) super().__init__(suit, 'Mustang', number, is_equipment=True, vis_mod=1)
self.icon = '🐎' self.icon = '🐎'
self.desc = "Gli altri giocatori ti vedono a distanza +1" self.desc = "Gli altri giocatori ti vedono a distanza +1"
class Prigione(Card): class Prigione(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Prigione', number, is_equipment=True) super().__init__(suit, 'Prigione', number, is_equipment=True)
@ -69,36 +83,47 @@ class Prigione(Card):
self.desc = "Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno" self.desc = "Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno"
self.need_target = True self.need_target = True
class Remington(Card): class Remington(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Remington', number, is_equipment=True, is_weapon=True, range=3) super().__init__(suit, 'Remington', number,
is_equipment=True, is_weapon=True, range=3)
self.icon = '🔫' self.icon = '🔫'
self.desc = "Puoi sparare a un giocatore che sia distante 3 o meno" self.desc = "Puoi sparare a un giocatore che sia distante 3 o meno"
class RevCarabine(Card): class RevCarabine(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Rev. Carabine', number, is_equipment=True, is_weapon=True, range=4) super().__init__(suit, 'Rev. Carabine', number,
is_equipment=True, is_weapon=True, range=4)
self.icon = '🔫' self.icon = '🔫'
self.desc = "Puoi sparare a un giocatore che sia distante 4 o meno" self.desc = "Puoi sparare a un giocatore che sia distante 4 o meno"
class Schofield(Card): class Schofield(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Schofield', number, is_equipment=True, is_weapon=True, range=2) super().__init__(suit, 'Schofield', number,
is_equipment=True, is_weapon=True, range=2)
self.icon = '🔫' self.icon = '🔫'
self.desc = "Puoi sparare a un giocatore che sia distante 2 o meno" self.desc = "Puoi sparare a un giocatore che sia distante 2 o meno"
class Volcanic(Card): class Volcanic(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Volcanic', number, is_equipment=True, is_weapon=True, range=1) super().__init__(suit, 'Volcanic', number,
is_equipment=True, is_weapon=True, range=1)
self.icon = '🔫' self.icon = '🔫'
self.desc = "Puoi sparare a un giocatore che sia distante 1 o meno, tuttavia puoi giocare quanti bang vuoi" self.desc = "Puoi sparare a un giocatore che sia distante 1 o meno, tuttavia puoi giocare quanti bang vuoi"
class Winchester(Card): class Winchester(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Winchester', number, is_equipment=True, is_weapon=True, range=5) super().__init__(suit, 'Winchester', number,
is_equipment=True, is_weapon=True, range=5)
self.icon = '🔫' self.icon = '🔫'
self.desc = "Puoi sparare a un giocatore che sia distante 5 o meno" self.desc = "Puoi sparare a un giocatore che sia distante 5 o meno"
class Bang(Card): class Bang(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Bang!', number) super().__init__(suit, 'Bang!', number)
@ -106,12 +131,37 @@ class Bang(Card):
self.desc = "Spara a un giocatore a distanta raggiungibile. Se non hai armi la distanza di default è 1" self.desc = "Spara a un giocatore a distanta raggiungibile. Se non hai armi la distanza di default è 1"
self.need_target = True self.need_target = True
def play_card(self, player, against):
if player.has_played_bang and not any([isinstance(c, Volcanic) for c in player.equipment]) and against != None:
return False
elif against != None:
import characters as chars
super().play_card(player, against=against)
player.has_played_bang = not isinstance(
player.character, chars.WillyTheKid)
player.game.attack(player, against)
return True
return False
class Birra(Card): class Birra(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Birra', number) super().__init__(suit, 'Birra', number)
self.icon = '🍺' self.icon = '🍺'
self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori" self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori"
def play_card(self, player, against):
if len(player.game.players) != 2 and player.lives != player.max_lives:
super().play_card(player, against=against)
player.lives = min(player.lives+1, player.max_lives)
return True
elif len(player.game.players) == 2:
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha rovesciato una {self.name}.')
return True
return False
class CatBalou(Card): class CatBalou(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Cat Balou', number) super().__init__(suit, 'Cat Balou', number)
@ -119,12 +169,33 @@ class CatBalou(Card):
self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco" self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
self.need_target = True self.need_target = True
def play_card(self, player, against):
if against != None:
super().play_card(player, against=against)
from players import PendingAction
player.pending_action = PendingAction.CHOOSE
player.choose_action = 'discard'
player.target_p = against
print('choose now')
return True
return False
class Diligenza(Card): class Diligenza(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Diligenza', number) super().__init__(suit, 'Diligenza', number)
self.icon = '🚡' self.icon = '🚡'
self.desc = "Pesca 2 carte dalla cima del mazzo" self.desc = "Pesca 2 carte dalla cima del mazzo"
def play_card(self, player, against):
super().play_card(player, against=against)
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha pescato 2 carte.')
for i in range(2):
player.hand.append(player.game.deck.draw())
return True
class Duello(Card): class Duello(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Duello', number) super().__init__(suit, 'Duello', number)
@ -132,30 +203,67 @@ class Duello(Card):
self.icon = '⚔️' self.icon = '⚔️'
self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita" self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita"
def play_card(self, player, against):
if against != None:
super().play_card(player, against=against)
player.game.duel(player, against)
return True
return False
class Emporio(Card): class Emporio(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Emporio', number) super().__init__(suit, 'Emporio', number)
self.icon = '🏪' self.icon = '🏪'
self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano" self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano"
def play_card(self, player, against):
super().play_card(player, against=against)
player.game.emporio()
return True
class Gatling(Card): class Gatling(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Gatling', number) super().__init__(suit, 'Gatling', number)
self.icon = '🛰' self.icon = '🛰'
self.desc = "Spara a tutti gli altri giocatori" self.desc = "Spara a tutti gli altri giocatori"
def play_card(self, player, against):
super().play_card(player, against=against)
player.game.attack_others(player)
return True
class Indiani(Card): class Indiani(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Indiani!', number) super().__init__(suit, 'Indiani!', number)
self.icon = '🏹' self.icon = '🏹'
self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita" self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita"
def play_card(self, player, against):
super().play_card(player, against=against)
player.game.indian_others(player)
return True
class Mancato(Card): class Mancato(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Mancato!', number) super().__init__(suit, 'Mancato!', number)
self.icon = '😅' self.icon = '😅'
self.desc = "Usa questa carta per annullare un bang" self.desc = "Usa questa carta per annullare un bang"
def play_card(self, player, against):
import characters as chars
if (not player.has_played_bang and against != None and isinstance(player.character, chars.CalamityJanet)):
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} come un BANG! contro {against}.')
player.has_played_bang = True
player.game.attack(player, against)
return True
return False
class Panico(Card): class Panico(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Panico!', number, range=1) super().__init__(suit, 'Panico!', number, range=1)
@ -163,18 +271,47 @@ class Panico(Card):
self.need_target = True self.need_target = True
self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco" self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
def play_card(self, player, against):
if against != None:
super().play_card(player, against=against)
from players import PendingAction
player.pending_action = PendingAction.CHOOSE
player.choose_action = 'steal'
player.target_p = against
print('choose now')
return True
return False
class Saloon(Card): class Saloon(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'Saloon', number) super().__init__(suit, 'Saloon', number)
self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta" self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta"
self.icon = '🍻' self.icon = '🍻'
def play_card(self, player, against):
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha curato 1 punto vita a tutti.')
for p in player.game.players:
p.lives = min(p.lives+1, p.max_lives)
p.notify_self()
return True
class WellsFargo(Card): class WellsFargo(Card):
def __init__(self, suit, number): def __init__(self, suit, number):
super().__init__(suit, 'WellsFargo', number) super().__init__(suit, 'WellsFargo', number)
self.desc = "Pesca 3 carte dalla cima del mazzo" self.desc = "Pesca 3 carte dalla cima del mazzo"
self.icon = '💸' self.icon = '💸'
def play_card(self, player, against):
player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha pescato 3 carte.')
for i in range(3):
player.hand.append(player.game.deck.draw())
return True
def get_starting_deck() -> List[Card]: def get_starting_deck() -> List[Card]:
return [ return [
Barile(Suit.SPADES, 'Q'), Barile(Suit.SPADES, 'Q'),

View File

@ -1,35 +1,35 @@
from typing import List, Set, Dict, Tuple, Optional from typing import List, Set, Dict, Tuple, Optional
import random import random
from cards import Card, get_starting_deck import cards as cs
class Deck: class Deck:
def __init__(self, game): def __init__(self, game):
super().__init__() super().__init__()
self.cards: List[Card] = get_starting_deck() self.cards: List[cs.Card] = cs.get_starting_deck()
self.game = game self.game = game
random.shuffle(self.cards) random.shuffle(self.cards)
self.scrap_pile: List[Card] = [] self.scrap_pile: List[cs.Card] = []
print(f'Deck initialized with {len(self.cards)} cards') print(f'Deck initialized with {len(self.cards)} cards')
def peek(self, n_cards: int) -> list: def peek(self, n_cards: int) -> list:
return self.cards[:n_cards] return self.cards[:n_cards]
def peek_scrap_pile(self) -> Card: def peek_scrap_pile(self) -> cs.Card:
if len(self.scrap_pile) > 0: if len(self.scrap_pile) > 0:
return self.scrap_pile[-1] return self.scrap_pile[-1]
else: else:
return None return None
def pick_and_scrap(self) -> Card: def pick_and_scrap(self) -> cs.Card:
card = self.cards.pop(0) card = self.cards.pop(0)
self.scrap_pile.append(card) self.scrap_pile.append(card)
self.game.notify_scrap_pile() self.game.notify_scrap_pile()
return card return card
def put_on_top(self, card: Card): def put_on_top(self, card: cs.Card):
self.cards.insert(0, card) self.cards.insert(0, card)
def draw(self) -> Card: def draw(self) -> cs.Card:
card = self.cards.pop(0) card = self.cards.pop(0)
if len(self.cards) == 0: if len(self.cards) == 0:
self.cards = self.scrap_pile[:-1].copy() self.cards = self.scrap_pile[:-1].copy()
@ -37,7 +37,7 @@ class Deck:
self.scrap_pile = self.scrap_pile[-1:] self.scrap_pile = self.scrap_pile[-1:]
return card return card
def draw_from_scrap_pile(self) -> Card: def draw_from_scrap_pile(self) -> cs.Card:
if len(self.scrap_pile) > 0: if len(self.scrap_pile) > 0:
card = self.scrap_pile.pop(-1) card = self.scrap_pile.pop(-1)
self.game.notify_scrap_pile() self.game.notify_scrap_pile()
@ -45,6 +45,6 @@ class Deck:
else: else:
return self.draw() return self.draw()
def scrap(self, card: Card): def scrap(self, card: cs.Card):
self.scrap_pile.append(card) self.scrap_pile.append(card)
self.game.notify_scrap_pile() self.game.notify_scrap_pile()

View File

@ -3,11 +3,10 @@ from enum import IntEnum
import json import json
from random import randrange from random import randrange
import socketio import socketio
import cards
import roles import roles as r
import cards import cards as cs
import characters import characters as chars
class PendingAction(IntEnum): class PendingAction(IntEnum):
PICK = 0 PICK = 0
@ -17,19 +16,22 @@ class PendingAction(IntEnum):
WAIT = 4 WAIT = 4
CHOOSE = 5 CHOOSE = 5
class Player: class Player:
import game as g
def __init__(self, name, sid, sio): def __init__(self, name, sid, sio):
super().__init__() super().__init__()
self.name = name self.name = name
self.sid = sid self.sid = sid
self.sio = sio self.sio = sio
self.hand: cards.Card = [] self.hand: cs.Card = []
self.equipment: cards.Card = [] self.equipment: cs.Card = []
self.role: roles.Role = None self.role: r.Role = None
self.character: characters.Character = None self.character: chars.Character = None
self.lives = 0 self.lives = 0
self.max_lives = 0 self.max_lives = 0
self.game = None self.game: g = None
self.is_my_turn = False self.is_my_turn = False
self.is_waiting_for_action = True self.is_waiting_for_action = True
self.has_played_bang = False self.has_played_bang = False
@ -41,7 +43,7 @@ class Player:
self.event_type: str = None self.event_type: str = None
self.expected_response = None self.expected_response = None
self.attacker = None self.attacker = None
self.target_p: str = None self.target_p: str = None
self.is_drawing = False self.is_drawing = False
self.mancato_needed = 0 self.mancato_needed = 0
@ -52,17 +54,20 @@ class Player:
def disconnect(self): def disconnect(self):
return self.game.handle_disconnect(self) return self.game.handle_disconnect(self)
def set_role(self, role: roles.Role): def set_role(self, role: r.Role):
self.role = role self.role = role
print(f'I {self.name} am a {role.name}, my goal is "{role.goal}"') print(f'I {self.name} am a {role.name}, my goal is "{role.goal}"')
self.sio.emit('role', room=self.sid, data=json.dumps(role, default=lambda o: o.__dict__)) self.sio.emit('role', room=self.sid, data=json.dumps(
role, default=lambda o: o.__dict__))
def set_character(self, character: str): def set_character(self, character: str):
print(self.available_characters, character) print(self.available_characters, character)
self.character = next(x for x in self.available_characters if x.name==character) self.character = next(
x for x in self.available_characters if x.name == character)
self.available_characters = [] self.available_characters = []
print(f'I {self.name} chose character {self.character.name}') print(f'I {self.name} chose character {self.character.name}')
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha scelto il personaggio.') self.sio.emit('chat_message', room=self.game.name,
data=f'{self.name} ha scelto il personaggio.')
self.game.notify_character_selection() self.game.notify_character_selection()
def prepare(self): def prepare(self):
@ -75,7 +80,8 @@ class Player:
def set_available_character(self, available): def set_available_character(self, available):
self.available_characters = available self.available_characters = available
print(f'I {self.name} have to choose between {available}') print(f'I {self.name} have to choose between {available}')
self.sio.emit('characters', room=self.sid, data=json.dumps(available, default=lambda o: o.__dict__)) self.sio.emit('characters', room=self.sid, data=json.dumps(
available, default=lambda o: o.__dict__))
def notify_card(self, player, card): def notify_card(self, player, card):
mess = { mess = {
@ -86,9 +92,10 @@ class Player:
self.sio.emit('notify_card', room=self.sid, data=mess) self.sio.emit('notify_card', room=self.sid, data=mess)
def notify_self(self): def notify_self(self):
if isinstance(self.character, characters.CalamityJanet): if isinstance(self.character, chars.CalamityJanet):
self.expected_response = [cards.Mancato(0,0).name, cards.Bang(0,0).name] self.expected_response = [
elif isinstance(self.character, characters.SuzyLafayette) and len(self.hand) == 0: cs.Mancato(0, 0).name, cs.Bang(0, 0).name]
elif isinstance(self.character, chars.SuzyLafayette) and len(self.hand) == 0:
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
ser = self.__dict__.copy() ser = self.__dict__.copy()
ser.pop('game') ser.pop('game')
@ -102,14 +109,18 @@ class Player:
ser['attacker'] = self.attacker.name ser['attacker'] = self.attacker.name
ser['sight'] = self.get_sight() ser['sight'] = self.get_sight()
ser['lives'] = max(ser['lives'], 0) ser['lives'] = max(ser['lives'], 0)
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__)) self.sio.emit('self', room=self.sid, data=json.dumps(
self.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__)) ser, default=lambda o: o.__dict__))
self.sio.emit('self_vis', room=self.sid, data=json.dumps(
self.game.get_visible_players(self), default=lambda o: o.__dict__))
if self.lives <= 0 and self.max_lives > 0: if self.lives <= 0 and self.max_lives > 0:
print('dying, attacker', self.attacker) print('dying, attacker', self.attacker)
if isinstance(self.character, characters.SidKetchum) and len(self.hand) > 1: if isinstance(self.character, chars.SidKetchum) and len(self.hand) > 1:
self.lives += 1 self.lives += 1
self.game.deck.scrap(self.hand.pop(randrange(0, len(self.hand)))) self.game.deck.scrap(self.hand.pop(
self.game.deck.scrap(self.hand.pop(randrange(0, len(self.hand)))) randrange(0, len(self.hand))))
self.game.deck.scrap(self.hand.pop(
randrange(0, len(self.hand))))
self.game.player_death(self) self.game.player_death(self)
self.game.notify_all() self.game.notify_all()
@ -117,13 +128,14 @@ class Player:
if self.lives == 0: if self.lives == 0:
return self.end_turn(forced=True) return self.end_turn(forced=True)
self.scrapped_cards = 0 self.scrapped_cards = 0
self.sio.emit('chat_message', room=self.game.name, data=f'È il turno di {self.name}.') self.sio.emit('chat_message', room=self.game.name,
data=f'È il turno di {self.name}.')
print(f'I {self.name} was notified that it is my turn') print(f'I {self.name} was notified that it is my turn')
self.was_shot = False self.was_shot = False
self.is_my_turn = True self.is_my_turn = True
self.is_waiting_for_action = True self.is_waiting_for_action = True
self.has_played_bang = False self.has_played_bang = False
if any([isinstance(c, cards.Dinamite) or isinstance(c, cards.Prigione) for c in self.equipment]): if any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]):
self.pending_action = PendingAction.PICK self.pending_action = PendingAction.PICK
else: else:
self.pending_action = PendingAction.DRAW self.pending_action = PendingAction.DRAW
@ -132,28 +144,29 @@ class Player:
def draw(self, pile): def draw(self, pile):
if self.pending_action != PendingAction.DRAW: if self.pending_action != PendingAction.DRAW:
return return
if isinstance(self.character, characters.KitCarlson): if isinstance(self.character, chars.KitCarlson):
self.is_drawing = True self.is_drawing = True
self.available_cards = [self.game.deck.draw() for i in range(3)] self.available_cards = [self.game.deck.draw() for i in range(3)]
self.pending_action = PendingAction.CHOOSE self.pending_action = PendingAction.CHOOSE
self.notify_self() self.notify_self()
else: else:
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
if pile == 'scrap' and isinstance(self.character, characters.PedroRamirez): if pile == 'scrap' and isinstance(self.character, chars.PedroRamirez):
self.hand.append(self.game.deck.draw_from_scrap_pile()) self.hand.append(self.game.deck.draw_from_scrap_pile())
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
elif type(pile) == str and pile != self.name and pile in self.game.players_map and isinstance(self.character, characters.JesseJones) and len(self.game.get_player_named(pile).hand) > 0: elif type(pile) == str and pile != self.name and pile in self.game.players_map and isinstance(self.character, chars.JesseJones) and len(self.game.get_player_named(pile).hand) > 0:
self.hand.append(self.game.get_player_named(pile).hand.pop(randrange(0, len(self.game.get_player_named(pile).hand)))) self.hand.append(self.game.get_player_named(pile).hand.pop(
randrange(0, len(self.game.get_player_named(pile).hand))))
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
else: else:
for i in range(2): for i in range(2):
card: cards.Card = self.game.deck.draw() card: cs.Card = self.game.deck.draw()
self.hand.append(card) self.hand.append(card)
if i == 1 and isinstance(self.character, characters.BlackJack): if i == 1 and isinstance(self.character, chars.BlackJack):
for p in self.game.players: for p in self.game.players:
if p != self: if p != self:
p.notify_card(self, card) p.notify_card(self, card)
if card.suit == cards.Suit.HEARTS or card.suit == cards.Suit.DIAMONDS: if card.suit == cs.Suit.HEARTS or card.suit == cs.Suit.DIAMONDS:
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
self.notify_self() self.notify_self()
@ -163,33 +176,36 @@ class Player:
pickable_cards = 1 + self.character.pick_mod pickable_cards = 1 + self.character.pick_mod
if self.is_my_turn: if self.is_my_turn:
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
if isinstance(self.equipment[i], cards.Dinamite): if isinstance(self.equipment[i], cs.Dinamite):
while pickable_cards > 0: while pickable_cards > 0:
pickable_cards -= 1 pickable_cards -= 1
picked: cards.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha estratto {picked}.') self.sio.emit('chat_message', room=self.game.name,
if picked.suit == cards.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0: data=f'{self.name} ha estratto {picked}.')
if picked.suit == cs.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0:
self.lives -= 3 self.lives -= 3
self.game.deck.scrap(self.equipment.pop(i)) self.game.deck.scrap(self.equipment.pop(i))
if isinstance(self.character, characters.BartCassidy): if isinstance(self.character, chars.BartCassidy):
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha fatto esplodere la dinamite.') self.sio.emit('chat_message', room=self.game.name,
data=f'{self.name} ha fatto esplodere la dinamite.')
print(f'{self.name} Boom, -3 hp') print(f'{self.name} Boom, -3 hp')
else: else:
self.game.next_player().equipment.append(self.equipment.pop(i)) self.game.next_player().equipment.append(self.equipment.pop(i))
self.game.next_player().notify_self() self.game.next_player().notify_self()
if any([isinstance(c, cards.Dinamite) or isinstance(c, cards.Prigione) for c in self.equipment]): if any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]):
self.notify_self() self.notify_self()
return return
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
if isinstance(self.equipment[i], cards.Prigione): if isinstance(self.equipment[i], cs.Prigione):
while pickable_cards > 0: while pickable_cards > 0:
pickable_cards -= 1 pickable_cards -= 1
picked: cards.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha estratto {picked}.') self.sio.emit('chat_message', room=self.game.name,
if picked.suit != cards.Suit.HEARTS and pickable_cards == 0: data=f'{self.name} ha estratto {picked}.')
if picked.suit != cs.Suit.HEARTS and pickable_cards == 0:
self.game.deck.scrap(self.equipment.pop(i)) self.game.deck.scrap(self.equipment.pop(i))
self.end_turn(forced=True) self.end_turn(forced=True)
return return
@ -207,29 +223,30 @@ class Player:
playable_cards = [] playable_cards = []
for i in range(len(self.hand)): for i in range(len(self.hand)):
card = self.hand[i] card = self.hand[i]
if isinstance(card, cards.Bang) and self.has_played_bang and not any([isinstance(c, cards.Volcanic) for c in self.equipment]): if isinstance(card, cs.Bang) and self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment]):
continue continue
elif isinstance(card, cards.Birra) and self.lives >= self.max_lives: elif isinstance(card, cs.Birra) and self.lives >= self.max_lives:
continue continue
else: else:
playable_cards.append(i) playable_cs.append(i)
return playable_cards return playable_cards
def get_public_description(self): def get_public_description(self):
s = f"{self.name} {'Sheriff ⭐️' if isinstance(self.role, roles.Sheriff) else ''} ({self.lives}/{self.max_lives} ⁍) {len(self.hand)} Cards in hand, " s = f"{self.name} {'Sheriff ⭐️' if isinstance(self.role, r.Sheriff) else ''} ({self.lives}/{self.max_lives} ⁍) {len(self.hand)} Cards in hand, "
s += f"equipment {[str(c) for c in self.equipment]}" s += f"equipment {[str(c) for c in self.equipment]}"
return s return s
def play_card(self, hand_index: int, againts=None): def play_card(self, hand_index: int, against=None):
if not (0 <= hand_index < len(self.hand)): if not (0 <= hand_index < len(self.hand)):
print('illegal') print('illegal')
return return
card: cards.Card = self.hand.pop(hand_index) card: cs.Card = self.hand.pop(hand_index)
print(self.name, 'is playing ', card, ' against:', againts) print(self.name, 'is playing ', card, ' against:', against)
if isinstance(card, cards.Prigione) and not isinstance(self.game.get_player_named(againts).role, roles.Sheriff): if isinstance(card, cs.Prigione) and not isinstance(self.game.get_player_named(against).role, r.Sheriff):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} contro {againts}.') self.sio.emit('chat_message', room=self.game.name,
self.game.get_player_named(againts).equipment.append(card) data=f'{self.name} ha giocato {card.name} contro {against}.')
self.game.get_player_named(againts).notify_self() self.game.get_player_named(against).equipment.append(card)
self.game.get_player_named(against).notify_self()
elif card.is_equipment: elif card.is_equipment:
if card.is_weapon: if card.is_weapon:
has_weapon = False has_weapon = False
@ -241,7 +258,7 @@ class Player:
break break
if not has_weapon: if not has_weapon:
self.equipment.append(card) self.equipment.append(card)
elif card.name in [c.name for c in self.equipment if not isinstance(c, cards.Dinamite)]: elif card.name in [c.name for c in self.equipment if not isinstance(c, cs.Dinamite)]:
for i in range(len(self.equipment)): for i in range(len(self.equipment)):
if type(self.equipment[i]) == type(card): if type(self.equipment[i]) == type(card):
self.game.deck.scrap(self.equipment[i]) self.game.deck.scrap(self.equipment[i])
@ -250,74 +267,7 @@ class Player:
else: else:
self.equipment.append(card) self.equipment.append(card)
else: else:
did_play_card = False did_play_card = card.play_card(self, against)
if isinstance(card, cards.Bang) and self.has_played_bang and not any([isinstance(c, cards.Volcanic) for c in self.equipment]) and againts != None:
self.hand.insert(hand_index, card)
return
elif isinstance(card, cards.Bang) and againts != None:
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} contro {againts}.')
self.has_played_bang = not isinstance(self.character, characters.WillyTheKid)
self.game.attack(self, againts)
did_play_card = True
elif isinstance(card, cards.Birra):
if len(self.game.players) != 2 and self.lives != self.max_lives:
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato una {card.name}.')
self.lives = min(self.lives+1, self.max_lives)
did_play_card = True
elif len(self.game.players) == 2:
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha rovesciato una {card.name}.')
did_play_card = True
elif isinstance(card, cards.CatBalou) and againts != None:
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} contro {againts}.')
self.pending_action = PendingAction.CHOOSE
self.choose_action = 'discard'
self.target_p = againts
did_play_card = True
print('choose now')
elif isinstance(card, cards.Diligenza):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} e ha pescato 2 carte.')
for i in range(2):
self.hand.append(self.game.deck.draw())
did_play_card = True
elif isinstance(card, cards.Duello):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} contro {againts}.')
self.game.duel(self, againts)
did_play_card = True
elif isinstance(card, cards.Emporio):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name}.')
self.game.emporio()
did_play_card = True
elif isinstance(card, cards.Gatling):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name}.')
self.game.attack_others(self)
did_play_card = True
elif isinstance(card, cards.Indiani):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name}.')
self.game.indian_others(self)
did_play_card = True
elif isinstance(card, cards.Mancato) and (not self.has_played_bang and againts != None and isinstance(self.character, characters.CalamityJanet)):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} come un BANG! contro {againts}.')
self.has_played_bang = True
self.game.attack(self, againts)
did_play_card = True
elif isinstance(card, cards.Panico) and againts != None:
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} contro {againts}.')
self.pending_action = PendingAction.CHOOSE
self.choose_action = 'steal'
self.target_p = againts
print('choose now')
did_play_card = True
elif isinstance(card, cards.Saloon):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} e ha curato 1 punto vita a tutti.')
for p in self.game.players:
p.lives = min(p.lives+1, p.max_lives)
p.notify_self()
did_play_card = True
elif isinstance(card, cards.WellsFargo):
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha giocato {card.name} e ha pescato 3 carte.')
for i in range(3):
self.hand.append(self.game.deck.draw())
did_play_card = True
if did_play_card: if did_play_card:
self.game.deck.scrap(card) self.game.deck.scrap(card)
else: else:
@ -327,7 +277,7 @@ class Player:
def choose(self, card_index): def choose(self, card_index):
if self.pending_action != PendingAction.CHOOSE: if self.pending_action != PendingAction.CHOOSE:
return return
if self.target_p and self.target_p != '': # panico, cat balou if self.target_p and self.target_p != '': # panico, cat balou
target = self.game.get_player_named(self.target_p) target = self.game.get_player_named(self.target_p)
card = None card = None
if card_index >= len(target.hand): if card_index >= len(target.hand):
@ -343,70 +293,72 @@ class Player:
self.choose_action = '' self.choose_action = ''
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
elif self.is_drawing and isinstance(self.character, characters.KitCarlson): # specifico per personaggio # specifico per personaggio
self.hand.append(self.available_cards.pop(card_index)) elif self.is_drawing and isinstance(self.character, chars.KitCarlson):
self.hand.append(self.available_cs.pop(card_index))
if len(self.available_cards) == 1: if len(self.available_cards) == 1:
self.game.deck.put_on_top(self.available_cards.pop()) self.game.deck.put_on_top(self.available_cs.pop())
self.is_drawing = False self.is_drawing = False
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
self.notify_self() self.notify_self()
else: # emporio else: # emporio
self.game.respond_emporio(self, card_index) self.game.respond_emporio(self, card_index)
def barrel_pick(self): def barrel_pick(self):
pickable_cards = 1 + self.character.pick_mod pickable_cards = 1 + self.character.pick_mod
if len([c for c in self.equipment if isinstance(c, cards.Barile)]) > 0 and isinstance(self.character, characters.Jourdonnais): if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 and isinstance(self.character, chars.Jourdonnais):
pickable_cards = 2 pickable_cards = 2
while pickable_cards > 0: while pickable_cards > 0:
pickable_cards -= 1 pickable_cards -= 1
picked: cards.Card = self.game.deck.pick_and_scrap() picked: cs.Card = self.game.deck.pick_and_scrap()
print(f'Did pick {picked}') print(f'Did pick {picked}')
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha estratto {picked}.') self.sio.emit('chat_message', room=self.game.name,
if picked.suit == cards.Suit.HEARTS: data=f'{self.name} ha estratto {picked}.')
if picked.suit == cs.Suit.HEARTS:
self.mancato_needed -= 1 self.mancato_needed -= 1
self.notify_self() self.notify_self()
if self.mancato_needed <= 0: if self.mancato_needed <= 0:
self.game.responders_did_respond_resume_turn() self.game.responders_did_respond_resume_turn()
return return
if len([c for c in self.hand if isinstance(c, cards.Mancato) or (isinstance(self.character, characters.CalamityJanet) and isinstance(c, cards.Bang))]) == 0: if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang))]) == 0:
self.take_damage_response() self.take_damage_response()
self.game.responders_did_respond_resume_turn() self.game.responders_did_respond_resume_turn()
else: else:
self.pending_action = PendingAction.RESPOND self.pending_action = PendingAction.RESPOND
self.expected_response = [cards.Mancato(0,0).name] self.expected_response = [cs.Mancato(0, 0).name]
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self() self.notify_self()
def get_banged(self, attacker, double=False): def get_banged(self, attacker, double=False):
self.attacker = attacker self.attacker = attacker
self.mancato_needed = 1 if not double else 2 self.mancato_needed = 1 if not double else 2
if len([c for c in self.hand if isinstance(c, cards.Mancato) or (isinstance(self.character, characters.CalamityJanet) and isinstance(c, cards.Bang))]) == 0 and len([c for c in self.equipment if isinstance(c, cards.Barile)]) == 0 and not isinstance(self.character, characters.Jourdonnais): if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang))]) == 0 and len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais):
print('Cant defend') print('Cant defend')
self.take_damage_response() self.take_damage_response()
return False return False
else: else:
if len([c for c in self.equipment if isinstance(c, cards.Barile)]) > 0 or isinstance(self.character, characters.Jourdonnais): if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 or isinstance(self.character, chars.Jourdonnais):
print('has barrel') print('has barrel')
self.pending_action = PendingAction.PICK self.pending_action = PendingAction.PICK
self.on_pick_cb = self.barrel_pick self.on_pick_cb = self.barrel_pick
else: else:
print('has mancato') print('has mancato')
self.pending_action = PendingAction.RESPOND self.pending_action = PendingAction.RESPOND
self.expected_response = [cards.Mancato(0,0).name] self.expected_response = [cs.Mancato(0, 0).name]
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self() self.notify_self()
return True return True
def get_indians(self, attacker): def get_indians(self, attacker):
self.attacker = attacker self.attacker = attacker
if len([c for c in self.hand if isinstance(c, cards.Bang) or (isinstance(self.character, characters.CalamityJanet) and isinstance(c, cards.Mancato))]) == 0: if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
print('Cant defend') print('Cant defend')
self.take_damage_response() self.take_damage_response()
return False return False
else: else:
print('has bang') print('has bang')
self.pending_action = PendingAction.RESPOND self.pending_action = PendingAction.RESPOND
self.expected_response = [cards.Bang(0,0).name] self.expected_response = [cs.Bang(0, 0).name]
self.event_type = 'indians' self.event_type = 'indians'
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self() self.notify_self()
@ -414,14 +366,14 @@ class Player:
def get_dueled(self, attacker): def get_dueled(self, attacker):
self.attacker = attacker self.attacker = attacker
if len([c for c in self.hand if isinstance(c, cards.Bang) or (isinstance(self.character, characters.CalamityJanet) and isinstance(c, cards.Mancato))]) == 0: if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
print('Cant defend') print('Cant defend')
self.take_damage_response() self.take_damage_response()
self.game.responders_did_respond_resume_turn() self.game.responders_did_respond_resume_turn()
return False return False
else: else:
self.pending_action = PendingAction.RESPOND self.pending_action = PendingAction.RESPOND
self.expected_response = [cards.Bang(0,0).name] self.expected_response = [cs.Bang(0, 0).name]
self.event_type = 'duel' self.event_type = 'duel'
self.on_failed_response_cb = self.take_damage_response self.on_failed_response_cb = self.take_damage_response
self.notify_self() self.notify_self()
@ -430,17 +382,19 @@ class Player:
def take_damage_response(self): def take_damage_response(self):
self.lives -= 1 self.lives -= 1
if self.lives > 0: if self.lives > 0:
if isinstance(self.character, characters.BartCassidy): if isinstance(self.character, chars.BartCassidy):
self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw())
elif isinstance(self.character, characters.ElGringo) and self.attacker and len(self.attacker.hand) > 0: elif isinstance(self.character, chars.ElGringo) and self.attacker and len(self.attacker.hand) > 0:
self.hand.append(self.attacker.hand.pop(randrange(0, len(self.attacker.hand)))) self.hand.append(self.attacker.hand.pop(
randrange(0, len(self.attacker.hand))))
self.attacker.notify_self() self.attacker.notify_self()
while self.lives <= 0 and len(self.game.players) > 2 and len([c for c in self.hand if isinstance(c, cards.Birra)]) > 0: while self.lives <= 0 and len(self.game.players) > 2 and len([c for c in self.hand if isinstance(c, cs.Birra)]) > 0:
for i in range(len(self.hand)): for i in range(len(self.hand)):
if isinstance(self.hand[i], cards.Birra): if isinstance(self.hand[i], cs.Birra):
self.lives += 1 self.lives += 1
self.game.deck.scrap(self.hand.pop(i)) self.game.deck.scrap(self.hand.pop(i))
self.sio.emit('chat_message', room=self.game.name, data=f'{self.name} ha usato una birra per recuperare una vita.') self.sio.emit('chat_message', room=self.game.name,
data=f'{self.name} ha usato una birra per recuperare una vita.')
break break
self.mancato_needed = 0 self.mancato_needed = 0
self.notify_self() self.notify_self()
@ -487,18 +441,20 @@ class Player:
return self.character.visibility_mod + covers return self.character.visibility_mod + covers
def scrap(self, card_index): def scrap(self, card_index):
if self.is_my_turn or isinstance(self.character, characters.SidKetchum): if self.is_my_turn or isinstance(self.character, chars.SidKetchum):
self.scrapped_cards += 1 self.scrapped_cards += 1
if isinstance(self.character, characters.SidKetchum) and self.scrapped_cards == 2: if isinstance(self.character, chars.SidKetchum) and self.scrapped_cards == 2:
self.scrapped_cards = 0 self.scrapped_cards = 0
self.lives = min(self.lives+1, self.max_lives) self.lives = min(self.lives+1, self.max_lives)
self.game.deck.scrap(self.hand.pop(card_index)) self.game.deck.scrap(self.hand.pop(card_index))
self.notify_self() self.notify_self()
def end_turn(self, forced=False): def end_turn(self, forced=False):
if not self.is_my_turn: return if not self.is_my_turn:
return
if len(self.hand) > self.max_lives and not forced: if len(self.hand) > self.max_lives and not forced:
print(f"I {self.name} have to many cards in my hand and I can't end the turn") print(
f"I {self.name} have to many cards in my hand and I can't end the turn")
else: else:
self.is_my_turn = False self.is_my_turn = False
self.pending_action = PendingAction.WAIT self.pending_action = PendingAction.WAIT