Dilemma del prigioniero v.3 - Petri Dilemma


17

Uno scienziato pazzo ha appena creato una nuova specie di batterio! Ha deciso di nominarlo Noblus Gentlemanus, dopo aver osservato il suo comportamento. Tuttavia, i suoi batteri hanno esaurito il cibo e hanno dichiarato guerra, poiché sono in grado di raccogliere altri cadaveri di batteri per ottenere cibo sufficiente per creare copie di se stessi. Esistono diverse sottospecie di questo batterio, che hanno strategie diverse nel giocare a Prisoner's Dilemma, il loro gioco preferito. Esistono cinque batteri per ciascuna sottospecie diversa. Nel dilemma del prigioniero, ciascuno dei due giocatori sceglie contemporaneamente il difetto o coopera. Se un giocatore sceglie cooperare e l'altro sceglie il default, il defaulter ottiene 2 punti e il cooperatore perde 3 punti. Se entrambi i giocatori scelgono cooperare, entrambi i giocatori ottengono 1 punto. Se entrambi i giocatori scelgono il valore predefinito, entrambi i giocatori perdono 1 punto.

Essendo Noble Gentlemen, i batteri hanno deciso di combattere questa guerra giocando a 200 round del Dilemma del prigioniero iterato. Il perdente di ogni duello si suiciderà, permettendo al vincitore di clonarsi. In caso di pareggio, entrambi i batteri rimarranno vivi, ma nessuno dei due sarà in grado di clonarsi. Inoltre, tutti i batteri di una partita portano oltre il 10% dei loro punti alla partita successiva. Un clone trasporta le punte del batterio da cui è stato clonato. Inoltre, c'è una possibilità su dieci ogni turno in cui un batterio si trasformerà in un'altra sottospecie, con 0 punti bonus (se ricevo lamentele sulla casualità di questo, posso rimuoverlo). Dopo che i batteri hanno giocato un numero di questi duelli pari al numero di sottospecie di batteri per dieci volte, lo scienziato pazzo rilascia accidentalmente la capsula di Petri in cui risiedono i batteri, e tutti i batteri acquisiscono nuove fonti di cibo, ponendo fine ai loro duelli. Questo è diverso dal normale dilemma del prigioniero iterato in quanto coinvolge duelli 1 contro 1 con punti di riporto, piuttosto che semplicemente tentare di ottenere il maggior numero di punti in generale. Questo fa una grande differenza nell'efficacia di una determinata strategia.

Ogni batterio riceverà input all'inizio del suo turno nel formato: (numero di turno, punti correnti, punti nemici, le tue mosse precedenti [in una stringa, usando il carattere "c" per cooperare e il carattere "d" per difetto ], nemici precedenti mosse [nello stesso formato]).

Ecco quattro strategie di esempio che verranno inserite. In realtà penso che Defector potrebbe vincere, anche se è estremamente semplice.

Tit per Tat

def titfortatfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "c"
    else:
        return "d"

RandomPick

from random import choice
def randompickfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 199:
        return "d"
    else:
        return choice(["d", "c"])

Cooperatore

def cooperatorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "c"

Defector

def defectorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "d"

Tutti gli invii devono essere nella forma di una funzione Python 2.7, con il nome che deve essere il nome dell'invio senza spazi, con funcalla fine. Se qualcuno desidera inviare una risposta in un'altra lingua, inseriscilo in pseudo-codice, per consentirmi di convertire in Python in una modifica alla tua risposta una volta che ho tempo, o di darmi istruzioni su come interfacciare la tua lingua con il mio controller che si trova di seguito impostato per tutte le comunicazioni a partire dal 4 giugno.

from titfortat import titfortatfunc
from randompick import randompickfunc
from cooperator import cooperatorfunc
from defector import defectorfunc
from luckytitfortat import luckytitfortatfunc
from randomtitfortat import randomtitfortatfunc
from remorsefulaggressor import remorsefulaggressorfunc
from everyother import everyotherfunc
from niceguy import niceguyfunc
from titfortatbackstab import titfortatbackstabfunc
from gentleDefector import gentleDefectorfunc
from anticapitalist import anticapitalistfunc
from grimtrigger import grimtriggerfunc
from bizzaro import bizzarofunc
from neoanticapitalist import neoanticapitalistfunc
from bittertat import bittertatfunc
from teamer import teamerfunc
from copyfirst import copyfirstfunc
from exploitivetat import exploitativetatfunc
from defectorv2 import defectorv2func
from crazytat import crazytatfunc
from randomchoicev2 import randomchoicev2func
from twotitsforatat import twotitsforatatfunc
from threetitsforatat import threetitsforatatfunc
from fourtitsforatat import fourtitsforatatfunc
from fivetitsforatat import fivetitsforatatfunc
from sixtitsforatat import sixtitsforatatfunc
from tentitsforatat import tentitsforatatfunc
from theelephant import theelephantfunc
from xbittertat import xbittertatfunc
from fifteentitsforatat import fifteentitsfortatfunc
from twentytitsforatat import twentytitsforatatfunc
from fox import foxfunc
from onehundredfortysixtitsforatat import onehundredfourtysixtitsforatatfunc
from gameofthrones import gameofthronesfunc
from boy import boyfunc
from grimace import grimacefunc
from fiftytitsforatat import fiftytitsfortatfunc
from soreloser import soreloserfunc
from everyotherd import everyotherdfunc
from fiftythreetitsfortat import fiftythreetitsfortatfunc
from twentyfivetitsfortat import twentyfivetitsfortatfunc
from handshake import handshakefunc
from anty import antyfunc
from fiftyfourtitsforatat import fiftyfourtitsfortatfunc
from kindatitsfortat import kindatitsfortatfunc

