markov_v10

AuthorPiotrekG
Submission date2018-09-05 19:31:46.464273
Rating7343
Matches played281
Win rate71.89

Use rpsrunner.py to play unranked matches on your computer.

Source code:

from __future__ import division
import random
import itertools

beat = {'R': 'P', 'P': 'S', 'S': 'R'}


class MarkovChain():

    def __init__(self, beat, level, memory, score=0):
        self.matrix = self.create_matrix(beat, level, memory)
        self.memory = memory
        self.level = level
        self.beat = beat
        self.score = score
        self.prediction = ''
        self.name = 'level: {}, memory: {}'.format(self.level, self.memory)

    @staticmethod
    def create_matrix(beat, level, memory):

        def create_keys(beat, level):
            keys = list(beat)

            if level > 1:

                for i in range(level - 1):
                    key_len = len(keys)
                    for i in itertools.product(keys, ''.join(beat)):
                        keys.append(''.join(i))
                    keys = keys[key_len:]

            return keys

        keys = create_keys(beat, level)

        matrix = {}
        for key in keys:
            matrix[key] = {'R': 1 / (1 - memory) / 3,
                           'P': 1 / (1 - memory) / 3,
                           'S': 1 / (1 - memory) / 3}

        return matrix

    def update_matrix(self, key_lagged, response):

        for key in self.matrix[key_lagged]:
            self.matrix[key_lagged][key] = self.memory * self.matrix[key_lagged][key]

        self.matrix[key_lagged][response] += 1

    def update_score(self, inp, out):

        if self.beat[out] == inp:
            self.score = self.score * 0.9 - 1
        elif out == inp:
            self.score = self.score * 0.9
        else:
            self.score = self.score * 0.9 + 1

    def predict(self, key_current):

        probs = self.matrix[key_current]

        if max(probs.values()) == min(probs.values()):
            self.prediction = random.choice(list(beat.keys()))
        else:
            self.prediction = max([(i[1], i[0]) for i in probs.items()])[1]

        return self.prediction


class HistoryColl():
    def __init__(self):
        self.history = ''

    def hist_collector(self, inp, out):
        self.history = self.history + inp
        self.history = self.history + out
        if len(self.history) > 10:
            self.history = self.history[-10:]

    def create_keys(self, level):
        return self.history[-level:]

    def create_keys_hist(self, level):
        key_hist = self.history[-level - 2:-2]
        inp_latest = self.history[-2]
        return key_hist, inp_latest


if input == '':

    output = random.choice(list(beat.keys()))

    history = HistoryColl()

    models = [MarkovChain(beat, 1, 0.99),
              MarkovChain(beat, 2, 0.99),
              MarkovChain(beat, 3, 0.99),
              MarkovChain(beat, 4, 0.99),
              MarkovChain(beat, 1, 0.97),
              MarkovChain(beat, 2, 0.97),
              MarkovChain(beat, 3, 0.97),
              MarkovChain(beat, 4, 0.97),
              MarkovChain(beat, 1, 0.95),
              MarkovChain(beat, 2, 0.95),
              MarkovChain(beat, 3, 0.95),
              MarkovChain(beat, 4, 0.95),
              MarkovChain(beat, 1, 0.93),
              MarkovChain(beat, 2, 0.93),
              MarkovChain(beat, 3, 0.93),
              MarkovChain(beat, 4, 0.93),
              MarkovChain(beat, 1, 0.9),
              MarkovChain(beat, 2, 0.9),
              MarkovChain(beat, 3, 0.9),
              MarkovChain(beat, 4, 0.9),
              MarkovChain(beat, 1, 0.8),
              MarkovChain(beat, 2, 0.8),
              MarkovChain(beat, 3, 0.8),
              MarkovChain(beat, 4, 0.8),
              MarkovChain(beat, 1, 0.7),
              MarkovChain(beat, 2, 0.7),
              MarkovChain(beat, 3, 0.7),
              MarkovChain(beat, 4, 0.7),
              MarkovChain(beat, 1, 0.6),
              MarkovChain(beat, 2, 0.6),
              MarkovChain(beat, 3, 0.6),
              MarkovChain(beat, 4, 0.6),
              MarkovChain(beat, 1, 0.5),
              MarkovChain(beat, 2, 0.5),
              MarkovChain(beat, 3, 0.5),
              MarkovChain(beat, 4, 0.5)]


elif len(history.history) == 10:

    history.hist_collector(input, output)

    max_score = 0

    for model in models:

        key_hist, inp_latest = history.create_keys_hist(model.level)
        key_curr = history.create_keys(model.level)

        if model.prediction != '':
            model.update_score(input, beat[model.prediction])

        model.update_matrix(key_hist, inp_latest)
        predicted_input = model.predict(key_curr)

        if model.score > max_score:
            best_model = model
            max_score = model.score
            output = beat[predicted_input]

    if max_score < 1:
        output = random.choice(list(beat.keys()))
        print('los')
    else:
        print(best_model.name, best_model.score)

else:
    history.hist_collector(input, output)
    output = random.choice(list(beat.keys()))