bang-mancato
This commit is contained in:
parent
d861a1869a
commit
1e98d4a1dd
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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)]
|
||||
|
@ -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:
|
||||
|
@ -92,8 +92,7 @@ export default {
|
||||
return {
|
||||
name: lobby.name,
|
||||
icon: "💥",
|
||||
number: lobby.players,
|
||||
suit: '🤠',
|
||||
number: `${lobby.players}🤠`,
|
||||
is_equipment: true,
|
||||
}
|
||||
},
|
||||
|
@ -2,6 +2,7 @@
|
||||
<div :class="{ card: true, equipment: card.is_equipment, character:card.is_character }">
|
||||
<h4>{{card.name}}</h4>
|
||||
<div class="emoji">{{card.icon}}</div>
|
||||
<div v-if="card.is_character" class="alt_text">{{card.alt_text}}</div>
|
||||
<div class="suit">{{card.number}}{{suit}}</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -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;
|
||||
}
|
||||
</style>
|
@ -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')
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Lobby: {{ lobbyName }}</h1>
|
||||
<h3>Giocatori</h3>
|
||||
<h3>Giocatori (tu sei {{username}})</h3>
|
||||
<div style="display:flex">
|
||||
<!-- <div style="position: relative;width:260pt;height:400pt;"> -->
|
||||
<Card v-for="p in playersTable" v-bind:key="p.card.name" :card="p.card"/>
|
||||
@ -68,7 +68,7 @@ export default {
|
||||
console.log('received visibility update')
|
||||
console.log(vis)
|
||||
this.players = JSON.parse(vis)
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
startGameCard() {
|
||||
@ -100,7 +100,8 @@ export default {
|
||||
return {
|
||||
name: player.name,
|
||||
number: ((this.username == player.name) ? 'YOU' : (this.players[0].name == player.name) ? 'OWNER' :'') + (player.dist ? `${player.dist}⛰` : ''),
|
||||
icon: '🤠',
|
||||
icon: (player.lives === undefined || player.lives > 0) ? '🤠' : '☠️',
|
||||
alt_text: player.lives !== undefined ? Array(player.lives).join('❤️')+Array(player.max_lives-player.lives).join('💀') : '',
|
||||
is_character: true,
|
||||
}
|
||||
},
|
||||
|
@ -18,16 +18,20 @@
|
||||
</transition-group>
|
||||
</div>
|
||||
<p>{{hint}}</p>
|
||||
<Chooser v-if="card_against" text="Contro chi vuoi giocare la carta" :cards="visiblePlayers" :select="selectAgainst"/>
|
||||
<Chooser v-if="pending_action == 3" text="Scegli come rispondere" :cards="respondCards" :select="respond"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Card from '@/components/Card.vue'
|
||||
import Chooser from '@/components/Chooser.vue'
|
||||
|
||||
export default {
|
||||
name: 'Player',
|
||||
components: {
|
||||
Card
|
||||
Card,
|
||||
Chooser,
|
||||
},
|
||||
data: () => ({
|
||||
my_role: null,
|
||||
@ -37,7 +41,9 @@ export default {
|
||||
lives: 0,
|
||||
max_lives: 0,
|
||||
hint: '',
|
||||
pending_action: null
|
||||
pending_action: null,
|
||||
card_against: null,
|
||||
visiblePlayers: []
|
||||
}),
|
||||
sockets: {
|
||||
role(role) {
|
||||
@ -52,7 +58,18 @@ export default {
|
||||
this.equipment = self.equipment
|
||||
this.lives = self.lives
|
||||
this.max_lives = self.max_lives
|
||||
}
|
||||
},
|
||||
self_vis(vis) {
|
||||
console.log('received visibility update')
|
||||
console.log(vis)
|
||||
this.visiblePlayers = JSON.parse(vis).map(player => {
|
||||
return {
|
||||
name: player.name,
|
||||
number: player.dist !== undefined ? `${player.dist}⛰` : '',
|
||||
icon: '🤠',
|
||||
is_character: true,
|
||||
}})
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
instruction() {
|
||||
@ -64,6 +81,17 @@ export default {
|
||||
canEndTurn() {
|
||||
return (this.pending_action == 2 && this.hand.length <= this.lives)
|
||||
},
|
||||
respondCards() {
|
||||
let cc = [{
|
||||
name: 'Prendi Danno',
|
||||
icon: '❌',
|
||||
is_equipment: true,
|
||||
}]
|
||||
this.hand.filter(x => x.name == 'Mancato!').forEach(x=>{
|
||||
cc.push(x)
|
||||
})
|
||||
return cc
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
end_turn(){
|
||||
@ -72,14 +100,28 @@ export default {
|
||||
},
|
||||
play_card(card) {
|
||||
if (this.pending_action == 2) {
|
||||
let card_data = {
|
||||
index: this.hand.indexOf(card),
|
||||
against: null
|
||||
if (card.need_target) {
|
||||
this.card_against = card
|
||||
} else {
|
||||
this.really_play_card(card, null)
|
||||
}
|
||||
console.log(card_data)
|
||||
this.$socket.emit('play_card', card_data)
|
||||
}
|
||||
},
|
||||
respond(card) {
|
||||
this.$socket.emit('respond', this.hand.indexOf(card))
|
||||
},
|
||||
selectAgainst(player) {
|
||||
this.really_play_card(this.card_against, player.name)
|
||||
this.card_against = null
|
||||
},
|
||||
really_play_card(card, against) {
|
||||
let card_data = {
|
||||
index: this.hand.indexOf(card),
|
||||
against: against
|
||||
}
|
||||
console.log(card_data)
|
||||
this.$socket.emit('play_card', card_data)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.emit('refresh')
|
||||
|
Loading…
Reference in New Issue
Block a user