Честная Скала, Бумага, Ножницы


58

Многие считают RPS азартной игрой. Если оба игрока играют непредсказуемо, лучшая стратегия - играть случайно. Однако давайте представим немного предсказуемости.

У каждого бота будет возможность рассказать другому боту, во что он будет играть одновременно. Затем наступает пауза, в которой каждый бот узнает, что объявил другой игрок. Если он разыгрывает это оружие, он объявил, что получит одно очко в дополнение к очкам за проигрыш или ничью.

Выигрыш стоит два очка, ничья, одно очко, а проигрыш 0 очков.

     Honest Bot       Dishonest
Win     3                  2
Draw    2                  1
Loss    1                  0

В ваших же интересах быть честным (но также следить за тем, чтобы ваш оппонент не верил вам).

Матчи будут проводиться в формате кругового турнира, и цель будет состоять в том, чтобы максимизировать ваш собственный общий счет по матчам, которые вы играете.

Формат ввода / вывода:

  • Ваш бот будет функцией Python 2.7, которая принимает 4 аргумента и должна иметь уникальное имя (которое будет использоваться для представления вашего представления).
  • Первые два аргумента всегда будут в порядке: прошлые ходы противника, за которыми следуют ваши прошлые ходы. Это будет список в порядке от первого до самого последнего раунда, где каждый индекс содержит список с ходом, который, по утверждению оппонента, он сделает, после чего следует ход, который они фактически сделали.
  • Следующие два аргумента позволят вашему боту определить, является ли это «честным» раундом или «реальным» раундом. Если это «честный» раунд, они оба будут None. Если это «настоящий» раунд, они будут, по порядку, ходом, который ваш оппонент объявил, что он сделает, после того, как вы заявили, что сделаете.
  • Все аргументы или части аргументов, которые представляют ходы, будут использовать «R», «P» и «S» для представления камня, бумаги и ножниц соответственно.
  • Ваша функция должна возвращать либо «R» для камня, «P» для бумаги или «S» для ножниц. Боты, которые могут возвращать другие значения, будут дисквалифицированы.
  • Каждый бот будет запускаться против каждого другого бота 200 раз, а сам - 100 раз. Цель состоит в том, чтобы быть ботом с наибольшим количеством очков в конце соревнования.
  • Что касается обсуждения в комментариях, представленные материалы не могут быть прочитаны или записаны в каком-либо файле, или каким-либо образом саботировать или читать код оппонента.

Примеры:

Это четыре примера ботов, которые я собрал быстро. Они будут участвовать в конкурсе в качестве дополнительных ботов. Если вы проиграли последнему, у вас есть работа.

def honestpaper(I,dont,care,about_these):
    return "P"

def honestrock(I,dont,care,about_these):
    return "R"

def honestscissors(I,dont,care,about_these):
    return "S"

import random
def randombot(I,dont,care,about_these):
    return random.choice(["R","P","S"])

контроллер:

А вот контроллер, который я буду использовать. Новые материалы будут импортированы в начале и добавлены в словарь bot_map.

from honestrock import honestrock
from honestpaper import honestpaper
from honestscissors import honestscissors
from randombot import randombot

bot_map = {
  0:honestrock, 1:honestpaper, 2:honestscissors, 3:randombot
}

player_num=len(bot_map)

def real(history1,history2,number,honest1,honest2):
    return bot_map[number](history1,history2,honest1,honest2)

def honest(history1,history2,number):
    return bot_map[number](history1,history2,None,None)

def play_match(num1,num2):
    history1=[]
    history2=[]
    score1=0
    score2=0
    for x in range(250):
        h1=honest(history2,history1,num1)
        h2=honest(history1,history2,num2)
        r1=real(history2,history1,num1,h2,h1)
        r2=real(history1,history2,num2,h1,h2)

        if h1==r1: score1+=1
        if h2==r2: score2+=1

        if r1==r2: score1+=1; score2+=1
        elif r1=="R":
            if r2=="P": score2+=2
            else: score1+=2
        elif r1=="P":
            if r2=="S": score2+=2
            else: score1+=2
        else:
            if r2=="R": score2+=2
            else: score1+=2

        history1.append([h1,r1])
        history2.append([h2,r2])
    return score1,score2

scores = []
for x in range(player_num):
    scores.append(0)

for _ in range(100):

    for x in range(player_num):
        for y in range(player_num):
            scorex,scorey=play_match(x,y)
            scores[x]+=scorex
            scores[y]+=scorey

for score in scores:
    print score

Итоговые результаты:

csbot                    3430397
thompson                 3410414
rlbot                    3340373
have_we_been_here_before 3270133
mason                    3227817
deepthought              3019363
adaptive_bot             2957506
THEbot                   2810535
dontlietome              2752984
irememberhowyoulie       2683508
learningbot4             2678388
betrayal                 2635901
averager                 2593368
honestrandom             2580764
twothirds                2568620
mirrorbot                2539016
tit4tat                  2537981
honestscissors           2486401
trusting_bot             2466662
rotate_scissors          2456069
rotate_paper             2455038
rotate_rock              2454999
honestpaper              2412600
honestrock               2361196
rockBot                  2283604
trustingRandom           2266456
user5957401bot           2250887
randombot                2065943
Dx                       1622238
liarliar                 1532558
everybodylies            1452785

1
Какой статус?
user1502040

Ответы:


11

каменщик

Пытается собрать информацию о других ботах, например, насколько они честны и как на них повлиял мой первый шаг. Затем я пытаюсь найти других очевидных ботов, которые следуют шаблону, и использовать их, чтобы дать мне больше очков. Наконец, у масона есть секретное оружие: знание тайного общества, в котором оба участвующих бота взаимно участвуют в полном розыгрыше, набирая по 500 очков каждый. К сожалению, секрет довольно ... Ну, секрет и меняется каждый раз, когда это делает Мейсон.

