def print_buildings_by_location(self, n_indent: int) -> None: """Display the player buildings of the player that is the location of the buildings in the deck: in the pile, the hand and the discard (but neither along the road nor replaced) .""" print(indent(n_indent) + self.name() + ', location of your buildings: ') for location in Location: player_building_names_by_location = sorted([player_building.name for player_building in self.get_player_buildings_by_location(location)] ) # type: List[PlayerBuilding] if player_building_names_by_location: print(indent(n_indent + 1) + location.name.lower() + ': ' + TXT_SEPARATOR.join(player_building_names_by_location) + '.')
def choose_action(self, possible_actions): self.print_buildings_by_location(3) n_possible_actions = len(possible_actions) # type: int # >= 1 because it must contain the passing action. if n_possible_actions == 1: print(indent(3) + 'You don\'t have any choice and you have to do the action: ' + possible_actions[0][1]) return possible_actions[0] else: print(indent(3) + 'Here are all the possible action(s):') for i_possible_actions, possible_action in enumerate(possible_actions): print(indent(4) + str(i_possible_actions) + ': ' + possible_action[1]) response = input(indent(3) + 'Which action do you choose? [0..' + str(n_possible_actions - 1) + '] ') # type: str return possible_actions[self.check_response_in_interval(response, 0, n_possible_actions - 1, 4)]
def choose_buy_resource(self, money_resource_cost: MoneyResource, qty_cost: int, resource_gain_choices, qty_gain: int) -> Resource: possibilities = list(Building.ABBREV_NO_USE_EFFECT) # type: List[str[1]] abbrev_resource_name_resource = {} # type: Dict[str[1], Resource] # E.g. {'F': food, ...}. for resource in resource_gain_choices: abbrev_resource_name = resource.get_name_abbreviation() abbrev_resource_name_resource[abbrev_resource_name] = resource possibilities.append(abbrev_resource_name) print(indent(4) + self.txt_name_money_resources_workers_PPs_deck(True, True, False, False, False) + '.') response = input(indent(4) + 'Do you want to consume ' + str(qty_cost) + ' ' + money_resource_cost.name + '(s) to obtain ' + str(qty_gain) + ' resource ' + Building.TXT_NO_USE_EFFECT + '? [' + '/'.join(possibilities) + '] ') # type: str response = self.check_response_in_possibilities(response, possibilities, 5) return None if response == Building.ABBREV_NO_USE_EFFECT else abbrev_resource_name_resource[response]
def choose_exchange_resource(self, can_no_use_effect: bool, qty_cost: int, resource_cost_choices, money_resource_gain: MoneyResource, qty_gain: int) -> Resource: abbrev_resource_name_resources = Resource.get_name_abbreviation_resources(resource_cost_choices) possibilities = list() # type: List[str[1]] if can_no_use_effect: possibilities.append(Building.ABBREV_NO_USE_EFFECT) possibilities += list(abbrev_resource_name_resources.keys()) print(indent(4) + self.txt_name_money_resources_workers_PPs_deck(True, True, False, False, False) + '.') response = input(indent(4) + 'Do you want to exchange ' + str(qty_cost) + ' of some resource with ' + str(qty_gain) + ' ' + money_resource_gain.name + (' or not use the effect ' + Building.TXT_NO_USE_EFFECT if can_no_use_effect else '') + '? [' + '/'.join(possibilities) + '] ') # type: str response = self.check_response_in_possibilities(response, possibilities, 5) return None if response == Building.ABBREV_NO_USE_EFFECT else abbrev_resource_name_resources[response]
def choose_n_provost_movement(self, n_min_provost_movements_player: int, n_max_provost_movements_player: int) -> int: response = input(indent(3) + 'How long do you want to move the Provost? [' + str(n_min_provost_movements_player) + '..' + str(n_max_provost_movements_player) + '] ') # type: str return self.check_response_in_interval(response, n_min_provost_movements_player, n_max_provost_movements_player, 4)
def apply_primary_effect(self, player: Player) -> None: """Apply the (default that is for park, forest, quarry and trading post) effect of a neutral building.""" print( indent(3) + 'Effect of the neutral building ' + self.name + ' for a worker of the player ' + player.name() + ': ' + self.primary_effect.text) self.apply_no_cost_only_gain_effect( self.primary_effect.money_resources_gain, player)
def choose_buy_castle_multi(self, costs, castle_gain_choices): # -> List[Castle] n_min_castle_gain = 0 # type: int n_max_castle_gain = len(castle_gain_choices) # type: int response = input(indent(4) + 'How many tokens of parts of the castle among [' + ', '.join(castle.name for castle in castle_gain_choices) + '] do you want to buy with: ' + ' or '.join(str(qty_cost) + ' ' + money_resource_cost.name + '(s)' for (money_resource_cost, qty_cost) in costs) + '? [' + str(n_min_castle_gain) + '..' + str(n_max_castle_gain) + '] ') # type: str return castle_gain_choices[:self.check_response_in_interval(response, n_min_castle_gain, n_max_castle_gain, 5)]
def income_effect(self, income_phase: phase.Phase = None) -> None: """Give some money to the player owing this hotel prestige building on the road.""" n_deniers = income_phase.n_deniers_if_hotel # type: int print( indent(2) + self.color_player.player.name() + ' obtains ' + str(n_deniers) + ' ' + Money.money.name + '(s) for a(n) ' + self.name + ' building along the road.') self.color_player.player.current_money_resources[ Money.money] += n_deniers
def choose_construct_residence(self, resource_costs, i_road_buildings_on_road): # -> Optional[Tuple[int, Building]] n_min_i_building = 0 # type: int n_max_i_building = len(i_road_buildings_on_road) # type: int response = input(indent(4) + 'Which of your ' + str(n_max_i_building) + ' building(s) [' + ', '.join(building_on_road.name for (i_road, building_on_road) in i_road_buildings_on_road) + '] do you want to choose (or ' + str(n_min_i_building) + ' if you don\'t want to use the effect)? [' + str(n_min_i_building) + '..' + str(n_max_i_building) + '] ') # type: str response = self.check_response_in_interval(response, n_min_i_building, n_max_i_building, 5) # type: int return None if response == n_min_i_building else i_road_buildings_on_road[response - 1]
def apply_no_cost_only_gain_effect(self, money_resources_gain, player: Player = None) -> None: """Apply the effect of a building for (the worker of) the player. This effect doesn't require any cost and give some gain; so, we don't ask it hte player want it and give him.""" if player is None: player = self.color_player.player money_resource, qty = money_resources_gain # type: Tuple[MoneyResource, int] player.current_money_resources[money_resource] += qty print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + '.')
def apply_primary_effect(self, player: Player) -> None: """Apply the effect of a peddler neutral building.""" """ Buy 1 cube (any resource but gold) from the stock with 1 denier. """ # Remark: Hard-coded! We don't use the tags <cost><n_deniers>-1 and <gain><CHOICES>... in <game_elements><buildings><neutral_buildings><neutral_building>. print( indent(3) + 'Effect of the neutral building ' + self.name + ' for a worker of the player ' + player.name() + ': ' + self.primary_effect.text) self.apply_peddler_effect(player)
def apply_peddler_effect(self, player: Player) -> None: """Apply the effect of a peddler (neutral or player) building.""" """ Buy 1 cube (any resource but gold) from the stock with 1 denier. """ # Remark: Hard-coded! We don't use the tags <cost><n_deniers>-1 and <gain><CHOICES>... in <game_elements><buildings><player_buildings><player_building><secondary_effect>. money_resource_cost, qty_cost = Money.money, -1 # type: MoneyResource, int if player.current_money_resources[money_resource_cost] + \ qty_cost < 0: # Has the player enough money or resource? print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' and can\'t apply the effect because he/she doesn\'t have enough money or resource as ' + str(qty_cost) + ' ' + money_resource_cost.name + '(s) required.') else: resource_gain_choices, qty_gain = [resource for resource in Resource.resources.values() if not resource.is_wild()], \ +1 # type: List[Resource], int resource_gain = player.choose_buy_resource( money_resource_cost, qty_cost, resource_gain_choices, qty_gain) # type: Resource if resource_gain is None: print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' and had chosen to don\'t apply the effect.') else: print( indent(4) + player.name() + ' wants to consume ' + str(qty_cost) + ' ' + money_resource_cost.name + '(s) to obtain ' + str(qty_gain) + ' ' + resource_gain.name + '(s).') player.current_money_resources[money_resource_cost] += qty_cost player.current_money_resources[resource_gain] += qty_gain print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' once the effect applied.')
def check_response_in_interval(self, response: str, n_min: int, n_max: int, n_indent: int) -> int: """Check that a (string) response is in an interval (of numeric values).""" is_response_ok = False # type: bool while not is_response_ok: try: response_ok = int(response) # type: int is_response_ok = n_min <= response_ok <= n_max # Is in the interval? except ValueError: is_response_ok = False # Not a numeric. if not is_response_ok: response = input(indent(n_indent) + 'Please: ') return response_ok
def choose_buy_resource_multi(self, costs, resource_gain_choices, qty_gain: int): # -> List[Resource] # Remark: we only consider the case that costs is a List[Tuple[Money,int]] without resource and of length 2 or more. possibilities = list(Building.ABBREV_NO_USE_EFFECT) # type: List[str[1..qty_gain]] abbrev_resource_name_resource = {resource.get_name_abbreviation(): resource for resource in resource_gain_choices } # type: Dict[str[1], Resource] # E.g. {'F': food, ...}. possibilities.extend([''.join( resource_gain.get_name_abbreviation() for resource_gain in list(resource_gain_choice)) for n_parts in range(1, qty_gain + 1) for resource_gain_choice in itertools.combinations_with_replacement(resource_gain_choices, n_parts)]) print(indent(4) + self.txt_name_money_resources_workers_PPs_deck(True, True, False, False, False) + '.') response = input(indent(4) + 'Do you want to consume either ' + ' or '.join(str(qty_cost) + ' ' + money_resource_cost.name + '(s) for ' + str(1 + i_costs) + ' resource(s)' for i_costs, (money_resource_cost, qty_cost) in enumerate(costs)) + ' ' + Building.TXT_NO_USE_EFFECT + '? [' + '/'.join(possibilities) + '] ') # type: str response = self.check_response_in_possibilities(response, possibilities, 5) choose_buy_resource_multi = list() if response != Building.ABBREV_NO_USE_EFFECT: for abbrev_resource_name in response: choose_buy_resource_multi.append(abbrev_resource_name_resource[abbrev_resource_name]) return choose_buy_resource_multi
def choose_n_batches_to_castle(self, n_max_batches_to_castle: int) -> int: response = input(indent(3) + 'How many batches do you want to offer to the castle? [0..' + str(n_max_batches_to_castle) + '] ') # type: str return self.check_response_in_interval(response, 0, n_max_batches_to_castle, 4)
def apply_effect_multi(self, player: Player, all_costs, resource_gain_choices, single_qty_gain: int) -> None: """Apply an effect with several choices (e.g. primary effects of bank and peddler player buildings).""" # :param all_costs: # type: List[Tuple[Money, int]] # Must be ordered! # :param resource_gain_choices: # type: List[Resource] costs = [(money_resource_cost, qty_cost) for (money_resource_cost, qty_cost) in all_costs if player.current_money_resources[money_resource_cost] + qty_cost >= 0] if not costs: # Has the player enough money or resource? print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' and can\'t apply the effect because he/she doesn\'t have enough money or resource as ' + 'either ' + ' or '.join( str(qty_cost) + ' ' + money_resource_cost.name + '(s)' for (money_resource_cost, qty_cost) in all_costs) + ' required.') elif len(costs) == 1: print( indent(4) + 'There exists only one choice according to money and resources you have.' ) money_resource_cost, qty_cost = costs[0] resource_gain = player.choose_buy_resource( money_resource_cost, qty_cost, resource_gain_choices, single_qty_gain) # type: Resource if resource_gain is None: print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' and had chosen to don\'t apply the effect.') else: print( indent(4) + player.name() + ' wants to consume ' + str(qty_cost) + ' ' + money_resource_cost.name + '(s) to obtain ' + str(single_qty_gain) + ' ' + resource_gain.name + '(s).') player.current_money_resources[money_resource_cost] += qty_cost player.current_money_resources[ resource_gain] += single_qty_gain print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' once the effect applied.') else: resources_gain = player.choose_buy_resource_multi( costs, resource_gain_choices, len(costs) * single_qty_gain) if not resources_gain: print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' and had chosen to don\'t apply the effect.') else: money_resource_cost, qty_cost = costs[ len(resources_gain) - 1] # costs must be ordered! print( indent(4) + player.name() + ' wants to consume ' + str(qty_cost) + ' ' + money_resource_cost.name + '(s).') player.current_money_resources[money_resource_cost] += qty_cost for resource_gain, qty_gain in collections.Counter( resources_gain).items(): # To group by resource. print( indent(4) + player.name() + ' wants to obtain ' + str(single_qty_gain * qty_gain) + ' ' + resource_gain.name + '(s).') player.current_money_resources[ resource_gain] += single_qty_gain * qty_gain print( indent(4) + player.txt_name_money_resources_workers_PPs_deck( True, True, False, False, False) + ' once the effect applied.')
def check_response_in_possibilities(self, response: str, possibilities, n_indent: int) -> str: """Check that a (string) response is in a list of (str[1..2]) possibilities.""" while len(response) == 0 or response.upper() not in possibilities: response = input(indent(n_indent) + 'Please: ') return response.upper()