rpsbot7

Authorffenliv
Submission date2019-01-28 15:36:07.535971
Rating2787
Matches played256
Win rate27.34

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

Source code:

import random
from random import randint
import math
import re

MOVES = ["R","P","S"]
BEATS = {"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}}

S_WEIGHT = 20 # options to weight results from each possible history path differently
D_WEIGHT = 40
T_WEIGHT = 30
P_WEIGHT = 20
M_S_WEIGHT = 5
M_D_WEIGHT = 5
M_T_WEIGHT = 3
M_P_WEIGHT = 2


def get_output(s_response, d_response, t_response, p_response, m_s_response, m_d_response, m_t_response, m_p_response):


    choices = [s_response, d_response, t_response, p_response, m_s_response, m_d_response, m_t_response, m_p_response]
    t_s_roll = randint(0, S_WEIGHT)
    t_d_roll = randint(0, D_WEIGHT)
    t_t_roll = randint(0, T_WEIGHT)
    t_p_roll = randint(0, P_WEIGHT)
    m_s_roll = randint(0, M_S_WEIGHT)
    m_d_roll = randint(0, M_D_WEIGHT)
    m_t_roll = randint(0, M_T_WEIGHT)
    m_p_roll = randint(0, M_P_WEIGHT)
    rolls = [t_s_roll, t_d_roll, t_t_roll, t_p_roll, m_s_roll, m_d_roll, m_t_roll, m_p_roll]
    max_roll = max(rolls)
    max_index = rolls.index(max_roll)
    max_rolls = [max_index]
    for count, i in enumerate(rolls):
        if i == max_roll and count != max_index:
            max_rolls.append(count)
    guess = random.choice(max_rolls)
    choice = choices[guess]
    response = BEATS[choice]
    if round % randint(2,5) == 0:
        lim_MOVES = MOVES
        lim_MOVES.remove(response)
        choice = random.choice(lim_MOVES)
        #inv_response = BEATS[response]
        return choice
    else:
        return response

def get_their_history(opp_history, opp_input, opp_throw, look_back):
    history_join = ''.join(opp_history) # join history into string
    for match in re.finditer(history_join[-look_back:], history_join): #iterate through string to find throw after pattern of look_back length
        if match.end() < len(history_join):
            common_response = history_join[match.end()]
            if common_response == 'R':
                opp_throw[0] += 1
            elif common_response == 'P':
                opp_throw[1] += 1
            elif common_response == 'S':
                opp_throw[2] += 1
    total = sum(opp_throw) # total number for calculating percentages; round would probably do, but I'm half-convinced it'll never work
    rolls = [0,0,0]
    for count, i in enumerate(opp_throw):
        if i > 0: # assign a roll to each possible response, from 0 to their total occurrences; skip the zeros to avoid division errors
            rolls[count] = randint(0, (i*100)/total)
        max_roll = max(rolls) # get the value of the max roll
        max_index = rolls.index(max(rolls)) # get the index of the max roll
        max_rolls = [max_index]
        for count, i in enumerate(rolls): # check for duplicates of the max roll to choose randomly from
            if i == max_roll:
                max_rolls.append(count)
        response = BEATS[MOVES[random.choice(max_rolls)]] # response is random choice from max_rolls
    return response

def get_my_history(my_history, my_input, my_throw, look_back):
    history_join = ''.join(my_history) # join history into string
    for match in re.finditer(history_join[-look_back:], history_join): #iterate through string to find throw after pattern of look_back length
        if match.end() < len(history_join):
            common_response = history_join[match.end()]
            if common_response == 'R':
                my_throw[0] += 1
            elif common_response == 'P':
                my_throw[1] += 1
            elif common_response == 'S':
                my_throw[2] += 1
    total = sum(my_throw) # total number for calculating percentages; round would probably do, but I'm half-convinced it'll never work
    rolls = [0,0,0]
    for count, i in enumerate(my_throw):
        if i > 0: # assign a roll to each possible response, from 0 to their total occurrences; skip the zeros to avoid division errors
            rolls[count] = randint(0, (i*100)/total)
        max_roll = max(rolls) # get the value of the max roll
        max_index = rolls.index(max(rolls)) # get the index of the max roll
        max_rolls = [max_index]
        for count, i in enumerate(rolls): # check for duplicates of the max roll to choose randomly from
            if i == max_roll:
                max_rolls.append(count)
        pre_response = MOVES[random.choice(max_rolls)] # response is random choice from max_rolls
        if pre_response < 10:
            response = random.choice(MOVES)
            return response
        else:
            MOVES[random.choice(max_rolls)] # response is random choice from max_rolls
            return response

if(1): #main game loop

    if input == "": # no input means new game; initialize variables and throw a random choice
        their_history = []
        my_history = []
        s_throw = [0,0,0]
        d_throw = [0,0,0]
        t_throw = [0,0,0]
        p_throw = [0,0,0]
        m_s_throw = [0,0,0]
        m_d_throw = [0,0,0]
        m_t_throw = [0,0,0]
        m_p_throw = [0,0,0]
        round = 0
        output = random.choice(MOVES)
        my_history.append(output)

    else:
        if round < 10: # young game, continue throwing random moves
            output = random.choice(MOVES)
            my_history.append(output)
            their_history.append(input) # possibly remove this later, as their initial moves may not have useful information in them
            round += 1

        else: # begin strategizing to find decent throw
            s_response = get_their_history(their_history, input, s_throw, 1)
            d_response = get_their_history(their_history, input, d_throw, 2)
            t_response = get_their_history(their_history, input, t_throw, 3)
            p_response = get_their_history(their_history, input, p_throw, 5)
            m_s_response = get_their_history(my_history, input, m_s_throw, 1)
            m_d_response = get_their_history(my_history, input, m_d_throw, 2)
            m_t_response = get_their_history(my_history, input, m_t_throw, 3)
            m_p_response = get_their_history(my_history, input, m_p_throw, 5)
            their_history.append(input)
            round += 1
            if round % randint(1,29) == 0:
                output = random.choice(MOVES)
                my_history.append(output)
            else:
                output = get_output(s_response, d_response, t_response, p_response, m_s_response, m_d_response, m_t_response, m_p_response)
                #print(thisHapp, thatHapp)
                my_history.append(output)