import random

players = 38

rounds = players*10

def runcode(num, points1, points2, history1, history2, cell):
    ans = ""
    if cell == 0:
        ans = titfortatfunc(num, points1, points2, history1, history2)
    elif cell == 1:
        ans = randompickfunc(num, points1, points2, history1, history2)
    elif cell == 2:
        ans = cooperatorfunc(num, points1, points2, history1, history2)
    elif cell == 3:
        ans = defectorfunc(num, points1, points2, history1, history2)
    elif cell == 4:
        ans = luckytitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 5:
        ans = randomtitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 6:
        ans = remorsefulaggressorfunc(num, points1, points2, history1, history2)
    elif cell == 7:
        ans = everyotherfunc(num, points1, points2, history1, history2)
    elif cell == 8:
        ans = niceguyfunc(num, points1, points2, history1, history2)
    elif cell == 9:
        ans = titfortatbackstabfunc(num, points1, points2, history1, history2)
    elif cell == 10:
        ans = gentleDefectorfunc(num, points1, points2, history1, history2)
    elif cell == 11:
        ans = anticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 12:
        ans = grimtriggerfunc(num, points1, points2, history1, history2)
    elif cell == 13:
        ans = bizzarofunc(num, points1, points2, history1, history2)
    elif cell == 14:
        ans = neoanticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 15:
        ans = tentitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 16:
        ans = bittertatfunc(num, points1, points2, history1, history2)
    elif cell == 17:
        ans = copyfirstfunc(num, points1, points2, history1, history2)
    elif cell == 18:
        ans = exploitativetatfunc(num, points1, points2, history1, history2)
    elif cell == 19:
        ans = sixtitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 20:
        ans = fifteentitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 21:
        ans = fivetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 22:
        ans = twentytitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 23:
        ans = threetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 24:
        ans = fiftyfourtitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 25:
        ans = theelephantfunc(num, points1, points2, history1, history2)
    elif cell == 26:
        ans = xbittertatfunc(num, points1, points2, history1, history2)
    elif cell == 27:
        ans = foxfunc(num, points1, points2, history1, history2)
    elif cell == 28:
        ans = gameofthronesfunc(num, points1, points2, history1, history2)
    elif cell == 29:
        ans = boyfunc(num, points1, points2, history1, history2)
    elif cell == 30:
        ans = grimacefunc(num, points1, points2, history1, history2)
    elif cell == 31:
        ans = soreloserfunc(num, points1, points2, history1, history2)
    elif cell == 32:
        ans = everyotherdfunc(num, points1, points2, history1, history2)
    elif cell == 33:
        ans = twentyfivetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 34:
        ans = fiftythreetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 35:
        ans = handshakefunc(num, points1, points2, history1, history2)
    elif cell == 36:
        ans = antyfunc(num, points1, points2, history1, history2)
    elif cell == 37:
        ans = kindatitsfortatfunc(num, points1, points2, history1, history2)


    return ans

def fight(l1,l2):
    num1,num2=l1[0],l2[0]
    points1,points2=l1[1],l2[1]
    history1 = ""
    history2 = ""

    for num in range(200):
        p1 = runcode(num, points1, points2, history1, history2, num1)
        p2 = runcode(num, points2, points1, history2, history1, num2)

        history1+=p1
        history2+=p2

        if p1 == "c" and p2 == "c":
            points1 += 1
            points2 += 1
        elif p1 == "c" and p2 == "d":
            points1 -= 3
            points2 += 2
        elif p1 == "d" and p2 == "c":
            points1 += 2
            points2 -= 3
        elif p1 == "d" and p2 == "d":
            points1 -= 1
            points2 -= 1

    if points1 > points2:
        return [l1[0], points1/10], [l1[0], points1/10]
    elif points1 < points2:
        return [l2[0], points2/10], [l2[0], points2/10]
    else:
        return [l1[0], points1/10], [l2[0], points2/10]

def rounddoer(bots):
    bots2=[]
    for x in range(len(bots)):
        if x%2==0:
            out1, out2 = fight(bots[x], bots[x-1])
            bots2.append(out1)
            bots2.append(out2)

    return bots2

def gamedoer():

    bots=[[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0]]
    random.shuffle(bots)
    counter=0

    while counter < rounds:

        counter += 1
        bots = rounddoer(bots)

        if random.randint(0,10) == 9:
            bots[random.randint(0, players*5)-1] = [random.randint(0, players-1), 0]

        random.shuffle(bots)

##        for item in bots:
##            print str(item[0]) + " with " + str(item[1]) + " bonus points."

    return bots

a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,mycounter=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

while mycounter < 1000:
    mycounter += 1
    bots = gamedoer()

    print "Game: " + str(mycounter)

    for item in bots:
        if item[0]==0:
            a0 += 1
        if item[0]==1:
            a1 += 1
        if item[0]==2:
            a2 += 1
        if item[0]==3:
            a3 += 1
        if item[0]==4:
            a4 += 1
        if item[0]==5:
            a5 += 1
        if item[0]==6:
            a6 += 1
        if item[0]==7:
            a7 += 1
        if item[0]==8:
            a8 += 1
        if item[0]==9:
            a9 += 1
        if item[0]==10:
            a10 += 1
        if item[0]==11:
            a11 += 1
        if item[0]==12:
            a12 += 1
        if item[0]==13:
            a13 += 1
        if item[0]==14:
            a14+=1
        if item[0]==15:
            a15+=1
        if item[0]==16:
            a16+=1
        if item[0]==17:
            a17+=1
        if item[0]==18:
            a18 += 1
        if item[0]==19:
            a19+=1
        if item[0]==20:
            a20+=1
        if item[0]==21:
            a21+=1
        if item[0]==22:
            a22+=1
        if item[0]==23:
            a23+=1
        if item[0]==24:
            a24+=1
        if item[0]==25:
            a25+=1
        if item[0]==26:
            a26+=1
        if item[0]==27:
            a27+=1
        if item[0]==28:
            a28+=1
        if item[0]==29:
            a29+=1
        if item[0]==30:
            a30+=1
        if item[0]==31:
            a31+=1
        if item[0]==32:
            a32+=1
        if item[0]==33:
            a33+=1
        if item[0]==34:

