Now that I’ve got a solid foundation in SimpleHand, it’s relatively easy to expand the implementation of YahtzeeHand. This is a valuable aspect of inheritance and object oriented programming in general. I’m able to add the logic for 3, 4 and 5 (Yahtzee!) of a kind very easily. Here’s what it looks like all together in the YahtzeeHand class:
class YahtzeeHand(SimpleHand):
def __init__(self, seed: int = 0):
super(YahtzeeHand, self).__init__(num_sides=6, num_dice=5, seed=seed)
def is_large_straight(self) -> bool:
return self.num_sequential() == 5
def is_small_straight(self) -> bool:
return self.num_sequential() >= 4
def is_triple(self) -> bool:
return self.max_duplicates() >= 3
def is_four_of_a_kind(self) -> bool:
return self.max_duplicates() >= 4
def is_yahtzee(self) -> bool:
return self.max_duplicates() >= 5
I’ve got enough here now that I can run a quick simulation to answer some basic questions about Yahtzee — specifically how difficult it is to make each type of hand on an initial roll. Because I’ve got the basic Yahtzee class built, the code to run 100,000 rolls and collect specifics flows pretty easily:
def verify_yahtzee_hand(num_rolls: int = 10000):
h = YahtzeeHand()
num_special_hands = {
"LargeStraight": 0,
"SmallStraight": 0,
"3ofaKind": 0,
"4ofaKind": 0,
"Yahtzee!": 0
}
for i in range(num_rolls):
h.roll_all()
if h.is_small_straight():
num_special_hands["SmallStraight"] += 1
if h.is_large_straight():
num_special_hands["LargeStraight"] += 1
if h.is_triple():
num_special_hands["3ofaKind"] += 1
if h.is_four_of_a_kind():
num_special_hands["4ofaKind"] += 1
if h.is_yahtzee():
num_special_hands["Yahtzee!"] += 1
print(f"{num_rolls} rolls:")
for (name, occurrences) in num_special_hands.items():
print(f"{name:20} : {occurrences:8d} / {num_rolls} -- {(occurrences / num_rolls):>8.2%}")
When we run the sim over 100,000 rolls, we get this result:
100000 rolls:
LargeStraight : 3034 / 100000 -- 3.03%
SmallStraight : 15357 / 100000 -- 15.36%
3ofaKind : 21388 / 100000 -- 21.39%
4ofaKind : 2071 / 100000 -- 2.07%
Yahtzee! : 70 / 100000 -- 0.07%
This yields some interesting results… namely, a “natural” Yahtzee (Yahtzee in one roll) is pretty tough to get! But also, a small straight (4 consecutive numbers) is relatively easy (about one chance in six). We are missing one major type of hand still: the full house. I’m going to need to build a bit of special logic to handle that, so I’ll do that in the next post!