Phase 1 - Simulator
https://inst.eecs.berkeley.edu/~cs61a/su19/proj/hog/#phase-1-simulator
from dice import six_sided, four_sided, make_test_dice
from ucb import main, trace, interact
GOAL_SCORE = 100 # The goal of Hog is to score 100 points.
FREE_BACON_ROLLS = 0
######################
# Phase 1: Simulator #
######################
Problem 1
Implement the roll_dice
function in hog.py
. It takes two arguments: a positive integer called num_rolls
giving the number of dice to roll and a dice
function. It returns the number of points scored by rolling the dice that number of times in a turn: either the sum of the outcomes or 1 (Pig Out).
To obtain a single outcome of a dice roll, call dice()
. You should call dice()
exactly num_rolls
times in the body of roll_dice
. Remember to call dice()
exactly num_rolls
times even if Pig Out happens in the middle of rolling. In this way, we correctly simulate rolling all the dice together.
Solution:
def roll_dice(num_rolls, dice=six_sided):
"""Simulate rolling the DICE exactly NUM_ROLLS > 0 times.
Return the sum of the outcomes unless any of the outcomes is 1.
In that case, return 1.
num_rolls: The number of dice rolls that will be made.
dice: A function that simulates a single dice roll outcome.
"""
# These assert statements ensure that num_rolls is a positive integer.
assert type(num_rolls) == int, 'num_rolls must be an integer.'
assert num_rolls > 0, 'Must roll at least once.'
"*** YOUR CODE HERE ***"
rolls_sum = 0
PIG_OUT_VAL = 1
PIG_OUT = False
for roll in range (0, num_rolls):
dice_result = dice()
if dice_result == PIG_OUT_VAL:
PIG_OUT = True
rolls_sum += dice_result
if PIG_OUT:
return PIG_OUT_VAL
else:
return rolls_sum
Problem 2
Implement the free_bacon
helper function that returns the number of points scored by rolling 0 dice, based on the opponent's current score
. You can assume that score
is less than 100. For a score less than 10, assume that the first of the two digits is 0.
Solution:
def free_bacon(score):
"""Return the points scored from rolling 0 dice (Free Bacon).
score: The opponent's current score.
"""
assert score < 100, 'The game should be over.'
"*** YOUR CODE HERE ***"
FREE_POINTS_MAX = 10
if score <= FREE_POINTS_MAX:
return FREE_POINTS_MAX
first_digit = score // 10;
second_digit = score % 10;
if first_digit < second_digit:
return FREE_POINTS_MAX - first_digit
else:
return FREE_POINTS_MAX - second_digit
Problem 3
Implement the take_turn
function, which returns the number of points scored for a turn by rolling the given dice
num_rolls
times.
You will need to implement the Free Bacon rule based on opponent_score
, which you can assume is less than 100.
Your implementation of take_turn
should call both roll_dice
and free_bacon
when possible.
Solution:
def take_turn(num_rolls, opponent_score, dice=six_sided):
"""Simulate a turn rolling NUM_ROLLS dice, which may be 0 (Free Bacon).
Return the points scored for the turn by the current player.
num_rolls: The number of dice rolls that will be made.
opponent_score: The total score of the opponent.
dice: A function that simulates a single dice roll outcome.
"""
# Leave these assert statements here; they help check for errors.
assert type(num_rolls) == int, 'num_rolls must be an integer.'
assert num_rolls >= 0, 'Cannot roll a negative number of dice in take_turn.'
assert num_rolls <= 10, 'Cannot roll more than 10 dice.'
assert opponent_score < 100, 'The game should be over.'
"*** YOUR CODE HERE ***"
return free_bacon(opponent_score) if num_rolls == FREE_BACON_ROLLS else roll_dice(num_rolls, dice)
Problem 4
Implement is_swap
, which returns whether or not the scores should be swapped, according to the rules.
The is_swap
function takes two arguments: the players' scores. It returns a boolean value to indicate whether the Swine Swap condition is met.
Solution:
def is_swap(player_score, opponent_score):
"""
Return whether the two scores should be swapped
"""
# BEGIN PROBLEM 4
"*** YOUR CODE HERE ***"
def get_lmd(number):
return number if number < 10 else get_lmd(number // 10)
lmd_player = get_lmd(player_score)
rmd_oponent = opponent_score % 10
return lmd_player == rmd_oponent
Problem 5
Implement the play
function, which simulates a full game of Hog. Players alternate turns rolling dice until one of the players reaches the goal
score.
To determine how much dice are rolled each turn, each player uses their respective strategy (Player 0 uses strategy0
and Player 1 uses strategy1
). A strategy is a function that, given a player's score and their opponent's score, returns the number of dice that the current player wants to roll in the turn. Each strategy function should be called only once per turn. Don't worry about the details of implementing strategies yet. You will develop them in Phase 3.
When the game ends, play
returns the final total scores of both players, with Player 0's score first, and Player 1's score second.
Solution:
This code also includes solutions to other (later) problems - it's the final version of the play function:
def play(strategy0, strategy1, score0=0, score1=0, dice=six_sided, goal=GOAL_SCORE, say=silence):
"""Simulate a game and return the final scores of both players,
with Player 0's score first, and Player 1's score second.
A strategy is a function that takes two total scores as arguments (the
current player's score, and the opponent's score), and returns a number of
dice that the current player will roll this turn.
strategy0: The strategy function for Player 0, who plays first.
strategy1: The strategy function for Player 1, who plays second.
score0: Starting score for Player 0
score1: Starting score for Player 1
dice: A function of zero arguments that simulates a dice roll.
goal: The game ends and someone wins when this score is reached.
say: The commentary function to call at the end of the first turn.
"""
player = 0 # Which player is about to take a turn, 0 (first) or 1 (second)
"*** YOUR CODE HERE ***"
def is_game_over(score0, score1, goal_score):
return score0 >= goal_score or score1 >= goal_score
def get_current_strategy(strategy0, strategy1, player=0):
if (player == 0):
return strategy0
else:
return strategy1
def get_num_rolls(score0, score1, player, current_strategy):
if (player == 0):
return current_strategy(score0, score1)
else:
return current_strategy(score1, score0)
def swine_swap(curr_player_score, other_player_score):
if (is_swap(curr_player_score, other_player_score)):
curr_player_score, other_player_score = other_player_score, curr_player_score
return curr_player_score, other_player_score
def set_scores(num_rolls, score0, score1, player):
if (player == 0):
score0 += take_turn(num_rolls, score1, dice)
score0, score1 = swine_swap(score0, score1)
else:
score1 += take_turn(num_rolls, score0, dice)
score1, score0 = swine_swap(score1, score0)
return score0, score1
commentary = say
while not is_game_over(score0, score1, goal):
current_strategy = get_current_strategy(strategy0, strategy1, player)
num_rolls = get_num_rolls(score0, score1, player, current_strategy)
score0, score1 = set_scores(num_rolls, score0, score1, player)
player = other(player)
commentary = commentary(score0, score1)
return score0, score1
Last updated