commit
f3631232d1
2
.gitignore
vendored
2
.gitignore
vendored
@ -139,3 +139,5 @@ cython_debug/
|
|||||||
|
|
||||||
frontend/package-lock.json
|
frontend/package-lock.json
|
||||||
bang-workspace.code-workspace
|
bang-workspace.code-workspace
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
@ -8,6 +8,9 @@ import socketio
|
|||||||
from bang.game import Game
|
from bang.game import Game
|
||||||
from bang.players import Player
|
from bang.players import Player
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.setrecursionlimit(10**6) # this should prevents bots from stopping
|
||||||
|
|
||||||
sio = socketio.Server(cors_allowed_origins="*")
|
sio = socketio.Server(cors_allowed_origins="*")
|
||||||
static_files={
|
static_files={
|
||||||
'/': {'content_type': 'text/html', 'filename': 'index.html'},
|
'/': {'content_type': 'text/html', 'filename': 'index.html'},
|
||||||
@ -205,6 +208,8 @@ def chat_message(sid, msg):
|
|||||||
ses.game.reset()
|
ses.game.reset()
|
||||||
elif '/startgame' in msg and not ses.game.started:
|
elif '/startgame' in msg and not ses.game.started:
|
||||||
ses.game.start_game()
|
ses.game.start_game()
|
||||||
|
elif '/setbotspeed' in msg:
|
||||||
|
ses.game.bot_speed = float(msg.split()[1])
|
||||||
elif '/addex' in msg and not ses.game.started:
|
elif '/addex' in msg and not ses.game.started:
|
||||||
cmd = msg.split()
|
cmd = msg.split()
|
||||||
if len(cmd) == 2:
|
if len(cmd) == 2:
|
||||||
@ -214,10 +219,39 @@ def chat_message(sid, msg):
|
|||||||
ses.game.notify_room()
|
ses.game.notify_room()
|
||||||
else:
|
else:
|
||||||
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
|
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
|
||||||
|
elif '/setcharacter' in msg:
|
||||||
|
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and changed character'})
|
||||||
|
import bang.characters as characters
|
||||||
|
cmd = msg.split()
|
||||||
|
if len(cmd) >= 2:
|
||||||
|
chs = characters.all_characters(ses.game.expansions)
|
||||||
|
ses.character = [c for c in chs if c.name == ' '.join(cmd[1:])][0]
|
||||||
|
ses.real_character = ses.character
|
||||||
|
ses.notify_self()
|
||||||
|
elif '/removecard' in msg:
|
||||||
|
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and removed a card'})
|
||||||
|
cmd = msg.split()
|
||||||
|
if len(cmd) == 2:
|
||||||
|
if len(ses.hand) > int(cmd[1]):
|
||||||
|
ses.hand.pop(int(cmd[1]))
|
||||||
|
else:
|
||||||
|
ses.hand.pop(int(cmd[1])-len(ses.hand))
|
||||||
|
ses.notify_self()
|
||||||
|
elif '/getcard' in msg:
|
||||||
|
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and got a card'})
|
||||||
|
import bang.cards as cs
|
||||||
|
cmd = msg.split()
|
||||||
|
if len(cmd) >= 2:
|
||||||
|
cards = cs.get_starting_deck(ses.game.expansions)
|
||||||
|
ses.hand.append([c for c in cards if c.name == ' '.join(cmd[1:])][0])
|
||||||
|
ses.notify_self()
|
||||||
elif '/gameinfo' in msg:
|
elif '/gameinfo' in msg:
|
||||||
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.game.__dict__}'})
|
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.game.__dict__}'})
|
||||||
elif '/meinfo' in msg:
|
elif '/meinfo' in msg:
|
||||||
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.__dict__}'})
|
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.__dict__}'})
|
||||||
|
elif '/mebot' in msg:
|
||||||
|
ses.is_bot = not ses.is_bot
|
||||||
|
ses.notify_self()
|
||||||
else:
|
else:
|
||||||
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} COMMAND NOT FOUND'})
|
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} COMMAND NOT FOUND'})
|
||||||
else:
|
else:
|
||||||
|
@ -58,12 +58,7 @@ class Card(ABC):
|
|||||||
if not has_weapon:
|
if not has_weapon:
|
||||||
player.equipment.append(self)
|
player.equipment.append(self)
|
||||||
elif self.name in [c.name for c in player.equipment if not isinstance(c, Dinamite)]:
|
elif self.name in [c.name for c in player.equipment if not isinstance(c, Dinamite)]:
|
||||||
for i in range(len(player.equipment)):
|
return False
|
||||||
print('tipo',type(self))
|
|
||||||
if type(player.equipment[i]) == type(self):
|
|
||||||
player.game.deck.scrap(player.equipment[i])
|
|
||||||
player.equipment[i] = self
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
player.equipment.append(self)
|
||||||
if against:
|
if against:
|
||||||
@ -77,6 +72,9 @@ class Card(ABC):
|
|||||||
def use_card(self, player):
|
def use_card(self, player):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_duplicate_card(self, player):
|
||||||
|
return self.name in [c.name for c in player.equipment]
|
||||||
|
|
||||||
|
|
||||||
class Barile(Card):
|
class Barile(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -124,6 +122,7 @@ class Prigione(Card):
|
|||||||
data=f'_play_card_against|{player.name}|{self.name}|{against}')
|
data=f'_play_card_against|{player.name}|{self.name}|{against}')
|
||||||
player.game.get_player_named(against).equipment.append(self)
|
player.game.get_player_named(against).equipment.append(self)
|
||||||
player.game.get_player_named(against).notify_self()
|
player.game.get_player_named(against).notify_self()
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class Remington(Card):
|
class Remington(Card):
|
||||||
|
@ -22,15 +22,16 @@ class Deck:
|
|||||||
self.event_cards: List[ce.CardEvent] = []
|
self.event_cards: List[ce.CardEvent] = []
|
||||||
if 'fistful_of_cards' in game.expansions:
|
if 'fistful_of_cards' in game.expansions:
|
||||||
self.event_cards.extend(ce.get_all_events())
|
self.event_cards.extend(ce.get_all_events())
|
||||||
random.shuffle(self.event_cards)
|
self.event_cards.insert(0, None)
|
||||||
|
self.event_cards.insert(0, None) # 2 perchè iniziale, e primo flip dallo sceriffo
|
||||||
random.shuffle(self.cards)
|
random.shuffle(self.cards)
|
||||||
self.scrap_pile: List[cs.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 flip_event(self):
|
def flip_event(self):
|
||||||
if len(self.event_cards) > 0:
|
if len(self.event_cards) > 0 and not isinstance(self.event_cards[0], ce.PerUnPugnoDiCarte):
|
||||||
self.event_cards.append(self.event_cards.pop(0))
|
self.event_cards.append(self.event_cards.pop(0))
|
||||||
self.game.notify_event_card()
|
self.game.notify_event_card()
|
||||||
|
|
||||||
def peek(self, n_cards: int) -> list:
|
def peek(self, n_cards: int) -> list:
|
||||||
return self.cards[:n_cards]
|
return self.cards[:n_cards]
|
||||||
@ -52,7 +53,9 @@ class Deck:
|
|||||||
def put_on_top(self, card: cs.Card):
|
def put_on_top(self, card: cs.Card):
|
||||||
self.cards.insert(0, card)
|
self.cards.insert(0, card)
|
||||||
|
|
||||||
def draw(self) -> cs.Card:
|
def draw(self, ignore_event = False) -> cs.Card:
|
||||||
|
if self.game.check_event(ce.MinieraAbbandonata) and len(self.scrap_pile) > 0 and not ignore_event:
|
||||||
|
return self.draw_from_scrap_pile()
|
||||||
card = self.cards.pop(0)
|
card = self.cards.pop(0)
|
||||||
if len(self.cards) == 0:
|
if len(self.cards) == 0:
|
||||||
self.reshuffle()
|
self.reshuffle()
|
||||||
@ -71,8 +74,11 @@ class Deck:
|
|||||||
else:
|
else:
|
||||||
return self.draw()
|
return self.draw()
|
||||||
|
|
||||||
def scrap(self, card: cs.Card):
|
def scrap(self, card: cs.Card, ignore_event = False):
|
||||||
if card.usable_next_turn:
|
if card.usable_next_turn:
|
||||||
card.can_be_used_now = False
|
card.can_be_used_now = False
|
||||||
self.scrap_pile.append(card)
|
if self.game.check_event(ce.MinieraAbbandonata) and not ignore_event:
|
||||||
self.game.notify_scrap_pile()
|
self.put_on_top(card)
|
||||||
|
else:
|
||||||
|
self.scrap_pile.append(card)
|
||||||
|
self.game.notify_scrap_pile()
|
||||||
|
@ -152,8 +152,11 @@ class Bibbia(Schivata):
|
|||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class Cappello(Mancato):
|
class Cappello(Mancato):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -168,8 +171,11 @@ class Cappello(Mancato):
|
|||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class PlaccaDiFerro(Cappello):
|
class PlaccaDiFerro(Cappello):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -195,8 +201,11 @@ class Pugnale(Pugno):
|
|||||||
if self.can_be_used_now:
|
if self.can_be_used_now:
|
||||||
return super().play_card(player, against=against)
|
return super().play_card(player, against=against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class Derringer(Pugnale):
|
class Derringer(Pugnale):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -212,8 +221,11 @@ class Derringer(Pugnale):
|
|||||||
player.hand.append(player.game.deck.draw())
|
player.hand.append(player.game.deck.draw())
|
||||||
return super().play_card(player, against=against)
|
return super().play_card(player, against=against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def use_card(self, player):
|
def use_card(self, player):
|
||||||
player.hand.append(player.game.deck.draw())
|
player.hand.append(player.game.deck.draw())
|
||||||
@ -235,8 +247,11 @@ class Borraccia(Card):
|
|||||||
player.notify_self()
|
player.notify_self()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class PonyExpress(WellsFargo):
|
class PonyExpress(WellsFargo):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -250,8 +265,11 @@ class PonyExpress(WellsFargo):
|
|||||||
if self.can_be_used_now:
|
if self.can_be_used_now:
|
||||||
return super().play_card(player, against)
|
return super().play_card(player, against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class Howitzer(Gatling):
|
class Howitzer(Gatling):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -265,8 +283,11 @@ class Howitzer(Gatling):
|
|||||||
if self.can_be_used_now:
|
if self.can_be_used_now:
|
||||||
return super().play_card(player, against)
|
return super().play_card(player, against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class CanCan(CatBalou):
|
class CanCan(CatBalou):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -280,8 +301,11 @@ class CanCan(CatBalou):
|
|||||||
if self.can_be_used_now:
|
if self.can_be_used_now:
|
||||||
return super().play_card(player, against)
|
return super().play_card(player, against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class Conestoga(Panico):
|
class Conestoga(Panico):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -297,8 +321,11 @@ class Conestoga(Panico):
|
|||||||
if self.can_be_used_now:
|
if self.can_be_used_now:
|
||||||
return super().play_card(player, against)
|
return super().play_card(player, against)
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class Pepperbox(Bang):
|
class Pepperbox(Bang):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -316,8 +343,11 @@ class Pepperbox(Bang):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class FucileDaCaccia(Card):
|
class FucileDaCaccia(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -336,12 +366,14 @@ class FucileDaCaccia(Card):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
player.equipment.append(self)
|
if not self.is_duplicate_card(player):
|
||||||
return True
|
player.equipment.append(self)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def get_starting_deck() -> List[Card]:
|
def get_starting_deck() -> List[Card]:
|
||||||
return [
|
return [
|
||||||
#TODO: aggiungere anche le carte normalmente presenti https://bang.dvgiochi.com/cardslist.php?id=3
|
|
||||||
Barile(Suit.CLUBS, 'A'),
|
Barile(Suit.CLUBS, 'A'),
|
||||||
Binocolo(Suit.DIAMONDS, 10),
|
Binocolo(Suit.DIAMONDS, 10),
|
||||||
Dinamite(Suit.CLUBS, 10),
|
Dinamite(Suit.CLUBS, 10),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
import random
|
||||||
|
|
||||||
class CardEvent(ABC):
|
class CardEvent(ABC):
|
||||||
def __init__(self, name, icon):
|
def __init__(self, name, icon):
|
||||||
@ -7,109 +8,114 @@ class CardEvent(ABC):
|
|||||||
|
|
||||||
class Agguato(CardEvent):
|
class Agguato(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Agguato', '🛁')
|
super().__init__("Agguato", "🛁")
|
||||||
self.desc = 'La distanza base di tra 2 qualsiasi giocatori è 1'
|
self.desc = "La distanza base di tra 2 qualsiasi giocatori è 1"
|
||||||
self.desc_eng = 'The base distance from any 2 players is 1'
|
self.desc_eng = "The base distance from any 2 players is 1"
|
||||||
|
|
||||||
class Cecchino(CardEvent):
|
class Cecchino(CardEvent):
|
||||||
def __init__(self): #TODO
|
def __init__(self):
|
||||||
super().__init__('Cecchino', '👁')
|
super().__init__("Cecchino", "👁")
|
||||||
self.desc = 'Nel proprio turno i giocatori possono scartare 2 Bang assieme per sparare un bang a cui servono 2 mancato'
|
self.desc = "Nel proprio turno i giocatori possono scartare 2 Bang assieme per sparare un bang che necessita 2 mancato (clicca la carta)"
|
||||||
self.desc_eng = 'During their turn, players can discard 2 Bang! to shoot a bang that requires 2 missed'
|
self.desc_eng = "During their turn, players can discard 2 Bang! to shoot a bang that requires 2 missed (click the card)"
|
||||||
|
|
||||||
class DeadMan(CardEvent):
|
class DeadMan(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Dead Man', '⚰️')
|
super().__init__("Dead Man", "⚰️")
|
||||||
self.desc = 'Al proprio turno il giocatore che è morto per primo torna in vita con 2 vite e 2 carte'
|
self.desc = "Al proprio turno il giocatore che è morto per primo torna in vita con 2 vite e 2 carte"
|
||||||
self.desc_eng = 'The first player that died return back to life with 2 hp and 2 cards'
|
self.desc_eng = "The first player that died return back to life with 2 hp and 2 cards"
|
||||||
|
|
||||||
class FratelliDiSangue(CardEvent):
|
class FratelliDiSangue(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Fratelli Di Sangue', '💉')
|
super().__init__("Fratelli Di Sangue", "💉")
|
||||||
self.desc = 'All\'inizio del proprio turno i giocatori possono perdere 1 vita per darla a un altro giocatore'
|
self.desc = "All'inizio del proprio turno, i giocatori possono perdere 1 vita (tranne l'ultimo) per darla a un altro giocatore"
|
||||||
self.desc_eng = 'At the begin of their turn, payers can lose 1 hp to give it to another player'
|
self.desc_eng = "At the begin of their turn, payers can lose 1 hp (except the last one) to give it to another player"
|
||||||
|
|
||||||
class IlGiudice(CardEvent):
|
class IlGiudice(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Il Giudice', '👨⚖️')
|
super().__init__("Il Giudice", "👨⚖️")
|
||||||
self.desc = 'Non si possono equipaggiare carte a se stessi o agli altri'
|
self.desc = "Non si possono equipaggiare carte a se stessi o agli altri"
|
||||||
self.desc_eng = 'You can\'t equip cards on your or other players'
|
self.desc_eng = "You can't equip cards on your or other players"
|
||||||
|
|
||||||
class Lazo(CardEvent):
|
class Lazo(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Lazo', '📿')
|
super().__init__("Lazo", "📿")
|
||||||
self.desc = 'Le carte equipaggiate non hanno effetto'
|
self.desc = "Le carte equipaggiate non hanno effetto"
|
||||||
self.desc_eng = 'Cards in the equipment slot do not work'
|
self.desc_eng = "Cards in the equipment slot do not work"
|
||||||
|
|
||||||
class LeggeDelWest(CardEvent):
|
class LeggeDelWest(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Legge Del West', '⚖️')
|
super().__init__("Legge Del West", "⚖️")
|
||||||
self.desc = 'I giocatori mostrano la seconda carta che pescano e sono obbligati a usarla in quel turno (se possibile)'
|
self.desc = "I giocatori mostrano la seconda carta che pescano e sono obbligati a usarla in quel turno (se possibile)"
|
||||||
self.desc_eng = 'Every player shows the second card that they draw and must use it in that round'
|
self.desc_eng = "Every player shows the second card that they draw and must use it in that round (if it is possible)"
|
||||||
|
|
||||||
class LiquoreForte(CardEvent):
|
class LiquoreForte(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Liquore Forte', '🥃')
|
super().__init__("Liquore Forte", "🥃")
|
||||||
self.desc = 'I giocatori possono evitare di pescare per recuperare 1 vita'
|
self.desc = "I giocatori possono evitare di pescare per recuperare 1 vita (clicca sulla carta evento per farlo)"
|
||||||
self.desc_eng = 'Players can skip drawing to regain 1 HP'
|
self.desc_eng = "Players can skip drawing to regain 1 HP (click on the event card to use)"
|
||||||
|
|
||||||
class MinieraAbbandonata(CardEvent):
|
class MinieraAbbandonata(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Miniera Abbandonata', '⛏')
|
super().__init__("Miniera Abbandonata", "⛏")
|
||||||
self.desc = 'I giocatori pescano dagli scarti e scartano in cima al mazzo'
|
self.desc = "I giocatori pescano dagli scarti nella loro fase 1 e scartano in cima al mazzo nella loro fase 3 (se gli scarti finiscono, è necessario pescare e scartare in cima al mazzo)"
|
||||||
self.desc_eng = 'Players draw from the discarded pile and discard to the deck'
|
#TODO: cambiare anche la descrizione inglese
|
||||||
|
self.desc_eng = "Players draw from the discarded pile and discard to the top of the deck (if the discards run out, they must draw and discard on top of the deck)"
|
||||||
|
|
||||||
class PerUnPugnoDiCarte(CardEvent):
|
class PerUnPugnoDiCarte(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Per Un Pugno Di Carte', '🎴')
|
super().__init__("Per Un Pugno Di Carte", "🎴")
|
||||||
self.desc = 'Il giocatore subisce tanti bang quante carte ha in mano'
|
self.desc = "All'inizio del proprio turno, il giocatore subisce tanti bang quante carte ha in mano"
|
||||||
self.desc_eng = 'On his turn the player is target of as many Bang as how many cards he has in his hand'
|
self.desc_eng = "On the beginning of his turn, the player is target of as many Bang as how many cards he has in his hand"
|
||||||
|
|
||||||
class Peyote(CardEvent):
|
class Peyote(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Peyote', '🌵')
|
super().__init__("Peyote", "🌵")
|
||||||
self.desc = 'Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina continua'
|
self.desc = "Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina aggiunge la carta alla mano e continua provando ad indovinare la carta successiva"
|
||||||
self.desc_eng = 'Instead of drawing, the player tries to guess the color of the suit, if he\'s right he repeats'
|
self.desc_eng = "Instead of drawing, the player tries to guess the color of the suit, if he's right he adds the card to the hand and continues trying to guess the next card"
|
||||||
|
|
||||||
class Ranch(CardEvent):
|
class Ranch(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Ranch', '🐮')
|
super().__init__("Ranch", "🐮")
|
||||||
self.desc = 'Dopo aver pescato il giocatore può scartare quante carte vuole dalla mano e pescarne altrettante dal mazzo'
|
self.desc = "Dopo aver pescato il giocatore può scartare quante carte vuole dalla mano e pescarne altrettante dal mazzo"
|
||||||
self.desc_eng = 'After drawing, the player can discard as many cards as he wants from his hand and draw as many from the deck'
|
self.desc_eng = "After drawing, the player can discard as many cards as he wants from his hand and draw as many from the deck"
|
||||||
|
|
||||||
class Rimbalzo(CardEvent):
|
class Rimbalzo(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Rimbalzo', '⏮')
|
super().__init__("Rimbalzo", "⏮")
|
||||||
self.desc = 'Il giocatore di turno può giocare bang contro le carte equipaggiate dagli altri giocatori, se non giocano mancato vengono scartate'
|
self.desc = "Il giocatore di turno può giocare bang contro le carte equipaggiate dagli altri giocatori, se non giocano mancato vengono scartate (clicca la carta evento)"
|
||||||
self.desc_eng = 'The player can play bang against the cards equipped by the other players, if they do not play miss they are discarded'
|
self.desc_eng = "The player can play bang against the cards equipped by the other players, if they do not play miss they are discarded (click the event card)"
|
||||||
|
|
||||||
class RouletteRussa(CardEvent):
|
class RouletteRussa(CardEvent):
|
||||||
def __init__(self):#TODO
|
def __init__(self):
|
||||||
super().__init__('Roulette Russa', '🇷🇺')
|
super().__init__("Roulette Russa", "🇷🇺")
|
||||||
self.desc = 'A partire dallo sceriffo, ogni giocatore scarta 1 mancato, il primo che non lo fa perde 2 vite'
|
self.desc = "A partire dallo sceriffo, ogni giocatore scarta 1 mancato, il primo che non lo fa perde 2 vite"
|
||||||
self.desc_eng = 'Starting from the sheriff, every player discards 1 missed, the first one that doesn\'t loses 2 HP'
|
self.desc_eng = "Starting from the sheriff, every player discards 1 missed, the first one that doesn't loses 2 HP"
|
||||||
|
|
||||||
class Vendetta(CardEvent):
|
class Vendetta(CardEvent):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Vendetta', '😤')
|
super().__init__("Vendetta", "😤")
|
||||||
self.desc = 'Alla fine del proprio turno il giocatore estrae, se esce ♥️ gioca un altro turno'
|
self.desc = "Alla fine del proprio turno il giocatore estrae dal mazzo, se esce ♥️ gioca un altro turno (ma non estrae di nuovo)"
|
||||||
self.desc_eng = 'When ending the turn, the player flips a card, if it\'s ♥️ he plays another turn'
|
self.desc_eng = "When ending the turn, the player flips a card from the deck, if it's ♥️ he plays another turn (but he does not flip another card)"
|
||||||
|
|
||||||
def get_all_events():
|
def get_all_events():
|
||||||
return [
|
cards = [
|
||||||
Agguato(),
|
Agguato(),
|
||||||
# Cecchino(),
|
Cecchino(),
|
||||||
DeadMan(),
|
DeadMan(),
|
||||||
# FratelliDiSangue(),
|
FratelliDiSangue(),
|
||||||
IlGiudice(),
|
IlGiudice(),
|
||||||
Lazo(),
|
Lazo(),
|
||||||
LeggeDelWest(),
|
LeggeDelWest(),
|
||||||
# LiquoreForte(),
|
LiquoreForte(),
|
||||||
# MinieraAbbandonata(),
|
MinieraAbbandonata(),
|
||||||
# PerUnPugnoDiCarte(),
|
Peyote(),
|
||||||
# Peyote(),
|
Ranch(),
|
||||||
# Ranch(),
|
Rimbalzo(),
|
||||||
# Rimbalzo(),
|
RouletteRussa(),
|
||||||
# RouletteRussa(),
|
|
||||||
Vendetta(),
|
Vendetta(),
|
||||||
]
|
]
|
||||||
|
random.shuffle(cards)
|
||||||
|
cards.append(PerUnPugnoDiCarte())
|
||||||
|
for c in cards:
|
||||||
|
c.expansion = 'fistful-of-cards'
|
||||||
|
return cards
|
@ -2,7 +2,7 @@
|
|||||||
from typing import List, Set, Dict, Tuple, Optional
|
from typing import List, Set, Dict, Tuple, Optional
|
||||||
import random
|
import random
|
||||||
import socketio
|
import socketio
|
||||||
import bang.players as players
|
import bang.players as pl
|
||||||
import bang.characters as characters
|
import bang.characters as characters
|
||||||
from bang.deck import Deck
|
from bang.deck import Deck
|
||||||
import bang.roles as roles
|
import bang.roles as roles
|
||||||
@ -14,8 +14,8 @@ class Game:
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.sio = sio
|
self.sio = sio
|
||||||
self.name = name
|
self.name = name
|
||||||
self.players: List[players.Player] = []
|
self.players: List[pl.Player] = []
|
||||||
self.dead_players: List[players.Player] = []
|
self.dead_players: List[pl.Player] = []
|
||||||
self.deck: Deck = None
|
self.deck: Deck = None
|
||||||
self.started = False
|
self.started = False
|
||||||
self.turn = 0
|
self.turn = 0
|
||||||
@ -24,10 +24,13 @@ class Game:
|
|||||||
self.initial_players = 0
|
self.initial_players = 0
|
||||||
self.password = ''
|
self.password = ''
|
||||||
self.expansions = []
|
self.expansions = []
|
||||||
self.available_expansions = ['dodge_city']
|
self.available_expansions = ['dodge_city', 'fistful_of_cards']
|
||||||
self.shutting_down = False
|
self.shutting_down = False
|
||||||
self.is_competitive = False
|
self.is_competitive = False
|
||||||
self.disconnect_bot = True
|
self.disconnect_bot = True
|
||||||
|
self.player_bangs = 0
|
||||||
|
self.is_russian_roulette_on = False
|
||||||
|
self.bot_speed = 1.5
|
||||||
|
|
||||||
def notify_room(self, sid=None):
|
def notify_room(self, sid=None):
|
||||||
if len([p for p in self.players if p.character == None]) != 0 or sid:
|
if len([p for p in self.players if p.character == None]) != 0 or sid:
|
||||||
@ -59,7 +62,7 @@ class Game:
|
|||||||
self.disconnect_bot = not self.disconnect_bot
|
self.disconnect_bot = not self.disconnect_bot
|
||||||
self.notify_room()
|
self.notify_room()
|
||||||
|
|
||||||
def add_player(self, player: players.Player):
|
def add_player(self, player: pl.Player):
|
||||||
if player.is_bot and len(self.players) >= 8:
|
if player.is_bot and len(self.players) >= 8:
|
||||||
return
|
return
|
||||||
if player in self.players or len(self.players) >= 10:
|
if player in self.players or len(self.players) >= 10:
|
||||||
@ -138,9 +141,10 @@ class Game:
|
|||||||
self.sio.emit('chat_message', room=self.name, data=f'_sheriff|{self.players[i].name}')
|
self.sio.emit('chat_message', room=self.name, data=f'_sheriff|{self.players[i].name}')
|
||||||
self.turn = i
|
self.turn = i
|
||||||
self.players[i].notify_self()
|
self.players[i].notify_self()
|
||||||
|
self.notify_event_card()
|
||||||
|
|
||||||
def attack_others(self, attacker: players.Player):
|
def attack_others(self, attacker: pl.Player):
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = pl.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.waiting_for = 0
|
self.waiting_for = 0
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
@ -150,11 +154,11 @@ class Game:
|
|||||||
self.waiting_for += 1
|
self.waiting_for += 1
|
||||||
p.notify_self()
|
p.notify_self()
|
||||||
if self.waiting_for == 0:
|
if self.waiting_for == 0:
|
||||||
attacker.pending_action = players.PendingAction.PLAY
|
attacker.pending_action = pl.PendingAction.PLAY
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
|
|
||||||
def indian_others(self, attacker: players.Player):
|
def indian_others(self, attacker: pl.Player):
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = pl.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.waiting_for = 0
|
self.waiting_for = 0
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
@ -164,60 +168,99 @@ class Game:
|
|||||||
self.waiting_for += 1
|
self.waiting_for += 1
|
||||||
p.notify_self()
|
p.notify_self()
|
||||||
if self.waiting_for == 0:
|
if self.waiting_for == 0:
|
||||||
attacker.pending_action = players.PendingAction.PLAY
|
attacker.pending_action = pl.PendingAction.PLAY
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
|
|
||||||
def attack(self, attacker: players.Player, target_username:str, double:bool=False):
|
def attack(self, attacker: pl.Player, target_username:str, double:bool=False):
|
||||||
if self.get_player_named(target_username).get_banged(attacker=attacker, double=double):
|
if self.get_player_named(target_username).get_banged(attacker=attacker, double=double):
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
self.waiting_for = 1
|
self.waiting_for = 1
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = pl.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.get_player_named(target_username).notify_self()
|
self.get_player_named(target_username).notify_self()
|
||||||
|
|
||||||
def duel(self, attacker: players.Player, target_username:str):
|
def rimbalzo(self, attacker: pl.Player, target_username:str, card_index:int):
|
||||||
|
if self.get_player_named(target_username).get_banged(attacker=attacker, no_dmg=True, card_index=card_index):
|
||||||
|
self.readyCount = 0
|
||||||
|
self.waiting_for = 1
|
||||||
|
attacker.pending_action = pl.PendingAction.WAIT
|
||||||
|
attacker.notify_self()
|
||||||
|
self.get_player_named(target_username).notify_self()
|
||||||
|
|
||||||
|
def duel(self, attacker: pl.Player, target_username:str):
|
||||||
if self.get_player_named(target_username).get_dueled(attacker=attacker):
|
if self.get_player_named(target_username).get_dueled(attacker=attacker):
|
||||||
self.readyCount = 0
|
self.readyCount = 0
|
||||||
self.waiting_for = 1
|
self.waiting_for = 1
|
||||||
attacker.pending_action = players.PendingAction.WAIT
|
attacker.pending_action = pl.PendingAction.WAIT
|
||||||
attacker.notify_self()
|
attacker.notify_self()
|
||||||
self.get_player_named(target_username).notify_self()
|
self.get_player_named(target_username).notify_self()
|
||||||
|
|
||||||
def emporio(self):
|
def emporio(self):
|
||||||
self.available_cards = [self.deck.draw() for i in range(len(self.players))]
|
self.available_cards = [self.deck.draw(True) for i in range(len([p for p in self.players if p.lives > 0]))]
|
||||||
self.players[self.turn].pending_action = players.PendingAction.CHOOSE
|
self.players[self.turn].pending_action = pl.PendingAction.CHOOSE
|
||||||
|
self.players[self.turn].choose_text = 'choose_card_to_get'
|
||||||
self.players[self.turn].available_cards = self.available_cards
|
self.players[self.turn].available_cards = self.available_cards
|
||||||
self.players[self.turn].notify_self()
|
self.players[self.turn].notify_self()
|
||||||
|
|
||||||
def respond_emporio(self, player, i):
|
def respond_emporio(self, player, i):
|
||||||
player.hand.append(self.available_cards.pop(i))
|
player.hand.append(self.available_cards.pop(i))
|
||||||
player.available_cards = []
|
player.available_cards = []
|
||||||
player.pending_action = players.PendingAction.WAIT
|
player.pending_action = pl.PendingAction.WAIT
|
||||||
player.notify_self()
|
player.notify_self()
|
||||||
nextPlayer = self.players[(self.turn + (len(self.players)-len(self.available_cards))) % len(self.players)]
|
nextPlayer = self.players[(self.turn + (len(self.players)-len(self.available_cards))) % len(self.players)]
|
||||||
if nextPlayer == self.players[self.turn]:
|
if nextPlayer == self.players[self.turn]:
|
||||||
self.players[self.turn].pending_action = players.PendingAction.PLAY
|
self.players[self.turn].pending_action = pl.PendingAction.PLAY
|
||||||
self.players[self.turn].notify_self()
|
self.players[self.turn].notify_self()
|
||||||
else:
|
else:
|
||||||
nextPlayer.pending_action = players.PendingAction.CHOOSE
|
nextPlayer.pending_action = pl.PendingAction.CHOOSE
|
||||||
|
self.players[self.turn].choose_text = 'choose_card_to_get'
|
||||||
nextPlayer.available_cards = self.available_cards
|
nextPlayer.available_cards = self.available_cards
|
||||||
nextPlayer.notify_self()
|
nextPlayer.notify_self()
|
||||||
|
|
||||||
def get_player_named(self, name:str):
|
def get_player_named(self, name:str):
|
||||||
return self.players[self.players_map[name]]
|
return self.players[self.players_map[name]]
|
||||||
|
|
||||||
def responders_did_respond_resume_turn(self):
|
def responders_did_respond_resume_turn(self, did_lose=False):
|
||||||
self.readyCount += 1
|
print('did_lose', did_lose)
|
||||||
if self.readyCount == self.waiting_for:
|
if self.player_bangs > 0 and self.check_event(ce.PerUnPugnoDiCarte):
|
||||||
self.waiting_for = 0
|
self.player_bangs -= 1
|
||||||
self.readyCount = 0
|
if self.player_bangs > 1:
|
||||||
self.players[self.turn].pending_action = players.PendingAction.PLAY
|
print('bang again')
|
||||||
self.players[self.turn].notify_self()
|
if self.players[self.turn].get_banged(self.deck.event_cards[0]):
|
||||||
|
self.players[self.turn].notify_self()
|
||||||
|
else:
|
||||||
|
self.responders_did_respond_resume_turn()
|
||||||
|
else:
|
||||||
|
print('ok play turn now')
|
||||||
|
self.player_bangs = 0
|
||||||
|
self.players[self.turn].play_turn()
|
||||||
|
elif self.is_russian_roulette_on and self.check_event(ce.RouletteRussa):
|
||||||
|
if did_lose:
|
||||||
|
print('stop roulette')
|
||||||
|
self.players[(self.turn+self.player_bangs) % len(self.players)].lives -= 1
|
||||||
|
self.players[(self.turn+self.player_bangs) % len(self.players)].notify_self()
|
||||||
|
self.is_russian_roulette_on = False
|
||||||
|
self.players[self.turn].play_turn()
|
||||||
|
else:
|
||||||
|
self.player_bangs += 1
|
||||||
|
print(f'next in line {self.players[(self.turn+self.player_bangs) % len(self.players)].name}')
|
||||||
|
if self.players[(self.turn+self.player_bangs) % len(self.players)].get_banged(self.deck.event_cards[0]):
|
||||||
|
self.players[(self.turn+self.player_bangs) % len(self.players)].notify_self()
|
||||||
|
else:
|
||||||
|
self.responders_did_respond_resume_turn(did_lose=True)
|
||||||
|
else:
|
||||||
|
self.readyCount += 1
|
||||||
|
if self.readyCount == self.waiting_for:
|
||||||
|
self.waiting_for = 0
|
||||||
|
self.readyCount = 0
|
||||||
|
self.players[self.turn].pending_action = pl.PendingAction.PLAY
|
||||||
|
self.players[self.turn].notify_self()
|
||||||
|
|
||||||
def next_player(self):
|
def next_player(self):
|
||||||
return self.players[(self.turn + 1) % len(self.players)]
|
return self.players[(self.turn + 1) % len(self.players)]
|
||||||
|
|
||||||
def play_turn(self):
|
def play_turn(self):
|
||||||
|
self.player_bangs = 0
|
||||||
if isinstance(self.players[self.turn].role, roles.Sheriff):
|
if isinstance(self.players[self.turn].role, roles.Sheriff):
|
||||||
self.deck.flip_event()
|
self.deck.flip_event()
|
||||||
if self.check_event(ce.DeadMan) and len(self.dead_players) > 0:
|
if self.check_event(ce.DeadMan) and len(self.dead_players) > 0:
|
||||||
@ -227,7 +270,21 @@ class Game:
|
|||||||
self.players[-1].hand.append(self.deck.draw())
|
self.players[-1].hand.append(self.deck.draw())
|
||||||
self.players_map = {c.name: i for i, c in enumerate(self.players)}
|
self.players_map = {c.name: i for i, c in enumerate(self.players)}
|
||||||
self.players[-1].notify_self()
|
self.players[-1].notify_self()
|
||||||
self.players[self.turn].play_turn()
|
elif self.check_event(ce.RouletteRussa):
|
||||||
|
self.is_russian_roulette_on = True
|
||||||
|
if self.players[self.turn].get_banged(self.deck.event_cards[0]):
|
||||||
|
self.players[self.turn].notify_self()
|
||||||
|
else:
|
||||||
|
self.responders_did_respond_resume_turn(did_lose=True)
|
||||||
|
return
|
||||||
|
if self.check_event(ce.PerUnPugnoDiCarte) and len(self.players[self.turn].hand) > 0:
|
||||||
|
self.player_bangs = len(self.players[self.turn].hand)
|
||||||
|
if self.players[self.turn].get_banged(self.deck.event_cards[0]):
|
||||||
|
self.players[self.turn].notify_self()
|
||||||
|
else:
|
||||||
|
self.responders_did_respond_resume_turn()
|
||||||
|
else:
|
||||||
|
self.players[self.turn].play_turn()
|
||||||
|
|
||||||
def next_turn(self):
|
def next_turn(self):
|
||||||
if self.shutting_down: return
|
if self.shutting_down: return
|
||||||
@ -237,7 +294,10 @@ class Game:
|
|||||||
|
|
||||||
def notify_event_card(self):
|
def notify_event_card(self):
|
||||||
if len(self.deck.event_cards) > 0:
|
if len(self.deck.event_cards) > 0:
|
||||||
self.sio.emit('event_card', room=self.name, data=self.deck.event_cards[0].__dict__)
|
if self.deck.event_cards[0] != None:
|
||||||
|
self.sio.emit('event_card', room=self.name, data=self.deck.event_cards[0].__dict__)
|
||||||
|
else:
|
||||||
|
self.sio.emit('event_card', room=self.name, data=None)
|
||||||
|
|
||||||
def notify_scrap_pile(self):
|
def notify_scrap_pile(self):
|
||||||
print('scrap')
|
print('scrap')
|
||||||
@ -246,7 +306,7 @@ class Game:
|
|||||||
else:
|
else:
|
||||||
self.sio.emit('scrap', room=self.name, data=None)
|
self.sio.emit('scrap', room=self.name, data=None)
|
||||||
|
|
||||||
def handle_disconnect(self, player: players.Player):
|
def handle_disconnect(self, player: pl.Player):
|
||||||
print(f'player {player.name} left the game {self.name}')
|
print(f'player {player.name} left the game {self.name}')
|
||||||
if player in self.players:
|
if player in self.players:
|
||||||
if self.disconnect_bot and self.started:
|
if self.disconnect_bot and self.started:
|
||||||
@ -266,24 +326,25 @@ class Game:
|
|||||||
return True
|
return True
|
||||||
else: return False
|
else: return False
|
||||||
|
|
||||||
def player_death(self, player: players.Player, disconnected=False):
|
def player_death(self, player: pl.Player, disconnected=False):
|
||||||
if not player in self.players: return
|
if not player in self.players: return
|
||||||
import bang.expansions.dodge_city.characters as chd
|
import bang.expansions.dodge_city.characters as chd
|
||||||
print(player.attacker)
|
print(player.attacker)
|
||||||
if player.attacker and isinstance(player.attacker.role, roles.Sheriff) and isinstance(player.role, roles.Vice):
|
if player.attacker and player.attacker in self.players and isinstance(player.attacker.role, roles.Sheriff) and isinstance(player.role, roles.Vice):
|
||||||
for i in range(len(player.attacker.hand)):
|
for i in range(len(player.attacker.hand)):
|
||||||
self.deck.scrap(player.attacker.hand.pop())
|
self.deck.scrap(player.attacker.hand.pop(), True)
|
||||||
for i in range(len(player.attacker.equipment)):
|
for i in range(len(player.attacker.equipment)):
|
||||||
self.deck.scrap(player.attacker.equipment.pop())
|
self.deck.scrap(player.attacker.equipment.pop(), True)
|
||||||
player.attacker.notify_self()
|
player.attacker.notify_self()
|
||||||
elif player.attacker and (isinstance(player.role, roles.Outlaw) or self.initial_players == 3):
|
elif player.attacker and player.attacker in self.players and (isinstance(player.role, roles.Outlaw) or self.initial_players == 3):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
player.attacker.hand.append(self.deck.draw())
|
player.attacker.hand.append(self.deck.draw(True))
|
||||||
player.attacker.notify_self()
|
player.attacker.notify_self()
|
||||||
print(f'player {player.name} died')
|
print(f'player {player.name} died')
|
||||||
if (self.waiting_for > 0):
|
if (self.waiting_for > 0):
|
||||||
self.responders_did_respond_resume_turn()
|
self.responders_did_respond_resume_turn()
|
||||||
|
|
||||||
|
if not player in self.players: return
|
||||||
index = self.players.index(player)
|
index = self.players.index(player)
|
||||||
died_in_his_turn = self.started and index == self.turn
|
died_in_his_turn = self.started and index == self.turn
|
||||||
if self.started and index <= self.turn:
|
if self.started and index <= self.turn:
|
||||||
@ -303,7 +364,7 @@ class Game:
|
|||||||
if self.started:
|
if self.started:
|
||||||
print('Check win status')
|
print('Check win status')
|
||||||
attacker_role = None
|
attacker_role = None
|
||||||
if player.attacker:
|
if player.attacker and player.attacker in self.players:
|
||||||
attacker_role = player.attacker.role
|
attacker_role = player.attacker.role
|
||||||
winners = [p for p in self.players if p.role != None and p.role.on_player_death(self.players, initial_players=self.initial_players, dead_role=player.role, attacker_role=attacker_role)]
|
winners = [p for p in self.players if p.role != None and p.role.on_player_death(self.players, initial_players=self.initial_players, dead_role=player.role, attacker_role=attacker_role)]
|
||||||
if len(winners) > 0:
|
if len(winners) > 0:
|
||||||
@ -318,22 +379,36 @@ class Game:
|
|||||||
vulture = [p for p in self.players if isinstance(p.character, characters.VultureSam)]
|
vulture = [p for p in self.players if isinstance(p.character, characters.VultureSam)]
|
||||||
if len(vulture) == 0:
|
if len(vulture) == 0:
|
||||||
for i in range(len(player.hand)):
|
for i in range(len(player.hand)):
|
||||||
self.deck.scrap(player.hand.pop())
|
self.deck.scrap(player.hand.pop(), True)
|
||||||
for i in range(len(player.equipment)):
|
for i in range(len(player.equipment)):
|
||||||
self.deck.scrap(player.equipment.pop())
|
self.deck.scrap(player.equipment.pop(), True)
|
||||||
|
elif len(vulture) == 2:
|
||||||
|
for i in range(len(player.hand)):
|
||||||
|
vulture[i%2].hand.append(player.hand.pop())
|
||||||
|
for i in range(len(player.equipment)):
|
||||||
|
vulture[i%2].hand.append(player.equipment.pop())
|
||||||
|
vulture[0].notify_self()
|
||||||
|
vulture[1].notify_self()
|
||||||
else:
|
else:
|
||||||
for i in range(len(player.hand)):
|
for i in range(len(player.hand)):
|
||||||
vulture[0].hand.append(player.hand.pop())
|
vulture[0].hand.append(player.hand.pop())
|
||||||
for i in range(len(player.equipment)):
|
for i in range(len(player.equipment)):
|
||||||
vulture[0].hand.append(player.equipment.pop())
|
vulture[0].hand.append(player.equipment.pop())
|
||||||
vulture[0].notify_self()
|
vulture[0].notify_self()
|
||||||
|
|
||||||
|
#se Vulture Sam è uno sceriffo e ha appena ucciso il suo Vice, deve scartare le carte che ha pescato con la sua abilità
|
||||||
|
if player.attacker and player.attacker in self.players and isinstance(player.attacker.role, roles.Sheriff) and isinstance(player.role, roles.Vice):
|
||||||
|
for i in range(len(player.attacker.hand)):
|
||||||
|
self.deck.scrap(player.attacker.hand.pop(), True)
|
||||||
|
player.attacker.notify_self()
|
||||||
|
|
||||||
greg = [p for p in self.players if isinstance(p.character, chd.GregDigger)]
|
greg = [p for p in self.players if isinstance(p.character, chd.GregDigger)]
|
||||||
if len(greg) > 0:
|
if len(greg) > 0:
|
||||||
greg[0].lives = min(greg[0].lives+2, greg[0].max_lives)
|
greg[0].lives = min(greg[0].lives+2, greg[0].max_lives)
|
||||||
herb = [p for p in self.players if isinstance(p.character, chd.HerbHunter)]
|
herb = [p for p in self.players if isinstance(p.character, chd.HerbHunter)]
|
||||||
if len(herb) > 0:
|
if len(herb) > 0:
|
||||||
herb[0].hand.append(self.deck.draw())
|
herb[0].hand.append(self.deck.draw(True))
|
||||||
herb[0].hand.append(self.deck.draw())
|
herb[0].hand.append(self.deck.draw(True))
|
||||||
herb[0].notify_self()
|
herb[0].notify_self()
|
||||||
|
|
||||||
if died_in_his_turn:
|
if died_in_his_turn:
|
||||||
@ -357,7 +432,7 @@ class Game:
|
|||||||
if len(self.deck.event_cards) == 0: return False
|
if len(self.deck.event_cards) == 0: return False
|
||||||
return isinstance(self.deck.event_cards[0], ev)
|
return isinstance(self.deck.event_cards[0], ev)
|
||||||
|
|
||||||
def get_visible_players(self, player: players.Player):
|
def get_visible_players(self, player: pl.Player):
|
||||||
i = self.players.index(player)
|
i = self.players.index(player)
|
||||||
sight = player.get_sight()
|
sight = player.get_sight()
|
||||||
mindist = 99 if not self.check_event(ce.Agguato) else 1
|
mindist = 99 if not self.check_event(ce.Agguato) else 1
|
||||||
@ -367,6 +442,7 @@ class Game:
|
|||||||
'lives': self.players[j].lives,
|
'lives': self.players[j].lives,
|
||||||
'max_lives': self.players[j].max_lives,
|
'max_lives': self.players[j].max_lives,
|
||||||
'is_sheriff': isinstance(self.players[j].role, roles.Sheriff),
|
'is_sheriff': isinstance(self.players[j].role, roles.Sheriff),
|
||||||
|
'cards': len(self.players[j].hand)+len(self.players[j].equipment)
|
||||||
} for j in range(len(self.players)) if i != j]
|
} for j in range(len(self.players)) if i != j]
|
||||||
|
|
||||||
def notify_all(self):
|
def notify_all(self):
|
||||||
|
@ -48,6 +48,13 @@ class Player:
|
|||||||
self.attacker: Player = None
|
self.attacker: Player = None
|
||||||
self.target_p: str = None
|
self.target_p: str = None
|
||||||
self.is_drawing = False
|
self.is_drawing = False
|
||||||
|
self.can_play_vendetta = True
|
||||||
|
self.is_giving_life = False
|
||||||
|
self.is_using_checchino = False
|
||||||
|
self.choose_text = 'choose_card_to_get'
|
||||||
|
self.using_rimbalzo = 0 # 0 no, 1 scegli giocatore, 2 scegli carta
|
||||||
|
self.can_play_ranch = True
|
||||||
|
self.is_playing_ranch = False
|
||||||
self.mancato_needed = 0
|
self.mancato_needed = 0
|
||||||
self.molly_discarded_cards = 0
|
self.molly_discarded_cards = 0
|
||||||
self.is_bot = bot
|
self.is_bot = bot
|
||||||
@ -59,11 +66,14 @@ class Player:
|
|||||||
self.role: r.Role = None
|
self.role: r.Role = None
|
||||||
self.character: chars.Character = None
|
self.character: chars.Character = None
|
||||||
self.real_character: chars.Character = None
|
self.real_character: chars.Character = None
|
||||||
|
self.is_using_checchino = False
|
||||||
self.lives = 0
|
self.lives = 0
|
||||||
self.max_lives = 0
|
self.max_lives = 0
|
||||||
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
|
||||||
|
self.can_play_ranch = True
|
||||||
|
self.is_playing_ranch = False
|
||||||
self.pending_action: PendingAction = None
|
self.pending_action: PendingAction = None
|
||||||
self.available_characters = []
|
self.available_characters = []
|
||||||
self.was_shot = False
|
self.was_shot = False
|
||||||
@ -146,13 +156,34 @@ 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, chars.CalamityJanet):
|
if self.pending_action == PendingAction.DRAW and self.game.check_event(ce.Peyote):
|
||||||
if cs.Mancato(0, 0).name not in self.expected_response:
|
self.available_cards = [{
|
||||||
self.expected_response.append(cs.Mancato(0, 0).name)
|
'icon': '🔴'
|
||||||
elif cs.Bang(0, 0).name not in self.expected_response:
|
},{
|
||||||
self.expected_response.append(cs.Bang(0, 0).name)
|
'icon': '⚫'
|
||||||
elif isinstance(self.character, chars.SuzyLafayette) and len(self.hand) == 0:
|
}]
|
||||||
self.hand.append(self.game.deck.draw())
|
self.is_drawing = True
|
||||||
|
self.choose_text = 'choose_guess'
|
||||||
|
self.pending_action = PendingAction.CHOOSE
|
||||||
|
elif self.can_play_ranch and self.pending_action == PendingAction.PLAY and self.game.check_event(ce.Ranch):
|
||||||
|
self.can_play_ranch = False
|
||||||
|
self.available_cards = [c for c in self.hand]
|
||||||
|
self.discarded_cards = []
|
||||||
|
self.available_cards.append({'icon': '✅'})
|
||||||
|
self.is_playing_ranch = True
|
||||||
|
self.choose_text = 'choose_ranch'
|
||||||
|
self.pending_action = PendingAction.CHOOSE
|
||||||
|
elif isinstance(self.character, chars.SuzyLafayette) and len(self.hand) == 0 and ( not self.is_my_turn or self.pending_action == PendingAction.PLAY):
|
||||||
|
self.hand.append(self.game.deck.draw(True))
|
||||||
|
if self.lives <= 0 and self.max_lives > 0:
|
||||||
|
print('dying, attacker', self.attacker)
|
||||||
|
if isinstance(self.character, chars.SidKetchum) and len(self.hand) > 1:
|
||||||
|
self.lives += 1
|
||||||
|
#TODO Sid dovrebbe poter decidere cosa scartare
|
||||||
|
self.game.deck.scrap(self.hand.pop(
|
||||||
|
randrange(0, len(self.hand))), True)
|
||||||
|
self.game.deck.scrap(self.hand.pop(
|
||||||
|
randrange(0, len(self.hand))), True)
|
||||||
ser = self.__dict__.copy()
|
ser = self.__dict__.copy()
|
||||||
ser.pop('game')
|
ser.pop('game')
|
||||||
ser.pop('sio')
|
ser.pop('sio')
|
||||||
@ -166,14 +197,6 @@ class Player:
|
|||||||
ser['sight'] = self.get_sight()
|
ser['sight'] = self.get_sight()
|
||||||
ser['lives'] = max(ser['lives'], 0)
|
ser['lives'] = max(ser['lives'], 0)
|
||||||
|
|
||||||
if self.lives <= 0 and self.max_lives > 0:
|
|
||||||
print('dying, attacker', self.attacker)
|
|
||||||
if isinstance(self.character, chars.SidKetchum) and len(self.hand) > 1:
|
|
||||||
self.lives += 1
|
|
||||||
self.game.deck.scrap(self.hand.pop(
|
|
||||||
randrange(0, len(self.hand))))
|
|
||||||
self.game.deck.scrap(self.hand.pop(
|
|
||||||
randrange(0, len(self.hand))))
|
|
||||||
if self.lives <= 0 and self.max_lives > 0:
|
if self.lives <= 0 and self.max_lives > 0:
|
||||||
self.pending_action = PendingAction.WAIT
|
self.pending_action = PendingAction.WAIT
|
||||||
ser['hand'] = []
|
ser['hand'] = []
|
||||||
@ -196,7 +219,7 @@ class Player:
|
|||||||
def bot_logic(self):
|
def bot_logic(self):
|
||||||
if self.game.shutting_down: return
|
if self.game.shutting_down: return
|
||||||
if self.pending_action != None and self.pending_action != PendingAction.WAIT:
|
if self.pending_action != None and self.pending_action != PendingAction.WAIT:
|
||||||
eventlet.sleep(uniform(0.6, 1.5))
|
eventlet.sleep(uniform(self.game.bot_speed/2-0.1, self.game.bot_speed))
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
if self.pending_action == PendingAction.PICK:
|
if self.pending_action == PendingAction.PICK:
|
||||||
@ -204,45 +227,39 @@ class Player:
|
|||||||
elif self.pending_action == PendingAction.DRAW:
|
elif self.pending_action == PendingAction.DRAW:
|
||||||
self.draw('')
|
self.draw('')
|
||||||
elif self.pending_action == PendingAction.PLAY:
|
elif self.pending_action == PendingAction.PLAY:
|
||||||
has_played = False
|
equippables = [c for c in self.hand if (c.is_equipment or c.usable_next_turn) and not isinstance(c, cs.Prigione) and not any([type(c) == type(x) for x in self.equipment])]
|
||||||
if len([c for c in self.hand if (c.is_equipment or c.usable_next_turn) and not self.game.check_event(ce.IlGiudice)]) > 0:
|
misc = [c for c in self.hand if (isinstance(c, cs.WellsFargo) and not c.usable_next_turn) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or (isinstance(c, cs.Birra) and self.lives < self.max_lives)]
|
||||||
for i in range(len(self.hand)):
|
need_target = [c for c in self.hand if c.need_target and c.can_be_used_now and not (c.need_with and len(self.hand) < 2) and not (self.has_played_bang and not (any([isinstance(c, cs.Volcanic) for c in self.equipment]) and not self.game.check_event(ce.Lazo))) and not ( isinstance(c, cs.Prigione) and self.game.check_event(ce.IlGiudice))]
|
||||||
if self.hand[i].is_equipment or self.hand[i].usable_next_turn:
|
green_cards = [c for c in self.equipment if not self.game.check_event(ce.Lazo) and not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now]
|
||||||
self.play_card(i)
|
if len(equippables) > 0 and not self.game.check_event(ce.IlGiudice):
|
||||||
has_played = True
|
for c in equippables:
|
||||||
break
|
if self.play_card(self.hand.index(c)):
|
||||||
elif any([isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or isinstance(c, cs.Birra) for c in self.hand]):
|
return
|
||||||
for i in range(len(self.hand)):
|
elif len(misc) > 0:
|
||||||
c = self.hand[i]
|
for c in misc:
|
||||||
if isinstance(c, cs.WellsFargo) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or (isinstance(c, cs.Birra) and self.lives < self.max_lives):
|
if self.play_card(self.hand.index(c)):
|
||||||
self.play_card(i)
|
return
|
||||||
has_played = True
|
elif len(need_target) > 0:
|
||||||
break
|
for c in need_target:
|
||||||
elif len([c for c in self.hand if c.need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment]))]) > 0:
|
_range = self.get_sight() if c.name == 'Bang!' or c.name == "Pepperbox" else c.range
|
||||||
for i in range(len(self.hand)):
|
others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff']) and p['lives'] > 0 and not ((isinstance(c, cs.CatBalou) or isinstance(c, cs.Panico)) and p['cards'] == 0) and not (p['is_sheriff'] and isinstance(c, cs.Prigione))]
|
||||||
if self.hand[i].need_target and not (self.has_played_bang and not any([isinstance(c, cs.Volcanic) for c in self.equipment])):
|
if len(others) == 0:
|
||||||
if self.hand[i].need_with and len(self.hand) < 2:
|
continue
|
||||||
continue
|
target = others[randrange(0, len(others))]
|
||||||
_range = self.get_sight() if self.hand[i].name == 'Bang!' or self.hand[i].name == "Pepperbox" else self.hand[i].range
|
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
|
||||||
others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])]
|
|
||||||
if len(others) == 0:
|
|
||||||
continue
|
|
||||||
target = others[randrange(0, len(others))]
|
target = others[randrange(0, len(others))]
|
||||||
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
|
if not c.need_with:
|
||||||
target = others[randrange(0, len(others))]
|
if self.play_card(self.hand.index(c), against=target['name']):
|
||||||
if not self.hand[i].need_with:
|
return
|
||||||
self.play_card(i, against=target['name'])
|
else:
|
||||||
else:
|
if self.play_card(self.hand.index(c), against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != self.hand.index(c)], 1)[0]):
|
||||||
self.play_card(i, against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != i], 1)[0])
|
return
|
||||||
has_played = True
|
elif len(green_cards) > 0:
|
||||||
break
|
for c in green_cards:
|
||||||
elif any([not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now for c in self.equipment]):
|
|
||||||
print('hmm', [not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now for c in self.equipment])
|
|
||||||
for i in range(len(self.equipment)):
|
|
||||||
c = self.equipment[i]
|
|
||||||
if not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now:
|
if not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now:
|
||||||
if not c.need_target:
|
if not c.need_target:
|
||||||
self.play_card(len(self.hand)+i)
|
if self.play_card(len(self.hand)+self.equipment.index(c)):
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
_range = self.get_sight() if c.name == "Pepperbox" else c.range
|
_range = self.get_sight() if c.name == "Pepperbox" else c.range
|
||||||
others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])]
|
others = [p for p in self.game.get_visible_players(self) if _range >= p['dist'] and not (isinstance(self.role, r.Vice) and p['is_sheriff'])]
|
||||||
@ -251,18 +268,18 @@ class Player:
|
|||||||
target = others[randrange(0, len(others))]
|
target = others[randrange(0, len(others))]
|
||||||
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
|
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
|
||||||
target = others[randrange(0, len(others))]
|
target = others[randrange(0, len(others))]
|
||||||
self.play_card(len(self.hand)+i, against=target['name'])
|
if self.play_card(len(self.hand)+self.equipment.index(c), against=target['name']):
|
||||||
has_played = True
|
return
|
||||||
break
|
break
|
||||||
maxcards = self.lives if not isinstance(self.character, chd.SeanMallory) else 10
|
maxcards = self.lives if not isinstance(self.character, chd.SeanMallory) else 10
|
||||||
if not has_played and len(self.hand) > maxcards:
|
if len(self.hand) > maxcards:
|
||||||
self.scrap(0)
|
self.scrap(0)
|
||||||
else:
|
else:
|
||||||
self.end_turn()
|
self.end_turn()
|
||||||
elif self.pending_action == PendingAction.RESPOND:
|
elif self.pending_action == PendingAction.RESPOND:
|
||||||
did_respond = False
|
did_respond = False
|
||||||
for i in range(len(self.hand)):
|
for i in range(len(self.hand)):
|
||||||
if self.hand[i].name in self.expected_response:
|
if self.hand[i].can_be_used_now and self.hand[i].name in self.expected_response:
|
||||||
self.respond(i)
|
self.respond(i)
|
||||||
did_respond = True
|
did_respond = True
|
||||||
break
|
break
|
||||||
@ -284,10 +301,13 @@ class Player:
|
|||||||
else:
|
else:
|
||||||
self.choose(randrange(0, len(target.hand)+len(target.equipment)))
|
self.choose(randrange(0, len(target.hand)+len(target.equipment)))
|
||||||
|
|
||||||
def play_turn(self):
|
def play_turn(self, can_play_vendetta = True):
|
||||||
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.can_play_ranch = True
|
||||||
|
self.is_playing_ranch = False
|
||||||
|
self.can_play_vendetta = can_play_vendetta
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
data=f'_turn|{self.name}')
|
data=f'_turn|{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')
|
||||||
@ -296,9 +316,21 @@ class Player:
|
|||||||
self.is_waiting_for_action = True
|
self.is_waiting_for_action = True
|
||||||
self.has_played_bang = False
|
self.has_played_bang = False
|
||||||
self.special_use_count = 0
|
self.special_use_count = 0
|
||||||
if not self.game.check_event(ce.Lazo) and any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]):
|
if self.game.check_event(ce.FratelliDiSangue) and self.lives > 1 and not self.is_giving_life and len([p for p in self.game.players if p != self and p.lives < p.max_lives]):
|
||||||
|
self.available_cards = [{
|
||||||
|
'name': p.name,
|
||||||
|
'icon': '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
||||||
|
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives))
|
||||||
|
} for p in self.game.players if p != self and p.lives < p.max_lives]
|
||||||
|
self.available_cards.append({'icon': '❌'})
|
||||||
|
self.choose_text = 'choose_fratelli_di_sangue'
|
||||||
|
self.pending_action = PendingAction.CHOOSE
|
||||||
|
self.is_giving_life = True
|
||||||
|
elif not self.game.check_event(ce.Lazo) and any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]):
|
||||||
|
self.is_giving_life = False
|
||||||
self.pending_action = PendingAction.PICK
|
self.pending_action = PendingAction.PICK
|
||||||
else:
|
else:
|
||||||
|
self.is_giving_life = False
|
||||||
if isinstance(self.real_character, chd.VeraCuster):
|
if isinstance(self.real_character, chd.VeraCuster):
|
||||||
self.set_available_character([p.character for p in self.game.players if p != self])
|
self.set_available_character([p.character for p in self.game.players if p != self])
|
||||||
else:
|
else:
|
||||||
@ -306,16 +338,43 @@ class Player:
|
|||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
|
||||||
def draw(self, pile):
|
def draw(self, pile):
|
||||||
|
if self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Cecchino) and len([c for c in self.hand if c.name == cs.Bang(0,0).name]) >= 2:
|
||||||
|
self.is_using_checchino = True
|
||||||
|
self.available_cards = [{
|
||||||
|
'name': p['name'],
|
||||||
|
'icon': '⭐️' if p['is_sheriff'] else '🤠',
|
||||||
|
'alt_text': ''.join(['❤️']*p['lives'])+''.join(['💀']*(p['max_lives']-p['lives']))
|
||||||
|
} for p in self.game.get_visible_players(self) if p['dist'] <= self.get_sight()]
|
||||||
|
self.available_cards.append({'icon': '❌'})
|
||||||
|
self.choose_text = 'choose_cecchino'
|
||||||
|
self.pending_action = PendingAction.CHOOSE
|
||||||
|
self.notify_self()
|
||||||
|
elif self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Rimbalzo) and len([c for c in self.hand if c.name == cs.Bang(0,0).name]) > 0:
|
||||||
|
self.available_cards = [{
|
||||||
|
'name': p.name,
|
||||||
|
'icon': '⭐️' if isinstance(p.role, r.Sheriff) else '🤠'
|
||||||
|
} for p in self.game.players if len(p.equipment) > 0 and p != self]
|
||||||
|
self.available_cards.append({'icon': '❌'})
|
||||||
|
self.choose_text = 'choose_rimbalzo_player'
|
||||||
|
self.pending_action = PendingAction.CHOOSE
|
||||||
|
self.using_rimbalzo = 1
|
||||||
|
self.notify_self()
|
||||||
if self.pending_action != PendingAction.DRAW:
|
if self.pending_action != PendingAction.DRAW:
|
||||||
return
|
return
|
||||||
if isinstance(self.character, chars.KitCarlson):
|
if pile == 'event' and self.lives < self.max_lives and self.game.check_event(ce.LiquoreForte):
|
||||||
|
self.lives += 1
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.notify_self()
|
||||||
|
elif 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.choose_text = 'choose_card_to_get'
|
||||||
self.pending_action = PendingAction.CHOOSE
|
self.pending_action = PendingAction.CHOOSE
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
elif isinstance(self.character, chd.PatBrennan) and type(pile) == str and pile != self.name and pile in self.game.players_map and len(self.game.get_player_named(pile).equipment) > 0:
|
elif isinstance(self.character, chd.PatBrennan) and type(pile) == str and pile != self.name and pile in self.game.players_map and len(self.game.get_player_named(pile).equipment) > 0:
|
||||||
self.is_drawing = True
|
self.is_drawing = True
|
||||||
self.available_cards = self.game.get_player_named(pile).equipment
|
self.available_cards = self.game.get_player_named(pile).equipment
|
||||||
|
self.choose_text = 'choose_card_to_get'
|
||||||
self.pending_action = PendingAction.CHOOSE
|
self.pending_action = PendingAction.CHOOSE
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
else:
|
else:
|
||||||
@ -356,7 +415,7 @@ 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], cs.Dinamite):
|
if i < len(self.equipment) and isinstance(self.equipment[i], cs.Dinamite):
|
||||||
while pickable_cards > 0:
|
while pickable_cards > 0:
|
||||||
pickable_cards -= 1
|
pickable_cards -= 1
|
||||||
picked: cs.Card = self.game.deck.pick_and_scrap()
|
picked: cs.Card = self.game.deck.pick_and_scrap()
|
||||||
@ -365,14 +424,13 @@ class Player:
|
|||||||
data=f'_flipped|{self.name}|{picked}')
|
data=f'_flipped|{self.name}|{picked}')
|
||||||
if picked.suit == cs.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0:
|
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), True)
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name, data=f'_explode|{self.name}')
|
||||||
data=f'_explode|{self.name}')
|
self.heal_if_needed()
|
||||||
if isinstance(self.character, chars.BartCassidy) and self.lives > 0:
|
if isinstance(self.character, chars.BartCassidy) and self.lives > 0:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}')
|
||||||
data=f'_special_bart_cassidy|{self.name}')
|
|
||||||
print(f'{self.name} Boom, -3 hp')
|
print(f'{self.name} Boom, -3 hp')
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@ -391,11 +449,11 @@ class Player:
|
|||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
data=f'_flipped|{self.name}|{picked}')
|
data=f'_flipped|{self.name}|{picked}')
|
||||||
if picked.suit != cs.Suit.HEARTS and pickable_cards == 0:
|
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), True)
|
||||||
self.end_turn(forced=True)
|
self.end_turn(forced=True)
|
||||||
return
|
return
|
||||||
elif pickable_cards == 0:
|
elif pickable_cards == 0:
|
||||||
self.game.deck.scrap(self.equipment.pop(i))
|
self.game.deck.scrap(self.equipment.pop(i), True)
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
if any([isinstance(c, cs.Prigione) for c in self.equipment]):
|
if any([isinstance(c, cs.Prigione) for c in self.equipment]):
|
||||||
@ -440,20 +498,31 @@ class Player:
|
|||||||
did_play_card = False
|
did_play_card = False
|
||||||
event_blocks_card = (self.game.check_event(ce.IlGiudice) and (card.is_equipment or (card.usable_next_turn and not card.can_be_used_now))) or (self.game.check_event(ce.Lazo) and card.usable_next_turn and card.can_be_used_now)
|
event_blocks_card = (self.game.check_event(ce.IlGiudice) and (card.is_equipment or (card.usable_next_turn and not card.can_be_used_now))) or (self.game.check_event(ce.Lazo) and card.usable_next_turn and card.can_be_used_now)
|
||||||
if not(against != None and isinstance(self.game.get_player_named(against).character, chd.ApacheKid) and card.suit == cs.Suit.DIAMONDS) and not event_blocks_card:
|
if not(against != None and isinstance(self.game.get_player_named(against).character, chd.ApacheKid) and card.suit == cs.Suit.DIAMONDS) and not event_blocks_card:
|
||||||
did_play_card = card.play_card(self, against, withCard)
|
if against == self.name and not isinstance(card, csd.Tequila):
|
||||||
|
did_play_card = False
|
||||||
|
else:
|
||||||
|
did_play_card = card.play_card(self, against, withCard)
|
||||||
if not card.is_equipment and not card.usable_next_turn or event_blocks_card:
|
if not card.is_equipment and not card.usable_next_turn or event_blocks_card:
|
||||||
if did_play_card:
|
if did_play_card:
|
||||||
self.game.deck.scrap(card)
|
self.game.deck.scrap(card, True)
|
||||||
else:
|
else:
|
||||||
self.hand.insert(hand_index, card)
|
self.hand.insert(hand_index, card)
|
||||||
if withCard:
|
if withCard:
|
||||||
self.hand.insert(_with, withCard)
|
self.hand.insert(_with, withCard)
|
||||||
elif card.usable_next_turn and card.can_be_used_now:
|
elif card.usable_next_turn and card.can_be_used_now:
|
||||||
if did_play_card:
|
if did_play_card:
|
||||||
self.game.deck.scrap(card)
|
self.game.deck.scrap(card, True)
|
||||||
else:
|
else:
|
||||||
self.equipment.insert(hand_index-len(self.hand), card)
|
self.equipment.insert(hand_index-len(self.hand), card)
|
||||||
|
elif card.is_equipment or (card.usable_next_turn and not card.can_be_used_now):
|
||||||
|
if not did_play_card:
|
||||||
|
self.hand.insert(hand_index, card)
|
||||||
|
else:
|
||||||
|
did_play_card = True
|
||||||
|
print("did play card:", did_play_card)
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
if self.is_bot:
|
||||||
|
return did_play_card or card.is_equipment or (card.usable_next_turn and not card.can_be_used_now)
|
||||||
|
|
||||||
def choose(self, card_index):
|
def choose(self, card_index):
|
||||||
if self.pending_action != PendingAction.CHOOSE:
|
if self.pending_action != PendingAction.CHOOSE:
|
||||||
@ -471,7 +540,7 @@ class Player:
|
|||||||
card.can_be_used_now = False
|
card.can_be_used_now = False
|
||||||
self.hand.append(card)
|
self.hand.append(card)
|
||||||
else:
|
else:
|
||||||
self.game.deck.scrap(card)
|
self.game.deck.scrap(card, True)
|
||||||
if self.event_type != 'rissa' or (self.event_type == 'rissa' and self.target_p == [p.name for p in self.game.players if p != self and (len(p.hand)+len(p.equipment)) > 0][-1]):
|
if self.event_type != 'rissa' or (self.event_type == 'rissa' and self.target_p == [p.name for p in self.game.players if p != self and (len(p.hand)+len(p.equipment)) > 0][-1]):
|
||||||
self.event_type = ''
|
self.event_type = ''
|
||||||
self.target_p = ''
|
self.target_p = ''
|
||||||
@ -482,6 +551,73 @@ class Player:
|
|||||||
while self.target_p == self.name or len(self.game.players[self.game.players_map[self.target_p]].hand) + len(self.game.players[self.game.players_map[self.target_p]].equipment) == 0:
|
while self.target_p == self.name or len(self.game.players[self.game.players_map[self.target_p]].hand) + len(self.game.players[self.game.players_map[self.target_p]].equipment) == 0:
|
||||||
self.target_p = self.game.players[self.game.players_map[self.target_p]+1].name
|
self.target_p = self.game.players[self.game.players_map[self.target_p]+1].name
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
elif self.is_giving_life and self.game.check_event(ce.FratelliDiSangue):
|
||||||
|
try:
|
||||||
|
player = self.game.get_player_named(self.available_cards[card_index]['name'])
|
||||||
|
player.lives += 1
|
||||||
|
self.lives -= 1
|
||||||
|
player.notify_self()
|
||||||
|
self.sio.emit('chat_message', room=self.game.name, data=f'_fratelli_sangue|{self.name}|{player.name}')
|
||||||
|
except: pass
|
||||||
|
self.play_turn()
|
||||||
|
elif self.is_using_checchino and self.game.check_event(ce.Cecchino):
|
||||||
|
try:
|
||||||
|
if self.available_cards[card_index]['name'] != '':
|
||||||
|
for _ in range(2):
|
||||||
|
card = next(c for c in self.hand if c.name == cs.Bang(0,0).name)
|
||||||
|
self.hand.remove(card)
|
||||||
|
self.game.deck.scrap(card, True)
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.game.attack(self, self.available_cards[card_index]['name'], double=True)
|
||||||
|
except:
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.is_using_checchino = False
|
||||||
|
self.notify_self()
|
||||||
|
elif self.using_rimbalzo > 0 and self.game.check_event(ce.Rimbalzo):
|
||||||
|
if self.using_rimbalzo == 1 and 'name' in self.available_cards[card_index]:
|
||||||
|
self.rimbalzo_p = self.available_cards[card_index]['name']
|
||||||
|
self.available_cards = self.game.get_player_named(self.available_cards[card_index]['name']).equipment
|
||||||
|
self.choose_text = 'choose_rimbalzo_card'
|
||||||
|
self.using_rimbalzo = 2
|
||||||
|
elif self.using_rimbalzo == 2 and 'name' in self.available_cards[card_index].__dict__:
|
||||||
|
card = next(c for c in self.hand if c.name == cs.Bang(0,0).name)
|
||||||
|
self.hand.remove(card)
|
||||||
|
self.game.deck.scrap(card, True)
|
||||||
|
self.using_rimbalzo = 0
|
||||||
|
self.available_cards = []
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.game.rimbalzo(self, self.rimbalzo_p, card_index)
|
||||||
|
else:
|
||||||
|
self.using_rimbalzo = 0
|
||||||
|
self.rimbalzo_p = ''
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.notify_self()
|
||||||
|
elif self.is_playing_ranch and self.game.check_event(ce.Ranch):
|
||||||
|
if card_index == len(self.available_cards) - 1:
|
||||||
|
self.hand = [c for c in self.hand if c not in self.discarded_cards]
|
||||||
|
for i in range(len(self.discarded_cards)):
|
||||||
|
self.game.deck.scrap(self.discarded_cards[i], True)
|
||||||
|
self.hand.append(self.game.deck.draw())
|
||||||
|
self.discarded_cards = []
|
||||||
|
self.is_playing_ranch = False
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
else:
|
||||||
|
self.discarded_cards.append(self.available_cards.pop(card_index))
|
||||||
|
self.notify_self()
|
||||||
|
elif self.is_drawing and self.game.check_event(ce.Peyote):
|
||||||
|
self.is_drawing = False
|
||||||
|
card = self.game.deck.draw()
|
||||||
|
self.sio.emit('chat_message', room=self.game.name, data=f"_guess|{self.name}|{self.available_cards[card_index]['icon']}")
|
||||||
|
self.available_cards = []
|
||||||
|
if card_index == card.suit%2:
|
||||||
|
self.hand.append(card)
|
||||||
|
self.sio.emit('chat_message', room=self.game.name, data=f"_guess_right|{self.name}")
|
||||||
|
self.pending_action = PendingAction.DRAW
|
||||||
|
else:
|
||||||
|
self.game.deck.scrap(card)
|
||||||
|
self.sio.emit('chat_message', room=self.game.name, data=f"_guess_wrong|{self.name}")
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.notify_self()
|
||||||
# specifico per personaggio
|
# specifico per personaggio
|
||||||
elif self.is_drawing and isinstance(self.character, chars.KitCarlson):
|
elif self.is_drawing and isinstance(self.character, chars.KitCarlson):
|
||||||
self.hand.append(self.available_cards.pop(card_index))
|
self.hand.append(self.available_cards.pop(card_index))
|
||||||
@ -515,23 +651,59 @@ class Player:
|
|||||||
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(did_lose=False)
|
||||||
return
|
return
|
||||||
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
||||||
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
||||||
self.take_damage_response()
|
self.take_damage_response()
|
||||||
self.game.responders_did_respond_resume_turn()
|
self.game.responders_did_respond_resume_turn(did_lose=True)
|
||||||
else:
|
else:
|
||||||
self.pending_action = PendingAction.RESPOND
|
self.pending_action = PendingAction.RESPOND
|
||||||
self.expected_response = self.game.deck.mancato_cards
|
self.expected_response = self.game.deck.mancato_cards.copy()
|
||||||
if isinstance(self.character, chd.ElenaFuente):
|
if isinstance(self.character, chars.CalamityJanet) and cs.Bang(0, 0).name not in self.expected_response:
|
||||||
|
self.expected_response.append(cs.Bang(0, 0).name)
|
||||||
|
elif isinstance(self.character, chd.ElenaFuente):
|
||||||
self.expected_response = self.game.deck.all_cards_str
|
self.expected_response = self.game.deck.all_cards_str
|
||||||
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 barrel_pick_no_dmg(self):
|
||||||
|
pickable_cards = 1 + self.character.pick_mod
|
||||||
|
if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 and isinstance(self.character, chars.Jourdonnais):
|
||||||
|
pickable_cards = 2
|
||||||
|
while pickable_cards > 0:
|
||||||
|
pickable_cards -= 1
|
||||||
|
picked: cs.Card = self.game.deck.pick_and_scrap()
|
||||||
|
print(f'Did pick {picked}')
|
||||||
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
|
data=f'_flipped|{self.name}|{picked}')
|
||||||
|
if picked.suit == cs.Suit.HEARTS:
|
||||||
|
self.mancato_needed -= 1
|
||||||
|
self.notify_self()
|
||||||
|
if self.mancato_needed <= 0:
|
||||||
|
self.game.responders_did_respond_resume_turn(did_lose=False)
|
||||||
|
return
|
||||||
|
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
||||||
|
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
||||||
|
self.take_no_damage_response()
|
||||||
|
self.game.responders_did_respond_resume_turn(did_lose=True)
|
||||||
|
else:
|
||||||
|
self.pending_action = PendingAction.RESPOND
|
||||||
|
self.expected_response = self.game.deck.mancato_cards.copy()
|
||||||
|
if isinstance(self.character, chars.CalamityJanet) and cs.Bang(0, 0).name not in self.expected_response:
|
||||||
|
self.expected_response.append(cs.Bang(0, 0).name)
|
||||||
|
elif isinstance(self.character, chd.ElenaFuente):
|
||||||
|
self.expected_response = self.game.deck.all_cards_str
|
||||||
|
self.on_failed_response_cb = self.take_no_damage_response
|
||||||
|
self.notify_self()
|
||||||
|
|
||||||
|
def get_banged(self, attacker, double=False, no_dmg=False, card_index=None):
|
||||||
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 card_index != None:
|
||||||
|
self.dmg_card_index = card_index
|
||||||
|
else:
|
||||||
|
self.dmg_card_index = -1
|
||||||
for i in range(len(self.equipment)):
|
for i in range(len(self.equipment)):
|
||||||
if self.equipment[i].can_be_used_now:
|
if self.equipment[i].can_be_used_now:
|
||||||
print('usable', self.equipment[i])
|
print('usable', self.equipment[i])
|
||||||
@ -539,26 +711,38 @@ class Player:
|
|||||||
and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
|
||||||
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
|
||||||
print('Cant defend')
|
print('Cant defend')
|
||||||
self.take_damage_response()
|
if not no_dmg:
|
||||||
|
self.take_damage_response()
|
||||||
|
else:
|
||||||
|
self.take_no_damage_response()
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if (not self.game.check_event(ce.Lazo) and len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0) or isinstance(self.character, chars.Jourdonnais):
|
if (not self.game.check_event(ce.Lazo) and 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
|
if not no_dmg:
|
||||||
|
self.on_pick_cb = self.barrel_pick
|
||||||
|
else:
|
||||||
|
self.on_pick_cb = self.barrel_pick_no_dmg
|
||||||
else:
|
else:
|
||||||
print('has mancato')
|
print('has mancato')
|
||||||
self.pending_action = PendingAction.RESPOND
|
self.pending_action = PendingAction.RESPOND
|
||||||
self.expected_response = self.game.deck.mancato_cards
|
self.expected_response = self.game.deck.mancato_cards.copy()
|
||||||
if self.attacker and isinstance(self.attacker.character, chd.BelleStar) or self.game.check_event(ce.Lazo):
|
if self.attacker and self.attacker in self.game.players and isinstance(self.attacker.character, chd.BelleStar) or self.game.check_event(ce.Lazo):
|
||||||
self.expected_response = self.game.deck.mancato_cards_not_green
|
self.expected_response = self.game.deck.mancato_cards_not_green
|
||||||
if isinstance(self.character, chd.ElenaFuente):
|
elif isinstance(self.character, chars.CalamityJanet) and cs.Bang(0, 0).name not in self.expected_response:
|
||||||
|
self.expected_response.append(cs.Bang(0, 0).name)
|
||||||
|
elif isinstance(self.character, chd.ElenaFuente):
|
||||||
self.expected_response = self.game.deck.all_cards_str
|
self.expected_response = self.game.deck.all_cards_str
|
||||||
self.on_failed_response_cb = self.take_damage_response
|
if not no_dmg:
|
||||||
|
self.on_failed_response_cb = self.take_damage_response
|
||||||
|
else:
|
||||||
|
self.on_failed_response_cb = self.take_no_damage_response
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_indians(self, attacker):
|
def get_indians(self, attacker):
|
||||||
self.attacker = attacker
|
self.attacker = attacker
|
||||||
|
if isinstance(self.character, chd.ApacheKid): return False
|
||||||
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
|
if not self.game.is_competitive and 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()
|
||||||
@ -567,6 +751,8 @@ class Player:
|
|||||||
print('has bang')
|
print('has bang')
|
||||||
self.pending_action = PendingAction.RESPOND
|
self.pending_action = PendingAction.RESPOND
|
||||||
self.expected_response = [cs.Bang(0, 0).name]
|
self.expected_response = [cs.Bang(0, 0).name]
|
||||||
|
if isinstance(self.character, chars.CalamityJanet) and cs.Mancato(0, 0).name not in self.expected_response:
|
||||||
|
self.expected_response.append(cs.Mancato(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
|
||||||
return True
|
return True
|
||||||
@ -576,39 +762,55 @@ class Player:
|
|||||||
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
|
if not self.game.is_competitive and 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(did_lose=True)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.pending_action = PendingAction.RESPOND
|
self.pending_action = PendingAction.RESPOND
|
||||||
self.expected_response = [cs.Bang(0, 0).name]
|
self.expected_response = [cs.Bang(0, 0).name]
|
||||||
|
if isinstance(self.character, chars.CalamityJanet) and cs.Mancato(0, 0).name not in self.expected_response:
|
||||||
|
self.expected_response.append(cs.Mancato(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
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def heal_if_needed(self):
|
||||||
|
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)):
|
||||||
|
if isinstance(self.hand[i], cs.Birra):
|
||||||
|
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
||||||
|
self.hand.append(self.game.deck.draw(True))
|
||||||
|
self.lives += 1 if not isinstance(self.character, chd.TequilaJoe) else 2
|
||||||
|
self.game.deck.scrap(self.hand.pop(i), True)
|
||||||
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
|
data=f'_beer_save|{self.name}')
|
||||||
|
break
|
||||||
|
|
||||||
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, chars.BartCassidy):
|
if isinstance(self.character, chars.BartCassidy):
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
data=f'_special_bart_cassidy|{self.name}')
|
data=f'_special_bart_cassidy|{self.name}')
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
elif isinstance(self.character, chars.ElGringo) and self.attacker and len(self.attacker.hand) > 0:
|
elif isinstance(self.character, chars.ElGringo) and self.attacker and self.attacker in self.game.players and len(self.attacker.hand) > 0:
|
||||||
self.hand.append(self.attacker.hand.pop(
|
self.hand.append(self.attacker.hand.pop(
|
||||||
randrange(0, len(self.attacker.hand))))
|
randrange(0, len(self.attacker.hand))))
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
self.sio.emit('chat_message', room=self.game.name,
|
||||||
data=f'_special_el_gringo|{self.name}|{self.attacker.name}')
|
data=f'_special_el_gringo|{self.name}|{self.attacker.name}')
|
||||||
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, cs.Birra)]) > 0:
|
self.heal_if_needed()
|
||||||
for i in range(len(self.hand)):
|
|
||||||
if isinstance(self.hand[i], cs.Birra):
|
|
||||||
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
|
||||||
self.hand.append(self.game.deck.draw())
|
|
||||||
self.lives += 1
|
|
||||||
self.game.deck.scrap(self.hand.pop(i))
|
|
||||||
self.sio.emit('chat_message', room=self.game.name,
|
|
||||||
data=f'_beer_save|{self.name}')
|
|
||||||
break
|
|
||||||
self.mancato_needed = 0
|
self.mancato_needed = 0
|
||||||
|
self.expected_response = []
|
||||||
|
self.event_type = ''
|
||||||
|
self.notify_self()
|
||||||
|
self.attacker = None
|
||||||
|
|
||||||
|
def take_no_damage_response(self):
|
||||||
|
if self.dmg_card_index != None and self.dmg_card_index != -1 and self.game.check_event(ce.Rimbalzo):
|
||||||
|
self.game.deck.scrap(self.equipment.pop(self.dmg_card_index))
|
||||||
|
self.dmg_card_index = -1
|
||||||
|
self.mancato_needed = 0
|
||||||
|
self.expected_response = []
|
||||||
self.event_type = ''
|
self.event_type = ''
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
self.attacker = None
|
self.attacker = None
|
||||||
@ -616,14 +818,14 @@ class Player:
|
|||||||
def respond(self, hand_index):
|
def respond(self, hand_index):
|
||||||
if self.pending_action != PendingAction.RESPOND: return
|
if self.pending_action != PendingAction.RESPOND: return
|
||||||
self.pending_action = PendingAction.WAIT
|
self.pending_action = PendingAction.WAIT
|
||||||
if hand_index != -1 and (
|
if hand_index != -1 and hand_index < (len(self.hand)+len(self.equipment)) and (
|
||||||
((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response)) or
|
((hand_index < len(self.hand) and self.hand[hand_index].name in self.expected_response)) or
|
||||||
self.equipment[hand_index-len(self.hand)].name in self.expected_response):
|
(hand_index-len(self.hand) < len(self.equipment) and self.equipment[hand_index-len(self.hand)].name in self.expected_response)):
|
||||||
card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand))
|
card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand))
|
||||||
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand)+1 and not self.is_my_turn and self.event_type != 'duel':
|
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand)+1 and not self.is_my_turn and self.event_type != 'duel':
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
card.use_card(self)
|
card.use_card(self)
|
||||||
self.game.deck.scrap(card)
|
self.game.deck.scrap(card, True)
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
self.mancato_needed -= 1
|
self.mancato_needed -= 1
|
||||||
if self.mancato_needed <= 0:
|
if self.mancato_needed <= 0:
|
||||||
@ -632,24 +834,25 @@ class Player:
|
|||||||
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand)+1 and not self.is_my_turn:
|
if isinstance(self.character, chd.MollyStark) and hand_index < len(self.hand)+1 and not self.is_my_turn:
|
||||||
self.molly_discarded_cards += 1
|
self.molly_discarded_cards += 1
|
||||||
else:
|
else:
|
||||||
self.game.responders_did_respond_resume_turn()
|
self.game.responders_did_respond_resume_turn(did_lose=False)
|
||||||
self.event_type = ''
|
self.event_type = ''
|
||||||
|
self.expected_response = []
|
||||||
else:
|
else:
|
||||||
self.pending_action = PendingAction.RESPOND
|
self.pending_action = PendingAction.RESPOND
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
else:
|
else:
|
||||||
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
|
||||||
for i in range(self.molly_discarded_cards):
|
for i in range(self.molly_discarded_cards):
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.molly_discarded_cards = 0
|
self.molly_discarded_cards = 0
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
elif self.attacker and isinstance(self.attacker.character, chd.MollyStark) and self.is_my_turn:
|
elif self.attacker and self.attacker in self.game.players and isinstance(self.attacker.character, chd.MollyStark) and self.is_my_turn:
|
||||||
for i in range(self.attacker.molly_discarded_cards):
|
for i in range(self.attacker.molly_discarded_cards):
|
||||||
self.attacker.hand.append(self.attacker.game.deck.draw())
|
self.attacker.hand.append(self.attacker.game.deck.draw(True))
|
||||||
self.attacker.molly_discarded_cards = 0
|
self.attacker.molly_discarded_cards = 0
|
||||||
self.attacker.notify_self()
|
self.attacker.notify_self()
|
||||||
self.on_failed_response_cb()
|
self.on_failed_response_cb()
|
||||||
self.game.responders_did_respond_resume_turn()
|
self.game.responders_did_respond_resume_turn(did_lose=True)
|
||||||
if self.mancato_needed <= 0:
|
if self.mancato_needed <= 0:
|
||||||
self.attacker = None
|
self.attacker = None
|
||||||
|
|
||||||
@ -685,8 +888,8 @@ class Player:
|
|||||||
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)
|
||||||
elif isinstance(self.character, chd.JoseDelgrado) and card.is_equipment and self.special_use_count < 2:
|
elif isinstance(self.character, chd.JoseDelgrado) and card.is_equipment and self.special_use_count < 2:
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.special_use_count += 1
|
self.special_use_count += 1
|
||||||
self.game.deck.scrap(card)
|
self.game.deck.scrap(card)
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
@ -696,15 +899,15 @@ class Player:
|
|||||||
self.special_use_count += 1
|
self.special_use_count += 1
|
||||||
cards = sorted(data['cards'], reverse=True)
|
cards = sorted(data['cards'], reverse=True)
|
||||||
for c in cards:
|
for c in cards:
|
||||||
self.game.deck.scrap(self.hand.pop(c))
|
self.game.deck.scrap(self.hand.pop(c), True)
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
self.game.attack(self, data['against'])
|
self.game.attack(self, data['against'])
|
||||||
|
|
||||||
def chuck_lose_hp_draw(self):
|
def chuck_lose_hp_draw(self):
|
||||||
if isinstance(self.character, chd.ChuckWengam) and self.lives > 1 and self.is_my_turn:
|
if isinstance(self.character, chd.ChuckWengam) and self.lives > 1 and self.is_my_turn:
|
||||||
self.lives -= 1
|
self.lives -= 1
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.hand.append(self.game.deck.draw())
|
self.hand.append(self.game.deck.draw(True))
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
|
||||||
def end_turn(self, forced=False):
|
def end_turn(self, forced=False):
|
||||||
@ -715,11 +918,11 @@ class Player:
|
|||||||
print(
|
print(
|
||||||
f"I {self.name} have to many cards in my hand and I can't end the turn")
|
f"I {self.name} have to many cards in my hand and I can't end the turn")
|
||||||
elif self.pending_action == PendingAction.PLAY or forced:
|
elif self.pending_action == PendingAction.PLAY or forced:
|
||||||
if not forced and self.game.check_event(ce.Vendetta):
|
if not forced and self.game.check_event(ce.Vendetta) and self.can_play_vendetta:
|
||||||
picked: cs.Card = self.game.deck.pick_and_scrap()
|
picked: cs.Card = self.game.deck.pick_and_scrap()
|
||||||
self.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked}')
|
self.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked}')
|
||||||
if picked.suit == cs.Suit.HEARTS:
|
if picked.suit == cs.Suit.HEARTS:
|
||||||
self.play_turn()
|
self.play_turn(can_play_vendetta=False)
|
||||||
return
|
return
|
||||||
self.is_my_turn = False
|
self.is_my_turn = False
|
||||||
for i in range(len(self.equipment)):
|
for i in range(len(self.equipment)):
|
||||||
|
@ -16,6 +16,15 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="lang" style="opacity:0" >Language</label>
|
<label for="lang" style="opacity:0" >Language</label>
|
||||||
|
<div v-if="showUpdateUI" style="position: fixed;bottom: 0;z-index: 1;background: rgba(0,0,0,0.5);padding: 20pt;" class="center-stuff">
|
||||||
|
<p class="update-dialog__content">
|
||||||
|
A new version is available. Refresh to load it?
|
||||||
|
</p>
|
||||||
|
<div class="update-dialog__actions">
|
||||||
|
<button @click="update">Update</button>
|
||||||
|
<button @click="showUpdateUI = false">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -26,6 +35,7 @@ export default {
|
|||||||
name: 'App',
|
name: 'App',
|
||||||
data: () => ({
|
data: () => ({
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
|
c: false,
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
},
|
},
|
||||||
@ -39,18 +49,32 @@ export default {
|
|||||||
},
|
},
|
||||||
room(data) {
|
room(data) {
|
||||||
this.isInLobby = true;
|
this.isInLobby = true;
|
||||||
this.$router.push({path:'game', query: { code: data.name, pwd: data.password }})
|
if (data.password)
|
||||||
|
this.$router.replace({path:'game', query: { code: data.name, pwd: data.password }})
|
||||||
|
else
|
||||||
|
this.$router.replace({path:'game', query: { code: data.name }})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
storeLangPref() {
|
storeLangPref() {
|
||||||
localStorage.setItem('lang', this.$i18n.locale)
|
localStorage.setItem('lang', this.$i18n.locale)
|
||||||
|
},
|
||||||
|
async update() {
|
||||||
|
this.showUpdateUI = false;
|
||||||
|
await this.$workbox.messageSW({ type: "SKIP_WAITING" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (localStorage.getItem('lang'))
|
if (localStorage.getItem('lang'))
|
||||||
this.$i18n.locale = localStorage.getItem('lang')
|
this.$i18n.locale = localStorage.getItem('lang')
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
if (this.$workbox) {
|
||||||
|
this.$workbox.addEventListener("waiting", () => {
|
||||||
|
this.showUpdateUI = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -87,6 +87,17 @@ export default {
|
|||||||
box-shadow: 0 0 0pt 4pt white, 0 0 5pt 4pt #aaa;
|
box-shadow: 0 0 0pt 4pt white, 0 0 5pt 4pt #aaa;
|
||||||
border: 2pt dashed rgb(50 122 172);
|
border: 2pt dashed rgb(50 122 172);
|
||||||
}
|
}
|
||||||
|
.card.back.fistful-of-cards{
|
||||||
|
color:white;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
45deg,
|
||||||
|
rgb(50 122 172),
|
||||||
|
rgb(50 122 172) 5px,
|
||||||
|
rgb(30 102 152) 5px,
|
||||||
|
rgb(30 102 152) 10px
|
||||||
|
);
|
||||||
|
border: 2pt solid rgb(50 122 172);
|
||||||
|
}
|
||||||
.card h4 {
|
.card h4 {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -124,12 +135,12 @@ export default {
|
|||||||
}
|
}
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root, #app {
|
:root, #app {
|
||||||
background-color: #181a1b;
|
background-color: #181a1b;
|
||||||
color: rgb(174, 194, 211);
|
color: rgb(174, 194, 211);
|
||||||
}
|
}
|
||||||
.card {
|
.card {
|
||||||
background-color: #181a1b;
|
background-color: #181a1b;
|
||||||
color: rgb(174, 194, 211);
|
color: rgb(174, 194, 211);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 3pt #987e51,
|
0 0 0 3pt #987e51,
|
||||||
0 0 0 6pt #181a1b,
|
0 0 0 6pt #181a1b,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<div v-if="eventCard" style="position:relative">
|
<div v-if="eventCard" style="position:relative">
|
||||||
<div class="card fistful-of-cards" style="position:relative; bottom:-3pt;right:-3pt;"/>
|
<div class="card fistful-of-cards" style="position:relative; bottom:-3pt;right:-3pt;"/>
|
||||||
<div class="card fistful-of-cards" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
|
<div class="card fistful-of-cards" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
|
||||||
<card :card="eventCard" :key="eventCard" :class="{'last-event':true,'fistful-of-cards':true}"/>
|
<card :card="eventCard" :key="eventCard" :class="eventClasses" @click.native="event"/>
|
||||||
</div>
|
</div>
|
||||||
<div style="position:relative">
|
<div style="position:relative">
|
||||||
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
|
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
|
||||||
@ -59,7 +59,12 @@ export default {
|
|||||||
this.lastScrap = card
|
this.lastScrap = card
|
||||||
},
|
},
|
||||||
event_card(card) {
|
event_card(card) {
|
||||||
this.eventCard = card
|
this.eventCard = card == false ? {
|
||||||
|
name: 'PewPew!',
|
||||||
|
icon: '🎲',
|
||||||
|
back: true,
|
||||||
|
expansion: 'fistful-of-cards',
|
||||||
|
} : card
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -68,6 +73,14 @@ export default {
|
|||||||
name: this.$t('end_turn'),
|
name: this.$t('end_turn'),
|
||||||
icon: '⛔️'
|
icon: '⛔️'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
eventClasses() {
|
||||||
|
let classes = {
|
||||||
|
'last-event':true,
|
||||||
|
'back':this.eventCard.back
|
||||||
|
}
|
||||||
|
classes[this.eventCard.expansion] = true
|
||||||
|
return classes
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -79,6 +92,11 @@ export default {
|
|||||||
else if (this.pending_action == 1)
|
else if (this.pending_action == 1)
|
||||||
this.$socket.emit('draw', pile)
|
this.$socket.emit('draw', pile)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
event() {
|
||||||
|
if (this.pending_action !== false) {
|
||||||
|
this.$socket.emit('draw', 'event')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -34,8 +34,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="!started">
|
<div v-if="!started">
|
||||||
<h3>{{$t("expansions")}}</h3>
|
<h3>{{$t("expansions")}}</h3>
|
||||||
<div v-for="ex in togglable_expansions" v-bind:key="ex">
|
<div v-for="ex in expansionsStatus" v-bind:key="ex.id">
|
||||||
<PrettyCheck @click.native="toggleExpansions(ex)" :disabled="!isRoomOwner" :value="is_toggled_expansion(ex)" class="p-switch p-fill" style="margin-top:5px; margin-bottom:3px;">{{get_expansion_name(ex)}}</PrettyCheck>
|
<PrettyCheck @click.native="toggleExpansions(ex.id)" :disabled="!isRoomOwner" :checked="ex.enabled" class="p-switch p-fill" style="margin-top:5px; margin-bottom:3px;">{{ex.name}}</PrettyCheck>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
<h3>{{$t('mods')}}</h3>
|
<h3>{{$t('mods')}}</h3>
|
||||||
@ -137,7 +137,16 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
inviteLink() {
|
inviteLink() {
|
||||||
return `${window.location.origin}/game?code=${this.lobbyName}&pwd=${this.password}`
|
return `${window.location.origin}/game?code=${this.lobbyName}${this.password?`&pwd=${this.password}`:''}`
|
||||||
|
},
|
||||||
|
expansionsStatus() {
|
||||||
|
return this.togglable_expansions.map(x=>{
|
||||||
|
return {
|
||||||
|
id: x,
|
||||||
|
name: x.replace(/(^|_)([a-z])/g, function($0,$1,$2) {return ' ' + $2.toUpperCase()}),
|
||||||
|
enabled: this.expansions.indexOf(x) !== -1
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
storedUsername() {
|
storedUsername() {
|
||||||
if (localStorage.getItem('username'))
|
if (localStorage.getItem('username'))
|
||||||
@ -174,11 +183,9 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
is_toggled_expansion(ex) {
|
is_toggled_expansion(ex) {
|
||||||
|
console.log(ex+' '+ this.expansions+ (this.expansions.indexOf(ex) !== -1))
|
||||||
return this.expansions.indexOf(ex) !== -1
|
return this.expansions.indexOf(ex) !== -1
|
||||||
},
|
},
|
||||||
get_expansion_name(ex) {
|
|
||||||
return ex.replace('_', ' ').replace(/\w\S*/g, m => m.charAt(0).toUpperCase()+m.substr(1).toLowerCase())
|
|
||||||
},
|
|
||||||
leaveRoom() {
|
leaveRoom() {
|
||||||
window.location.replace(window.location.origin)
|
window.location.replace(window.location.origin)
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<Chooser v-if="is_my_turn && pending_action == 4" :text="$t('wait')" :cards="[]"/>
|
<Chooser v-if="is_my_turn && pending_action == 4" :text="$t('wait')" :cards="[]"/>
|
||||||
<Chooser v-if="card_against" :text="$t('card_against')" :cards="visiblePlayers" :select="selectAgainst" :cancel="cancelCardAgainst"/>
|
<Chooser v-if="card_against" :text="$t('card_against')" :cards="visiblePlayers" :select="selectAgainst" :cancel="cancelCardAgainst"/>
|
||||||
<Chooser v-if="pending_action == 3" :text="respondText" :cards="respondCards" :select="respond"/>
|
<Chooser v-if="pending_action == 3" :text="respondText" :cards="respondCards" :select="respond"/>
|
||||||
<Chooser v-if="shouldChooseCard" :text="$t('choose_card_to_get')" :cards="available_cards" :select="choose"/>
|
<Chooser v-if="shouldChooseCard" :text="$t(choose_text)" :cards="available_cards" :select="choose"/>
|
||||||
<Chooser v-if="lives <= 0 && max_lives > 0" :text="$t('you_died')" :cancelText="$t('spectate')" :cancel="()=>{max_lives = 0}"/>
|
<Chooser v-if="lives <= 0 && max_lives > 0" :text="$t('you_died')" :cancelText="$t('spectate')" :cancel="()=>{max_lives = 0}"/>
|
||||||
<Chooser v-if="win_status !== undefined" :text="win_status?$t('you_win'):$t('you_lose')" />
|
<Chooser v-if="win_status !== undefined" :text="win_status?$t('you_win'):$t('you_lose')" />
|
||||||
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')" />
|
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')" />
|
||||||
@ -54,7 +54,7 @@
|
|||||||
:cards="hand.filter(x => x.is_equipment)" :select="(card) => {joseScrap=false;scrap(card)}" :cancel="() => {joseScrap=false}"/>
|
:cards="hand.filter(x => x.is_equipment)" :select="(card) => {joseScrap=false;scrap(card)}" :cancel="() => {joseScrap=false}"/>
|
||||||
<Chooser v-if="holydayScrap && scrapHand.length < 2" :text="`${$t('discard')} ${2 - scrapHand.length}`"
|
<Chooser v-if="holydayScrap && scrapHand.length < 2" :text="`${$t('discard')} ${2 - scrapHand.length}`"
|
||||||
:cards="notScrappedHand" :select="holydayScrapAdd" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
|
:cards="notScrappedHand" :select="holydayScrapAdd" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
|
||||||
<Chooser v-if="holydayScrap && scrapHand.length == 2" :text="$t('card_against')" :cards="otherPlayers" :select="holydayScrapBang" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
|
<Chooser v-if="holydayScrap && scrapHand.length == 2" :text="$t('card_against')" :cards="visiblePlayers" :select="holydayScrapBang" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -101,6 +101,7 @@ export default {
|
|||||||
desc: '',
|
desc: '',
|
||||||
scrapHand: [],
|
scrapHand: [],
|
||||||
sidWantsScrapForHealth: false,
|
sidWantsScrapForHealth: false,
|
||||||
|
choose_text: '',
|
||||||
joseScrap: false,
|
joseScrap: false,
|
||||||
holydayScrap: false,
|
holydayScrap: false,
|
||||||
special_use_count: 0,
|
special_use_count: 0,
|
||||||
@ -128,6 +129,7 @@ export default {
|
|||||||
this.max_lives = self.max_lives
|
this.max_lives = self.max_lives
|
||||||
this.has_played_bang = self.has_played_bang
|
this.has_played_bang = self.has_played_bang
|
||||||
this.special_use_count = self.special_use_count
|
this.special_use_count = self.special_use_count
|
||||||
|
this.choose_text = self.choose_text
|
||||||
this.is_my_turn = self.is_my_turn
|
this.is_my_turn = self.is_my_turn
|
||||||
if (this.is_my_turn) document.title = this.$t('your_turn')+' | PewPew!'
|
if (this.is_my_turn) document.title = this.$t('your_turn')+' | PewPew!'
|
||||||
else if (this.pending_action == 3) document.title = this.$t('your_response')+' | PewPew!'
|
else if (this.pending_action == 3) document.title = this.$t('your_response')+' | PewPew!'
|
||||||
@ -191,6 +193,7 @@ export default {
|
|||||||
name: player.name,
|
name: player.name,
|
||||||
number: player.dist !== undefined ? `${player.dist}⛰` : '',
|
number: player.dist !== undefined ? `${player.dist}⛰` : '',
|
||||||
icon: player.is_sheriff ? '⭐' : '🤠',
|
icon: player.is_sheriff ? '⭐' : '🤠',
|
||||||
|
alt_text: Array(player.lives+1).join('❤️')+Array(player.max_lives-player.lives+1).join('💀'),
|
||||||
is_character: true,
|
is_character: true,
|
||||||
}})
|
}})
|
||||||
if (this.card_against && this.card_against.can_target_self) {
|
if (this.card_against && this.card_against.can_target_self) {
|
||||||
|
@ -38,6 +38,12 @@
|
|||||||
"hand": "HAND",
|
"hand": "HAND",
|
||||||
"card_against": "Who will you play your card against?",
|
"card_against": "Who will you play your card against?",
|
||||||
"choose_card_to_get": "Choose a card",
|
"choose_card_to_get": "Choose a card",
|
||||||
|
"choose_guess": "Guess the color of the suit",
|
||||||
|
"choose_ranch": "Choose the cards to replace",
|
||||||
|
"choose_fratelli_di_sangue": "Choose who you want to donate one of your lives",
|
||||||
|
"choose_cecchino": "Choose who to shoot",
|
||||||
|
"choose_rimbalzo_player": "Choose the target of the bang",
|
||||||
|
"choose_rimbalzo_card": "Choose the card to discard the bang to",
|
||||||
"you_died":"YOU DIED",
|
"you_died":"YOU DIED",
|
||||||
"spectate":"SPECTATE",
|
"spectate":"SPECTATE",
|
||||||
"you_win":"YOU WON",
|
"you_win":"YOU WON",
|
||||||
@ -80,7 +86,11 @@
|
|||||||
"special_bart_cassidy": "{0} received a compensation because he was injured.",
|
"special_bart_cassidy": "{0} received a compensation because he was injured.",
|
||||||
"special_el_gringo": "{0} stole a card from {1} when he was was injured.",
|
"special_el_gringo": "{0} stole a card from {1} when he was was injured.",
|
||||||
"special_calamity": "{0} played {1} as Bang! against {2}.",
|
"special_calamity": "{0} played {1} as Bang! against {2}.",
|
||||||
"allroles": "In the game there are: {0}."
|
"allroles": "In the game there are: {0}.",
|
||||||
|
"guess": "{0} guesses {1}.",
|
||||||
|
"guess_right": "{0} was right.",
|
||||||
|
"guess_wrong": "{0} was wrong.",
|
||||||
|
"fratelli_sangue": "{0} gave one of his lives to {1}."
|
||||||
},
|
},
|
||||||
"foc": {
|
"foc": {
|
||||||
"leggedelwest": "He must play this card on this turn if possible."
|
"leggedelwest": "He must play this card on this turn if possible."
|
||||||
|
@ -38,6 +38,12 @@
|
|||||||
"hand": "MANO",
|
"hand": "MANO",
|
||||||
"card_against": "Contro chi vuoi giocare la carta",
|
"card_against": "Contro chi vuoi giocare la carta",
|
||||||
"choose_card_to_get": "Scegli che carta pescare",
|
"choose_card_to_get": "Scegli che carta pescare",
|
||||||
|
"choose_guess": "Indovina il colore del seme",
|
||||||
|
"choose_ranch": "Scegli le carte da sostituire",
|
||||||
|
"choose_fratelli_di_sangue": "Scegli a chi donare una delle tue vite",
|
||||||
|
"choose_cecchino": "Scegli contro chi sparare",
|
||||||
|
"choose_rimbalzo_player": "Scegli contro chi scartare il bang",
|
||||||
|
"choose_rimbalzo_card": "Scegli contro che carta scartare il bang",
|
||||||
"you_died": "SEI MORTO",
|
"you_died": "SEI MORTO",
|
||||||
"spectate": "SPETTATORE",
|
"spectate": "SPETTATORE",
|
||||||
"you_win": "HAI VINTO",
|
"you_win": "HAI VINTO",
|
||||||
@ -80,7 +86,11 @@
|
|||||||
"special_bart_cassidy": "{0} ha ricevuto un risarcimento perchè è stato ferito.",
|
"special_bart_cassidy": "{0} ha ricevuto un risarcimento perchè è stato ferito.",
|
||||||
"special_el_gringo": "{0} rubato una carta a {1} mentre veniva colpito.",
|
"special_el_gringo": "{0} rubato una carta a {1} mentre veniva colpito.",
|
||||||
"special_calamity": "{0} ha giovato {1} come un Bang! contro {2}.",
|
"special_calamity": "{0} ha giovato {1} come un Bang! contro {2}.",
|
||||||
"allroles": "Nella partita ci sono: {0}."
|
"allroles": "Nella partita ci sono: {0}.",
|
||||||
|
"guess": "{0} pensa sia {1}.",
|
||||||
|
"guess_right": "{0} ha indovinato.",
|
||||||
|
"guess_wrong": "{0} ha sbagliato.",
|
||||||
|
"fratelli_sangue": "{0} ha donato una delle sue vite a {1}."
|
||||||
},
|
},
|
||||||
"foc": {
|
"foc": {
|
||||||
"leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile"
|
"leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile"
|
||||||
|
@ -3,15 +3,15 @@ import { Workbox } from "workbox-window";
|
|||||||
let wb;
|
let wb;
|
||||||
|
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
wb = new Workbox(`${process.env.BASE_URL}service-worker.js`);
|
wb = new Workbox(`${process.env.BASE_URL}service-worker.js`);
|
||||||
|
|
||||||
wb.addEventListener("controlling", () => {
|
wb.addEventListener("controlling", () => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
wb.register();
|
wb.register();
|
||||||
} else {
|
} else {
|
||||||
wb = null;
|
wb = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default wb;
|
export default wb;
|
Loading…
Reference in New Issue
Block a user