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): 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 pass

View File

@ -1,10 +1,10 @@
from card.card import Card from card.basic.card_victory import Victory
class Curse(Card): class Curse(Victory):
@staticmethod @classmethod
def pile_setup(player_count): def pile_setup(cls, player_count):
if player_count % Card.normal_full_table < Card.normal_full_table/2: if player_count % cls.normal_full_table < cls.normal_full_table/2:
return Card.pile_player_rate return Victory.pile_player_rate
else: 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): class Kingdom(Card):
pile_player_rate = 10 pile_player_rate = 10
@staticmethod @classmethod
def pile_setup(player_count): def pile_setup(cls, player_count):
return (floor(player_count/Card.normal_full_table) + 1) * Card.pile_player_rate 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): class Treasure(Card):
@classmethod @classmethod
def pile_setup(cls, player_count): 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: class Card:
prevent_attack = False
normal_full_table = 6 normal_full_table = 6
pile_player_rate = 10 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. # This is here so that 'special' card can override this function so that unique card effects can happen.
pass pass
def react(self, what_attack):
return False
@classmethod @classmethod
def pile_setup(cls, player_count): def pile_setup(cls, player_count):
# This is here so that each card can override this function so that the right number of . # 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): class Militia(Action, Attack):
def effect(self): def attack(self, player):
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() player.print_hand()
print("Player " + str(player.get_player_index()) + ", you MUST discard down to 3 card.") 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): 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:
@ -17,16 +15,17 @@ class Militia(Action, Attack):
" 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)

View File

@ -3,4 +3,8 @@ from card.basic.card_reaction import Reaction
class Moat(Action, 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_action import Action
from card.basic.card_curse import Curse from card.basic.card_curse import Curse
from card.basic.card_victory import Victory from card.basic.card_victory import Victory
from card.named.province import Province
from card.named.estate import Estate from card.named.estate import Estate
from card.named.copper import Copper from card.named.copper import Copper
from card.named.silver import Silver from card.named.silver import Silver
@ -65,7 +66,7 @@ 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():
@ -76,7 +77,7 @@ def get_card_info():
["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2 ["Gold", 6, 0, 3, 0, 0, 0, Gold], # 2
["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3 ["Estate", 2, 1, 0, 0, 0, 0, Estate], # 3
["Dutchy", 5, 3, 0, 0, 0, 0, Victory], # 4 ["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 ["Curse", 0, -1, 0, 0, 0, 0, Curse], # 6
["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7 ["Cellar", 2, 0, 0, 1, 0, 0, Cellar], # 7
["Market", 5, 0, 1, 1, 1, 1, Action], # 8 ["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. #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:

View File

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

View File

@ -18,20 +18,11 @@ class Hand(Supply):
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(): for c in self.get_supply():
if c.prevent_attack: attack_blocked |= c.react(what_attack)
found_at = self.get_supply().index(c) return attack_blocked
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
def __get_unique_class_instances(self): def __get_unique_class_instances(self):
unique_class_instances = list() unique_class_instances = list()

View File

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

View File

@ -42,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
@ -129,7 +132,7 @@ class Player:
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:
@ -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):

View File

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

View File

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