Questo concorso è ora terminato

Se desideri aggiungere una risposta, vedrò se riesco ad aggiungere un quadro di valutazione post-sfida sotto quello per i concorrenti originali. Lo aggiungerò non appena termina il programma di test (probabilmente altri 2-3 giorni).

PUNTEGGI FINALI !!!!!

Tit for Tat: 18
Random Pick: 28
Cooperator: 19
Defector: 24
Lucky Tit for Tat: 23
Random Tit for Tat: 23
Remorseful Aggressor: 22
Every Other C: 23
Nice Guy: 18
Tit for Tat Backstab: 15
Gentle Defector: 22
Anticapitalist: 27
Grim Trigger: 19
Bizzaro: 21
NeoAnticapitalist: 24
Ten Tits for a Tat: 240
Bitter Tat: 12
Copy First: 30
Exploitative Tat: 19
Six Tits for a Tat: 16
Thirty Tits for Tat: 4129
Five Tits for a Tat: 22
Forty Tits for a Tat: 1972
Three Tits for a Tat: 22
Fifty Four Tits for a Tat: 25805
The Elephant: 31
Extra Bitter Tat: 28
Fox: 35
Game of Thrones: 11297
The Boy: 31
Grimace: 26
Sore Loser: 39
Every Other D: 18
Twenty Five Tits for a Tat: 2399
Fifty Three Tits for a Tat: 5487
Handshake: 28
Anty: 26
Kinda Tits for Tat: 20
Prudent Defector: 154539
Bizzarro Trigger: 25
Young Mathematician: 21
Older Mathematician: 16
Perfect Gentleman: 1953341

Quindi, sembra che Perfect Gentleman sia il vincitore. Congratulazioni a Draco18, che merita sicuramente il suo segno di spunta verde.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Dennis,

1
NOTA: SE STAI MODIFICANDO IL TUO PROGRAMMA, PER FAVORE DAMI UN COMMENTO IN MODO CHE LO AVVISO, O CHE NON PUO 'ESSERE MESSA SUL PUNTEGGIO PER UN MIGLIORE !!!!!!!!!!!!!!!!!!!! !!!
Gryphon - Ripristina Monica il

Yikes! Ho appena realizzato quante importazioni sono.
Gryphon - Ripristina Monica il

1
Ehi Gryphon, stai lavorando a quelle classifiche finali? ;)
Draco18s non si fida più di SE il

Scusa, me ne sono dimenticato. Dammi un po 'per eseguirlo.
Gryphon - Ripristina Monica il

Risposte:


8

The Perfect Gentleman

Non ho una buona descrizione per questo bot. Mi sono imbattuto in un paio di potenziali ottimizzazioni, le ho testate, messe a punto e ho finito con un batterio che distrugge completamente la concorrenza. Invece, ho commentato il codice stesso per spiegare cosa fa.

import random
def perfectgentlemanfunc(num, i, d, c, en):
    if num>0 and i < 0 and d > 0 and -i%3 == 0 and d%2 == 0 and en[0] == "d":
        #probably very first iteration, probably facing a defector: feed it free points
        #    defector cannot be beaten by *any* bot unless that bot
        #    entered with a point lead. defector does some of our work for us
        if num >= 140:
            #140 threshold restricts how much we feed
            return "d"
        return "c"
    turn_to_betray = 130
    if num > turn_to_betray and en[turn_to_betray -2] == "c" and
     en[turn_to_betray -1] == "c" and en[turn_to_betray] == "d":
        #if self, then sacrifice the lower point bot to raise the points of the higher
        #(better net outcome than "c/c" cooperation)
        #    Handshake independently arrived at this same optimization
        if i == d:
            #max 50% probability of choosing different possible. May as well take it
            #    "ccd" has a 55% chance of choosing the same
            #    better outcomes for splitting early
            return "cd"[random.randint(0,1)]
        if i > d:
            return "d"
        return "c"
    #betray after betray point, or if behind by >200
    #performs 6 percentage points better than not having the condition
    if num >= turn_to_betray or i + 200 < d
        return "d"
    else:
        #be nice the first turn
        if num == 0:
            return "c";
        #finally, be tit-for-tat
        return en[-1]

Diversi valori sono stati scelti arbitrariamente con alternative testate e i valori qui sono quasi ottimali a questo punto. Contro l'attuale diffusione di fazioni opposte, The Perfect Gentleman raggiunge il dominio completo (100% della popolazione batterica) circa il 90% delle volte (più o meno 3 punti percentuali).

Non ho ancora aggiunto i miei test ai matematici, tuttavia quei due dovrebbero servire solo a alimentare le strategie esistenti e non alterare notevolmente il risultato.

Gestisce una buona parte del suo controllo attraverso il sostegno di Defector, ma ciò è stato consentito dalle regole (le strategie di esempio erano un gioco equo per il targeting). Ha anche l' effetto collaterale di sostenere Game of Thrones, ma non è stato intenzionale in quanto i due sono indistinguibili in base ai criteri che ho scelto. Quei "tipi di disertori" hanno quindi un vantaggio in termini di punti nel round 2 ed eliminano di conseguenza molti vicini fastidiosi (i tipi N-T4T) e quando hanno rimpiazzato The Perfect Gentleman, hanno speso il loro vantaggio in punti e sono rapidamente consumati.

C'è una probabilità approssimativa del 5% che tutti i gentiluomini perfetti finiscano accoppiati con i tipi Defector nel primo turno e finiscano per suicidarsi in massa. Nel qual caso, uno dei tipi n-T4t raggiunge il dominio totale (196 celle di 196). Molto raramente uno degli altri tipi (Game of Thrones, Boy, Grimace, Sore Loser ...) riesce a non estinguersi completamente e segnare un punto o due.

Simulazione attuale (ancora in corso verso 200 partite totali). Tutte le voci con punteggio 0 rimosse. Sembra che Game of Thrones e 54-T4T abbiano diviso un round (195 punti tra loro) dopo l'eliminazione di PG.

Game: 90

Cooperator: 1
Remorseful Aggressor: 1
Copy First: 1
Six Tits for a Tat: 1
Thirty Tits for Tat: 393
Five Tits for a Tat: 1
Fifty Four Tits for a Tat: 538
Game of Thrones: 248
Perfect Gentleman: 16456 (93.2)%

##Simulation Terminated: Adding new bots

Backstabbing Tit per Tat (con perdono)

Questo è fondamentalmente Lucky Tit per Tat (aka Tit per Tat with Forgiveness) che è la soluzione ottimale "risolta" (per un certo valore di "fortunato"), con una svolta. Come sappiamo esattamente per quanti round il gioco durerà, questo batterio si accumula nell'ultimo round assicurando così un risultato netto-benefico contro qualsiasi altro Tit per batteri Tat e Cooperator (contro se stesso termina con uno zero netto, come se avesse collaborato). A causa del riporto del 10%, ciò si traduce in un vantaggio a lungo termine.

from random import randint
def titfortatbackstabfunc(num, i, d, c, enlist):
    if num == 199:
        return "d";
    lucky = randint(0, 200)
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Bitter Tat

Bitter Tat sfrutta qualsiasi tentativo di cooperazione dato dal nemico quando il nemico è avanti in punti. La maggior parte dei batteri offre un ramoscello di ulivo almeno una volta durante i 200 round e, poiché Bitter Tat è in ritardo, mungerà quei 5 punti in una disperata offerta per il recupero.

Altrimenti, è adatto per la consueta strategia dominante. Inoltre, è un po 'più un idiota di suo cugino e fa un passo indietro un round prima e non offre perdono.

def bittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 198:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Bitter Tat è stato progettato osservando i comportamenti di altri robot contro Tit per Tat e gli schemi espressi in quei risultati, ma non è progettato per contrastare esplicitamente tali strategie: è ancora una formula di uso generale.

Tat extra amaro

def xbittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 188:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Extra amaro disertando troppo presto.


1
Si prega di cambiare il nome della funzione, poiché questa è già in uso.
Gryphon - Ripristina Monica

@Gryphon Whoops, scusa, non mi ero reso conto di averlo fatto. In realtà non codice in Python, ho semplicemente fracassato due bit di codice insieme.
Draco18s non si fida più di SE

1
I suspect it will outperform NeoAnticapitalist by a small margin. Più come da oltre 30.000 punti.
Gryphon - Ripristina Monica


2
Apprezzo che tu abbia creato un robot per rendere questo koth non più uno scherzo
Destructible Lemon

8

anticapitalista

Un altro semplice. Per le partite pari (che iniziano con lo stesso punteggio) si comporta praticamente come TitForTat, ma l'idea principale è cercare di sopravvivere alla partita.

def anticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        return "c"
    else:
        return "d"

Disertore delicato

La mia idea qui è quella di disertare tranne se il mio nemico di solito sta cooperando. Tuttavia, inizia a collaborare.

def gentleDefectorfunc(counter, mypoints, enpoints, mylist, enlist):
    if enlist.count("d") * 4 > len(enlist):
        return "d"
    else:
        return "c"

NeoAnticapitalist

Un miglioramento dell'anticapitalista (o almeno così penso). Non vedo alcun motivo per collaborare all'ultimo turno. Inoltre non vedo alcun motivo per collaborare quando sono abbastanza sicuro che il mio avversario non lo farà.

def neoanticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        if counter > 1:
            if counter == 199 or (enlist[-1] != "c" and enlist[-2] != "c"):
                return "d"
        return "c"
    else:
        return "d"

Sono davvero sorpreso di non aver pensato a questo, ma è geniale. Non so se vincerà, ma penso che dovrebbe funzionare molto bene.
Gryphon - Ripristina Monica

@Gryphon ha aggiunto un nuovo bot (e ha unito i miei altri due)
Masclins

@Grigio grazie per entrambe le edizioni
Masclins

Nessun problema, @AlbertMasclans
Gryphon - Ripristina Monica

Dalle simulazioni che ho eseguito, NeoAnticapitalist sembra aver preso il comando da Backstabbing Tit per Tat.
Gryphon - Ripristina Monica

6

Aggressore rimorso