def mason(op_hist, my_hist, op_move, my_move):
    win_map = {"R": "P", "P": "S", "S": "R"}
    lose_map = {"R": "S", "P": "R", "S": "P"}
    if not len(op_hist):
        return "S"
    if op_hist[0] == ['S', 'S']:
        code = "S" + "".join("RPS"[ord(i) % 3] if isinstance(i, str) else "RPS"[i % 3] for i in __import__("sys")._getframe().f_code.co_code)[1::2]
        honest, guess = zip(*op_hist)
        if honest == guess == tuple(code[:len(op_hist)]):
            return code[len(op_hist)]
    op_honesty = sum(len(set(round))-1 for round in op_hist) / float(len(op_hist))
    if not my_move:
        moves = "".join(i[1] for i in op_hist)
        # Identify rotators
        if "PSRPSR" in moves:
            return moves[-2]
        # Identify consecutive moves
        if "RRRRR" in moves[:-10] or "SSSSS" in moves[:-10] or "PPPPP" in moves[:-10]:
            return win_map[moves[-1]]
        # Try just what wins against whatever they choose most
        return win_map[max("RPS", key=moves.count)]
    op_beats_my_honest = sum(win_map[me[0]] == op[1] for op, me in zip(op_hist, my_hist)) / float(len(op_hist))
    op_draws_my_honest = sum(me[0] == op[1] for op, me in zip(op_hist, my_hist)) / float(len(op_hist))
    op_loses_my_honest = sum(lose_map[me[0]] == op[1] for op, me in zip(op_hist, my_hist)) / float(len(op_hist))
    if op_honesty <= 0.4:
        return win_map[op_move]
    max_prob = max((op_loses_my_honest, op_draws_my_honest, op_beats_my_honest))
    if max_prob >= 0.6:
        if op_beats_my_honest == max_prob:
            return lose_map[my_move]
        if op_draws_my_honest == max_prob:
            return win_map[my_move]
        if op_loses_my_honest == max_prob:
            return my_move
        assert False
    return my_move

9

Rlbot: обучение с подкреплением

Использует метод обучения с подкреплением, решая эту игру аналогично проблеме бандитов, вооруженных русскими. Он делает это двумя способами: пытается узнать, какое объявление лучше против каждого оппонента, и придерживается этого (полезно против постоянных ботов), и пытается узнать результат различных ходов в предыдущих аналогичных ситуациях (аналогично в отношении относительных игр). Например, камень против бумаги похож на предыдущий документ против ножниц). Исходные предположения оптимистичны, поэтому этот игрок будет считать, что честность даст ему 3 очка, а ложь даст 2, и поэтому всегда будет честен, пока не доказано обратное.

Обновление: первые результаты турнира высветили проблему с этим ботом, заключающуюся в невозможности обнаружить паттерны в декларациях своих оппонентов (что заставило его играть неоптимально против ротаторов). Затем я добавил компонент соответствия шаблонов в код для честных раундов, который использует регулярное выражение для поиска самого длинного суффикса в истории объявлений оппонентов, который присутствует где-то ранее в этой истории, и какой ход был выполнен после этого , Мы предполагаем, что противник будет снова делать то же самое движение, и использовать обучение подкрепления, как и прежде, чтобы решить, каким должен быть лучший ответ.

import re
def rlbot(hismoves,mymoves,hismove,mymove):
 def score(d,m1,m2):
  s=0
  if m1==m2:
   s=1
  elif (m1+m2) in "RPSR":
   s=2
  return s+(d==m2)

 alpha=0.2
 if mymove:
  history=[([d1,m1],[d2,m2]) for ((d1,m1),(d2,m2)) in zip(hismoves,mymoves) if score(None,hismove,mymove)==score(None,d1,d2)]
  bestscore=-1
  bestmove=""
  for move in "RPS":
   ev=2+(move==mymove)
   for ((d1,m1),(d2,m2)) in history:
    if score(None,move,mymove)==score(None,m2,d2):
     ev=(1-alpha)*ev+alpha*score(d2,m1,m2)
   if ev>bestscore:
    bestscore=ev
    bestmove=move
  return bestmove

 else:
  if len(hismoves)==0:
   return "R"
  bestscore=-1
  bestmove=""
  hisdeclarations="".join(d for [d,m] in hismoves)
  predicted_move=re.search(r'(.*)\n.*\1(.)',hisdeclarations+'\n'+hisdeclarations).group(2)
  history=[([d1,m1],[d2,m2]) for ((d1,m1),(d2,m2)) in zip(hismoves,mymoves) if d1==predicted_move]
  for move in "RPS":
   ev=3
   for (his,my) in history:
    (d1,m1)=his
    (d2,m2)=my
    if d2==move:
     ev=(1-alpha)*ev+alpha*score(d2,m1,m2)
   if ev>bestscore:
    bestscore=ev
    bestmove=move
  return bestmove

Попробуйте онлайн!


6

Я никогда особо не использовал Python, поэтому уверен, что где-то допустил ошибку.

import random
def learningbot3(opponentlist,a,opponent,me):
 #tell the other bot a random thing
 if opponent==None:
  return random.choice(["R","P","S"])
 #check whether the other bot has mostly told the truth in the last 10 rounds
 truth=0
 for game in opponentlist[-10:]:
  truth-=1
  if game[0]==game[1]:
   truth+=2
 #assume the other bot will tell the truth
 if truth>=3:
  if me==opponent:
    return me
  elif opponent=="R":
   return "P"
  elif opponent=="P":
   return "S"
  elif opponent=="S":
   return "R"
 #assume the other bot is lying
 elif truth<=-3:
  return random.choice([me,opponent])
  #return opponent
 #pick whatever we said we would
 else:
  return me

Он должен проверить последние 10 раундов, чтобы увидеть, как часто противник лгал, а затем выбрать другой ответ в зависимости от этого.


6

Вот мой адаптивный бот. Он анализирует последние 2 хода противника, чтобы определить, честный он бот или нет, и играет соответственно:

Редактировать 1: Если другой бот является постоянным (то есть всегда играет одно и то же оружие), этот бот сокрушает его, играя выигрышным оружием и будучи честным в то же время.

Редактировать 2: Улучшен постоянный детектор ботов, чтобы работать с ротаторными ботами тоже.

import random
def adaptive_bot(other_past, my_past, other_next, my_next):
    winners = {"R": "P", "P": "S", "S": "R"}
    if my_next is None:
        return winners[other_past[-6:][0][1]] if other_past else random.choice(list(winners.keys()))
    else:
        is_other_honest = all([other_claim == other_move for other_claim, other_move in other_past[-2:]])
        return winners[other_next] if is_other_honest else my_next

5

csbot

