from dice import six_sided, four_sided, make_test_dicefrom ucb import main, trace, interactGOAL_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:
defroll_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.asserttype(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 =Falsefor roll inrange (0, num_rolls): dice_result =dice()if dice_result == PIG_OUT_VAL: PIG_OUT =True rolls_sum += dice_resultif PIG_OUT:return PIG_OUT_VALelse: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:
deffree_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 =10if 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_digitelse: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 dicenum_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:
deftake_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.asserttype(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 ***"returnfree_bacon(opponent_score)if num_rolls == FREE_BACON_ROLLS elseroll_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:
defis_swap(player_score,opponent_score):""" Return whether the two scores should be swapped """# BEGIN PROBLEM 4"*** YOUR CODE HERE ***"defget_lmd(number):return number if number <10elseget_lmd(number //10) lmd_player =get_lmd(player_score) rmd_oponent = opponent_score %10return 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:
defplay(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 (thecurrent player's score, and the opponent's score), and returns a number ofdice 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 0score1: Starting score for Player 1dice: 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 ***"defis_game_over(score0,score1,goal_score):return score0 >= goal_score or score1 >= goal_scoredefget_current_strategy(strategy0,strategy1,player=0):if (player ==0):return strategy0else:return strategy1defget_num_rolls(score0,score1,player,current_strategy): if (player ==0):returncurrent_strategy(score0, score1)else:returncurrent_strategy(score1, score0)defswine_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 defset_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, score1commentary = saywhilenotis_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