mirror of
https://github.com/neogeek23/Dominion-Strategy-Simulator.git
synced 2026-02-04 11:08:18 +00:00
PY-2017.3 <Brad@Libra Merge branch 'master'
Conflicts: _windows/laf.xml editor.xml
This commit is contained in:
commit
3d8cf58e5a
15
README.md
15
README.md
@ -11,11 +11,10 @@ Things done:
|
|||||||
6) Input safety
|
6) Input safety
|
||||||
|
|
||||||
Things to do:
|
Things to do:
|
||||||
1) Make end of game conditions match actual end of game conditions
|
1) Testing classes
|
||||||
2) Testing classes
|
2) Turn Timer
|
||||||
3) Turn Timer
|
3) Django server and hosting
|
||||||
4) Django server and hosting
|
4) HTML5 frontend
|
||||||
5) HTML5 frontend
|
5) Multiplayer
|
||||||
6) 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) 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
|
||||||
8) Choosing play sets
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="Git.Application.Settings">
|
|
||||||
<option name="SSH_EXECUTABLE" value="IDEA_SSH" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<application>
|
<application>
|
||||||
<component name="LafManager">
|
<component name="LafManager">
|
||||||
<laf class-name="com.intellij.ide.ui.laf.darcula.DarculaLaf" />
|
<laf class-name="com.intellij.ide.ui.laf.IntelliJLaf" />
|
||||||
</component>
|
</component>
|
||||||
</application>
|
</application>
|
||||||
5
card/basic/card_action.py
Normal file
5
card/basic/card_action.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from card.basic.card_kingdom import Kingdom
|
||||||
|
|
||||||
|
|
||||||
|
class Action(Kingdom):
|
||||||
|
pass
|
||||||
11
card/basic/card_attack.py
Normal file
11
card/basic/card_attack.py
Normal file
@ -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
|
||||||
10
card/basic/card_curse.py
Normal file
10
card/basic/card_curse.py
Normal file
@ -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
|
||||||
10
card/basic/card_kingdom.py
Normal file
10
card/basic/card_kingdom.py
Normal file
@ -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
|
||||||
5
card/basic/card_reaction.py
Normal file
5
card/basic/card_reaction.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from card.basic.card_kingdom import Kingdom
|
||||||
|
|
||||||
|
|
||||||
|
class Reaction(Kingdom):
|
||||||
|
pass
|
||||||
8
card/basic/card_treasure.py
Normal file
8
card/basic/card_treasure.py
Normal file
@ -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
|
||||||
21
card/basic/card_victory.py
Normal file
21
card/basic/card_victory.py
Normal file
@ -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
|
||||||
51
card/card.py
51
card/card.py
@ -1,22 +1,11 @@
|
|||||||
from enum import Enum, auto
|
|
||||||
|
|
||||||
|
|
||||||
class Card:
|
class Card:
|
||||||
class CardType(Enum):
|
normal_full_table = 6
|
||||||
Treasure = auto()
|
pile_player_rate = 10
|
||||||
Action = auto()
|
|
||||||
Reaction = auto()
|
|
||||||
Attack = auto()
|
|
||||||
Victory = auto()
|
|
||||||
Curse = auto()
|
|
||||||
|
|
||||||
prevent_attack = False
|
def __init__(self, name, cost, value, coin, action, buy, draw, owner):
|
||||||
|
|
||||||
def __init__(self, name, cost, cardtype, value, coin, action, buy, draw, owner):
|
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self.__cost = cost
|
self.__cost = cost
|
||||||
self.__coin = coin
|
self.__coin = coin
|
||||||
self.__type = cardtype
|
|
||||||
self.__action = action
|
self.__action = action
|
||||||
self.__buy = buy
|
self.__buy = buy
|
||||||
self.__draw = draw
|
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.
|
# This is here so that 'special' card can override this function so that unique card effects can happen.
|
||||||
pass
|
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.
|
# This is here so that 'special' card can override this function so that unique card setup effects can happen.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return self.__name
|
return self.__name
|
||||||
|
|
||||||
def get_type(self):
|
|
||||||
return self.__type
|
|
||||||
|
|
||||||
def get_points(self):
|
def get_points(self):
|
||||||
return self.__value
|
return self.__value
|
||||||
|
|
||||||
@ -60,7 +55,15 @@ class Card:
|
|||||||
return self.__owner
|
return self.__owner
|
||||||
|
|
||||||
def identify(self):
|
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):
|
def __get_index_not_self(self):
|
||||||
result = -1
|
result = -1
|
||||||
@ -69,13 +72,5 @@ class Card:
|
|||||||
result = self._Card__owner.get_hand().get_player_index()
|
result = self._Card__owner.get_hand().get_player_index()
|
||||||
return result
|
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):
|
def __str__(self):
|
||||||
return "A " + self.__name + " card."
|
return "a " + self.__name + " card"
|
||||||
|
|||||||
@ -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]
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
from card.card import Card
|
|
||||||
|
|
||||||
|
|
||||||
class Moat(Card):
|
|
||||||
prevent_attack = True
|
|
||||||
@ -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):
|
def effect(self):
|
||||||
hand_index = 0
|
hand_index = 0
|
||||||
cards_discarded = 0
|
cards_discarded = 0
|
||||||
5
card/named/copper.py
Normal file
5
card/named/copper.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from card.basic.card_treasure import Treasure
|
||||||
|
|
||||||
|
|
||||||
|
class Copper(Treasure):
|
||||||
|
pile_player_rate = 60
|
||||||
8
card/named/estate.py
Normal file
8
card/named/estate.py
Normal file
@ -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
|
||||||
5
card/named/gold.py
Normal file
5
card/named/gold.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from card.basic.card_treasure import Treasure
|
||||||
|
|
||||||
|
|
||||||
|
class Gold(Treasure):
|
||||||
|
pile_player_rate = 30
|
||||||
@ -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):
|
def effect(self):
|
||||||
silver_card_index = self._Card__owner.get_hand().get_index_of_card_by_name("Silver")
|
silver_card_index = self._Card__owner.get_hand().get_index_of_card_by_name("Silver")
|
||||||
if silver_card_index >= 0:
|
if silver_card_index >= 0:
|
||||||
@ -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
|
from random import randint
|
||||||
|
|
||||||
|
|
||||||
class Militia(Card):
|
class Militia(Action, Attack):
|
||||||
def effect(self):
|
def attack(self, player):
|
||||||
for player in self._Card__owner.get_table().get_players():
|
player.print_hand()
|
||||||
if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()):
|
print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.")
|
||||||
player.print_hand()
|
self.__force_discard(self.get_owner().get_std_chances(), player)
|
||||||
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):
|
def __force_discard(self, chances, player):
|
||||||
if player.get_hand().get_remaining() > 3 and chances > 0:
|
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) + "): "
|
" discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): "
|
||||||
, int)
|
, int)
|
||||||
self.__check_discard(hand_index, player, chances)
|
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.")
|
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):
|
def __check_discard(self, index, player, chances):
|
||||||
if 0 > index or index >= self._Card__owner.get_hand().get_remaining():
|
if 0 > index >= player.get_hand().get_remaining():
|
||||||
print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". 1 chance lost.")
|
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)
|
self.__force_discard(chances - 1, player)
|
||||||
else:
|
else:
|
||||||
print("Discarding " + player.get_hand().get_card(index).get_name() + ".")
|
print("Discarding " + player.get_hand().get_card(index).get_name() + ".")
|
||||||
player.discard_from_hand(index)
|
player.discard_from_hand(index)
|
||||||
player.print_hand()
|
player.print_hand()
|
||||||
self.__force_discard(self._Card__owner.get_std_chances(), player)
|
self.__force_discard(self.get_owner().get_std_chances(), player)
|
||||||
9
card/named/mine.py
Normal file
9
card/named/mine.py
Normal file
@ -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
|
||||||
10
card/named/moat.py
Normal file
10
card/named/moat.py
Normal file
@ -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)
|
||||||
5
card/named/province.py
Normal file
5
card/named/province.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from card.basic.card_victory import Victory
|
||||||
|
|
||||||
|
|
||||||
|
class Province(Victory):
|
||||||
|
pass
|
||||||
6
card/named/remodel.py
Normal file
6
card/named/remodel.py
Normal file
@ -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
|
||||||
6
card/named/silver.py
Normal file
6
card/named/silver.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from card.basic.card_treasure import Treasure
|
||||||
|
|
||||||
|
|
||||||
|
class Silver(Treasure):
|
||||||
|
pile_player_rate = 40
|
||||||
|
|
||||||
9
card/named/workshop.py
Normal file
9
card/named/workshop.py
Normal file
@ -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)
|
||||||
@ -1,5 +0,0 @@
|
|||||||
from card.card_gain_trash import CardGainTrash
|
|
||||||
|
|
||||||
|
|
||||||
class Remodel(CardGainTrash):
|
|
||||||
coin_gain = 2
|
|
||||||
@ -6,9 +6,9 @@ class CardGain(Card):
|
|||||||
|
|
||||||
def gain_card(self, spending_limit):
|
def gain_card(self, spending_limit):
|
||||||
gainable_cards = self.__get_gainable_cards(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
|
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:
|
while len(gainable_cards) > 0 and 0 <= index < len(gainable_cards) - 1 and chances > 0:
|
||||||
index = self.__get_gain_card()
|
index = self.__get_gain_card()
|
||||||
@ -18,24 +18,24 @@ class CardGain(Card):
|
|||||||
index = 0
|
index = 0
|
||||||
chances -= 1
|
chances -= 1
|
||||||
else:
|
else:
|
||||||
pile_index = self._Card__owner.get_table().get_pile_index_of_card(gainable_cards[index].get_name())
|
pile_index = self.get_owner().get_table().get_pile_index_of_card(gainable_cards[index].get_name())
|
||||||
print("Player " + str(self._Card__owner.get_player_index()) + " drawing "
|
print("Player " + str(self.get_owner().get_player_index()) + " drawing "
|
||||||
+ self._Card__owner.get_table().get_pile(pile_index).get_card_group().get_name() + " to hand.")
|
+ self.get_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.get_owner().get_table().get_pile(pile_index).transfer_top_card(self.get_owner().get_hand())
|
||||||
self._Card__owner.claim_top_card(self._Card__owner.get_hand())
|
self.get_owner().claim_top_card(self.get_owner().get_hand())
|
||||||
chances = 0
|
chances = 0
|
||||||
|
|
||||||
def __get_gain_card(self):
|
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)
|
"obtain: ", int)
|
||||||
|
|
||||||
def __get_gainable_cards(self, spending_limit):
|
def __get_gainable_cards(self, spending_limit):
|
||||||
result = list()
|
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 p.get_card_group().get_cost() <= spending_limit:
|
||||||
if self.gainable_type_restriction is None:
|
if self.gainable_type_restriction is None:
|
||||||
result.append(p.get_card_group())
|
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())
|
result.append(p.get_card_group())
|
||||||
return result
|
return result
|
||||||
@ -1,5 +1,5 @@
|
|||||||
from card.card_trash import CardTrash
|
from card.special.card_trash import CardTrash
|
||||||
from card.card_gain import CardGain
|
from card.special.card_gain import CardGain
|
||||||
|
|
||||||
|
|
||||||
class CardGainTrash(CardTrash, CardGain):
|
class CardGainTrash(CardTrash, CardGain):
|
||||||
@ -6,10 +6,10 @@ class CardTrash(Card):
|
|||||||
|
|
||||||
def trash_card_get_cost(self):
|
def trash_card_get_cost(self):
|
||||||
tc = self.__get_trashable_cards()
|
tc = self.__get_trashable_cards()
|
||||||
self._Card__print_card_list(tc, " Trashable Cards: ")
|
self.print_card_list(tc, " Trashable Cards: ")
|
||||||
index = 0
|
index = 0
|
||||||
bonus = 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:
|
while 0 < len(tc) and 0 <= index < len(tc) - 1 and chances > 0:
|
||||||
index = self.__get_card_to_trash()
|
index = self.__get_card_to_trash()
|
||||||
@ -19,9 +19,9 @@ class CardTrash(Card):
|
|||||||
index = 0
|
index = 0
|
||||||
chances -= 1
|
chances -= 1
|
||||||
else:
|
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()
|
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
|
chances = 0
|
||||||
return bonus
|
return bonus
|
||||||
|
|
||||||
@ -29,15 +29,15 @@ class CardTrash(Card):
|
|||||||
self.trash_card_get_cost()
|
self.trash_card_get_cost()
|
||||||
|
|
||||||
def __get_card_to_trash(self):
|
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):
|
def __get_trashable_cards(self):
|
||||||
result = list()
|
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 c != self:
|
||||||
if self.trashable_type_restriction is None:
|
if self.trashable_type_restriction is None:
|
||||||
result.append(c)
|
result.append(c)
|
||||||
elif c.get_type() in self.trashable_type_restriction:
|
elif isinstance(c, self.trashable_type_restriction):
|
||||||
result.append(c)
|
result.append(c)
|
||||||
return result
|
return result
|
||||||
@ -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)
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
<code_scheme name="Default" version="173">
|
|
||||||
<codeStyleSettings language="Python">
|
|
||||||
<indentOptions>
|
|
||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
|
||||||
<option name="SMART_TABS" value="true" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="LocalDatabaseDriverManager" version="163">
|
|
||||||
<driver id="exasol">
|
|
||||||
<artifact name="Exasol" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="h2.unified">
|
|
||||||
<artifact name="H2" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="azure.ms">
|
|
||||||
<artifact name="SQL Server" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
<option name="send-app-info" value="false" />
|
|
||||||
</driver>
|
|
||||||
<driver id="oracle">
|
|
||||||
<artifact name="Oracle" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
<option name="auto-commit" value="false" />
|
|
||||||
</driver>
|
|
||||||
<driver id="derby.embedded">
|
|
||||||
<artifact name="Apache Derby" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="sybase.jtds">
|
|
||||||
<artifact name="jTDS (SQL Server and Sybase)" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="sqlserver.jtds">
|
|
||||||
<artifact name="jTDS (SQL Server and Sybase)" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="hsqldb.local">
|
|
||||||
<artifact name="HSQLDB" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="derby.remote">
|
|
||||||
<artifact name="Apache Derby" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="sqlite.xerial">
|
|
||||||
<artifact name="Xerial SQLiteJDBC" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="sybase.ase">
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="postgresql">
|
|
||||||
<artifact name="PostgreSQL" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="redshift">
|
|
||||||
<artifact name="Redshift" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="db2">
|
|
||||||
<artifact name="DB2" use="true" />
|
|
||||||
<option name="auto-sync" value="false" />
|
|
||||||
</driver>
|
|
||||||
<driver id="sqlserver.ms">
|
|
||||||
<artifact name="SQL Server" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
<option name="send-app-info" value="false" />
|
|
||||||
</driver>
|
|
||||||
<driver id="db2.jtopen">
|
|
||||||
<artifact name="JTOpen (DB2 iSeries)" use="true" />
|
|
||||||
<option name="auto-sync" value="false" />
|
|
||||||
</driver>
|
|
||||||
<driver id="mysql">
|
|
||||||
<artifact name="MySQL Connector/J" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
<driver id="hsqldb.remote">
|
|
||||||
<artifact name="HSQLDB" use="true" />
|
|
||||||
<option name="auto-sync" value="true" />
|
|
||||||
</driver>
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="DatabaseSettings" version="2">
|
|
||||||
<csv-formats>
|
|
||||||
<csv-format name="Tab-separated (TSV)" id="Tab-separated (TSV)_id">
|
|
||||||
<data>
|
|
||||||
<record-format prefix="" suffix="" nullText="" quotationPolicy="as needed" valueSeparator="	" recordSeparator=" ">
|
|
||||||
<quotation>
|
|
||||||
<quotes left=""" right=""" leftEscaped="""" rightEscaped="""" />
|
|
||||||
<quotes left="'" right="'" leftEscaped="''" rightEscaped="''" />
|
|
||||||
</quotation>
|
|
||||||
</record-format>
|
|
||||||
</data>
|
|
||||||
</csv-format>
|
|
||||||
<csv-format name="Comma-separated (CSV)" id="Comma-separated (CSV)_id">
|
|
||||||
<data>
|
|
||||||
<record-format prefix="" suffix="" nullText="" quotationPolicy="as needed" valueSeparator="," recordSeparator=" ">
|
|
||||||
<quotation>
|
|
||||||
<quotes left=""" right=""" leftEscaped="""" rightEscaped="""" />
|
|
||||||
<quotes left="'" right="'" leftEscaped="''" rightEscaped="''" />
|
|
||||||
</quotation>
|
|
||||||
</record-format>
|
|
||||||
</data>
|
|
||||||
</csv-format>
|
|
||||||
</csv-formats>
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
13
debugger.xml
13
debugger.xml
@ -1,13 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="XDebuggerSettings">
|
|
||||||
<data-views />
|
|
||||||
<general />
|
|
||||||
<debuggers>
|
|
||||||
<debugger id="javascript">
|
|
||||||
<configuration>
|
|
||||||
<custom-object-presentation />
|
|
||||||
</configuration>
|
|
||||||
</debugger>
|
|
||||||
</debuggers>
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
@ -3,7 +3,8 @@
|
|||||||
<option name="FONT_SIZE" value="18" />
|
<option name="FONT_SIZE" value="18" />
|
||||||
<option name="FONT_SCALE" value="1.5" />
|
<option name="FONT_SCALE" value="1.5" />
|
||||||
</component>
|
</component>
|
||||||
<component name="EditorSettings">
|
<component name="TodoConfiguration">
|
||||||
<option name="USE_SOFT_WRAPS" value="CONSOLE" />
|
<pattern pattern="\btodo\b.*" />
|
||||||
|
<pattern pattern="\bfixme\b.*" />
|
||||||
</component>
|
</component>
|
||||||
</application>
|
</application>
|
||||||
@ -1,5 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="FileTypeManager" version="17">
|
|
||||||
<ignoreFiles list="*$py.class;*.hprof;*.pyc;*.pyo;*.rbc;*.yarb;*~;.DS_Store;.git;.hg;.svn;CVS;__pycache__;_svn;vssver.scc;vssver2.scc;" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
7
find.xml
7
find.xml
@ -1,7 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="FindSettings">
|
|
||||||
<option name="customScope" value="All Places" />
|
|
||||||
<option name="defaultScopeName" value="All Places" />
|
|
||||||
<option name="SEARCH_SCOPE" value="All Places" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
76
game.py
76
game.py
@ -1,14 +1,21 @@
|
|||||||
from table.table import Table
|
from table.table import Table
|
||||||
from player.human import Human
|
from player.human import Human
|
||||||
from player.bots.pure_big_money import Pure_Big_Money
|
from player.bots.pure_big_money import Pure_Big_Money
|
||||||
from card.card import Card
|
from card.basic.card_action import Action
|
||||||
from card.militia import Militia
|
from card.basic.card_curse import Curse
|
||||||
from card.moat import Moat
|
from card.basic.card_victory import Victory
|
||||||
from card.cellar import Cellar
|
from card.named.province import Province
|
||||||
from card.merchant import Merchant
|
from card.named.estate import Estate
|
||||||
from card.mine import Mine
|
from card.named.copper import Copper
|
||||||
from card.remodel import Remodel
|
from card.named.silver import Silver
|
||||||
from card.workshop import Workshop
|
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():
|
def main():
|
||||||
@ -31,14 +38,15 @@ def setup_new_game(game_list, parameter, card_info):
|
|||||||
index = 0
|
index = 0
|
||||||
for p in parameter[2:]:
|
for p in parameter[2:]:
|
||||||
if p:
|
if p:
|
||||||
for i in range(card_info[index][9]):
|
for i in range(card_info[index][7].pile_setup(humans + bots)):
|
||||||
card = card_info[index][8](card_info[index][0], card_info[index][1], card_info[index][2],
|
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][3], card_info[index][4], card_info[index][5],
|
||||||
card_info[index][6], card_info[index][7], None)
|
card_info[index][6], None)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
t.create_pile(card)
|
t.create_pile(card)
|
||||||
else:
|
else:
|
||||||
t.get_pile(t.get_pile_index_of_card(card_info[index][0])).add_card(card)
|
t.get_pile(t.get_pile_index_of_card(card_info[index][0])).add_card(card)
|
||||||
|
card_info[index][7].setup()
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
for i in range(humans):
|
for i in range(humans):
|
||||||
@ -58,29 +66,29 @@ def setup_new_game(game_list, parameter, card_info):
|
|||||||
|
|
||||||
def get_game_parameters():
|
def get_game_parameters():
|
||||||
# humans, bots, card #1, card #2, ... etc
|
# 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():
|
def get_card_info():
|
||||||
# 0 1 2 3 4 5 6 7 8 9
|
# 0 1 2 3 4 5 6 7
|
||||||
# [name, cost, cardtype, v, c, a, b, d, class, count] - values to pass to Card()
|
# [name, cost, v, c, a, b, d, class] - values to pass to Card()
|
||||||
return [["Copper", 0, Card.CardType.Treasure, 0, 1, 0, 0, 0, Card, 60], # 1
|
return [["Copper", 0, 0, 1, 0, 0, 0, Copper], # 0
|
||||||
["Silver", 3, Card.CardType.Treasure, 0, 2, 0, 0, 0, Card, 40], # 2
|
["Silver", 3, 0, 2, 0, 0, 0, Silver], # 1
|
||||||
["Gold", 6, Card.CardType.Treasure, 0, 3, 0, 0, 0, Card, 30], # 3
|
["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2
|
||||||
["Estate", 2, Card.CardType.Victory, 1, 0, 0, 0, 0, Card, 40], # 4
|
["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3
|
||||||
["Dutchy", 5, Card.CardType.Victory, 3, 0, 0, 0, 0, Card, 12], # 5
|
["Dutchy", 5, 3, 0, 0, 0, 0, Victory], # 4
|
||||||
["Province", 8, Card.CardType.Victory, 6, 0, 0, 0, 0, Card, 12], # 6
|
["Province", 8, 6, 0, 0, 0, 0, Province], # 5
|
||||||
["Curse", 0, Card.CardType.Curse, -1, 0, 0, 0, 0, Card, 10], # 7
|
["Curse", 0, -1, 0, 0, 0, 0, Curse], # 6
|
||||||
["Cellar", 2, Card.CardType.Action, 0, 0, 1, 0, 0, Cellar, 10], # 8
|
["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7
|
||||||
["Market", 5, Card.CardType.Action, 0, 1, 1, 1, 1, Card, 10], # 9
|
["Market", 5, 0, 1, 1, 1, 1, Action], # 8
|
||||||
["Merchant", 3, Card.CardType.Action, 0, 0, 1, 0, 1, Merchant, 10], # 10
|
["Merchant", 3, 0, 0, 1, 0, 1, Merchant], # 9
|
||||||
["Militia", 4, Card.CardType.Attack, 0, 2, 0, 0, 0, Militia, 10], # 11
|
["Militia", 4, 0, 2, 0, 0, 0, Militia], # 10
|
||||||
["Mine", 5, Card.CardType.Action, 0, 0, 0, 0, 0, Mine, 10], # 12
|
["Mine", 5, 0, 0, 0, 0, 0, Mine], # 11
|
||||||
["Moat", 2, Card.CardType.Reaction, 0, 0, 0, 0, 2, Moat, 10], # 13
|
["Moat", 2, 0, 0, 0, 0, 2, Moat], # 12
|
||||||
["Remodel", 4, Card.CardType.Action, 0, 0, 0, 0, 0, Remodel, 10], # 14
|
["Remodel", 4, 0, 0, 0, 0, 0, Remodel], # 13
|
||||||
["Smithy", 4, Card.CardType.Action, 0, 0, 0, 0, 3, Card, 10], # 15
|
["Smithy", 4, 0, 0, 0, 0, 3, Action], # 14
|
||||||
["Village", 3, Card.CardType.Action, 0, 0, 2, 0, 1, Card, 10], # 16
|
["Village", 3, 0, 0, 2, 0, 1, Action], # 15
|
||||||
["Workshop", 4, Card.CardType.Action, 0, 0, 0, 0, 0, Workshop, 10]] # 17
|
["Workshop", 4, 0, 0, 0, 0, 0, Workshop]] # 16
|
||||||
# Big Money
|
# Big Money
|
||||||
# ["Adventurer",
|
# ["Adventurer",
|
||||||
# ["Bureaucrat",
|
# ["Bureaucrat",
|
||||||
@ -107,8 +115,8 @@ def get_card_info():
|
|||||||
|
|
||||||
|
|
||||||
def get_starting_deck():
|
def get_starting_deck():
|
||||||
# return [["Copper", 7], ["Estate", 3]]
|
return [["Copper", 7], ["Estate", 3]]
|
||||||
return [["Market", 2], ["Merchant", 2], ["Smithy", 2], ["Village", 2], ["Moat", 2]]
|
# return [["Market", 2], ["Merchant", 2], ["Smithy", 2], ["Village", 2], ["Moat", 2]]
|
||||||
# return [["Militia", 4], ["Cellar", 3], ["Moat", 3]]
|
# return [["Militia", 4], ["Cellar", 3], ["Moat", 3]]
|
||||||
# return [["Silver", 7], ["Merchant", 3]]
|
# return [["Silver", 7], ["Merchant", 3]]
|
||||||
# return [["Copper", 4], ["Mine", 2], ["Remodel", 2], ["Workshop", 2]]
|
# return [["Copper", 4], ["Mine", 2], ["Remodel", 2], ["Workshop", 2]]
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Default" />
|
|
||||||
</profile>
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
from player.player import Player
|
from player.player import Player
|
||||||
from card.card import Card
|
from card.basic.card_treasure import Treasure
|
||||||
#name943meats23jet
|
|
||||||
|
|
||||||
class Pure_Big_Money(Player):
|
class Pure_Big_Money(Player):
|
||||||
def take_action(self):
|
def take_action(self):
|
||||||
@ -12,7 +12,7 @@ class Pure_Big_Money(Player):
|
|||||||
hand = self.get_hand().get_supply()
|
hand = self.get_hand().get_supply()
|
||||||
|
|
||||||
for c in hand:
|
for c in hand:
|
||||||
if c.get_type() == Card.CardType.Treasure:
|
if isinstance(c, Treasure):
|
||||||
choice = hand.index(c)
|
choice = hand.index(c)
|
||||||
|
|
||||||
print(message + str(choice))
|
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.
|
#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):
|
def get_buy_input(self, message, target_type):
|
||||||
coin = self._Player__purchase_power
|
coin = self.get_coin()
|
||||||
choice = -1
|
choice = -1
|
||||||
|
|
||||||
if coin >= 8:
|
if coin >= 8:
|
||||||
@ -39,7 +39,10 @@ class Pure_Big_Money(Player):
|
|||||||
min_coin = self.get_hand().get_supply()[choice].get_purchase_power()
|
min_coin = self.get_hand().get_supply()[choice].get_purchase_power()
|
||||||
|
|
||||||
for c in self.get_hand().get_supply():
|
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()
|
min_coin = c.get_purchase_power()
|
||||||
choice = self.get_hand().get_supply().index(c)
|
choice = self.get_hand().get_supply().index(c)
|
||||||
|
|
||||||
@ -48,7 +51,7 @@ class Pure_Big_Money(Player):
|
|||||||
|
|
||||||
def __get_first_non_Treasure(self):
|
def __get_first_non_Treasure(self):
|
||||||
for c in self.get_hand().get_supply():
|
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 self.get_hand().get_supply().index(c)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@ -6,3 +6,9 @@ class Discard(Supply):
|
|||||||
while self.get_remaining() > 0:
|
while self.get_remaining() > 0:
|
||||||
self.transfer_top_card(deck)
|
self.transfer_top_card(deck)
|
||||||
deck.shuffle()
|
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.")
|
||||||
|
|||||||
@ -2,43 +2,32 @@ from table.supply import Supply
|
|||||||
|
|
||||||
|
|
||||||
class Hand(Supply):
|
class Hand(Supply):
|
||||||
def contains_one_of(self, acceptible_types):
|
def contains_one_of(self, acceptable_class):
|
||||||
result = False
|
result = False
|
||||||
unique_types = self.__get_unique_types()
|
unique_class_instances = self.__get_unique_class_instances()
|
||||||
|
|
||||||
for at in acceptible_types:
|
for uci in unique_class_instances:
|
||||||
result |= at in unique_types
|
result |= isinstance(uci, acceptable_class)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_card_type_count(self, card_type):
|
def get_card_type_count(self, card_class):
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
for c in self._Supply__card:
|
for c in self.get_supply():
|
||||||
if c.get_type() == card_type:
|
if isinstance(c, card_class):
|
||||||
result += 1
|
result += 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def blocks_attack(self, what_attack):
|
def reaction_blocks_attack(self, what_attack):
|
||||||
yes_no = False
|
attack_blocked = False
|
||||||
found_at = -1
|
for c in self.get_supply():
|
||||||
|
attack_blocked |= c.react(what_attack)
|
||||||
|
return attack_blocked
|
||||||
|
|
||||||
for c in self._Supply__card:
|
def __get_unique_class_instances(self):
|
||||||
if c.prevent_attack:
|
unique_class_instances = list()
|
||||||
found_at = self._Supply__card.index(c)
|
|
||||||
|
|
||||||
if found_at >= 0:
|
for c in self.get_supply():
|
||||||
owner = self._Supply__card[found_at].get_owner()
|
if c not in unique_class_instances:
|
||||||
yes_no = "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd "
|
unique_class_instances.append(c)
|
||||||
"like to reveal "
|
return unique_class_instances
|
||||||
+ 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
|
|
||||||
|
|||||||
@ -5,5 +5,5 @@ class Human(Player):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Player " + str(self.get_player_index()) + " (human)"
|
return "Player " + str(self.get_player_index()) + " (human)"
|
||||||
|
|
||||||
def militia_input(self, message):
|
def militia_input(self, message, target_type):
|
||||||
return self.get_general_input(message)
|
return self.get_general_input(message, target_type)
|
||||||
|
|||||||
@ -2,7 +2,8 @@ from player.deck import Deck
|
|||||||
from player.discard import Discard
|
from player.discard import Discard
|
||||||
from player.hand import Hand
|
from player.hand import Hand
|
||||||
from player.counter import Counter
|
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
|
from random import randint
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +42,9 @@ class Player:
|
|||||||
def get_player_index(self):
|
def get_player_index(self):
|
||||||
return self.__table.get_players().index(self)
|
return self.__table.get_players().index(self)
|
||||||
|
|
||||||
|
def get_coin(self):
|
||||||
|
return self.__purchase_power
|
||||||
|
|
||||||
def get_score(self):
|
def get_score(self):
|
||||||
score = 0
|
score = 0
|
||||||
|
|
||||||
@ -99,10 +103,10 @@ class Player:
|
|||||||
def discard_from_hand(self, n):
|
def discard_from_hand(self, n):
|
||||||
self.__hand.transfer_card_by_index(n, self.__discard)
|
self.__hand.transfer_card_by_index(n, self.__discard)
|
||||||
|
|
||||||
def play_card(self, acceptable_card_type, chances, counter):
|
def play_card(self, acceptable_card_class, chances, counter):
|
||||||
if chances > 0 and self.__hand.contains_one_of(acceptable_card_type):
|
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)
|
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:
|
elif chances <= 0:
|
||||||
print("You have used up all of your chances to enter a valid integer; forfeiting remaining plays.")
|
print("You have used up all of your chances to enter a valid integer; forfeiting remaining plays.")
|
||||||
if counter is not None:
|
if counter is not None:
|
||||||
@ -113,23 +117,22 @@ class Player:
|
|||||||
counter.int = 0
|
counter.int = 0
|
||||||
|
|
||||||
def take_action(self):
|
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:
|
while self.__actions.int > 0:
|
||||||
self.play_card([Card.CardType.Action, Card.CardType.Attack, Card.CardType.Reaction],
|
self.play_card(Action, self.__std_chances, self.__actions)
|
||||||
self.__std_chances, self.__actions)
|
|
||||||
|
|
||||||
def take_buy(self):
|
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.")
|
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:
|
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)
|
self.buy_card(self.__std_chances)
|
||||||
|
|
||||||
def buy_card(self, chances):
|
def buy_card(self, chances):
|
||||||
self.__table.print()
|
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)
|
pile_index = self.get_buy_input("\nPlease choose a pile from the table that you'd like to purchase: ", int)
|
||||||
|
|
||||||
if pile_index < 0:
|
if pile_index < 0:
|
||||||
@ -169,15 +172,15 @@ class Player:
|
|||||||
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Hand:")
|
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Hand:")
|
||||||
self.__hand.print()
|
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:
|
if hand_index < 0:
|
||||||
print("You have elected to forfeit any remaining plays.")
|
print("You have elected to forfeit any remaining plays.")
|
||||||
if counter is not None:
|
if counter is not None:
|
||||||
counter.int = 0
|
counter.int = 0
|
||||||
elif hand_index >= self.__hand.get_remaining():
|
elif hand_index >= self.__hand.get_remaining():
|
||||||
print("Acceptable inputs range from 0 to " + str(self.__hand.get_remaining() - 1) + ". 1 chance lost.")
|
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)
|
self.play_card(acceptable_card_class, chances - 1, counter)
|
||||||
elif self.__hand.get_card(hand_index).get_type() in acceptable_card_type:
|
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())
|
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 = self.__hand.get_card(hand_index)
|
||||||
play_card.play()
|
play_card.play()
|
||||||
@ -187,7 +190,7 @@ class Player:
|
|||||||
self.__print()
|
self.__print()
|
||||||
else:
|
else:
|
||||||
print("Index in bounds but not an acceptable card type. Chance to get it right reduced.")
|
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
|
# 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):
|
def get_play_input(self, message, target_type):
|
||||||
@ -232,7 +235,6 @@ class Player:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def __print_discard(self):
|
def __print_discard(self):
|
||||||
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Discard:")
|
|
||||||
self.__discard.print()
|
self.__discard.print()
|
||||||
|
|
||||||
def __print_deck(self):
|
def __print_deck(self):
|
||||||
@ -244,8 +246,9 @@ class Player:
|
|||||||
print("Actions: " + str(self.__actions.int))
|
print("Actions: " + str(self.__actions.int))
|
||||||
print("Buys: " + str(self.__buys))
|
print("Buys: " + str(self.__buys))
|
||||||
print("Coin: " + str(self.__purchase_power))
|
print("Coin: " + str(self.__purchase_power))
|
||||||
self.print_hand()
|
print("Deck Remaining: " + str(self.__deck.get_remaining()))
|
||||||
self.__print_discard()
|
self.__print_discard()
|
||||||
|
self.print_hand()
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def __turn_setup(self):
|
def __turn_setup(self):
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from table.supply import Supply
|
from table.supply import Supply
|
||||||
|
|
||||||
|
|
||||||
class Pile(Supply):
|
class Pile(Supply):
|
||||||
def __init__(self, card):
|
def __init__(self, card):
|
||||||
self.__card_group = card
|
self.__card_group = card
|
||||||
|
|||||||
@ -43,7 +43,8 @@ class Supply:
|
|||||||
return self.__card[n]
|
return self.__card[n]
|
||||||
|
|
||||||
def get_top_card(self):
|
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):
|
def get_remaining(self):
|
||||||
return len(self.__card)
|
return len(self.__card)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from table.trash import Trash
|
from table.trash import Trash
|
||||||
from table.pile import Pile
|
from table.pile import Pile
|
||||||
|
from card.named.province import Province
|
||||||
|
|
||||||
|
|
||||||
class Table:
|
class Table:
|
||||||
@ -45,22 +46,34 @@ class Table:
|
|||||||
result = self.__pile.index(p)
|
result = self.__pile.index(p)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def are_there_any_empty_piles(self):
|
def are_there_three_empty_piles(self):
|
||||||
result = False
|
count = 0
|
||||||
for p in self.__pile:
|
for p in self.__pile:
|
||||||
result = result or p.get_remaining() == 0
|
if p.get_remaining() == 0:
|
||||||
return result
|
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):
|
def play(self):
|
||||||
turn = 0
|
player_turn = 0
|
||||||
# turn < 10 is for testing, otherwise endless as buying card is not yet done
|
should_continue = True
|
||||||
while not self.are_there_any_empty_piles(): # and turn < 10:
|
while should_continue:
|
||||||
|
# game ends after
|
||||||
|
should_continue = not self.should_game_end() or player_turn % len(self.__player) != 0
|
||||||
self.print()
|
self.print()
|
||||||
self.__player[turn % len(self.__player)].take_turn()
|
self.__player[player_turn % len(self.__player)].take_turn()
|
||||||
turn += 1
|
player_turn += 1
|
||||||
else:
|
else:
|
||||||
self.print()
|
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:
|
for p in self.__player:
|
||||||
print("" + str(p) + " scored " + str(p.get_score()) + " points.")
|
print("" + str(p) + " scored " + str(p.get_score()) + " points.")
|
||||||
if p.get_score() > self.__winning_score:
|
if p.get_score() > self.__winning_score:
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
<application>
|
|
||||||
<component name="UISettings">
|
|
||||||
<option name="HIDE_TOOL_STRIPES" value="false" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user