# BUTT DESTROYER V1.21

This program has been disqualified.

 Author JFreegman Submission date 2012-07-27 09:39:34.309950 Rating 6094 Matches played 87 Win rate 63.22

## Source code:

``````# Author: JFreegman
# Contact: JFreegman@gmail.com
# Date: July 27, 2012
# v1.21

# All code is written from scratch. The general idea is based off Iocaine Powder
# by Dan Egnor (http://ofb.net/~egnor/iocaine.html).

import random

def get_history_match(n=200):
start = len(opp_moves) - min(len(opp_moves) / 2, n)
end = len(opp_moves)
for i in xrange(start, end):
partition = opp_moves[i:end]
match = opp_moves[:-1].find(partition)
if match != -1:
return opp_moves[match+len(partition)]
return random_weapon()

def get_probs(total_moves, n):
last = get_move_freq(total_moves[-n:])
probs = {}
probs['R'] = float(last['R']) / last['total'] * 100
probs['S'] = float(last['S']) / last['total'] * 100
probs['P'] = float(last['P']) / last['total'] * 100
return probs

def get_move_freq(moves):
mov_freq = {'R': 0, 'P': 0, 'S': 0}
count = 0
for move in moves:
if move == 'R':
mov_freq['R'] += 1
elif move == 'P':
mov_freq['P'] += 1
elif move == 'S':
mov_freq['S'] += 1
else:
raise ValueError, 'Invalid move'
count += 1
mov_freq['total'] = count
return mov_freq

def winning_move(m):
d = {'R': 'P', 'P': 'S', 'S': 'R'}
return d[m]

def losing_move(m):
d = {'R': 'S', 'P': 'R', 'S': 'P'}
return d[m]

def random_weapon():
return random.choice(['R', 'P', 'S'])

if not input:
strat_history = [{}]
last_strats = {}
res_history = []
opp_moves = ""
strat_success = {
'freq20': [0,0,False], 'c1_freq20': [0,0,False], 'c2_freq20': [0,0,False],
'hist': [0,0,False], 'random': [0,0,False], 'c1_hist': [0,0,False],
'c2_hist': [0,0,False], 'c1_freq100': [0,0,False], 'c2_freq100': [0,0,False],
'freq100': [0,0,False], 'freqtot': [0,0,False], 'c1_freqtot': [0,0,False],
'c2_freqtot': [0,0,False], 'freq5': [0,0,False], 'c1_freq5': [0,0,False],
'c2_freq5': [0,0,False],'hist5': [0,0,False], 'hist20': [0,0,False],
'c1_hist5': [0,0,False], 'c1_hist20': [0,0,False], 'c2_hist5': [0,0,False],
'c2_hist20': [0,0,False], 'opposite': [0,0,False]
}
output = random_weapon()
else:
last_opp_move = input
opp_moves += input
beat_opp = winning_move(last_opp_move)
lose_opp = losing_move(last_opp_move)
# update strategy success rates based on last round results
for s in last_strats:
if last_strats[s] == beat_opp:
strat_success[s][2] = True
strat_success[s][0] += 1
elif last_strats[s] == lose_opp:
# performance decays with a weight for losing streaks
if not strat_success[s][2]:
strat_success[s][1] += 1
else:
strat_success[s][1] = 0
strat_success[s][2] = False
strat_success[s][0] = strat_success[s][0] - (strat_success[s][1] * .5)

opp_freq5 = get_probs(opp_moves, 5)
opp_prob_f_5 = max(opp_freq5, key=opp_freq5.get)
opp_freq20 = get_probs(opp_moves, 20)
opp_prob_f_20 = max(opp_freq20, key=opp_freq20.get)
opp_freq100 = get_probs(opp_moves, 100)
opp_prob_f_100 = max(opp_freq100, key=opp_freq100.get)
opp_freqtot = get_probs(opp_moves, len(opp_moves))
opp_prob_f_tot = max(opp_freqtot, key=opp_freqtot.get)
opp_prob_h = get_history_match()
opp_prob_h20 = get_history_match(20)
opp_prob_h5 = get_history_match(5)

# naive moves for each strategy
my_move_freq5 = winning_move(opp_prob_f_5)
my_move_freq20 = winning_move(opp_prob_f_20)
my_move_freq100 = winning_move(opp_prob_f_100)
my_move_freqtot = winning_move(opp_prob_f_tot)
my_move_hist = winning_move(opp_prob_h)
my_move_hist20 = winning_move(opp_prob_h20)
my_move_hist5 = winning_move(opp_prob_h5)

# counter-moves in case opp predicts my naive moves
c1_move_freq5 = losing_move(my_move_freq5)
c1_move_freq20 = losing_move(my_move_freq20)
c1_move_freq100 = losing_move(my_move_freq100)
c1_move_freqtot = losing_move(my_move_freqtot)
c1_move_hist = losing_move(my_move_hist)
c1_move_hist20 = losing_move(my_move_hist20)
c1_move_hist5 = losing_move(my_move_hist5)

# counter-counter moves in case opp predicts my first counter
c2_move_freq5 = losing_move(c1_move_freq5)
c2_move_freq20 = losing_move(c1_move_freq20)
c2_move_freq100 = losing_move(c1_move_freq100)
c2_move_freqtot = losing_move(c1_move_freqtot)
c2_move_hist = losing_move(c1_move_hist)
c2_move_hist5 = losing_move(c1_move_hist5)
c2_move_hist20 = losing_move(c1_move_hist20)

random_move = random_weapon()
# dict of all available strategies and their move
strats = {'freq20': my_move_freq20, 'freq100': my_move_freq100,
'hist': my_move_hist, 'random': random_move,
'c1_freq20': c1_move_freq20, 'c2_freq20': c2_move_freq20,
'c1_freq100': c1_move_freq100, 'c2_freq100': c2_move_freq100,
'c1_hist': c1_move_hist, 'c2_hist': c2_move_hist,
'freqtot': my_move_freqtot, 'c1_freqtot': c1_move_freqtot,
'c2_freqtot': c2_move_freqtot, 'c1_freq5': c1_move_freq5,
'c2_freq5': c2_move_freq5, 'freq5': my_move_freq5,
'hist5': my_move_hist5, 'hist20': my_move_hist20,
'c1_hist5': c1_move_hist5, 'c1_hist20': c1_move_hist20,
'c2_hist5': c2_move_hist5, 'c2_hist20': c2_move_hist20,}

# Pick the strategy with the highest current success rate
strat = max(strats, key=lambda x: strat_success[x][0])
opposite = losing_move(strats[strat])
strats['opposite'] = opposite
if strat_success['opposite'] > strat_success[strat]:
output = opposite
else:
output = strats[strat]
last_strats = strats``````