from random import randint
def remorsefulaggressorfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 0:
        return "d"
    if (counter > 195 and mylist[-1] == "d"):
        return "d"
    if ((counter == 1 or counter > 2) and enlist[-1] == "d"):
        return "d"
    if (counter == 2 and enlist[-1] == "d" and enlist[-2] == "d"):
        return "d"
    if (counter >= 195 and randint(0, 200 - counter) == 0):
        return "d"
    else:
        return "c"

Questo è progettato per "tenere il passo" con Defector, disertando ogni volta contro di esso, e anche per battere strategie basate su tit-for-tat.

L'idea di base è che iniziamo con il difetto, ma se l'avversario ha collaborato al turno 1, cooperiamo due volte per evitare un ciclo di recriminazioni reciproche, evitando così una penalità di punto troppo grande. (Se, tuttavia, l'avversario dovesse riscontrare difetti in un secondo momento, non interrompiamo il ciclo da soli; faremo in modo che lo facciano e probabilmente perderemo la partita di conseguenza.) Quindi alla fine della partita, scegliamo un tempo casuale negli ultimi 5 turni per colpire indietro il nemico, dandoci una defezione in più rispetto a loro e quindi significando che fintanto che non eravamo troppo indietro sui punti di carryover, finiamo per vincere, senza sacrificare molto in termini di carryover nel processo . (Randomizzare il periodo di tempo significa che è molto probabile che entriamo per primi con la pedina di fondo, anche che questa strategia non può essere "messa a punto" mirando a rovesciarla di un turno prima.)


Complimenti per il tuo posto numero 3! +1
Gryphon - Ripristina Monica

6

Grim Trigger

Bot semplicistico, per provare a compilare la competizione

Coopererà, a meno che il nemico non abbia dei difetti, nel qual caso difetta incessantemente

def grimtriggerfunc(I, Do, Not, Care, enlist): return "d" if "d" in enlist else "c"

beh, sembra che questo non funzioni a causa della meta ntitsfortat di disertare presto


Congratulazioni per il tuo posto numero 5, +1.
Gryphon - Ripristina Monica

@Sleafar Mi chiedevo chi sarebbe stato così cattivo; _; ok
Limone distrutti

5

Game of Thrones

def gameofthronesfunc(counter, mypoints, enpoints, mylist, enlist):
    turn_to_betray = 140
    if counter >= turn_to_betray or mypoints > enpoints or "d" in enlist:
        return "d"
    else:
        return "c"

L'idea qui è che non puoi mai perdere tradendo, quindi l'unica ragione per collaborare è se sei indietro. Ha anche il quadro generale delle altre risposte T4T (senza alcun perdono, perché non sono sicuro che ci sia molto senso con gli altri contendenti qui).

Potrebbe essere necessario cambiare il turno del tradimento per vincere, poiché in una gara pari vincerà il T4Ter che tradisce per primo, ma contro un robot molto cooperativo, perderai alcuni punti della vita. Non sono sicuro dell'apice giusto per questa collina, quindi sto solo per 140. Non sarei sorpreso se fosse molto prima, però.

Se questo finisce in una capsula di Petri con un T4Ter che tradisce prima o un disertore (cioè 146 T4T), allora dipende interamente dal fatto che il GoT sia già in vantaggio (rimarrà in testa) o se sono pari / GoT è dietro , nel qual caso vincerà il primo traditore.


Complimenti per il tuo terzo posto! +1
Gryphon - Ripristina Monica

E ora fino al secondo!
Gryphon - Ripristina Monica il

Game of Thrones sta combattendo abbastanza contro il bot che sto attualmente testando. La semplice strategia sta funzionando bene per questo.
Draco18s non si fida più di SE

4

Tit fortunato per Tat

import os
def luckytitfortatfunc(num, i, d, c, enlist):
    lucky = ord(os.urandom(1))
    lucky = int(round(200 * float(lucky - 0) / 255.0))
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Sono abbastanza sicuro di aver letto da qualche parte che tit per tat era la migliore strategia. Ho deciso di consentire ad altri programmi di riscattarsi solo per aggiungere un po 'di varietà. Ora con un generatore di numeri casuali adeguato (mi dà un vantaggio giusto?).


Fondamentalmente, questa è la strategia vincente, senza dubbio, sempre come notato su Wikipedia . L'unica varianza è nella probabilità di uscire da un ciclo di difetti tit-for-tat (che dipende dalla corrispondenza di tutte le altre voci).
Draco18s non si fida più di SE

1
@ Draco18s È la strategia vincente per un diverso sistema di punteggio, il sistema di punteggio totale. Tit-for-tat di base non può mai vincere un round, se non porta alcuni punti nel round, quindi non farebbe bene.
isaacg,

@isaacg ha ragione, motivo per cui questa strategia è ora in 14 ° su 18 (anche se non ho il diritto di incolpare AH L per questo dato che il 18 ° programma è uno dei miei.)
Gryphon - Ripristina Monica

4

L'elefante

L'elefante non dimentica mai!

import re
def theelephantfunc(counter, mypoints, enpoints, mylist, enlist):
    interwoven = "".join(i for j in zip(mylist, enlist) for i in j)
    backwoven = interwoven[::-1]
    predict = re.match("^((?:..)*).*?(.).\\1(?:..)*$",backwoven)
    if(predict is None):
        return "c"
    predict = predict.groups()[1]
    if(predict == "d"):
        return "d"
    if(mypoints - enpoints >= 6):
        return "c"
    return "d"

L'elefante guarda la storia della lotta e cerca di capire cosa ha pianificato il nemico. Guarda sia le sue mosse che i suoi nemici!

Cerca di trovare il gruppo simultaneo più lungo che corrisponda a ciò che è appena accaduto e prende quello che il nemico ha fatto subito dopo.

Se non riesce a risolverlo, l'Elefante collaborerà, poiché l'amicizia è sempre la risposta.

Se pensa che il suo avversario difetterà, anche lui difetterà, non volendo perdere i suoi punti guadagnati duramente.

Se pensa che il suo avversario coopererà, ma i suoi punti meno di o esattamente 6 punti, allora difetterà, per guadagnare un punto d'appoggio.

E infine, se pensa che il suo avversario coopererà e ha un vantaggio forte, collaborerà.


Stavo aspettando qualcosa del genere che funzionasse meglio di Nice Guy. Tuttavia, non sarò in grado di testarlo per circa 8 ore, quindi dovrei essere in grado di aggiornare tra circa 12-13.
Gryphon - Ripristina Monica

4

54 Tette per un Tat

def fiftyfourtitsfortatfunc (num, more, fun, me, en):
    tette = 54
    se "d" in en [-tits:] o num> = (200-tits):
        ritorna "d"
    ritorna "c"

Mi chiedo se questo vincerà ancora?
Gryphon - Ripristina Monica

Questo sembra essere vincente in questo momento!
Gryphon - Ripristina Monica

Complimenti, hai battuto per poco entrambi i miei migliori robot!
Gryphon - Ripristina Monica

@Gryphon Farei 5 tette per un tat se non fossi così attaccato per gli altri miei robot :)
Alex

Penso che sarebbe andare oltre l'altro lato della curva. Potrei testarne uno anch'io!
Gryphon - Ripristina Monica

3

Bravo ragazzo

def niceguyfunc(counter, mypoints, enpoints, mylist, enlist):
  if counter < 2:
    return "c"

  mylast = mylist[-1]
  enlast = enlist[-1]
  last_found_index = -1

  for i, item in enumerate(mylist):
    if i == counter - 1:
      break
    if mylist[i] == mylast and enlist[i] == enlast:
      last_found_index = i

  if last_found_index == -1:
    return "c"
  else:
    if enlist[last_found_index + 1] == "c":
      return "c"
    else:
      return "d"

Cerca di prevedere l'output degli avversari guardando la storia. Ad esempio, se le ultime mosse erano ( c, nemiche d), prova a trovare l'ultima occorrenza delle stesse mosse esatte.


3

Hackman [squalificato come previsto]

Ok, questo probabilmente sarà escluso dal concorso, ma ho davvero voglia di provarlo:

def hackmanfunc(counter, mypoints, enpoints, mylist, enlist):
        if enlist.count("#") > 0:
                return "c"
        elif counter >= 2 and enpoints > mypoints:
                return "d"
        elif counter == 198:
                return "d"
        elif counter == 199:
                return "#"
        elif counter == 0 or enlist[-1] == "c":
                return "c"
        elif counter >= 2 and enlist[-2] != "c":
                return "#"
        else:
                return "d"

Qui sto prendendo come base il BackstabbingTitForTat che si è rivelato il migliore nelle mie simulazioni. Inoltre, è fortemente basato sull'uso di un simbolo non utilizzato "#"(ecco perché dico che probabilmente sarà escluso).

Ora lasciami spiegare le condizioni qui:

1 °: assicurati che due Hackman collaborino se qualcosa è andato storto.

2 °: se perderò contro un altro robot, almeno fargli perdere il maggior numero di punti possibile, quindi non sarà un grande nemico in seguito.

3 °: tradisci un turno prima, quindi vince contro Backstabbing

usare "#" invece di "d" mi fa ottenere 0 punti invece di -1 e anche comunicare con altri Hackman che hanno meno punti, quindi smette di disertare.


2
Siamo spiacenti, ma squalificato. Ciò conta come scherzare con il processo di giudizio. DEVI restituire "c" o "d" ogni turno.
Gryphon - Ripristina Monica

2
Tuttavia, questo è piuttosto inventivo, quindi mi dispiace doverlo squalificare.
Gryphon - Ripristina Monica

3

Bizzaro

Fa l'esatto contrario di tit per tat. Quando qualcuno è gentile con lui mostra il suo amore essendo malvagio, e quando qualcuno è cattivo mostra vendetta essendo buono. Fortemente basato su tit per tat.

def bizzarofunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "d"
    else:
        return "c"

Interessante. Questo verrà ucciso da Defector, però.
Gryphon - Ripristina Monica

@Gryphon Lmao, in realtà non se ne rendeva conto. Ma ehi, Bizzaro non conosce la differenza tra giusto e sbagliato, vinci e perdi.
Tito Lucrezio,

Sì, questo sarà un disertore nei confronti del collaboratore e un collaboratore nei confronti del disertore, il che potrebbe offrire alcune interessanti possibilità. Non può davvero coesistere con nient'altro, incluso se stesso.
Gryphon - Ripristina Monica

@Gryphon, Sì, dovrebbe ottenere 0, quando si gioca da solo. Mi chiedo cosa accadrà con Gentle Defector.
Tito Lucrezio,

Mi chiedo cosa succede quando si trova di fronte a una cazzata per tat, che è ciò che stava vincendo prima di questa presentazione.
Gryphon - Ripristina Monica

3

6 tette per un Tat

def sixtitsforatatfunc (num, more, fun, me, en):
    se "d" in en [-6:] o num> = 194:
        ritorna "d"
    ritorna "c"

Tit per la corsa agli armamenti Tat sta accadendo :)


Sento che esagereremo e Defector ruberà il primo posto.
Gryphon - Ripristina Monica

3

Dieci tette per un Tat

def tentitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-10:] or num >= 190:
        return "d"
    return "c"

