lab_dice/yahtzee.py

146 lines
6.7 KiB
Python

from die import Die
class Yachtzee:
"""A command-line Yachtzee game.
This version of Yachtzee is initialized with a list of goals.
"""
def __init__(self, goals):
"""Initializes the class Yachtzee.
Sets the characteristics score, goals, and dice to initial states."""
self.score = 0
self.goals = goals
self.dice = [Die() for num in range(5)]
def play(self):
"""Plays the Yachtzee game.
Prints Welcome to Yachtzee! Plays a round of the game until all of the goals have been used.
When the goals have all been used, prints the final score."""
print("Welcome to Yachtzee!")
while self.count_unused_goals() > 0:
self.play_round()
print(f"Your final score was {self.score}")
def play_round(self):
"""Starts one round of the Yachtzee game.
Prints a border consisting of 80 equal signs. Sets the rolls left to 3. Iteratively rolls the die for each of the five dice. Saves
the goals and score, determined by the goal chosen and the die."""
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):
"""Shows the score, rolls left, and dice numbers.
Saves the values from the dice rolls as a string separated by commas. Prints the score, rolls left, and 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):
"""Allows the player to choose the goal to satisfy.
Makes the empty list options. Stores the return from get_unused_goals in the unused_goals list. Iteratively adds options to the options list for
each goal in unused goals. If there is at least one re-roll left, adds re-roll as an option. Stores the options in the choice list. If player chose to
re-roll, then does reroll and returns the choose_goal. Otherwise, returns the chosen goal."""
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):
"""Asks the player what they would like to do and presents options.
Prints the question, then iteratively numbers the items in the options list and prints as a numbered list. Prompts for the input with >
and stores the input in the choice list. If the choice is not valid, the prints so and prompts for another choice. Returns the choice as
integer."""
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):
"""Assesses whether the choice selected is valid.
Returns false if the choice is not a digit, if the choice is less than 0, or if the choice is greater than the length of the list of options.
Otherwise, returns True."""
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):
"""Reurns the number of unused goals left.
Returns the length of the list unused_goals."""
return len(self.get_unused_goals())
def get_unused_goals(self):
"""Returns a list of available goals for the player to use.
Makes an empty list for unused_goals. Iteratively adds goal to unused_goals if the goal is not used. Returns the list of unused goals."""
unused_goals = []
for goal in self.goals:
if not goal.used:
unused_goals.append(goal)
return unused_goals
def reroll(self):
"""Rerolls the die that are not kept by the player.
Subtracts 1 from the rolls left. Sets choices equal to the choice_ints output from get_reroll_choices(). Sets dice_to_reroll equal to
output from get_dice_to_reroll() output. Then, iteratively rolls die for dice_to_reroll."""
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):
"""Gets the dice the player wants to re-roll.
Makes an empty list for dice_to_reroll. For die in dice, iteratively removes the number rolled from the choice_ints for each of the numbers in
choice_ints and adds the die to the dice_to_reroll list, and then returns the list."""
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 the dice to re-roll.
Asks which dice to re-roll, then stores the input as choices. If invalid input, prompts to enter the numbers from the dice to re-roll
then stores the input as choices. Converts the choices to integers and returns."""
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):
"""Assesses whether the chosen dice to re-roll are valid.
If the choices are not digits, returns False. Stores integers converted from choices_str as choice_ints. Iteratively removes the die.face value
from the choice_ints if it's in there. Returns the length of the choice_ints list if it is equal to 0."""
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