Merge pull request #16 from albertoxamin/dev

add fistful of cards
This commit is contained in:
Alberto Xamin 2020-12-23 13:11:50 +01:00 committed by GitHub
commit f3631232d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 719 additions and 278 deletions

2
.gitignore vendored
View File

@ -139,3 +139,5 @@ cython_debug/
frontend/package-lock.json
bang-workspace.code-workspace
.vscode/

View File

@ -8,6 +8,9 @@ import socketio
from bang.game import Game
from bang.players import Player
import sys
sys.setrecursionlimit(10**6) # this should prevents bots from stopping
sio = socketio.Server(cors_allowed_origins="*")
static_files={
'/': {'content_type': 'text/html', 'filename': 'index.html'},
@ -205,6 +208,8 @@ def chat_message(sid, msg):
ses.game.reset()
elif '/startgame' in msg and not ses.game.started:
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:
cmd = msg.split()
if len(cmd) == 2:
@ -214,10 +219,39 @@ def chat_message(sid, msg):
ses.game.notify_room()
else:
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:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.game.__dict__}'})
elif '/meinfo' in msg:
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:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} COMMAND NOT FOUND'})
else:

View File

@ -58,12 +58,7 @@ class Card(ABC):
if not has_weapon:
player.equipment.append(self)
elif self.name in [c.name for c in player.equipment if not isinstance(c, Dinamite)]:
for i in range(len(player.equipment)):
print('tipo',type(self))
if type(player.equipment[i]) == type(self):
player.game.deck.scrap(player.equipment[i])
player.equipment[i] = self
break
return False
else:
player.equipment.append(self)
if against:
@ -77,6 +72,9 @@ class Card(ABC):
def use_card(self, player):
pass
def is_duplicate_card(self, player):
return self.name in [c.name for c in player.equipment]
class Barile(Card):
def __init__(self, suit, number):
@ -124,6 +122,7 @@ class Prigione(Card):
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).notify_self()
return True
return False
class Remington(Card):

View File

@ -22,15 +22,16 @@ class Deck:
self.event_cards: List[ce.CardEvent] = []
if 'fistful_of_cards' in game.expansions:
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)
self.scrap_pile: List[cs.Card] = []
print(f'Deck initialized with {len(self.cards)} cards')
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.game.notify_event_card()
self.game.notify_event_card()
def peek(self, n_cards: int) -> list:
return self.cards[:n_cards]
@ -52,7 +53,9 @@ class Deck:
def put_on_top(self, card: cs.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)
if len(self.cards) == 0:
self.reshuffle()
@ -71,8 +74,11 @@ class Deck:
else:
return self.draw()
def scrap(self, card: cs.Card):
def scrap(self, card: cs.Card, ignore_event = False):
if card.usable_next_turn:
card.can_be_used_now = False
self.scrap_pile.append(card)
self.game.notify_scrap_pile()
if self.game.check_event(ce.MinieraAbbandonata) and not ignore_event:
self.put_on_top(card)
else:
self.scrap_pile.append(card)
self.game.notify_scrap_pile()

View File

