progress
This commit is contained in:
parent
28a8cd02b5
commit
768415d2ed
38
cards.py
38
cards.py
@ -1,12 +1,12 @@
|
|||||||
from typing import List, Set, Dict, Tuple, Optional
|
from typing import List, Set, Dict, Tuple, Optional
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from enum import Enum
|
from enum import IntEnum
|
||||||
|
|
||||||
class Suit(Enum):
|
class Suit(IntEnum):
|
||||||
DIAMONDS = 1 # ♦
|
DIAMONDS = 0 # ♦
|
||||||
CLUBS = 2 # ♣
|
CLUBS = 1 # ♣
|
||||||
HEARTS = 3 # ♥
|
HEARTS = 2 # ♥
|
||||||
SPADES = 4 # ♠
|
SPADES = 3 # ♠
|
||||||
|
|
||||||
class Card(ABC):
|
class Card(ABC):
|
||||||
sym = {
|
sym = {
|
||||||
@ -15,7 +15,7 @@ class Card(ABC):
|
|||||||
'Q': 12,
|
'Q': 12,
|
||||||
'K': 13
|
'K': 13
|
||||||
}
|
}
|
||||||
def __init__(self, name: str, suit: Suit, number, is_equipment:bool=False, is_weapon:bool=False):
|
def __init__(self, suit: Suit, name: str, number, is_equipment:bool=False, is_weapon:bool=False, vis_mod:int=0, sight_mod:int=0, range:int=99):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.suit = suit
|
self.suit = suit
|
||||||
@ -26,6 +26,14 @@ class Card(ABC):
|
|||||||
self.number = self.sym[number]
|
self.number = self.sym[number]
|
||||||
self.is_equipment = is_equipment
|
self.is_equipment = is_equipment
|
||||||
self.is_weapon = is_weapon
|
self.is_weapon = is_weapon
|
||||||
|
self.vis_mod = vis_mod
|
||||||
|
self.sight_mod = sight_mod
|
||||||
|
self.range = range
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
char = ['♦️','♣️','♥️','♠️'][int(self.suit)]
|
||||||
|
return f'{self.name} {char}{self.number}'
|
||||||
|
return super().__str__()
|
||||||
|
|
||||||
class Barile(Card):
|
class Barile(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -37,11 +45,11 @@ class Dinamite(Card):
|
|||||||
|
|
||||||
class Mirino(Card):
|
class Mirino(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Mirino', number, is_equipment=True)
|
super().__init__(suit, 'Mirino', number, is_equipment=True, sight_mod=1)
|
||||||
|
|
||||||
class Mustang(Card):
|
class Mustang(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Mustang', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Mustang', number, is_equipment=True, is_weapon=True, vis_mod=1)
|
||||||
|
|
||||||
class Prigione(Card):
|
class Prigione(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -49,23 +57,23 @@ class Prigione(Card):
|
|||||||
|
|
||||||
class Remington(Card):
|
class Remington(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Remington', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Remington', number, is_equipment=True, is_weapon=True, range=3)
|
||||||
|
|
||||||
class RevCarabine(Card):
|
class RevCarabine(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Rev. Carabine', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Rev. Carabine', number, is_equipment=True, is_weapon=True, range=4)
|
||||||
|
|
||||||
class Schofield(Card):
|
class Schofield(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Schofield', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Schofield', number, is_equipment=True, is_weapon=True, range=2)
|
||||||
|
|
||||||
class Volcanic(Card):
|
class Volcanic(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Volcanic', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Volcanic', number, is_equipment=True, is_weapon=True, range=1)
|
||||||
|
|
||||||
class Winchester(Card):
|
class Winchester(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Winchester', number, is_equipment=True, is_weapon=True)
|
super().__init__(suit, 'Winchester', number, is_equipment=True, is_weapon=True, range=5)
|
||||||
|
|
||||||
class Bang(Card):
|
class Bang(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -105,7 +113,7 @@ class Mancato(Card):
|
|||||||
|
|
||||||
class Panico(Card):
|
class Panico(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Panico!', number)
|
super().__init__(suit, 'Panico!', number, range=1)
|
||||||
|
|
||||||
class Saloon(Card):
|
class Saloon(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
|
@ -8,21 +8,21 @@ class Character(ABC):
|
|||||||
self.sight_mod = 0
|
self.sight_mod = 0
|
||||||
self.visibility_mod = 0
|
self.visibility_mod = 0
|
||||||
|
|
||||||
@abstractmethod
|
# @abstractmethod
|
||||||
def on_hurt(self, dmg: int):
|
# def on_hurt(self, dmg: int):
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
@abstractmethod
|
# @abstractmethod
|
||||||
def on_pick(self, card): # tipo dinamite e prigione
|
# def on_pick(self, card): # tipo dinamite e prigione
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
@abstractmethod
|
# @abstractmethod
|
||||||
def on_empty_hand(self):
|
# def on_empty_hand(self):
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
@abstractmethod
|
# @abstractmethod
|
||||||
def on_empty_hand(self):
|
# def on_empty_hand(self):
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
class BartCassidy(Character):
|
class BartCassidy(Character):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -35,5 +35,78 @@ class BlackJack(Character):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Black Jack", max_lives=4)
|
super().__init__("Black Jack", max_lives=4)
|
||||||
|
|
||||||
|
class CalamityJanet(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Calamity Janet", max_lives=4)
|
||||||
|
|
||||||
|
class ElGringo(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("El Gringo", max_lives=3)
|
||||||
|
|
||||||
|
class JesseJones(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Jesse Jones", max_lives=4)
|
||||||
|
|
||||||
|
class Jourdonnais(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Jourdonnais", max_lives=4)
|
||||||
|
|
||||||
|
class KitCarlson(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Kit Carlson", max_lives=4)
|
||||||
|
|
||||||
|
class LuckyDuke(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Lucky Duke", max_lives=4)
|
||||||
|
|
||||||
|
class PaulRegret(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Paul Regret", max_lives=3)
|
||||||
|
|
||||||
|
class PedroRamirez(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Pedro Ramirez", max_lives=4)
|
||||||
|
|
||||||
|
class RoseDoolan(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Rose Doolan", max_lives=4)
|
||||||
|
|
||||||
|
class SidKetchum(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Sid Ketchum", max_lives=4)
|
||||||
|
|
||||||
|
class SlabTheKiller(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Slab The Killer", max_lives=4)
|
||||||
|
|
||||||
|
class SuzyLafayette(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Suzy Lafayette", max_lives=4)
|
||||||
|
|
||||||
|
class VultureSam(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Vulture Sam", max_lives=4)
|
||||||
|
|
||||||
|
class WillyTheKid(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Willy The Kid", max_lives=4)
|
||||||
|
|
||||||
def all_characters():
|
def all_characters():
|
||||||
return [BartCassidy(), BlackJack()]
|
return [
|
||||||
|
BartCassidy(),
|
||||||
|
BlackJack(),
|
||||||
|
CalamityJanet(),
|
||||||
|
ElGringo(),
|
||||||
|
JesseJones(),
|
||||||
|
Jourdonnais(),
|
||||||
|
KitCarlson(),
|
||||||
|
LuckyDuke(),
|
||||||
|
PaulRegret(),
|
||||||
|
PedroRamirez(),
|
||||||
|
RoseDoolan(),
|
||||||
|
SidKetchum(),
|
||||||
|
SlabTheKiller(),
|
||||||
|
SuzyLafayette(),
|
||||||
|
VultureSam(),
|
||||||
|
WillyTheKid(),
|
||||||
|
]
|
18
deck.py
18
deck.py
@ -1,28 +1,30 @@
|
|||||||
from typing import List, Set, Dict, Tuple, Optional
|
from typing import List, Set, Dict, Tuple, Optional
|
||||||
import random
|
import random
|
||||||
import cards
|
from cards import Card, get_starting_deck
|
||||||
|
|
||||||
class Deck:
|
class Deck:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.cards: List[cards.Card] = random.shuffle(cards.get_starting_deck())
|
self.cards: List[Card] = get_starting_deck()
|
||||||
self.scrap_pile: List[cards.Card] = []
|
random.shuffle(self.cards)
|
||||||
|
self.scrap_pile: List[Card] = []
|
||||||
|
print(f'Deck initialized with {len(self.cards)} cards')
|
||||||
|
|
||||||
def peek(self, n_cards: int) -> list:
|
def peek(self, n_cards: int) -> list:
|
||||||
return self.cards[:n_cards]
|
return self.cards[:n_cards]
|
||||||
|
|
||||||
def peek_scrap_pile(self,) -> cards.Card:
|
def peek_scrap_pile(self,) -> Card:
|
||||||
if len(self.scrap_pile) > 0:
|
if len(self.scrap_pile) > 0:
|
||||||
return self.scrap_pile[-1]
|
return self.scrap_pile[-1]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def pick_and_scrap(self) -> cards.Card:
|
def pick_and_scrap(self) -> Card:
|
||||||
card = self.cards.pop(0)
|
card = self.cards.pop(0)
|
||||||
self.scrap_pile.append(card)
|
self.scrap_pile.append(card)
|
||||||
return card
|
return card
|
||||||
|
|
||||||
def draw(self) -> cards.Card:
|
def draw(self) -> Card:
|
||||||
card = self.cards.pop(0)
|
card = self.cards.pop(0)
|
||||||
if len(self.cards) == 0:
|
if len(self.cards) == 0:
|
||||||
self.cards = self.scrap_pile[:-1].copy()
|
self.cards = self.scrap_pile[:-1].copy()
|
||||||
@ -30,11 +32,11 @@ class Deck:
|
|||||||
self.scrap_pile = self.scrap_pile[-1:]
|
self.scrap_pile = self.scrap_pile[-1:]
|
||||||
return card
|
return card
|
||||||
|
|
||||||
def draw_from_scrap_pile(self) -> cards.Card:
|
def draw_from_scrap_pile(self) -> Card:
|
||||||
if len(self.scrap_pile) > 0:
|
if len(self.scrap_pile) > 0:
|
||||||
return self.scrap_pile.pop(0)
|
return self.scrap_pile.pop(0)
|
||||||
else:
|
else:
|
||||||
return self.draw()
|
return self.draw()
|
||||||
|
|
||||||
def scrap(self, card: cards.Card):
|
def scrap(self, card: Card):
|
||||||
self.scrap_pile.append(card)
|
self.scrap_pile.append(card)
|
21
game.py
21
game.py
@ -16,13 +16,15 @@ class Game:
|
|||||||
def add_player(self, player: players.Player):
|
def add_player(self, player: players.Player):
|
||||||
player.join_game(self)
|
player.join_game(self)
|
||||||
self.players.append(player)
|
self.players.append(player)
|
||||||
|
print(f'Added player {player.id} to game')
|
||||||
|
|
||||||
def choose_characters(self):
|
def choose_characters(self):
|
||||||
char_cards = random.sample(all_characters(), len(self.players))
|
char_cards = random.sample(all_characters(), len(self.players)*2)
|
||||||
for i in range(len(self.players)):
|
for i in range(len(self.players)):
|
||||||
self.players[i].set_available_character(char_cards[i*2:i*2+2])
|
self.players[i].set_available_character(char_cards[i*2:i*2+2])
|
||||||
|
|
||||||
def start_game(self):
|
def start_game(self):
|
||||||
|
print('GAME IS STARING')
|
||||||
if self.started:
|
if self.started:
|
||||||
return
|
return
|
||||||
self.started = True
|
self.started = True
|
||||||
@ -43,6 +45,11 @@ class Game:
|
|||||||
self.players[i].hand.append(self.deck.draw())
|
self.players[i].hand.append(self.deck.draw())
|
||||||
self.play_turn()
|
self.play_turn()
|
||||||
|
|
||||||
|
def get_visible_players(self, player):
|
||||||
|
i = self.players.index(player)
|
||||||
|
sight = player.get_sight()
|
||||||
|
return [self.players[j] for j in range(len(self.players)) if i != j and min(abs(i-j)-1, abs(i-len(self.players)-j))+players[j].get_visibility() <= sight]
|
||||||
|
|
||||||
def play_turn(self):
|
def play_turn(self):
|
||||||
self.players[self.turn].play_turn()
|
self.players[self.turn].play_turn()
|
||||||
|
|
||||||
@ -50,3 +57,15 @@ class Game:
|
|||||||
self.turn = (self.turn + 1) % len(self.players)
|
self.turn = (self.turn + 1) % len(self.players)
|
||||||
self.play_turn()
|
self.play_turn()
|
||||||
|
|
||||||
|
|
||||||
|
game = Game()
|
||||||
|
p1 = players.Player('p1')
|
||||||
|
game.add_player(p1)
|
||||||
|
p2 = players.Player('p2')
|
||||||
|
game.add_player(p2)
|
||||||
|
p3 = players.Player('p3')
|
||||||
|
game.add_player(p3)
|
||||||
|
game.start_game()
|
||||||
|
for p in game.players:
|
||||||
|
p.set_character(random.choice(p.available_characters))
|
||||||
|
game.distribute_roles()
|
63
players.py
63
players.py
@ -13,15 +13,22 @@ class Player:
|
|||||||
self.lives = 0
|
self.lives = 0
|
||||||
self.max_lives = 0
|
self.max_lives = 0
|
||||||
self.game = None
|
self.game = None
|
||||||
|
self.is_my_turn = False
|
||||||
|
self.is_waiting_for_action = True
|
||||||
|
self.has_played_bang = False
|
||||||
|
|
||||||
def join_game(self, game):
|
def join_game(self, game):
|
||||||
self.game = game
|
self.game = game
|
||||||
|
print(f'I {self.id} joined {game}')
|
||||||
|
|
||||||
def set_role(self, role: roles.Role):
|
def set_role(self, role: roles.Role):
|
||||||
self.role = role
|
self.role = role
|
||||||
|
print(f'I {self.id} am a {role.name}')
|
||||||
|
|
||||||
def set_character(self, character: characters.Character):
|
def set_character(self, character: characters.Character):
|
||||||
|
self.available_characters = []
|
||||||
self.character = character
|
self.character = character
|
||||||
|
print(f'I {self.id} chose character {character.name}')
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
self.max_lives = self.character.max_lives + self.role.health_mod
|
self.max_lives = self.character.max_lives + self.role.health_mod
|
||||||
@ -31,13 +38,65 @@ class Player:
|
|||||||
|
|
||||||
def set_available_character(self, available):
|
def set_available_character(self, available):
|
||||||
self.available_characters = available
|
self.available_characters = available
|
||||||
|
print(f'I {self.id} have to choose between {available}')
|
||||||
|
|
||||||
def play_turn(self):
|
def play_turn(self):
|
||||||
print('not implemented')
|
self.is_my_turn = True
|
||||||
|
self.is_waiting_for_action = True
|
||||||
|
self.has_played_bang = False
|
||||||
|
print(f'I {self.id} was notified that it is my turn')
|
||||||
|
print(f'lives: {self.lives}/{self.max_lives} hand: {[str(c) for c in self.hand]}')
|
||||||
|
|
||||||
|
def get_playable_cards(self):
|
||||||
|
playable_cards = []
|
||||||
|
for i in range(len(self.hand)):
|
||||||
|
card = self.hand[i]
|
||||||
|
if type(card) == cards.Bang and self.has_played_bang and not any([type(c) == cards.Volcanic for c in self.equipment]):
|
||||||
|
continue
|
||||||
|
elif type(card) == cards.Birra and self.lives >= self.max_lives:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
playable_cards.append(i)
|
||||||
|
return playable_cards
|
||||||
|
|
||||||
|
def play_card(self, hand_index: int, againts=None):
|
||||||
|
if not (0 <= hand_index < len(self.hand)):
|
||||||
|
print('illegal')
|
||||||
|
return
|
||||||
|
card: cards.Card = self.hand.pop(hand_index)
|
||||||
|
print(self.id, 'is playing ', card, ' against:', againts)
|
||||||
|
if card.is_equipment and card.name not in [c.name for c in self.equipment]:
|
||||||
|
if card.is_weapon:
|
||||||
|
for i in range(len(self.equipment)):
|
||||||
|
if self.equipment[i].is_weapon:
|
||||||
|
game.deck.scrap(self.equipment[i])
|
||||||
|
self.equipment[i] = card
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.equipment.append(card)
|
||||||
|
else:
|
||||||
|
if type(card) == cards.Bang and self.has_played_bang and not any([type(c) == cards.Volcanic for c in self.equipment]):
|
||||||
|
print('you retard')
|
||||||
|
game.deck.scrap(card)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_sight(self):
|
||||||
|
aim = 0
|
||||||
|
for card in self.equipment:
|
||||||
|
aim += card.sight_mod
|
||||||
|
if card.is_weapon:
|
||||||
|
aim += card.range
|
||||||
|
return 1 + self.character.sight_mod + aim
|
||||||
|
|
||||||
|
def get_visibility(self):
|
||||||
|
covers = 0
|
||||||
|
for card in self.equipment:
|
||||||
|
covers += card.vis_mod
|
||||||
|
return self.character.visibility_mod + covers
|
||||||
|
|
||||||
def end_turn(self):
|
def end_turn(self):
|
||||||
if len(self.hand) > self.max_lives:
|
if len(self.hand) > self.max_lives:
|
||||||
print("discard a card")
|
print(f"I {self.id} have to many cards in my hand and I can't end the turn")
|
||||||
else:
|
else:
|
||||||
game.next_turn()
|
game.next_turn()
|
||||||
|
|
||||||
|
12
roles.py
12
roles.py
@ -13,8 +13,7 @@ class Role(ABC):
|
|||||||
|
|
||||||
class Sheriff(Role):
|
class Sheriff(Role):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Sceriffo", +1)
|
super().__init__("Sceriffo", "Elimina tutti i Fuorilegge e il Rinnegato!", health_mod=+1)
|
||||||
self.goal = "Elimina tutti i Fuorilegge e il Rinnegato!"
|
|
||||||
self.max_players = 1
|
self.max_players = 1
|
||||||
|
|
||||||
def on_player_death(self, alive_players: list):
|
def on_player_death(self, alive_players: list):
|
||||||
@ -25,8 +24,7 @@ class Sheriff(Role):
|
|||||||
|
|
||||||
class Vice(Role):
|
class Vice(Role):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Vice")
|
super().__init__("Vice", "Proteggi lo Sceriffo! Elimina tutti i Fuorilegge e il Rinnegato!")
|
||||||
self.goal = "Proteggi lo Sceriffo! Elimina tutti i Fuorilegge e il Rinnegato!"
|
|
||||||
self.max_players = 2
|
self.max_players = 2
|
||||||
|
|
||||||
def on_player_death(self, alive_players: list):
|
def on_player_death(self, alive_players: list):
|
||||||
@ -36,8 +34,7 @@ class Vice(Role):
|
|||||||
|
|
||||||
class Outlaw(Role):
|
class Outlaw(Role):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Fuorilegge")
|
super().__init__("Fuorilegge", "Elimina lo Sceriffo!")
|
||||||
self.goal = "Elimina lo Sceriffo!"
|
|
||||||
self.max_players = 3
|
self.max_players = 3
|
||||||
|
|
||||||
def on_player_death(self, alive_players: list):
|
def on_player_death(self, alive_players: list):
|
||||||
@ -47,8 +44,7 @@ class Outlaw(Role):
|
|||||||
|
|
||||||
class Renegade(Role):
|
class Renegade(Role):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Rinnegato")
|
super().__init__("Rinnegato", "Rimani l'ultimo personaggio in gioco!")
|
||||||
self.goal = "Rimani l'ultimo personaggio in gioco!"
|
|
||||||
self.max_players = 1
|
self.max_players = 1
|
||||||
|
|
||||||
def on_player_death(self, alive_players: list):
|
def on_player_death(self, alive_players: list):
|
||||||
|
Loading…
Reference in New Issue
Block a user