From 1e98d4a1ddeee717c44e71cbdfd0aba05d7623bb Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 21 Nov 2020 12:19:20 +0100 Subject: [PATCH] bang-mancato --- backend/__init__.py | 10 +++ backend/bot.py | 0 backend/cards.py | 5 ++ backend/deck.py | 1 + backend/game.py | 21 ++++- backend/players.py | 132 +++++++++++++++++++++-------- frontend/src/App.vue | 3 +- frontend/src/components/Card.vue | 14 +++ frontend/src/components/Deck.vue | 2 +- frontend/src/components/Lobby.vue | 7 +- frontend/src/components/Player.vue | 58 +++++++++++-- 11 files changed, 204 insertions(+), 49 deletions(-) delete mode 100644 backend/bot.py diff --git a/backend/__init__.py b/backend/__init__.py index 3bebecc..1da2cd3 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -81,6 +81,11 @@ def draw(sid): ses = sio.get_session(sid) ses.draw() +@sio.event +def pick(sid): + ses = sio.get_session(sid) + ses.pick() + @sio.event def end_turn(sid): ses = sio.get_session(sid) @@ -91,5 +96,10 @@ def play_card(sid, data): ses = sio.get_session(sid) ses.play_card(data['index'], data['against']) +@sio.event +def respond(sid, data): + ses = sio.get_session(sid) + ses.respond(data) + if __name__ == '__main__': eventlet.wsgi.server(eventlet.listen(('', 5001)), app) diff --git a/backend/bot.py b/backend/bot.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/cards.py b/backend/cards.py index 6473a34..03a577f 100644 --- a/backend/cards.py +++ b/backend/cards.py @@ -29,6 +29,7 @@ class Card(ABC): self.sight_mod = sight_mod self.range = range self.desc = desc + self.need_target = False def __str__(self): char = ['♦️','♣️','♥️','♠️'][int(self.suit)] @@ -64,6 +65,7 @@ class Prigione(Card): super().__init__(suit, 'Prigione', number, is_equipment=False) self.icon = '⛓' self.desc = "Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno" + self.need_target = True class Remington(Card): def __init__(self, suit, number): @@ -100,6 +102,7 @@ class Bang(Card): super().__init__(suit, 'Bang!', number) self.icon = '💥' self.desc = "Spara a un giocatore a distanta raggiungibile. Se non hai armi la distanza di default è 1" + self.need_target = True class Birra(Card): def __init__(self, suit, number): @@ -112,6 +115,7 @@ class CatBalou(Card): super().__init__(suit, 'Cat Balou', number) self.icon = '💃' self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco" + self.need_target = True class Diligenza(Card): def __init__(self, suit, number): @@ -148,6 +152,7 @@ class Panico(Card): def __init__(self, suit, number): super().__init__(suit, 'Panico!', number, range=1) self.icon = '😱' + self.need_target = True class Saloon(Card): def __init__(self, suit, number): diff --git a/backend/deck.py b/backend/deck.py index c0b068f..1b5a838 100644 --- a/backend/deck.py +++ b/backend/deck.py @@ -23,6 +23,7 @@ class Deck: def pick_and_scrap(self) -> Card: card = self.cards.pop(0) self.scrap_pile.append(card) + self.game.notify_scrap_pile() return card def draw(self) -> Card: diff --git a/backend/game.py b/backend/game.py index f0c4e77..b0e2ffd 100644 --- a/backend/game.py +++ b/backend/game.py @@ -4,6 +4,7 @@ import socketio import players from characters import all_characters from deck import Deck +from players import Player import roles class Game: @@ -25,6 +26,7 @@ class Game: return True self.sio.emit('room', room=self.name, data={'name': self.name, 'started': self.started, 'players': [p.name for p in self.players]}) self.sio.emit('chat_message', room=self.name, data=f'{player.name} si è disconnesso.') + self.players_map = {c.name: i for i, c in enumerate(self.players)} return False def add_player(self, player: players.Player): @@ -50,6 +52,7 @@ class Game: print('GAME IS STARING') if self.started: return + self.players_map = {c.name: i for i, c in enumerate(self.players)} self.sio.emit('chat_message', room=self.name, data=f'La partita sta iniziando...') self.sio.emit('start', room=self.name) self.started = True @@ -74,8 +77,22 @@ class Game: def get_visible_players(self, player): i = self.players.index(player) sight = player.get_sight() - return [{'name': self.players[j].name, 'dist': min(abs(i - j) - 1, abs(i - len(self.players) - j)) + self.players[j].get_visibility()} - for j in range(len(self.players)) if i != j and min(abs(i - j) - 1, abs(i - len(self.players) - j)) + self.players[j].get_visibility() <= sight] + return [{ + 'name': self.players[j].name, + 'dist': min(abs(i - j), abs(i - len(self.players) - j)) + self.players[j].get_visibility(), + 'lives': self.players[j].lives, + 'max_lives': self.players[j].max_lives, + } for j in range(len(self.players)) if i != j] + + def attack(self, attacker:Player, target_username:str): + self.sio.emit('chat_message', room=self.name, data=f'{attacker.name} ha fatto Bang contro {target_username}.') + if self.players[self.players_map[target_username]].get_banged(): + attacker.pending_action = players.PendingAction.WAIT + attacker.notify_self() + + def responders_did_respond(self): + self.players[self.turn].pending_action = players.PendingAction.PLAY + self.players[self.turn].notify_self() def next_player(self): return self.players[(self.turn + 1) % len(self.players)] diff --git a/backend/players.py b/backend/players.py index 8b86e8e..99f2c9c 100644 --- a/backend/players.py +++ b/backend/players.py @@ -1,6 +1,7 @@ from enum import IntEnum import json import socketio +from cards import Mancato import roles import cards @@ -32,6 +33,9 @@ class Player: self.pending_action: PendingAction = None self.available_characters = [] self.was_shot = False + self.on_pick_cb = None + self.on_response_cb = None + self.expected_response = None def join_game(self, game): self.game = game @@ -69,6 +73,9 @@ class Player: ser.pop('game') ser.pop('sio') ser.pop('sid') + ser.pop('on_pick_cb') + ser.pop('on_response_cb') + ser.pop('expected_response') self.sio.emit('self', room=self.sid, data=json.dumps(ser, default=lambda o: o.__dict__)) self.sio.emit('self_vis', room=self.sid, data=json.dumps(self.game.get_visible_players(self), default=lambda o: o.__dict__)) @@ -84,46 +91,51 @@ class Player: self.pending_action = PendingAction.DRAW self.notify_self() - # # print(f'lives: {self.lives}/{self.max_lives} hand: {[str(c) for c in self.hand]}') - # print(f'I {self.name} can see {[p.get_public_description() for p in self.game.get_visible_players(self)]}') - # ser = self.__dict__.copy() - # ser.pop('game') - # print(json.dumps(ser, default=lambda o: o.__dict__, indent=4)) def draw(self): + if self.pending_action != PendingAction.DRAW: + return for i in range(2): self.hand.append(self.game.deck.draw()) self.pending_action = PendingAction.PLAY self.notify_self() def pick(self): + if self.pending_action != PendingAction.PICK: + return pickable_cards = 1 + self.character.pick_mod - for i in range(len(self.equipment)): - if isinstance(self.equipment[i], cards.Dinamite): - while pickable_cards > 0: - pickable_cards -= 1 - picked: cards.Card = self.game.deck.pick_and_scrap() - print(f'Did pick {picked}') - if picked.suit == cards.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0: - self.lives -= 3 - self.game.deck.scrap(self.equipment.pop(i)) - print(f'{self.name} Boom, -3 hp') - else: - self.game.next_player().equipment.append(self.equipment.pop(i)) - if any([isinstance(c, cards.Dinamite) or isinstance(c, cards.Prigione) for c in self.equipment]): - return - for i in range(len(self.equipment)): - if isinstance(self.equipment[i], cards.Prigione): - while pickable_cards > 0: - pickable_cards -= 1 - picked: cards.Card = self.game.deck.pick_and_scrap() - print(f'Did pick {picked}') - if picked.suit != cards.Suit.HEARTS and pickable_cards == 0: - self.game.deck.scrap(self.equipment.pop(i)) - self.end_turn(forced=True) - else: - break - break - self.pending_action = PendingAction.DRAW + if self.is_my_turn: + for i in range(len(self.equipment)): + if isinstance(self.equipment[i], cards.Dinamite): + while pickable_cards > 0: + pickable_cards -= 1 + picked: cards.Card = self.game.deck.pick_and_scrap() + print(f'Did pick {picked}') + if picked.suit == cards.Suit.SPADES and 2 <= picked.number <= 9 and pickable_cards == 0: + self.lives -= 3 + self.game.deck.scrap(self.equipment.pop(i)) + print(f'{self.name} Boom, -3 hp') + else: + self.game.next_player().equipment.append(self.equipment.pop(i)) + self.game.next_player().notify_self() + if any([isinstance(c, cards.Dinamite) or isinstance(c, cards.Prigione) for c in self.equipment]): + self.notify_self() + return + for i in range(len(self.equipment)): + if isinstance(self.equipment[i], cards.Prigione): + while pickable_cards > 0: + pickable_cards -= 1 + picked: cards.Card = self.game.deck.pick_and_scrap() + print(f'Did pick {picked}') + if picked.suit != cards.Suit.HEARTS and pickable_cards == 0: + self.game.deck.scrap(self.equipment.pop(i)) + self.end_turn(forced=True) + else: + break + break + self.pending_action = PendingAction.DRAW + self.notify_self() + else: + self.on_pick_cb() def get_playable_cards(self): playable_cards = [] @@ -163,10 +175,64 @@ class Player: self.equipment.append(card) else: if isinstance(card, cards.Bang) and self.has_played_bang and not any([isinstance(c, cards.Volcanic) for c in self.equipment]): - print('you retard') + return + if isinstance(card, cards.Bang) and againts != None: + self.game.attack(self, againts) self.game.deck.scrap(card) self.notify_self() + def barrel_pick(self): + pickable_cards = 1 + self.character.pick_mod + while pickable_cards > 0: + pickable_cards -= 1 + picked: cards.Card = self.game.deck.pick_and_scrap() + print(f'Did pick {picked}') + if picked.suit == cards.Suit.HEARTS: + self.pending_action = PendingAction.WAIT + self.notify_self() + self.game.responders_did_respond() + return + if len([c for c in self.hand if isinstance(c, cards.Mancato)]) == 0: + self.take_damage_response() + self.game.responders_did_respond() + else: + self.pending_action = PendingAction.RESPOND + self.expected_response = cards.Mancato + self.on_response_cb = self.take_damage_response() + self.notify_self() + + def get_banged(self): + if len([c for c in self.hand if isinstance(c, cards.Mancato) or isinstance(c, cards.Barile)]) == 0: + print('Cant defend') + self.take_damage_response() + return False + else: + if len([c for c in self.hand if isinstance(c, cards.Barile)]) > 0: + print('has barrel') + self.pending_action = PendingAction.PICK + self.on_pick_cb = self.barrel_pick + else: + print('has mancato') + self.pending_action = PendingAction.RESPOND + self.expected_response = cards.Mancato + self.on_response_cb = self.take_damage_response() + self.notify_self() + return True + + def take_damage_response(self): + self.lives -= 1 + self.notify_self() + + def respond(self, hand_index): + self.pending_action = PendingAction.WAIT + if hand_index != -1 and isinstance(self.hand[hand_index], self.expected_response): + self.game.deck.scrap(self.hand.pop(hand_index)) + self.notify_self() + self.game.responders_did_respond() + else: + self.on_response_cb() + self.game.responders_did_respond() + def get_sight(self): aim = 0 for card in self.equipment: diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 0f0feef..fa6062c 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -92,8 +92,7 @@ export default { return { name: lobby.name, icon: "💥", - number: lobby.players, - suit: '🤠', + number: `${lobby.players}🤠`, is_equipment: true, } }, diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue index b6ec7ff..c2b549c 100644 --- a/frontend/src/components/Card.vue +++ b/frontend/src/components/Card.vue @@ -2,6 +2,7 @@

{{card.name}}

{{card.icon}}
+
{{card.alt_text}}
{{card.number}}{{suit}}
@@ -86,4 +87,17 @@ export default { bottom: 3pt; left:3pt; } +.card.character .suit { + font-size: x-small; + right: 3pt; + text-align: center; +} +.card.character .alt_text { + right: 3pt; + text-align: center; + position: absolute; + font-size: small; + bottom: 16pt; + left: 3pt; +} \ No newline at end of file diff --git a/frontend/src/components/Deck.vue b/frontend/src/components/Deck.vue index b838110..a6f9cf9 100644 --- a/frontend/src/components/Deck.vue +++ b/frontend/src/components/Deck.vue @@ -36,7 +36,7 @@ export default { }, methods: { action() { - if (this.pending_action && this.pending_action < 2) { + if (this.pending_action !== false && this.pending_action < 2) { console.log('action') if (this.pending_action == 0) this.$socket.emit('pick') diff --git a/frontend/src/components/Lobby.vue b/frontend/src/components/Lobby.vue index e5be4df..e3f8a0f 100644 --- a/frontend/src/components/Lobby.vue +++ b/frontend/src/components/Lobby.vue @@ -1,7 +1,7 @@