buy trains

This commit is contained in:
Alberto Xamin 2023-05-05 20:57:15 +02:00 committed by Alberto Xamin
parent a6029cdb0d
commit f716a96334
5 changed files with 122 additions and 3 deletions

View File

@ -67,7 +67,7 @@ class Card(ABC):
def __str__(self) -> str:
if str(self.suit).isnumeric():
char = ["♦️", "♣️", "♥️", "♠️", "🤑"][int(self.suit)]
char = ["♦️", "♣️", "♥️", "♠️", "🤑", "🚋"][int(self.suit)]
else:
char = self.suit
return f"{self.name} {char}{self.number}"

View File

@ -1,5 +1,6 @@
from typing import TYPE_CHECKING
import bang.cards as cs
import bang.players as pl
if TYPE_CHECKING:
from bang.players import Player
@ -10,6 +11,22 @@ class StationCard:
self.name = name
self.expansion = "train_robbery"
self.price: list[dict] = []
self.attached_train = None
def discard_and_buy_train(self, player: "Player", card_index: int):
"""Discard the card and buy the train"""
card = player.available_cards.pop(card_index)
for i, card in enumerate(player.hand):
if card == self:
player.hand.pop(i)
break
else:
player.lives -= 1
card = player.hand.pop(card_index)
player.game.deck.scrap(card, True, player=player)
player.hand.append(self.attached_train)
self.attached_train = None
player.pending_action = pl.PendingAction.PLAY
def check_price(self, player: "Player") -> bool:
"""Check if the card can be used to rob the train"""
@ -28,6 +45,12 @@ class BoomTown(StationCard):
not isinstance(c, cs.Bang) for c in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Bang)],
self.discard_and_buy_train,
)
return True
class Caticor(StationCard):
@ -43,6 +66,16 @@ class Caticor(StationCard):
for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[
c
for c in player.hand
if isinstance(c, cs.CatBalou) or isinstance(c, cs.Panico)
],
self.discard_and_buy_train,
)
return True
class CreepyCreek(StationCard):
@ -57,6 +90,12 @@ class CreepyCreek(StationCard):
card.suit != cs.Suit.SPADES for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.SPADES],
self.discard_and_buy_train,
)
return True
class CrownsHole(StationCard):
@ -71,6 +110,12 @@ class CrownsHole(StationCard):
not isinstance(card, cs.Birra) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Birra)],
self.discard_and_buy_train,
)
return True
class Deadwood(StationCard):
@ -85,6 +130,12 @@ class Deadwood(StationCard):
not card.is_equipment for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.is_equipment],
self.discard_and_buy_train,
)
return True
class Dodgeville(StationCard):
@ -99,6 +150,12 @@ class Dodgeville(StationCard):
not isinstance(card, cs.Mancato) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Mancato)],
self.discard_and_buy_train,
)
return True
class FortWorth(StationCard):
@ -113,6 +170,12 @@ class FortWorth(StationCard):
card.number not in {1, 10, 11, 12, 13} for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.number in {1, 10, 11, 12, 13}],
self.discard_and_buy_train,
)
return True
class Frisco(StationCard):
@ -127,6 +190,12 @@ class Frisco(StationCard):
card.suit != cs.Suit.CLUBS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.CLUBS],
self.discard_and_buy_train,
)
return True
class MinersOath(StationCard):
@ -141,6 +210,12 @@ class MinersOath(StationCard):
card.suit != cs.Suit.DIAMONDS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.DIAMONDS],
self.discard_and_buy_train,
)
return True
class SanTafe(StationCard):
@ -155,6 +230,12 @@ class SanTafe(StationCard):
card.suit != cs.Suit.HEARTS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.HEARTS],
self.discard_and_buy_train,
)
return True
class Tombrock(StationCard):
@ -167,6 +248,12 @@ class Tombrock(StationCard):
def check_price(self, player: "Player"):
if player.lives <= 1:
return False
player.set_choose_action(
"choose_buy_train",
[{"icon": "💔"}],
self.discard_and_buy_train,
)
return True
class Yooma(StationCard):
@ -181,6 +268,12 @@ class Yooma(StationCard):
not (2 <= card.number <= 9) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if 2 <= c.number <= 9],
self.discard_and_buy_train,
)
return True
class VirginiaTown(StationCard):
@ -193,6 +286,12 @@ class VirginiaTown(StationCard):
def check_price(self, player: "Player"):
if super().check_price(player) and len(player.hand < 2):
return False
player.set_choose_action(
"choose_buy_train",
player.hand.copy(),
self.discard_and_buy_train,
)
return True
def get_all_stations():

View File

@ -9,6 +9,7 @@ class TrainCard(Card):
self.is_equipment = True
self.is_locomotive = is_locomotive
self.expansion = "train_robbery"
self.type = "train"
# Circus Wagon: gli altri giocatori

View File

@ -19,7 +19,7 @@ import bang.expansions.the_valley_of_shadows.cards as tvosc
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, Callable
from metrics import Metrics
from globals import G
import sys
@ -104,6 +104,7 @@ class Player:
self.is_bot = bot
self.discord_token = discord_token
self.discord_id = None
self.did_choose_callback = None
self.played_cards = 0
self.avatar = ""
self.last_played_card: cs.Card = None
@ -1402,6 +1403,9 @@ class Player:
self.target_p = self.rissa_targets.pop(0).name
print(f"rissa targets: {self.rissa_targets}")
self.notify_self()
elif self.did_choose_callback is not None:
self.did_choose_callback(self, card_index)
self.notify_self()
elif self.choose_text == "choose_ricercato":
player = self.game.get_player_named(
self.available_cards[card_index]["name"]
@ -2569,12 +2573,26 @@ class Player:
if train is not None and not train.is_locomotive:
if station.check_price(self):
print(f"{station=} {train=}")
station.attached_train = train
# shift train forward
for i in range(train_index, len(self.game.deck.current_train) - 1):
self.game.deck.current_train[i] = self.game.deck.current_train[
i + 1
]
self.game.notify_stations()
# self.game.deck.current_train[train_index] = None
self.notify_self()
def set_choose_action(self, choose_text: str, available_cards: List):
def set_choose_action(
self,
choose_text: str,
available_cards: List,
did_choose_callback: Callable(Player, int) = None,
):
self.pending_action = PendingAction.CHOOSE
self.choose_text = choose_text
self.available_cards = available_cards
self.did_choose_callback = did_choose_callback
def check_can_end_turn(self):
must_be_used_cards = [c for c in self.hand if c.must_be_used]

View File

@ -11,6 +11,7 @@
'gold-rush': card.expansion === 'gold_rush',
brown: card.kind === 0,
black: card.kind === 1,
'train-piece': card.type && card.type === 'train',
}"
>
<h4>{{ cardName }}</h4>