def csbot(ophist,myhist,opdecl,mydecl):

  import random

  RPS = "RPS"

  def value(opd,myd,opmove,mymove):
    if opmove==mymove:
      val = 9
    elif opmove+mymove in RPS+RPS:
      val = 20
    else:
      val = -2
    return val+10*(myd==mymove)-(opd==opmove)

  def best(od,md):
    l = float(len(ophist))
    weights = dict([ (m, random.random()/8) for m in RPS ])
    for n in range(len(ophist)):
      if ophist[n][0]==od and myhist[n][0]==md:
        weights[ophist[n][1]] += 1+4*((n+1)/l)**2
    sw = sum([ weights[m] for m in RPS ])
    bestexpect = 0
    for m in RPS:
      expect = sum([ weights[om]/sw*value(od,md,om,m) for om in RPS ])
      if expect > bestexpect:
        bestexpect = expect
        bestmove = m
    return bestmove, bestexpect


  honest = all ([ decl==mv for decl, mv in ophist ])

  if honest:
    if mydecl<>None:
      return mydecl
    expnxt = set();
    for i in range(len(ophist)-1):
      if ophist[i][0]==ophist[-1][0]:
        expnxt.add(ophist[i+1][0])
    if len(expnxt)==1:
      return RPS[ (RPS.index(expnxt.pop())+1) % 3 ]

  if mydecl==None:
    l = float(len(ophist))
    weights = dict([ (m, random.random()) for m in RPS ])
    for n in range(len(ophist)):
      weights[ophist[n][0]] += 1+((n+1)/l)**2
    sw = sum([ weights[m] for m in RPS ])
    bestexpect = 0
    worstexpect = 99
    for m in RPS:
      expect = sum([ best(od,m)[1]/sw*weights[od] for od in RPS ])
      if expect > bestexpect:
        bestexpect = expect
        bestmove = m
      if expect < worstexpect:
        worstexpect = expect
    if bestexpect-worstexpect < 3:
      bestmove = random.choice(RPS)
    return bestmove

  return best(opdecl,mydecl)[0]

Будьте честны, пока другой игрок, и выявляйте простых детерминированных ботов. Сыграйте ход, который максимизирует ожидаемое значение, когда мы в основном получаем свои очки, но также не хотим давать очки другому игроку. Но собственные очки лучше в десять раз, отсюда и необычные числа в valueфункции. Движения противников ожидаются в зависимости от того, как часто мы видели их раньше в этой ситуации (объявленные ходы), но недавно увиденные ходы имеют больший вес, чем ходы, замеченные ранее. Для случайных начальных ходов (ситуаций, которых раньше не было) и некоторой дополнительной нечеткости, веса включают небольшие дополнительные случайные числа

Обновление: используйте ожидаемые результаты также в честном раунде. Чтобы сделать это, нормализуйте и возьмите дополнительное очко, которое оппонент может получить за честность - это не могло повлиять на наше решение в реальном раунде, но необходимо сейчас. Я думал об этом с самого начала, но ошибочно считал, что это не стоит. Я видел, что можно было бы дать trusting_botменьше очков (но бот в любом случае не является сильным противником), но упустил возможность получить дополнительные очки rockbotза хорошую игру в честном раунде, даже если его игра в этом раунде случайна.


Это не всегда, кажется, возвращает результат.
user1502040

Я думаю, что вы if mydecl == None:ошибаетесь.
user1502040

@ user1502040 Почему ты так думаешь? Я никогда не наблюдал никаких проблем.
Кристиан Сиверс


4

предательство

def betrayal(yours, mine, you ,me):
    import random
    if you is None:
        pick = random.choice(['R','P','S'])
    else:
        you = you[0]
        me = me[0]
        if len(yours) < 50: #Build myself a reputation of honesty
            pick = me
        else:
            if len(yours) >= 50 and len(yours) < 100:
                honesty = sum([1 if y[0]==y[1] else 0 for y in yours])/float(len(yours))
                if honesty <= 0.5: #If dishonest try to outwit
                    pick = 'S' if me=='R' else 'R' if me == 'P' else 'P'
                else: #Else just plain cheat
                    pick = 'P' if you=='R' else 'R' if you=='S' else 'S'
            elif len(yours) >= 100: #When dishonest moves outweight honest moves, change tactics...
                honesty = sum([1 if y[0]==y[1] else 0 for y in yours[50:]])/float(len(yours[50:]))
                if honesty <= 0.5: #... and just play according to most likely pick
                    what_did_you_do = [k[1] for k in yours if k[1]!=k[0]]
                    index = [i for i,k in enumerate(yours) if k[1]!=k[0]]
                    what_i_said_i_ll_do = [k[0] for i,k in enumerate(mine) if i in index]
                    matches = zip(what_i_said_i_ll_do, what_did_you_do)
                    what_you_might_answer = [k[1] for k in matches if k[0]==me]
                    table = [len([k for k in what_you_might_answer if k=='R']),len([k for k in what_you_might_answer if k=='P']),len([k for k in what_you_might_answer if k=='S'])]
                    maybe_your_pick = ['R','P','S'][table.index(max(table))]
                    pick = 'P' if maybe_your_pick=='R' else 'R' if maybe_your_pick=='S' else 'S'
                else:
                    pick = 'P' if you=='R' else 'R' if you=='S' else 'S'
    return pick

Идея состоит в том, что в течение первых 50 ходов я играю честно, а затем, как только я заманиваю оппонента, заставляя его думать, что я честен, играю нечестно, пытаясь сыграть то, что противоречит тому, что будет играть противник (в зависимости от того, был ли он честным или нечестным). в прошлом). Когда я достигаю точки, в которой я играл честно, чаще, чем нечестно, я меняю тактику и выбираю наиболее вероятный ход противника на основе предыдущих известных конфигураций.


3
import random
def honestrandom(a, b, c, move):
    if move == None:
        return random.choice(["R","P","S"])
    return move

3

Имя бота: я помню, как ты лжешь

import random

#Bot Name: I Remember How You Lie
def irememberhowyoulie(opponentlist, mylist, opponentmove, mymove):
    random.seed()

    wintable = {
                "R": {"R": 1, "P": 0, "S": 2},
                "P": {"R": 2, "P": 1, "S": 0},
                "S": {"R": 0, "P": 2, "S": 1}
               }

    winprob = {
               "R": {"R": 0.0, "P": 0.0, "S": 0.0},
               "P": {"R": 0.0, "P": 0.0, "S": 0.0},
               "S": {"R": 0.0, "P": 0.0, "S": 0.0}
              }

    totalprob = {"R": 0, "P": 0, "S": 0}

    # Calculate the probability that the opponent will lie base on the probability that it lied in the last 15 ~ 25 rounds
    # And calculate the probability that what the bot will show next
    picklength = min(random.randint(15, 25), len(opponentlist))
    lying, tempsum = 0, 0.0
    pickedup = {"R": 0, "P": 0, "S": 0}
    if picklength == 0:
        lying = 0.5
    else:
        for eachround in opponentlist[-picklength:]:
            pickedup[eachround[1]] += 1
            if eachround[0] != eachround[1]:
                lying += 1
        lying = lying * 1.0 / picklength
    for s in pickedup:
        pickedup[s] = 1.0 / (1 + pickedup[s])
        tempsum += pickedup[s]

    #Honest Round
    if opponentmove is None and mymove is None:
        a = random.random() * tempsum
        if a < pickedup["R"]:
            return "R"
        elif a < pickedup["R"] + pickedup["P"]:
            return "P"
        else:
            return "S"

    #Real Round
    else:                
        for me in winprob:
            ishonest = 0
            if me == mymove:
                ishonest = 1
            for op in winprob[me]:
                if op == opponentmove:
                    winprob[me][op] = (wintable[me][op] + ishonest) * (1 - lying)
                else:
                    winprob[me][op] = (wintable[me][op] + ishonest) * lying * pickedup[op] / (tempsum - pickedup[opponentmove])
                totalprob[me] += winprob[me][op]

        optimalmove, optimalvalue = "R", -9999999.0
        for me in totalprob:
            if totalprob[me] > optimalvalue:
                optimalmove, optimalvalue = me, totalprob[me]
        return optimalmove