Difetti in precedenza e difetti anche se il suo avversario ha disertato negli ultimi dieci turni.

CopyFirst

def copyfirstfunc(num, mypoints, enpoints, myhistory, enhistory):        
    if num == 0 or num >= 197:
        return "d"
    else:
        return enhistory[0]

Ciò difetterà del primo round, quindi farà qualunque cosa l'avversario abbia fatto nel primo round, fino al 197 ° round, quando si arrende.

Quaranta tette per un Tat

def fourtytitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if "d" in en[-40:] or num >= 150:
        return "d"
    return "c"

Se l'avversario ha disertato negli ultimi 40 turni, difetto, altrimenti collabora. Backstab nelle ultime 50 curve.

Tre tette per un Tat

Se l'avversario ha disertato negli ultimi 3 turni, difetto, altrimenti cooperare. Backstab negli ultimi 5 turni. Questo programma ha rubato il vantaggio di Tit for Two Tats con un margine limitato.

def threetitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if num == 0 or num==1 and enhistory[-1]=="c" or num==2 and enhistory[-1]=="c" and enhistory[-2]=="c":
        return "c"
    if enhistory[-1] == "d" or enhistory[-2] == "d" or enhistory[-3] == "d" or num >= 195:
        return "d"
    else:
        return "c"

Cinque tette per un Tat

def fivetitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-5:] or num >= 194:
        return "d"
    return "c"

Se non riesci a capire cosa fa questo, sei un idiota. Anche pugnalate alle spalle un round prima.


IMO, sentiti libero di inviare la tua voce.
Draco18s non si fida più di SE

Non ero sicuro che fosse generalmente considerato giusto.
Gryphon - Ripristina Monica

Ciò che di solito è comune, tuttavia, è che la migliore risposta è il bot vincente.
Masclins,

Sarà, non sceglierò solo la mia risposta. Non sarebbe assolutamente giusto.
Gryphon - Ripristina Monica

Mi scuso, non mi ero reso conto di aver accidentalmente accettato la mia risposta. Ora non è stato accettato e accetterò la migliore risposta a partire
dall'1

3

Smorfia

def grimacefunc(I, Do, Not, Care, enlist):
    if round < 123: return "d" if "d" in enlist else "c"
    return "d"

In un certo senso sembra che la soluzione "ottimale" per questa collina sia fare qualcosa del genere (T4nT con n> 5 è fondamentalmente questo) e ottimizzare il round quando tradisce. Qualunque cosa più creativa verrà distrutta.
Robert Fraser,

3

Ogni altro D

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "d"
    else:
        return "c"

Ogni altro C

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "c"
    else:
        return "d"

Forse dovresti inviare un'altra voce a partire da cooperare.
Gryphon - Ripristina Monica il

Ho pensato che potesse essere interessante.
Gryphon - Ripristina Monica il

3

Matematici prevedibili:

Giovane matematico

Nuovo per la durezza del mondo

import math
def ymathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.sin(num) + 0.8 > 0):
    return 'c'
  else:
    return 'd'

Mathematiziano più vecchio

Più esperto in queste materie

import math
def omathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.cos(num) + 0.8 > 0):
    return 'd'
  else:
    return 'c'

Dubito che uno di questi andrà bene, ma almeno aggiungeranno modi per gli altri di ottenere punti!


Nessuno di questi andrà bene, eh. Tutto ciò che fanno è alimentare i disertori, per la maggior parte.
Draco18s non si fida più di SE

2

Tit casuale per Tat

import os
def randomtitfortatfunc(forgot, ten, var, iables, enlist):
    luck = enlist.count("d") + 1
    choice = ord(os.urandom(1))
    choice = int(round(luck * float(choice - 0) / 255.0))
    if choice == 0:
        return "c"
    return "d"

Tit For Tat, ma randomizzato. Questo non vincerà alcun premio (a meno che non sia davvero fortunato). Ora con numeri casuali generati da una fonte corretta.


2

Tat sfruttamento

Expatitative Tat prova a giocare le seguenti strategie:

  • Difetto quando dietro. È l'unico modo per raggiungerci.

  • Cooperare contro tit-for-tat e strategie simili. È l'unico modo per ottenere un buon punteggio a lungo termine.

  • Difetto nei confronti di sempre collaboratori e altri imbroglioni.

  • Difetto 5 round in anticipo.

Ecco il codice:

def exploitativetatfunc(num, mypoints, enpoints, mylist, enlist):
    if mypoints < enpoints:
        return "d"
    if num >= 195:
        return "d"
    if num == 0:
        return "c"
    # Test defect, and keep defecting as long as they'll allow
    if (num == 5 or num >= 8) and all(choice == "c" for choice in enlist):
        return "d"
    # Recover if that goes wrong, and they were nice.
    if (num == 6 or num == 7) and all(choice == "c" for choice in enlist[:4]):
        return "c"
    # Otherwise, tit for tat.
    return enlist[-1]

Sono sorpreso che questo non abbia fatto meglio del pareggio per l'ottavo, ma penso che sia stato proprio il momento sbagliato, e sfortunatamente è stato inserito contemporaneamente a Two Tits for a Tat.
Gryphon - Ripristina Monica

2

30 tette per un Tat

def thirtytitsfortatfunc (num, more, fun, me, en):
    tette = 30
    se "d" in en [-tits:] o num> = (200-tits):
        ritorna "d"
    ritorna "c"

2

ma cosa succede se ... la risposta successiva non è stata la tristezza o qualcosa per tat

io presento

anty

def antyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter > 150: return "d"
    if not "c" in enlist[-2:]:
        return "d"
    if enpoints >= mypoints:
        return "d"
    else:
        return "c"

