"""The Game of Hog.""" from dice import four_sided, six_sided, make_test_dice from ucb import main, trace, log_current_line, interact from random import randrange GOAL_SCORE = 100 # The goal of Hog is to score 100 points. ###################### # Phase 1: Simulator # ###################### def roll_dice(num_rolls, dice=six_sided): """Simulate rolling the DICE exactly NUM_ROLLS times. Return the sum of the outcomes unless any of the outcomes is 1. In that case, return 0. """ # 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.' # BEGIN Question 1 rolls =[] sum = 0 for i in range(0,num_rolls): rolls.append(dice()) sum+= rolls[i] if(1 in rolls): return 0 return sum # END Question 1 def is_prime(n): """takes a number and then returns True if the number is prime and False if the number is not prime ie 1 is not prime >>> is_prime(37) True >>> is_prime(42) False >>> is_prime(1) False""" if(n==1 or n==0): return False k = n-1 while k > 1: if(n%k==0): return False k -= 1 return True def next_prime(n): """takes a number n and then returns the next larger integer x that is a prime number >>> next_prime(32) 37 >>> next_prime(4) 5""" num = n + 1 not_correct = True while not_correct: if is_prime(num): not_correct = False return num num += 1 def free_bacon(opponent_score): # free bacon rule function can be used return max(opponent_score%10, opponent_score//10) + 1 def take_turn(num_rolls, opponent_score, dice=six_sided): """Simulate a turn rolling NUM_ROLLS dice, which may be 0 (Free bacon). num_rolls: The number of dice rolls that will be made. opponent_score: The total score of the opponent. dice: A function of no args that returns an integer outcome >>> take_turn(0, 38) 9 """ assert type(num_rolls) == int, 'num_rolls must be an integer.' assert num_rolls >= 0, 'Cannot roll a negative number of dice.' assert num_rolls <= 10, 'Cannot roll more than 10 dice.' assert opponent_score < 100, 'The game should be over.' # BEGIN Question 2 turn_score = 0 if(num_rolls == 0): turn_score = free_bacon(opponent_score) #free bacon rule else: turn_score = roll_dice(num_rolls, dice) if(is_prime(turn_score)): # implementation of the Hogtimus prime rule return next_prime(turn_score) else: return turn_score # END Question 2 def select_dice(score, opponent_score): """Select six-sided dice unless the sum of SCORE and OPPONENT_SCORE is a multiple of 7, in which case select four-sided dice (Hog wild). """ # BEGIN Question 3 if((score+opponent_score)%7 == 0): #hog wild special rule implemented here return four_sided else: return six_sided # END Question 3 def is_swap(score0, score1): """Returns whether the last two digits of SCORE0 and SCORE1 are reversed versions of each other, such as 19 and 91. """ # BEGIN Question 4 return (score0%10 *10 + (score0//10)%10)==score1 or (score1%10 *10 + (score1//10)%10) == score0 # END Question 4 def other(who): """Return the other player, for a player WHO numbered 0 or 1. >>> other(0) 1 >>> other(1) 0 """ return 1 - who def play(strategy0, strategy1, score0=0, score1=0, goal=GOAL_SCORE): """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 : The starting score for Player 0 score1 : The starting score for Player 1 """ def turn_score(current_score, opponent_score, strategy): # returns both score to be added for the turn as well as number of dice rolled by current player strat0 = strategy(current_score, opponent_score) turn_dice = select_dice(current_score, opponent_score) return take_turn(strat0, opponent_score, turn_dice), strat0 who = 0 # Which player is about to take a turn, 0 (first) or 1 (second) # BEGIN Question 5 keep_playing = True while keep_playing: if(who==0): add_score, piggy_back = turn_score(score0, score1, strategy0) if(add_score==0): #piggy back rule score1 += piggy_back score0 += add_score else: add_score, piggy_back = turn_score(score1, score0, strategy1) if(add_score==0): #piggy back rule score0 += piggy_back score1 += add_score if(is_swap(score0,score1)): score0, score1 = score1, score0 if(score0>=goal or score1>=goal): keep_playing = False who = other(who) return score0, score1 ####################### # Phase 2: Strategies # ####################### def always_roll(n): """Return a strategy that always rolls N dice. 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. >>> strategy = always_roll(5) >>> strategy(0, 0) 5 >>> strategy(99, 99) 5 """ def strategy(score, opponent_score): return n return strategy # Experiments def make_averaged(fn, num_samples=10000): """Return a function that returns the average_value of FN when called. To implement this function, you will have to use *args syntax, a new Python feature introduced in this project. See the project description. >>> dice = make_test_dice(3, 1, 5, 6) >>> averaged_dice = make_averaged(dice, 1000) >>> averaged_dice() 3.75 >>> make_averaged(roll_dice, 1000)(2, dice) 5.5 In this last example, two different turn scenarios are averaged. - In the first, the player rolls a 3 then a 1, receiving a score of 0. - In the other, the player rolls a 5 and 6, scoring 11. Thus, the average value is 5.5. Note that the last example uses roll_dice so the hogtimus prime rule does not apply. """ # BEGIN Question 6 def avg_value(*args): sum = 0 k = 0 while k < num_samples: sum += fn(*args) k+=1 return sum / num_samples return avg_value # END Question 6 def max_scoring_num_rolls(dice=six_sided, num_samples=10000): """Return the number of dice (1 to 10) that gives the highest average turn score by calling roll_dice with the provided DICE over NUM_SAMPLES times. Assume that dice always return positive outcomes. >>> dice = make_test_dice(3) >>> max_scoring_num_rolls(dice) 10 """ # BEGIN Question 7 best_avg = 0 best_num_rolls = 0 counter = 10 while counter >= 1: a = make_averaged(roll_dice, num_samples) dice_avg = a(counter, dice) if(dice_avg >= best_avg): best_avg = dice_avg best_num_rolls = counter counter -= 1 return best_num_rolls # END Question 7 def winner(strategy0, strategy1): """Return 0 if strategy0 wins against strategy1, and 1 otherwise.""" score0, score1 = play(strategy0, strategy1) if score0 > score1: return 0 else: return 1 def average_win_rate(strategy, baseline= always_roll(5)): """Return the average win rate of STRATEGY against BASELINE. Averages the winrate when starting the game as player 0 and as player 1. """ win_rate_as_player_0 = 1 - make_averaged(winner)(strategy, baseline) # 1 - because if zero comes more often then 1 - is the real winning rate you have win_rate_as_player_1 = make_averaged(winner)(baseline, strategy) return (win_rate_as_player_0 + win_rate_as_player_1) / 2 def run_experiments(): """Run a series of strategy experiments and report results.""" if True: # Change to False when done finding max_scoring_num_rolls six_sided_max = max_scoring_num_rolls(six_sided) print('Max scoring num rolls for six-sided dice:', six_sided_max) four_sided_max = max_scoring_num_rolls(four_sided) print('Max scoring num rolls for four-sided dice:', four_sided_max) if False: # Change to True to test always_roll(3) print('always_roll(3) win rate:', average_win_rate(always_roll(3))) if False: # Change to True to test bacon_strategy print('bacon_strategy win rate:', average_win_rate(bacon_strategy)) if False: # Change to True to test swap_strategy print('swap_strategy win rate:', average_win_rate(swap_strategy)) if True: # tests the final_strategy's win rate print('final_strategy win rate:', average_win_rate(final_strategy)) "*** You may add additional experiments as you wish ***" # Strategies def bacon_strategy(score, opponent_score, margin=6, num_rolls=3): """This strategy rolls 0 dice if that gives at least MARGIN points, and rolls NUM_ROLLS otherwise. """ # BEGIN Question 8 if(take_turn(0, opponent_score)>=margin): return 0 return num_rolls # END Question 8 def swap_strategy(score, opponent_score, num_rolls=3): """This strategy rolls 0 dice when it results in a beneficial swap and rolls NUM_ROLLS otherwise. """ # BEGIN Question 9 swap_check = take_turn(0, opponent_score) if(is_swap(swap_check+score, opponent_score) and (swap_check+score)<opponent_score): return 0 return num_rolls # END Question 9 def close_swap_strategy(score, opponent_score, num_rolls =3): if(opponent_score > score): counter = 6 while(counter<=10): if(is_swap(score, opponent_score+counter)): return counter counter += 1 return num_rolls def hogwild_free_strategy(score, opponent_score, num_rolls =3): add = take_turn(0, opponent_score) if((score+opponent_score+add)%7==0): return 0 return num_rolls def choose_dice_strategy(score, opponent_score, num_rolls =3): if(select_dice(score,opponent_score)==six_sided): num_rolls = 5 return num_rolls """def hogwild_piggy_strategy(score, opponent_score, num_rolls=3): if(opponent_score > score): counter = 10 while(counter <= 10): if((score + opponent_score + counter) % 7 == 0): return counter counter += 1 return num_rolls""" def final_strategy(score, opponent_score): """Write a brief description of your final strategy. first combine bacon_strategy and swap_strategy, checking swap_strategy first *** YOUR DESCRIPTION HERE *** """ # BEGIN Question 10 """if(score >= 92): # can try to use dice to get hogtimus prime with 7 return 3""" bacon = free_bacon(opponent_score) """if(choose_dice_strategy(score, opponent_score) == six_sided): return choose_dice_strategy(score, opponent_score)""" if(close_swap_strategy(score, opponent_score)>=6): return close_swap_strategy(score, opponent_score) if(hogwild_free_strategy(score, opponent_score)==0): return 0 """if(hogwild_piggy_strategy(score, opponent_score)>=10): return hogwild_piggy_strategy(score, opponent_score)""" if(swap_strategy(score, opponent_score)==0 or bacon_strategy(score, opponent_score)==0): return 0 return 3 # Replace this statement # END Question 10 ########################## # Command Line Interface # ########################## # Note: Functions in this section do not need to be changed. They use features # of Python not yet covered in the course. @main def run(*args): """Read in the command-line argument and calls corresponding functions. This function uses Python syntax/techniques not yet covered in this course. """ import argparse parser = argparse.ArgumentParser(description="Play Hog") parser.add_argument('--run_experiments', '-r', action='store_true', help='Runs strategy experiments') args = parser.parse_args() if args.run_experiments: run_experiments()
Run
Reset
Share
Import
Link
Embed
Language▼
English
中文
Python Fiddle
Python Cloud IDE
Follow @python_fiddle
Browser Version Not Supported
Due to Python Fiddle's reliance on advanced JavaScript techniques, older browsers might have problems running it correctly. Please download the latest version of your favourite browser.
Chrome 10+
Firefox 4+
Safari 5+
IE 10+
Let me try anyway!
url:
Go
Python Snippet
Stackoverflow Question