This commit is contained in:
Alberto Xamin 2023-05-04 09:22:47 +02:00 committed by Alberto Xamin
parent 1ee92afb9a
commit 14534997e8
7 changed files with 216 additions and 139 deletions

View File

@ -371,14 +371,18 @@ class Birra(Card):
player.game.deck.draw(True, player=p) player.game.deck.draw(True, player=p)
p.notify_self() p.notify_self()
if "gold_rush" in player.game.expansions and self.number != 42: if "gold_rush" in player.game.expansions and self.number != 42:
from bang.players import PendingAction player.set_choose_action(
"choose_birra_function",
player.available_cards = [ [
{"name": "Pepita", "icon": "💵️", "alt_text": "1", "noDesc": True}, {
self, "name": "Pepita",
] "icon": "💵️",
player.choose_text = "choose_birra_function" "alt_text": "1",
player.pending_action = PendingAction.CHOOSE "noDesc": True,
},
self,
],
)
player.notify_self() player.notify_self()
return True return True
if ( if (

View File

@ -60,11 +60,7 @@ class Lemat(Card):
for p in player.game.get_visible_players(player) for p in player.game.get_visible_players(player)
) )
): ):
from bang.players import PendingAction player.set_choose_action("choose_play_as_bang", player.hand.copy())
player.available_cards = player.hand.copy()
player.pending_action = PendingAction.CHOOSE
player.choose_text = "choose_play_as_bang"
player.notify_self() player.notify_self()
return False return False

View File

@ -21,12 +21,11 @@ class BlackFlower(Character):
for p in player.game.get_visible_players(player) for p in player.game.get_visible_players(player)
) )
) and super().special(player, data): ) and super().special(player, data):
from bang.players import PendingAction
player.available_cards = [c for c in player.hand if c.suit == cs.Suit.CLUBS]
player.special_use_count += 1 player.special_use_count += 1
player.pending_action = PendingAction.CHOOSE player.set_choose_action(
player.choose_text = "choose_play_as_bang" "choose_play_as_bang",
[c for c in player.hand if c.suit == cs.Suit.CLUBS],
)
player.notify_self() player.notify_self()

View File

