mirror of
https://github.com/neogeek23/Dominion-Strategy-Simulator.git
synced 2026-02-04 02:58:16 +00:00
Add files via upload
This commit is contained in:
parent
0281eddc83
commit
b2360cf84b
@ -23,5 +23,5 @@ class Cellar(Action):
|
||||
self._Card__owner.draw_cards(cards_discarded)
|
||||
|
||||
def __get_index(self, message):
|
||||
return self.__Card_owner.get_general_input(message, int)
|
||||
return self.__Card_owner.take_input(message, int)
|
||||
|
||||
|
||||
@ -13,5 +13,5 @@ class Merchant(Action):
|
||||
self._Card__owner.add_purchase_power(3)
|
||||
|
||||
def __get_Merchant_input(self, message):
|
||||
return self.__Card_owner.get_general_input("Player " + str(self._Card__owner.get_player_index()) + ", " +
|
||||
message, str)
|
||||
return self.__Card_owner.take_input("Player " + str(self._Card__owner.get_player_index()) + ", " +
|
||||
message, str)
|
||||
|
||||
@ -11,9 +11,9 @@ class Militia(Action, Attack):
|
||||
|
||||
def __force_discard(self, chances, player):
|
||||
if player.get_hand().get_remaining() > 3 and chances > 0:
|
||||
hand_index = player.militia_input("\nPlease provide an index to identify a card from hand you would like to"
|
||||
" discard (0 to " + str(player.get_hand().get_remaining() - 1) + "): "
|
||||
, int)
|
||||
hand_index = player.get_response_input("\nPlease provide an index to identify a card from hand you would "
|
||||
"like to discard (0 to " + str(player.get_hand().get_remaining() - 1)
|
||||
+ "): ", int, self.__class__)
|
||||
self.__check_discard(hand_index, player, chances)
|
||||
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.")
|
||||
|
||||
@ -5,6 +5,6 @@ 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 "
|
||||
return "Y" == owner.take_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)
|
||||
|
||||
@ -26,7 +26,7 @@ class CardGain(Card):
|
||||
chances = 0
|
||||
|
||||
def __get_gain_card(self):
|
||||
return self.get_owner().get_general_input("\nPlease identify the index of which card you would like to "
|
||||
return self.get_owner().take_input("\nPlease identify the index of which card you would like to "
|
||||
"obtain: ", int)
|
||||
|
||||
def __get_gainable_cards(self, spending_limit):
|
||||
|
||||
@ -29,7 +29,7 @@ class CardTrash(Card):
|
||||
self.trash_card_get_cost()
|
||||
|
||||
def __get_card_to_trash(self):
|
||||
return self.get_owner().get_general_input("\nPlease identify the index of the desired card to trash: ", int)
|
||||
return self.get_owner().take_input("\nPlease identify the index of the desired card to trash: ", int)
|
||||
|
||||
def __get_trashable_cards(self):
|
||||
result = list()
|
||||
|
||||
11
game.py
11
game.py
@ -1,6 +1,8 @@
|
||||
from table.table import Table
|
||||
from player.human import Human
|
||||
from player.bots.pure_big_money import Pure_Big_Money
|
||||
from player.bots.smithy_big_money import Smithy_Big_Money
|
||||
from player.bots.militia_big_money import Militia_Big_Money
|
||||
from card.basic.card_action import Action
|
||||
from card.basic.card_curse import Curse
|
||||
from card.basic.card_victory import Victory
|
||||
@ -56,7 +58,12 @@ def setup_new_game(game_list, parameter, card_info):
|
||||
t.add_player(human)
|
||||
|
||||
for i in range(bots):
|
||||
bot = Pure_Big_Money(t)
|
||||
if i % 3 == 0:
|
||||
bot = Militia_Big_Money(t)
|
||||
elif i % 3 == 1:
|
||||
bot = Smithy_Big_Money(t)
|
||||
else:
|
||||
bot = Pure_Big_Money(t)
|
||||
bot.draw_deck(t, get_starting_deck())
|
||||
bot.draw_hand()
|
||||
t.add_player(bot)
|
||||
@ -66,7 +73,7 @@ def setup_new_game(game_list, parameter, card_info):
|
||||
|
||||
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]
|
||||
return [0, 3, True, True, True, True, True, True, False, True, True, True, True, True, True, True, True, True, True]
|
||||
|
||||
|
||||
def get_card_info():
|
||||
|
||||
105
player/bot.py
Normal file
105
player/bot.py
Normal file
@ -0,0 +1,105 @@
|
||||
from player.player import Player
|
||||
from card.basic.card_action import Action
|
||||
from card.basic.card_treasure import Treasure
|
||||
from card.named.militia import Militia
|
||||
|
||||
|
||||
class Bot(Player):
|
||||
target_card = None
|
||||
target_card_threshold = 0
|
||||
|
||||
def get_play_input(self, message, target_type, restriction):
|
||||
if restriction == Treasure:
|
||||
choice = self.get_subclass_input(Treasure)
|
||||
elif restriction == Action:
|
||||
choice = self.get_subclass_input(Action)
|
||||
else:
|
||||
choice = -1
|
||||
|
||||
print(message + str(choice))
|
||||
return choice
|
||||
|
||||
def get_response_input(self, message, target_type, restriction):
|
||||
if restriction == Militia:
|
||||
choice = self.get_militia_input()
|
||||
else:
|
||||
choice = -1
|
||||
return choice
|
||||
|
||||
def can_afford_on_avg(self, card_name):
|
||||
card_cost = self.get_table().get_piles()[self.get_table().get_pile_index_of_card(card_name)].get_card_group()\
|
||||
.get_cost()
|
||||
total_coin = 0
|
||||
hand = self.get_hand().get_supply()
|
||||
deck = self.get_deck().get_supply()
|
||||
discard = self.get_discard().get_supply()
|
||||
supplies = hand + deck + discard
|
||||
|
||||
for c in supplies:
|
||||
total_coin += c.get_purchase_power()
|
||||
return card_cost <= total_coin/(len(hand) + len(deck) + len(discard))
|
||||
|
||||
def has_how_many_of_card(self, card_name):
|
||||
total = 0
|
||||
hand = self.get_hand().get_supply()
|
||||
deck = self.get_deck().get_supply()
|
||||
discard = self.get_discard().get_supply()
|
||||
supplies = hand + deck + discard
|
||||
|
||||
for c in supplies:
|
||||
if c.get_name() == card_name:
|
||||
total += 1
|
||||
return total
|
||||
|
||||
#This will pick either the first or the first least effective purchasing card as this bot doesn't care about that
|
||||
def get_militia_input(self):
|
||||
choice = self.__get_first_non_Treasure()
|
||||
min_coin = self.get_hand().get_supply()[choice].get_purchase_power()
|
||||
|
||||
for c in self.get_hand().get_supply():
|
||||
# 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()
|
||||
choice = self.get_hand().get_supply().index(c)
|
||||
return choice
|
||||
|
||||
# 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.get_coin()
|
||||
choice = -1
|
||||
|
||||
if coin >= self.target_card_threshold and not self.get_table().pile_is_empty(self.target_card) and \
|
||||
self.has_how_many_of_card(self.target_card) < 3:
|
||||
choice = self.get_table().get_pile_index_of_card(self.target_card)
|
||||
elif coin >= 8 and not self.get_table().pile_is_empty("Province"):
|
||||
choice = self.get_table().get_pile_index_of_card("Province")
|
||||
elif coin >= 8 and not self.get_table().pile_is_empty("Dutchy"):
|
||||
choice = self.get_table().get_pile_index_of_card("Dutchy")
|
||||
elif coin >= 6 and not self.get_table().pile_is_empty("Gold") and not \
|
||||
self.get_table().pile_is_empty("Province"):
|
||||
choice = self.get_table().get_pile_index_of_card("Gold")
|
||||
elif coin >= 5 and not self.get_table().pile_is_empty("Dutchy") and \
|
||||
(self.can_afford_on_avg("Province") or self.get_table().pile_is_empty("Province")):
|
||||
choice = self.get_table().get_pile_index_of_card("Dutchy")
|
||||
elif coin >= 3 and not self.get_table().pile_is_empty("Silver"):
|
||||
choice = self.get_table().get_pile_index_of_card("Silver")
|
||||
|
||||
print(message + str(choice))
|
||||
return choice
|
||||
|
||||
def get_subclass_input(self, subclass):
|
||||
choice = -1
|
||||
hand = self.get_hand().get_supply()
|
||||
|
||||
for c in hand:
|
||||
if isinstance(c, subclass):
|
||||
choice = hand.index(c)
|
||||
return choice
|
||||
|
||||
def __get_first_non_Treasure(self):
|
||||
for c in self.get_hand().get_supply():
|
||||
if not isinstance(c, Treasure):
|
||||
return self.get_hand().get_supply().index(c)
|
||||
return 0
|
||||
9
player/bots/militia_big_money.py
Normal file
9
player/bots/militia_big_money.py
Normal file
@ -0,0 +1,9 @@
|
||||
from player.bot import Bot
|
||||
|
||||
|
||||
class Militia_Big_Money(Bot):
|
||||
target_card = "Militia"
|
||||
target_card_threshold = 4
|
||||
|
||||
def __str__(self):
|
||||
return "Player " + str(self.get_player_index()) + " (militia big money bot)"
|
||||
@ -1,59 +1,12 @@
|
||||
from player.player import Player
|
||||
from card.basic.card_treasure import Treasure
|
||||
from player.bot import Bot
|
||||
|
||||
|
||||
class Pure_Big_Money(Player):
|
||||
class Pure_Big_Money(Bot):
|
||||
target_card = "Province"
|
||||
target_card_threshold = 8
|
||||
|
||||
def take_action(self):
|
||||
print("\nAs a BIG MONEY BOT, I'm skipping this unnecessary action phase. Beep-boop, bow to me humans!")
|
||||
|
||||
#This method will only be called for this bot when it is time to play treasures, it will play all of them always.
|
||||
def get_play_input(self, message, target_type):
|
||||
choice = -1
|
||||
hand = self.get_hand().get_supply()
|
||||
|
||||
for c in hand:
|
||||
if isinstance(c, Treasure):
|
||||
choice = hand.index(c)
|
||||
|
||||
print(message + str(choice))
|
||||
return choice
|
||||
|
||||
#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.get_coin()
|
||||
choice = -1
|
||||
|
||||
if coin >= 8:
|
||||
choice = self.get_table().get_pile_index_of_card("Province")
|
||||
elif coin >= 6:
|
||||
choice = self.get_table().get_pile_index_of_card("Gold")
|
||||
elif coin >= 3:
|
||||
choice = self.get_table().get_pile_index_of_card("Silver")
|
||||
|
||||
print(message + str(choice))
|
||||
return choice
|
||||
|
||||
#This will pick either the first or the first least effective purchasing card as this bot doesn't care about that
|
||||
def militia_input(self, message, target_type):
|
||||
choice = self.__get_first_non_Treasure()
|
||||
min_coin = self.get_hand().get_supply()[choice].get_purchase_power()
|
||||
|
||||
for c in self.get_hand().get_supply():
|
||||
# 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()
|
||||
choice = self.get_hand().get_supply().index(c)
|
||||
|
||||
print(message + str(choice))
|
||||
return choice
|
||||
|
||||
def __get_first_non_Treasure(self):
|
||||
for c in self.get_hand().get_supply():
|
||||
if not isinstance(c, Treasure):
|
||||
return self.get_hand().get_supply().index(c)
|
||||
return 0
|
||||
|
||||
def __str__(self):
|
||||
return "Player " + str(self.get_player_index()) + " (pure big money bot)"
|
||||
|
||||
9
player/bots/smithy_big_money.py
Normal file
9
player/bots/smithy_big_money.py
Normal file
@ -0,0 +1,9 @@
|
||||
from player.bot import Bot
|
||||
|
||||
|
||||
class Smithy_Big_Money(Bot):
|
||||
target_card = "Smithy"
|
||||
target_card_threshold = 5
|
||||
|
||||
def __str__(self):
|
||||
return "Player " + str(self.get_player_index()) + " (smithy big money bot)"
|
||||
@ -22,7 +22,11 @@ class Hand(Supply):
|
||||
attack_blocked = False
|
||||
for c in self.get_supply():
|
||||
attack_blocked |= c.react(what_attack)
|
||||
return attack_blocked
|
||||
if attack_blocked:
|
||||
print(str(c.get_owner()) + " has " + str(c) + " as the " + str(self.get_supply().index(c)) +
|
||||
' and blocked the ' + what_attack + " attack.")
|
||||
return True
|
||||
return False
|
||||
|
||||
def __get_unique_class_instances(self):
|
||||
unique_class_instances = list()
|
||||
|
||||
@ -5,5 +5,3 @@ class Human(Player):
|
||||
def __str__(self):
|
||||
return "Player " + str(self.get_player_index()) + " (human)"
|
||||
|
||||
def militia_input(self, message, target_type):
|
||||
return self.get_general_input(message, target_type)
|
||||
|
||||
@ -39,6 +39,9 @@ class Player:
|
||||
def get_discard(self):
|
||||
return self.__discard
|
||||
|
||||
def get_deck(self):
|
||||
return self.__deck
|
||||
|
||||
def get_player_index(self):
|
||||
return self.__table.get_players().index(self)
|
||||
|
||||
@ -103,18 +106,30 @@ class Player:
|
||||
def discard_from_hand(self, n):
|
||||
self.__hand.transfer_card_by_index(n, self.__discard)
|
||||
|
||||
def play_card(self, acceptable_card_class, chances, counter):
|
||||
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)
|
||||
self.__check_play_card(hand_index, counter, acceptable_card_class, 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 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 take_turn(self):
|
||||
self.__turn_setup()
|
||||
self.__print()
|
||||
self.take_action()
|
||||
self.take_buy()
|
||||
self.discard_remaining_hand()
|
||||
self.draw_hand()
|
||||
|
||||
# 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, card_restriction):
|
||||
return self.__get_input(self.__std_chances, target_type, message)
|
||||
|
||||
def get_buy_input(self, message, target_type):
|
||||
return self.__get_input(self.__std_chances, target_type, message)
|
||||
|
||||
def get_response_input(self, message, target_type, card_restriction):
|
||||
return self.__get_input(self.__std_chances, target_type, message)
|
||||
|
||||
def take_action(self):
|
||||
print("\nPlease play an Action card until you have no remaining actions.")
|
||||
@ -130,6 +145,20 @@ class Player:
|
||||
self.play_card(Treasure, self.__std_chances, play_another)
|
||||
self.buy_card(self.__std_chances)
|
||||
|
||||
def play_card(self, acceptable_card_class, chances, counter):
|
||||
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,
|
||||
acceptable_card_class)
|
||||
self.__check_play_card(hand_index, counter, acceptable_card_class, 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 buy_card(self, chances):
|
||||
self.__table.print()
|
||||
while self.__buys > 0 and not self.__table.are_there_three_empty_piles() and chances > 0:
|
||||
@ -156,22 +185,6 @@ class Player:
|
||||
self.claim_top_card(self.__discard)
|
||||
chances = self.get_std_chances()
|
||||
|
||||
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_class, chances):
|
||||
if hand_index < 0:
|
||||
print("You have elected to forfeit any remaining plays.")
|
||||
@ -192,19 +205,6 @@ class Player:
|
||||
print("Index in bounds but not an acceptable card type. Chance to get it right reduced.")
|
||||
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
|
||||
def get_play_input(self, message, target_type):
|
||||
return self.get_general_input(message, target_type)
|
||||
|
||||
def get_buy_input(self, message, target_type):
|
||||
return self.get_general_input(message, target_type)
|
||||
|
||||
def militia_input(self, message, target_type):
|
||||
return self.get_general_input(message, target_type)
|
||||
|
||||
def get_general_input(self, message, target_type):
|
||||
return self.__get_input(self.__std_chances, target_type, message)
|
||||
|
||||
def __get_input(self, chances, target_type, message):
|
||||
value = input(message)
|
||||
if chances > 0:
|
||||
|
||||
@ -9,6 +9,9 @@ class Supply:
|
||||
for i in range(n):
|
||||
self.add_card(card)
|
||||
|
||||
def is_empty(self):
|
||||
return len(self.__card) <= 0
|
||||
|
||||
def get_supply(self):
|
||||
return self.__card
|
||||
|
||||
|
||||
@ -46,6 +46,9 @@ class Table:
|
||||
result = self.__pile.index(p)
|
||||
return result
|
||||
|
||||
def pile_is_empty(self, card_name):
|
||||
return self.__pile[self.get_pile_index_of_card(card_name)].is_empty()
|
||||
|
||||
def are_there_three_empty_piles(self):
|
||||
count = 0
|
||||
for p in self.__pile:
|
||||
@ -67,7 +70,7 @@ class Table:
|
||||
should_continue = True
|
||||
while should_continue:
|
||||
# game ends after
|
||||
should_continue = not self.should_game_end() or player_turn % len(self.__player) != 0
|
||||
should_continue = not self.should_game_end() or player_turn % len(self.__player) != len(self.__player) - 1
|
||||
self.print()
|
||||
self.__player[player_turn % len(self.__player)].take_turn()
|
||||
player_turn += 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user