class GoalOnes: "One point for each one" def prompt(self, dice): potential_score = self.score(dice) return f"Ones ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 1: total += 1 return total class GoalTwos: "Two points for each two" def prompt(self, dice): potential_score = self.score(dice) return f"Twos ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 2: total += 2 return total class GoalThrees: "Three points for each three" def prompt(self, dice): potential_score = self.score(dice) return f"Threes ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 3: total += 3 return total class GoalFours: "Four points for each four" def prompt(self, dice): potential_score = self.score(dice) return f"Fours ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 4: total += 4 return total class GoalFives: "Five points for each five" def prompt(self, dice): potential_score = self.score(dice) return f"Fives ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 5: total += 5 return total class GoalSixes: "Six points for each six" def prompt(self, dice): potential_score = self.score(dice) return f"Sixes ({potential_score})" def score(self, dice): total = 0 for die in dice: if die.face == 6: total += 6 return total class GoalThreeOfAKind: "Sum all dice if there are at least three of the same face" def prompt(self, dice): potential_score = self.score(dice) return f"Three of a kind ({potential_score})" def score(self, dice): counts = {} total = 0 for die in dice: counts[die.face] = counts.get(die.face, 0) + 1 total += die.face for cnt in counts.values(): if cnt >= 3: return total return 0 class GoalFourOfAKind: "Sum all dice if there are at least four of the same face" def prompt(self, dice): potential_score = self.score(dice) return f"Four of a kind ({potential_score})" def score(self, dice): counts = {} total = 0 for die in dice: counts[die.face] = counts.get(die.face, 0) + 1 total += die.face for cnt in counts.values(): if cnt >= 4: return total return 0 class GoalFullHouse: "Fixed score when three of one face and two of another are present" def prompt(self, dice): potential_score = self.score(dice) return f"Full House ({potential_score})" def score(self, dice): counts = {} for die in dice: counts[die.face] = counts.get(die.face, 0) + 1 values = sorted(counts.values()) # Full house is a 2 and a 3 if values == [2, 3]: return 25 return 0 class GoalSmallStraight: "Fixed score for any run of four consecutive face values" def prompt(self, dice): potential_score = self.score(dice) return f"Small Straight ({potential_score})" def score(self, dice): faces = sorted({die.face for die in dice}) # Check for any sequence of length 4 runs = [faces[i:i+4] for i in range(len(faces) - 3)] for run in runs: if run == list(range(run[0], run[0] + 4)): return 30 return 0 class GoalLargeStraight: "Fixed score for a run of five consecutive face values" def prompt(self, dice): potential_score = self.score(dice) return f"Large Straight ({potential_score})" def score(self, dice): faces = sorted({die.face for die in dice}) if faces == list(range(1, 6)) or faces == list(range(2, 7)): return 40 return 0 class GoalYahtzee: "Fixed score for five of a kind (Yahtzee)" def prompt(self, dice): potential_score = self.score(dice) return f"Yahtzee ({potential_score})" def score(self, dice): first = dice[0].face for die in dice: if die.face != first: return 0 return 50 class GoalChance: "Sum of all dice (always available)" def prompt(self, dice): potential_score = self.score(dice) return f"Chance ({potential_score})" def score(self, dice): total = 0 for die in dice: total += die.face return total