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