mirror of
https://github.com/neogeek23/Dominion-Strategy-Simulator.git
synced 2026-02-04 11:08:18 +00:00
Add files via upload
Generalized out attack cards. Fixed bugs.
This commit is contained in:
parent
03fb263288
commit
e3ff6416ff
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 .
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
5
card/named/province.py
Normal file
@ -0,0 +1,5 @@
|
||||
from card.basic.card_victory import Victory
|
||||
|
||||
|
||||
class Province(Victory):
|
||||
pass
|
||||
5
game.py
5
game.py
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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.")
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user