From 53829481d5f678c3d7f0c7bd60bdca4bdd7ee97a Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:57:25 -0600 Subject: [PATCH 01/46] Delete git.xml --- _windows/git.xml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 _windows/git.xml diff --git a/_windows/git.xml b/_windows/git.xml deleted file mode 100644 index a8092bd..0000000 --- a/_windows/git.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file From 34e521fa764f36bbec05699695c51fa0900116ea Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:57:31 -0600 Subject: [PATCH 02/46] Delete laf.xml --- _windows/laf.xml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 _windows/laf.xml diff --git a/_windows/laf.xml b/_windows/laf.xml deleted file mode 100644 index dbf49b4..0000000 --- a/_windows/laf.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 07d2e8b1bd215a2f5c3e3897f849b20890ca6604 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:57:40 -0600 Subject: [PATCH 03/46] Delete Default.xml --- codestyles/Default.xml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 codestyles/Default.xml diff --git a/codestyles/Default.xml b/codestyles/Default.xml deleted file mode 100644 index 1345acf..0000000 --- a/codestyles/Default.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file From 37d580ba03d212ad72ea91c1b27d70677c870305 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:57:49 -0600 Subject: [PATCH 04/46] Delete Default.xml --- inspection/Default.xml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 inspection/Default.xml diff --git a/inspection/Default.xml b/inspection/Default.xml deleted file mode 100644 index da0c24f..0000000 --- a/inspection/Default.xml +++ /dev/null @@ -1,3 +0,0 @@ - - \ No newline at end of file From 33a6a57f992b26bf0da5a4d4bc150225dd18a044 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:02 -0600 Subject: [PATCH 05/46] Delete databaseDrivers.xml --- databaseDrivers.xml | 78 --------------------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 databaseDrivers.xml diff --git a/databaseDrivers.xml b/databaseDrivers.xml deleted file mode 100644 index 98bf5b5..0000000 --- a/databaseDrivers.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 34048d950913f0a10c898809f2ffd0e0c2184d72 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:11 -0600 Subject: [PATCH 06/46] Delete databaseSettings.xml --- databaseSettings.xml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 databaseSettings.xml diff --git a/databaseSettings.xml b/databaseSettings.xml deleted file mode 100644 index 0962833..0000000 --- a/databaseSettings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From e91c09dc80351ff54d34d5f838d5d55a0324fb5b Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:21 -0600 Subject: [PATCH 07/46] Delete debugger.xml --- debugger.xml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 debugger.xml diff --git a/debugger.xml b/debugger.xml deleted file mode 100644 index 544ab15..0000000 --- a/debugger.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file From 7911b792ca4d6e78856bd25cd7455ca7f37cb821 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:30 -0600 Subject: [PATCH 08/46] Delete editor.xml --- editor.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 editor.xml diff --git a/editor.xml b/editor.xml deleted file mode 100644 index 66a0938..0000000 --- a/editor.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file From 2d2ee3981e2bf9690d71c12ced56b8388424ded7 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:37 -0600 Subject: [PATCH 09/46] Delete filetypes.xml --- filetypes.xml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 filetypes.xml diff --git a/filetypes.xml b/filetypes.xml deleted file mode 100644 index 137cd9e..0000000 --- a/filetypes.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From a2cb5794d47c56e2cc19f3f69ff04889e08887d1 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:45 -0600 Subject: [PATCH 10/46] Delete find.xml --- find.xml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 find.xml diff --git a/find.xml b/find.xml deleted file mode 100644 index 965789e..0000000 --- a/find.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file From 2b4b1f605cf8dcb6d79463f8526f83e8b560bc24 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 12:58:52 -0600 Subject: [PATCH 11/46] Delete ui.lnf.xml --- ui.lnf.xml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 ui.lnf.xml diff --git a/ui.lnf.xml b/ui.lnf.xml deleted file mode 100644 index 73792a4..0000000 --- a/ui.lnf.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file From 94d2e582142b9c159acdba1b4d60ccaf059989ff Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 14:01:44 -0500 Subject: [PATCH 12/46] Add files via upload Refactored card typing to no longer be a piece of data but a feature of the object structure. --- card/basic/card_action.py | 5 ++++ card/basic/card_attack.py | 5 ++++ card/basic/card_curse.py | 10 +++++++ card/basic/card_kingdom.py | 10 +++++++ card/basic/card_reaction.py | 5 ++++ card/basic/card_treasure.py | 8 ++++++ card/basic/card_victory.py | 21 +++++++++++++++ card/card.py | 47 ++++++++++++++------------------- card/named/cellar.py | 27 +++++++++++++++++++ card/named/copper.py | 5 ++++ card/named/estate.py | 8 ++++++ card/named/gold.py | 5 ++++ card/named/merchant.py | 17 ++++++++++++ card/named/militia.py | 32 ++++++++++++++++++++++ card/named/mine.py | 9 +++++++ card/named/moat.py | 6 +++++ card/named/remodel.py | 6 +++++ card/named/silver.py | 6 +++++ card/named/workshop.py | 9 +++++++ card/special/card_gain.py | 41 ++++++++++++++++++++++++++++ card/special/card_gain_trash.py | 9 +++++++ card/special/card_trash.py | 43 ++++++++++++++++++++++++++++++ player/bots/pure_big_money.py | 13 +++++---- player/hand.py | 38 +++++++++++++------------- player/player.py | 28 ++++++++++---------- table/pile.py | 1 + 26 files changed, 348 insertions(+), 66 deletions(-) create mode 100644 card/basic/card_action.py create mode 100644 card/basic/card_attack.py create mode 100644 card/basic/card_curse.py create mode 100644 card/basic/card_kingdom.py create mode 100644 card/basic/card_reaction.py create mode 100644 card/basic/card_treasure.py create mode 100644 card/basic/card_victory.py create mode 100644 card/named/cellar.py create mode 100644 card/named/copper.py create mode 100644 card/named/estate.py create mode 100644 card/named/gold.py create mode 100644 card/named/merchant.py create mode 100644 card/named/militia.py create mode 100644 card/named/mine.py create mode 100644 card/named/moat.py create mode 100644 card/named/remodel.py create mode 100644 card/named/silver.py create mode 100644 card/named/workshop.py create mode 100644 card/special/card_gain.py create mode 100644 card/special/card_gain_trash.py create mode 100644 card/special/card_trash.py diff --git a/card/basic/card_action.py b/card/basic/card_action.py new file mode 100644 index 0000000..88d78cf --- /dev/null +++ b/card/basic/card_action.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Action(Kingdom): + pass diff --git a/card/basic/card_attack.py b/card/basic/card_attack.py new file mode 100644 index 0000000..af4c9e8 --- /dev/null +++ b/card/basic/card_attack.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Attack(Kingdom): + pass diff --git a/card/basic/card_curse.py b/card/basic/card_curse.py new file mode 100644 index 0000000..daa9f83 --- /dev/null +++ b/card/basic/card_curse.py @@ -0,0 +1,10 @@ +from card.card import Card + + +class Curse(Card): + @staticmethod + def pile_setup(player_count): + if player_count % Card.normal_full_table < Card.normal_full_table/2: + return Card.pile_player_rate + else: + return (player_count - 1) * Card.pile_player_rate diff --git a/card/basic/card_kingdom.py b/card/basic/card_kingdom.py new file mode 100644 index 0000000..46b670e --- /dev/null +++ b/card/basic/card_kingdom.py @@ -0,0 +1,10 @@ +from card.card import Card +from math import floor + + +class Kingdom(Card): + pile_player_rate = 10 + + @staticmethod + def pile_setup(player_count): + return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate diff --git a/card/basic/card_reaction.py b/card/basic/card_reaction.py new file mode 100644 index 0000000..2ebf00a --- /dev/null +++ b/card/basic/card_reaction.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Reaction(Kingdom): + pass diff --git a/card/basic/card_treasure.py b/card/basic/card_treasure.py new file mode 100644 index 0000000..4206a6a --- /dev/null +++ b/card/basic/card_treasure.py @@ -0,0 +1,8 @@ +from card.card import Card +from math import floor + + +class Treasure(Card): + @classmethod + def pile_setup(cls, player_count): + return (floor(player_count/Card.normal_full_table) + 1) * cls.pile_player_rate diff --git a/card/basic/card_victory.py b/card/basic/card_victory.py new file mode 100644 index 0000000..e023e99 --- /dev/null +++ b/card/basic/card_victory.py @@ -0,0 +1,21 @@ +from card.card import Card +from math import floor + + +class Victory(Card): + two_player_count = 8 + four_player_count = 12 + five_player_count = 15 + six_player_count = 18 + + @classmethod + def pile_setup(cls, player_count): + if 0 < player_count % Card.normal_full_table < Card.normal_full_table/2: + supplement = cls.two_player_count + elif Card.normal_full_table/2 <= player_count % Card.normal_full_table < Card.normal_full_table - 1: + supplement = cls.four_player_count + elif player_count % Card.normal_full_table == Card.normal_full_table - 1: + supplement = cls.five_player_count + else: + supplement = cls.six_player_count + return (floor(player_count/Card.normal_full_table) * cls.six_player_count) + supplement diff --git a/card/card.py b/card/card.py index b1f0107..35c41b3 100644 --- a/card/card.py +++ b/card/card.py @@ -1,22 +1,12 @@ -from enum import Enum, auto - - class Card: - class CardType(Enum): - Treasure = auto() - Action = auto() - Reaction = auto() - Attack = auto() - Victory = auto() - Curse = auto() - prevent_attack = False + normal_full_table = 6 + pile_player_rate = 10 - def __init__(self, name, cost, cardtype, value, coin, action, buy, draw, owner): + def __init__(self, name, cost, value, coin, action, buy, draw, owner): self.__name = name self.__cost = cost self.__coin = coin - self.__type = cardtype self.__action = action self.__buy = buy self.__draw = draw @@ -34,16 +24,19 @@ class Card: # This is here so that 'special' card can override this function so that unique card effects can happen. pass - def setup(self): + @classmethod + def pile_setup(cls, player_count): + # This is here so that each card can override this function so that the right number of . + pass + + @staticmethod + def setup(): # This is here so that 'special' card can override this function so that unique card setup effects can happen. pass def get_name(self): return self.__name - def get_type(self): - return self.__type - def get_points(self): return self.__value @@ -60,7 +53,15 @@ class Card: return self.__owner def identify(self): - return self.__name + ", " + str(self.__type) + ", " + str(self.__cost) + return self.__name + ", " + self.__str__() + ", costing " + str(self.__cost) + + def print_card_list(self, card, message): + print("\nPlayer " + str(self._Card__owner.get_player_index()) + " " + message) + + counter = 0 + for c in card: + print(str(counter) + ": " + c.identify()) + counter += 1 def __get_index_not_self(self): result = -1 @@ -69,13 +70,5 @@ class Card: result = self._Card__owner.get_hand().get_player_index() return result - def __print_card_list(self, card, message): - print("\nPlayer " + str(self._Card__owner.get_player_index()) + " " + message) - - counter = 0 - for c in card: - print(str(counter) + ": " + c.identify()) - counter += 1 - def __str__(self): - return "A " + self.__name + " card." + return "a " + self.__name + " card" diff --git a/card/named/cellar.py b/card/named/cellar.py new file mode 100644 index 0000000..da3d5d5 --- /dev/null +++ b/card/named/cellar.py @@ -0,0 +1,27 @@ +from card.basic.card_action import Action + + +class Cellar(Action): + def effect(self): + hand_index = 0 + cards_discarded = 0 + have_not_run_yet = True + while self._Card__owner.get_hand().get_remaining() >= 0 and \ + 0 <= hand_index < self._Card__owner.get_hand().get_remaining() and \ + (hand_index != self._Card__owner.get_hand().get_supply().index(self) or have_not_run_yet): + hand_index = self.__get_index("Player " + str(self._Card__owner.get_player_index()) + ", input the index " + "from your hand to discard that card and gain an action, or input an " + "impossible index to end discard selection: ") + + if 0 <= hand_index < self._Card__owner.get_hand().get_remaining() and \ + hand_index != self._Card__owner.get_hand().get_supply().index(self): + self._Card__owner.discard_from_hand(hand_index) + self._Card__owner.print_hand() + cards_discarded += 1 + hand_index = self.__get_index_not_self() + have_not_run_yet = False + self._Card__owner.draw_cards(cards_discarded) + + def __get_index(self, message): + return self.__Card_owner.get_general_input(message, int) + diff --git a/card/named/copper.py b/card/named/copper.py new file mode 100644 index 0000000..35112e1 --- /dev/null +++ b/card/named/copper.py @@ -0,0 +1,5 @@ +from card.basic.card_treasure import Treasure + + +class Copper(Treasure): + pile_player_rate = 60 diff --git a/card/named/estate.py b/card/named/estate.py new file mode 100644 index 0000000..c913a43 --- /dev/null +++ b/card/named/estate.py @@ -0,0 +1,8 @@ +from card.basic.card_victory import Victory + + +class Estate(Victory): + two_player_count = 14 + four_player_count = 18 + five_player_count = 21 + six_player_count = 24 diff --git a/card/named/gold.py b/card/named/gold.py new file mode 100644 index 0000000..cd81068 --- /dev/null +++ b/card/named/gold.py @@ -0,0 +1,5 @@ +from card.basic.card_treasure import Treasure + + +class Gold(Treasure): + pile_player_rate = 30 \ No newline at end of file diff --git a/card/named/merchant.py b/card/named/merchant.py new file mode 100644 index 0000000..cf0b9b4 --- /dev/null +++ b/card/named/merchant.py @@ -0,0 +1,17 @@ +from card.basic.card_action import Action + + +class Merchant(Action): + def effect(self): + silver_card_index = self._Card__owner.get_hand().get_index_of_card_by_name("Silver") + if silver_card_index >= 0: + yes_no = self.__get_Merchant_input("'Y' if you'd like to play a silver card and gain an extra coin: ") + + if yes_no: + self._Card__owner.get_hand().transfer_card_by_card( + self._Card__owner.get_hand().get_card(silver_card_index), self._Card__owner.get_discard()) + self._Card__owner.add_purchase_power(3) + + def __get_Merchant_input(self, message): + return self.__Card_owner.get_general_input("Player " + str(self._Card__owner.get_player_index()) + ", " + + message, str) diff --git a/card/named/militia.py b/card/named/militia.py new file mode 100644 index 0000000..ffc8783 --- /dev/null +++ b/card/named/militia.py @@ -0,0 +1,32 @@ +from card.basic.card_attack import Attack +from card.basic.card_action import Action +from random import randint + + +class Militia(Action, Attack): + def effect(self): + for player in self._Card__owner.get_table().get_players(): + if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()): + player.print_hand() + print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.") + self.__force_discard(self._Card__owner.get_std_chances(), player) + + def __force_discard(self, chances, player): + if player.get_hand().get_remaining() > 3 and chances > 0: + hand_index = player.militia_input("\nPlease provide an index to identify a card from hand you would like to" + " discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): " + , int) + self.__check_discard(hand_index, player, chances) + elif self._Card__owner.get_hand().get_remaining() > 3 and chances <= 0: + print("You're out of chances to select a valid card to discard, randomly selecting for you.") + player.discard_from_hand(randint(0, self.__hand.get_remaining() - 1)) + + def __check_discard(self, index, player, chances): + if 0 > index or index >= self._Card__owner.get_hand().get_remaining(): + print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". 1 chance lost.") + self.__force_discard(chances - 1, player) + else: + print("Discarding " + player.get_hand().get_card(index).get_name() + ".") + player.discard_from_hand(index) + player.print_hand() + self.__force_discard(self._Card__owner.get_std_chances(), player) diff --git a/card/named/mine.py b/card/named/mine.py new file mode 100644 index 0000000..a667f38 --- /dev/null +++ b/card/named/mine.py @@ -0,0 +1,9 @@ +from card.basic.card_action import Action +from card.basic.card_treasure import Treasure +from card.special.card_gain_trash import CardGainTrash + + +class Mine(Action, CardGainTrash): + coin_gain = 3 + trashable_type_restriction = Treasure + gainable_type_restriction = Treasure diff --git a/card/named/moat.py b/card/named/moat.py new file mode 100644 index 0000000..9e8f76f --- /dev/null +++ b/card/named/moat.py @@ -0,0 +1,6 @@ +from card.basic.card_action import Action +from card.basic.card_reaction import Reaction + + +class Moat(Action, Reaction): + prevent_attack = True diff --git a/card/named/remodel.py b/card/named/remodel.py new file mode 100644 index 0000000..5bfda77 --- /dev/null +++ b/card/named/remodel.py @@ -0,0 +1,6 @@ +from card.basic.card_action import Action +from card.special.card_gain_trash import CardGainTrash + + +class Remodel(Action, CardGainTrash): + coin_gain = 2 diff --git a/card/named/silver.py b/card/named/silver.py new file mode 100644 index 0000000..073e8b2 --- /dev/null +++ b/card/named/silver.py @@ -0,0 +1,6 @@ +from card.basic.card_treasure import Treasure + + +class Silver(Treasure): + pile_player_rate = 40 + diff --git a/card/named/workshop.py b/card/named/workshop.py new file mode 100644 index 0000000..3166050 --- /dev/null +++ b/card/named/workshop.py @@ -0,0 +1,9 @@ +from card.basic.card_action import Action +from card.special.card_gain import CardGain + + +class Workshop(Action, CardGain): + coin_gain = 4 + + def effect(self): + self.gain_card(self.coin_gain) diff --git a/card/special/card_gain.py b/card/special/card_gain.py new file mode 100644 index 0000000..bf724c4 --- /dev/null +++ b/card/special/card_gain.py @@ -0,0 +1,41 @@ +from card.card import Card + + +class CardGain(Card): + gainable_type_restriction = None + + def gain_card(self, spending_limit): + gainable_cards = self.__get_gainable_cards(spending_limit) + self.print_card_list(gainable_cards, "Gainable Cards: ") + index = 0 + chances = self.get_owner().get_std_chances() + + while len(gainable_cards) > 0 and 0 <= index < len(gainable_cards) - 1 and chances > 0: + index = self.__get_gain_card() + + if 0 > index >= len(gainable_cards): + print("Acceptable inputs range from 0 to " + str(len(gainable_cards) - 1) + ". 1 chance lost.") + index = 0 + chances -= 1 + else: + pile_index = self.get_owner().get_table().get_pile_index_of_card(gainable_cards[index].get_name()) + print("Player " + str(self.get_owner().get_player_index()) + " drawing " + + self.get_owner().get_table().get_pile(pile_index).get_card_group().get_name() + " to hand.") + self.get_owner().get_table().get_pile(pile_index).transfer_top_card(self.get_owner().get_hand()) + self.get_owner().claim_top_card(self.get_owner().get_hand()) + chances = 0 + + def __get_gain_card(self): + return self.get_owner().get_general_input("\nPlease identify the index of which card you would like to " + "obtain: ", int) + + def __get_gainable_cards(self, spending_limit): + result = list() + + for p in self.get_owner().get_table().get_piles(): + if p.get_card_group().get_cost() <= spending_limit: + if self.gainable_type_restriction is None: + result.append(p.get_card_group()) + elif isinstance(p.get_card_group(), self.gainable_type_restriction): + result.append(p.get_card_group()) + return result diff --git a/card/special/card_gain_trash.py b/card/special/card_gain_trash.py new file mode 100644 index 0000000..0144f1a --- /dev/null +++ b/card/special/card_gain_trash.py @@ -0,0 +1,9 @@ +from card.special.card_trash import CardTrash +from card.special.card_gain import CardGain + + +class CardGainTrash(CardTrash, CardGain): + coin_gain = 0 + + def effect(self): + self.gain_card(self.trash_card_get_cost() + self.coin_gain) diff --git a/card/special/card_trash.py b/card/special/card_trash.py new file mode 100644 index 0000000..8925171 --- /dev/null +++ b/card/special/card_trash.py @@ -0,0 +1,43 @@ +from card.card import Card + + +class CardTrash(Card): + trashable_type_restriction = None + + def trash_card_get_cost(self): + tc = self.__get_trashable_cards() + self.print_card_list(tc, " Trashable Cards: ") + index = 0 + bonus = 0 + chances = self.get_owner().get_std_chances() + + while 0 < len(tc) and 0 <= index < len(tc) - 1 and chances > 0: + index = self.__get_card_to_trash() + + if index < 0 or index >= len(tc): + print("Acceptable inputs range from 0 to " + str(len(tc) - 1) + ". 1 chance lost.") + index = 0 + chances -= 1 + else: + print("Player " + str(self.get_owner().get_player_index()) + " trashing " + tc[index].get_name() + ".") + bonus = tc[index].get_cost() + self.get_owner().get_hand().transfer_card_by_card(tc[index], self.get_owner().get_table().get_trash()) + chances = 0 + return bonus + + def trash_card(self): + self.trash_card_get_cost() + + def __get_card_to_trash(self): + return self.get_owner().get_general_input("\nPlease identify the index of the desired card to trash: ", int) + + def __get_trashable_cards(self): + result = list() + + for c in self.get_owner().get_hand().get_supply(): + if c != self: + if self.trashable_type_restriction is None: + result.append(c) + elif isinstance(c, self.trashable_type_restriction): + result.append(c) + return result diff --git a/player/bots/pure_big_money.py b/player/bots/pure_big_money.py index e04b83e..6f4b724 100644 --- a/player/bots/pure_big_money.py +++ b/player/bots/pure_big_money.py @@ -1,6 +1,6 @@ from player.player import Player -from card.card import Card -#name943meats23jet +from card.basic.card_treasure import Treasure + class Pure_Big_Money(Player): def take_action(self): @@ -12,7 +12,7 @@ class Pure_Big_Money(Player): hand = self.get_hand().get_supply() for c in hand: - if c.get_type() == Card.CardType.Treasure: + if isinstance(c, Treasure): choice = hand.index(c) print(message + str(choice)) @@ -39,7 +39,10 @@ class Pure_Big_Money(Player): min_coin = self.get_hand().get_supply()[choice].get_purchase_power() for c in self.get_hand().get_supply(): - if c.get_purchase_power() < min_coin and c.get_type() != Card.CardType.Treasure: + # We want to do isinstance rather than not isinstance because we only want to evaluate this loop when we are + # evaluating an all treasure card hand as at that point the choice will be a treasure card, otherwise the + # choice will already be non-treasure and we don't need to check anything since this bot doesn't do action + if c.get_purchase_power() < min_coin and isinstance(c, Treasure): min_coin = c.get_purchase_power() choice = self.get_hand().get_supply().index(c) @@ -48,7 +51,7 @@ class Pure_Big_Money(Player): def __get_first_non_Treasure(self): for c in self.get_hand().get_supply(): - if c.get_type() != Card.CardType.Treasure: + if not isinstance(c, Treasure): return self.get_hand().get_supply().index(c) return 0 diff --git a/player/hand.py b/player/hand.py index 485ffee..0559258 100644 --- a/player/hand.py +++ b/player/hand.py @@ -2,19 +2,19 @@ from table.supply import Supply class Hand(Supply): - def contains_one_of(self, acceptible_types): + def contains_one_of(self, acceptable_class): result = False - unique_types = self.__get_unique_types() + unique_class_instances = self.__get_unique_class_instances() - for at in acceptible_types: - result |= at in unique_types + for uci in unique_class_instances: + result |= isinstance(uci, acceptable_class) return result - def get_card_type_count(self, card_type): + def get_card_type_count(self, card_class): result = 0 - for c in self._Supply__card: - if c.get_type() == card_type: + for c in self.get_supply(): + if isinstance(c, card_class): result += 1 return result @@ -22,23 +22,21 @@ class Hand(Supply): yes_no = False found_at = -1 - for c in self._Supply__card: + for c in self.get_supply(): if c.prevent_attack: - found_at = self._Supply__card.index(c) + found_at = self.get_supply().index(c) if found_at >= 0: - owner = self._Supply__card[found_at].get_owner() + owner = self.get_supply()[found_at].get_owner() yes_no = "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd " - "like to reveal " - + self._Supply__card[found_at].get_name() + " to block the " - + what_attack + " attack: ", str) + "like to reveal " + self.get_supply()[found_at].get_name() + + " to block the " + what_attack + " attack: ", str) return yes_no - def __get_unique_types(self): - unique_type = list() + def __get_unique_class_instances(self): + unique_class_instances = list() - for c in self._Supply__card: - current_type = c.get_type() - if not current_type in unique_type: - unique_type.append(current_type) - return unique_type + for c in self.get_supply(): + if c not in unique_class_instances: + unique_class_instances.append(c) + return unique_class_instances diff --git a/player/player.py b/player/player.py index 7328b9d..2c49b0d 100644 --- a/player/player.py +++ b/player/player.py @@ -2,7 +2,8 @@ from player.deck import Deck from player.discard import Discard from player.hand import Hand from player.counter import Counter -from card.card import Card +from card.basic.card_treasure import Treasure +from card.basic.card_action import Action from random import randint @@ -99,10 +100,10 @@ class Player: def discard_from_hand(self, n): self.__hand.transfer_card_by_index(n, self.__discard) - def play_card(self, acceptable_card_type, chances, counter): - if chances > 0 and self.__hand.contains_one_of(acceptable_card_type): + def play_card(self, acceptable_card_class, chances, counter): + if chances > 0 and self.__hand.contains_one_of(acceptable_card_class): hand_index = self.get_play_input("\nPlease identify a card from hand to play by providing its index: ", int) - self.__check_play_card(hand_index, counter, acceptable_card_type, chances) + self.__check_play_card(hand_index, counter, acceptable_card_class, chances) elif chances <= 0: print("You have used up all of your chances to enter a valid integer; forfeiting remaining plays.") if counter is not None: @@ -113,18 +114,17 @@ class Player: counter.int = 0 def take_action(self): - print("\nPlease play an Action, Attack, or Reaction card until you have no remaining actions.") + print("\nPlease play an Action card until you have no remaining actions.") while self.__actions.int > 0: - self.play_card([Card.CardType.Action, Card.CardType.Attack, Card.CardType.Reaction], - self.__std_chances, self.__actions) + self.play_card(Action, self.__std_chances, self.__actions) def take_buy(self): - if self.__hand.contains_one_of([Card.CardType.Treasure]): + if self.__hand.contains_one_of(Treasure): print("\nPlease play all Treasure card that you want to play.") - play_another = Counter(self.__hand.get_card_type_count(Card.CardType.Treasure)) + play_another = Counter(self.__hand.get_card_type_count(Treasure)) while play_another.int > 0: - self.play_card([Card.CardType.Treasure], self.__std_chances, play_another) + self.play_card(Treasure, self.__std_chances, play_another) self.buy_card(self.__std_chances) def buy_card(self, chances): @@ -169,15 +169,15 @@ class Player: print("\nPlayer " + str(self.__table.get_players().index(self)) + " Hand:") self.__hand.print() - def __check_play_card(self, hand_index, counter, acceptable_card_type, chances): + def __check_play_card(self, hand_index, counter, acceptable_card_class, chances): if hand_index < 0: print("You have elected to forfeit any remaining plays.") if counter is not None: counter.int = 0 elif hand_index >= self.__hand.get_remaining(): print("Acceptable inputs range from 0 to " + str(self.__hand.get_remaining() - 1) + ". 1 chance lost.") - self.play_card(acceptable_card_type, chances - 1, counter) - elif self.__hand.get_card(hand_index).get_type() in acceptable_card_type: + self.play_card(acceptable_card_class, chances - 1, counter) + elif isinstance(self.__hand.get_card(hand_index), acceptable_card_class): print("Player " + str(self.get_player_index()) + " playing: " + self.__hand.get_card(hand_index).get_name()) play_card = self.__hand.get_card(hand_index) play_card.play() @@ -187,7 +187,7 @@ class Player: self.__print() else: print("Index in bounds but not an acceptable card type. Chance to get it right reduced.") - self.play_card(acceptable_card_type, chances - 1, counter) + self.play_card(acceptable_card_class, chances - 1, counter) # The following two methods are identical under different names so they can be overridden by bot classes later def get_play_input(self, message, target_type): diff --git a/table/pile.py b/table/pile.py index 4cd30f0..b80a271 100644 --- a/table/pile.py +++ b/table/pile.py @@ -1,5 +1,6 @@ from table.supply import Supply + class Pile(Supply): def __init__(self, card): self.__card_group = card From caa3e24e7b1c0eb9b13dc7f1b94c0302d6e583d5 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:02:42 -0600 Subject: [PATCH 13/46] Delete card_action.py --- card/basic/card_action.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 card/basic/card_action.py diff --git a/card/basic/card_action.py b/card/basic/card_action.py deleted file mode 100644 index 88d78cf..0000000 --- a/card/basic/card_action.py +++ /dev/null @@ -1,5 +0,0 @@ -from card.basic.card_kingdom import Kingdom - - -class Action(Kingdom): - pass From d6e468b2c6fd84b39ef0167ba0316b96a5d7b3a4 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:02:47 -0600 Subject: [PATCH 14/46] Delete card_attack.py --- card/basic/card_attack.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 card/basic/card_attack.py diff --git a/card/basic/card_attack.py b/card/basic/card_attack.py deleted file mode 100644 index af4c9e8..0000000 --- a/card/basic/card_attack.py +++ /dev/null @@ -1,5 +0,0 @@ -from card.basic.card_kingdom import Kingdom - - -class Attack(Kingdom): - pass From 81bda535f02a0104759eb9b9eb16717447b1d17d Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:02:53 -0600 Subject: [PATCH 15/46] Delete card_curse.py --- card/basic/card_curse.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 card/basic/card_curse.py diff --git a/card/basic/card_curse.py b/card/basic/card_curse.py deleted file mode 100644 index daa9f83..0000000 --- a/card/basic/card_curse.py +++ /dev/null @@ -1,10 +0,0 @@ -from card.card import Card - - -class Curse(Card): - @staticmethod - def pile_setup(player_count): - if player_count % Card.normal_full_table < Card.normal_full_table/2: - return Card.pile_player_rate - else: - return (player_count - 1) * Card.pile_player_rate From 73d4a62dba712a1e160eca246b543214aba4bd9a Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:02:58 -0600 Subject: [PATCH 16/46] Delete card_kingdom.py --- card/basic/card_kingdom.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 card/basic/card_kingdom.py diff --git a/card/basic/card_kingdom.py b/card/basic/card_kingdom.py deleted file mode 100644 index 46b670e..0000000 --- a/card/basic/card_kingdom.py +++ /dev/null @@ -1,10 +0,0 @@ -from card.card import Card -from math import floor - - -class Kingdom(Card): - pile_player_rate = 10 - - @staticmethod - def pile_setup(player_count): - return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate From d71830c5683529bada2c41914db29e597878082f Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:04 -0600 Subject: [PATCH 17/46] Delete card_reaction.py --- card/basic/card_reaction.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 card/basic/card_reaction.py diff --git a/card/basic/card_reaction.py b/card/basic/card_reaction.py deleted file mode 100644 index 2ebf00a..0000000 --- a/card/basic/card_reaction.py +++ /dev/null @@ -1,5 +0,0 @@ -from card.basic.card_kingdom import Kingdom - - -class Reaction(Kingdom): - pass From f3621c6ac08d234443735ca46abfff4e73bfa901 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:10 -0600 Subject: [PATCH 18/46] Delete card_treasure.py --- card/basic/card_treasure.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 card/basic/card_treasure.py diff --git a/card/basic/card_treasure.py b/card/basic/card_treasure.py deleted file mode 100644 index 4206a6a..0000000 --- a/card/basic/card_treasure.py +++ /dev/null @@ -1,8 +0,0 @@ -from card.card import Card -from math import floor - - -class Treasure(Card): - @classmethod - def pile_setup(cls, player_count): - return (floor(player_count/Card.normal_full_table) + 1) * cls.pile_player_rate From 2f15c84fe6bc9c8491d02f4abcf0280ba0023f99 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:18 -0600 Subject: [PATCH 19/46] Delete card_victory.py --- card/basic/card_victory.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 card/basic/card_victory.py diff --git a/card/basic/card_victory.py b/card/basic/card_victory.py deleted file mode 100644 index e023e99..0000000 --- a/card/basic/card_victory.py +++ /dev/null @@ -1,21 +0,0 @@ -from card.card import Card -from math import floor - - -class Victory(Card): - two_player_count = 8 - four_player_count = 12 - five_player_count = 15 - six_player_count = 18 - - @classmethod - def pile_setup(cls, player_count): - if 0 < player_count % Card.normal_full_table < Card.normal_full_table/2: - supplement = cls.two_player_count - elif Card.normal_full_table/2 <= player_count % Card.normal_full_table < Card.normal_full_table - 1: - supplement = cls.four_player_count - elif player_count % Card.normal_full_table == Card.normal_full_table - 1: - supplement = cls.five_player_count - else: - supplement = cls.six_player_count - return (floor(player_count/Card.normal_full_table) * cls.six_player_count) + supplement From 49104ded039a4fad4542205bb40b58ca85680195 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:31 -0600 Subject: [PATCH 20/46] Delete cellar.py --- card/named/cellar.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 card/named/cellar.py diff --git a/card/named/cellar.py b/card/named/cellar.py deleted file mode 100644 index da3d5d5..0000000 --- a/card/named/cellar.py +++ /dev/null @@ -1,27 +0,0 @@ -from card.basic.card_action import Action - - -class Cellar(Action): - def effect(self): - hand_index = 0 - cards_discarded = 0 - have_not_run_yet = True - while self._Card__owner.get_hand().get_remaining() >= 0 and \ - 0 <= hand_index < self._Card__owner.get_hand().get_remaining() and \ - (hand_index != self._Card__owner.get_hand().get_supply().index(self) or have_not_run_yet): - hand_index = self.__get_index("Player " + str(self._Card__owner.get_player_index()) + ", input the index " - "from your hand to discard that card and gain an action, or input an " - "impossible index to end discard selection: ") - - if 0 <= hand_index < self._Card__owner.get_hand().get_remaining() and \ - hand_index != self._Card__owner.get_hand().get_supply().index(self): - self._Card__owner.discard_from_hand(hand_index) - self._Card__owner.print_hand() - cards_discarded += 1 - hand_index = self.__get_index_not_self() - have_not_run_yet = False - self._Card__owner.draw_cards(cards_discarded) - - def __get_index(self, message): - return self.__Card_owner.get_general_input(message, int) - From badf5f5fc64eb5f6d33a738e2718629d69035b85 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:37 -0600 Subject: [PATCH 21/46] Delete copper.py --- card/named/copper.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 card/named/copper.py diff --git a/card/named/copper.py b/card/named/copper.py deleted file mode 100644 index 35112e1..0000000 --- a/card/named/copper.py +++ /dev/null @@ -1,5 +0,0 @@ -from card.basic.card_treasure import Treasure - - -class Copper(Treasure): - pile_player_rate = 60 From 4bb6baaf40831a9b23541bb63f023d8f9c2322ef Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:44 -0600 Subject: [PATCH 22/46] Delete estate.py --- card/named/estate.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 card/named/estate.py diff --git a/card/named/estate.py b/card/named/estate.py deleted file mode 100644 index c913a43..0000000 --- a/card/named/estate.py +++ /dev/null @@ -1,8 +0,0 @@ -from card.basic.card_victory import Victory - - -class Estate(Victory): - two_player_count = 14 - four_player_count = 18 - five_player_count = 21 - six_player_count = 24 From d53706f6730eff736004d3459ea4f865e339920d Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:50 -0600 Subject: [PATCH 23/46] Delete gold.py --- card/named/gold.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 card/named/gold.py diff --git a/card/named/gold.py b/card/named/gold.py deleted file mode 100644 index cd81068..0000000 --- a/card/named/gold.py +++ /dev/null @@ -1,5 +0,0 @@ -from card.basic.card_treasure import Treasure - - -class Gold(Treasure): - pile_player_rate = 30 \ No newline at end of file From f1f5e38d7a42ca7da1fef03d65eb1e0953bd2d00 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:03:56 -0600 Subject: [PATCH 24/46] Delete merchant.py --- card/named/merchant.py | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 card/named/merchant.py diff --git a/card/named/merchant.py b/card/named/merchant.py deleted file mode 100644 index cf0b9b4..0000000 --- a/card/named/merchant.py +++ /dev/null @@ -1,17 +0,0 @@ -from card.basic.card_action import Action - - -class Merchant(Action): - def effect(self): - silver_card_index = self._Card__owner.get_hand().get_index_of_card_by_name("Silver") - if silver_card_index >= 0: - yes_no = self.__get_Merchant_input("'Y' if you'd like to play a silver card and gain an extra coin: ") - - if yes_no: - self._Card__owner.get_hand().transfer_card_by_card( - self._Card__owner.get_hand().get_card(silver_card_index), self._Card__owner.get_discard()) - self._Card__owner.add_purchase_power(3) - - def __get_Merchant_input(self, message): - return self.__Card_owner.get_general_input("Player " + str(self._Card__owner.get_player_index()) + ", " + - message, str) From c3ad73227513bf69cf8ce6a880ba2fb60c31f4b6 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:03 -0600 Subject: [PATCH 25/46] Delete militia.py --- card/named/militia.py | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 card/named/militia.py diff --git a/card/named/militia.py b/card/named/militia.py deleted file mode 100644 index ffc8783..0000000 --- a/card/named/militia.py +++ /dev/null @@ -1,32 +0,0 @@ -from card.basic.card_attack import Attack -from card.basic.card_action import Action -from random import randint - - -class Militia(Action, Attack): - def effect(self): - for player in self._Card__owner.get_table().get_players(): - if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()): - player.print_hand() - print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.") - self.__force_discard(self._Card__owner.get_std_chances(), player) - - def __force_discard(self, chances, player): - if player.get_hand().get_remaining() > 3 and chances > 0: - hand_index = player.militia_input("\nPlease provide an index to identify a card from hand you would like to" - " discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): " - , int) - self.__check_discard(hand_index, player, chances) - elif self._Card__owner.get_hand().get_remaining() > 3 and chances <= 0: - print("You're out of chances to select a valid card to discard, randomly selecting for you.") - player.discard_from_hand(randint(0, self.__hand.get_remaining() - 1)) - - def __check_discard(self, index, player, chances): - if 0 > index or index >= self._Card__owner.get_hand().get_remaining(): - print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". 1 chance lost.") - self.__force_discard(chances - 1, player) - else: - print("Discarding " + player.get_hand().get_card(index).get_name() + ".") - player.discard_from_hand(index) - player.print_hand() - self.__force_discard(self._Card__owner.get_std_chances(), player) From 414c66149716f41fb8c332304ab8715550234abb Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:09 -0600 Subject: [PATCH 26/46] Delete mine.py --- card/named/mine.py | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 card/named/mine.py diff --git a/card/named/mine.py b/card/named/mine.py deleted file mode 100644 index a667f38..0000000 --- a/card/named/mine.py +++ /dev/null @@ -1,9 +0,0 @@ -from card.basic.card_action import Action -from card.basic.card_treasure import Treasure -from card.special.card_gain_trash import CardGainTrash - - -class Mine(Action, CardGainTrash): - coin_gain = 3 - trashable_type_restriction = Treasure - gainable_type_restriction = Treasure From 06c3f3ce6b62e45578653732684a4111727543b4 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:16 -0600 Subject: [PATCH 27/46] Delete moat.py --- card/named/moat.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 card/named/moat.py diff --git a/card/named/moat.py b/card/named/moat.py deleted file mode 100644 index 9e8f76f..0000000 --- a/card/named/moat.py +++ /dev/null @@ -1,6 +0,0 @@ -from card.basic.card_action import Action -from card.basic.card_reaction import Reaction - - -class Moat(Action, Reaction): - prevent_attack = True From 316abed7dda1943fd82d9b4c81d9b1d352962f95 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:24 -0600 Subject: [PATCH 28/46] Delete remodel.py --- card/named/remodel.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 card/named/remodel.py diff --git a/card/named/remodel.py b/card/named/remodel.py deleted file mode 100644 index 5bfda77..0000000 --- a/card/named/remodel.py +++ /dev/null @@ -1,6 +0,0 @@ -from card.basic.card_action import Action -from card.special.card_gain_trash import CardGainTrash - - -class Remodel(Action, CardGainTrash): - coin_gain = 2 From d4e870a05d37fddf25295d0b8fc68b739e6b38d0 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:31 -0600 Subject: [PATCH 29/46] Delete silver.py --- card/named/silver.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 card/named/silver.py diff --git a/card/named/silver.py b/card/named/silver.py deleted file mode 100644 index 073e8b2..0000000 --- a/card/named/silver.py +++ /dev/null @@ -1,6 +0,0 @@ -from card.basic.card_treasure import Treasure - - -class Silver(Treasure): - pile_player_rate = 40 - From 9d24e960b9fea5412d221a7a59dbaf66e7ff0ff2 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:04:38 -0600 Subject: [PATCH 30/46] Delete workshop.py --- card/named/workshop.py | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 card/named/workshop.py diff --git a/card/named/workshop.py b/card/named/workshop.py deleted file mode 100644 index 3166050..0000000 --- a/card/named/workshop.py +++ /dev/null @@ -1,9 +0,0 @@ -from card.basic.card_action import Action -from card.special.card_gain import CardGain - - -class Workshop(Action, CardGain): - coin_gain = 4 - - def effect(self): - self.gain_card(self.coin_gain) From bf33716c4283ac0b2cb7ea3fc176daeaaf5b6618 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:05:02 -0600 Subject: [PATCH 31/46] Delete card_gain.py --- card/special/card_gain.py | 41 --------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 card/special/card_gain.py diff --git a/card/special/card_gain.py b/card/special/card_gain.py deleted file mode 100644 index bf724c4..0000000 --- a/card/special/card_gain.py +++ /dev/null @@ -1,41 +0,0 @@ -from card.card import Card - - -class CardGain(Card): - gainable_type_restriction = None - - def gain_card(self, spending_limit): - gainable_cards = self.__get_gainable_cards(spending_limit) - self.print_card_list(gainable_cards, "Gainable Cards: ") - index = 0 - chances = self.get_owner().get_std_chances() - - while len(gainable_cards) > 0 and 0 <= index < len(gainable_cards) - 1 and chances > 0: - index = self.__get_gain_card() - - if 0 > index >= len(gainable_cards): - print("Acceptable inputs range from 0 to " + str(len(gainable_cards) - 1) + ". 1 chance lost.") - index = 0 - chances -= 1 - else: - pile_index = self.get_owner().get_table().get_pile_index_of_card(gainable_cards[index].get_name()) - print("Player " + str(self.get_owner().get_player_index()) + " drawing " - + self.get_owner().get_table().get_pile(pile_index).get_card_group().get_name() + " to hand.") - self.get_owner().get_table().get_pile(pile_index).transfer_top_card(self.get_owner().get_hand()) - self.get_owner().claim_top_card(self.get_owner().get_hand()) - chances = 0 - - def __get_gain_card(self): - return self.get_owner().get_general_input("\nPlease identify the index of which card you would like to " - "obtain: ", int) - - def __get_gainable_cards(self, spending_limit): - result = list() - - for p in self.get_owner().get_table().get_piles(): - if p.get_card_group().get_cost() <= spending_limit: - if self.gainable_type_restriction is None: - result.append(p.get_card_group()) - elif isinstance(p.get_card_group(), self.gainable_type_restriction): - result.append(p.get_card_group()) - return result From 5b84778f1c65da95a07d566cf4915640fe0fe6b1 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:05:08 -0600 Subject: [PATCH 32/46] Delete card_gain_trash.py --- card/special/card_gain_trash.py | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 card/special/card_gain_trash.py diff --git a/card/special/card_gain_trash.py b/card/special/card_gain_trash.py deleted file mode 100644 index 0144f1a..0000000 --- a/card/special/card_gain_trash.py +++ /dev/null @@ -1,9 +0,0 @@ -from card.special.card_trash import CardTrash -from card.special.card_gain import CardGain - - -class CardGainTrash(CardTrash, CardGain): - coin_gain = 0 - - def effect(self): - self.gain_card(self.trash_card_get_cost() + self.coin_gain) From 3bbe17b9eac2b4ff384e6886b930f49ac7e62607 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:05:15 -0600 Subject: [PATCH 33/46] Delete card_trash.py --- card/special/card_trash.py | 43 -------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 card/special/card_trash.py diff --git a/card/special/card_trash.py b/card/special/card_trash.py deleted file mode 100644 index 8925171..0000000 --- a/card/special/card_trash.py +++ /dev/null @@ -1,43 +0,0 @@ -from card.card import Card - - -class CardTrash(Card): - trashable_type_restriction = None - - def trash_card_get_cost(self): - tc = self.__get_trashable_cards() - self.print_card_list(tc, " Trashable Cards: ") - index = 0 - bonus = 0 - chances = self.get_owner().get_std_chances() - - while 0 < len(tc) and 0 <= index < len(tc) - 1 and chances > 0: - index = self.__get_card_to_trash() - - if index < 0 or index >= len(tc): - print("Acceptable inputs range from 0 to " + str(len(tc) - 1) + ". 1 chance lost.") - index = 0 - chances -= 1 - else: - print("Player " + str(self.get_owner().get_player_index()) + " trashing " + tc[index].get_name() + ".") - bonus = tc[index].get_cost() - self.get_owner().get_hand().transfer_card_by_card(tc[index], self.get_owner().get_table().get_trash()) - chances = 0 - return bonus - - def trash_card(self): - self.trash_card_get_cost() - - def __get_card_to_trash(self): - return self.get_owner().get_general_input("\nPlease identify the index of the desired card to trash: ", int) - - def __get_trashable_cards(self): - result = list() - - for c in self.get_owner().get_hand().get_supply(): - if c != self: - if self.trashable_type_restriction is None: - result.append(c) - elif isinstance(c, self.trashable_type_restriction): - result.append(c) - return result From 83077b90b43d71c4d864829b689775c8c3676970 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:05:47 -0600 Subject: [PATCH 34/46] Rename card/card_gain.py to card/special/card_gain.py --- card/{ => special}/card_gain.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => special}/card_gain.py (100%) diff --git a/card/card_gain.py b/card/special/card_gain.py similarity index 100% rename from card/card_gain.py rename to card/special/card_gain.py From 452031d32ea7d5f9c388d9c703b561513df25ee7 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:06:05 -0600 Subject: [PATCH 35/46] Rename card/card_gain_trash.py to card/special/card_gain_trash.py --- card/{ => special}/card_gain_trash.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => special}/card_gain_trash.py (100%) diff --git a/card/card_gain_trash.py b/card/special/card_gain_trash.py similarity index 100% rename from card/card_gain_trash.py rename to card/special/card_gain_trash.py From 7b47c177b946ad3f4516dac201442a1b46e9d702 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:06:22 -0600 Subject: [PATCH 36/46] Rename card/card_trash.py to card/special/card_trash.py --- card/{ => special}/card_trash.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => special}/card_trash.py (100%) diff --git a/card/card_trash.py b/card/special/card_trash.py similarity index 100% rename from card/card_trash.py rename to card/special/card_trash.py From cfec484e8436ad7d35c2e179f252a449b71cc02c Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:06:44 -0600 Subject: [PATCH 37/46] Rename card/cellar.py to card/named/cellar.py --- card/{ => named}/cellar.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/cellar.py (100%) diff --git a/card/cellar.py b/card/named/cellar.py similarity index 100% rename from card/cellar.py rename to card/named/cellar.py From 8a09314c750c7f2bcb6d2a6501a095410bf0b70e Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:07:03 -0600 Subject: [PATCH 38/46] Rename card/merchant.py to card/named/merchant.py --- card/{ => named}/merchant.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/merchant.py (100%) diff --git a/card/merchant.py b/card/named/merchant.py similarity index 100% rename from card/merchant.py rename to card/named/merchant.py From a01fdf86dca7e7916a2e2f4baebab71ec722dce0 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:07:20 -0600 Subject: [PATCH 39/46] Rename card/militia.py to card/named/militia.py --- card/{ => named}/militia.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/militia.py (100%) diff --git a/card/militia.py b/card/named/militia.py similarity index 100% rename from card/militia.py rename to card/named/militia.py From 36ce3c22f1fd2f0df1ffbbcb9c7bab1b45c00b9b Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:07:36 -0600 Subject: [PATCH 40/46] Rename card/moat.py to card/named/moat.py --- card/{ => named}/moat.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/moat.py (100%) diff --git a/card/moat.py b/card/named/moat.py similarity index 100% rename from card/moat.py rename to card/named/moat.py From ed9a1e8b3a651e994674676dada7b40a6b68b79a Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:07:51 -0600 Subject: [PATCH 41/46] Rename card/remodel.py to card/named/remodel.py --- card/{ => named}/remodel.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/remodel.py (100%) diff --git a/card/remodel.py b/card/named/remodel.py similarity index 100% rename from card/remodel.py rename to card/named/remodel.py From eb5bc105fd454c83602ea7849db08e7a10047bba Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:08:06 -0600 Subject: [PATCH 42/46] Rename card/mine.py to card/named/mine.py --- card/{ => named}/mine.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/mine.py (100%) diff --git a/card/mine.py b/card/named/mine.py similarity index 100% rename from card/mine.py rename to card/named/mine.py From 3604e666a5bd69c8e9d75c564dd58d198ac06bea Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 13:08:21 -0600 Subject: [PATCH 43/46] Rename card/workshop.py to card/named/workshop.py --- card/{ => named}/workshop.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename card/{ => named}/workshop.py (100%) diff --git a/card/workshop.py b/card/named/workshop.py similarity index 100% rename from card/workshop.py rename to card/named/workshop.py From 03fb263288d5a765cfdc21abc93e6bc4595ccf4c Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 14:10:20 -0500 Subject: [PATCH 44/46] Add files via upload --- card/basic/card_action.py | 5 +++ card/basic/card_attack.py | 5 +++ card/basic/card_curse.py | 10 +++++ card/basic/card_kingdom.py | 10 +++++ card/basic/card_reaction.py | 5 +++ card/basic/card_treasure.py | 8 ++++ card/basic/card_victory.py | 21 ++++++++++ card/named/cellar.py | 4 +- card/named/copper.py | 5 +++ card/named/estate.py | 8 ++++ card/named/gold.py | 5 +++ card/named/merchant.py | 4 +- card/named/militia.py | 5 ++- card/named/mine.py | 11 ++--- card/named/moat.py | 5 ++- card/named/remodel.py | 5 ++- card/named/silver.py | 6 +++ card/named/workshop.py | 5 ++- card/special/card_gain.py | 20 ++++----- card/special/card_gain_trash.py | 4 +- card/special/card_trash.py | 14 +++---- game.py | 73 ++++++++++++++++++--------------- 22 files changed, 169 insertions(+), 69 deletions(-) create mode 100644 card/basic/card_action.py create mode 100644 card/basic/card_attack.py create mode 100644 card/basic/card_curse.py create mode 100644 card/basic/card_kingdom.py create mode 100644 card/basic/card_reaction.py create mode 100644 card/basic/card_treasure.py create mode 100644 card/basic/card_victory.py create mode 100644 card/named/copper.py create mode 100644 card/named/estate.py create mode 100644 card/named/gold.py create mode 100644 card/named/silver.py diff --git a/card/basic/card_action.py b/card/basic/card_action.py new file mode 100644 index 0000000..88d78cf --- /dev/null +++ b/card/basic/card_action.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Action(Kingdom): + pass diff --git a/card/basic/card_attack.py b/card/basic/card_attack.py new file mode 100644 index 0000000..af4c9e8 --- /dev/null +++ b/card/basic/card_attack.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Attack(Kingdom): + pass diff --git a/card/basic/card_curse.py b/card/basic/card_curse.py new file mode 100644 index 0000000..daa9f83 --- /dev/null +++ b/card/basic/card_curse.py @@ -0,0 +1,10 @@ +from card.card import Card + + +class Curse(Card): + @staticmethod + def pile_setup(player_count): + if player_count % Card.normal_full_table < Card.normal_full_table/2: + return Card.pile_player_rate + else: + return (player_count - 1) * Card.pile_player_rate diff --git a/card/basic/card_kingdom.py b/card/basic/card_kingdom.py new file mode 100644 index 0000000..46b670e --- /dev/null +++ b/card/basic/card_kingdom.py @@ -0,0 +1,10 @@ +from card.card import Card +from math import floor + + +class Kingdom(Card): + pile_player_rate = 10 + + @staticmethod + def pile_setup(player_count): + return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate diff --git a/card/basic/card_reaction.py b/card/basic/card_reaction.py new file mode 100644 index 0000000..2ebf00a --- /dev/null +++ b/card/basic/card_reaction.py @@ -0,0 +1,5 @@ +from card.basic.card_kingdom import Kingdom + + +class Reaction(Kingdom): + pass diff --git a/card/basic/card_treasure.py b/card/basic/card_treasure.py new file mode 100644 index 0000000..4206a6a --- /dev/null +++ b/card/basic/card_treasure.py @@ -0,0 +1,8 @@ +from card.card import Card +from math import floor + + +class Treasure(Card): + @classmethod + def pile_setup(cls, player_count): + return (floor(player_count/Card.normal_full_table) + 1) * cls.pile_player_rate diff --git a/card/basic/card_victory.py b/card/basic/card_victory.py new file mode 100644 index 0000000..e023e99 --- /dev/null +++ b/card/basic/card_victory.py @@ -0,0 +1,21 @@ +from card.card import Card +from math import floor + + +class Victory(Card): + two_player_count = 8 + four_player_count = 12 + five_player_count = 15 + six_player_count = 18 + + @classmethod + def pile_setup(cls, player_count): + if 0 < player_count % Card.normal_full_table < Card.normal_full_table/2: + supplement = cls.two_player_count + elif Card.normal_full_table/2 <= player_count % Card.normal_full_table < Card.normal_full_table - 1: + supplement = cls.four_player_count + elif player_count % Card.normal_full_table == Card.normal_full_table - 1: + supplement = cls.five_player_count + else: + supplement = cls.six_player_count + return (floor(player_count/Card.normal_full_table) * cls.six_player_count) + supplement diff --git a/card/named/cellar.py b/card/named/cellar.py index a4fd832..da3d5d5 100644 --- a/card/named/cellar.py +++ b/card/named/cellar.py @@ -1,7 +1,7 @@ -from card.card import Card +from card.basic.card_action import Action -class Cellar(Card): +class Cellar(Action): def effect(self): hand_index = 0 cards_discarded = 0 diff --git a/card/named/copper.py b/card/named/copper.py new file mode 100644 index 0000000..35112e1 --- /dev/null +++ b/card/named/copper.py @@ -0,0 +1,5 @@ +from card.basic.card_treasure import Treasure + + +class Copper(Treasure): + pile_player_rate = 60 diff --git a/card/named/estate.py b/card/named/estate.py new file mode 100644 index 0000000..c913a43 --- /dev/null +++ b/card/named/estate.py @@ -0,0 +1,8 @@ +from card.basic.card_victory import Victory + + +class Estate(Victory): + two_player_count = 14 + four_player_count = 18 + five_player_count = 21 + six_player_count = 24 diff --git a/card/named/gold.py b/card/named/gold.py new file mode 100644 index 0000000..cd81068 --- /dev/null +++ b/card/named/gold.py @@ -0,0 +1,5 @@ +from card.basic.card_treasure import Treasure + + +class Gold(Treasure): + pile_player_rate = 30 \ No newline at end of file diff --git a/card/named/merchant.py b/card/named/merchant.py index cb9df3d..cf0b9b4 100644 --- a/card/named/merchant.py +++ b/card/named/merchant.py @@ -1,7 +1,7 @@ -from card.card import Card +from card.basic.card_action import Action -class Merchant(Card): +class Merchant(Action): def effect(self): silver_card_index = self._Card__owner.get_hand().get_index_of_card_by_name("Silver") if silver_card_index >= 0: diff --git a/card/named/militia.py b/card/named/militia.py index da037bd..ffc8783 100644 --- a/card/named/militia.py +++ b/card/named/militia.py @@ -1,8 +1,9 @@ -from card.card import Card +from card.basic.card_attack import Attack +from card.basic.card_action import Action from random import randint -class Militia(Card): +class Militia(Action, Attack): def effect(self): for player in self._Card__owner.get_table().get_players(): if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()): diff --git a/card/named/mine.py b/card/named/mine.py index 3c4f81d..a667f38 100644 --- a/card/named/mine.py +++ b/card/named/mine.py @@ -1,8 +1,9 @@ -from card.card import Card -from card.card_gain_trash import CardGainTrash +from card.basic.card_action import Action +from card.basic.card_treasure import Treasure +from card.special.card_gain_trash import CardGainTrash -class Mine(CardGainTrash): +class Mine(Action, CardGainTrash): coin_gain = 3 - trashable_type_restriction = [Card.CardType.Treasure] - gainable_type_restriction = [Card.CardType.Treasure] + trashable_type_restriction = Treasure + gainable_type_restriction = Treasure diff --git a/card/named/moat.py b/card/named/moat.py index 76cdfd4..9e8f76f 100644 --- a/card/named/moat.py +++ b/card/named/moat.py @@ -1,5 +1,6 @@ -from card.card import Card +from card.basic.card_action import Action +from card.basic.card_reaction import Reaction -class Moat(Card): +class Moat(Action, Reaction): prevent_attack = True diff --git a/card/named/remodel.py b/card/named/remodel.py index 4d95eef..5bfda77 100644 --- a/card/named/remodel.py +++ b/card/named/remodel.py @@ -1,5 +1,6 @@ -from card.card_gain_trash import CardGainTrash +from card.basic.card_action import Action +from card.special.card_gain_trash import CardGainTrash -class Remodel(CardGainTrash): +class Remodel(Action, CardGainTrash): coin_gain = 2 diff --git a/card/named/silver.py b/card/named/silver.py new file mode 100644 index 0000000..073e8b2 --- /dev/null +++ b/card/named/silver.py @@ -0,0 +1,6 @@ +from card.basic.card_treasure import Treasure + + +class Silver(Treasure): + pile_player_rate = 40 + diff --git a/card/named/workshop.py b/card/named/workshop.py index 30b5fbd..3166050 100644 --- a/card/named/workshop.py +++ b/card/named/workshop.py @@ -1,7 +1,8 @@ -from card.card_gain import CardGain +from card.basic.card_action import Action +from card.special.card_gain import CardGain -class Workshop(CardGain): +class Workshop(Action, CardGain): coin_gain = 4 def effect(self): diff --git a/card/special/card_gain.py b/card/special/card_gain.py index 1020c29..bf724c4 100644 --- a/card/special/card_gain.py +++ b/card/special/card_gain.py @@ -6,9 +6,9 @@ class CardGain(Card): def gain_card(self, spending_limit): gainable_cards = self.__get_gainable_cards(spending_limit) - self._Card__print_card_list(gainable_cards, "Gainable Cards: ") + self.print_card_list(gainable_cards, "Gainable Cards: ") index = 0 - chances = self._Card__owner.get_std_chances() + chances = self.get_owner().get_std_chances() while len(gainable_cards) > 0 and 0 <= index < len(gainable_cards) - 1 and chances > 0: index = self.__get_gain_card() @@ -18,24 +18,24 @@ class CardGain(Card): index = 0 chances -= 1 else: - pile_index = self._Card__owner.get_table().get_pile_index_of_card(gainable_cards[index].get_name()) - print("Player " + str(self._Card__owner.get_player_index()) + " drawing " - + self._Card__owner.get_table().get_pile(pile_index).get_card_group().get_name() + " to hand.") - self._Card__owner.get_table().get_pile(pile_index).transfer_top_card(self._Card__owner.get_hand()) - self._Card__owner.claim_top_card(self._Card__owner.get_hand()) + pile_index = self.get_owner().get_table().get_pile_index_of_card(gainable_cards[index].get_name()) + print("Player " + str(self.get_owner().get_player_index()) + " drawing " + + self.get_owner().get_table().get_pile(pile_index).get_card_group().get_name() + " to hand.") + self.get_owner().get_table().get_pile(pile_index).transfer_top_card(self.get_owner().get_hand()) + self.get_owner().claim_top_card(self.get_owner().get_hand()) chances = 0 def __get_gain_card(self): - return self.__Card_owner.get_general_input("\nPlease identify the index of which card you would like to " + return self.get_owner().get_general_input("\nPlease identify the index of which card you would like to " "obtain: ", int) def __get_gainable_cards(self, spending_limit): result = list() - for p in self._Card__owner.get_table().get_piles(): + for p in self.get_owner().get_table().get_piles(): if p.get_card_group().get_cost() <= spending_limit: if self.gainable_type_restriction is None: result.append(p.get_card_group()) - elif p.get_card_group().get_type() in self.gainable_type_restriction: + elif isinstance(p.get_card_group(), self.gainable_type_restriction): result.append(p.get_card_group()) return result diff --git a/card/special/card_gain_trash.py b/card/special/card_gain_trash.py index c68bd91..0144f1a 100644 --- a/card/special/card_gain_trash.py +++ b/card/special/card_gain_trash.py @@ -1,5 +1,5 @@ -from card.card_trash import CardTrash -from card.card_gain import CardGain +from card.special.card_trash import CardTrash +from card.special.card_gain import CardGain class CardGainTrash(CardTrash, CardGain): diff --git a/card/special/card_trash.py b/card/special/card_trash.py index 5d6d198..8925171 100644 --- a/card/special/card_trash.py +++ b/card/special/card_trash.py @@ -6,10 +6,10 @@ class CardTrash(Card): def trash_card_get_cost(self): tc = self.__get_trashable_cards() - self._Card__print_card_list(tc, " Trashable Cards: ") + self.print_card_list(tc, " Trashable Cards: ") index = 0 bonus = 0 - chances = self._Card__owner.get_std_chances() + chances = self.get_owner().get_std_chances() while 0 < len(tc) and 0 <= index < len(tc) - 1 and chances > 0: index = self.__get_card_to_trash() @@ -19,9 +19,9 @@ class CardTrash(Card): index = 0 chances -= 1 else: - print("Player " + str(self._Card__owner.get_player_index()) + " trashing " + tc[index].get_name() + ".") + print("Player " + str(self.get_owner().get_player_index()) + " trashing " + tc[index].get_name() + ".") bonus = tc[index].get_cost() - self._Card__owner.get_hand().transfer_card_by_card(tc[index], self._Card__owner.get_table().get_trash()) + self.get_owner().get_hand().transfer_card_by_card(tc[index], self.get_owner().get_table().get_trash()) chances = 0 return bonus @@ -29,15 +29,15 @@ class CardTrash(Card): self.trash_card_get_cost() def __get_card_to_trash(self): - return self.__Card_owner.get_general_input("\nPlease identify the index of the desired card to trash: ", int) + return self.get_owner().get_general_input("\nPlease identify the index of the desired card to trash: ", int) def __get_trashable_cards(self): result = list() - for c in self._Card__owner.get_hand().get_supply(): + for c in self.get_owner().get_hand().get_supply(): if c != self: if self.trashable_type_restriction is None: result.append(c) - elif c.get_type() in self.trashable_type_restriction: + elif isinstance(c, self.trashable_type_restriction): result.append(c) return result diff --git a/game.py b/game.py index 8794d6c..516a5ae 100644 --- a/game.py +++ b/game.py @@ -1,14 +1,20 @@ from table.table import Table from player.human import Human from player.bots.pure_big_money import Pure_Big_Money -from card.card import Card -from card.militia import Militia -from card.moat import Moat -from card.cellar import Cellar -from card.merchant import Merchant -from card.mine import Mine -from card.remodel import Remodel -from card.workshop import Workshop +from card.basic.card_action import Action +from card.basic.card_curse import Curse +from card.basic.card_victory import Victory +from card.named.estate import Estate +from card.named.copper import Copper +from card.named.silver import Silver +from card.named.gold import Gold +from card.named.militia import Militia +from card.named.moat import Moat +from card.named.cellar import Cellar +from card.named.merchant import Merchant +from card.named.mine import Mine +from card.named.remodel import Remodel +from card.named.workshop import Workshop def main(): @@ -31,14 +37,15 @@ def setup_new_game(game_list, parameter, card_info): index = 0 for p in parameter[2:]: if p: - for i in range(card_info[index][9]): - card = card_info[index][8](card_info[index][0], card_info[index][1], card_info[index][2], - card_info[index][3], card_info[index][4], card_info[index][5], - card_info[index][6], card_info[index][7], None) + for i in range(card_info[index][7].pile_setup(humans + bots)): + card = card_info[index][7](card_info[index][0], card_info[index][1], card_info[index][2], + card_info[index][3], card_info[index][4], card_info[index][5], + card_info[index][6], None) if i == 0: t.create_pile(card) else: t.get_pile(t.get_pile_index_of_card(card_info[index][0])).add_card(card) + card_info[index][7].setup() index += 1 for i in range(humans): @@ -62,25 +69,25 @@ def get_game_parameters(): def get_card_info(): - # 0 1 2 3 4 5 6 7 8 9 - # [name, cost, cardtype, v, c, a, b, d, class, count] - values to pass to Card() - return [["Copper", 0, Card.CardType.Treasure, 0, 1, 0, 0, 0, Card, 60], # 1 - ["Silver", 3, Card.CardType.Treasure, 0, 2, 0, 0, 0, Card, 40], # 2 - ["Gold", 6, Card.CardType.Treasure, 0, 3, 0, 0, 0, Card, 30], # 3 - ["Estate", 2, Card.CardType.Victory, 1, 0, 0, 0, 0, Card, 40], # 4 - ["Dutchy", 5, Card.CardType.Victory, 3, 0, 0, 0, 0, Card, 12], # 5 - ["Province", 8, Card.CardType.Victory, 6, 0, 0, 0, 0, Card, 12], # 6 - ["Curse", 0, Card.CardType.Curse, -1, 0, 0, 0, 0, Card, 10], # 7 - ["Cellar", 2, Card.CardType.Action, 0, 0, 1, 0, 0, Cellar, 10], # 8 - ["Market", 5, Card.CardType.Action, 0, 1, 1, 1, 1, Card, 10], # 9 - ["Merchant", 3, Card.CardType.Action, 0, 0, 1, 0, 1, Merchant, 10], # 10 - ["Militia", 4, Card.CardType.Attack, 0, 2, 0, 0, 0, Militia, 10], # 11 - ["Mine", 5, Card.CardType.Action, 0, 0, 0, 0, 0, Mine, 10], # 12 - ["Moat", 2, Card.CardType.Reaction, 0, 0, 0, 0, 2, Moat, 10], # 13 - ["Remodel", 4, Card.CardType.Action, 0, 0, 0, 0, 0, Remodel, 10], # 14 - ["Smithy", 4, Card.CardType.Action, 0, 0, 0, 0, 3, Card, 10], # 15 - ["Village", 3, Card.CardType.Action, 0, 0, 2, 0, 1, Card, 10], # 16 - ["Workshop", 4, Card.CardType.Action, 0, 0, 0, 0, 0, Workshop, 10]] # 17 + # 0 1 2 3 4 5 6 7 + # [name, cost, v, c, a, b, d, class] - values to pass to Card() + return [["Copper", 0, 0, 1, 0, 0, 0, Copper], # 0 + ["Silver", 3, 0, 2, 0, 0, 0, Silver], # 1 + ["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2 + ["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3 + ["Dutchy", 5, 3, 0, 0, 0, 0, Victory], # 4 + ["Province", 8, 6, 0, 0, 0, 0, Victory], # 5 + ["Curse", 0, -1, 0, 0, 0, 0, Curse], # 6 + ["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7 + ["Market", 5, 0, 1, 1, 1, 1, Action], # 8 + ["Merchant", 3, 0, 0, 1, 0, 1, Merchant], # 9 + ["Militia", 4, 0, 2, 0, 0, 0, Militia], # 10 + ["Mine", 5, 0, 0, 0, 0, 0, Mine], # 11 + ["Moat", 2, 0, 0, 0, 0, 2, Moat], # 12 + ["Remodel", 4, 0, 0, 0, 0, 0, Remodel], # 13 + ["Smithy", 4, 0, 0, 0, 0, 3, Action], # 14 + ["Village", 3, 0, 0, 2, 0, 1, Action], # 15 + ["Workshop", 4, 0, 0, 0, 0, 0, Workshop]] # 16 # Big Money # ["Adventurer", # ["Bureaucrat", @@ -107,8 +114,8 @@ def get_card_info(): def get_starting_deck(): - # return [["Copper", 7], ["Estate", 3]] - return [["Market", 2], ["Merchant", 2], ["Smithy", 2], ["Village", 2], ["Moat", 2]] + return [["Copper", 7], ["Estate", 3]] + # return [["Market", 2], ["Merchant", 2], ["Smithy", 2], ["Village", 2], ["Moat", 2]] # return [["Militia", 4], ["Cellar", 3], ["Moat", 3]] # return [["Silver", 7], ["Merchant", 3]] # return [["Copper", 4], ["Mine", 2], ["Remodel", 2], ["Workshop", 2]] From e3ff6416ff28dd1770c8bd7e147529b587c5af8e Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 23:30:39 -0500 Subject: [PATCH 45/46] Add files via upload Generalized out attack cards. Fixed bugs. --- card/basic/card_attack.py | 8 +++++++- card/basic/card_curse.py | 14 +++++++------- card/basic/card_kingdom.py | 6 +++--- card/basic/card_treasure.py | 2 +- card/card.py | 4 +++- card/named/militia.py | 21 ++++++++++----------- card/named/moat.py | 6 +++++- card/named/province.py | 5 +++++ game.py | 5 +++-- player/bots/pure_big_money.py | 2 +- player/discard.py | 6 ++++++ player/hand.py | 17 ++++------------- player/human.py | 4 ++-- player/player.py | 9 ++++++--- table/supply.py | 3 ++- table/table.py | 33 +++++++++++++++++++++++---------- 16 files changed, 88 insertions(+), 57 deletions(-) create mode 100644 card/named/province.py diff --git a/card/basic/card_attack.py b/card/basic/card_attack.py index af4c9e8..d3acc68 100644 --- a/card/basic/card_attack.py +++ b/card/basic/card_attack.py @@ -2,4 +2,10 @@ from card.basic.card_kingdom import Kingdom class Attack(Kingdom): - pass + def effect(self): + for player in self.get_owner().get_table().get_players(): + if self.get_owner() != player and not player.get_hand().reaction_blocks_attack(self.get_name()): + self.attack(player) + + def attack(self, player): + pass diff --git a/card/basic/card_curse.py b/card/basic/card_curse.py index daa9f83..185531c 100644 --- a/card/basic/card_curse.py +++ b/card/basic/card_curse.py @@ -1,10 +1,10 @@ -from card.card import Card +from card.basic.card_victory import Victory -class Curse(Card): - @staticmethod - def pile_setup(player_count): - if player_count % Card.normal_full_table < Card.normal_full_table/2: - return Card.pile_player_rate +class Curse(Victory): + @classmethod + def pile_setup(cls, player_count): + if player_count % cls.normal_full_table < cls.normal_full_table/2: + return Victory.pile_player_rate else: - return (player_count - 1) * Card.pile_player_rate + return (player_count - 1) * cls.pile_player_rate diff --git a/card/basic/card_kingdom.py b/card/basic/card_kingdom.py index 46b670e..77b6075 100644 --- a/card/basic/card_kingdom.py +++ b/card/basic/card_kingdom.py @@ -5,6 +5,6 @@ from math import floor class Kingdom(Card): pile_player_rate = 10 - @staticmethod - def pile_setup(player_count): - return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate + @classmethod + def pile_setup(cls, player_count): + return (floor(player_count/cls.normal_full_table) + 1) * cls.pile_player_rate diff --git a/card/basic/card_treasure.py b/card/basic/card_treasure.py index 4206a6a..f16fdce 100644 --- a/card/basic/card_treasure.py +++ b/card/basic/card_treasure.py @@ -5,4 +5,4 @@ from math import floor class Treasure(Card): @classmethod def pile_setup(cls, player_count): - return (floor(player_count/Card.normal_full_table) + 1) * cls.pile_player_rate + return (floor(player_count/cls.normal_full_table) + 1) * cls.pile_player_rate diff --git a/card/card.py b/card/card.py index 35c41b3..6dcffa7 100644 --- a/card/card.py +++ b/card/card.py @@ -1,5 +1,4 @@ class Card: - prevent_attack = False normal_full_table = 6 pile_player_rate = 10 @@ -24,6 +23,9 @@ class Card: # This is here so that 'special' card can override this function so that unique card effects can happen. pass + def react(self, what_attack): + return False + @classmethod def pile_setup(cls, player_count): # This is here so that each card can override this function so that the right number of . diff --git a/card/named/militia.py b/card/named/militia.py index ffc8783..6711e1b 100644 --- a/card/named/militia.py +++ b/card/named/militia.py @@ -4,12 +4,10 @@ from random import randint class Militia(Action, Attack): - def effect(self): - for player in self._Card__owner.get_table().get_players(): - if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()): - player.print_hand() - print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.") - self.__force_discard(self._Card__owner.get_std_chances(), player) + def attack(self, player): + player.print_hand() + print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.") + self.__force_discard(self.get_owner().get_std_chances(), player) def __force_discard(self, chances, player): if player.get_hand().get_remaining() > 3 and chances > 0: @@ -17,16 +15,17 @@ class Militia(Action, Attack): " discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): " , int) self.__check_discard(hand_index, player, chances) - elif self._Card__owner.get_hand().get_remaining() > 3 and chances <= 0: + elif self.get_owner().get_hand().get_remaining() > 3 and chances <= 0: print("You're out of chances to select a valid card to discard, randomly selecting for you.") - player.discard_from_hand(randint(0, self.__hand.get_remaining() - 1)) + player.discard_from_hand(randint(0, self.get_owner().get_hand().get_remaining() - 1)) def __check_discard(self, index, player, chances): - if 0 > index or index >= self._Card__owner.get_hand().get_remaining(): - print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". 1 chance lost.") + if 0 > index >= player.get_hand().get_remaining(): + print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". " + str(chances - 1) + + "chances to input a valid index.") self.__force_discard(chances - 1, player) else: print("Discarding " + player.get_hand().get_card(index).get_name() + ".") player.discard_from_hand(index) player.print_hand() - self.__force_discard(self._Card__owner.get_std_chances(), player) + self.__force_discard(self.get_owner().get_std_chances(), player) diff --git a/card/named/moat.py b/card/named/moat.py index 9e8f76f..d15679b 100644 --- a/card/named/moat.py +++ b/card/named/moat.py @@ -3,4 +3,8 @@ from card.basic.card_reaction import Reaction class Moat(Action, Reaction): - prevent_attack = True + def react(self, what_attack): + owner = self.get_owner() + return "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd " + "like to reveal " + str(self) + " to block the " + str(what_attack) + + " attack: ", str) diff --git a/card/named/province.py b/card/named/province.py new file mode 100644 index 0000000..1f0eec4 --- /dev/null +++ b/card/named/province.py @@ -0,0 +1,5 @@ +from card.basic.card_victory import Victory + + +class Province(Victory): + pass diff --git a/game.py b/game.py index 516a5ae..91c1d80 100644 --- a/game.py +++ b/game.py @@ -4,6 +4,7 @@ from player.bots.pure_big_money import Pure_Big_Money from card.basic.card_action import Action from card.basic.card_curse import Curse from card.basic.card_victory import Victory +from card.named.province import Province from card.named.estate import Estate from card.named.copper import Copper from card.named.silver import Silver @@ -65,7 +66,7 @@ def setup_new_game(game_list, parameter, card_info): def get_game_parameters(): # humans, bots, card #1, card #2, ... etc - return [1, 1, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True] + return [2, 1, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True] def get_card_info(): @@ -76,7 +77,7 @@ def get_card_info(): ["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2 ["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3 ["Dutchy", 5, 3, 0, 0, 0, 0, Victory], # 4 - ["Province", 8, 6, 0, 0, 0, 0, Victory], # 5 + ["Province", 8, 6, 0, 0, 0, 0, Province], # 5 ["Curse", 0, -1, 0, 0, 0, 0, Curse], # 6 ["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7 ["Market", 5, 0, 1, 1, 1, 1, Action], # 8 diff --git a/player/bots/pure_big_money.py b/player/bots/pure_big_money.py index 6f4b724..8513dd3 100644 --- a/player/bots/pure_big_money.py +++ b/player/bots/pure_big_money.py @@ -20,7 +20,7 @@ class Pure_Big_Money(Player): #This method will only be called when it is time to buy things, a very simple logic will decide its action. def get_buy_input(self, message, target_type): - coin = self._Player__purchase_power + coin = self.get_coin() choice = -1 if coin >= 8: diff --git a/player/discard.py b/player/discard.py index 3ecf828..8c43b82 100644 --- a/player/discard.py +++ b/player/discard.py @@ -6,3 +6,9 @@ class Discard(Supply): while self.get_remaining() > 0: self.transfer_top_card(deck) deck.shuffle() + + def print(self): + if len(self.get_supply()) > 0: + print("Discard shows " + str(self.get_top_card()) + " face up.") + else: + print("Discard is empty.") diff --git a/player/hand.py b/player/hand.py index 0559258..87d1959 100644 --- a/player/hand.py +++ b/player/hand.py @@ -18,20 +18,11 @@ class Hand(Supply): result += 1 return result - def blocks_attack(self, what_attack): - yes_no = False - found_at = -1 - + def reaction_blocks_attack(self, what_attack): + attack_blocked = False for c in self.get_supply(): - if c.prevent_attack: - found_at = self.get_supply().index(c) - - if found_at >= 0: - owner = self.get_supply()[found_at].get_owner() - yes_no = "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd " - "like to reveal " + self.get_supply()[found_at].get_name() + - " to block the " + what_attack + " attack: ", str) - return yes_no + attack_blocked |= c.react(what_attack) + return attack_blocked def __get_unique_class_instances(self): unique_class_instances = list() diff --git a/player/human.py b/player/human.py index 9486eb9..b06cb39 100644 --- a/player/human.py +++ b/player/human.py @@ -5,5 +5,5 @@ class Human(Player): def __str__(self): return "Player " + str(self.get_player_index()) + " (human)" - def militia_input(self, message): - return self.get_general_input(message) + def militia_input(self, message, target_type): + return self.get_general_input(message, target_type) diff --git a/player/player.py b/player/player.py index 2c49b0d..0c492e1 100644 --- a/player/player.py +++ b/player/player.py @@ -42,6 +42,9 @@ class Player: def get_player_index(self): return self.__table.get_players().index(self) + def get_coin(self): + return self.__purchase_power + def get_score(self): score = 0 @@ -129,7 +132,7 @@ class Player: def buy_card(self, chances): self.__table.print() - while self.__buys > 0 and not self.__table.are_there_any_empty_piles() and chances > 0: + while self.__buys > 0 and not self.__table.are_there_three_empty_piles() and chances > 0: pile_index = self.get_buy_input("\nPlease choose a pile from the table that you'd like to purchase: ", int) if pile_index < 0: @@ -232,7 +235,6 @@ class Player: return True def __print_discard(self): - print("\nPlayer " + str(self.__table.get_players().index(self)) + " Discard:") self.__discard.print() def __print_deck(self): @@ -244,8 +246,9 @@ class Player: print("Actions: " + str(self.__actions.int)) print("Buys: " + str(self.__buys)) print("Coin: " + str(self.__purchase_power)) - self.print_hand() + print("Deck Remaining: " + str(self.__deck.get_remaining())) self.__print_discard() + self.print_hand() print("") def __turn_setup(self): diff --git a/table/supply.py b/table/supply.py index 86d4d79..6157e7a 100644 --- a/table/supply.py +++ b/table/supply.py @@ -43,7 +43,8 @@ class Supply: return self.__card[n] def get_top_card(self): - return self.__card[len(self.__card) - 1] + if len(self.__card) > 0: + return self.__card[len(self.__card) - 1] def get_remaining(self): return len(self.__card) diff --git a/table/table.py b/table/table.py index 4a78636..2adb2dd 100644 --- a/table/table.py +++ b/table/table.py @@ -1,5 +1,6 @@ from table.trash import Trash from table.pile import Pile +from card.named.province import Province class Table: @@ -45,22 +46,34 @@ class Table: result = self.__pile.index(p) return result - def are_there_any_empty_piles(self): - result = False + def are_there_three_empty_piles(self): + count = 0 for p in self.__pile: - result = result or p.get_remaining() == 0 - return result + if p.get_remaining() == 0: + count += 1 + return count > 2 + + def has_provinces_run_out(self): + for p in self.__pile: + if isinstance(p.get_card_group(), Province): + return p.get_remaining() == 0 + return False + + def should_game_end(self): + return self.are_there_three_empty_piles() or self. has_provinces_run_out() def play(self): - turn = 0 - # turn < 10 is for testing, otherwise endless as buying card is not yet done - while not self.are_there_any_empty_piles(): # and turn < 10: + player_turn = 0 + should_continue = True + while should_continue: + # game ends after + should_continue = not self.should_game_end() or player_turn % len(self.__player) != 0 self.print() - self.__player[turn % len(self.__player)].take_turn() - turn += 1 + self.__player[player_turn % len(self.__player)].take_turn() + player_turn += 1 else: self.print() - print("\n\nGame had " + str(turn) + " turns in " + str(turn/len(self.__player)) + " rounds.") + print("\n\nGame had " + str(player_turn) + " turns in " + str(player_turn/len(self.__player)) + " rounds.") for p in self.__player: print("" + str(p) + " scored " + str(p.get_score()) + " points.") if p.get_score() > self.__winning_score: From 8788b0e777bb8a4f3d936d9f5c34b291662db176 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Wed, 10 Jan 2018 22:31:31 -0600 Subject: [PATCH 46/46] Update README.md --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e5d86ef..43e422b 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,10 @@ Things done: 6) Input safety Things to do: -1) Make end of game conditions match actual end of game conditions -2) Testing classes -3) Turn Timer -4) Django server and hosting -5) HTML5 frontend -6) Multiplayer -7) Remaining 2nd Edition Base Cards: Bureaucrat, Chapel, Feast, Laboratory, Moneylender, Throne Room, Council Room, Festival, Library, Harbringer, Vassal, Gardens, Poacher, Bandit, Witch, Artisan, & Sentry -8) Choosing play sets +1) Testing classes +2) Turn Timer +3) Django server and hosting +4) HTML5 frontend +5) Multiplayer +6) Remaining 2nd Edition Base Cards: Bureaucrat, Chapel, Feast, Laboratory, Moneylender, Throne Room, Council Room, Festival, Library, Harbringer, Vassal, Gardens, Poacher, Bandit, Witch, Artisan, & Sentry +7) Choosing play sets