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
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
diff --git a/_windows/laf.xml b/_windows/laf.xml
index c1f98d9..dbf49b4 100644
--- a/_windows/laf.xml
+++ b/_windows/laf.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
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..d3acc68
--- /dev/null
+++ b/card/basic/card_attack.py
@@ -0,0 +1,11 @@
+from card.basic.card_kingdom import Kingdom
+
+
+class Attack(Kingdom):
+ 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
new file mode 100644
index 0000000..185531c
--- /dev/null
+++ b/card/basic/card_curse.py
@@ -0,0 +1,10 @@
+from card.basic.card_victory import Victory
+
+
+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) * cls.pile_player_rate
diff --git a/card/basic/card_kingdom.py b/card/basic/card_kingdom.py
new file mode 100644
index 0000000..77b6075
--- /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
+
+ @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_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..f16fdce
--- /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/cls.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..6dcffa7 100644
--- a/card/card.py
+++ b/card/card.py
@@ -1,22 +1,11 @@
-from enum import Enum, auto
-
-
class Card:
- class CardType(Enum):
- Treasure = auto()
- Action = auto()
- Reaction = auto()
- Attack = auto()
- Victory = auto()
- Curse = auto()
+ normal_full_table = 6
+ pile_player_rate = 10
- prevent_attack = False
-
- 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 +23,22 @@ class Card:
# This is here so that 'special' card can override this function so that unique card effects can happen.
pass
- def setup(self):
+ 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 .
+ 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 +55,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 +72,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/mine.py b/card/mine.py
deleted file mode 100644
index 3c4f81d..0000000
--- a/card/mine.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from card.card import Card
-from card.card_gain_trash import CardGainTrash
-
-
-class Mine(CardGainTrash):
- coin_gain = 3
- trashable_type_restriction = [Card.CardType.Treasure]
- gainable_type_restriction = [Card.CardType.Treasure]
diff --git a/card/moat.py b/card/moat.py
deleted file mode 100644
index 76cdfd4..0000000
--- a/card/moat.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from card.card import Card
-
-
-class Moat(Card):
- prevent_attack = True
diff --git a/card/cellar.py b/card/named/cellar.py
similarity index 92%
rename from card/cellar.py
rename to card/named/cellar.py
index a4fd832..da3d5d5 100644
--- a/card/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/merchant.py b/card/named/merchant.py
similarity index 88%
rename from card/merchant.py
rename to card/named/merchant.py
index cb9df3d..cf0b9b4 100644
--- a/card/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/militia.py b/card/named/militia.py
similarity index 51%
rename from card/militia.py
rename to card/named/militia.py
index da037bd..6711e1b 100644
--- a/card/militia.py
+++ b/card/named/militia.py
@@ -1,14 +1,13 @@
-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):
- 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)
+class Militia(Action, Attack):
+ 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:
@@ -16,16 +15,17 @@ class Militia(Card):
" 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/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..d15679b
--- /dev/null
+++ b/card/named/moat.py
@@ -0,0 +1,10 @@
+from card.basic.card_action import Action
+from card.basic.card_reaction import Reaction
+
+
+class Moat(Action, Reaction):
+ 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/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/remodel.py b/card/remodel.py
deleted file mode 100644
index 4d95eef..0000000
--- a/card/remodel.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from card.card_gain_trash import CardGainTrash
-
-
-class Remodel(CardGainTrash):
- coin_gain = 2
diff --git a/card/card_gain.py b/card/special/card_gain.py
similarity index 50%
rename from card/card_gain.py
rename to card/special/card_gain.py
index 1020c29..bf724c4 100644
--- a/card/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/card_gain_trash.py b/card/special/card_gain_trash.py
similarity index 58%
rename from card/card_gain_trash.py
rename to card/special/card_gain_trash.py
index c68bd91..0144f1a 100644
--- a/card/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/card_trash.py b/card/special/card_trash.py
similarity index 56%
rename from card/card_trash.py
rename to card/special/card_trash.py
index 5d6d198..8925171 100644
--- a/card/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/card/workshop.py b/card/workshop.py
deleted file mode 100644
index 30b5fbd..0000000
--- a/card/workshop.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from card.card_gain import CardGain
-
-
-class Workshop(CardGain):
- coin_gain = 4
-
- def effect(self):
- self.gain_card(self.coin_gain)
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
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
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
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
diff --git a/editor.xml b/editor.xml
index e8334e3..66a0938 100644
--- a/editor.xml
+++ b/editor.xml
@@ -3,7 +3,8 @@
-
-
+
+
+
\ No newline at end of file
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
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
diff --git a/game.py b/game.py
index 8794d6c..91c1d80 100644
--- a/game.py
+++ b/game.py
@@ -1,14 +1,21 @@
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.province import Province
+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 +38,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):
@@ -58,29 +66,29 @@ 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():
- # 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, 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
+ ["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 +115,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]]
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
diff --git a/player/bots/pure_big_money.py b/player/bots/pure_big_money.py
index e04b83e..8513dd3 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))
@@ -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:
@@ -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/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 485ffee..87d1959 100644
--- a/player/hand.py
+++ b/player/hand.py
@@ -2,43 +2,32 @@ 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
- 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():
+ attack_blocked |= c.react(what_attack)
+ return attack_blocked
- for c in self._Supply__card:
- if c.prevent_attack:
- found_at = self._Supply__card.index(c)
+ def __get_unique_class_instances(self):
+ unique_class_instances = list()
- if found_at >= 0:
- owner = self._Supply__card[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)
- return yes_no
-
- def __get_unique_types(self):
- unique_type = 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/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 7328b9d..0c492e1 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
@@ -41,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
@@ -99,10 +103,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,23 +117,22 @@ 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):
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:
@@ -169,15 +172,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 +190,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):
@@ -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/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
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:
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