Last active
May 29, 2019 18:14
-
-
Save 20esaua/49198915c77cf3cf1386b81da637614c to your computer and use it in GitHub Desktop.
markov chain based rock paper scissors game (in progress)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import choice as random | |
ROCK = 1 | |
PAPER = 2 | |
SCISSORS = 3 | |
out_of = 3 | |
best = out_of -1 | |
MOVES = { | |
'r' : ROCK, | |
'p' : PAPER, | |
's' : SCISSORS | |
} | |
BEAT = { | |
ROCK : PAPER, | |
PAPER : SCISSORS, | |
SCISSORS : ROCK | |
} | |
NAMES = { | |
ROCK : 'rock', | |
PAPER : 'paper', | |
SCISSORS : 'scissors' | |
} | |
class Node: | |
def __init__(self, parent, type): | |
self.children = [] | |
self.count = 0 | |
self.parent = parent | |
self.type = type | |
if not self.get_parent() is None: | |
self.get_parent().add_child(self) | |
def get_weight(self): | |
sum = 0 | |
for child in self.get_parent().get_children(): | |
sum += child.count | |
return self.count / sum | |
def get_children(self): | |
return self.children | |
def add_child(self, child): | |
self.children.append(child) | |
return self | |
def get_type(self): | |
return self.type | |
def get_parent(self): | |
return self.parent | |
root = Node(None, None) | |
current_node = root | |
default_scores = { | |
'you' : 0, | |
'me' : 0 | |
} | |
global_weights = { | |
ROCK : 0, | |
PAPER : 0, | |
SCISSORS : 0 | |
} | |
header = '\n\nYou v.s. me. Best %s out of %s.\n\n' % (best, out_of) | |
scores = default_scores | |
print(header) | |
while True: | |
# predict the player's move | |
predicted_move = ROCK | |
greatest_child = None | |
for child in current_node.get_children(): | |
if greatest_child is None: | |
greatest_child = child | |
elif child.get_weight() > greatest_child.get_weight: | |
greatest_child = child | |
# no data, so just pick a random one and yolo it | |
if greatest_child is None: | |
greatest_child = {'key' : ROCK, ROCK : 0} | |
for child in global_weights: | |
if greatest_child[greatest_child['key']] < global_weights[child]: | |
greatest_child['key'] = child | |
greatest_child[child] = global_weights[child] | |
if greatest_child is None: | |
greatest_child = random([ROCK, PAPER, SCISSORS]) | |
if not type(greatest_child) is int: | |
greatest_child = greatest_child.get_type() | |
predicted_move = greatest_child | |
use_move = BEAT[predicted_move] | |
# get player's actual move | |
move = 0 | |
while True: | |
move = input('Your move: ').lower().strip() | |
for possible_move in MOVES: | |
if move.startswith(possible_move): | |
move = MOVES[possible_move] | |
break | |
if type(move) is int: | |
break | |
# check who wins | |
message = 'I went with %s. ' % NAMES[use_move] | |
if move == use_move: | |
message += 'Tie!' | |
elif BEAT[move] == use_move: | |
message += 'I won that round!' | |
scores['me'] += 1 | |
elif move == BEAT[use_move]: | |
message += 'You won that round!' | |
scores['you'] += 1 | |
print(message + '\n') | |
winner = None | |
for player in scores: | |
if scores[player] >= best: | |
scores = default_scores | |
winner = player | |
if not winner is None: | |
print('\n%s wins!' % winner) | |
scores = default_scores | |
print(header) | |
# update markov chain | |
found = False | |
for node in current_node.get_children(): | |
if node.get_type() == move: | |
found = node | |
break | |
if not found: | |
current_node = Node(current_node, move) | |
current_node.count += 1 | |
else: | |
found.count += 1 | |
current_node = found |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment