diff --git a/characters.py b/characters.py index ba56150..7ab27e3 100644 --- a/characters.py +++ b/characters.py @@ -1,12 +1,13 @@ from abc import ABC, abstractmethod class Character(ABC): - def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0): + def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0): super().__init__() self.name = name self.max_lives = max_lives self.sight_mod = 0 self.visibility_mod = 0 + self.pick_mod = 0 # @abstractmethod # def on_hurt(self, dmg: int): @@ -57,7 +58,7 @@ class KitCarlson(Character): class LuckyDuke(Character): def __init__(self): - super().__init__("Lucky Duke", max_lives=4) + super().__init__("Lucky Duke", max_lives=4, pick_mod=1) class PaulRegret(Character): def __init__(self): diff --git a/game.py b/game.py index 59d35c9..302a298 100644 --- a/game.py +++ b/game.py @@ -16,7 +16,7 @@ class Game: def add_player(self, player: players.Player): player.join_game(self) self.players.append(player) - print(f'Added player {player.id} to game') + print(f'Added player {player.name} to game') def choose_characters(self): char_cards = random.sample(all_characters(), len(self.players)*2) @@ -48,7 +48,10 @@ class Game: 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))+self.players[j].get_visibility() <= 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)) + self.players[j].get_visibility() <= sight] + + def next_player(self): + return self.players[(self.turn + 1) % len(self.players)] def play_turn(self): self.players[self.turn].play_turn() @@ -68,4 +71,4 @@ game.add_player(p3) game.start_game() for p in game.players: p.set_character(random.choice(p.available_characters)) -game.distribute_roles() \ No newline at end of file +game.distribute_roles() diff --git a/players.py b/players.py index 2ce95dd..60f257a 100644 --- a/players.py +++ b/players.py @@ -1,11 +1,21 @@ +from enum import IntEnum +import json + import roles import cards import characters +class PendingAction(IntEnum): + PICK = 0 + DRAW = 1 + PLAY = 2 + RESPOND = 3 + WAIT = 4 + class Player: - def __init__(self, id): + def __init__(self, name): super().__init__() - self.id = id + self.name = name self.hand: cards.Card = [] self.equipment: cards.Card = [] self.role: roles.Role = None @@ -16,19 +26,22 @@ class Player: self.is_my_turn = False self.is_waiting_for_action = True self.has_played_bang = False + self.pending_action: PendingAction = None + self.available_characters = [] + self.was_shot = False def join_game(self, game): self.game = game - print(f'I {self.id} joined {game}') + print(f'I {self.name} joined {self.game}') def set_role(self, role: roles.Role): self.role = role - print(f'I {self.id} am a {role.name}, my goal is "{role.goal}"') + print(f'I {self.name} am a {role.name}, my goal is "{role.goal}"') def set_character(self, character: characters.Character): self.available_characters = [] self.character = character - print(f'I {self.id} chose character {character.name}') + print(f'I {self.name} chose character {character.name}') def prepare(self): self.max_lives = self.character.max_lives + self.role.health_mod @@ -38,30 +51,71 @@ class Player: def set_available_character(self, available): self.available_characters = available - print(f'I {self.id} have to choose between {available}') - + print(f'I {self.name} have to choose between {available}') + def play_turn(self): + print(f'I {self.name} was notified that it is my turn') + self.was_shot = False 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]}') - print(f'I {self.id} can see {[p.get_public_description() for p in self.game.get_visible_players(self)]}') + if any([isinstance(c) == cards.Dinamite or isinstance(c) == cards.Prigione for c in self.equipment]): + self.pending_action = PendingAction.PICK + + # # 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): + for i in range(2): + self.hand.append(self.game.deck.draw()) + self.pending_action = PendingAction.PLAY + + def pick(self): + 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 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]): + if isinstance(card) == cards.Bang and self.has_played_bang and not any([isinstance(c) == cards.Volcanic for c in self.equipment]): continue - elif type(card) == cards.Birra and self.lives >= self.max_lives: + elif isinstance(card) == cards.Birra and self.lives >= self.max_lives: continue else: playable_cards.append(i) return playable_cards def get_public_description(self): - s = f"{self.id} {'Sheriff ⭐️' if type(self.role) == roles.Sheriff else ''} ({self.lives}/{self.max_lives} ⁍) {len(self.hand)} Cards in hand, " + s = f"{self.name} {'Sheriff ⭐️' if isinstance(self.role) == roles.Sheriff else ''} ({self.lives}/{self.max_lives} ⁍) {len(self.hand)} Cards in hand, " s += f"equipment {[str(c) for c in self.equipment]}" return s @@ -70,21 +124,20 @@ class Player: print('illegal') return card: cards.Card = self.hand.pop(hand_index) - print(self.id, 'is playing ', card, ' against:', againts) + print(self.name, '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.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]): + 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') - game.deck.scrap(card) - pass + self.game.deck.scrap(card) def get_sight(self): aim = 0 @@ -100,9 +153,8 @@ class Player: covers += card.vis_mod return self.character.visibility_mod + covers - def end_turn(self): - if len(self.hand) > self.max_lives: - print(f"I {self.id} have to many cards in my hand and I can't end the turn") + def end_turn(self, forced=False): + if len(self.hand) > self.max_lives and not forced: + print(f"I {self.name} have to many cards in my hand and I can't end the turn") else: - game.next_turn() - + self.game.next_turn() diff --git a/roles.py b/roles.py index fee4ef0..8ec70ba 100644 --- a/roles.py +++ b/roles.py @@ -17,7 +17,7 @@ class Sheriff(Role): self.max_players = 1 def on_player_death(self, alive_players: list): - if not any([type(p.role) == Outlaw or type(p.role) == Renegade for p in alive_players]): + if not any([isinstance(p.role) == Outlaw or isinstance(p.role) == Renegade for p in alive_players]): print("The Sheriff won!") pass @@ -28,7 +28,7 @@ class Vice(Role): self.max_players = 2 def on_player_death(self, alive_players: list): - if not any([type(p.role) == Outlaw or type(p.role) == Renegade for p in alive_players]): + if not any([isinstance(p.role) == Outlaw or isinstance(p.role) == Renegade for p in alive_players]): print("The Vice won!") pass @@ -38,7 +38,7 @@ class Outlaw(Role): self.max_players = 3 def on_player_death(self, alive_players: list): - if not any([type(p.role) == Sheriff for p in alive_players]): + if not any([isinstance(p.role) == Sheriff for p in alive_players]): print("The Outlaw won!") pass @@ -48,6 +48,6 @@ class Renegade(Role): self.max_players = 1 def on_player_death(self, alive_players: list): - if len(alive_players) == 1 and type(alive_players[0]) == Renegade: + if len(alive_players) == 1 and isinstance(alive_players[0]) == Renegade: print("The Renegade won!") pass