Uczciwy kamień, papier, nożyczki

58

Wiele osób uważa RPS za grę losową. Jeśli obaj gracze grają nieprzewidywalnie, najlepszą strategią jest gra losowa. Wprowadźmy jednak trochę przewidywalności.

Każdy bot będzie miał okazję powiedzieć drugiemu botowi, co będzie grał jednocześnie. Następnie następuje przerwa, w której każdy bot będzie wiedział, co ogłosił drugi gracz. Jeśli zagra tą bronią, którą ogłosi, zdobędzie jeden punkt oprócz punktów za przegraną lub remis.

Wygrana jest warta dwa punkty, remis, jeden punkt, a przegrana 0 punktów.

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

W twoim najlepszym interesie jest bycie uczciwym (ale także upewnienie się, że przeciwnik ci nie wierzy).

Mecze będą rozgrywane w formacie round robin, a celem będzie zmaksymalizowanie własnego wyniku w meczach, w które grasz.

Format we / wy:

  • Twój bot będzie funkcją Python 2.7, która pobiera 4 argumenty i musi mieć unikalną nazwę (która będzie używana do przedstawienia twojego przesłania).
  • Pierwsze dwa argumenty zawsze będą w kolejności: przeszłe ruchy przeciwnika, a następnie poprzednie ruchy. Będzie to lista w kolejności od pierwszej do ostatniej rundy, przy czym każdy indeks będzie zawierał listę ruchów, o których twierdził przeciwnik, a następnie ruch, który faktycznie wykonali.
  • Następne dwa argumenty pozwolą Twojemu botowi ustalić, czy jest to runda „uczciwa”, czy „prawdziwa”. Jeśli jest to „uczciwa” runda, obie będą Żadne. Jeśli jest to „prawdziwa” runda, będą to kolejno ruch, który zadeklarował twój przeciwnik, a następnie ruch, który zadeklarujesz, że wykonasz.
  • Wszystkie argumenty lub części argumentów, które reprezentują ruchy, będą używać odpowiednio „R”, „P” i „S” do przedstawienia odpowiednio kamienia, papieru i nożyczek.
  • Twoja funkcja powinna zwracać albo „R” dla kamienia, „P” dla papieru lub „S” dla nożyczek. Boty, które mogą zwracać inne wartości, zostaną zdyskwalifikowane.
  • Każdy bot zostanie uruchomiony przeciwko każdemu drugiemu botowi 200 razy, a sam 100 razy. Celem jest bycie botem z największą liczbą punktów na koniec zawodów.
  • W odniesieniu do dyskusji w komentarzach, zgłoszenia nie mogą odczytywać ani zapisywać żadnych plików, ani w żaden sposób sabotować ani odczytywać kodu przeciwnika.

Przykłady:

Są to cztery przykładowe boty, które szybko zestawiłem. Dołączą do konkursu jako dodatkowe boty. Jeśli przegrasz do ostatniego, masz trochę do zrobienia.

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"])

Kontroler:

A oto kontroler, którego będę używać. Nowe zgłoszenia zostaną zaimportowane na początku i dodane do słownika 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

Ostateczne wyniki:

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
Gryphon - Przywróć Monikę
źródło
1
Jaki jest status
user1502040,

Odpowiedzi:

11

Mason

Próbuje zebrać informacje o innych botach, takie jak ich uczciwość i wpływ, jaki wywarł na nich mój pierwszy ruch. Następnie próbuję znaleźć inne oczywiste boty, które podążają za tym wzorem, i wykorzystuję je, by dać mi więcej punktów. Wreszcie, Mason ma tajną broń: wiedzę o tajnym stowarzyszeniu, w którym oba boty biorące udział w sobie biorą udział w pełnym losowaniu, zdobywając po 500 punktów każdy. Niestety, sekret jest raczej ... Dobrze tajny i zmienia się za każdym razem, gdy robi to Mason.

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
niebieski
źródło
9

Rlbot: nauka wzmocnienia

Wykorzystuje podejście uczenia się wzmacniającego, rozwiązując tę ​​grę w sposób podobny do problemu n-uzbrojonego bandyty. Robi to na dwa sposoby: próbuje dowiedzieć się, która deklaracja jest lepsza dla każdego przeciwnika i trzyma się tego (przydatny w przypadku stałych botów), i próbuje poznać wyniki różnych ruchów w poprzednich podobnych sytuacjach (podobnie w odniesieniu do względnych zagrań , np. kamień kontra papier jest podobny do poprzedniego papieru kontra nożyce). Początkowe założenia są optymistyczne, więc ten gracz będzie zakładał, że uczciwość da mu 3 punkty, a kłamstwo da 2, a zatem zawsze będzie uczciwy, dopóki nie zostanie udowodnione inaczej.

Aktualizacja: Wyniki pierwszego turnieju uwidoczniły problem z tym botem, którym była niemożność wykrycia wzorców w deklaracjach przeciwników (co spowodowało, że grał on nieoptymalnie przeciwko rotatorom). Następnie dodałem do kodu element dopasowujący wzorzec dla uczciwych rund, który używa wyrażenia regularnego, aby wyszukać najdłuższy przyrostek w historii deklaracji przeciwników, który jest obecny gdzieś w tej historii, i jaki ruch został wykonany po tym . Zakładamy, że przeciwnik ponownie wykona ten sam ruch i użyje uczenia wzmacniającego jak wcześniej, aby zdecydować, jaka powinna być najlepsza odpowiedź.

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

Wypróbuj online!

Lew
źródło
6

Nigdy tak naprawdę nie używałem Pythona, więc jestem pewien, że gdzieś popełniłem błąd.

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

Powinien sprawdzić ostatnie 10 rund, aby zobaczyć, jak często kłamał przeciwnik, a następnie wybrać inną odpowiedź w zależności od tego.

12Me21
źródło
6

Oto mój adaptacyjny bot. Analizuje 2 ostatnie ruchy przeciwnika, aby ustalić, czy jest to uczciwy bot, czy nie, i gra odpowiednio:

Edycja 1: Jeśli drugi bot jest stałym botem (tzn. Zawsze gra tą samą bronią), ten bot miażdży go, grając zwycięską bronią i jednocześnie będąc szczerym.

Edycja 2: Ulepszony stały wykrywacz botów do pracy z botami rotatorowymi.

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
Selcuk
źródło
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]

Bądź szczery, dopóki jest inny gracz, i wykrywaj proste deterministyczne boty. Zagraj w ruch, który maksymalizuje oczekiwaną wartość, w którym głównie zbieramy nasze punkty, ale także nie chcemy dawać punktów drugiemu graczowi. Ale własne punkty są lepsze dziesięciokrotnie, stąd niezwykłe liczby w valuefunkcji. Ruchy przeciwnika są oczekiwane w zależności od tego, jak często je widzieliśmy w tej sytuacji (ruchy zadeklarowane), ale ostatnio widziane ruchy są ważone bardziej niż ruchy widziane wcześniej. W przypadku losowych początkowych ruchów (sytuacje, których nigdy wcześniej nie widziałem) i dodatkowego rozmycia, wagi obejmują małe dodatkowe losowe liczby.

Aktualizacja: Używaj oczekiwanych wyników także w uczciwej rundzie. Aby móc to zrobić, znormalizować i wziąć dodatkowy punkt, który przeciwnik może uzyskać za uczciwość - nie mógł wpłynąć na naszą decyzję w prawdziwej rundzie, ale jest teraz potrzebny. Zastanawiałem się nad zrobieniem tego od samego początku, ale niesłusznie pomyślałem, że nie będzie to opłacalne. Widziałem, że można dać trusting_botmniej punktów (ale ten bot i tak nie jest silnym przeciwnikiem), ale przegapiłem, że dodatkowe punkty można zdobyć rockbotdzięki dobrej grze w uczciwej rundzie, chociaż jej gra w tej rundzie jest losowa.

Christian Sievers
źródło
To nie zawsze wydaje się zwracać wynik.
user1502040,
Myślę, że twój if mydecl == None:jest błędny.
user1502040,
@ user1502040 Dlaczego tak uważasz? Nigdy nie zaobserwowałem żadnego problemu.
Christian Sievers
@ChristianSievers stackoverflow.com/questions/3257919/…
Selcuk
4

Zdrada

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

Chodzi o to, że przez pierwsze 50 ruchów gram uczciwie, a potem, gdy już skłaniam przeciwnika do myślenia, że ​​jestem uczciwy, graj nieuczciwie, próbując zagrać w coś, co przeciwstawi się temu, co przeciwnik zagra (na podstawie tego, czy był uczciwy czy nieuczciwy w przeszłości). Kiedy dochodzę do punktu, w którym grałem tak często uczciwie niż nieuczciwie, zmieniam taktykę i wybieram najbardziej prawdopodobny ruch przeciwnika na podstawie poprzednich znanych konfiguracji.

plannapus
źródło
3
import random
def honestrandom(a, b, c, move):
    if move == None:
        return random.choice(["R","P","S"])
    return move
Steadybox
źródło
3

Nazwa bota: I Remember How You Lie

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

Testowany na kilka 100-rundowych przebiegów i okazało się, że zwycięzca osiąga średnio około 220 punktów. Myślę, że raczej szczerze;)

Po raz pierwszy biorę udział w wyzwaniach KOTH, więc myślę, że wciąż jest miejsce na ulepszenia

Shieru Asakoto
źródło
3

Wet za wet

Klasyczny zawodnik Axelrodian: pełen nadziei, ale małostkowy; proste, ale solidne. To nie jest Dylemat Więźnia i nie próbowałem przewidzieć ruchu przeciwnika, więc bardzo wątpię, czy będzie on naprawdę konkurencyjny. Ale „kooperacja” nadal generuje najbardziej ogólne punkty dla zawodników, więc myślę, że przynajmniej zrobi to średnio.

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'])
stellatedHexahedron
źródło
3

Dwie trzecie

Wykorzystuje strategię, o której wspomniał Peter Taylor w piaskownicy i w tym komentarzu .

Wykorzystuje równowagę Nasha .

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
mbomb007
źródło
To dla mnie błędy. W linii 13 zwróć losowy wybór (ruchy). Myślę, że to prawdopodobnie dlatego, że używasz .choice w słowniku. Dopóki to nie zostanie naprawione, obawiam się, że to zgłoszenie jest nieprawidłowe.
Gryphon - Przywróć Monikę
@Gryphon To nie jest słownik, to zestaw.
LyricLy,
O przepraszam. Właśnie zobaczyłem nawiasy klamrowe i pomyślałem „słownik”. Mój błąd. Wiesz jakiś pomysł, dlaczego los.choice popełnił błąd w tym wierszu?
Gryphon - Przywróć Monikę
@Gryphon Wygląda na to, że random.choicepolega na wybraniu losowego numeru indeksu, a następnie zwróceniu obiektu na liście pod tym indeksem. Ponieważ zestawy nie mają kolejności, nie obsługują także indeksowania i dlatego nie działają random.choice. Prostym rozwiązaniem byłoby przeniesienie zestawu na listę przed wywołaniem random.choice.
LyricLy,
Ach Nie mam Pythona na tym komputerze, więc nie mogę tego teraz naprawić, ale poprawię to w kodzie, kiedy wrócę do domu. Jeśli @ mbomb007 naprawi to tutaj, byłoby świetnie.
Gryphon - Przywróć Monikę
3

Głęboka myśl

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

Kilka uwag na ten temat:

  • DeepThought lubi myśleć. Dużo. Przykro mi z tego powodu, ale tak naprawdę nie wiem, jak to naprawić. Obwiniam Python.
  • DeepThought stara się być szczery. Beeing uczciwy zapewnia jeden dodatkowy punkt, który jest taki sam, jak oczekiwana wartość dla normale RPS
  • Ale: DeepThought dostaje średnio ponad 2 punkty na grę. Używa detekcji, aby znaleźć pewne typowe zachowania (takie jak oszukiwanie, uczciwość itp.) I dostosowuje się do tego.
  • DeepThought jest czysto deterministyczny, więc będzie czerpał z siebie, ponieważ zawsze dokona tej samej decyzji na obu końcach.
  • Aby się nie kłamać, ma specjalne wykrywanie, podobnie jak niektóre inne boty tutaj. Jest to bardzo agresywne, nawet zakładając, że jest prawdą po jednej rundzie (a także w pierwszej rundzie). Zasadniczo, dopóki ruchy przeciwnika są dokładnie moje, zakładam, że jest to odbicie lustrzane.
  • Interesującą częścią (i tą, która ma dziesiątki fałszywie dodatnich wyników) jest sprawdzenie deterministycznego bota, który zależy tylko od własnego wcześniejszego wyniku. To sprawdzenie szuka dowolnego wzorca wielkości n, który powtarza się dwukrotnie i który może opisywać ostatnie n-1 ruchy, przewidywać roszczenia przeciwnika i poruszać się z wyprzedzeniem. Ta część zajmuje niestety trochę czasu.

Jestem nowy zarówno dla Kotha, jak i Pythona, więc powiedz mi, czy coś pomieszałem w tym bocie. Nie sądzę, że może pokonać naukę wzmocnioną (ponieważ myślę, że zbyt szybko nauczy się moich ruchów), ale spróbujmy.

Podoba mi się to wyzwanie, a jeśli znajdę trochę czasu, chciałbym dodać organiczną metodę obliczeniową (choć może być zbyt mała presja na wyższe wymiary). Czy można dodawać wiele sugestii? A może zabrania się przejmowania głównego bota przez wstawianie takich, które mają jedynie na celu przegrywanie z głównym botem?

EDYCJA: Naprawiono literówkę, która sprawiała, że ​​nie mówiłem po angielsku

alex berne
źródło
Publikowanie wielu wpisów nie jest zabronione, ale zabronione jest publikowanie wpisu, który podpiera innego bota (nawet takiego, który nie należy do Ciebie). Można przegrać z innym botem, o ile nie jest to zgodne z projektem.
Gryphon - Przywróć Monikę
Wystąpił błąd podczas uruchamiania tego, ponieważ 32. linia funkcji DeepThought return resultwymaga dodatkowego wcięcia. Uważam, że powinna znajdować się wewnątrz gigantycznej instrukcji if, która następuje zaraz po niej, ponieważ zmienna returnjest deklarowana tylko w tym, że instrukcja. Dokonałem tej modyfikacji w moim kodzie i teraz działa ona bezbłędnie. Jeśli nie miałbyś nic przeciwko wprowadzeniu tej zmiany tutaj, byłoby świetnie.
Gryphon - Przywróć Monikę
3
Wygląda na to, że mieszasz się ze stanem globalnego generatora losowego, co prawdopodobnie nie jest w porządku. Uważałem robi coś podobnego, i znalazłem to rozwiązanie: utworzyć nowy obiekt z losową R=random.Random(seed)i używać go tak: R.choice(...).
Christian Sievers,
@Gryphon naprawiony. Prawdopodobnie niektóre błędy, które wystąpiły podczas transformacji z mojego lokalnego skryptu na se, gdzie wszystko musi zostać wykryte jeszcze jeden raz
alex berne
1
@alexberne Możesz wybrać wklejony kod i kliknąć {}przycisk na pasku narzędzi, aby automatycznie wciąć każdą linię.
Selcuk,
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])
użytkownik5957401
źródło
2

have_we_been_here_before

Po prostu pyta „byliśmy tu wcześniej” i wybiera ruch, który dałby najlepszy średni wynik we wszystkich poprzednich grach.

Edycja: Klub uczciwości. Dodałem mały blok kodu, ponieważ inny bot (mason) zrobił bardzo dobrze, tworząc ze sobą tajny klub. Zauważ jednak, że uczciwa gra przeciwko uczciwym przeciwnikom przynosi średnio dokładnie taką samą wypłatę, gdy gra się przeciwko sobie, a może być może są też szersze wzajemne korzyści?

Edycja2: W momencie pisania dwóch botów przede mną, oba wykorzystują rotatory, więc dodam kolejny blok kodu, aby wskoczyć również na ten bandwagon. Wydaje mi się, że mój kod musi wydawać się dość oldschoolowy - trzymać się znanych konstruktów znalezionych w dowolnym języku programowania, ponieważ tak naprawdę nie znam 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)
Antony
źródło
2

THEbot: uczciwy odkrywca

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
Cinaski
źródło
Właśnie zdałem sobie sprawę, że przegłosowałem przez błędne kliknięcie, przepraszam. Cofnie się podczas edycji. (Nie można tego zmienić inaczej)
Christian Sievers
@ChristianSievers edytowane
Cinaski
@ChristianSievers dziękuję!
Cinaski,
2

Thompson

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]
użytkownik1502040
źródło
Ciekawy wpis. Niedługo go uruchomię, powinien być w stanie opublikować wyniki po południu.
Gryphon - Przywróć Monikę
OK, lekko zmieniłem parametry.
user1502040,
Rozumiem. Przepraszam, że aktualizacja trwa tak długo, po prostu, za każdym razem, gdy jest już prawie skończona, ktoś aktualizuje swojego bota lub dostaję nowego i muszę go uruchomić ponownie.
Gryphon - Przywróć Monikę
@Gryphon możesz przechowywać tabelę wyników wszystkich par, więc kiedy bot zostanie zaktualizowany, musisz uruchomić tylko 200 * (num_bots - 1) + 100 nowych dopasowań.
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

Spróbuję prostego bota, który w tych warunkach przerwie ostatnią grę przeciwnika

Guillaume Pagès
źródło
Witamy w PPCG!
Martin Ender
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]

Chodzi o to, aby zmaksymalizować wynik podczas gry w siebie, a jednocześnie być losowo konkurencyjnym na innych etapach przeciwko innym złym botom.

Stephen
źródło
1
Słowo isjest słowem kluczowym, dlatego jest nieprawidłowe.
Erik the Outgolfer
@EriktheOutgolfer dzięki :)
Stephen
1

Dx

Napisałem tylko tego bota, więc mogę mieć buźkę w nazwie bota 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]]])
Roman Gräf
źródło
1

Wszyscy kłamią

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"

Kłamie o swoim ruchu („Będę grał w nożyczki!”) I zakłada, że ​​przeciwnik też kłamał i że spróbują pokonać to, co powiedziałem, że mój ruch to („hmm, Rock bije nożyczki, więc gram że ”), ale tak naprawdę gram ruch, który bije ten ruch („ Paper! Surprise! ”).

Nie drzewo
źródło
3
Dla mnie brzmi to jak pierwszy poziom strategii Iocaine Powder :-) „Sprytny człowiek umieściłby truciznę we własnej kielichu, ponieważ wiedziałby, że tylko wielki głupiec sięgnąłby po to, co mu dano. Nie jestem wielki głupiec, więc wyraźnie nie mogę wybrać wina przed tobą. Ale musiałeś wiedzieć, że nie byłem wielkim głupcem, na to liczyłeś, więc wyraźnie nie mogę wybrać wina przede mną ... . ”
Antony
1

Zaufanie Botowi

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

Zawsze twierdzi, że rzuca nożyczkami, ale zrobi wszystko, co bije to, co powiedział przeciwnik. Rzetelnie rysuje sam ze sobą.

ATaco
źródło
Byłoby to bardziej skuteczne, gdyby zawsze było uczciwe wobec samego siebie.
Gryphon - Przywróć Monikę
@Gryphon Prawdopodobnie, ale nie pytam wystarczająco dobrze, aby spróbować stworzyć coś, co tak będzie współpracowało.
ATaco
Nieważne więc.
Gryphon - Przywróć Monikę
1

Nazwa bota: Liar Liar

Nie mogę przestać kłamać.

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)
Juan Ferrer
źródło
1

RockBot

Zakłada, że ​​przeciwnik będzie uczciwy i spróbuje go pokonać, ale nie chce grać w rock.

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"])
Slepz
źródło
1
To wydaje się błędne, ponieważ w ostatnim wierszu „P”, „S” nie znajduje się w nawiasach kwadratowych (nie na liście). Zmieniłem to w mojej wersji, ale jeśli mógłbyś zrobić to samo tutaj, byłoby świetnie. Dzięki.
Gryphon - Przywróć Monikę
Czy to nie okropnie przegra z ciągłymi nożyczkami?
Wildcard
@Wildcard tak, ale poradzi sobie całkiem dobrze z papierowym botem
Slepz
1

Nazwa bota: dontlietome

Określa, czy przeciwnik kłamie, czy nie, w zależności od tego, ile razy przeciwnik kłamał w ostatnich 10 rundach. Wybiera ruch w zależności od tego, czy przeciwnik kłamie, czy nie. Jeśli przeciwnik jest zdeterminowany, by kłamać, wówczas zagrywa podpowiedź.

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
coolioasjulio
źródło
W wierszu „if is_trustworthy (opp_moves, self.length):”, self nie jest zdefiniowane. Dodatkowo, w linii „return lose_against_map [opp_hint]”, lose_against_map również nie jest zdefiniowane. Długość siebie wydaje się być rozwiązana przez usunięcie ja. ale drugi problem nadal występuje. Dopóki to nie zostanie naprawione, obawiam się, że jest to nieważne.
Gryphon - Przywróć Monikę
Ups, napisałem to przy użyciu obiektu i zapomniałem usunąć niektóre odnośniki i w pełni skopiować kod. Naprawię je, jak tylko wrócę do domu.
coolioasjulio
DOBRZE. Jeśli jest to tylko mały błąd, naprawiam go (tak jak w przypadku niektórych innych botów, i zrobiłbym to, gdyby to był sam problem.), Ale brakująca funkcja to inna historia.
Gryphon - Przywróć Monikę
@Gryphon Naprawiłem błędy. (usunął ja, dodał odnośnik lost_against_mapi naprawił instrukcję if sprawdzającą, czy uczciwa runda)
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
KSmarts
źródło
0

Uśrednianie

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
Erik the Outgolfer
źródło
0

Tylko trochę lepiej niż mój poprzedni wpis ...

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)
12Me21
źródło
0

csbot na sterydach

Myślę, że należy postępować zgodnie z sugestią @ user1502040 zawartą w komentarzach. W przeciwnym razie ten bot miałby przewagę, którą uważałbym za niesprawiedliwą. Przedkładam to, aby można było ocenić różnicę, którą powoduje. Przy sugerowanym losowym wysiewie sterydy zostaną zneutralizowane, a bot będzie równoważny csbot, więc tylko jeden powinien wziąć udział w konkursie.

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
Christian Sievers
źródło