mirror of
https://github.com/neogeek23/Dominion-Strategy-Simulator.git
synced 2026-02-04 02:58:16 +00:00
Add files via upload
had removed passive method as it is not used, where as a setup method will probably be
This commit is contained in:
parent
2d059b2c7d
commit
69a8022f22
72
player/card/card.py
Normal file
72
player/card/card.py
Normal file
@ -0,0 +1,72 @@
|
||||
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
|
||||
|
||||
def __init__(self, name, cost, cardtype, 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
|
||||
self.__value = value
|
||||
self.__owner = owner
|
||||
|
||||
def play(self):
|
||||
self.__owner.add_actions(self.__action)
|
||||
self.__owner.add_buys(self.__buy)
|
||||
self.__owner.add_purchase_power(self.__coin)
|
||||
self.__owner.draw_cards(self.__draw)
|
||||
self.effect()
|
||||
|
||||
def effect(self):
|
||||
# This is here so that 'special' card can override this function so that unique card effects can happen.
|
||||
pass
|
||||
|
||||
def setup(self):
|
||||
# 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_cost(self):
|
||||
return self.__cost
|
||||
|
||||
def set_owner(self, owner):
|
||||
self.__owner = owner
|
||||
|
||||
def get_owner(self):
|
||||
return self.__owner
|
||||
|
||||
def identify(self):
|
||||
return self.__name + ", " + str(self.__type) + ", " + str(self.__cost)
|
||||
|
||||
def __get_index_not_self(self):
|
||||
result = -1
|
||||
for c in self._Card__owner.get_hand().get_supply():
|
||||
if c != self:
|
||||
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
|
||||
40
player/card/card_gain.py
Normal file
40
player/card/card_gain.py
Normal file
@ -0,0 +1,40 @@
|
||||
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._Card__print_card_list(gainable_cards, "Gainable Cards: ")
|
||||
index = 0
|
||||
chances = self._Card__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._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())
|
||||
chances = 0
|
||||
|
||||
def __get_gain_card(self):
|
||||
return int(input("\nPlease identify the index of which card you would like to obtain: "))
|
||||
|
||||
def __get_gainable_cards(self, spending_limit):
|
||||
result = list()
|
||||
|
||||
for p in self._Card__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:
|
||||
result.append(p.get_card_group())
|
||||
return result
|
||||
9
player/card/card_gain_trash.py
Normal file
9
player/card/card_gain_trash.py
Normal file
@ -0,0 +1,9 @@
|
||||
from card.card_trash import CardTrash
|
||||
from card.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)
|
||||
43
player/card/card_trash.py
Normal file
43
player/card/card_trash.py
Normal file
@ -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._Card__print_card_list(tc, " Trashable Cards: ")
|
||||
index = 0
|
||||
bonus = 0
|
||||
chances = self._Card__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._Card__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())
|
||||
chances = 0
|
||||
return bonus
|
||||
|
||||
def trash_card(self):
|
||||
self.trash_card_get_cost()
|
||||
|
||||
def __get_card_to_trash(self):
|
||||
return int(input("\nPlease identify the index of the desired card to trash: "))
|
||||
|
||||
def __get_trashable_cards(self):
|
||||
result = list()
|
||||
|
||||
for c in self._Card__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:
|
||||
result.append(c)
|
||||
return result
|
||||
27
player/card/cellar.py
Normal file
27
player/card/cellar.py
Normal file
@ -0,0 +1,27 @@
|
||||
from card.card import Card
|
||||
|
||||
|
||||
class Cellar(Card):
|
||||
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 int(input(message))
|
||||
|
||||
16
player/card/merchant.py
Normal file
16
player/card/merchant.py
Normal file
@ -0,0 +1,16 @@
|
||||
from card.card import Card
|
||||
|
||||
|
||||
class Merchant(Card):
|
||||
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 int(input("Player " + str(self._Card__owner.get_player_index()) + ", " + message))
|
||||
33
player/card/militia.py
Normal file
33
player/card/militia.py
Normal file
@ -0,0 +1,33 @@
|
||||
from card.card import Card
|
||||
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)
|
||||
|
||||
def __force_discard(self, chances, player):
|
||||
if player.get_hand().get_remaining() > 3 and chances > 0:
|
||||
hand_index = self.__get_index("\nPlease identify a card from hand you would like to discard by providing "
|
||||
"its index 0 to " + str(player.get_hand().get_remaining() - 1) + ": ")
|
||||
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 __get_index(self, message):
|
||||
return int(input(message))
|
||||
|
||||
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)
|
||||
8
player/card/mine.py
Normal file
8
player/card/mine.py
Normal file
@ -0,0 +1,8 @@
|
||||
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]
|
||||
5
player/card/moat.py
Normal file
5
player/card/moat.py
Normal file
@ -0,0 +1,5 @@
|
||||
from card.card import Card
|
||||
|
||||
|
||||
class Moat(Card):
|
||||
prevent_attack = True
|
||||
5
player/card/remodel.py
Normal file
5
player/card/remodel.py
Normal file
@ -0,0 +1,5 @@
|
||||
from card.card_gain_trash import CardGainTrash
|
||||
|
||||
|
||||
class Remodel(CardGainTrash):
|
||||
coin_gain = 2
|
||||
8
player/card/workshop.py
Normal file
8
player/card/workshop.py
Normal file
@ -0,0 +1,8 @@
|
||||
from card.card_gain import CardGain
|
||||
|
||||
|
||||
class Workshop(CardGain):
|
||||
coin_gain = 4
|
||||
|
||||
def effect(self):
|
||||
self.gain_card(self.coin_gain)
|
||||
116
player/game.py
Normal file
116
player/game.py
Normal file
@ -0,0 +1,116 @@
|
||||
from table.table import Table
|
||||
from player.player import Player
|
||||
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
|
||||
|
||||
|
||||
def main():
|
||||
game = list()
|
||||
card_info = get_card_info()
|
||||
setup_new_game(game, get_game_parameters(), card_info)
|
||||
play_game(game[0])
|
||||
|
||||
|
||||
def play_game(game_table):
|
||||
game_table.play()
|
||||
|
||||
|
||||
# place holder setup for testing until frontend constructed
|
||||
def setup_new_game(game_list, parameter, card_info):
|
||||
t = Table()
|
||||
humans = parameter[0]
|
||||
# bots = parameter[1]
|
||||
|
||||
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)
|
||||
if i == 0:
|
||||
t.add_pile(card)
|
||||
else:
|
||||
t.get_pile(t.get_pile_index_of_card(card_info[index][0])).add_card(card)
|
||||
index += 1
|
||||
|
||||
for i in range(humans):
|
||||
human = Player(True, t)
|
||||
human.draw_deck(t, get_starting_deck())
|
||||
human.draw_hand()
|
||||
t.add_player(human)
|
||||
|
||||
# for i in range(bots):
|
||||
# bot = Player(False, t)
|
||||
# bot.draw_deck(t, get_starting_deck())
|
||||
# bot.draw_hand()
|
||||
# t.add_player(bot)
|
||||
|
||||
game_list.append(t)
|
||||
|
||||
|
||||
def get_game_parameters():
|
||||
# humans, bots, card #1, card #2, ... etc
|
||||
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, 24], # 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, 30], # 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
|
||||
# Big Money
|
||||
# ["Adventurer",
|
||||
# ["Bureaucrat",
|
||||
# ["Chancellor",
|
||||
# ["Chapel",
|
||||
# ["Feast",
|
||||
# ["Laboratory",
|
||||
# ["Moneylender",
|
||||
# ["Throne Room",
|
||||
# Interaction
|
||||
# ["Council Room",
|
||||
# ["Festival",
|
||||
# ["Library",
|
||||
# ["Spy",
|
||||
# ["Thief",
|
||||
# Size Distortion
|
||||
# ["Gardens",
|
||||
# ["Woodcuter",
|
||||
# ["Witch",
|
||||
# Villiage Square
|
||||
# Trash Heap
|
||||
# http://dominioncg.wikia.com/wiki/Pre-set_Sets_of_10
|
||||
# http://www.dominiondeck.com/games/popular
|
||||
|
||||
|
||||
def get_starting_deck():
|
||||
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]]
|
||||
|
||||
|
||||
main()
|
||||
3
player/player/counter.py
Normal file
3
player/player/counter.py
Normal file
@ -0,0 +1,3 @@
|
||||
class Counter:
|
||||
def __init__(self, n):
|
||||
self.int = n
|
||||
7
player/player/deck.py
Normal file
7
player/player/deck.py
Normal file
@ -0,0 +1,7 @@
|
||||
from table.supply import Supply
|
||||
from random import shuffle
|
||||
|
||||
|
||||
class Deck(Supply):
|
||||
def shuffle(self):
|
||||
shuffle(self._Supply__card)
|
||||
8
player/player/discard.py
Normal file
8
player/player/discard.py
Normal file
@ -0,0 +1,8 @@
|
||||
from table.supply import Supply
|
||||
|
||||
|
||||
class Discard(Supply):
|
||||
def cycle_card(self, deck):
|
||||
while self.get_remaining() > 0:
|
||||
self.transfer_top_card(deck)
|
||||
deck.shuffle()
|
||||
47
player/player/hand.py
Normal file
47
player/player/hand.py
Normal file
@ -0,0 +1,47 @@
|
||||
from table.supply import Supply
|
||||
|
||||
|
||||
class Hand(Supply):
|
||||
def contains_one_of(self, acceptible_types):
|
||||
result = False
|
||||
unique_types = self.__get_unique_types()
|
||||
|
||||
for at in acceptible_types:
|
||||
result |= at in unique_types
|
||||
return result
|
||||
|
||||
def get_card_type_count(self, card_type):
|
||||
result = 0
|
||||
|
||||
for c in self._Supply__card:
|
||||
if c.get_type() == card_type:
|
||||
result += 1
|
||||
return result
|
||||
|
||||
def blocks_attack(self, what_attack):
|
||||
yes_no = False
|
||||
found_at = -1
|
||||
|
||||
for c in self._Supply__card:
|
||||
if c.prevent_attack:
|
||||
found_at = self._Supply__card.index(c)
|
||||
|
||||
if found_at >= 0:
|
||||
yes_no = "Y" == self.__get_reveal("Player "
|
||||
+ str(self._Supply__card[found_at].get_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: ")
|
||||
return yes_no
|
||||
|
||||
def __get_reveal(self, message):
|
||||
return input(message)
|
||||
|
||||
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
|
||||
202
player/player/player.py
Normal file
202
player/player/player.py
Normal file
@ -0,0 +1,202 @@
|
||||
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
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self, human, table):
|
||||
self.__std_chances = 3
|
||||
self.__deck = Deck()
|
||||
self.__discard = Discard()
|
||||
self.__hand = Hand()
|
||||
self.__purchase_power = 0
|
||||
self.__actions = Counter(0)
|
||||
self.__buys = 0
|
||||
self.__is_human = human
|
||||
self.__table = table
|
||||
|
||||
def add_actions(self, n):
|
||||
self.__actions.int += n
|
||||
|
||||
def add_purchase_power(self, n):
|
||||
self.__purchase_power += n
|
||||
|
||||
def add_buys(self, n):
|
||||
self.__buys += n
|
||||
|
||||
def get_table(self):
|
||||
return self.__table
|
||||
|
||||
def get_std_chances(self):
|
||||
return self.__std_chances
|
||||
|
||||
def get_hand(self):
|
||||
return self.__hand
|
||||
|
||||
def get_discard(self):
|
||||
return self.__discard
|
||||
|
||||
def get_player_index(self):
|
||||
return self.__table.get_players().index(self)
|
||||
|
||||
def get_score(self):
|
||||
return 0
|
||||
|
||||
def draw_card(self):
|
||||
self.__deck.transfer_top_card(self.__hand)
|
||||
|
||||
def draw_cards(self, how_many):
|
||||
spillover = how_many - self.__deck.get_remaining()
|
||||
lacking_cards = spillover - self.__discard.get_remaining()
|
||||
|
||||
if lacking_cards <= 0:
|
||||
lacking_cards = 0
|
||||
elif lacking_cards == 1:
|
||||
print("You are lacking " + str(lacking_cards) + " card. You cannot draw anymore.")
|
||||
else:
|
||||
print("You are lacking " + str(lacking_cards) + " card. You cannot draw anymore.")
|
||||
|
||||
if spillover > 0:
|
||||
for i in range(how_many - spillover):
|
||||
self.draw_card()
|
||||
|
||||
self.__discard.cycle_card(self.__deck)
|
||||
|
||||
for i in range(spillover - lacking_cards):
|
||||
self.draw_card()
|
||||
else:
|
||||
for i in range(how_many):
|
||||
self.draw_card()
|
||||
|
||||
def draw_deck(self, table, deck_setup):
|
||||
for ds in deck_setup:
|
||||
index = table.get_pile_index_of_card(ds[0])
|
||||
for i in range(ds[1]):
|
||||
table.get_pile(index).transfer_top_card(self.__deck)
|
||||
self.claim_top_card(self.__deck)
|
||||
self.__deck.shuffle()
|
||||
|
||||
def draw_hand(self):
|
||||
self.draw_cards(5)
|
||||
|
||||
def discard_remaining_hand(self):
|
||||
while self.__hand.get_remaining() > 0:
|
||||
self.__hand.transfer_top_card(self.__discard)
|
||||
|
||||
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):
|
||||
hand_index = self.__get_play_input("\nPlease identify a card from hand to play by providing its index: ")
|
||||
self.__check_play_card(hand_index, counter, acceptable_card_type, 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:
|
||||
counter.int = 0
|
||||
else:
|
||||
print("There are no more acceptable card in hand, moving to next phase.")
|
||||
if counter is not None:
|
||||
counter.int = 0
|
||||
|
||||
def take_action(self):
|
||||
print("\nPlease play an Action, Attack, or Reaction 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)
|
||||
|
||||
def take_buy(self):
|
||||
if self.__hand.contains_one_of([Card.CardType.Treasure]):
|
||||
print("\nPlease play all Treasure card that you want to play.")
|
||||
|
||||
play_another = Counter(self.__hand.get_card_type_count(Card.CardType.Treasure))
|
||||
while play_another.int > 0:
|
||||
self.play_card([Card.CardType.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:
|
||||
pile_index = self.__get_buy_input("\nPlease identify a pile from the table that you'd like to purchase: ")
|
||||
|
||||
if pile_index < 0:
|
||||
print("You have elected to forfeit any remaining plays.")
|
||||
self.__buys = 0
|
||||
elif pile_index >= self.__table.get_pile_count():
|
||||
print("Acceptable inputs range from 0 to " + str(self.__table.get_pile_count() - 1) + ". Try again.")
|
||||
chances -= 1
|
||||
elif self.__table.get_pile(pile_index).get_card_group().get_cost() > self.__purchase_power:
|
||||
print("You do not have enough coin. Try again.")
|
||||
chances -= 1
|
||||
else:
|
||||
print("Player " + str(self.get_table().get_players().index(self)) + " buying card " +
|
||||
self.__table.get_pile(pile_index).get_card_group().get_name())
|
||||
self.__table.get_pile(pile_index).transfer_top_card(self.__discard)
|
||||
self.claim_top_card(self.__discard)
|
||||
self.__buys -= 1
|
||||
|
||||
def take_turn(self):
|
||||
self.__turn_setup()
|
||||
self.__print()
|
||||
self.take_action()
|
||||
self.take_buy()
|
||||
self.discard_remaining_hand()
|
||||
self.draw_hand()
|
||||
self.print_hand()
|
||||
|
||||
def claim_top_card(self, supply):
|
||||
supply.get_top_card().set_owner(self)
|
||||
|
||||
def print_hand(self):
|
||||
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):
|
||||
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:
|
||||
print("Player " + str(self.get_player_index()) + " playing: " + self.__hand.get_card(hand_index).get_name())
|
||||
self.__hand.get_card(hand_index).play()
|
||||
self.__hand.transfer_card_by_card(self.__hand.get_card(hand_index), self.__discard)
|
||||
if counter is not None:
|
||||
counter.int -= 1
|
||||
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)
|
||||
|
||||
# The following two methods are identical under different names so they can be overridden by bot classes later
|
||||
def __get_play_input(self, message):
|
||||
return int(input(message))
|
||||
|
||||
def __get_buy_input(self, message):
|
||||
return int(input(message))
|
||||
|
||||
def __print_discard(self):
|
||||
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Discard:")
|
||||
self.__discard.print()
|
||||
|
||||
def __print_deck(self):
|
||||
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Deck:")
|
||||
self.__deck.print()
|
||||
|
||||
def __print(self):
|
||||
print("\nPlayer " + str(self.__table.get_players().index(self)) + ": ")
|
||||
print("Actions: " + str(self.__actions.int))
|
||||
print("Buys: " + str(self.__buys))
|
||||
print("Coin: " + str(self.__purchase_power))
|
||||
self.print_hand()
|
||||
self.__print_discard()
|
||||
# self.__print_deck()
|
||||
|
||||
def __turn_setup(self):
|
||||
self.__actions.int = 1
|
||||
self.__buys = 1
|
||||
self.__purchase_power = 0
|
||||
5
player/table/pile.py
Normal file
5
player/table/pile.py
Normal file
@ -0,0 +1,5 @@
|
||||
from table.supply import Supply
|
||||
|
||||
class Pile(Supply):
|
||||
def get_card_group(self):
|
||||
return self._Supply__card[0]
|
||||
55
player/table/supply.py
Normal file
55
player/table/supply.py
Normal file
@ -0,0 +1,55 @@
|
||||
class Supply:
|
||||
def __init__(self):
|
||||
self.__card = list()
|
||||
|
||||
def add_card(self, card):
|
||||
self.__card.append(card)
|
||||
|
||||
def add_cards(self, card, n):
|
||||
for i in range(n):
|
||||
self.add_card(card)
|
||||
|
||||
def get_supply(self):
|
||||
return self.__card
|
||||
|
||||
def get_index_of_card_by_name(self, name):
|
||||
for c in self.__card:
|
||||
if c.get_name() == name:
|
||||
return self.__card.index(c)
|
||||
return -1
|
||||
|
||||
def get_index_of_card_by_card(self, card):
|
||||
for c in self.__card:
|
||||
if c == card:
|
||||
return self.__card.index(c)
|
||||
return -1
|
||||
|
||||
def transfer_top_card(self, recipient_supply):
|
||||
self.transfer_card_by_index(len(self.__card) - 1, recipient_supply)
|
||||
|
||||
def transfer_card_by_index(self, n, recipient_supply):
|
||||
transfer_card = self.__card.pop(n)
|
||||
recipient_supply.add_card(transfer_card)
|
||||
|
||||
def transfer_card_by_card(self, card, recipient_supply):
|
||||
card_index = self.get_index_of_card_by_card(card)
|
||||
|
||||
if card_index >= 0:
|
||||
self.transfer_card_by_index(card_index, recipient_supply)
|
||||
else:
|
||||
raise ValueError('Card not found in hand during attempt to transfer card.')
|
||||
|
||||
def get_card(self, n):
|
||||
return self.__card[n]
|
||||
|
||||
def get_top_card(self):
|
||||
return self.__card[len(self.__card) - 1]
|
||||
|
||||
def get_remaining(self):
|
||||
return len(self.__card)
|
||||
|
||||
def print(self):
|
||||
index = 0
|
||||
for c in self.__card:
|
||||
print(str(index) + ": " + c.identify())
|
||||
index += 1
|
||||
80
player/table/table.py
Normal file
80
player/table/table.py
Normal file
@ -0,0 +1,80 @@
|
||||
from table.trash import Trash
|
||||
from table.pile import Pile
|
||||
|
||||
|
||||
class Table:
|
||||
def __init__(self):
|
||||
self.__player = list()
|
||||
self.__pile = list()
|
||||
self.__trash = Trash()
|
||||
self.__winner = None
|
||||
self.__winning_score = 0
|
||||
|
||||
def add_player(self, p):
|
||||
self.__player.append(p)
|
||||
|
||||
def get_player(self, n):
|
||||
return self.__player[n]
|
||||
|
||||
def get_players(self):
|
||||
return self.__player
|
||||
|
||||
def get_trash(self):
|
||||
return self.__trash
|
||||
|
||||
def add_pile(self, card):
|
||||
p = Pile()
|
||||
p.add_card(card)
|
||||
card.setup()
|
||||
self.__pile.append(p)
|
||||
|
||||
def get_piles(self):
|
||||
return self.__pile
|
||||
|
||||
def get_pile(self, n):
|
||||
return self.__pile[n]
|
||||
|
||||
def get_pile_count(self):
|
||||
return len(self.__pile)
|
||||
|
||||
def get_pile_index_of_card(self, card_name):
|
||||
result = 0
|
||||
|
||||
for p in self.__pile:
|
||||
if p.get_card_group().get_name() == card_name:
|
||||
result = self.__pile.index(p)
|
||||
return result
|
||||
|
||||
def are_there_any_empty_piles(self):
|
||||
result = False
|
||||
for p in self.__pile:
|
||||
result = result or p.get_remaining() == 0
|
||||
return result
|
||||
|
||||
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:
|
||||
self.print()
|
||||
self.__player[turn % len(self.__player)].take_turn()
|
||||
turn += 1
|
||||
else:
|
||||
self.print()
|
||||
for p in self.__player:
|
||||
if p.get_score() > self.__winning_score:
|
||||
self.__winning_score = p.get_score
|
||||
self.__winner = p
|
||||
print("\n\nPlayer " + str(self.__winner) + " won with " + str(self.__winning_score) + " points.\n\n")
|
||||
|
||||
def print(self):
|
||||
print("\nPiles: ")
|
||||
index = 0
|
||||
for s in self.__pile:
|
||||
print(str(index) + ": " + s.get_card_group().identify() + ": " + str(s.get_remaining()))
|
||||
index += 1
|
||||
|
||||
print("\nTrash: ")
|
||||
index = 0
|
||||
for s in self.__trash.get_supply():
|
||||
print(str(index) + ": " + s.identify())
|
||||
index += 1
|
||||
5
player/table/trash.py
Normal file
5
player/table/trash.py
Normal file
@ -0,0 +1,5 @@
|
||||
from table.pile import Pile
|
||||
|
||||
|
||||
class Trash(Pile):
|
||||
pass
|
||||
Loading…
x
Reference in New Issue
Block a user