Guest User

Untitled

a guest
Jan 22nd, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.32 KB | None | 0 0
  1. """The Game of Pig"""
  2.  
  3. from dice import make_fair_die, make_test_die
  4. from ucb import main, trace, log_current_line, interact
  5.  
  6. goal = 100 # The goal of pig is always to score 100 points.
  7.  
  8. # Taking turns
  9.  
  10. def roll(turn_total, outcome):
  11. """Performs the roll action, which adds outcome to turn_total, or loses the
  12. turn on outcome == 1.
  13.  
  14. Arguments:
  15. turn -- number of points accumulated by the player so far during the turn
  16. outcome -- the outcome of the roll (the number generated by the die)
  17.  
  18. Returns three values in order:
  19. - the number of points the player scores after the roll
  20. Note: If the turn is not over after this roll, this return value is 0.
  21. No points are scored until the end of the turn.
  22. - the player turn point total after the roll
  23. - a boolean; whether or not the player's turn is over
  24.  
  25. >>> roll(7, 3)
  26. (0, 10, False)
  27. >>> roll(99, 1)
  28. (1, 0, True)
  29. """
  30. if outcome == 1:
  31. return 1,0,True
  32. else:
  33. return 0,turn_total+outcome, False
  34.  
  35. def hold(turn_total, outcome):
  36. """Performs the hold action, which adds turn_total to the player's score.
  37.  
  38. Arguments:
  39. turn -- number of points accumulated by the player so far during the turn
  40. outcome -- the outcome of the roll, ie. the number generated by the die
  41.  
  42. Returns three values in order:
  43. - the number of points the player scores after holding
  44. - the player turn total after the roll (always 0)
  45. - a boolean; whether or not the player's turn is over
  46.  
  47. >>> hold(99, 1)
  48. (99, 0, True)
  49. """
  50. return turn_total, 0, True
  51.  
  52. def take_turn(plan, dice=make_fair_die(), who='Someone', comments=False):
  53. """Simulate a single turn and return the points scored for the whole turn.
  54.  
  55. Important: The d function should be called once, **and only once**, for
  56. every action taken! Testing depends upon this fact.
  57.  
  58. Arguments:
  59. plan -- a function that takes the turn total and returns an action function
  60. dice -- a function that takes no args and returns an integer outcome.
  61. Note: dice is non-pure! Call it exactly once per action.
  62. who -- name of the current player
  63. comments -- a boolean; whether commentary is enabled
  64. """
  65. score_for_turn = 0 # Points scored in the whole turn
  66. turn_state = False
  67. points_gained = 0
  68. score_for_turn = 0
  69. while turn_state == False:
  70.  
  71. action = plan(score_for_turn)
  72. dice_roll = dice()
  73.  
  74. points_gained, score_for_turn, turn_state = action(score_for_turn, dice_roll)
  75. #print(points_gained)
  76. #print(score_for_turn)
  77. #print(turn_state)
  78. commentate(action, dice_roll, points_gained, score_for_turn, turn_state, who)
  79. '''fix'''
  80.  
  81. return points_gained
  82.  
  83. def take_turn_test():
  84. """Test the take_turn function using deterministic test dice."""
  85. plan = make_roll_until_plan(10) # plan is a function (see problem 2)
  86. "*** YOUR CODE HERE ***"
  87. print(take_turn(plan, make_test_die(1,2,3))) # Not deterministic
  88.  
  89.  
  90. # Commentating
  91.  
  92. def commentate(action, outcome, score_for_turn, turn_total, over, who):
  93. """Print descriptive comments about a game event.
  94.  
  95. action -- the action function chosen by the current player
  96. outcome -- the outcome of the die roll
  97. score_for_turn -- the points scored in this turn by the current player
  98. turn_total -- the current turn total
  99. over -- a boolean that indicates whether the turn is over
  100. who -- the name of the current player
  101. """
  102. print(draw_number(outcome))
  103. print(who, describe_action(action))
  104. if over:
  105. print(who, 'scored', score_for_turn, 'point(s) on this turn.')
  106. else:
  107. print(who, 'now has a turn total of', turn_total, 'point(s).')
  108.  
  109. def describe_action(action):
  110. """Generate a string that describes an action.
  111.  
  112. action -- a function, which should be either hold or roll
  113.  
  114. If action is neither the hold nor roll function, the description should
  115. announce that cheating has occurred.
  116.  
  117. >>> describe_action(roll)
  118. 'chose to roll.'
  119. >>> describe_action(hold)
  120. 'decided to hold.'
  121. >>> describe_action(commentate)
  122. 'took an illegal action!'
  123. """
  124. "*** YOUR CODE HERE ***"
  125. return 'did something...'
  126.  
  127. def draw_number(n, dot='*'):
  128. """Return an ascii art representation of rolling the number n.
  129.  
  130. >>> print(draw_number(5))
  131. -------
  132. | * * |
  133. | * |
  134. | * * |
  135. -------
  136. """
  137.  
  138.  
  139. '''doesn't work'''
  140. c = n/6==1 or n/3 == 1 or n/1 == 1 or n/5==1
  141. f = n/6 == 1 or n/5 ==1 or n/4 == 1
  142. b = n/6 == 1 or n/5 == 1 or n/2 == 1 or n/4 == 1
  143. s = n/6 == 1 or n/3 == 1
  144. #print(c,f,b,s)
  145. return draw_die(c,f,b,s,dot)
  146.  
  147. def draw_die(c, f, b, s, dot):
  148. """Return an ascii art representation of a die.
  149.  
  150. c, f, b, & s are boolean arguments. This function returns a multi-line
  151. string of the following form, where the letters in the diagram are either
  152. filled if the corresponding argument is true, or empty if it is false.
  153.  
  154. -------
  155. | b f |
  156. | s c s |
  157. | f b |
  158. -------
  159.  
  160. Note: The sides with 2 and 3 dots have 2 possible depictions due to
  161. rotation. Either representation is acceptable.
  162.  
  163. Note: This function uses Python syntax not yet covered in the course.
  164.  
  165. c, f, b, s -- booleans; whether to place dots in corresponding positions
  166. dot -- A length-one string to use for a dot
  167. """
  168. border = ' -------'
  169. def draw(b):
  170. return dot if b else ' '
  171. c, f, b, s = map(draw, [c, f, b, s])
  172. top = ' '.join(['|', b, ' ', f, '|'])
  173. middle = ' '.join(['|', s, c, s, '|'])
  174. bottom = ' '.join(['|', f, ' ', b, '|'])
  175. return '\n'.join([border, top, middle, bottom, border])
  176.  
  177.  
  178. # Game simulator
  179.  
  180. def play(strategy, opponent_strategy):
  181. """Simulate a game and return 0 if the first player wins and 1 otherwise.
  182.  
  183. strategy -- The strategy function for the first player (who plays first)
  184. opponent_strategy -- The strategy function for the second player
  185. """
  186. who = 0 # Which player is about to take a turn, 0 (first) or 1 (second)
  187.  
  188. player_total = 0
  189. opponent_total = 0
  190.  
  191. player_strat = strategy
  192. opponent_strat = opponent_strategy
  193. sides = 6
  194.  
  195. while player_total < 100 and opponent_total < 100:
  196.  
  197. '''decides whose move it is '''
  198. if who == 0:
  199. print("Player1:")
  200. d = take_turn(player_strat(player_total, opponent_total), make_fair_die(sides), "Player 1")
  201. player_total += d
  202. print(player_total)
  203. else:
  204. print("Player2:")
  205. d = take_turn(opponent_strat(player_total, opponent_total), make_fair_die(sides), "Player 2")
  206. opponent_total += d
  207. print(opponent_total)
  208. ''' alternate player'''
  209. who = (who + 1) % 2
  210.  
  211. '''check if total score is a multiple of 7'''
  212.  
  213. '''what does: This sum of scores does not include the turn total. mean???'''
  214. if ( player_total + opponent_total ) % 7 == 0:
  215. sides = 4
  216. else:
  217. sides = 6
  218.  
  219. return who
  220.  
  221.  
  222.  
  223.  
  224. def other(who):
  225. """Return the other player, for players numbered 0 and 1.
  226.  
  227. >>> other(0)
  228. 1
  229. >>> other(1)
  230. 0
  231. """
  232. return (who + 1) % 2
  233.  
  234.  
  235. # Basic Strategies
  236.  
  237. def make_roll_until_plan(turn_goal=20):
  238. """Return a plan to roll until turn total is at least turn_goal."""
  239. def plan(turn):
  240. ''' turn = points in that turn round'''
  241. if turn >= turn_goal:
  242. return hold
  243. else:
  244. return roll
  245. return plan
  246.  
  247. def make_roll_until_strategy(turn_goal):
  248. """Return a strategy to always adopt a plan to roll until turn_goal.
  249.  
  250. A strategy is a function that takes two game scores as arguments and
  251. returns a plan (which is a function from turn totals to actions).
  252. """
  253. def simple_strategy(p_score, o_score):
  254. return make_roll_until_plan(turn_goal)
  255.  
  256. return simple_strategy
  257.  
  258.  
  259.  
  260.  
  261.  
  262. def make_roll_until_strategy_test():
  263. """Test that make_roll_until_strategy gives a strategy that returns correct
  264. roll-until plans."""
  265. strategy = make_roll_until_strategy(15)
  266. plan = strategy(0, 0)
  267. assert plan(14) == roll, 'Should have returned roll'
  268. assert plan(15) == hold, 'Should have returned hold'
  269. assert plan(16) == hold, 'Should have returned hold'
  270.  
  271.  
  272. # Experiments (Phase 2)
  273.  
  274. def average_value(fn, num_samples):
  275. """Compute the average value returned by fn over num_samples trials.
  276.  
  277. >>> d = make_test_die(1, 3, 5, 7)
  278. >>> average_value(d, 100)
  279. 4.0
  280. """
  281. "*** YOUR CODE HERE ***"
  282.  
  283. def averaged(fn, num_samples=100):
  284. """Return a function that returns the average_value of fn when called.
  285.  
  286. Note: To implement this function, you will have to use *args syntax, a new
  287. Python feature introduced in this project. See the project
  288. description for details.
  289.  
  290. >>> die = make_test_die(3, 1, 5, 7)
  291. >>> avg_die = averaged(die)
  292. >>> avg_die()
  293. 4.0
  294. >>> avg_turn = averaged(take_turn)
  295. >>> avg_turn(make_roll_until_plan(4), die, 'The player', False)
  296. 3.0
  297.  
  298. In this last example, two different turn scenarios are averaged.
  299. - In the first, the player rolls a 3 then a 1, receiving a score of 1.
  300. - In the other, the player rolls a 5 (then holds on the 7), scoring 5.
  301. Thus, the average value is 3.0
  302.  
  303. Note: If this last test is called with comments=True in take_turn, the
  304. doctests will fail because of the extra output.
  305. """
  306. "*** YOUR CODE HERE ***"
  307.  
  308. def compare_strategies(strategy, baseline=make_roll_until_strategy(20)):
  309. """Return the average win rate (out of 1) of strategy against baseline."""
  310. as_first = 1 - averaged(play)(strategy, baseline)
  311. as_second = averaged(play)(baseline, strategy)
  312. return (as_first + as_second) / 2 # Average the two results
  313.  
  314. def eval_strategy_range(make_strategy, lower_bound, upper_bound):
  315. """Return the best integer argument value for make_strategy to use against
  316. the roll-until-20 baseline, between lower_bound and upper_bound (inclusive).
  317.  
  318. make_strategy -- A one-argument function that returns a strategy.
  319. lower_bound -- lower bound of the evaluation range
  320. upper_bound -- upper bound of the evaluation range
  321. """
  322. best_value, best_win_rate = 0, 0
  323. value = lower_bound
  324. while value <= upper_bound:
  325. strategy = make_strategy(value)
  326. win_rate = compare_strategies(strategy)
  327. print(value, 'win rate against the baseline:', win_rate)
  328. if win_rate > best_win_rate:
  329. best_win_rate, best_value = win_rate, value
  330. value += 1
  331. return best_value
  332.  
  333. def run_strategy_experiments():
  334. """Run a series of strategy experiments and report results."""
  335. "*** YOUR CODE HERE ***"
  336.  
  337. def make_die_specific_strategy(four_side_goal, six_side_goal=20):
  338. """Return a strategy that returns a die-specific roll-until plan.
  339.  
  340. four_side_goal -- the roll-until goal whenever the turn uses a 4-sided die
  341. six_side_goal -- the roll-until goal whenever the turn uses a 6-sided die
  342.  
  343. """
  344. "*** YOUR CODE HERE ***"
  345.  
  346. def make_pride_strategy(margin, turn_goal=20):
  347. """Return a strategy that wants to finish a turn winning by at least margin.
  348.  
  349. margin -- the size of the lead that the player requires
  350. turn_goal -- the minimum roll-until turn goal, even when winning
  351. """
  352. "*** YOUR CODE HERE ***"
  353.  
  354. def final_strategy(score, opponent_score):
  355. """Write a brief description of your final strategy.
  356.  
  357. *** YOUR DESCRIPTION HERE ***
  358. """
  359. "*** YOUR CODE HERE ***"
  360.  
  361. def interactive_strategy(score, opponent_score):
  362. """Prints total game scores and returns an interactive plan.
  363.  
  364. Note: this function uses Python syntax not yet covered in the course.
  365. """
  366. print('You have', score, 'and they have', opponent_score, 'total score')
  367. def plan(turn):
  368. if turn > 0:
  369. print('You now have a turn total of', turn, 'points')
  370. while True:
  371. response = input('(R)oll or (H)old?')
  372. if response.lower()[0] == 'r':
  373. return roll
  374. elif response.lower()[0] == 'h':
  375. return hold
  376. print('Huh?')
  377. return plan
  378.  
  379. @main
  380. def run():
  381. take_turn_test()
  382.  
  383. # Uncomment the next line to play an interactive game
  384. # play(interactive_strategy, make_roll_until_strategy(20))
  385.  
  386. # Uncomment the next line to test make_roll_until_strategy
  387. # make_roll_until_strategy_test()
  388.  
  389. run_strategy_experiments()
Add Comment
Please, Sign In to add comment