Add files via upload

Generalized out attack cards.  Fixed bugs.
This commit is contained in:
Brad Stein 2018-01-10 23:30:39 -05:00 committed by GitHub
parent 03fb263288
commit e3ff6416ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 88 additions and 57 deletions

View File

@ -2,4 +2,10 @@ 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

View File

@ -1,10 +1,10 @@
from card.card import Card
from card.basic.card_victory import Victory
class Curse(Card):
@staticmethod
def pile_setup(player_count):
if player_count % Card.normal_full_table < Card.normal_full_table/2:
return Card.pile_player_rate
class Curse(Victory):
@classmethod
def pile_setup(cls, player_count):
if player_count % cls.normal_full_table < cls.normal_full_table/2:
return Victory.pile_player_rate
else:
return (player_count - 1) * Card.pile_player_rate
return (player_count - 1) * cls.pile_player_rate

View File

@ -5,6 +5,6 @@ from math import floor
class Kingdom(Card):
pile_player_rate = 10
@staticmethod
def pile_setup(player_count):
return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate
@classmethod
def pile_setup(cls, player_count):
return (floor(player_count/cls.normal_full_table) + 1) * cls.pile_player_rate

View File

@ -5,4 +5,4 @@ from math import floor
class Treasure(Card):
@classmethod
def pile_setup(cls, player_count):
return (floor(player_count/Card.normal_full_table) + 1) * cls.pile_player_rate
return (floor(player_count/cls.normal_full_table) + 1) * cls.pile_player_rate

View File

@ -1,5 +1,4 @@
class Card:
prevent_attack = False
normal_full_table = 6
pile_player_rate = 10
@ -24,6 +23,9 @@ class Card:
# This is here so that 'special' card can override this function so that unique card effects can happen.
pass
def react(self, what_attack):
return False
@classmethod
def pile_setup(cls, player_count):
# This is here so that each card can override this function so that the right number of .

View File

@ -4,12 +4,10 @@ from random import randint
class Militia(Action, Attack):
def effect(self):
for player in self._Card__owner.get_table().get_players():
if self._Card__owner != player and not player.get_hand().blocks_attack(self.get_name()):
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._Card__owner.get_std_chances(), player)
self.__force_discard(self.get_owner().get_std_chances(), player)
def __force_discard(self, chances, player):
if player.get_hand().get_remaining() > 3 and chances > 0:
@ -17,16 +15,17 @@ class Militia(Action, Attack):
" discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): "
, int)
self.__check_discard(hand_index, player, chances)
elif self._Card__owner.get_hand().get_remaining() > 3 and chances <= 0:
elif self.get_owner().get_hand().get_remaining() > 3 and chances <= 0:
print("You're out of chances to select a valid card to discard, randomly selecting for you.")
player.discard_from_hand(randint(0, self.__hand.get_remaining() - 1))
player.discard_from_hand(randint(0, self.get_owner().get_hand().get_remaining() - 1))
def __check_discard(self, index, player, chances):
if 0 > index or index >= self._Card__owner.get_hand().get_remaining():
print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". 1 chance lost.")
if 0 > index >= player.get_hand().get_remaining():
print("Valid inputs range from 0 to " + str(player.get_hand().get_remaining() - 1) + ". " + str(chances - 1)
+ "chances to input a valid index.")
self.__force_discard(chances - 1, player)
else:
print("Discarding " + player.get_hand().get_card(index).get_name() + ".")
player.discard_from_hand(index)
player.print_hand()
self.__force_discard(self._Card__owner.get_std_chances(), player)
self.__force_discard(self.get_owner().get_std_chances(), player)

View File

@ -3,4 +3,8 @@ from card.basic.card_reaction import Reaction
class Moat(Action, Reaction):
prevent_attack = True
def react(self, what_attack):
owner = self.get_owner()
return "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd "
"like to reveal " + str(self) + " to block the " + str(what_attack) +
" attack: ", str)

5
card/named/province.py Normal file
View File

@ -0,0 +1,5 @@
from card.basic.card_victory import Victory
class Province(Victory):
pass

View File

@ -4,6 +4,7 @@ from player.bots.pure_big_money import Pure_Big_Money
from card.basic.card_action import Action
from card.basic.card_curse import Curse
from card.basic.card_victory import Victory
from card.named.province import Province
from card.named.estate import Estate
from card.named.copper import Copper
from card.named.silver import Silver
@ -65,7 +66,7 @@ def setup_new_game(game_list, parameter, card_info):
def get_game_parameters():
# humans, bots, card #1, card #2, ... etc
return [1, 1, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True]
return [2, 1, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True]
def get_card_info():
@ -76,7 +77,7 @@ def get_card_info():
["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2
["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3
["Dutchy", 5, 3, 0, 0, 0, 0, Victory], # 4
["Province", 8, 6, 0, 0, 0, 0, Victory], # 5
["Province", 8, 6, 0, 0, 0, 0, Province], # 5
["Curse", 0, -1, 0, 0, 0, 0, Curse], # 6
["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7
["Market", 5, 0, 1, 1, 1, 1, Action], # 8

View File

@ -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:

View File

@ -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.")

View File

@ -18,20 +18,11 @@ class Hand(Supply):
result += 1
return result
def blocks_attack(self, what_attack):
yes_no = False
found_at = -1
def reaction_blocks_attack(self, what_attack):
attack_blocked = False
for c in self.get_supply():
if c.prevent_attack:
found_at = self.get_supply().index(c)
if found_at >= 0:
owner = self.get_supply()[found_at].get_owner()
yes_no = "Y" == owner.get_general_input("Player " + str(owner.get_player_index()) + ", enter 'Y' if you'd "
"like to reveal " + self.get_supply()[found_at].get_name() +
" to block the " + what_attack + " attack: ", str)
return yes_no
attack_blocked |= c.react(what_attack)
return attack_blocked
def __get_unique_class_instances(self):
unique_class_instances = list()

View File

@ -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)

View File

@ -42,6 +42,9 @@ class Player:
def get_player_index(self):
return self.__table.get_players().index(self)
def get_coin(self):
return self.__purchase_power
def get_score(self):
score = 0
@ -129,7 +132,7 @@ class Player:
def buy_card(self, chances):
self.__table.print()
while self.__buys > 0 and not self.__table.are_there_any_empty_piles() and chances > 0:
while self.__buys > 0 and not self.__table.are_there_three_empty_piles() and chances > 0:
pile_index = self.get_buy_input("\nPlease choose a pile from the table that you'd like to purchase: ", int)
if pile_index < 0:
@ -232,7 +235,6 @@ class Player:
return True
def __print_discard(self):
print("\nPlayer " + str(self.__table.get_players().index(self)) + " Discard:")
self.__discard.print()
def __print_deck(self):
@ -244,8 +246,9 @@ class Player:
print("Actions: " + str(self.__actions.int))
print("Buys: " + str(self.__buys))
print("Coin: " + str(self.__purchase_power))
self.print_hand()
print("Deck Remaining: " + str(self.__deck.get_remaining()))
self.__print_discard()
self.print_hand()
print("")
def __turn_setup(self):

View File

@ -43,6 +43,7 @@ class Supply:
return self.__card[n]
def get_top_card(self):
if len(self.__card) > 0:
return self.__card[len(self.__card) - 1]
def get_remaining(self):

View File

@ -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: