sp
2 years ago
1 changed files with 123 additions and 0 deletions
@ -0,0 +1,123 @@ |
|||
# coding: utf-8 |
|||
import os, sys, subprocess |
|||
import time |
|||
from z3 import * |
|||
|
|||
CHOICES = ["Rock", "Paper", "Scissors", "Spock", "Lizard"] |
|||
|
|||
def next_random_number(s_i): |
|||
return ((11 * s_i) + 12345) & 0x7fff |
|||
|
|||
class RPSSLComputer: |
|||
def __init__(self, s0): |
|||
self.previous_random_number = s0 |
|||
|
|||
def compute_choice(self): |
|||
random_number = next_random_number(self.previous_random_number) |
|||
self.previous_random_number = random_number |
|||
return random_number % 5, CHOICES[random_number % 5] |
|||
|
|||
|
|||
# cf. https://bigbangtheory.fandom.com/wiki/Rock,_Paper,_Scissors,_Lizard,_Spock |
|||
def winning_mapping(i): |
|||
if i == 0: return 1#"Paper" |
|||
if i == 1: return 2#"Scissors" |
|||
if i == 2: return 0#"Rock" |
|||
if i == 3: return 4#"Lizard" |
|||
if i == 4: return 0#"Rock" |
|||
return "Did you forget to compute the remainder modulo 5?" |
|||
|
|||
def compute_winner(computer, player): |
|||
if computer == player: |
|||
return "\tTie.", False |
|||
is_player_bigger = True if player > computer else False |
|||
absolute_difference = abs(computer - player) |
|||
if absolute_difference % 2 == 1: |
|||
if is_player_bigger: |
|||
return "\tPlayer wins.", True |
|||
else: |
|||
return "\tComputer wins.", False |
|||
else: |
|||
if is_player_bigger: |
|||
return "\tComputer wins.", False |
|||
else: |
|||
return "\tPlayer wins.", True |
|||
|
|||
solver = Solver() |
|||
states = list() |
|||
|
|||
# We are adding the first state s_0 to the list of states |
|||
states.append(BitVec("state0", 16)) |
|||
|
|||
s0 = int(sys.argv[1]) |
|||
computer = RPSSLComputer(s0) |
|||
|
|||
preprocess_count = 5 |
|||
|
|||
def add_constraint(solver, index, computers_choice): |
|||
# TODO create a BitVec and append it to the list of states |
|||
# You might want to call it state{index} |
|||
|
|||
# TODO Enforce that the newly added BitVec-variable must evaluate to the result of the LCG computation using the previous result |
|||
|
|||
# TODO Enforce that the unsigned remainder of the newly added BitVec-varialbe and 5 evaluates to the choice of the computer |
|||
|
|||
pass |
|||
|
|||
def store_backtracking_point(solver): |
|||
solver.push() |
|||
|
|||
def restore_backtracking_point(solver): |
|||
solver.pop() |
|||
|
|||
def add_next_state_constraint(solver): |
|||
s_i_plus_1 = BitVec("s_i_plus_1", 16) |
|||
# TODO Enforce that the next state value is computed via the same computation as above |
|||
|
|||
return s_i_plus_1 |
|||
|
|||
def get_players_choice(solver, s_i_plus_1): |
|||
# TODO Get the value of next_state from the model and return it modulo 5 |
|||
# Hint: winning_mapping(...) returns a good answer for the computer's choice |
|||
# Hint: use solver.model() like a python dict. |
|||
# Hint: use `.as_long()` to convert a z3 variable to a python integer value |
|||
return 0 |
|||
|
|||
|
|||
# Main loop: |
|||
|
|||
# We read preprocess_count many choices from the computer before we start to ask z3 for a solution |
|||
# Note that for these preprocessing rounds we do not need to make a good guess and compute the winner |
|||
# We are only interested in what the computer picks for the first few rounds |
|||
for index in range(1,preprocess_count): |
|||
computer_choice, _ = computer.compute_choice() |
|||
player_choice = 0 # We always choose Rock since we cannot make good guesses in the beginning |
|||
|
|||
add_constraint(solver,index,computer_choice) |
|||
output, won = compute_winner(computer_choice, player_choice) |
|||
print(output) |
|||
if won: print("Congratulations!") |
|||
else: print("Try again.") |
|||
|
|||
|
|||
# Now we start by adding a 'special' variable s_i_plus_1 and try to win |
|||
index = preprocess_count |
|||
while True: |
|||
store_backtracking_point(solver) |
|||
s_i_plus_1 = add_next_state_constraint(solver) |
|||
solver.check() |
|||
|
|||
player_choice = get_players_choice(solver, s_i_plus_1) |
|||
computer_choice, _ = computer.compute_choice() |
|||
output, won = compute_winner(computer_choice, player_choice) |
|||
|
|||
print(output) |
|||
if won: print("Congratulations!") |
|||
else: print("Try again.") |
|||
|
|||
restore_backtracking_point(solver) |
|||
add_constraint(solver, index, computer_choice) |
|||
# input("") |
|||
index += 1 |
|||
if index >= 100: |
|||
break |
Write
Preview
Loading…
Cancel
Save
Reference in new issue