Протестировано несколько пробежек по 100 раундов, и выяснилось, что победитель набирает в среднем около 220 очков. Скорее честно думаю;)

Впервые для меня, чтобы участвовать в проблемах КОТ, так что я думаю, что есть еще возможности для улучшения


3

Синица для Тат

Классический аксельродианский участник: обнадеживающий, но мелкий; простой, но надежный. Это не дилемма заключенного, и я не пытался предсказать ход противника, поэтому я очень сомневаюсь, что он будет действительно конкурентоспособным. Но «сотрудничество» по-прежнему приносит участникам наибольшее количество баллов, поэтому я думаю, что это, по крайней мере, сработает.

import random
def tit4tat(opphist, myhist, oppfut, myfut):
    if (not myfut): return random.choice(['R','P','S'])
    if (not opphist) or opphist[-1][0]==opphist[-1][1]: return myfut
    return random.choice(['R','P','S'])

3

Две трети

Использует стратегию Питера Тейлора, упомянутую в Песочнице и в этом комментарии .

Он использует равновесие Нэша .

import random

def two_thirds(h_opp, h_me, opp, me):

    def result(opp, me):
        if opp==me: return 0
        if opp=="R" and me=="S" or opp=="S" and me=="P" or opp=="P" and me=="R": return -1
        return 1

    moves = {"R", "P", "S"}
    honest = (opp == None)
    if honest:
        return random.choice(list(moves))
    else:
        res = result(opp, me)
        if res==-1:
            counter = list(moves - {opp, me})[0]
            return random.choice([me,counter,counter])
        if res==1:
            return random.choice([me,me,opp])
        return me

Это ошибки для меня. В строке 13 верните random.choice (перемещается). Я думаю, что это, вероятно, потому что вы используете .choice в словаре. Пока это не исправлено, я боюсь, что это представление недействительно.
Грифон - Восстановить Монику

@Gryphon Это не словарь, это набор.
LyricLy

Ах, прости. Я просто увидел волнистые скобки и подумал «словарь». Виноват. Любая идея, почему random.choice ошибается в этой строке тогда?
Грифон - Восстановить Монику

@Gryphon Может показаться, что random.choiceвыбор случайного номера индекса, а затем возвращает объект в списке с этим индексом. Поскольку наборы не имеют порядка, они также не поддерживают индексацию и, следовательно, не работают с ними random.choice. Простым решением этой проблемы было бы привести набор к списку перед вызовом random.choice.
LyricLy

Ах. У меня нет python на этом компьютере, поэтому я не могу это исправить прямо сейчас, но я исправлю это в своем коде, когда вернусь домой. Если бы @ mbomb007 исправил бы это здесь, это было бы здорово.
Грифон - Восстановить Монику

3

Глубокая мысль

def check_not_loose_bot(opHist, myHist):
    not_loose_points = 0
    for i in range(0, len(opHist)):
        if opHist[i][1] == opHist[i][0] or myHist[i][0] == win_map[opHist[i][0]] and opHist[i][1] == win_map[myHist[i][0]]:
            not_loose_points += 1
    not_loose_percent = float(not_loose_points) / len(opHist)
    if not_loose_percent > 0.9:
    #    print("is not willing to loose")
        return True
    return False

def check_trick_bot(opHist, myHist):
    trick_points = 0
    for i in range(0, len(opHist)):
        if opHist[i][1] == win_map[myHist[i][0]]:
            trick_points += 1
    trick_percent = float(trick_points) / len(opHist)
    if trick_percent > 0.9:
  #      print("is tricking me")
        return True
    return False

def check_honest_bot(opHist):
  #  print("check honest")
    honest_points = 0
    for i in range(0, len(opHist)):
        if opHist[i][0] == opHist[i][1] :
            honest_points += 1
    honest_percent = float(honest_points) / len(opHist)
    if honest_percent > 0.9:
    #    print("is honest")
        return True
    return False

def check_self_match(opHist, myHist):
    for i in range(0, len(myHist)):
        if opHist[i][0] != myHist[i][0]:
            # im not playing against myself, because the other one was claiming a different value than i did
#            print("differ: "+str(opHist)+", "+str(myHist))
            return False
        if opHist[i][1] != opHist[i][0]:
#            print("lie")
            # im not playing against myself, because the other bot wasn't honest (and i'm always honest as long as i think i play against myself)
            return False
    return True

def check_equal(move1, move2, fullCheck): # WARNING: FOR COMPABILITY THIS IS RETURNING NEQ INSTEAD OF EQ
    if fullCheck:
        return move1 != move2
    else:
        return move1[0] != move2[0] #only check claims

def is_pattern(opHist, pattern_start, prob_pattern_start, pattern_length, full_check):
    for i in range(0, pattern_length-1):
        if check_equal(opHist[pattern_start + i] , opHist[prob_pattern_start + i], full_check):
            return False
    return True

win_map = {"R": "P", "P": "S", "S": "R"}
def deterministic_best_guess(opHist, full_check = True):
    size = 0
    random_result = random.choice(["R", "P", "S"])
    for pattern_length in range(2, (len(opHist)+1)/2): #a pattern has to occur at least twice
        for pattern_start in range(0, len(opHist) - 2 * pattern_length):
            if not is_pattern(opHist, pattern_start, len(opHist) - pattern_length + 1, pattern_length, full_check):
                 continue
            is_repeated = False
            is_fooled = False
            for repeated_pattern_start in range(pattern_start + pattern_length, len(opHist) - pattern_length):
                if not is_pattern(opHist, pattern_start, repeated_pattern_start, pattern_length, full_check):
                     continue
                is_repeated = True
                if check_equal(opHist[pattern_start + pattern_length - 1], opHist[repeated_pattern_start + pattern_length - 1], full_check):
                    is_fooled = True
                    break
    #            print("pattern found: " + str(opHist[pattern_start : pattern_start + pattern_length]) +" at "+str(pattern_start)+" and "+str(repeated_pattern_start))
   #             print("check: "+str(opHist))
            if is_fooled or not is_repeated:
                break
            #we have found a deterministic best guess
  #          print("most likely next step: "+ str(opHist[pattern_start + pattern_length - 1]))
            if full_check:
                return win_map[opHist[pattern_start + pattern_length - 1][1]], True
            return win_map[opHist[pattern_start + pattern_length - 1][0]], True # if we don't have a full check, the pattern only applies to claims. So pretend to win against the claimed result.

    #fallback
 #   print("fallback")
    return random_result, False

def DeepThought(opHist, myHist, opMove, myMove):
    if opMove == None:
    #claiming phase
        if len(myHist) == 0:
        #seed random to be able to be deterministic when chosing randomly
            #The seed is secret (kind of)
            random.seed(133427)
        else:
            #seed random according to my previous claims
            seed = 133427
            for i in range(0, len(myHist)):
                if myHist[i][0] == "R":
                    seed = seed*3+1
                elif myHist[i][0] == "S":
                    seed = seed*7+1
                elif myHist[i][0] == "P":
                    seed = seed*11+1
                while seed%2 == 0:
                    seed /= 2
            random.seed(seed)
        if check_self_match(opHist, myHist):
            #claim a random value, will happen in the first round or in a self-match
            result = random.choice(["R", "P", "S"])
            return result
      #  print("differ detected")
        if check_trick_bot(opHist, myHist) and len(myHist) > 10:
            # i play against a trick bot. I can reduce its points by trieing to guess its claim, and force him to lie
            result, sure = deterministic_best_guess(opHist, False)
        else:
            result, sure = deterministic_best_guess(opHist)
        random.seed(0)
        return result
    if check_self_match(opHist, myHist):
        #i play against myself, i can only hope for a honest draw, so do that
        return myMove
#    print("no self-math")
    #dbg needs a valid seed, so provide it
    random.seed(133427)
    result, sure = deterministic_best_guess(opHist)
    if sure:
        #i'm sure i play against a deterministic bot. I'll be honestly winning. YEY.
        return myMove
    if check_honest_bot(opHist) and len(opHist) > 10:
        #i play against an honest bot. I'll accept a draw, but i will not accept a loss
        if win_map[myMove] == opMove:
            return win_map[opMove]
        return myMove
    if check_trick_bot(opHist, myHist) and len(opHist) > 10:
        #i play against a tricking bot. He'll make me either loose honestly (1 Pnt) or i have to be dishonest (2 Pnt). So let's lie.
        return win_map[win_map[myMove]]
    if check_not_loose_bot(opHist, myHist) and len(opHist) > 10:
        #i play against a bot thats not willing to loose. If it looks like i won, i can loose honestly (1Pnt, 2Pnt for him),
        #or i have to be dishonest (2 Pnt, 0 Pnt for him). So let's lie in that case.
        #If it looks like its a draw, i'll be honest (conservative way), and get my 2 : 2 Pnt.
        #If it lokks like i'll loose, I'll not accept it. I'll lie to win for 2 : 1 Pnt.
        if myMove == opMove:
            return myMove
        if myMove == win_map[opMove]:
            # He'll lie. So lie together and keep smiling.
            return opMove
        # I'll loose. NO!!!! Not gonna happen
        return win_map[opMove]
    return myMove

Просто несколько заметок на нем:

  • DeepThought любит думать. Много. Я сожалею об этом, но я действительно не знаю, как это исправить. Я обвиняю Python.
  • DeepThought пытается быть честным. Быть честным дает вам один дополнительный пункт, который совпадает с ожидаемым значением для нормального RPS
  • Но: DeepThought получает в среднем даже больше, чем 2 очка за игру. Он использует некоторое обнаружение, чтобы найти некоторые распространенные поведения (например, обман, честность и т. Д.), И адаптируется в соответствии с этим.
  • DeepThought является чисто детерминированным, поэтому он будет притягивать себя, потому что он всегда будет принимать одно и то же решение с обеих сторон.
  • Чтобы быть уверенным, что он не лжет против себя, у него есть специальное обнаружение, как и у некоторых других ботов. Это очень агрессивно, даже если предположить, что это правда после одного раунда (и в первом раунде тоже). По сути, пока ходы противника принадлежат мне, я предполагаю, что это зеркальное совпадение.
  • Интересная часть (и часть, которая имеет десятки ложных срабатываний) - это проверка на детерминированного бота, который зависит только от его собственного предварительного результата. Эта проверка ищет любой паттерн размера n, который повторяется дважды, и который может описывать последние n-1 ходы, предсказывать претензии противника и заранее двигаться. Эта часть занимает некоторое время, к сожалению.

Я новичок как в Koth, так и в Python, так что скажите мне, если я что-то напутал в этом боте. Я не думаю, что это может превзойти усиленное обучение (потому что я думаю, что это выучит мои движения слишком быстро), но давайте попробуем.

Мне нравится этот вызов, и если я найду время, я бы хотел добавить органичный подход к вычислениям (хотя, возможно, будет слишком мало давления на более высокие измерения). Разрешено ли добавлять несколько предложений? Или запрещено предотвращать загрузку вашего основного бота, вставляя в него те, которые предназначены только для проигрыша вашему основному боту?

РЕДАКТИРОВАТЬ: Исправлена ​​опечатка кода, которая характеризовала меня как не говорящего по-английски


Запрещено публиковать несколько записей, но запрещается публиковать записи, которые поддерживают другого бота (даже не вашего). Можно проиграть другому боту, если это не так.
Грифон - Восстановить Монику

Я получил ошибку при запуске этого, так как 32-я строка вашей функции DeepThought return resultтребует дополнительного отступа. Я считаю, что это должно быть внутри гигантского оператора if, сразу после него, поскольку переменная returnобъявляется только в этом операторе it. Я сделал эту модификацию в своем коде, и теперь она работает без ошибок. Если бы вы не возражали против такого изменения, это было бы здорово.
Грифон - Восстановить Монику

3
Вы, кажется, возитесь с состоянием глобального генератора случайных чисел, что, вероятно, не в порядке. Я считал делать подобную вещь, и нашел это решение: создать новый случайный объект R=random.Random(seed)и использовать его как это: R.choice(...).
Кристиан Сиверс

@ Грифон исправлен. Вероятно, некоторые ошибки произошли при преобразовании из моего локального сценария в se, где все должно быть добавлено еще один раз
alex berne

1
@alexberne Вы можете выбрать вставленный код и нажать {}кнопку на панели инструментов, чтобы автоматически сделать отступ для каждой строки.
Сельчук

2
import random
def user5957401bot(a,b,c,d):
    if d == None: 
       return random.choice(["R","P","S"])
    else:
       return random.choice(["R","P","S",d])

2

have_we_been_here_before