@ -152,8 +152,11 @@ class Bibbia(Schivata):
pass
return False
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class Cappello(Mancato):
def __init__(self, suit, number):
@ -168,8 +171,11 @@ class Cappello(Mancato):
pass
return False
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class PlaccaDiFerro(Cappello):
def __init__(self, suit, number):
@ -195,8 +201,11 @@ class Pugnale(Pugno):
if self.can_be_used_now:
return super().play_card(player, against=against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class Derringer(Pugnale):
def __init__(self, suit, number):
@ -212,8 +221,11 @@ class Derringer(Pugnale):
player.hand.append(player.game.deck.draw())
return super().play_card(player, against=against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
def use_card(self, player):
player.hand.append(player.game.deck.draw())
@ -235,8 +247,11 @@ class Borraccia(Card):
player.notify_self()
return True
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class PonyExpress(WellsFargo):
def __init__(self, suit, number):
@ -250,8 +265,11 @@ class PonyExpress(WellsFargo):
if self.can_be_used_now:
return super().play_card(player, against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class Howitzer(Gatling):
def __init__(self, suit, number):
@ -265,8 +283,11 @@ class Howitzer(Gatling):
if self.can_be_used_now:
return super().play_card(player, against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class CanCan(CatBalou):
def __init__(self, suit, number):
@ -280,8 +301,11 @@ class CanCan(CatBalou):
if self.can_be_used_now:
return super().play_card(player, against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class Conestoga(Panico):
def __init__(self, suit, number):
@ -297,8 +321,11 @@ class Conestoga(Panico):
if self.can_be_used_now:
return super().play_card(player, against)
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class Pepperbox(Bang):
def __init__(self, suit, number):
@ -316,8 +343,11 @@ class Pepperbox(Bang):
return True
return False
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
class FucileDaCaccia(Card):
def __init__(self, suit, number):
@ -336,12 +366,14 @@ class FucileDaCaccia(Card):
return True
return False
else:
player.equipment.append(self)
return True
if not self.is_duplicate_card(player):
player.equipment.append(self)
return True
else:
return False
def get_starting_deck() -> List[Card]:
return [
#TODO: aggiungere anche le carte normalmente presenti https://bang.dvgiochi.com/cardslist.php?id=3
Barile(Suit.CLUBS, 'A'),
Binocolo(Suit.DIAMONDS, 10),
Dinamite(Suit.CLUBS, 10),

View File

@ -1,4 +1,5 @@
from abc import ABC, abstractmethod
import random
class CardEvent(ABC):
def __init__(self, name, icon):
@ -7,109 +8,114 @@ class CardEvent(ABC):
class Agguato(CardEvent):
def __init__(self):
super().__init__('Agguato', '🛁')
self.desc = 'La distanza base di tra 2 qualsiasi giocatori è 1'
self.desc_eng = 'The base distance from any 2 players is 1'
super().__init__("Agguato", "🛁")
self.desc = "La distanza base di tra 2 qualsiasi giocatori è 1"
self.desc_eng = "The base distance from any 2 players is 1"
class Cecchino(CardEvent):
def __init__(self): #TODO
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_eng = 'During their turn, players can discard 2 Bang! to shoot a bang that requires 2 missed'
def __init__(self):
super().__init__("Cecchino", "👁")
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 (click the card)"
class DeadMan(CardEvent):
def __init__(self):
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_eng = 'The first player that died return back to life with 2 hp and 2 cards'
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_eng = "The first player that died return back to life with 2 hp and 2 cards"
class FratelliDiSangue(CardEvent):
def __init__(self):#TODO
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_eng = 'At the begin of their turn, payers can lose 1 hp to give it to another player'
def __init__(self):
super().__init__("Fratelli Di Sangue", "💉")
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 (except the last one) to give it to another player"
class IlGiudice(CardEvent):
def __init__(self):
super().__init__('Il Giudice', '👨‍⚖️')
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'
super().__init__("Il Giudice", "👨‍⚖️")
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"
class Lazo(CardEvent):
def __init__(self):
super().__init__('Lazo', '📿')
self.desc = 'Le carte equipaggiate non hanno effetto'
self.desc_eng = 'Cards in the equipment slot do not work'
super().__init__("Lazo", "📿")
self.desc = "Le carte equipaggiate non hanno effetto"
self.desc_eng = "Cards in the equipment slot do not work"
class LeggeDelWest(CardEvent):
def __init__(self):
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_eng = 'Every player shows the second card that they draw and must use it in that round'
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_eng = "Every player shows the second card that they draw and must use it in that round (if it is possible)"
class LiquoreForte(CardEvent):
def __init__(self):#TODO
super().__init__('Liquore Forte', '🥃')
self.desc = 'I giocatori possono evitare di pescare per recuperare 1 vita'
self.desc_eng = 'Players can skip drawing to regain 1 HP'
def __init__(self):
super().__init__("Liquore Forte", "🥃")
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 (click on the event card to use)"
class MinieraAbbandonata(CardEvent):
def __init__(self):#TODO
super().__init__('Miniera Abbandonata', '')
self.desc = 'I giocatori pescano dagli scarti e scartano in cima al mazzo'
self.desc_eng = 'Players draw from the discarded pile and discard to the deck'
def __init__(self):
super().__init__("Miniera Abbandonata", "")
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)"
#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):
def __init__(self):#TODO
super().__init__('Per Un Pugno Di Carte', '🎴')
self.desc = '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'
def __init__(self):
super().__init__("Per Un Pugno Di Carte", "🎴")
self.desc = "All'inizio del proprio turno, il giocatore subisce tanti bang quante carte ha in mano"
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):
def __init__(self):#TODO
super().__init__('Peyote', '🌵')
self.desc = 'Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina continua'
self.desc_eng = 'Instead of drawing, the player tries to guess the color of the suit, if he\'s right he repeats'
def __init__(self):
super().__init__("Peyote", "🌵")
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 adds the card to the hand and continues trying to guess the next card"
class Ranch(CardEvent):
def __init__(self):#TODO
super().__init__('Ranch', '🐮')
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'
def __init__(self):
super().__init__("Ranch", "🐮")
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"
class Rimbalzo(CardEvent):
def __init__(self):#TODO
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_eng = 'The player can play bang against the cards equipped by the other players, if they do not play miss they are discarded'
def __init__(self):
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 (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 (click the event card)"
class RouletteRussa(CardEvent):
def __init__(self):#TODO
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_eng = 'Starting from the sheriff, every player discards 1 missed, the first one that doesn\'t loses 2 HP'
def __init__(self):
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_eng = "Starting from the sheriff, every player discards 1 missed, the first one that doesn't loses 2 HP"
class Vendetta(CardEvent):
def __init__(self):
super().__init__('Vendetta', '😤')
self.desc = 'Alla fine del proprio turno il giocatore estrae, se esce ♥️ gioca un altro turno'
self.desc_eng = 'When ending the turn, the player flips a card, if it\'s ♥️ he plays another turn'
super().__init__("Vendetta", "😤")
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 from the deck, if it's ♥️ he plays another turn (but he does not flip another card)"
def get_all_events():
return [
cards = [
Agguato(),
# Cecchino(),
Cecchino(),
DeadMan(),
# FratelliDiSangue(),
FratelliDiSangue(),
IlGiudice(),
Lazo(),
LeggeDelWest(),
# LiquoreForte(),
# MinieraAbbandonata(),
# PerUnPugnoDiCarte(),
# Peyote(),
# Ranch(),
# Rimbalzo(),
# RouletteRussa(),
LiquoreForte(),
MinieraAbbandonata(),
Peyote(),
Ranch(),
Rimbalzo(),
RouletteRussa(),
Vendetta(),
]
random.shuffle(cards)
cards.append(PerUnPugnoDiCarte())
for c in cards:
c.expansion = 'fistful-of-cards'
return cards

View File

@ -2,7 +2,7 @@
from typing import List, Set, Dict, Tuple, Optional
import random
import socketio
import bang.players as players
import bang.players as pl
import bang.characters as characters
from bang.deck import Deck
import bang.roles as roles
@ -14,8 +14,8 @@ class Game:
super().__init__()
self.sio = sio
self.name = name
self.players: List[players.Player] = []
self.dead_players: List[players.Player] = []
self.players: List[pl.Player] = []
self.dead_players: List[pl.Player] = []
self.deck: Deck = None
self.started = False
self.turn = 0
@ -24,10 +24,13 @@ class Game:
self.initial_players = 0
self.password = ''
self.expansions = []
self.available_expansions = ['dodge_city']
self.available_expansions = ['dodge_city', 'fistful_of_cards']
self.shutting_down = False
self.is_competitive = False
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):
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.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:
return
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.turn = i
self.players[i].notify_self()
self.notify_event_card()
def attack_others(self, attacker: players.Player):
attacker.pending_action = players.PendingAction.WAIT
def attack_others(self, attacker: pl.Player):
attacker.pending_action = pl.PendingAction.WAIT
attacker.notify_self()
self.waiting_for = 0
self.readyCount = 0
@ -150,11 +154,11 @@ class Game:
self.waiting_for += 1
p.notify_self()
if self.waiting_for == 0:
attacker.pending_action = players.PendingAction.PLAY
attacker.pending_action = pl.PendingAction.PLAY
attacker.notify_self()
def indian_others(self, attacker: players.Player):
attacker.pending_action = players.PendingAction.WAIT
def indian_others(self, attacker: pl.Player):
attacker.pending_action = pl.PendingAction.WAIT
attacker.notify_self()
self.waiting_for = 0
self.readyCount = 0
@ -164,60 +168,99 @@ class Game:
self.waiting_for += 1
p.notify_self()
if self.waiting_for == 0:
attacker.pending_action = players.PendingAction.PLAY
attacker.pending_action = pl.PendingAction.PLAY
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):
self.readyCount = 0
self.waiting_for = 1
attacker.pending_action = players.PendingAction.WAIT
attacker.pending_action = pl.PendingAction.WAIT
attacker.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):
self.readyCount = 0
self.waiting_for = 1
attacker.pending_action = players.PendingAction.WAIT
attacker.pending_action = pl.PendingAction.WAIT
attacker.notify_self()
self.get_player_named(target_username).notify_self()
def emporio(self):
self.available_cards = [self.deck.draw() for i in range(len(self.players))]
self.players[self.turn].pending_action = players.PendingAction.CHOOSE
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 = 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].notify_self()
def respond_emporio(self, player, i):
player.hand.append(self.available_cards.pop(i))
player.available_cards = []
player.pending_action = players.PendingAction.WAIT
player.pending_action = pl.PendingAction.WAIT
player.notify_self()
nextPlayer = self.players[(self.turn + (len(self.players)-len(self.available_cards))) % len(self.players)]
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()
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.notify_self()
def get_player_named(self, name:str):
return self.players[self.players_map[name]]
def responders_did_respond_resume_turn(self):
self.readyCount += 1
if self.readyCount == self.waiting_for:
self.waiting_for = 0
self.readyCount = 0
self.players[self.turn].pending_action = players.PendingAction.PLAY
self.players[self.turn].notify_self()
def responders_did_respond_resume_turn(self, did_lose=False):
print('did_lose', did_lose)
if self.player_bangs > 0 and self.check_event(ce.PerUnPugnoDiCarte):
self.player_bangs -= 1
if self.player_bangs > 1:
print('bang again')
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):
return self.players[(self.turn + 1) % len(self.players)]
def play_turn(self):
self.player_bangs = 0
if isinstance(self.players[self.turn].role, roles.Sheriff):
self.deck.flip_event()
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_map = {c.name: i for i, c in enumerate(self.players)}
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):
if self.shutting_down: return
@ -237,7 +294,10 @@ class Game:
def notify_event_card(self):
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):
print('scrap')
@ -246,7 +306,7 @@ class Game:
else:
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}')
if player in self.players:
if self.disconnect_bot and self.started:
@ -266,24 +326,25 @@ class Game:
return True
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
import bang.expansions.dodge_city.characters as chd
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)):
self.deck.scrap(player.attacker.hand.pop())
self.deck.scrap(player.attacker.hand.pop(), True)
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()
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):
player.attacker.hand.append(self.deck.draw())
player.attacker.hand.append(self.deck.draw(True))
player.attacker.notify_self()
print(f'player {player.name} died')
if (self.waiting_for > 0):
self.responders_did_respond_resume_turn()
if not player in self.players: return
index = self.players.index(player)
died_in_his_turn = self.started and index == self.turn
if self.started and index <= self.turn:
@ -303,7 +364,7 @@ class Game:
if self.started:
print('Check win status')
attacker_role = None
if player.attacker:
if player.attacker and player.attacker in self.players:
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)]
if len(winners) > 0:
@ -318,22 +379,36 @@ class Game:
vulture = [p for p in self.players if isinstance(p.character, characters.VultureSam)]
if len(vulture) == 0:
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)):
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:
for i in range(len(player.hand)):
vulture[0].hand.append(player.hand.pop())
for i in range(len(player.equipment)):
vulture[0].hand.append(player.equipment.pop())
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)]
if len(greg) > 0:
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)]
if len(herb) > 0:
herb[0].hand.append(self.deck.draw())
herb[0].hand.append(self.deck.draw())
herb[0].hand.append(self.deck.draw(True))
herb[0].hand.append(self.deck.draw(True))
herb[0].notify_self()
if died_in_his_turn:
@ -357,7 +432,7 @@ class Game:
if len(self.deck.event_cards) == 0: return False
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)
sight = player.get_sight()
mindist = 99 if not self.check_event(ce.Agguato) else 1
@ -367,6 +442,7 @@ class Game:
'lives': self.players[j].lives,
'max_lives': self.players[j].max_lives,
'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]
def notify_all(self):

