You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.9 KiB

  1. # coding: utf-8
  2. import os, sys, subprocess
  3. import time
  4. from z3 import *
  5. CHOICES = ["Rock", "Paper", "Scissors", "Spock", "Lizard"]
  6. def next_random_number(s_i):
  7. return ((11 * s_i) + 12345) & 0x7fff
  8. class RPSSLComputer:
  9. def __init__(self, s0):
  10. self.previous_random_number = s0
  11. def compute_choice(self):
  12. random_number = next_random_number(self.previous_random_number)
  13. self.previous_random_number = random_number
  14. return random_number % 5, CHOICES[random_number % 5]
  15. # cf. https://bigbangtheory.fandom.com/wiki/Rock,_Paper,_Scissors,_Lizard,_Spock
  16. def winning_mapping(i):
  17. if i == 0: return 1#"Paper"
  18. if i == 1: return 2#"Scissors"
  19. if i == 2: return 0#"Rock"
  20. if i == 3: return 4#"Lizard"
  21. if i == 4: return 0#"Rock"
  22. return "Did you forget to compute the remainder modulo 5?"
  23. def compute_winner(computer, player):
  24. if computer == player:
  25. return "\tTie.", False
  26. is_player_bigger = True if player > computer else False
  27. absolute_difference = abs(computer - player)
  28. if absolute_difference % 2 == 1:
  29. if is_player_bigger:
  30. return "\tPlayer wins.", True
  31. else:
  32. return "\tComputer wins.", False
  33. else:
  34. if is_player_bigger:
  35. return "\tComputer wins.", False
  36. else:
  37. return "\tPlayer wins.", True
  38. solver = Solver()
  39. states = list()
  40. # We are adding the first state s_0 to the list of states
  41. states.append(BitVec("state0", 16))
  42. s0 = int(sys.argv[1])
  43. computer = RPSSLComputer(s0)
  44. preprocess_count = 5
  45. def add_constraint(solver, index, computers_choice):
  46. # TODO create a BitVec and append it to the list of states
  47. # You might want to call it state{index}
  48. # TODO Enforce that the newly added BitVec-variable must evaluate to the result of the LCG computation using the previous result
  49. # TODO Enforce that the unsigned remainder of the newly added BitVec-varialbe and 5 evaluates to the choice of the computer
  50. pass
  51. def store_backtracking_point(solver):
  52. solver.push()
  53. def restore_backtracking_point(solver):
  54. solver.pop()
  55. def add_next_state_constraint(solver):
  56. s_i_plus_1 = BitVec("s_i_plus_1", 16)
  57. # TODO Enforce that the next state value is computed via the same computation as above
  58. return s_i_plus_1
  59. def get_players_choice(solver, s_i_plus_1):
  60. # TODO Get the value of next_state from the model and return it modulo 5
  61. # Hint: winning_mapping(...) returns a good answer for the computer's choice
  62. # Hint: use solver.model() like a python dict.
  63. # Hint: use `.as_long()` to convert a z3 variable to a python integer value
  64. return 0
  65. # Main loop:
  66. # We read preprocess_count many choices from the computer before we start to ask z3 for a solution
  67. # Note that for these preprocessing rounds we do not need to make a good guess and compute the winner
  68. # We are only interested in what the computer picks for the first few rounds
  69. for index in range(1,preprocess_count):
  70. computer_choice, _ = computer.compute_choice()
  71. player_choice = 0 # We always choose Rock since we cannot make good guesses in the beginning
  72. add_constraint(solver,index,computer_choice)
  73. output, won = compute_winner(computer_choice, player_choice)
  74. print(output)
  75. if won: print("Congratulations!")
  76. else: print("Try again.")
  77. # Now we start by adding a 'special' variable s_i_plus_1 and try to win
  78. index = preprocess_count
  79. while True:
  80. store_backtracking_point(solver)
  81. s_i_plus_1 = add_next_state_constraint(solver)
  82. solver.check()
  83. player_choice = get_players_choice(solver, s_i_plus_1)
  84. computer_choice, _ = computer.compute_choice()
  85. output, won = compute_winner(computer_choice, player_choice)
  86. print(output)
  87. if won: print("Congratulations!")
  88. else: print("Try again.")
  89. restore_backtracking_point(solver)
  90. add_constraint(solver, index, computer_choice)
  91. # input("")
  92. index += 1
  93. if index >= 100:
  94. break