Просто спрашивает «были ли мы здесь раньше» и выбирает ход, который дал бы лучший средний результат в любых таких предыдущих играх.

Редактировать: Честность Клуб. Я добавил небольшой блок кода, потому что другой бот (каменщик) преуспел, создав собственный секретный клуб. Однако обратите внимание, что честная игра против честных оппонентов приносит в среднем одинаковую выгоду, играя против себя, и, возможно, есть и более широкие взаимные выгоды?

Edit2: Во время написания двух ботов впереди меня оба эксплуатировали ротаторы, поэтому я собираюсь добавить еще один блок кода, чтобы тоже запрыгнуть на эту команду. Я предполагаю, что мой код должен казаться довольно старой школой - придерживаться знакомых конструкций, найденных в любом языке программирования, потому что я действительно не знаю Python.

import random

def have_we_been_here_before(opponentList, myList, opponent, me):

    def win(x):
        if x=="R": return "P"
        elif x=="P": return "S"
        elif x=="S": return "R"

    def calc_score(r1, r2):
        if r1==r2: return 1
        elif r1==win(r2): return 2
        else: return 0

    def have_we(opponentList, myList, opponent, me, me2):
        score, count = 0, 0
        for n in range(len(opponentList)):
            if (opponent == opponentList[n][0] and me == myList[n][0]):
                score += calc_score(me2, opponentList[n][1])
                count += 1
        if count == 0: return 0
        else: return float(score) / float(count)

    if opponent == None:

        # exploit rotators
        if len(opponentList) >= 3:
            rotator = True

            for n in range(3, len(opponentList)):
                if opponentList[n][1] != opponentList[n % 3][1]:
                    rotator = False
                    break

            if rotator: return win(opponentList[len(opponentList) % 3][1])

        if len(opponentList) == 0:
            return random.choice(["R", "P", "S"])
        else:
            # crude attempt to exploit the house bots
            prev = random.choice(opponentList)[1]
            return win(prev)

    # Play honestly if opponent has played honestly so far
    honest = True
    for oppMove in opponentList:
        if (oppMove[0] != oppMove[1]):
            honest = False
            break

    if honest: return me
    # Done playing honestly

    # Have we been here before?
    rock = have_we(opponentList, myList, opponent, me, "R")
    paper = have_we(opponentList, myList, opponent, me, "P")
    sissors = have_we(opponentList, myList, opponent, me, "S")

    if rock > paper and rock > sissors: return "R"
    elif paper > rock and paper > sissors: return "P"
    elif sissors > paper and sissors > rock: return "S"
    else: return win(opponent)

2

THEbot: Честный эксплуататор

import random 
def thebot(ho,hm,om,mm):
    hands = {"R": "P", "P": "S", "S": "R"}
    if om == None:
        if (len(set([i[0] for i in ho])) < 3) and (len(ho) > 2):
            return hands[random.choice(list(set([i[0] for i in ho])))]
        else:
            return random.choice(["R","P","S"])
    else:
        if sum(1 for i in ho if i[0]==i[1]) > (len(ho)/3):
            if om == mm:
                return om
            else:
                return hands[om]
        else:
            return mm

Я только что понял, что я отказался от голосования, извините. Отмена при редактировании. (Не могу изменить это в противном случае.)
Кристиан Сиверс

@ChristianSievers отредактировано
Cinaski

@ChristianSievers спасибо!
Cinaski

2

Томпсон

import math
import random

moves = list(range(3))
names = "RPS"
from_name = dict(zip(names, moves))
to_name = dict(zip(moves, names))

#Payoff matrices given each relationship between honest moves.
A = [
    [[2, 1, 3], [2, 1, 0], [0, 2, 1]],
    [[1, 3, 2], [1, 0, 2], [2, 1, 0]],
    [[3, 2, 1], [0, 2, 1], [1, 0, 2]]
]

#Add a 1.2% penalty for the opponent's score (idea shamelessly stolen from csbot).
for d_h in range(3):
    for i in range(3):
        for j in range(3):
            A[d_h][i][j] -= 0.012 * A[[0, 2, 1][d_h]][j][i]

third = 1. / 3
two_thirds = 2 * third

nash_prior = [
    [[1, 0, 0], [two_thirds, 0, third], [third, 0, two_thirds]], 
    [[third, 0, two_thirds], [1, 0, 0], [two_thirds, 0, third]], 
    [[two_thirds, 0, third], [third, 0, two_thirds], [1, 0, 0]]
]

def mult_m_v(M, v):
    w = [0 for _ in v]
    for i, M_i in enumerate(M):
        for M_ij, v_j in zip(M_i, v):
            w[i] += M_ij * v_j
    return w

def mean_belief(counts):
    c = 1. / sum(counts)
    return [n * c for n in counts]

def sample_belief(counts):
    return mean_belief([random.gammavariate(n, 1) for n in counts])

def thompson(h_opp, h_me, opp, me):

    #Prior rationality of opponent.
    a = 0.95

    #Confidence in priors.
    n0_h = 0.5
    n0_m = 0.5

    def v(x):
        return [x for _ in range(3)]

    h_p = [v(n0_h * third) for _ in range(3)]

    m_p0 = [v(None) for _ in range(3)]
    m_p1 = [v(None) for _ in range(3)]

    #Expected prior is a mixture between nash equilibrium and uniform distribution.
    for h_i in range(3):
        for h_j in range(3):
            m_p0[h_i][h_j] = [n0_m * (a * nash + (1 - a) * third) for nash in nash_prior[h_i][h_j]] 

    for d_j_prev in range(3):
        for d_ij in range(3):
            m_p1[d_j_prev][d_ij] = list(m_p0[0][d_ij])

    #Track whether it's better to model the real moves based on the exact honest moves or
    #just the relationship between honest moves together with the opponent's defection strategy in the previous round.
    log_mp0 = 0
    log_mp1 = 0

    #Identify myself and always cooperate.
    is_me = True

    for (t, ((h_i, m_i), (h_j, m_j))) in enumerate(zip(h_me, h_opp)):

        h_i, m_i, h_j, m_j = from_name[h_i], from_name[m_i], from_name[h_j], from_name[m_j]

        d_j = (m_j - h_j) % 3
        d_ij = (h_j - h_i) % 3

        if t:
            h_j_prev = from_name[h_opp[t - 1][0]]
            m_j_prev = from_name[h_opp[t - 1][1]]
            h_p[h_j_prev][h_j] += 1

            d_j_prev = (m_j_prev - h_j_prev) % 3

            log_mp0 += math.log(m_p0[h_i][h_j][d_j] / sum(m_p0[h_i][h_j]))
            log_mp1 += math.log(m_p1[d_j_prev][d_ij][d_j] / sum(m_p1[d_j_prev][d_ij]))

            m_p1[d_j_prev][d_ij][d_j] += 1

        m_p0[h_i][h_j][d_j] += 1

        if is_me and ((h_i != h_j) or (h_j != m_j)):
            is_me = False

    if is_me:
        random.seed(len(h_me) + 1337)
        me_next = random.randrange(3)

    log_ps = [log_mp0, log_mp1]
    log_p_max = max(log_ps)
    ps = [math.exp(log_p - log_p_max) for log_p in log_ps]
    p0 = ps[0] / sum(ps)

    #We have to blend between the predictions of our 2 models for the real rounds.  

    def sample_expectation(h_i, h_j, d_j_prev=None):
        d_ij = (h_j - h_i) % 3
        if d_j_prev is None or random.random() < p0:
            p = m_p0[h_i][h_j]
        else:
            p = m_p1[d_j_prev][d_ij]
        return mult_m_v(A[d_ij], sample_belief(p))

    def take_expectation(h_i, h_j, d_j_prev=None):
        d_ij = (h_j - h_i) % 3
        e0 = mult_m_v(A[d_ij], mean_belief(m_p0[h_i][h_j]))
        if d_j_prev is None:
            return e0
        e1 = mult_m_v(A[d_ij], mean_belief(m_p1[d_j_prev][d_ij]))
        return [p0 * e0i + (1 - p0) * e1i for e0i, e1i in zip(e0, e1)]

    #We use thompson sampling, selecting the optimal deterministic strategy
    #with respect to a random opponent sampled from the posterior.

    #Actually, we use optimistic thompson sampling which clips samples to have >= than the mean expected value.

    if opp == None:
        #For the honest round we perform a lookahead to the real round to choose our strategy.
        if h_opp:
            if is_me:
                return to_name[me_next]
            h_j_prev = from_name[h_opp[-1][0]]
            m_j_prev = from_name[h_opp[-1][1]]
            d_j_prev = (m_j_prev - h_j_prev) % 3
            h_p_s = sample_belief(h_p[h_j_prev])
            h_p_u = mean_belief(h_p[h_j_prev])
            s_i = [0] * 3
            s_i_u = [0] * 3
            for h_i in range(3):
                for h_j in range(3):
                    s_i[h_i] += h_p_s[h_j] * max(sample_expectation(h_i, h_j, d_j_prev))
                    s_i_u[h_i] += h_p_u[h_j] * max(take_expectation(h_i, h_j, d_j_prev))
                s_i[h_i] = max(s_i[h_i], s_i_u[h_i])
            return to_name[s_i.index(max(s_i))]
        else:
            return to_name[me_next]
    else:
        if h_opp:
            if is_me:
                return me
            h_j_prev = from_name[h_opp[-1][0]]
            m_j_prev = from_name[h_opp[-1][1]]
            d_j_prev = (m_j_prev - h_j_prev) % 3
        else:
            if opp == me:
                return me
            d_j_prev = None
        h_i, h_j = from_name[me], from_name[opp]
        s_i = [max(s0, s1) for s0, s1 in zip(sample_expectation(h_i, h_j, d_j_prev), take_expectation(h_i, h_j, d_j_prev))]
        return to_name[(h_i + s_i.index(max(s_i))) % 3]

Интересная запись. Я скоро запусту его, должен быть в состоянии опубликовать результаты сегодня днем.
Грифон - Восстановить Монику

ОК, я немного перевернул параметры.
user1502040

Понял. Извините, что обновление занимает так много времени, просто каждый раз, когда он заканчивается, кто-то обновляет своего бота, или я получаю новый, и мне нужно запустить его снова.
Грифон - Восстановить Монику

@Gryphon, вы можете хранить таблицу результатов всех пар, поэтому при обновлении бота вам нужно всего лишь запустить 200 * (num_bots - 1) + 100 новых матчей.
user1502040

2

mirrorbot

import random

def mirrorbot(op_hist, my_hist, op_move, my_move):
    if my_move == None :
        return random.choice(["R","P","S"])
    else :
        for x in range(len(op_hist)):
            if ((op_hist[len(op_hist) -x-1][0] == my_move) and (my_hist[len(op_hist) -x-1][0] == op_move)):
                return op_hist[len(op_hist) -x-1][1]
        return my_move

Я попробую простого бота, который переделает последнюю игру своего противника в этих условиях.


Добро пожаловать в PPCG!
Мартин Эндер

1
def rotate_rock(h1, h2, is_, honest):
 return ("R", "P", "S")[len(h1) % 3]

def rotate_paper(h1, h2, is_, honest):
 return ("P", "S", "R")[len(h1) % 3]

def rotate_scissors(h1, h2, is_, honest):
 return ("S", "R", "P")[len(h1) % 3]

Идея здесь состоит в том, чтобы максимизировать счет, играя себя, и в то же время быть случайным конкурентом на других этапах против других плохих ботов.


1
Слово isявляется ключевым словом, поэтому оно недопустимо.
Эрик Outgolfer

@EriktheOutgolfer спасибо :)
Стивен

1

Dx

Я только написал этого бота, чтобы у меня был смайлик на моем имени бота xD.

def Dx(ophist, myhist, opmove, mymove):
    from random import choice
    import math
    def honest(hist):
        return [int(x[0]==x[1]) for x in hist]

    def avg(arr):
        if len(arr)==0:
            return 0
        return sum(arr)/float(len(arr))

    def clamp(i, lo, hi):
        return min(hi, max(lo, i))

    def deltas(arr):
        return [a-b for a,b in zip(arr[1:],arr[:-1])]

    def delta_based_prediction(arr,l):
        deltarr = []
        i=0
        while len(arr)<0:
            deltarr[i]=avg(arr[-l:])
            i+=1
            arr = deltas(arr)
        return sum(deltarr)

    next_honesty = delta_based_prediction(honest(ophist),int(math.sqrt(len(ophist))))
    if abs(next_honesty-0.5)<0.1 or not opmove:
        return choice(['R','P','S'])
    next_honesty=int(clamp(round(next_honesty),0,1))
    winner = {'S': 'R', 'R': 'P', 'P': 'S'}

    if next_honesty > 0:
        return winner[opmove]

    return choice([opmove, winner[winner[opmove]]])

1

Все лгут

import random

def everybodylies (opphist, myhist, oppmove, mymove):
    if mymove == None:
        return random.choice(["R","P","S"])
    elif mymove == "R": return "S"
    elif mymove == "P": return "R"
    elif mymove == "S": return "P"