@ -1,5 +1,9 @@
from typing import TYPE_CHECKING
import bang.cards as cs import bang.cards as cs
if TYPE_CHECKING:
from bang.players import Player
class StationCard: class StationCard:
def __init__(self, name: str): def __init__(self, name: str):
@ -7,8 +11,9 @@ class StationCard:
self.expansion = "train_robbery" self.expansion = "train_robbery"
self.price: list[dict] = [] self.price: list[dict] = []
def card_check(self, card: cs.Card): def check_price(self, player: "Player") -> bool:
"""Check if the card can be used to rob the train""" """Check if the card can be used to rob the train"""
return len(player.hand) > 0
class BoomTown(StationCard): class BoomTown(StationCard):
@ -18,8 +23,11 @@ class BoomTown(StationCard):
super().__init__("Boom Town") super().__init__("Boom Town")
self.price = [cs.Bang(0, 0).__dict__] self.price = [cs.Bang(0, 0).__dict__]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return isinstance(card, cs.Bang) if super().check_price(player) and all(
not isinstance(c, cs.Bang) for c in player.hand
):
return False
class Caticor(StationCard): class Caticor(StationCard):
@ -29,8 +37,12 @@ class Caticor(StationCard):
super().__init__("Caticor") super().__init__("Caticor")
self.price = [cs.CatBalou(0, 0).__dict__, cs.Panico(0, 0).__dict__] self.price = [cs.CatBalou(0, 0).__dict__, cs.Panico(0, 0).__dict__]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return isinstance(card, cs.CatBalou) or isinstance(card, cs.Panico) if super().check_price(player) and all(
not (isinstance(card, cs.CatBalou) or isinstance(card, cs.Panico))
for card in player.hand
):
return False
class CreepyCreek(StationCard): class CreepyCreek(StationCard):
@ -40,8 +52,11 @@ class CreepyCreek(StationCard):
super().__init__("Creepy Creek") super().__init__("Creepy Creek")
self.price = [{"icon": "♠️"}] self.price = [{"icon": "♠️"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.suit == cs.Suit.SPADES if super().check_price(player) and all(
card.suit != cs.Suit.SPADES for card in player.hand
):
return False
class CrownsHole(StationCard): class CrownsHole(StationCard):
@ -51,8 +66,11 @@ class CrownsHole(StationCard):
super().__init__("Crown's Hole") super().__init__("Crown's Hole")
self.price = [cs.Birra(0, 0).__dict__] self.price = [cs.Birra(0, 0).__dict__]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return isinstance(card, cs.Birra) if super().check_price(player) and all(
not isinstance(card, cs.Birra) for card in player.hand
):
return False
class Deadwood(StationCard): class Deadwood(StationCard):
@ -62,8 +80,11 @@ class Deadwood(StationCard):
super().__init__("Deadwood") super().__init__("Deadwood")
self.price = [{"is_equipment": True}] self.price = [{"is_equipment": True}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.is_equipment if super().check_price(player) and all(
not card.is_equipment for card in player.hand
):
return False
class Dodgeville(StationCard): class Dodgeville(StationCard):
@ -73,8 +94,11 @@ class Dodgeville(StationCard):
super().__init__("Dodgeville") super().__init__("Dodgeville")
self.price = [cs.Mancato(0, 0).__dict__] self.price = [cs.Mancato(0, 0).__dict__]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return isinstance(card, cs.Mancato) if super().check_price(player) and all(
not isinstance(card, cs.Mancato) for card in player.hand
):
return False
class FortWorth(StationCard): class FortWorth(StationCard):
@ -84,8 +108,11 @@ class FortWorth(StationCard):
super().__init__("Fort Worth") super().__init__("Fort Worth")
self.price = [{"icon": "10\nJ\nQ\nK\nA"}] self.price = [{"icon": "10\nJ\nQ\nK\nA"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.number in {1, 10, 11, 12, 13} if super().check_price(player) and all(
card.number not in {1, 10, 11, 12, 13} for card in player.hand
):
return False
class Frisco(StationCard): class Frisco(StationCard):
@ -95,8 +122,11 @@ class Frisco(StationCard):
super().__init__("Frisco") super().__init__("Frisco")
self.price = [{"icon": "♣️"}] self.price = [{"icon": "♣️"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.suit == cs.Suit.CLUBS if super().check_price(player) and all(
card.suit != cs.Suit.CLUBS for card in player.hand
):
return False
class MinersOath(StationCard): class MinersOath(StationCard):
@ -106,8 +136,11 @@ class MinersOath(StationCard):
super().__init__("Miner's Oath") super().__init__("Miner's Oath")
self.price = [{"icon": "♦️"}] self.price = [{"icon": "♦️"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.suit == cs.Suit.DIAMONDS if super().check_price(player) and all(
card.suit != cs.Suit.DIAMONDS for card in player.hand
):
return False
class SanTafe(StationCard): class SanTafe(StationCard):
@ -117,8 +150,11 @@ class SanTafe(StationCard):
super().__init__("San Tafe") super().__init__("San Tafe")
self.price = [{"icon": "♥️"}] self.price = [{"icon": "♥️"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return card.suit == cs.Suit.HEARTS if super().check_price(player) and all(
card.suit != cs.Suit.HEARTS for card in player.hand
):
return False
class Tombrock(StationCard): class Tombrock(StationCard):
@ -128,8 +164,9 @@ class Tombrock(StationCard):
super().__init__("Tombrock") super().__init__("Tombrock")
self.price = [{"icon": "💔"}] self.price = [{"icon": "💔"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return True if player.lives <= 1:
return False
class Yooma(StationCard): class Yooma(StationCard):
@ -139,8 +176,11 @@ class Yooma(StationCard):
super().__init__("Yooma") super().__init__("Yooma")
self.price = [{"icon": "2-9"}] self.price = [{"icon": "2-9"}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return 2 <= card.number <= 9 if super().check_price(player) and all(
not (2 <= card.number <= 9) for card in player.hand
):
return False
class VirginiaTown(StationCard): class VirginiaTown(StationCard):
@ -150,8 +190,9 @@ class VirginiaTown(StationCard):
super().__init__("Virginia Town") super().__init__("Virginia Town")
self.price = [{}, {}] self.price = [{}, {}]
def card_check(self, card: cs.Card): def check_price(self, player: "Player"):
return True if super().check_price(player) and len(player.hand < 2):
return False
def get_all_stations(): def get_all_stations():

View File

@ -17,6 +17,8 @@ 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 bang.expansions.the_valley_of_shadows.cards as tvosc
import bang.expansions.the_valley_of_shadows.characters as tvosch import bang.expansions.the_valley_of_shadows.characters as tvosch
import bang.expansions.train_robbery.stations as trs
import bang.expansions.train_robbery.trains as trt
from typing import List, TYPE_CHECKING from typing import List, TYPE_CHECKING
from metrics import Metrics from metrics import Metrics
from globals import G from globals import G
@ -280,25 +282,25 @@ class Player:
if self.pending_action == PendingAction.DRAW and self.game.check_event( if self.pending_action == PendingAction.DRAW and self.game.check_event(
ce.Peyote ce.Peyote
): ):
self.available_cards = [
{"icon": "🔴", "noDesc": True},
{"icon": "", "noDesc": True},
]
self.is_drawing = True self.is_drawing = True
self.choose_text = "choose_guess" self.set_choose_action(
self.pending_action = PendingAction.CHOOSE "choose_guess",
[
{"icon": "🔴", "noDesc": True},
{"icon": "", "noDesc": True},
],
)
elif ( elif (
self.can_play_ranch self.can_play_ranch
and self.pending_action == PendingAction.PLAY and self.pending_action == PendingAction.PLAY
and self.game.check_event(ce.Ranch) and self.game.check_event(ce.Ranch)
): ):
self.can_play_ranch = False self.can_play_ranch = False
self.available_cards = [c for c in self.hand]
self.discarded_cards = [] self.discarded_cards = []
self.available_cards.append({"icon": "", "noDesc": True})
self.is_playing_ranch = True self.is_playing_ranch = True
self.choose_text = "choose_ranch" self.set_choose_action(
self.pending_action = PendingAction.CHOOSE "choose_ranch", [c for c in self.hand] + [{"icon": "", "noDesc": True}]
)
elif ( elif (
self.character self.character
and self.character.check(self.game, chars.SuzyLafayette) and self.character.check(self.game, chars.SuzyLafayette)
@ -338,9 +340,7 @@ class Player:
self.game.players[self.game.turn].notify_self() self.game.players[self.game.turn].notify_self()
self.scrapped_cards = 0 self.scrapped_cards = 0
self.previous_pending_action = self.pending_action self.previous_pending_action = self.pending_action
self.pending_action = PendingAction.CHOOSE self.set_choose_action("choose_sid_scrap", self.hand)
self.choose_text = "choose_sid_scrap"
self.available_cards = self.hand
self.lives += 1 self.lives += 1
ser = self.__dict__.copy() ser = self.__dict__.copy()
@ -782,35 +782,36 @@ class Player:
for p in self.game.get_alive_players() for p in self.game.get_alive_players()
) )
): ):
self.available_cards = [ self.set_choose_action(
{ "choose_fratelli_di_sangue",
"name": p.name, [
"icon": p.role.icon {
if (self.game.initial_players == 3) "name": p.name,
else "⭐️" "icon": p.role.icon
if isinstance(p.role, r.Sheriff) if (self.game.initial_players == 3)
else "🤠", else "⭐️"
"alt_text": "".join(["❤️"] * p.lives) if isinstance(p.role, r.Sheriff)
+ "".join(["💀"] * (p.max_lives - p.lives)), else "🤠",
"avatar": p.avatar, "alt_text": "".join(["❤️"] * p.lives)
"is_character": True, + "".join(["💀"] * (p.max_lives - p.lives)),
"is_player": True, "avatar": p.avatar,
} "is_character": True,
for p in self.game.get_alive_players() "is_player": True,
if p != self and p.lives < p.max_lives }
] for p in self.game.get_alive_players()
self.available_cards.append({"icon": "", "noDesc": True}) if p != self and p.lives < p.max_lives
self.choose_text = "choose_fratelli_di_sangue" ]
self.pending_action = PendingAction.CHOOSE + [{"icon": "", "noDesc": True}],
)
self.is_giving_life = True self.is_giving_life = True
elif ( elif (
self.game.check_event(ceh.NuovaIdentita) self.game.check_event(ceh.NuovaIdentita)
and self.not_chosen_character is not None and self.not_chosen_character is not None
and not again and not again
): ):
self.available_cards = [self.character, self.not_chosen_character] self.set_choose_action(
self.choose_text = "choose_nuova_identita" "choose_nuova_identita", [self.character, self.not_chosen_character]
self.pending_action = PendingAction.CHOOSE )
elif not self.game.check_event(ce.Lazo) and any( elif not self.game.check_event(ce.Lazo) and any(
( (
isinstance(c, cs.Dinamite) isinstance(c, cs.Dinamite)
@ -840,25 +841,26 @@ class Player:
and sum((c.name == cs.Bang(0, 0).name for c in self.hand)) >= 2 and sum((c.name == cs.Bang(0, 0).name for c in self.hand)) >= 2
): ):
self.is_using_checchino = True self.is_using_checchino = True
self.available_cards = [ self.set_choose_action(
{ "choose_cecchino",
"name": p["name"], [
"icon": p["role"].icon {
if (self.game.initial_players == 3) "name": p["name"],
else "⭐️" "icon": p["role"].icon
if p["is_sheriff"] if (self.game.initial_players == 3)
else "🤠", else "⭐️"
"alt_text": "".join(["❤️"] * p["lives"]) if p["is_sheriff"]
+ "".join(["💀"] * (p["max_lives"] - p["lives"])), else "🤠",
"is_character": True, "alt_text": "".join(["❤️"] * p["lives"])
"is_player": True, + "".join(["💀"] * (p["max_lives"] - p["lives"])),
} "is_character": True,
for p in self.game.get_visible_players(self) "is_player": True,
if p["dist"] <= self.get_sight() }
] for p in self.game.get_visible_players(self)
self.available_cards.append({"icon": "", "noDesc": True}) if p["dist"] <= self.get_sight()
self.choose_text = "choose_cecchino" ]
self.pending_action = PendingAction.CHOOSE + [{"icon": "", "noDesc": True}],
)
self.notify_self() self.notify_self()
if ( if (
self.is_my_turn self.is_my_turn
@ -884,15 +886,15 @@ class Player:
self.notify_self() self.notify_self()
elif self.character.check(self.game, chars.KitCarlson) and not self.is_ghost: elif self.character.check(self.game, chars.KitCarlson) and not self.is_ghost:
self.is_drawing = True self.is_drawing = True
self.available_cards = [self.game.deck.draw() for i in range(3)] self.set_choose_action(
self.choose_text = "choose_card_to_get" "choose_card_to_get", [self.game.deck.draw() for i in range(3)]
self.pending_action = PendingAction.CHOOSE )
self.notify_self() self.notify_self()
elif self.character.check(self.game, grch.DutchWill) and not self.is_ghost: elif self.character.check(self.game, grch.DutchWill) and not self.is_ghost:
self.is_drawing = True self.is_drawing = True
self.available_cards = [self.game.deck.draw() for i in range(2)] self.set_choose_action(
self.choose_text = "choose_card_to_get" "choose_card_to_get", [self.game.deck.draw() for i in range(2)]
self.pending_action = PendingAction.CHOOSE )
self.notify_self() self.notify_self()
elif ( elif (
self.character.check(self.game, chd.PatBrennan) self.character.check(self.game, chd.PatBrennan)
@ -902,10 +904,10 @@ class Player:
and len(self.game.get_player_named(pile).equipment) > 0 and len(self.game.get_player_named(pile).equipment) > 0
): ):
self.is_drawing = True self.is_drawing = True
self.available_cards = self.game.get_player_named(pile).equipment
self.pat_target = pile self.pat_target = pile
self.choose_text = "choose_card_to_get" self.set_choose_action(
self.pending_action = PendingAction.CHOOSE "choose_card_to_get", self.game.get_player_named(pile).equipment
)
self.notify_self() self.notify_self()
else: else:
self.pending_action = PendingAction.PLAY self.pending_action = PendingAction.PLAY
@ -1004,12 +1006,13 @@ class Player:
def manette(self): def manette(self):
if self.game.check_event(ceh.Manette): if self.game.check_event(ceh.Manette):
self.choose_text = "choose_manette" self.set_choose_action(
self.available_cards = [ "choose_manette",
{"name": "", "icon": "♦♣♥♠"[s], "alt_text": "", "noDesc": True} [
for s in [0, 1, 2, 3] {"name": "", "icon": "♦♣♥♠"[s], "alt_text": "", "noDesc": True}
] for s in [0, 1, 2, 3]
self.pending_action = PendingAction.CHOOSE ],
)
def pick(self): def pick(self):
if self.pending_action != PendingAction.PICK: if self.pending_action != PendingAction.PICK:
@ -2100,9 +2103,7 @@ class Player:
if len(equipments) == 0: if len(equipments) == 0:
return False return False
else: else:
self.choose_text = "choose_dalton" self.set_choose_action("choose_dalton", equipments)
self.pending_action = PendingAction.CHOOSE
self.available_cards = equipments
return True return True
def get_indians(self, attacker): def get_indians(self, attacker):
@ -2501,26 +2502,29 @@ class Player:
self.character.special(self, data) self.character.special(self, data)
def gold_rush_discard(self): def gold_rush_discard(self):
self.available_cards = [ self.set_choose_action(
{ "gold_rush_discard",
"name": p.name, [
"icon": p.role.icon {
if (self.game.initial_players == 3) "name": p.name,
else "⭐️" "icon": p.role.icon
if isinstance(p.role, r.Sheriff) if (self.game.initial_players == 3)
else "🤠", else "⭐️"
"is_character": True, if isinstance(p.role, r.Sheriff)
"avatar": p.avatar, else "🤠",
"alt_text": "".join(["🎴️"] * len(p.gold_rush_equipment)), "is_character": True,
"is_player": True, "avatar": p.avatar,
} "alt_text": "".join(["🎴️"] * len(p.gold_rush_equipment)),
for p in self.game.get_alive_players() "is_player": True,
if p != self }
and any((e.number + 1 <= self.gold_nuggets for e in p.gold_rush_equipment)) for p in self.game.get_alive_players()
] if p != self
self.available_cards.append({"icon": "", "noDesc": True}) and any(
self.choose_text = "gold_rush_discard" (e.number + 1 <= self.gold_nuggets for e in p.gold_rush_equipment)
self.pending_action = PendingAction.CHOOSE )
]
+ [{"icon": "", "noDesc": True}],
)
self.notify_self() self.notify_self()
def buy_gold_rush_card(self, index): def buy_gold_rush_card(self, index):
@ -2550,6 +2554,28 @@ class Player:
self.game.deck.fill_gold_rush_shop() self.game.deck.fill_gold_rush_shop()
self.notify_self() self.notify_self()
def buy_train(self, index):
if self.pending_action != PendingAction.PLAY:
return
print(
f"{self.name} wants to buy train card on station index {index} in room {self.game.name}"
)
station: trs.StationCard = self.game.deck.stations[index]
train_index = len(self.game.deck.current_train) - 5 - index
if train_index < 0 or train_index >= len(self.game.deck.current_train):
return
train: trt.TrainCard = self.game.deck.current_train[train_index]
if train is not None and not train.is_locomotive:
if station.check_price(self):
print(f"{station=} {train=}")
self.notify_self()
def set_choose_action(self, choose_text: str, available_cards: List):
self.pending_action = PendingAction.CHOOSE
self.choose_text = choose_text
self.available_cards = available_cards
def check_can_end_turn(self): def check_can_end_turn(self):
must_be_used_cards = [c for c in self.hand if c.must_be_used] must_be_used_cards = [c for c in self.hand if c.must_be_used]
if self.game.check_event(ce.LeggeDelWest) and len(must_be_used_cards) > 0: if self.game.check_event(ce.LeggeDelWest) and len(must_be_used_cards) > 0:

View File

@ -679,6 +679,14 @@ def buy_gold_rush_card(sid, data: int):
ses.buy_gold_rush_card(data) ses.buy_gold_rush_card(data)
@sio.event
@bang_handler
def buy_train(sid, data: int):
ses: Player = sio.get_session(sid)
ses.game.rpc_log.append(f"{ses.name};buy_train;{data}")
ses.buy_train(data)
@sio.event @sio.event
@bang_handler @bang_handler
def chat_message(sid, msg, pl=None): def chat_message(sid, msg, pl=None):

View File

@ -12,7 +12,7 @@
</div> </div>
</div> </div>
<div v-if="currentStations.length > 0" class="deck" :style="`position:relative;border: 2px dashed #6a6a6a42;border-radius:8pt;align-items: flex-end;flex-direction:row;`" > <div v-if="currentStations.length > 0" class="deck" :style="`position:relative;border: 2px dashed #6a6a6a42;border-radius:8pt;align-items: flex-end;flex-direction:row;`" >
<station-card v-for="station, i in currentStations" :key="station.name" :card="{name:i}" :price="station.price" :trainPiece="trainPieceForStation(i)"/> <station-card @click.native="()=>{buyTrain(i)}" v-for="station, i in currentStations" :key="station.name" :card="station" :price="station.price" :trainPiece="trainPieceForStation(i)"/>
</div> </div>
<div v-if="eventCard" style="position:relative"> <div v-if="eventCard" style="position:relative">
<div class="card fistful-of-cards" style="position:relative; bottom:-3pt;right:-3pt;"/> <div class="card fistful-of-cards" style="position:relative; bottom:-3pt;right:-3pt;"/>
@ -181,6 +181,9 @@ export default {
return null; return null;
return this.currentTrain[index]; return this.currentTrain[index];
}, },
buyTrain(i) {
this.$socket.emit('buy_train', i)
},
action(pile) { action(pile) {
if (this.pending_action !== false && this.pending_action < 2) { if (this.pending_action !== false && this.pending_action < 2) {
// console.log('action') // console.log('action')