This program has been disqualified.
Author | ElectraMiner |
Submission date | 2017-01-13 04:53:11.273489 |
Rating | 5201 |
Matches played | 50 |
Win rate | 50.0 |
import random
import math
layerSize = 3
layerCount = 2
histLength = 10
def high(count):
if count[0] > count[1] and count[0] > count[2]:
return RPS(0)
if count[1] > count[2]:
return RPS(1.0/3)
return RPS(2.0/3)
def toRPS(s):
if s == "R":
return RPS(0)
if s == "P":
return RPS(1.0/3)
return RPS(2.0/3)
class RPS():
coord = [0.0,0.0]
def __init__(self, num):
self.coord = [math.sin(num*math.pi*2),math.cos(num*math.pi*2)]
if num == -1:
self.coord = [0,0]
def multiply(self, num):
self.coord[0] *= num
self.coord[1] *= num
def average(self, coords):
self.coord = [0,0]
for c in coords:
self.coord[0] += c.coord[0]
self.coord[1] += c.coord[1]
distance = math.sqrt(self.coord[0]**2+self.coord[1]**2)
if distance == 0:
self.coord = [0,0]
else:
self.coord[0] /= distance
self.coord[1] /= distance
return self
def rotate(self, rotate):
angle = math.asin(self.coord[0])
if self.coord[1]<0:
angle = 3.14 - angle
angle /= 6.28
return RPS((angle + rotate) % 1)
def accuracy(self, target):
if self.coord == [0,0]:
return 1/3
angle = math.asin(self.coord[0])
if self.coord[1]<0:
angle = 3.14 - angle
angle /= 6.28
if target == "P":
angle -= 1.0/3
if target == "S":
angle += 1.0/3
angle %= 1
if angle < 0.5:
return angle
return 1 - angle
def toString(self):
if self.coord == [0,0]:
output = random.choice(["R","P","S"])
if self.accuracy("R") < 1.0/6:
return "R"
if self.accuracy("P") < 1.0/6:
return "P"
return "S"
def clone(self):
rps = RPS(-1)
rps.coord[0] = self.coord[0]
rps.coord[1] = self.coord[1]
return rps
class Neuron():
weights = []
rotate = 0
def __init__(self, weights, rotate):
self.weights = weights
self.rotate = rotate
def calculate(self, numbers):
sum = RPS(0)
for i in range(len(numbers)):
numbers[i].multiply(self.weights[i])
return sum.average(numbers).rotate(self.rotate)
def improve(self, seed):
if seed == 0:
return
random.seed(seed)
for w in range(len(self.weights)):
r = random.random()-0.5
r /= 5
self.weights[w] += r
r = random.random()-0.5
r /= 5
self.rotate += r
def undo(self, seed):
if seed == 0:
return
random.seed(seed)
for w in range(len(self.weights)):
r = random.random()-0.5
r /= 5
self.weights[w] -= r
r = random.random()-0.5
r /= 5
self.rotate -= r
class Network():
history = []
oppHist = []
most = [0, 0, 0]
oppMost = [0, 0, 0]
network = []
answer = None
def __init__(self):
self.network.append([])
for n in range(layerSize):
weights = []
for w in range(histLength*2+2):
weights.append((random.random()-0.5)*2)
self.network[0].append(Neuron(weights,(random.random()-0.5)*2))
for l in range(layerCount-1):
self.network.append([])
for n in range(layerSize):
weights = []
for w in range(layerSize):
weights.append((random.random()-0.5)*2)
self.network[l+1].append(Neuron(weights,(random.random()-0.5)*2))
weights = []
for w in range(layerSize):
weights.append((random.random()-0.5)*2)
self.network.append(Neuron(weights,(random.random()-0.5)*2))
def calculate(self):
inputs = []
for i in range(histLength):
h = len(self.history)-i-1
if h<0:
inputs.append(RPS(-1))
inputs.append(RPS(-1))
else:
inputs.append(self.history[h].clone())
inputs.append(self.oppHist[h].clone())
inputs.append(high(self.most))
inputs.append(high(self.oppMost))
for l in range(layerCount):
inp = []
for n in range(layerSize):
inp.append(self.network[l][n].calculate(inputs))
inputs = inp
return self.network[layerCount].calculate(inputs)
def run(self, ourMove, oppMove):
if ourMove != "":
self.history.append(toRPS(ourMove))
self.oppHist.append(toRPS(oppMove))
self.answer = self.calculate()
return self.answer.toString()
def improve(self, actual):
if actual != "":
if actual == "R":
self.oppMost[0] += 1
actual = "P"
elif actual == "P":
actual = "S"
self.oppMost[1] += 1
else:
actual = "R"
self.oppMost[2] += 1
accuracy = self.answer.accuracy(actual)
if self.answer.toString()!=actual:
seed = []
for n in range(layerCount*layerSize+1):
seed.append(random.choice([random.random(),0]))
for l in range(layerCount):
for n in range(layerSize):
self.network[l][n].improve(seed[l*layerSize+n])
self.network[layerCount].improve(seed[layerCount*layerSize])
guess = self.calculate()
if (guess.accuracy(actual) >= accuracy):
for n in range(layerCount*layerSize+1):
seed.append(random.random())
for l in range(layerCount):
for n in range(layerSize):
self.network[l][n].undo(seed[l*layerSize+n])
self.network[layerCount].undo(seed[layerCount*layerSize])
else:
accuracy = guess
if input == "":
network = Network()
output = ""
network.improve(input)
output = network.run(output, input)
if output == "R":
network.most[0] += 1
elif output == "P":
network.most[1] += 1
else:
network.most[2] += 1