Он лжет о своем движении («Я буду играть ножницами!») И предполагает, что противник также лгал, и что они попытаются превзойти то, что я сказал, что мой ход будет («хм, Рок бьет ножницы, поэтому я играю это "), но я на самом деле играю ход, который бьет этот ход (" Бумага! Сюрприз! ").


3
Для меня это звучит как первый уровень стратегии « Порошок йокаина» :-) «Теперь умный человек положил бы яд в свой кубок, потому что знал бы, что только великий дурак достигнет того, что ему дали. Я не великий дурак, так что я явно не могу выбрать вино перед тобой. Но ты, должно быть, знал, что я не великий дурак, ты бы на это рассчитывал, поэтому я не могу явно выбрать вино перед собой .. . "
Антоний

1

Доверять бот

def trusting_bot(h_opp, h_me, opp, me):
    if opp=="S":
        return "R"
    elif opp=="R":
        return "P"
    else:
        return "S"

Всегда претендует на то, чтобы метать ножницы, но будет делать все, что скажет противник. Надежно нарисует с собой.


Это было бы более эффективно, если бы оно всегда было честным против самого себя.
Грифон - Восстановить Монику

@Gryphon Вероятно, но я не достаточно хорошо питон, чтобы хотеть попытаться сделать что-то, что так взаимодействует.
ATaco


1

Имя бота: Лжец, Лжец

Не могу перестать лгать.

import random

def liarliar (herHistory, myHistory, herMove, myMove):
    options = ["R", "P", "S"]
    if myMove == None:
        return random.choice(options)
    else:
        options.remove(myMove);
        return random.choice(options)

1

RockBot

Предполагается, что противник будет честным и пытается победить их, но отказывается играть в рок.

import random
def rockBot(oppHist,myHist,oppMove,myMove):
    if oppMove == None:
        return random.choice(["R","P","S"])
    else:
        if(oppMove == "R"):
            return "P"
        elif(oppMove == "P"):
            return "S"
        elif(myMove != "R"):
            return myMove
        else:
            return random.choice(["P","S"])

1
Это кажется ошибкой, потому что в последней строке «P», «S» не заключены в квадратные скобки (не в список). Я изменил это в моей версии, но если бы вы могли сделать то же самое здесь, было бы здорово. Благодарю.
Грифон - Восстановить Монику

Не будет ли это ужасно проигрывать постоянным ножницам?
Wildcard

@Wildcard да, но он отлично
справится

1

Название бота: dontlietome

Определяет, лжет противник или нет, в зависимости от того, сколько раз противник солгал в последних 10 раундах. Выбирает ход в зависимости от того, лжет противник или нет. Если оппонент определил, что он лжет, тогда играет, как подсказка.

import random
def dontlietome(opp_moves, my_moves, opp_hint, my_hint):
    def is_trustworthy(moves, length):
        length = max(-length, -len(moves))
        history = [1 if move[0] == move[1] else 0 for move in moves[length:]]
        prob_honest = float(sum(history))/float(len(history))
        choice = random.uniform(0., 1.)
        if choice <= prob_honest:
            return True
        else:
            return False

    moves = ["R", "P", "S"]
    lose_against_map = {"S":"R", "R":"P", "P":"S"}
    length = 10
    if opp_hint == None:
        # Honest round
        return random.choice(moves)
    else:
        # Real round
        if len(opp_moves) < length:
            return my_hint
        if is_trustworthy(opp_moves, length):
            return lose_against_map[opp_hint]
        else:
            return my_hint

В строке «if is_trustworthy (opp_moves, self.length):» self не определено. Кроме того, в строке "return lost_against_map [opp_hint]" также не определено lost_against_map. Длина собственной личности, кажется, решается удалением себя. но другая проблема все еще остается. Пока это не исправлено, я боюсь, что это недействительно.
Грифон - Восстановить Монику

К сожалению, я написал это, используя объект, и я забыл удалить некоторые ссылки на себя и полностью скопировать код. Я исправлю это, как только вернусь домой.
coolioasjulio

ХОРОШО. Если это просто небольшая ошибка, я исправляю ее (как и в некоторых других ботах, и если бы это была только проблема с самим собой), но отсутствующая функция - это отдельная история.
Грифон - Восстановить Монику

@ Грифон Я исправил ошибки. (удалил сам, добавил ссылку lost_against_mapи исправил проверку if, если честный раунд)
coolioasjulio

0
import random
def trustingRandom(a,b,c,d):
  move = random.choice(["R","P","S"])
  if c == "R":
    move = "P"
  elif c == "P":
    move = "S"
  elif c == "S":
    move = "R"
  return move

0

усреднитель

def averager(op, mp, od, md):
  import random
  if od == md == None:
    if op == mp == []:
      return random.choice('RPS')
    else:
      opa = [i[1] for i in op]
      copa = [opa.count(i) for i in 'RPS']
      copam = [i for i, j in zip('RPS', copa) if j == max(copa)]
      opd = [i[0] for i in op]
      copd = [opd.count(i) for i in 'RPS']
      copm = [i for i, j in zip('RPS', copd) if j == max(copd) and i in copam]
      return random.choice(copam if copm == [] else copm)
  else:
    if op == mp == []:
      return md
    else:
      hop = sum([1. if i[0] == i[1] else 0. for i in op]) / len(op)
      hmp = sum([1. if i[0] == i[1] else 0. for i in mp]) / len(mp)
      return 'PSR'['RPS'.index(od)] if hmp >= 0.75 and hop >= 0.50 else md

0

Просто немного лучше, чем моя предыдущая запись ...

def learningbot4(yourlist,mylist,you,me):
  CHECK={"R":{"R":0,"P":1,"S":-1},"P":{"R":-1,"P":0,"S":1},"S":{"R":1,"P":-1,"S":0}}
  results={None:{"R":0,"P":0,"S":0},"R":{"R":0,"P":0,"S":0},"P":{"R":0,"P":0,"S":0},"S":{"R":0,"P":0,"S":0}}
  for i in range(len(yourlist)):
    res=CHECK[yourlist[i][1]][mylist[i][1]]
    if mylist[i][0]==mylist[i][1]: res+=0.5
    results[yourlist[i][0]][mylist[i][1]]+=res
    results[None][mylist[i][0]]+=res
  return max(results[you],key=results[you].get)

0

csbot на стероидах

Я думаю, что предложение, которое @ user1502040 делает в комментариях, должно следовать. В противном случае у этого бота было бы преимущество, которое я бы счел несправедливым. Я представляю это так, чтобы можно было оценить разницу, которую он имеет. При предложенном случайном посеве стероиды будут нейтрализованы, а бот будет эквивалентен csbot, поэтому в соревновании должен участвовать только один.

from random import seed
from csbot import csbot

def csbot_on_steroids(ophist,myhist,opdecl,mydecl):
  seed()
  m = csbot(ophist,myhist,opdecl,mydecl)
  seed(0)
  return m
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.