cardAgainst, ragTime

This commit is contained in:
Alberto Xamin 2020-11-26 22:48:58 +01:00
parent a141e985da
commit 3772d3cbf9
No known key found for this signature in database
GPG Key ID: 4F026F48309500A2
6 changed files with 68 additions and 34 deletions

1
.gitignore vendored
View File

@ -138,3 +138,4 @@ dmypy.json
cython_debug/ cython_debug/
frontend/package-lock.json frontend/package-lock.json
bang-workspace.code-workspace

View File

@ -90,58 +90,58 @@ def join_room(sid, room):
@sio.event @sio.event
def chat_message(sid, msg): def chat_message(sid, msg):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}') sio.emit('chat_message', room=ses.game.name, data=f'[{ses.name}]: {msg}')
@sio.event @sio.event
def start_game(sid): def start_game(sid):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.game.start_game() ses.game.start_game()
advertise_lobbies() advertise_lobbies()
@sio.event @sio.event
def set_character(sid, name): def set_character(sid, name):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.set_character(name) ses.set_character(name)
@sio.event @sio.event
def refresh(sid): def refresh(sid):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.notify_self() ses.notify_self()
@sio.event @sio.event
def draw(sid, pile): def draw(sid, pile):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.draw(pile) ses.draw(pile)
@sio.event @sio.event
def pick(sid): def pick(sid):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.pick() ses.pick()
@sio.event @sio.event
def end_turn(sid): def end_turn(sid):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.end_turn() ses.end_turn()
@sio.event @sio.event
def play_card(sid, data): def play_card(sid, data):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.play_card(data['index'], data['against']) ses.play_card(data['index'], data['against'], data['with'])
@sio.event @sio.event
def respond(sid, data): def respond(sid, data):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.respond(data) ses.respond(data)
@sio.event @sio.event
def choose(sid, card_index): def choose(sid, card_index):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.choose(card_index) ses.choose(card_index)
@sio.event @sio.event
def scrap(sid, card_index): def scrap(sid, card_index):
ses = sio.get_session(sid) ses: Player = sio.get_session(sid)
ses.scrap(card_index) ses.scrap(card_index)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -35,13 +35,14 @@ class Card(ABC):
self.alt_text = f'{self.range} 🔍' self.alt_text = f'{self.range} 🔍'
self.desc = desc self.desc = desc
self.need_target = False self.need_target = False
self.need_with = False
def __str__(self): def __str__(self):
char = ['♦️', '♣️', '♥️', '♠️'][int(self.suit)] char = ['♦️', '♣️', '♥️', '♠️'][int(self.suit)]
return f'{self.name} {char}{self.number}' return f'{self.name} {char}{self.number}'
return super().__str__() return super().__str__()
def play_card(self, player, against):#self --> carta def play_card(self, player, against=None, _with=None):#self --> carta
if self.is_equipment: if self.is_equipment:
if self.is_weapon: if self.is_weapon:
has_weapon = False has_weapon = False
@ -106,7 +107,7 @@ class Prigione(Card):
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.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 self.need_target = True
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if against != None and not isinstance(player.game.get_player_named(against).role, r.Sheriff): if against != None and not isinstance(player.game.get_player_named(against).role, r.Sheriff):
player.sio.emit('chat_message', room=player.game.name, player.sio.emit('chat_message', room=player.game.name,
data=f'{self.name} ha giocato {self.name} contro {against}.') data=f'{self.name} ha giocato {self.name} contro {against}.')
@ -161,7 +162,7 @@ class Bang(Card):
self.desc = "Spara a un giocatore a distanta raggiungibile. Se non hai armi la distanza di default è 1" self.desc = "Spara a un giocatore a distanta raggiungibile. Se non hai armi la distanza di default è 1"
self.need_target = True self.need_target = True
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if player.has_played_bang and not any([isinstance(c, Volcanic) for c in player.equipment]) and against != None: if player.has_played_bang and not any([isinstance(c, Volcanic) for c in player.equipment]) and against != None:
return False return False
elif against != None: elif against != None:
@ -180,7 +181,7 @@ class Birra(Card):
self.icon = '🍺' self.icon = '🍺'
self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori" self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if len(player.game.players) != 2 and player.lives != player.max_lives: if len(player.game.players) != 2 and player.lives != player.max_lives:
super().play_card(player, against=against) super().play_card(player, against=against)
player.lives = min(player.lives+1, player.max_lives) player.lives = min(player.lives+1, player.max_lives)
@ -199,7 +200,7 @@ class CatBalou(Card):
self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco" 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 self.need_target = True
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0: if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0:
super().play_card(player, against=against) super().play_card(player, against=against)
from bang.players import PendingAction from bang.players import PendingAction
@ -217,7 +218,7 @@ class Diligenza(Card):
self.icon = '🚡' self.icon = '🚡'
self.desc = "Pesca 2 carte dalla cima del mazzo" self.desc = "Pesca 2 carte dalla cima del mazzo"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
super().play_card(player, against=against) super().play_card(player, against=against)
player.sio.emit('chat_message', room=player.game.name, player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha pescato 2 carte.') data=f'{player.name} ha giocato {self.name} e ha pescato 2 carte.')
@ -233,7 +234,7 @@ class Duello(Card):
self.icon = '⚔️' self.icon = '⚔️'
self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita" self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if against != None: if against != None:
super().play_card(player, against=against) super().play_card(player, against=against)
player.game.duel(player, against) player.game.duel(player, against)
@ -247,7 +248,7 @@ class Emporio(Card):
self.icon = '🏪' self.icon = '🏪'
self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano" self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
super().play_card(player, against=against) super().play_card(player, against=against)
player.game.emporio() player.game.emporio()
return True return True
@ -259,7 +260,7 @@ class Gatling(Card):
self.icon = '🛰' self.icon = '🛰'
self.desc = "Spara a tutti gli altri giocatori" self.desc = "Spara a tutti gli altri giocatori"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
super().play_card(player, against=against) super().play_card(player, against=against)
player.game.attack_others(player) player.game.attack_others(player)
return True return True
@ -271,7 +272,7 @@ class Indiani(Card):
self.icon = '🏹' self.icon = '🏹'
self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita" self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
super().play_card(player, against=against) super().play_card(player, against=against)
player.game.indian_others(player) player.game.indian_others(player)
return True return True
@ -283,7 +284,7 @@ class Mancato(Card):
self.icon = '😅' self.icon = '😅'
self.desc = "Usa questa carta per annullare un bang" self.desc = "Usa questa carta per annullare un bang"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
import bang.characters as chars import bang.characters as chars
if (not player.has_played_bang and against != None and isinstance(player.character, chars.CalamityJanet)): if (not player.has_played_bang and against != None and isinstance(player.character, chars.CalamityJanet)):
player.sio.emit('chat_message', room=player.game.name, player.sio.emit('chat_message', room=player.game.name,
@ -301,7 +302,7 @@ class Panico(Card):
self.need_target = True self.need_target = True
self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco" self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0: if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0:
super().play_card(player, against=against) super().play_card(player, against=against)
from bang.players import PendingAction from bang.players import PendingAction
@ -319,7 +320,7 @@ class Saloon(Card):
self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta" self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta"
self.icon = '🍻' self.icon = '🍻'
def play_card(self, player, against): def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name, player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha curato 1 punto vita a tutti.') data=f'{player.name} ha giocato {self.name} e ha curato 1 punto vita a tutti.')
for p in player.game.players: for p in player.game.players:
@ -334,7 +335,7 @@ class WellsFargo(Card):
self.desc = "Pesca 3 carte dalla cima del mazzo" self.desc = "Pesca 3 carte dalla cima del mazzo"
self.icon = '💸' self.icon = '💸'
def play_card(self, player, against): def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name, player.sio.emit('chat_message', room=player.game.name,
data=f'{player.name} ha giocato {self.name} e ha pescato 3 carte.') data=f'{player.name} ha giocato {self.name} e ha pescato 3 carte.')
for i in range(3): for i in range(3):

View File

@ -19,7 +19,7 @@ class Pugno(Card):
self.desc = "Spara a un giocatore a distanta 1" self.desc = "Spara a un giocatore a distanta 1"
self.need_target = True self.need_target = True
def play_card(self, player, against): def play_card(self, player, against, _with=None):
if against != None: if against != None:
import bang.characters as chars import bang.characters as chars
super().play_card(player, against=against) super().play_card(player, against=against)
@ -34,13 +34,28 @@ class Schivata(Mancato):
self.icon = '🙅‍♂️' self.icon = '🙅‍♂️'
self.desc += " e poi pesca una carta" self.desc += " e poi pesca una carta"
def play_card(self, player, against): def play_card(self, player, against, _with=None):
return False return False
def use_card(self, player): def use_card(self, player):
player.hand.append(player.game.deck.draw()) player.hand.append(player.game.deck.draw())
player.notify_self() player.notify_self()
class RagTime(Panico):
def __init__(self, suit, number):
Card.__init__(self, suit, 'Rag Time', number)
self.icon = '🎹'
self.desc = "Ruba 1 carta dalla mano di un giocatore"
self.need_target = True
self.need_with = True
def play_card(self, player, against, _with):
if against != None and _with != None:
player.game.deck.scrap(_with)
super().play_card(player, against=against)
return True
return False
def get_starting_deck() -> List[Card]: def get_starting_deck() -> List[Card]:
return [ return [
#TODO: aggiungere anche le carte normalmente presenti https://bang.dvgiochi.com/cardslist.php?id=3 #TODO: aggiungere anche le carte normalmente presenti https://bang.dvgiochi.com/cardslist.php?id=3
@ -65,4 +80,5 @@ def get_starting_deck() -> List[Card]:
Pugno(Suit.SPADES, 10), Pugno(Suit.SPADES, 10),
Schivata(Suit.DIAMONDS, 7), Schivata(Suit.DIAMONDS, 7),
Schivata(Suit.HEARTS, 'K'), Schivata(Suit.HEARTS, 'K'),
RagTime(Suit.HEARTS, 9)
] ]

View File

@ -248,18 +248,23 @@ class Player:
s += f"equipment {[str(c) for c in self.equipment]}" s += f"equipment {[str(c) for c in self.equipment]}"
return s return s
def play_card(self, hand_index: int, against=None): def play_card(self, hand_index: int, against=None, _with=None):
if not (0 <= hand_index < len(self.hand)): if not (0 <= hand_index < len(self.hand)):
print('illegal') print('illegal')
return return
card: cs.Card = self.hand.pop(hand_index) card: cs.Card = self.hand.pop(hand_index)
print(self.name, 'is playing ', card, ' against:', against) withCard: cs.Card = None
did_play_card = card.play_card(self, against) if _with:
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 = card.play_card(self, against, withCard)
if not card.is_equipment: if not card.is_equipment:
if did_play_card: if did_play_card:
self.game.deck.scrap(card) self.game.deck.scrap(card)
else: else:
self.hand.insert(hand_index, card) self.hand.insert(hand_index, card)
if withCard:
self.hand.insert(_with, withCard)
self.notify_self() self.notify_self()
def choose(self, card_index): def choose(self, card_index):

View File

@ -32,8 +32,9 @@
<Chooser v-if="win_status !== undefined" :text="win_status?'HAI VINTO':'HAI PERSO'" /> <Chooser v-if="win_status !== undefined" :text="win_status?'HAI VINTO':'HAI PERSO'" />
<Chooser v-if="show_role" text="Tu sei" :cards="[my_role]" :hintText="my_role.goal" :select="() => {show_role=false}" :cancel="() => {show_role=false}" cancelText="OK" /> <Chooser v-if="show_role" text="Tu sei" :cards="[my_role]" :hintText="my_role.goal" :select="() => {show_role=false}" :cancel="() => {show_role=false}" cancelText="OK" />
<Chooser v-if="notifycard" :key="notifycard.card" :text="`${notifycard.player} ha pescato come seconda carta:`" :cards="[notifycard.card]" hintText="Se la carta è cuori o quadri ne pesca un'altra" class="turn-notify-4s"/> <Chooser v-if="notifycard" :key="notifycard.card" :text="`${notifycard.player} ha pescato come seconda carta:`" :cards="[notifycard.card]" hintText="Se la carta è cuori o quadri ne pesca un'altra" class="turn-notify-4s"/>
<Chooser v-if="!show_role && is_my_turn" text="GIOCA IL TUO TURNO" :key="is_my_turn" class="turn-notify" /> <Chooser v-if="!show_role && is_my_turn && pending_action < 2" text="GIOCA IL TUO TURNO" :key="is_my_turn" class="turn-notify" />
<Chooser v-if="hasToPickResponse" :text="`ESTRAI UNA CARTA ${attacker?('PER DIFENDERTI DA '+attacker):''}`" :key="hasToPickResponse" class="turn-notify" /> <Chooser v-if="hasToPickResponse" :text="`ESTRAI UNA CARTA ${attacker?('PER DIFENDERTI DA '+attacker):''}`" :key="hasToPickResponse" class="turn-notify" />
<Chooser v-if="!card_against && card_with" :text="`SCEGLI CHE CARTA SCARTARE PER GIOCCARE ${card_with.name}`" :cards="hand.filter(x => x !== card_with)" :select="selectWith" :cancel="()=>{card_with = null}"/>
<Chooser v-if="showScrapScreen" :text="`SCARTA ${hand.length}/${lives}`" :cards="hand" :select="scrap" :cancel="cancelEndingTurn"/> <Chooser v-if="showScrapScreen" :text="`SCARTA ${hand.length}/${lives}`" :cards="hand" :select="scrap" :cancel="cancelEndingTurn"/>
<Chooser v-if="sidWantsScrapForHealth && sidScrapForHealth.length < 2" :text="`SCARTA ${2 - sidScrapForHealth.length} PER RECUPERARE 1 VITA`" <Chooser v-if="sidWantsScrapForHealth && sidScrapForHealth.length < 2" :text="`SCARTA ${2 - sidScrapForHealth.length} PER RECUPERARE 1 VITA`"
:cards="sidScrapHand" :select="sidScrap" :cancel="() => {sidWantsScrapForHealth = false;sidScrapForHealth=[]}"/> :cards="sidScrapHand" :select="sidScrap" :cancel="() => {sidWantsScrapForHealth = false;sidScrapForHealth=[]}"/>
@ -66,6 +67,7 @@ export default {
hint: '', hint: '',
pending_action: null, pending_action: null,
card_against: null, card_against: null,
card_with: null,
has_played_bang: false, has_played_bang: false,
playersDistances: [], playersDistances: [],
is_my_turn: false, is_my_turn: false,
@ -195,7 +197,9 @@ export default {
let calamity_special = (card.name === 'Mancato!' && this.character.name === 'Calamity Janet') let calamity_special = (card.name === 'Mancato!' && this.character.name === 'Calamity Janet')
let cant_play_bang = (this.has_played_bang && this.equipment.filter(x => x.name == 'Volcanic').length == 0) let cant_play_bang = (this.has_played_bang && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
if (this.pending_action == 2) { if (this.pending_action == 2) {
if ((card.need_target || calamity_special) && !((card.name == 'Bang!' || (calamity_special && card.name=='Mancato!')) && cant_play_bang)) { if (card.need_with && !this.card_with) {
this.card_with = card
} else if ((card.need_target || calamity_special) && !((card.name == 'Bang!' || (calamity_special && card.name=='Mancato!')) && cant_play_bang)) {
if (card.name == 'Bang!' || calamity_special) if (card.name == 'Bang!' || calamity_special)
this.range = this.sight this.range = this.sight
else else
@ -217,14 +221,21 @@ export default {
this.really_play_card(this.card_against, player.name) this.really_play_card(this.card_against, player.name)
this.card_against = null this.card_against = null
}, },
selectWith(card) {
this.card_against = this.card_with
this.card_with = card
},
cancelCardAgainst() { cancelCardAgainst() {
this.card_against = null this.card_against = null
this.card_with = null
}, },
really_play_card(card, against) { really_play_card(card, against) {
let card_data = { let card_data = {
index: this.hand.indexOf(card), index: this.hand.indexOf(card),
against: against against: against,
with: this.hand.indexOf(this.card_with),
} }
this.card_with = null
console.log(card_data) console.log(card_data)
this.$socket.emit('play_card', card_data) this.$socket.emit('play_card', card_data)
}, },