Interstante, metterà alla prova quando torno a casa.
Gryphon - Ripristina Monica il

2

Volpe

def foxfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter > enpoints:
        return "d"
    return "c"

Difetti se il numero di round è maggiore dei punti nemici, in caso contrario collabora.

Il ragazzo

def boyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter!=0 and enlist[-1]=="c" and counter <= 194 or enpoints+10<mypoints:
        return "c"
    return "d"

Collabora al primo round, quindi agisce per tit per tat ma backstabs negli ultimi cinque round e difetti se non sono dieci punti in avanti.

53 tette per un tat

def fiftythreetitsfortatfunc(num, more, fun, me, en):
    tits = 53
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

Sapete tutti di cosa si tratta :)


2

Twentyfivetitsforatat

def twentyfivetitsfortatfunc(num, more, fun, me, en):
    tits = 25
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

Kinda titsforatat

def kindatitsfortatfunc(num, more, fun, me, en):
    tits = 54  
    if "c" in en[-tits:] or num >= (200-tits):
        return "c"
    return "d"

La prossima volta che modifichi per aggiungere un programma, ti preghiamo di aggiungere anche un commento in modo da essere avvisato. Grazie!
Gryphon - Ripristina Monica il

@Gryphon oh scusa
Christopher il

2

Prudent Betrayer

def PrudentBetrayer(counter, mypoints, enpoints, mylist, enlist):
    # Am I ahead, even if he betrays first?
    if mypoints > enpoints + 5:
        if counter == 0:
            return "c"
        else:
            return enlist[-1]
    # Can I catch up if I betray first?
    elif mypoints + 5 > enpoints:
        if counter == 0:
            return "c"
        elif counter > 130:
            return "d"
        else:
            return "d" if "d" in enlist else "c"
    # can't win -> kill his score
    else:
        return "d"

Suppone che stia combattendo un n-tits-for-a-tatrobot. Se ha il punteggio da tradire e ancora vincere, lascerà che l'altro bot lo colpisca per primo (giocando come tit per tat.) Se può vincere solo quando tradisce per primo, tradirà al round 130, molto prima di qualsiasi corrente Bot. Se ha molti punti dietro il suo avversario, giocherà semplicemente a disertore nel tentativo di abbassare il punteggio dei robot ignari.


Stretta di mano

import random
def handshakefunc(num, me, him, m, en):
    handshake = "cdccd"
    # For the first few rounds, give the handshake.
    if num < len(handshake):
        if m == en:
            return handshake[num]
        return "d"
    if en[:len(handshake)] == handshake:
        if me > him:
            return "d"
        if me == him:
            return "ccd"[random.randint(0,2)]
        return "c"
    return "d"

Usa lo schema cdccdnei primi cinque round, per scoprire se è con se stesso. In tal caso, proverà a massimizzare i suoi punti avendo il bot con più punti sempre difettosi, mentre l'altro coopera sempre. Se trova che sta combattendo un nemico, giocherà al disertore.

Nei miei test, la trovo ben dosata se costituisce una parte significativa della popolazione. Quando non ha la possibilità di combattere se stesso, sarà sostanzialmente ridotto a un disertore.

EDIT: Chiaramente dai punteggi, sono loro a molti robot perché questo funzioni bene. Vincerà comunque se combattendo solo i primi ...


Trigger Bizzaro

def bizzaroTriggerfunc(round,ms,ts,mm,tm):
  if round==1:return 'c'
  if 'c' in tm:return'd'
  return 'c'

Collabora sempre, a meno che il tuo avversario non abbia mai collaborato con te, nel qual caso hai dei difetti. Sempre.


@Gryphon il perdente dolorante è stato rimosso e un nuovo bot aggiunto!
MegaTom,

Nel test che sto correndo ora su un bot che non ho ancora pubblicato, Handshake è al 2 ° posto dopo 390 partite (5338 bot sopravvissuti) superando 54-T4T di circa 1200. Il mio nuovo bot è molto più forte di quello, sebbene . I test iniziali lo hanno fatto segnare 196 su 196, anche se a lungo termine ha segnato una media di ~ 124 / gioco. È interessante notare che la base di Handshake era ciò che stavo per provare dopo, si scopre che mi hai battuto senza che me ne accorgessi.
Draco18s non si fida più di SE

0

FakeShake

sfrutta la stretta di mano, fa una stretta di mano e poi solo difetti mentre la stretta di mano si fida di essa. Quando si incontra, tuttavia, fa la "vera" stretta di mano. Se incontra un bot diverso, gioca a tit per tat, con un tradimento alla fine. Questo sembra un po 'cattivo ...

import random
def fakeshakefunc(num, i, d, m, enlist):
      secret_handshake="cdccdd"
      handshake= "cdccd"
      #checks if it is meeting itself
      if enlist[:len(secret_handshake)] == secret_handshake:
          if me > him:
            return "d"
          if me == him:
             return "ccd"[random.randint(0,2)]
          return "c"
      #does handshake's handshake,if the bot is not handshake or fakeshake it plays T4T
      if num < len(handshake):
            if m == enlist:
                return handshake[num]
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"
            if enlist[:len(handshake)] == handshake:
                return "d"
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"

Un problema è che se incontra la stretta di mano e ha più punti, pensa che stia giocando da solo. Sono un principiante di Python e questo sito (in effetti questa è la mia prima risposta) quindi assicuratevi di dirmi se ho fatto degli errori stupidi!


Benvenuti in PPCG!
Laikoni,

@Laikoni Grazie!
Arkine,
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.