Skip to content

Instantly share code, notes, and snippets.

@countofkrakow
Last active August 26, 2021 08:09
Show Gist options
  • Save countofkrakow/5b4bdbaf08c21cdeec74b757e4d6e2be to your computer and use it in GitHub Desktop.
Save countofkrakow/5b4bdbaf08c21cdeec74b757e4d6e2be to your computer and use it in GitHub Desktop.
Rock Paper Scissors command line
# inspiration for this code came from here https://daniel.lawrence.lu/programming/rps/
import random
def selectBest(s):
return [i for i in range(len(s)) if max(s) == s[i]][0]
def selectBestDict(s):
ew = {i:s[beatedBy[beatedBy[i]]] - s[beatedBy[i]] for i in s.keys()};
return [i for i in ew.keys() if max(ew.values()) == ew[i]][0]
vals = 'R P S'.split(' ')
msg_win = "You win this round."
msg_lose = "You lose this round."
msg_tie = "Tie! You both picked "
help = "Enter R for rock, P for paper, S for scissors, H for help, or Q to quit."
history = []
moves = ["R","P","S"]
beatedBy = {"R":"P", "P":"S", "S":"R"}
result = {"R":{"R":0, "P":-1, "S":1}, "P":{"R":1, "P":0, "S":-1}, "S":{"R":-1, "P":1, "S":0}}
alpha = 0.01
# setup
markov_orders = [0,1,2,3,4,5,6]
historyCount = {}
M = 1 + 6 * len(markov_orders)
weight = [1] * M
decay = [0.85] * M
score = [0] * M
scoreboard = {"player": 0, "ai": 0}
selected = [0] * M
move = [random.choice(moves) for i in range(M)]
last = None
def loop():
global weight
global last
print("Rock Paper Scissors")
print("-------------------")
while 1:
# get input
userval = input("Enter Your Move: ")
userval = userval.upper()
if userval == 'Q':
print("Final Score: player %s to ai %s" % (scoreboard["player"], scoreboard["ai"]))
if scoreboard["player"] > scoreboard["ai"]:
print("You win!")
elif scoreboard["player"] < scoreboard["ai"]:
print("You Lose!")
else:
print("You tied.")
break
elif userval == 'H':
print(help)
elif userval in vals:
output, weight = compute_move(userval, history, score, weight)
print(f"AI guessed......{output}")
scoreboard["ai"] += result[output][userval]
scoreboard["player"] += result[userval][output]
print(scoreboard)
else:
print("%s is not a valid command." % userval)
def compute_move(user_input, history, score, weight):
global last
score = [decay[i] * score[i] + weight[i] * result[move[i]][user_input] for i in range(M)]
weight = [weight[i] + alpha * result[move[i]][user_input] for i in range(M)]
index = 0
# random optimal
move[index] = random.choice(moves)
# adjust random optimal score to zero
score[index] = 0
index += 1
first_meta_index = index
# markov with meta strategies
for m in markov_orders:
if len(history) > m:
key = tuple(history[-m - 1:-1])
if not (key in historyCount):
historyCount[key] = [{"R": 0, "P": 0, "S": 0}, {"R": 0, "P": 0, "S": 0}]
historyCount[key][0][history[-1][0]] += 1
historyCount[key][1][history[-1][1]] += 1
for m in markov_orders:
if len(history) >= m:
key = tuple(history[-m:])
if key in historyCount:
move[index] = selectBestDict(historyCount[key][0])
move[index + 3] = selectBestDict(historyCount[key][1])
else:
move[index] = random.choice(moves)
move[index + 3] = random.choice(moves)
else:
move[index] = random.choice(moves)
move[index + 3] = random.choice(moves)
index += 6
# set other meta strategies
for i in range(first_meta_index, M, 3):
move[i + 1] = beatedBy[move[i]]
move[i + 2] = beatedBy[move[i + 1]]
best = selectBest(score)
selected[best] += 1
output = move[best]
last = output
history += [(last, user_input)]
return output, weight
if __name__ == '__main__':
loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment