Roccia onesta, carta, forbici


58

Molte persone considerano l'RPS un gioco d'azzardo. Se entrambi i giocatori giocano in modo imprevedibile, la strategia migliore è quella di giocare in modo casuale. Tuttavia, introduciamo un po 'di prevedibilità ad esso.

Ogni bot avrà la possibilità di dire all'altro bot cosa giocherà contemporaneamente. Poi c'è una pausa in cui ogni bot saprà cosa ha annunciato l'altro giocatore. Se gioca quell'arma ha annunciato che segnerà un punto in aggiunta ai suoi punti per una vittoria o un pareggio.

Una vittoria vale due punti, un pareggio, un punto e una perdita di 0 punti.

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

È nel tuo interesse essere sincero (ma anche assicurarti che il tuo avversario non ti creda).

Le partite si giocheranno in un formato round robin e l'obiettivo sarà quello di massimizzare il tuo punteggio totale in tutte le partite che giochi.

Formato I / O:

  • Il bot sarà una funzione Python 2.7 che accetta 4 argomenti e deve avere un nome univoco (che verrà utilizzato per rappresentare l'invio).
  • I primi due argomenti saranno sempre, in ordine: le mosse passate dell'avversario, seguite dalle tue mosse passate. Questa sarà una lista in ordine dal primo al round più recente, con ogni indice contenente una lista con la mossa che l'avversario ha dichiarato di voler fare, seguita dalla mossa che ha effettivamente fatto.
  • I prossimi due argomenti permetteranno al tuo bot di determinare se si tratta di un round "onesto" o di un round "reale". Se si tratta di un round "onesto", entrambi saranno Nessuno. Se si tratta di un round "reale", saranno, nell'ordine, la mossa dichiarata dal tuo avversario, seguita dalla mossa che hai dichiarato di voler fare.
  • Tutti gli argomenti o parti di argomenti che rappresentano le mosse useranno "R", "P" e "S" per rappresentare rispettivamente roccia, carta e forbici.
  • La tua funzione dovrebbe restituire una "R" per il rock, una "P" per la carta o una "S" per le forbici. I robot che hanno la capacità di restituire altri valori saranno squalificati.
  • Ogni bot verrà eseguito contro ogni altro bot 200 volte e 100 volte stesso. L'obiettivo è quello di essere il bot con il maggior numero di punti alla fine della competizione.
  • Per quanto riguarda la discussione nei commenti, gli invii non possono leggere o scrivere su alcun file, né in alcun modo sabotare o leggere il codice dell'avversario.

Esempi:

Questi sono quattro robot di esempio che ho messo insieme rapidamente. Si uniranno alla competizione come bot aggiuntivi. Se perdi l'ultimo, hai del lavoro da fare.

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

controller:

Ed ecco il controller che userò. I nuovi invii verranno importati all'inizio e aggiunti al dizionario 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

Punteggi finali:

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
Qual è lo stato?
user1502040

Risposte:


11

Muratore

Cerca di raccogliere informazioni su altri robot come quanto sono onesti e come vengono effettuati dalla mia prima mossa. Poi provo a trovare altri robot evidenti che seguono uno schema e li sfruttano per darmi più punti. Infine, il Mason ha un'arma segreta: conoscenza di una società segreta in cui entrambi i robot partecipanti si danno reciprocamente un pareggio completo, guadagnando 500 punti ciascuno. Sfortunatamente il segreto è piuttosto ... Bene segreto e cambia ogni volta che lo fa il muratore.

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: apprendimento di rinforzo

Utilizza un approccio di apprendimento di rinforzo, affrontando questo gioco in modo simile al problema dei banditi n-armati. Lo fa in due modi: cerca di imparare quale dichiarazione è migliore contro ogni avversario e si attacca a quella (utile contro i robot costanti), e cerca di imparare il risultato di varie mosse in precedenti situazioni simili (simili per quanto riguarda le giocate relative , ad esempio rock vs paper è simile a un precedente paper vs scissor). Le ipotesi iniziali sono ottimistiche, quindi questo giocatore supporrà che essere onesti gli darà 3 punti e mentire darà 2, e quindi sarà sempre onesto fino a prova contraria.

Aggiornamento: I primi risultati del torneo hanno evidenziato un problema con questo bot, che era la sua incapacità di rilevare schemi nelle dichiarazioni dei suoi avversari (che lo ha fatto giocare in modo subottimale contro i rotatori). Ho quindi aggiunto un codice di corrispondenza del modello al codice per i round onesti, che utilizza una regex per cercare il suffisso più lungo nella storia delle dichiarazioni degli avversari che è presente da qualche parte in precedenza in quella storia e quale mossa è stata giocata dopo . Partiamo dal presupposto che l'avversario giocherà di nuovo la stessa mossa e useremo l'apprendimento per rinforzo di prima per decidere quale dovrebbe essere la migliore risposta.

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

Provalo online!


6

Non ho mai usato molto Python, quindi sono sicuro di aver fatto un errore da qualche parte.

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

Dovrebbe controllare gli ultimi 10 round per vedere quanto spesso l'avversario ha mentito, quindi ha scelto una risposta diversa a seconda di ciò.


6

Ecco il mio robot adattivo. Analizza le ultime 2 mosse dell'avversario per determinare se si tratta di un bot onesto o meno e gioca di conseguenza:

Modifica 1: Se l'altro robot è un robot costante (cioè gioca sempre la stessa arma), questo robot lo schiaccia giocando l'arma vincente ed essendo onesto allo stesso tempo.

Modifica 2: Rilevatore di bot costante migliorato per funzionare anche con i robot rotatori.

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]

Sii onesto fintanto che è l'altro giocatore e rileva semplici robot deterministici. Gioca la mossa che massimizza il valore atteso, dove principalmente andiamo per i nostri punti, ma anche a non dare punti all'altro giocatore. Ma i propri punti sono migliori di un fattore dieci, quindi i numeri insoliti nella valuefunzione. Sono previste mosse avversarie in base alla frequenza con cui le abbiamo già viste in questa situazione (mosse dichiarate), ma le mosse viste di recente hanno un peso maggiore rispetto alle mosse viste in precedenza. Per le mosse iniziali casuali (situazioni mai viste prima) e un po 'di confusione extra, i pesi includono piccoli numeri casuali extra.

Aggiornamento: usa i risultati previsti anche nel round onesto. Per essere in grado di farlo, normalizza e prendi in considerazione il punto aggiuntivo che l'avversario può ottenere per onestà: non potrebbe influenzare la nostra decisione nel round reale ma è necessario ora. Ho pensato di farlo sin dall'inizio, ma ho erroneamente pensato che non sarebbe valsa la pena. Ho visto che sarebbe stato possibile assegnare trusting_botmeno punti (ma quel bot non è comunque un avversario forte), ma ho perso i punti extra che si potevano ottenere rockbotda una buona giocata nel turno onesto anche se la sua giocata in questo turno è casuale.


Questo non sembra sempre restituire un risultato.
user1502040

Penso che il tuo if mydecl == None:sia errato.
user1502040

@ user1502040 Perché la pensi così? Non ho mai osservato alcun problema.
Christian Sievers,


4

Tradimento

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

L'idea è che per le prime 50 mosse gioco onestamente, e quindi una volta attirato l'avversario nel pensare di essere onesto, gioca in modo disonesto, cercando di giocare ciò che potrebbe contrastare ciò che l'avversario giocherà (basato sul fatto che fosse onesto o disonesto nel passato). Quando raggiungo il punto in cui ho giocato più spesso onestamente che disonestamente, cambio tattica e scelgo la mossa più probabile dell'avversario in base alle precedenti configurazioni conosciute.


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

3

Nome Bot: Ricordo come menti

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

Testato per diverse tirature da 100 round e si è scoperto che il vincitore segna circa 220 in media. Piuttosto onesto penso;)

La prima volta che parteciperò alle sfide di KOTH, quindi penso che ci sia ancora spazio per miglioramenti


3

Tit per Tat

Il classico concorrente axelrodiano: pieno di speranza, ma meschino; semplice ma robusto. Questo non è il dilemma del prigioniero e non ho fatto alcun tentativo di prevedere la mossa dell'avversario, quindi dubito fortemente che sarà veramente competitivo. Ma "cooperare" produce ancora i punti più complessivi per i concorrenti, quindi penso che lo farà almeno in modo mediocre.

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

Due terzi

Utilizza la strategia menzionata da Peter Taylor nella Sandbox e in questo commento .

Usa l' equilibrio di Nash .

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

Questo errore per me. Alla riga 13, restituisci random.choice (mosse). Penso che sia probabilmente perché stai usando .choice su un dizionario. Fino a quando ciò non verrà risolto, temo che questo invio non sia valido.
Gryphon - Ripristina Monica il

@Gryphon Non è un dizionario, è un set.
Lirico

Mi dispiace. Ho appena visto parentesi graffe e pensato "dizionario". Colpa mia. Qualche idea sul perché allora random.choice stia sbagliando su quella linea?
Gryphon - Ripristina Monica il

@Gryphon Sembrerebbe che random.choicesi basi sulla scelta di un numero di indice casuale e sulla restituzione dell'oggetto nell'elenco di tale indice. Poiché i set non hanno un ordine, non supportano l'indicizzazione e quindi non funzionano random.choice. Una semplice soluzione per questo sarebbe quella di lanciare il set in un elenco prima di chiamare random.choice.
Lirico

Ah. Non ho Python su questo computer, quindi non posso risolvere questo problema ora, ma lo riparerò nel mio codice quando torno a casa. Se @ mbomb007 lo risolvesse qui, sarebbe fantastico.
Gryphon - Ripristina Monica il

3

Pensiero profondo

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

Solo alcune note su di esso:

  • A DeepThought piace pensare. Un sacco. Mi dispiace, ma non so davvero come risolverlo. Incolpo Python.
  • DeepThought cerca di essere onesto. Beeing onesto ti fornisce un punto adizionale, che è lo stesso del valore atteso per RPS normale
  • Ma: DeepThought ottiene in media anche più di 2 punti per partita. Usa un po 'di rilevamento per trovare comportamenti comuni (come inganno, essere onesti, ecc.), E si adatta in base a ciò.
  • DeepThought è puramente deterministico, quindi attirerà contro se stesso, perché farà sempre la stessa decisione su entrambe le estremità.
  • Per essere sicuro di non mentire contro se stesso, ha un rilevamento speciale, come anche alcuni altri robot qui. Questo è molto aggressivo, anche assumendo che sia vero dopo un round (e anche nel primo round). Fondamentalmente, fintanto che le mosse dell'avversario sono esattamente mie, supporrò che sia una partita speculare.
  • La parte interessante (e la parte che ha dozzine di falsi positivi) è la verifica di un bot deterministico, che dipende solo dal proprio risultato precedente. Tale controllo cerca qualsiasi modello di dimensione n, che si ripete due volte e che potrebbe descrivere le ultime mosse n-1, prevedere il reclamo dell'avversario e muovere in anticipo. Questa parte richiede del tempo, purtroppo.

Sono nuovo di entrambi, Koth e Python, quindi dimmi se ho sbagliato qualcosa in questo bot. Non penso che possa battere l'apprendimento rinforzato (perché immagino che imparerà le mie mosse troppo rapidamente), ma proviamo.

Mi piace questa sfida, e se trovo un po 'di tempo, vorrei aggiungere un approccio di calcolo organico (anche se potrebbe esserci una pressione troppo ridotta sulle dimensioni più elevate). È consentito aggiungere più suggerimenti? O è vietato prevenire il booting del tuo bot principale inserendone alcuni che mirano solo a perdere il tuo primario?

EDIT: fisso errore di battitura che mi caratterizzava come un madrelingua inglese


Non è vietato pubblicare più voci, ma è vietato pubblicare una voce che sostiene un bot diverso (anche uno che non è il tuo). Va bene perdere un altro bot, purché non sia progettato.
Gryphon - Ripristina Monica il

Si è verificato un errore durante l'esecuzione, poiché la 32a riga della funzione DeepThought return resultrichiede un rientro aggiuntivo. Credo che dovrebbe essere all'interno della gigantesca istruzione if subito dopo, poiché la variabile returnè dichiarata solo in quella istruzione. Ho apportato questa modifica nel mio codice e ora funziona senza errori. Se non ti dispiacerebbe apportare questo cambiamento qui, sarebbe fantastico.
Gryphon - Ripristina Monica il

3
Sembra che tu stia scherzando con lo stato del generatore casuale globale, che probabilmente non va bene. Ho pensato di fare una cosa simile, e ho trovato questa soluzione: creare un nuovo oggetto casuale R=random.Random(seed)e usarlo in questo modo: R.choice(...).
Christian Sievers,

@Gryphon fixed. Probabilmente alcuni errori che si sono verificati durante la trasformazione dalla mia sceneggiatura locale in se, dove ogni cosa deve essere intentata un'altra volta
alex berne,

1
@alexberne È possibile selezionare il codice incollato e fare clic sul {}pulsante sulla barra degli strumenti per rientrare automaticamente in ogni riga.
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])

2

have_we_been_here_before

Chiede semplicemente "siamo già stati qui prima" e sceglie la mossa che avrebbe dato il miglior risultato medio in una di queste partite precedenti.

Modifica: Honesty Club. Ho aggiunto un piccolo blocco di codice perché un altro bot (muratore) ha fatto molto bene formando un club segreto con se stesso. Si noti tuttavia che giocare onestamente contro avversari onesti ha in media esattamente lo stesso guadagno quando si gioca contro se stessi, e forse ci sono anche benefici reciproci più ampi da avere?

Edit2: Al momento in cui scrivo i due robot davanti a me entrambi sfruttano i rotatori, quindi aggiungerò un altro blocco di codice per saltare anche su quel carrozzone. Immagino che il mio codice debba sembrare piuttosto vecchia scuola, attenendosi a costrutti familiari trovati in qualsiasi linguaggio di programmazione perché in realtà non conosco 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: THE Honest Exploiter

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

Mi sono appena reso conto di aver effettuato il downgrade del voto per errore, mi dispiace. Annulla quando si modifica. (Non posso cambiarlo altrimenti).
Christian Sievers,

@ChristianSievers modificato
Cinaski il

@ChristianSievers grazie!
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]

Ingresso interessante. Lo eseguirò presto, dovrei riuscire a pubblicare i risultati questo pomeriggio.
Gryphon - Ripristina Monica l'

OK, ho leggermente modificato i parametri.
user1502040

Fatto. Mi dispiace che l'aggiornamento richieda così tanto tempo, è solo che ogni volta che è quasi finito, qualcuno aggiorna il proprio bot o ne ottengo uno nuovo e devo eseguirlo di nuovo.
Gryphon - Ripristina Monica il

@Gryphon potresti tenere una tabella dei risultati di tutte le coppie, quindi quando un bot viene aggiornato devi solo eseguire 200 * (num_bots - 1) + 100 nuove partite.
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

Proverò un semplice bot che rifare l'ultimo gioco del suo avversario in queste condizioni


Benvenuti in 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]

L'idea qui è quella di massimizzare il punteggio mentre si gioca da soli, pur essendo casualmente competitivo durante altre fasi contro altri robot cattivi.


1
La parola isè una parola chiave, quindi non è valida.
Erik the Outgolfer,

@EriktheOutgolfer ringrazia :)
Stephen,

1

Dx

Ho scritto solo questo bot in modo da poter avere una faccina nel mio nome bot 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

Tutti mentono

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"

Riguarda la sua mossa ("Giocherò con le forbici!"), E presume che anche l'avversario stesse mentendo e che proveranno a battere quello che ho detto che la mia mossa sarebbe ("hmm, Rock batte Scissors quindi sto giocando che "), ma in realtà gioco la mossa che batte quella mossa (" Carta! Sorpresa! ").


3
Mi sembra il primo livello della strategia della polvere di Iocaina :-) "Ora, un uomo intelligente metterebbe il veleno nel suo calice, perché saprebbe che solo un grande sciocco avrebbe raggiunto ciò che gli era stato dato. un grande sciocco, quindi chiaramente non posso scegliere il vino di fronte a te. Ma devi aver saputo che non ero un grande sciocco, ci avresti contato, quindi chiaramente non posso scegliere il vino di fronte a me .. "
Antony,

1

Trusting Bot

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

Afferma sempre di lanciare le forbici, ma farà qualunque cosa batte ciò che l'avversario ha detto. Disegnerà in modo affidabile con se stesso.


Ciò sarebbe più efficace se fosse sempre onesto con se stesso.
Gryphon - Ripristina Monica il

@Gryphon Probabilmente, ma non ho abbastanza pitone da voler provare a fare qualcosa che coopera così.
ATaco,

Non importa allora.
Gryphon - Ripristina Monica il

1

Nome del bot: bugiardo bugiardo

Non riesco a smettere di mentire.

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

Presuppone che l'avversario sarà onesto e cerca di batterli, ma rifiuta di suonare il 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"])

1
Questo sembra errore perché, nell'ultima riga, "P", "S" non è racchiuso tra parentesi quadre (non un elenco). L'ho cambiato nella mia versione, ma se potessi fare lo stesso qui, sarebbe fantastico. Grazie.
Gryphon - Ripristina Monica il

Questo non perderà orribilmente con le forbici costanti?
Wildcard il

@Wildcard sì, ma andrà abbastanza bene contro il bot di carta
Slepz,

1

Nome del bot: dontlietome

Determina se l'avversario sta mentendo o meno in base a quante volte l'avversario ha mentito negli ultimi 10 round. Seleziona la mossa a seconda che l'avversario stia mentendo o meno. Se l'avversario è determinato a mentire, allora gioca quale suggerimento era.

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

Nella riga "if is_trustworthy (opp_moves, self.length):", self non è definito. Inoltre, nella riga "return L'auto-lunghezza sembra essere risolta rimuovendo l'io. ma l'altro problema persiste. Fino a quando non sarà risolto, temo che non sia valido.
Gryphon - Ripristina Monica il

Oops L'ho scritto usando un oggetto e ho dimenticato di rimuovere alcuni riferimenti automatici e di copiare completamente il codice. Li sistemerò non appena torno a casa.
coolioasjulio,

OK. Se è solo un piccolo errore, lo correggo (come ho fatto in altri robot, e lo farei se fosse solo un problema personale), ma una funzione mancante è una storia diversa.
Gryphon - Ripristina Monica il

@Gryphon Ho corretto i bug. (rimosso il sé, aggiunto il riferimento lost_against_mape corretto l'istruzione if verificando se round onesto)
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

Averager

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

Solo un po 'meglio della mia voce precedente ...

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 con steroidi

Penso che il suggerimento che @ user1502040 fa nei commenti dovrebbe essere seguito. Altrimenti questo bot avrebbe un vantaggio che considererei ingiusto. Lo sottopongo in modo tale da poter valutare la differenza che fa. Con il seeding casuale suggerito gli steroidi sarebbero neutralizzati e il bot sarebbe equivalente csbot, quindi solo uno dovrebbe partecipare al concorso.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.