add fantasma, serpente a sonagli
This commit is contained in:
parent
e7bfcb02ff
commit
0668fbf670
@ -1,11 +1,31 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from bang.cards import Card, Suit
|
import bang.roles as r
|
||||||
|
import bang.players as pl
|
||||||
|
from bang.cards import Card, Suit, Bang
|
||||||
|
import bang.expansions.fistful_of_cards.card_events as ce
|
||||||
|
|
||||||
class Fantasma(Card):
|
class Fantasma(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Fantasma', number, is_equipment=True)
|
super().__init__(suit, 'Fantasma', number, is_equipment=True)
|
||||||
self.icon = '👻️' #porta in vita i giocatori morti ma non
|
self.icon = '👻️' #porta in vita i giocatori morti ma non
|
||||||
#TODO
|
|
||||||
|
def play_card(self, player, against, _with=None):
|
||||||
|
if (player.game.check_event(ce.IlGiudice)):
|
||||||
|
return False
|
||||||
|
if len(player.game.get_dead_players(include_ghosts=False)) > 0:
|
||||||
|
player.pending_action = pl.PendingAction.CHOOSE
|
||||||
|
player.choose_text = 'choose_fantasma'
|
||||||
|
player.available_cards = [{
|
||||||
|
'name': p.name,
|
||||||
|
'icon': p.role.icon if(player.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
||||||
|
'avatar': p.avatar,
|
||||||
|
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives)),
|
||||||
|
'is_character': True,
|
||||||
|
'noDesc': True
|
||||||
|
} for p in player.game.get_dead_players(include_ghosts=False)]
|
||||||
|
player.game.deck.scrap(self, True)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
class Lemat(Card):
|
class Lemat(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -19,11 +39,22 @@ class SerpenteASonagli(Card):
|
|||||||
self.need_target = True
|
self.need_target = True
|
||||||
self.icon = '🐍️' # Ogni turno pesca se il seme picche -1hp
|
self.icon = '🐍️' # Ogni turno pesca se il seme picche -1hp
|
||||||
self.alt_text = "♠️ =💔"
|
self.alt_text = "♠️ =💔"
|
||||||
#TODO
|
|
||||||
|
def play_card(self, player, against, _with=None):
|
||||||
|
if (player.game.check_event(ce.IlGiudice)):
|
||||||
|
return False
|
||||||
|
if against != None:
|
||||||
|
self.reset_card()
|
||||||
|
player.sio.emit('chat_message', room=player.game.name,
|
||||||
|
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 Shotgun(Card):
|
class Shotgun(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Shotgun', number, is_equipment=True, range=1)
|
super().__init__(suit, 'Shotgun', number, is_equipment=True, is_weapon=True, range=1)
|
||||||
self.icon = '🔫' # Ogni volta che colpisci un giocatore deve scartare una carta
|
self.icon = '🔫' # Ogni volta che colpisci un giocatore deve scartare una carta
|
||||||
#TODO
|
#TODO
|
||||||
|
|
||||||
@ -57,16 +88,17 @@ class Tomahawk(Card):
|
|||||||
self.need_target = True
|
self.need_target = True
|
||||||
|
|
||||||
def play_card(self, player, against, _with=None):
|
def play_card(self, player, against, _with=None):
|
||||||
if against != None:
|
if against != None and player.game.can_card_reach(self, player, against):
|
||||||
super().play_card(player, against=against)
|
super().play_card(player, against=against)
|
||||||
player.game.attack(player, against)
|
player.game.attack(player, against, card_name=self.name)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class Sventagliata(Card):
|
class Sventagliata(Bang):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Sventagliata', number)
|
super().__init__(suit, number)
|
||||||
self.icon = '💕️'
|
self.name = 'Sventagliata'
|
||||||
|
self.icon = '🎏'
|
||||||
self.alt_text = "💥💥" # spara al target e anche, a uno a distanza 1 dal target
|
self.alt_text = "💥💥" # spara al target e anche, a uno a distanza 1 dal target
|
||||||
self.need_target = True
|
self.need_target = True
|
||||||
|
|
||||||
@ -74,7 +106,7 @@ class Sventagliata(Card):
|
|||||||
if against != None:
|
if against != None:
|
||||||
#TODO
|
#TODO
|
||||||
# super().play_card(player, against=against)
|
# super().play_card(player, against=against)
|
||||||
# player.game.attack(player, against)
|
# player.game.attack(player, against, card_name=self.name)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -89,7 +121,7 @@ class Salvo(Card):
|
|||||||
if against != None:
|
if against != None:
|
||||||
#TODO
|
#TODO
|
||||||
# super().play_card(player, against=against)
|
# super().play_card(player, against=against)
|
||||||
# player.game.attack(player, against)
|
# player.game.attack(player, against, card_name=self.name)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -97,7 +129,7 @@ class Mira(Card):
|
|||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Mira', number)
|
super().__init__(suit, 'Mira', number)
|
||||||
self.icon = '👌🏻'
|
self.icon = '👌🏻'
|
||||||
self.alt_text = "💥🃏 | 👤💥💥"
|
self.alt_text = "💥🃏💔💔"
|
||||||
self.need_target = True
|
self.need_target = True
|
||||||
self.need_with = True
|
self.need_with = True
|
||||||
|
|
||||||
@ -105,7 +137,7 @@ class Mira(Card):
|
|||||||
if against != None:
|
if against != None:
|
||||||
#TODO
|
#TODO
|
||||||
# super().play_card(player, against=against)
|
# super().play_card(player, against=against)
|
||||||
# player.game.attack(player, against)
|
# player.game.attack(player, against, card_name=self.name)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -113,7 +145,7 @@ class Bandidos(Card):
|
|||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Bandidos', number)
|
super().__init__(suit, 'Bandidos', number)
|
||||||
self.icon = '🤠️'
|
self.icon = '🤠️'
|
||||||
self.alt_text = "👤🃏🃏 | 👤💔"
|
self.alt_text = "👤🃏🃏/💔"
|
||||||
|
|
||||||
def play_card(self, player, against, _with=None):
|
def play_card(self, player, against, _with=None):
|
||||||
#TODO
|
#TODO
|
||||||
@ -161,19 +193,19 @@ def get_starting_deck() -> List[Card]:
|
|||||||
cards = [
|
cards = [
|
||||||
Fantasma(Suit.SPADES, 9),
|
Fantasma(Suit.SPADES, 9),
|
||||||
Fantasma(Suit.SPADES, 10),
|
Fantasma(Suit.SPADES, 10),
|
||||||
Lemat(Suit.DIAMONDS, 4),
|
# Lemat(Suit.DIAMONDS, 4),
|
||||||
SerpenteASonagli(Suit.HEARTS, 7),
|
SerpenteASonagli(Suit.HEARTS, 7),
|
||||||
Shotgun(Suit.SPADES, 'K'),
|
# Shotgun(Suit.SPADES, 'K'),
|
||||||
Taglia(Suit.CLUBS, 9),
|
# Taglia(Suit.CLUBS, 9),
|
||||||
UltimoGiro(Suit.DIAMONDS, 8),
|
UltimoGiro(Suit.DIAMONDS, 8),
|
||||||
Tomahawk(Suit.DIAMONDS, 'A'),
|
Tomahawk(Suit.DIAMONDS, 'A'),
|
||||||
Sventagliata(Suit.SPADES, 2),
|
# Sventagliata(Suit.SPADES, 2),
|
||||||
Salvo(Suit.HEARTS, 5),
|
# Salvo(Suit.HEARTS, 5),
|
||||||
Bandidos(Suit.DIAMONDS,'Q'), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita
|
# Bandidos(Suit.DIAMONDS,'Q'), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita
|
||||||
Fuga(Suit.HEARTS, 3), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio
|
# Fuga(Suit.HEARTS, 3), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio
|
||||||
Mira(Suit.CLUBS, 6),
|
# Mira(Suit.CLUBS, 6),
|
||||||
Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo
|
# Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo
|
||||||
RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang
|
# RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang
|
||||||
]
|
]
|
||||||
for c in cards:
|
for c in cards:
|
||||||
c.expansion_icon = '👻️'
|
c.expansion_icon = '👻️'
|
||||||
|
@ -5,6 +5,7 @@ import socketio
|
|||||||
import eventlet
|
import eventlet
|
||||||
|
|
||||||
import bang.players as pl
|
import bang.players as pl
|
||||||
|
import bang.cards as cs
|
||||||
import bang.characters as characters
|
import bang.characters as characters
|
||||||
import bang.expansions.dodge_city.characters as chd
|
import bang.expansions.dodge_city.characters as chd
|
||||||
from bang.deck import Deck
|
from bang.deck import Deck
|
||||||
@ -15,6 +16,33 @@ import bang.expansions.gold_rush.shop_cards as grc
|
|||||||
import bang.expansions.gold_rush.characters as grch
|
import bang.expansions.gold_rush.characters as grch
|
||||||
from metrics import Metrics
|
from metrics import Metrics
|
||||||
|
|
||||||
|
debug_commands = [
|
||||||
|
{'cmd':'/debug', 'help':'Toggles the debug mode'},
|
||||||
|
{'cmd':'/set_chars', 'help':'Set how many characters to distribute - sample /set_chars 3'},
|
||||||
|
{'cmd':'/suicide', 'help':'Kills you'},
|
||||||
|
{'cmd':'/nextevent', 'help':'Flip the next event card'},
|
||||||
|
{'cmd':'/notify', 'help':'Send a message to a player - sample /notify player hi!'},
|
||||||
|
{'cmd':'/show_cards', 'help':'View the hand of another - sample /show_cards player'},
|
||||||
|
{'cmd':'/ddc', 'help':'Destroy all cards - sample /ddc player'},
|
||||||
|
{'cmd':'/dsh', 'help':'Set health - sample /dsh player'},
|
||||||
|
# {'cmd':'/togglebot', 'help':''},
|
||||||
|
{'cmd':'/cancelgame', 'help':'Stops the current game'},
|
||||||
|
{'cmd':'/startgame', 'help':'Force starts the game'},
|
||||||
|
{'cmd':'/setbotspeed', 'help':'Changes the bot response time - sample /setbotspeed 0.5'},
|
||||||
|
# {'cmd':'/addex', 'help':''},
|
||||||
|
{'cmd':'/setcharacter', 'help':'Changes your current character - sample /setcharacter Willy The Kid'},
|
||||||
|
{'cmd':'/setevent', 'help':'Changes the event deck - sample /setevent 0 Manette'},
|
||||||
|
{'cmd':'/removecard', 'help':'Remove a card from hand/equip - sample /removecard 0'},
|
||||||
|
{'cmd':'/getcard', 'help':'Get a brand new card - sample /getcard Birra'},
|
||||||
|
{'cmd':'/meinfo', 'help':'Get player data'},
|
||||||
|
{'cmd':'/gameinfo', 'help':'Get game data'},
|
||||||
|
{'cmd':'/playerinfo', 'help':'Get player data - sample /playerinfo player'},
|
||||||
|
{'cmd':'/mebot', 'help':'Toggles bot mode'},
|
||||||
|
{'cmd':'/getnuggets', 'help':'Adds nuggets to yourself - sample /getnuggets 5'},
|
||||||
|
{'cmd':'/startwithseed', 'help':'start the game with custom seed'},
|
||||||
|
{'cmd':'/getset', 'help':'get extension set of cards sample - /get valley', 'admin':True},
|
||||||
|
]
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self, name, sio:socketio):
|
def __init__(self, name, sio:socketio):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -158,31 +186,7 @@ class Game:
|
|||||||
})
|
})
|
||||||
self.sio.emit('debug', room=self.name, data=self.debug)
|
self.sio.emit('debug', room=self.name, data=self.debug)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
commands = [
|
self.sio.emit('commands', room=self.name, data=[x for x in debug_commands if 'admin' not in x])
|
||||||
{'cmd':'/debug', 'help':'Toggles the debug mode'},
|
|
||||||
{'cmd':'/set_chars', 'help':'Set how many characters to distribute - sample /set_chars 3'},
|
|
||||||
{'cmd':'/suicide', 'help':'Kills you'},
|
|
||||||
{'cmd':'/nextevent', 'help':'Flip the next event card'},
|
|
||||||
{'cmd':'/notify', 'help':'Send a message to a player - sample /notify player hi!'},
|
|
||||||
{'cmd':'/show_cards', 'help':'View the hand of another - sample /show_cards player'},
|
|
||||||
{'cmd':'/ddc', 'help':'Destroy all cards - sample /ddc player'},
|
|
||||||
{'cmd':'/dsh', 'help':'Set health - sample /dsh player'},
|
|
||||||
# {'cmd':'/togglebot', 'help':''},
|
|
||||||
{'cmd':'/cancelgame', 'help':'Stops the current game'},
|
|
||||||
{'cmd':'/startgame', 'help':'Force starts the game'},
|
|
||||||
{'cmd':'/setbotspeed', 'help':'Changes the bot response time - sample /setbotspeed 0.5'},
|
|
||||||
# {'cmd':'/addex', 'help':''},
|
|
||||||
{'cmd':'/setcharacter', 'help':'Changes your current character - sample /setcharacter Willy The Kid'},
|
|
||||||
{'cmd':'/setevent', 'help':'Changes the event deck - sample /setevent 0 Manette'},
|
|
||||||
{'cmd':'/removecard', 'help':'Remove a card from hand/equip - sample /removecard 0'},
|
|
||||||
{'cmd':'/getcard', 'help':'Get a brand new card - sample /getcard Birra'},
|
|
||||||
{'cmd':'/meinfo', 'help':'Get player data'},
|
|
||||||
{'cmd':'/gameinfo', 'help':'Get game data'},
|
|
||||||
{'cmd':'/playerinfo', 'help':'Get player data - sample /playerinfo player'},
|
|
||||||
{'cmd':'/mebot', 'help':'Toggles bot mode'},
|
|
||||||
{'cmd':'/getnuggets', 'help':'Adds nuggets to yourself - sample /getnuggets 5'},
|
|
||||||
{'cmd':'/startwithseed', 'help':'start the game with custom seed'}]
|
|
||||||
self.sio.emit('commands', room=self.name, data=commands)
|
|
||||||
else:
|
else:
|
||||||
self.sio.emit('commands', room=self.name, data=[{'cmd':'/debug', 'help':'Toggles the debug mode'}])
|
self.sio.emit('commands', room=self.name, data=[{'cmd':'/debug', 'help':'Toggles the debug mode'}])
|
||||||
self.sio.emit('spectators', room=self.name, data=len(self.spectators))
|
self.sio.emit('spectators', room=self.name, data=len(self.spectators))
|
||||||
@ -205,7 +209,8 @@ class Game:
|
|||||||
self.notify_room()
|
self.notify_room()
|
||||||
|
|
||||||
def feature_flags(self):
|
def feature_flags(self):
|
||||||
self.available_expansions.append('the_valley_of_shadows')
|
if 'the_valley_of_shadows' not in self.expansions:
|
||||||
|
self.available_expansions.append('the_valley_of_shadows')
|
||||||
self.notify_room()
|
self.notify_room()
|
||||||
|
|
||||||
def add_player(self, player: pl.Player):
|
def add_player(self, player: pl.Player):
|
||||||
@ -346,6 +351,11 @@ class Game:
|
|||||||
if self.pending_winners and not self.someone_won:
|
if self.pending_winners and not self.someone_won:
|
||||||
return self.announces_winners()
|
return self.announces_winners()
|
||||||
|
|
||||||
|
def can_card_reach(self, card: cs.Card, player: pl.Player, target:str):
|
||||||
|
if card and card.range != 0 and card.range < 99:
|
||||||
|
return not any((True for p in self.get_visible_players(player) if p['name'] == target and p['dist'] >= card.range))
|
||||||
|
return True
|
||||||
|
|
||||||
def attack(self, attacker: pl.Player, target_username:str, double:bool=False, card_name:str=None):
|
def attack(self, attacker: pl.Player, target_username:str, double:bool=False, card_name:str=None):
|
||||||
if self.get_player_named(target_username).get_banged(attacker=attacker, double=double, card_name=card_name):
|
if self.get_player_named(target_username).get_banged(attacker=attacker, double=double, card_name=card_name):
|
||||||
self.ready_count = 0
|
self.ready_count = 0
|
||||||
@ -510,7 +520,7 @@ class Game:
|
|||||||
pl.hand.append(self.deck.draw())
|
pl.hand.append(self.deck.draw())
|
||||||
pl.hand.append(self.deck.draw())
|
pl.hand.append(self.deck.draw())
|
||||||
pl.notify_self()
|
pl.notify_self()
|
||||||
elif self.check_event(ceh.CittaFantasma):
|
elif self.check_event(ceh.CittaFantasma) or self.players[self.turn].is_ghost:
|
||||||
print(f'{self.name}: {self.players[self.turn]} is dead, event ghost')
|
print(f'{self.name}: {self.players[self.turn]} is dead, event ghost')
|
||||||
self.players[self.turn].is_ghost = True
|
self.players[self.turn].is_ghost = True
|
||||||
else:
|
else:
|
||||||
@ -777,8 +787,8 @@ class Game:
|
|||||||
def get_alive_players(self):
|
def get_alive_players(self):
|
||||||
return [p for p in self.players if not p.is_dead or p.is_ghost]
|
return [p for p in self.players if not p.is_dead or p.is_ghost]
|
||||||
|
|
||||||
def get_dead_players(self):
|
def get_dead_players(self, include_ghosts=True):
|
||||||
return [p for p in self.players if p.is_dead]
|
return [p for p in self.players if p.is_dead and (include_ghosts or not p.is_ghost)]
|
||||||
|
|
||||||
def notify_all(self):
|
def notify_all(self):
|
||||||
if self.started:
|
if self.started:
|
||||||
|
@ -12,6 +12,7 @@ import bang.expansions.fistful_of_cards.card_events as ce
|
|||||||
import bang.expansions.high_noon.card_events as ceh
|
import bang.expansions.high_noon.card_events as ceh
|
||||||
import bang.expansions.gold_rush.shop_cards as grc
|
import bang.expansions.gold_rush.shop_cards as grc
|
||||||
import bang.expansions.gold_rush.characters as grch
|
import bang.expansions.gold_rush.characters as grch
|
||||||
|
import bang.expansions.the_valley_of_shadows.cards as tvosc
|
||||||
import eventlet
|
import eventlet
|
||||||
from typing import List
|
from typing import List
|
||||||
from metrics import Metrics
|
from metrics import Metrics
|
||||||
@ -208,6 +209,10 @@ class Player:
|
|||||||
self.sio.emit('notify_card', room=self.sid, data=mess)
|
self.sio.emit('notify_card', room=self.sid, data=mess)
|
||||||
|
|
||||||
def notify_self(self):
|
def notify_self(self):
|
||||||
|
if any((True for c in self.equipment if isinstance(c, tvosc.Fantasma))):
|
||||||
|
self.is_ghost = True
|
||||||
|
elif self.is_ghost and not self.game.check_event(ceh.CittaFantasma):
|
||||||
|
self.is_ghost = False
|
||||||
if self.is_ghost: self.lives = 0
|
if self.is_ghost: self.lives = 0
|
||||||
if self.pending_action == PendingAction.DRAW and self.game.check_event(ce.Peyote):
|
if self.pending_action == PendingAction.DRAW and self.game.check_event(ce.Peyote):
|
||||||
self.available_cards = [{
|
self.available_cards = [{
|
||||||
@ -247,6 +252,7 @@ class Player:
|
|||||||
self.choose_text = 'choose_sid_scrap'
|
self.choose_text = 'choose_sid_scrap'
|
||||||
self.available_cards = self.hand
|
self.available_cards = self.hand
|
||||||
self.lives += 1
|
self.lives += 1
|
||||||
|
|
||||||
ser = self.__dict__.copy()
|
ser = self.__dict__.copy()
|
||||||
ser.pop('game')
|
ser.pop('game')
|
||||||
ser.pop('sio')
|
ser.pop('sio')
|
||||||
@ -269,14 +275,12 @@ class Player:
|
|||||||
self.pending_action = PendingAction.WAIT
|
self.pending_action = PendingAction.WAIT
|
||||||
ser['hand'] = []
|
ser['hand'] = []
|
||||||
ser['equipment'] = []
|
ser['equipment'] = []
|
||||||
self.sio.emit('self', room=self.sid, data=json.dumps(
|
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__))
|
||||||
ser, default=lambda o: o.__dict__))
|
|
||||||
self.game.player_death(self)
|
self.game.player_death(self)
|
||||||
if self.game and self.game.started: # falso quando un bot viene eliminato dalla partita
|
if self.game and self.game.started: # falso quando un bot viene eliminato dalla partita
|
||||||
self.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__))
|
self.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__))
|
||||||
self.game.notify_all()
|
self.game.notify_all()
|
||||||
self.sio.emit('self', room=self.sid, data=json.dumps(
|
self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__))
|
||||||
ser, default=lambda o: o.__dict__))
|
|
||||||
|
|
||||||
def bot_spin(self):
|
def bot_spin(self):
|
||||||
while self.is_bot and self.game != None and not self.game.shutting_down:
|
while self.is_bot and self.game != None and not self.game.shutting_down:
|
||||||
@ -449,6 +453,7 @@ class Player:
|
|||||||
'name': p.name,
|
'name': p.name,
|
||||||
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
||||||
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives)),
|
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives)),
|
||||||
|
'avatar': p.avatar,
|
||||||
'is_character': True,
|
'is_character': True,
|
||||||
'noDesc': True
|
'noDesc': True
|
||||||
} for p in self.game.get_alive_players() if p != self and p.lives < p.max_lives]
|
} for p in self.game.get_alive_players() if p != self and p.lives < p.max_lives]
|
||||||
@ -460,7 +465,7 @@ class Player:
|
|||||||
self.available_cards = [self.character, self.not_chosen_character]
|
self.available_cards = [self.character, self.not_chosen_character]
|
||||||
self.choose_text = 'choose_nuova_identita'
|
self.choose_text = 'choose_nuova_identita'
|
||||||
self.pending_action = PendingAction.CHOOSE
|
self.pending_action = PendingAction.CHOOSE
|
||||||
elif not self.game.check_event(ce.Lazo) and any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]):
|
elif not self.game.check_event(ce.Lazo) and any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) or isinstance(c, tvosc.SerpenteASonagli) for c in self.equipment]):
|
||||||
self.is_giving_life = False
|
self.is_giving_life = False
|
||||||
self.pending_action = PendingAction.PICK
|
self.pending_action = PendingAction.PICK
|
||||||
else:
|
else:
|
||||||
@ -490,6 +495,7 @@ class Player:
|
|||||||
'name': p.name,
|
'name': p.name,
|
||||||
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
||||||
'is_character': True,
|
'is_character': True,
|
||||||
|
'avatar': p.avatar,
|
||||||
'noDesc': True
|
'noDesc': True
|
||||||
} for p in self.game.get_alive_players() if len(p.equipment) > 0 and p != self]
|
} for p in self.game.get_alive_players() if len(p.equipment) > 0 and p != self]
|
||||||
self.available_cards.append({'icon': '❌', 'noDesc': True})
|
self.available_cards.append({'icon': '❌', 'noDesc': True})
|
||||||
@ -624,7 +630,20 @@ class Player:
|
|||||||
self.sio.emit('chat_message', room=self.game.name, data=f'_prison_free|{self.name}')
|
self.sio.emit('chat_message', room=self.game.name, data=f'_prison_free|{self.name}')
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
if any([isinstance(c, cs.Prigione) for c in self.equipment]):
|
for i in range(len(self.equipment)):
|
||||||
|
if isinstance(self.equipment[i], tvosc.SerpenteASonagli):
|
||||||
|
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.name}|{picked.num_suit()}')
|
||||||
|
if picked.check_suit(self.game, [cs.Suit.SPADES]) and pickable_cards == 0:
|
||||||
|
self.lives -= 1
|
||||||
|
self.sio.emit('chat_message', room=self.game.name, data=f'_snake_bit|{self.name}')
|
||||||
|
self.end_turn(forced=True)
|
||||||
|
return
|
||||||
|
if any((isinstance(c, cs.Prigione) for c in self.equipment)):
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
return
|
return
|
||||||
if isinstance(self.real_character, chd.VeraCuster):
|
if isinstance(self.real_character, chd.VeraCuster):
|
||||||
@ -799,6 +818,15 @@ class Player:
|
|||||||
player.notify_self()
|
player.notify_self()
|
||||||
self.pending_action = PendingAction.PLAY
|
self.pending_action = PendingAction.PLAY
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
elif 'choose_fantasma' in self.choose_text:
|
||||||
|
if card_index <= len(self.available_cards):
|
||||||
|
player = self.game.get_player_named(self.available_cards[card_index]['name'])
|
||||||
|
player.equipment.append(self.game.deck.scrap_pile.pop(-1))
|
||||||
|
player.notify_self()
|
||||||
|
self.game.notify_all()
|
||||||
|
self.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{player.name}|Fantasma|{player.name}')
|
||||||
|
self.pending_action = PendingAction.PLAY
|
||||||
|
self.notify_self()
|
||||||
elif self.game.check_event(ceh.NuovaIdentita) and self.choose_text == 'choose_nuova_identita':
|
elif self.game.check_event(ceh.NuovaIdentita) and self.choose_text == 'choose_nuova_identita':
|
||||||
if card_index == 1: # the other character
|
if card_index == 1: # the other character
|
||||||
self.character = self.not_chosen_character
|
self.character = self.not_chosen_character
|
||||||
@ -1251,6 +1279,7 @@ class Player:
|
|||||||
'name': p.name,
|
'name': p.name,
|
||||||
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
|
||||||
'is_character': True,
|
'is_character': True,
|
||||||
|
'avatar': p.avatar,
|
||||||
'alt_text': ''.join(['🎴️'] * len(p.gold_rush_equipment)),
|
'alt_text': ''.join(['🎴️'] * len(p.gold_rush_equipment)),
|
||||||
'noDesc': True
|
'noDesc': True
|
||||||
} for p in self.game.get_alive_players() if p != self and len([e for e in p.gold_rush_equipment if e.number + 1 <= self.gold_nuggets]) > 0]
|
} for p in self.game.get_alive_players() if p != self and len([e for e in p.gold_rush_equipment if e.number + 1 <= self.gold_nuggets]) > 0]
|
||||||
@ -1336,7 +1365,7 @@ class Player:
|
|||||||
self.play_turn(can_play_vendetta=False)
|
self.play_turn(can_play_vendetta=False)
|
||||||
return
|
return
|
||||||
##Ghost##
|
##Ghost##
|
||||||
if self.is_dead and self.is_ghost and self.game.check_event(ceh.CittaFantasma):
|
if self.is_dead and self.is_ghost and self.game.check_event(ceh.CittaFantasma) and not any((True for c in self.equipment if isinstance(c, tvosc.Fantasma))):
|
||||||
self.is_ghost = False
|
self.is_ghost = False
|
||||||
for i in range(len(self.hand)):
|
for i in range(len(self.hand)):
|
||||||
self.game.deck.scrap(self.hand.pop(), True)
|
self.game.deck.scrap(self.hand.pop(), True)
|
||||||
|
71
backend/tests/valley_of_shadows_test.py
Normal file
71
backend/tests/valley_of_shadows_test.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
from random import randint
|
||||||
|
from bang.characters import Character
|
||||||
|
from bang.expansions.the_valley_of_shadows.cards import *
|
||||||
|
from tests.dummy_socket import DummySocket
|
||||||
|
from bang.deck import Deck
|
||||||
|
from bang.game import Game
|
||||||
|
from bang.players import Player, PendingAction
|
||||||
|
|
||||||
|
# test UltimoGiro
|
||||||
|
def test_ultimo_giro():
|
||||||
|
sio = DummySocket()
|
||||||
|
g = Game('test', sio)
|
||||||
|
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
|
||||||
|
for p in ps:
|
||||||
|
g.add_player(p)
|
||||||
|
g.start_game()
|
||||||
|
for p in ps:
|
||||||
|
p.available_characters = [Character('test_char', 4)]
|
||||||
|
p.set_character(p.available_characters[0].name)
|
||||||
|
ultimo_giro_guy = g.players[g.turn]
|
||||||
|
ultimo_giro_guy.draw('')
|
||||||
|
ultimo_giro_guy.lives = 3
|
||||||
|
ultimo_giro_guy.hand = [UltimoGiro(0,0)]
|
||||||
|
assert ultimo_giro_guy.lives == 3
|
||||||
|
ultimo_giro_guy.play_card(0)
|
||||||
|
assert ultimo_giro_guy.lives == 4
|
||||||
|
|
||||||
|
# test Tomahawk
|
||||||
|
def test_tomahawk():
|
||||||
|
sio = DummySocket()
|
||||||
|
g = Game('test', sio)
|
||||||
|
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(6)]
|
||||||
|
for p in ps:
|
||||||
|
g.add_player(p)
|
||||||
|
g.start_game()
|
||||||
|
for p in ps:
|
||||||
|
p.available_characters = [Character('test_char', 4)]
|
||||||
|
p.set_character(p.available_characters[0].name)
|
||||||
|
tomahawk_guy = g.players[g.turn]
|
||||||
|
tomahawk_guy.draw('')
|
||||||
|
tomahawk_guy.hand = [Tomahawk(0,0)]
|
||||||
|
assert len(tomahawk_guy.hand) == 1
|
||||||
|
tomahawk_guy.play_card(0, g.players[(g.turn+3)%6].name)
|
||||||
|
assert len(tomahawk_guy.hand) == 1
|
||||||
|
tomahawk_guy.play_card(0, g.players[(g.turn+1)%6].name)
|
||||||
|
assert len(tomahawk_guy.hand) == 0
|
||||||
|
|
||||||
|
# test Fantasma
|
||||||
|
def test_fantasma():
|
||||||
|
sio = DummySocket()
|
||||||
|
g = Game('test', sio)
|
||||||
|
ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)]
|
||||||
|
for p in ps:
|
||||||
|
g.add_player(p)
|
||||||
|
g.start_game()
|
||||||
|
|
||||||
|
for p in ps:
|
||||||
|
p.available_characters = [Character('test_char', 4)]
|
||||||
|
p.set_character(p.available_characters[0].name)
|
||||||
|
fantasma_guy = g.players[g.turn]
|
||||||
|
fantasma_guy.lives = 0
|
||||||
|
fantasma_guy.notify_self()
|
||||||
|
pl = g.players[g.turn]
|
||||||
|
pl.draw('')
|
||||||
|
pl.hand = [Fantasma(0,0)]
|
||||||
|
pl.play_card(0)
|
||||||
|
assert pl.pending_action == PendingAction.CHOOSE
|
||||||
|
assert pl.available_cards[0]['name'] == fantasma_guy.name
|
||||||
|
pl.choose(0)
|
||||||
|
assert pl.pending_action == PendingAction.PLAY
|
||||||
|
assert len(fantasma_guy.equipment) == 1 and isinstance(fantasma_guy.equipment[0], Fantasma)
|
@ -713,7 +713,7 @@
|
|||||||
},
|
},
|
||||||
"Sventagliata": {
|
"Sventagliata": {
|
||||||
"name": "Sventagliata",
|
"name": "Sventagliata",
|
||||||
"desc": "Conta come l'unico BANGI del turno. Anche un giocatore a tua scelta a distanza 1 dal bersaglio (se ce, te escluso) è bersaglio di un BANG.."
|
"desc": "Conta come l'unico BANG! del turno. Anche un giocatore a tua scelta a distanza 1 dal bersaglio (se ce, te escluso) è bersaglio di un BANG."
|
||||||
},
|
},
|
||||||
"UltimoGiro": {
|
"UltimoGiro": {
|
||||||
"name": "Ultimo Giro",
|
"name": "Ultimo Giro",
|
||||||
|
Loading…
Reference in New Issue
Block a user