From 7f4fc2919666a0cbe292df218dbd888f264d0125 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Thu, 17 Dec 2020 22:21:52 +0100 Subject: [PATCH] some event cards --- backend/__init__.py | 12 +++-- .../fistful_of_cards/card_events.py | 44 +++++++++---------- backend/bang/game.py | 12 ++++- backend/bang/players.py | 28 +++++++++--- frontend/src/components/Lobby.vue | 1 + 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/backend/__init__.py b/backend/__init__.py index d604504..79f07e1 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -67,7 +67,7 @@ def get_me(sid, room): print('room exists') if room['username'] != None and any([p.name == room['username'] for p in de_games[0].players if p.is_bot]): print('getting inside the bot') - bot = [p for p in de_games[0].players if p.is_bot][0] + bot = [p for p in de_games[0].players if p.is_bot and p.name == room['username'] ][0] bot.sid = sid bot.is_bot = False sio.enter_room(sid, de_games[0].name) @@ -82,6 +82,7 @@ def get_me(sid, room): sio.get_session(sid).game = de_games[0] sio.enter_room(sid, de_games[0].name) de_games[0].notify_room(sid) + de_games[0].notify_all() de_games[0].notify_event_card() else: create_room(sid, room['name']) @@ -172,15 +173,17 @@ def chat_message(sid, msg): elif '/suicide' in msg and ses.game.started and ses.lives > 0: ses.lives = 0 ses.notify_self() + elif '/nextevent' in msg and ses.game.started: + ses.game.deck.flip_event() elif '/notify' in msg and ses.game.started: cmd = msg.split() - if len(cmd) == 3: + if len(cmd) >= 3: if cmd[1] in ses.game.players_map: ses.game.get_player_named(cmd[1]).notify_card(ses, { - 'name': cmd[2], + 'name': ' '.join(cmd[2:]), 'icon': '๐Ÿšจ', 'suit': 4, - 'number': cmd[2] + 'number': ' '.join(cmd[2:]) }) else: sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'}) @@ -205,6 +208,7 @@ def chat_message(sid, msg): elif '/addex' in msg and not ses.game.started: cmd = msg.split() if len(cmd) == 2: + cmd[1] = cmd[1].replace('foc', 'fistful_of_cards') if cmd[1] not in ses.game.available_expansions: ses.game.available_expansions.append(cmd[1]) ses.game.notify_room() diff --git a/backend/bang/expansions/fistful_of_cards/card_events.py b/backend/bang/expansions/fistful_of_cards/card_events.py index b6eede0..7a09cb2 100644 --- a/backend/bang/expansions/fistful_of_cards/card_events.py +++ b/backend/bang/expansions/fistful_of_cards/card_events.py @@ -12,19 +12,19 @@ class Agguato(CardEvent): self.desc_eng = '' class Cecchino(CardEvent): - def __init__(self): + 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 = '' class DeadMan(CardEvent): - def __init__(self): + def __init__(self):#TODO 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 = '' class FratelliDiSangue(CardEvent): - def __init__(self): + 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 = '' @@ -42,49 +42,49 @@ class Lazo(CardEvent): self.desc_eng = '' class LeggeDelWest(CardEvent): - def __init__(self): + def __init__(self):#TODO 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 = '' class LiquoreForte(CardEvent): - def __init__(self): + def __init__(self):#TODO super().__init__('Liquore Forte', '๐Ÿฅƒ') self.desc = 'I giocatori possono evitare di pescare per recuperare 1 vita' self.desc_eng = '' class MinieraAbbandonata(CardEvent): - def __init__(self): + def __init__(self):#TODO super().__init__('Miniera Abbandonata', 'โ›') self.desc = 'I giocatori pescano dagli scarti e scartano in cima al mazzo' self.desc_eng = '' class PerUnPugnoDiCarte(CardEvent): - def __init__(self): + 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 = '' class Peyote(CardEvent): - def __init__(self): + 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 = '' class Ranch(CardEvent): - def __init__(self): + 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 = '' class Rimbalzo(CardEvent): - def __init__(self): + 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 = '' class RouletteRussa(CardEvent): - def __init__(self): + 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 = '' @@ -98,18 +98,18 @@ class Vendetta(CardEvent): def get_all_events(): return [ Agguato(), - Cecchino(), - DeadMan(), - FratelliDiSangue(), + # Cecchino(), + # DeadMan(), + # FratelliDiSangue(), IlGiudice(), Lazo(), - LeggeDelWest(), - LiquoreForte(), - MinieraAbbandonata(), - PerUnPugnoDiCarte(), - Peyote(), - Ranch(), - Rimbalzo(), - RouletteRussa(), + # LeggeDelWest(), + # LiquoreForte(), + # MinieraAbbandonata(), + # PerUnPugnoDiCarte(), + # Peyote(), + # Ranch(), + # Rimbalzo(), + # RouletteRussa(), Vendetta(), ] \ No newline at end of file diff --git a/backend/bang/game.py b/backend/bang/game.py index ddcc8be..187ac8c 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -6,6 +6,7 @@ import bang.players as players import bang.characters as characters from bang.deck import Deck import bang.roles as roles +import bang.expansions.fistful_of_cards.card_events as ce import eventlet class Game: @@ -93,7 +94,8 @@ class Game: self.players[i].hand.append(self.deck.draw()) self.players[i].notify_self() current_roles = [type(x.role).__name__ for x in self.players] - current_roles = {x:current_roles.count(x) for x in current_roles} + random.shuffle(current_roles) + current_roles = str({x:current_roles.count(x) for x in current_roles}).replace('{','').replace('}','') self.sio.emit('chat_message', room=self.name, data=f'_allroles|{current_roles}') self.play_turn() @@ -344,12 +346,17 @@ class Game: eventlet.sleep(0.5) self.notify_room() + def check_event(self, ev): + 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): i = self.players.index(player) sight = player.get_sight() + mindist = 99 if self.check_event(ce.Agguato) else 1 return [{ 'name': self.players[j].name, - 'dist': min(abs(i - j), (i+ abs(j-len(self.players))), (j+ abs(i-len(self.players)))) + self.players[j].get_visibility() - (player.get_sight(countWeapon=False)-1), + 'dist': min([abs(i - j), (i+ abs(j-len(self.players))), (j+ abs(i-len(self.players))), mindist]) + self.players[j].get_visibility() - (player.get_sight(countWeapon=False)-1), 'lives': self.players[j].lives, 'max_lives': self.players[j].max_lives, 'is_sheriff': isinstance(self.players[j].role, roles.Sheriff), @@ -367,6 +374,7 @@ class Game: 'is_my_turn': p.is_my_turn, 'pending_action': p.pending_action, 'character': p.character.__dict__ if p.character else None, + 'real_character': p.real_character.__dict__ if p.real_character else None, 'icon': p.role.icon if self.initial_players == 3 and p.role else '๐Ÿค ' } for p in self.players] self.sio.emit('players_update', room=self.name, data=data) diff --git a/backend/bang/players.py b/backend/bang/players.py index 90c4fa7..8996653 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -8,6 +8,7 @@ import bang.cards as cs import bang.expansions.dodge_city.cards as csd import bang.characters as chars import bang.expansions.dodge_city.characters as chd +import bang.expansions.fistful_of_cards.card_events as ce import eventlet class PendingAction(IntEnum): @@ -201,7 +202,7 @@ class Player: 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]) > 0: + 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) @@ -263,7 +264,7 @@ class Player: did_respond = True break for i in range(len(self.equipment)): - if self.equipment[i].name in self.expected_response: + if not self.game.check_event(ce.Lazo) and self.equipment[i].name in self.expected_response: self.respond(len(self.hand)+i) did_respond = True break @@ -291,7 +292,7 @@ class Player: self.is_my_turn = True self.is_waiting_for_action = True self.has_played_bang = False - if any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]): + if not self.game.check_event(ce.Lazo) and any([isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) for c in self.equipment]): self.pending_action = PendingAction.PICK else: if isinstance(self.real_character, chd.VeraCuster): @@ -428,9 +429,12 @@ class Player: withCard = self.hand.pop(_with) if hand_index > _with else self.hand.pop(_with - 1) print(self.name, 'is playing ', card, ' against:', against, ' with:', _with) did_play_card = False - if not(against != None and isinstance(self.game.get_player_named(against).character, chd.ApacheKid) and card.suit == cs.Suit.DIAMONDS): + 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) + print('giudice', self.game.check_event(ce.IlGiudice), 'and', card.is_equipment, 'or (', card.usable_next_turn ,'and' ,not card.can_be_used_now) + print('lazo', (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 not card.is_equipment and not card.usable_next_turn: + if not card.is_equipment and not card.usable_next_turn or event_blocks_card: if did_play_card: self.game.deck.scrap(card) else: @@ -523,7 +527,7 @@ class Player: self.take_damage_response() return False else: - if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 or isinstance(self.character, chars.Jourdonnais): + if (not self.game.check_event(ce.Lazo) and len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0) or isinstance(self.character, chars.Jourdonnais): print('has barrel') self.pending_action = PendingAction.PICK self.on_pick_cb = self.barrel_pick @@ -531,7 +535,7 @@ class Player: 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): + 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_not_green if isinstance(self.character, chd.ElenaFuente): self.expected_response = self.game.deck.all_cards_str @@ -644,6 +648,8 @@ class Player: range += card.range else: aim += card.sight_mod + if self.game.check_event(ce.Lazo): + return 1 + self.character.sight_mod return max(1, range) + aim + self.character.sight_mod def get_visibility(self): @@ -652,6 +658,8 @@ class Player: covers = 0 for card in self.equipment: covers += card.vis_mod + if self.game.check_event(ce.Lazo): + return self.character.visibility_mod return self.character.visibility_mod + covers def scrap(self, card_index): @@ -678,6 +686,12 @@ 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): + 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() + return self.is_my_turn = False for i in range(len(self.equipment)): if self.equipment[i].usable_next_turn and not self.equipment[i].can_be_used_now: diff --git a/frontend/src/components/Lobby.vue b/frontend/src/components/Lobby.vue index 4b8c426..66087ba 100644 --- a/frontend/src/components/Lobby.vue +++ b/frontend/src/components/Lobby.vue @@ -22,6 +22,7 @@ + {{getActionEmoji(p)}}