from die import Die class Yahtzee: """A command-line Yahtzee game. This version of Yahtzee is initialized with a list of goals. """ def __init__(self, goals): """Initialize a new game. Sets the starting score to zero, strores the list of goals and creates five dice for game. """ self.score = 0 self.goals = goals self.dice = [Die() for num in range(5)] def play(self): """Play an entire game. Starts by greeting the user, then plays rounds until all the goals have been used. When the game is over, tells the player their final score. """ print("Welcome to Yachtzee!") self.score = 0 for goal in self.goals: goal.used = False while self.count_unused_goals() > 0: self.play_round() print(f"Your final score was {self.score}") def play_round(self): """Play one round. Rolls all dice, displays game status, allows player to re roll or choose a goal and updates score. """ print("=" * 80) self.rolls_left = 3 for die in self.dice: die.roll() self.show_status() goal = self.choose_goal() goal.used = True self.score += goal.score(self.dice) def show_status(self): """Displays current game status. Shows player's score, remaining rolls, and current values of all five dice. """ dice = ', '.join([str(die) for die in self.dice]) print(f"Score: {self.score}. Rolls left: {self.rolls_left}. Dice: {dice}.") def choose_goal(self): """Allow player to choose a goal or re roll dice. Displays available goals and re roll options, then processes player's choice. """ options = [] unused_goals = self.get_unused_goals() for goal in unused_goals: option = goal.prompt(self.dice) options.append(option) if self.rolls_left > 0: options.append("Re-roll") choice = self.get_choice(options) if options[choice] == "Re-roll": self.reroll() self.show_status() return self.choose_goal() else: return unused_goals[choice] def get_choice(self, options): """Get choice from player. Displays numbered options and repeatedly asks for input until the player enters a valid choice. """ print("What would you like to do?") for i, option in enumerate(options): print(f"{i}. {option}") choice = input("> ") while not self.option_choice_is_valid(choice, options): print("Sorry, that's not a valid choice.") choice = input("> ") return int(choice) def option_choice_is_valid(self, choice, options): """Check if choice is valid. Ensures choice is a number within range. """ if not choice.isdigit(): return False if int(choice) < 0: return False if int(choice) >= len(options): return False return True def count_unused_goals(self): """Count how many goals remain unused. Returns number of goals not yet been scored. """ return len(self.get_unused_goals()) def get_unused_goals(self): """Get all unused goals. Returns a list of goals that have not been selected yet. """ unused_goals = [] for goal in self.goals: if not goal.used: unused_goals.append(goal) return unused_goals def reroll(self): """Re - roll selected dice. Decreases the number of rolls left and rolls only the dice chosen by the player. """ self.rolls_left -= 1 choices = self.get_reroll_choices() dice_to_reroll = self.get_dice_to_reroll(choices) for die in dice_to_reroll: die.roll() def get_dice_to_reroll(self, choice_ints): """Determine which dice to re roll. Matches player's selected values to dice and returns the corresponding dice. """ dice_to_reroll = [] for die in self.dice: if die.face in choice_ints: choice_ints.remove(die.face) dice_to_reroll.append(die) return dice_to_reroll def get_reroll_choices(self): """Gets dice values the player wants to re - roll. Player enter dice values and returns them as a integers. """ print("Which dice do you want to re-roll?") choices = input("> ") while not self.reroll_choices_are_valid(choices): print("Please enter the numbers on dice you want to re-roll.") choices = input("> ") choice_ints = [int(digit) for digit in choices] return choice_ints def reroll_choices_are_valid(self, choices_str): """Check re roll input is valid. Makes sure entered values are nummbers that match dice. """ if not choices_str.isdigit(): return False choice_ints = [int(digit) for digit in choices_str] for die in self.dice: if die.face in choice_ints: choice_ints.remove(die.face) return len(choice_ints) == 0