RPSBrain v2

This program has been disqualified.


AuthorElectraMiner
Submission date2017-01-13 05:25:56.619702
Rating4694
Matches played20
Win rate45.0

Source code:

import random
import math
layerSize = 4
layerCount = 2
histLength = 8
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.random())
                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