View File

@ -48,6 +48,13 @@ class Player:
self.attacker: Player = None
self.target_p: str = None
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.molly_discarded_cards = 0
self.is_bot = bot
@ -59,11 +66,14 @@ class Player:
self.role: r.Role = None
self.character: chars.Character = None
self.real_character: chars.Character = None
self.is_using_checchino = False
self.lives = 0
self.max_lives = 0
self.is_my_turn = False
self.is_waiting_for_action = True
self.has_played_bang = False
self.can_play_ranch = True
self.is_playing_ranch = False
self.pending_action: PendingAction = None
self.available_characters = []
self.was_shot = False
@ -146,13 +156,34 @@ class Player:
self.sio.emit('notify_card', room=self.sid, data=mess)
def notify_self(self):
if isinstance(self.character, chars.CalamityJanet):
if cs.Mancato(0, 0).name not in self.expected_response:
self.expected_response.append(cs.Mancato(0, 0).name)
elif cs.Bang(0, 0).name not in self.expected_response:
self.expected_response.append(cs.Bang(0, 0).name)
elif isinstance(self.character, chars.SuzyLafayette) and len(self.hand) == 0:
self.hand.append(self.game.deck.draw())
if self.pending_action == PendingAction.DRAW and self.game.check_event(ce.Peyote):
self.available_cards = [{
'icon': '🔴'
},{
'icon': ''
}]
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.pop('game')
ser.pop('sio')
@ -166,14 +197,6 @@ class Player:
ser['sight'] = self.get_sight()
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:
self.pending_action = PendingAction.WAIT
ser['hand'] = []
@ -196,7 +219,7 @@ class Player:
def bot_logic(self):
if self.game.shutting_down: return
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:
return
if self.pending_action == PendingAction.PICK:
@ -204,45 +227,39 @@ class Player:
elif self.pending_action == PendingAction.DRAW:
self.draw('')
elif self.pending_action == PendingAction.PLAY:
has_played = False
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:
for i in range(len(self.hand)):
if self.hand[i].is_equipment or self.hand[i].usable_next_turn:
self.play_card(i)
has_played = True
break
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]):
for i in range(len(self.hand)):
c = self.hand[i]
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):
self.play_card(i)
has_played = True
break
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:
for i in range(len(self.hand)):
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 self.hand[i].need_with and len(self.hand) < 2:
continue
_range = self.get_sight() if self.hand[i].name == 'Bang!' or self.hand[i].name == "Pepperbox" else self.hand[i].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'])]
if len(others) == 0:
continue
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])]
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)]
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))]
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]
if len(equippables) > 0 and not self.game.check_event(ce.IlGiudice):
for c in equippables:
if self.play_card(self.hand.index(c)):
return
elif len(misc) > 0:
for c in misc:
if self.play_card(self.hand.index(c)):
return
elif len(need_target) > 0:
for c in need_target:
_range = self.get_sight() if c.name == 'Bang!' or 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']) 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 len(others) == 0:
continue
target = others[randrange(0, len(others))]
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
target = others[randrange(0, len(others))]
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
target = others[randrange(0, len(others))]
if not self.hand[i].need_with:
self.play_card(i, against=target['name'])
else:
self.play_card(i, against=target['name'], _with=sample([j for j in range(len(self.hand)) if j != i], 1)[0])
has_played = True
break
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 c.need_with:
if self.play_card(self.hand.index(c), against=target['name']):
return
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]):
return
elif len(green_cards) > 0:
for c in green_cards:
if not isinstance(c, cs.Mancato) and c.usable_next_turn and c.can_be_used_now:
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:
_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'])]
@ -251,18 +268,18 @@ class Player:
target = others[randrange(0, len(others))]
if target['is_sheriff'] and isinstance(self.role, r.Renegade):
target = others[randrange(0, len(others))]
self.play_card(len(self.hand)+i, against=target['name'])
has_played = True
if self.play_card(len(self.hand)+self.equipment.index(c), against=target['name']):
return
break
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)
else:
self.end_turn()
elif self.pending_action == PendingAction.RESPOND:
did_respond = False
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)
did_respond = True
break
@ -284,10 +301,13 @@ class Player:
else:
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:
return self.end_turn(forced=True)
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,
data=f'_turn|{self.name}')
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.has_played_bang = False
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
else:
self.is_giving_life = False
if isinstance(self.real_character, chd.VeraCuster):
self.set_available_character([p.character for p in self.game.players if p != self])
else:
@ -306,16 +338,43 @@ class Player:
self.notify_self()
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:
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.available_cards = [self.game.deck.draw() for i in range(3)]
self.choose_text = 'choose_card_to_get'
self.pending_action = PendingAction.CHOOSE
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:
self.is_drawing = True
self.available_cards = self.game.get_player_named(pile).equipment
self.choose_text = 'choose_card_to_get'
self.pending_action = PendingAction.CHOOSE
self.notify_self()
else:
@ -356,7 +415,7 @@ class Player:
pickable_cards = 1 + self.character.pick_mod
if self.is_my_turn:
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:
pickable_cards -= 1
picked: cs.Card = self.game.deck.pick_and_scrap()
@ -365,14 +424,13 @@ class Player:
data=f'_flipped|{self.name}|{picked}')
if picked.suit == cs.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0:
self.lives -= 3
self.game.deck.scrap(self.equipment.pop(i))
self.sio.emit('chat_message', room=self.game.name,
data=f'_explode|{self.name}')
self.game.deck.scrap(self.equipment.pop(i), True)
self.sio.emit('chat_message', room=self.game.name, data=f'_explode|{self.name}')
self.heal_if_needed()
if isinstance(self.character, chars.BartCassidy) and self.lives > 0:
for i in range(3):
self.hand.append(self.game.deck.draw())
self.sio.emit('chat_message', room=self.game.name,
data=f'_special_bart_cassidy|{self.name}')
self.hand.append(self.game.deck.draw(True))
self.sio.emit('chat_message', room=self.game.name, data=f'_special_bart_cassidy|{self.name}')
print(f'{self.name} Boom, -3 hp')
break
else:
@ -391,11 +449,11 @@ class Player:
self.sio.emit('chat_message', room=self.game.name,
data=f'_flipped|{self.name}|{picked}')
if picked.suit != cs.Suit.HEARTS and pickable_cards == 0:
self.game.deck.scrap(self.equipment.pop(i))
self.game.deck.scrap(self.equipment.pop(i), True)
self.end_turn(forced=True)
return
elif pickable_cards == 0:
self.game.deck.scrap(self.equipment.pop(i))
self.game.deck.scrap(self.equipment.pop(i), True)
break
break
if any([isinstance(c, cs.Prigione) for c in self.equipment]):
@ -440,20 +498,31 @@ class Player:
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)
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 did_play_card:
self.game.deck.scrap(card)
self.game.deck.scrap(card, True)
else:
self.hand.insert(hand_index, card)
if withCard:
self.hand.insert(_with, withCard)
elif card.usable_next_turn and card.can_be_used_now:
if did_play_card:
self.game.deck.scrap(card)
self.game.deck.scrap(card, True)
else:
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()
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):
if self.pending_action != PendingAction.CHOOSE:
@ -471,7 +540,7 @@ class Player:
card.can_be_used_now = False
self.hand.append(card)
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]):
self.event_type = ''
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:
self.target_p = self.game.players[self.game.players_map[self.target_p]+1].name
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
elif self.is_drawing and isinstance(self.character, chars.KitCarlson):
self.hand.append(self.available_cards.pop(card_index))
@ -515,23 +651,59 @@ class Player:
self.mancato_needed -= 1
self.notify_self()
if self.mancato_needed <= 0:
self.game.responders_did_respond_resume_turn()
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_damage_response()
self.game.responders_did_respond_resume_turn()
self.game.responders_did_respond_resume_turn(did_lose=True)
else:
self.pending_action = PendingAction.RESPOND
self.expected_response = self.game.deck.mancato_cards
if isinstance(self.character, chd.ElenaFuente):
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_damage_response
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.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)):
if self.equipment[i].can_be_used_now:
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.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
print('Cant defend')
self.take_damage_response()
if not no_dmg:
self.take_damage_response()
else:
self.take_no_damage_response()
return False
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):
print('has barrel')
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:
print('has mancato')
self.pending_action = PendingAction.RESPOND
self.expected_response = self.game.deck.mancato_cards
if self.attacker and isinstance(self.attacker.character, chd.BelleStar) or self.game.check_event(ce.Lazo):
self.expected_response = self.game.deck.mancato_cards.copy()
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
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.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
def get_indians(self, 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:
print('Cant defend')
self.take_damage_response()
@ -567,6 +751,8 @@ class Player:
print('has bang')
self.pending_action = PendingAction.RESPOND
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.on_failed_response_cb = self.take_damage_response
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:
print('Cant defend')
self.take_damage_response()
self.game.responders_did_respond_resume_turn()
self.game.responders_did_respond_resume_turn(did_lose=True)
return False
else:
self.pending_action = PendingAction.RESPOND
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.on_failed_response_cb = self.take_damage_response
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):
self.lives -= 1
if self.lives > 0:
if isinstance(self.character, chars.BartCassidy):
self.sio.emit('chat_message', room=self.game.name,
data=f'_special_bart_cassidy|{self.name}')
self.hand.append(self.game.deck.draw())
elif isinstance(self.character, chars.ElGringo) and self.attacker and len(self.attacker.hand) > 0:
self.hand.append(self.game.deck.draw(True))
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(
randrange(0, len(self.attacker.hand))))
self.sio.emit('chat_message', room=self.game.name,
data=f'_special_el_gringo|{self.name}|{self.attacker.name}')
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:
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.heal_if_needed()
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.notify_self()
self.attacker = None
@ -616,14 +818,14 @@ class Player:
def respond(self, hand_index):
if self.pending_action != PendingAction.RESPOND: return
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
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))
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)
self.game.deck.scrap(card)
self.game.deck.scrap(card, True)
self.notify_self()
self.mancato_needed -= 1
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:
self.molly_discarded_cards += 1
else:
self.game.responders_did_respond_resume_turn()
self.game.responders_did_respond_resume_turn(did_lose=False)
self.event_type = ''
self.expected_response = []
else:
self.pending_action = PendingAction.RESPOND
self.notify_self()
else:
if isinstance(self.character, chd.MollyStark) and not self.is_my_turn:
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.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):
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.notify_self()
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:
self.attacker = None
@ -685,8 +888,8 @@ class Player:
self.scrapped_cards = 0
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:
self.hand.append(self.game.deck.draw())
self.hand.append(self.game.deck.draw())
self.hand.append(self.game.deck.draw(True))
self.hand.append(self.game.deck.draw(True))
self.special_use_count += 1
self.game.deck.scrap(card)
self.notify_self()
@ -696,15 +899,15 @@ class Player:
self.special_use_count += 1
cards = sorted(data['cards'], reverse=True)
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.game.attack(self, data['against'])
def chuck_lose_hp_draw(self):
if isinstance(self.character, chd.ChuckWengam) and self.lives > 1 and self.is_my_turn:
self.lives -= 1
self.hand.append(self.game.deck.draw())
self.hand.append(self.game.deck.draw())
self.hand.append(self.game.deck.draw(True))
self.hand.append(self.game.deck.draw(True))
self.notify_self()
def end_turn(self, forced=False):
@ -715,11 +918,11 @@ class Player:
print(
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:
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()
self.sio.emit('chat_message', room=self.game.name, data=f'_flipped|{self.name}|{picked}')
if picked.suit == cs.Suit.HEARTS:
self.play_turn()
self.play_turn(can_play_vendetta=False)
return
self.is_my_turn = False
for i in range(len(self.equipment)):

View File

@ -16,6 +16,15 @@
</option>
</select>
<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>
</template>
@ -26,6 +35,7 @@ export default {
name: 'App',
data: () => ({
isConnected: false,
c: false,
}),
computed: {
},
@ -39,18 +49,32 @@ export default {
},
room(data) {
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: {
storeLangPref() {
localStorage.setItem('lang', this.$i18n.locale)
},
async update() {
this.showUpdateUI = false;
await this.$workbox.messageSW({ type: "SKIP_WAITING" });
}
},
mounted() {
if (localStorage.getItem('lang'))
this.$i18n.locale = localStorage.getItem('lang')
},
created() {
if (this.$workbox) {
this.$workbox.addEventListener("waiting", () => {
this.showUpdateUI = true;
});
}
}
}
</script>

View File

@ -87,6 +87,17 @@ export default {
box-shadow: 0 0 0pt 4pt white, 0 0 5pt 4pt #aaa;
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 {
position: absolute;
text-align: center;
@ -124,12 +135,12 @@ export default {
}
@media (prefers-color-scheme: dark) {
:root, #app {
background-color: #181a1b;
color: rgb(174, 194, 211);
}
background-color: #181a1b;
color: rgb(174, 194, 211);
}
.card {
background-color: #181a1b;
color: rgb(174, 194, 211);
color: rgb(174, 194, 211);
box-shadow:
0 0 0 3pt #987e51,
0 0 0 6pt #181a1b,

View File

@ -5,7 +5,7 @@
<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: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 style="position:relative">
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
@ -59,7 +59,12 @@ export default {
this.lastScrap = card
},
event_card(card) {
this.eventCard = card
this.eventCard = card == false ? {
name: 'PewPew!',
icon: '🎲',
back: true,
expansion: 'fistful-of-cards',
} : card
},
},
computed: {
@ -68,6 +73,14 @@ export default {
name: this.$t('end_turn'),
icon: '⛔️'
}
},
eventClasses() {
let classes = {
'last-event':true,
'back':this.eventCard.back
}
classes[this.eventCard.expansion] = true
return classes
}
},
methods: {
@ -79,6 +92,11 @@ export default {
else if (this.pending_action == 1)
this.$socket.emit('draw', pile)
}
},
event() {
if (this.pending_action !== false) {
this.$socket.emit('draw', 'event')
}
}
},
watch: {

View File

@ -34,8 +34,8 @@
</div>
<div v-if="!started">
<h3>{{$t("expansions")}}</h3>
<div v-for="ex in togglable_expansions" v-bind:key="ex">
<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>
<div v-for="ex in expansionsStatus" v-bind:key="ex.id">
<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>
</div>
<h3>{{$t('mods')}}</h3>
@ -137,7 +137,16 @@ export default {
},
computed: {
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() {
if (localStorage.getItem('username'))
@ -174,11 +183,9 @@ export default {
},
methods: {
is_toggled_expansion(ex) {
console.log(ex+' '+ this.expansions+ (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() {
window.location.replace(window.location.origin)
},

View File

@ -38,7 +38,7 @@
<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="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="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')" />
@ -54,7 +54,7 @@
: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}`"
: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>
</template>
@ -101,6 +101,7 @@ export default {
desc: '',
scrapHand: [],
sidWantsScrapForHealth: false,
choose_text: '',
joseScrap: false,
holydayScrap: false,
special_use_count: 0,
@ -128,6 +129,7 @@ export default {
this.max_lives = self.max_lives
this.has_played_bang = self.has_played_bang
this.special_use_count = self.special_use_count
this.choose_text = self.choose_text
this.is_my_turn = self.is_my_turn
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!'
@ -191,6 +193,7 @@ export default {
name: player.name,
number: player.dist !== undefined ? `${player.dist}` : '',
icon: player.is_sheriff ? '⭐' : '🤠',
alt_text: Array(player.lives+1).join('❤️')+Array(player.max_lives-player.lives+1).join('💀'),
is_character: true,
}})
if (this.card_against && this.card_against.can_target_self) {

View File

@ -38,6 +38,12 @@
"hand": "HAND",
"card_against": "Who will you play your card against?",
"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",
"spectate":"SPECTATE",
"you_win":"YOU WON",
@ -80,7 +86,11 @@
"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_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": {
"leggedelwest": "He must play this card on this turn if possible."

View File

@ -38,6 +38,12 @@
"hand": "MANO",
"card_against": "Contro chi vuoi giocare la carta",
"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",
"spectate": "SPETTATORE",
"you_win": "HAI VINTO",
@ -80,7 +86,11 @@
"special_bart_cassidy": "{0} ha ricevuto un risarcimento perchè è stato ferito.",
"special_el_gringo": "{0} rubato una carta a {1} mentre veniva colpito.",
"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": {
"leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile"

View File

@ -3,15 +3,15 @@ import { Workbox } from "workbox-window";
let wb;
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", () => {
window.location.reload();
});
wb.addEventListener("controlling", () => {
window.location.reload();
});
wb.register();
wb.register();
} else {
wb = null;
wb = null;
}
export default wb;