lab_dice/yahtzee.py

156 lines
5.7 KiB
Python

from die import Die
class Yachtzee:
"""A command-line Yahtzee game.
This version of Yahtzee is initialized with a list of goals.
"""
def __init__(self, goals):
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!")
while self.count_unused_goals() > 0:
self.play_round()
print(f"Your final score was {self.score}")
def play_round(self):
"""Play a round of the game.
This will reset the rolls, rolls the dice shows the status of the game.
Then it allows the player to choose a goal and will then update the 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):
"""Shows the score, rolls left, and faces of the dice.
This prints the information for the player.
"""
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):
"""Let's the player choose a goal or to re roll the dice.
It creates a list of options for the player based on previous choices.
The player can choose an option."""
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):
"""Has the player choose a choice from the options given.
Displays a list of options, and either accepts the option or if it
is not a valid option tells the player they cannot choose that.
"""
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):
"""Checks to see if the player's choice is valid.
The choice has to be a number in the list of options otherwise
it will send the payler the error message."""
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):
"""Counts how many goals are left to be scored.
It will return however many unused goals are left.
"""
return len(self.get_unused_goals())
def get_unused_goals(self):
"""Gives a list of goals that haven't been scored yet.
This will show the player what goals are left and then they can decide
how to proceed in tha game.
"""
unused_goals = []
for goal in self.goals:
if not goal.used:
unused_goals.append(goal)
return unused_goals
def reroll(self):
"""Lets the player re-roll the dice if they choose to.
The player can choose which dice to re-roll if they decide to do that
in the game.
It then reduces the amount of rolls that are left.
"""
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):
"""The player can choose which dice to re-roll.
The player can pick which dice to re-roll and then the game will change
the number for those 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):
"""Asks the player which dice to re-roll.
It will ask the player which dice to re-roll if that is the choice they
choose. If they enter an invalid option the game sends a clarifying
question to make sure the input is valid.
"""
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):
"""Checks to see if re-roll choice is valid.
Makes sure what the player says matches what is valid in the game.
If not valid, it will ask the clarifying question.
"""
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