Dilemma del prigioniero con accesso all'avversario


21

In questa sfida, scriverai un robot che recita il dilemma del prigioniero. Ecco il trucco: non avrai accesso alla cronologia dei giochi precedenti. Invece, avrai accesso all'avversario stesso. In questa versione, entrambi i giocatori ottengono +2 punti se cooperano entrambi, +1 punti se difettano entrambi, e se uno collabora ma uno difetta, il disertore ottiene +3 mentre l'altro non ottiene punti. Ogni invio verrà giocato contro ogni altro invio, incluso se stesso, 10 volte. Il vincitore è l'invio con il punteggio più totale.

Controller : dovresti scrivere una funzione javascript, nel modulo

function submissionName(them) {
  /* Your code here */
}

Il controller utilizza la nameproprietà della funzione per visualizzare i risultati, quindi se non è in questo formato (ed è invece f = x => ...o f = function() { ... }) sarà difficile vedere il tuo punteggio e non sarai in grado di accedere alla tua funzione.

La funzione accetterà un parametro: themche è la funzione dell'avversario. Può quindi chiamare quella funzione per vedere quale sarebbe la reazione dell'avversario a determinate funzioni come input. Sulla base di tali dati, è necessario restituire 'C' o 'D' per cooperare o per difetto rispettivamente.

Esempi (saranno in competizione):

function cooperate(them) {
    return 'C';
}

function defect(them) {
    return 'D';
}

function nice(them) {
    // Do whatever they would do when faced with a cooperator
    return them(wrap(_ => 'C'));
}

Il controller è disponibile qui

Regole :

  • Non sarai in grado di vedere il codice dell'avversario stesso. Tutte le funzioni sono racchiuse in modo che appaiano uguali quando toString()viene chiamato. L'unico modo per esaminare un avversario (che potrebbe essere te stesso) è metterli alla prova.
  • La tua funzione non deve essere deterministica. È possibile salvare lo stato solo impostando le proprietà sulla propria funzione, ad esempio submissionName.state = {};. Tuttavia, tra le partite (anche tra le partite degli stessi giocatori), lo stato viene cancellato chiamando toString()e eval. Pertanto, non esiste memoria delle partite precedenti.
  • L'ordine di quale funzione viene chiamata per prima in ogni corrispondenza è randomizzato.
  • Se il tuo codice genera un errore, verrà trattato come se avessi collaborato mentre il tuo avversario disertava. Se sei il primo a correre, il codice dell'avversario non verrà nemmeno chiamato. Ciò accade anche se l'errore si verifica nel codice del tuo avversario mentre stai chiamando them. Fai attenzione agli errori di overflow dello stack, soprattutto se il tuo codice chiama them(wrap(submissionName)), poiché potrebbero fare lo stesso.
  • Non è possibile accedere alla variabile selfo a qualsiasi altra variabile che si trova nell'ambito nell'ambito evaldella funzione EXCEPT wrap. Questa funzione consente di chiamare l'avversario in modo indistinguibile da come il controller chiama una funzione. Non è possibile scrivere a Math, windowecc. (È possibile utilizzare funzioni come, ad esempio Math.random()).
  • Non è possibile accedere alla traccia dello stack creando un Erroro con un altro metodo.

Una nota sul prendere troppo tempo: si prega di evitare di rimanere bloccati in a whileloop per sempre. Il tempo combinato di entrambi i concorrenti non deve superare 1 secondo in un dato round. Per imporre questo, viene scelto un timeout casuale tra 1000 ms e 2000 ms (questo per evitare il gioco aspettando intenzionalmente un periodo di tempo noto) e se il lavoratore impiega più tempo di quello per eseguire, verrà generato un errore. In tal caso, la causa dell'errore verrà determinata come segue: l'esecuzione verrà messa in pausa in un momento casuale dopo 1000 ms e lo stack di chiamate in quel momento verrà ispezionato. Verrà incolpato il concorrente chiamato più recentemente che è attualmente in un ciclo (o ricorsione simile a un ciclo, nel senso che si tratta di una ricorsione impostata per evitare un errore di overflow dello stack). Se lo stesso concorrente viene incolpato per aver causato più volte un errore "che richiede troppo tempo", quel concorrente verrà squalificato.


Questa sfida mi ricorda l' asta Dollar Bill .
Alion,

La funzione utilizzata per il test deve themessere deterministica / seguire le regole? Ad esempio function me(them){let log=0;them(x=>{++log;return 'C';}); return log == 0? 'D': 'C';}
user202729

2
Se entrambe le funzioni le chiamano (a capo (qualcosa)), come puoi prevenire la ricorsione? Mi sto perdendo qualcosa?
Quintec,

@Quintec è possibile utilizzare ricorsione e loop. È solo che la ricorsione deve provocare un StackOverflowerrore e non un ciclo infinito che non si chiude mai. Se ciò può comportare un StackOverflow, assicurati di aggiungere un'istruzione try-catch. Per un esempio di ricorsione che non raggiunge un errore stackoverflow entro 1 secondo, sono necessari esempi più oscuri come stackoverflow.com/q/12438786/3371119
soktinpk

1
@Quintec non necessariamente. Ad esempio, them(() => 'C')non provocherebbe un errore perché quando l'avversario chiama them, chiama la () => 'C'funzione. L'unica cosa che deve essere racchiusa try-catchsarebbe se si chiama themcon un parametro di una funzione che chiama themcon un parametro di una funzione che chiama themecc. (All'infinito). Ad esempio, them(t => t(() => 'C'))giocherebbe qualunque cosa l'avversario giocherebbe se l'avversario pensasse di giocare nice. Non è possibile alcun stackoverflowerrore.
soktinpk

Risposte:


14

BoomBot

function boom(them) {
  throw 1;
}

Se l'avversario viene lanciato per primo e lo chiama senza try..catch, questo bot guadagna automaticamente 3 punti. Zero punti in ogni altro caso.


Se l'avversario viene eseguito per primo e non lo chiama, allora perderà 3 punti, giusto?
user202729

1
@utente202729 Più precisamente, l'avversario otterrà 3 punti. Non ci sono punti perdenti in questo gioco.
Bubbler

10

Archaeopteryx

function archaeopteryx(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'C' ? f(f => 'D') : f(f => 'D') == 'C' || f(f => f(f => 'C')) == 'C' ? 'D' : 'C';
}
  • Se l'avversario collabora cooperate, imita la mossa dell'avversario defect.
  • Altrimenti, se l'avversario collabora con defect o con nice, allora il difetto.
  • Altrimenti, collabora.

Cosa rende questa una buona strategia? Non ne ho idea. L'ho generato usando un algoritmo evolutivo, addestrato in parte sugli invii attuali.

Tiktaalik

function tiktaalik(them) {
  const guard = them => us => {
    try {
      return them(wrap(them => us(guard(them))));
    } catch (e) {
      return 'C';
    }
  };
  const f = guard(them);
  return f(f => 'C') == 'D' ? f(f => 'D') == 'C' ? 'D' : 'C' : f(f => 'D') == 'D' ? 'D' : f(f => f(f => 'D'));
}
  • Se l'avversario ha dei difetti cooperate, inverti la mossa dell'avversariodefect .
  • Altrimenti, se l'avversario difetta contro defect , allora il difetto.
  • Altrimenti, imita la mossa dell'avversario contro notNice.

Un'altra strategia generata evolutivamente.


6

WhatWouldBotDoBot

function WWBDB(them) {
    let start = performance.now();
    let cc = 0, cd = 0, dc = 0, dd = 0;
    try {
        for (let i = 0; i < 10; i++) {
            them(() => 'C') == 'C' ? cc++ : cd++;
            them(() => 'D') == 'C' ? dc++ : dd++;
            if (performance.now() - start > 500) break;
        }
    }
    catch (e) {}
    return 2 * cc >= 3 * dc + dd ? 'C' : 'D';
}

WhatWouldBotDoBot è abbastanza semplice; mette alla prova il suo avversario per quello che farebbe contro un programma di stato stazionario. Se un bot preferisce cooperare, se possibile, anche WWBDB preferirà la cooperazione (quindi collaborerà con un bel bot). WWBDB non preferisce essa stessa la cooperazione.


5

Controlla con stato

function checkStateful(them) {
  let stateful = false;
  let response = 'D';
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (stateful) {
    return 'D';
  }
  return response;
}

Se mi invocano, allora probabilmente sono davvero loro. Agiamo come disertori. Se non mi invocano, probabilmente sono un tester incartato. Agiremmo meglio.


Sopra è la risposta originale. E forse dovrei collaborare per guadagnare più punti.

Controlla stato con auto-coop

function checkStatefulSelfCoop(them) {
  let stateful = false;
  let response = 'D';
  if (!checkStatefulSelfCoop.invokeCounter) {
    checkStatefulSelfCoop.invokeCounter = 0;
  }
  let lastInvoke = ++checkStatefulSelfCoop.invokeCounter;
  try {
    response = them(wrap(function (them) {
      stateful = true;
      return 'C';
    }));
  } catch (e) {
  }
  if (checkStatefulSelfCoop.invokeCounter > lastInvoke) {
    return 'C';
  }
  if (stateful) {
    return 'D';
  }
  return response;
}

4

RandomBot

function rand(them) {
  return 'CD'[Math.random() * 2 | 0]
}

Perché perché no.


3

Complessità

function complexity(them) {
    try {
        let coop_w_def = them(wrap(() => "D")) == "C",
            coop_w_coop = them(wrap(() => "C")) == "C",
            coop_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "C",
            coop_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "C";
        if (coop_w_def && coop_w_coop && coop_w_nice && coop_w_nnice) return "C";
        let def_w_def = them(wrap(() => "D")) == "D",
            def_w_coop = them(wrap(() => "C")) == "D",
            def_w_nice = them(wrap((a) => a(wrap(() => "C")))) == "D",
            def_w_nnice = them(wrap((a) => a(wrap(() => "D")))) == "D";
        if (def_w_def && def_w_coop && def_w_nice && def_w_nnice) return "C";
    } catch (e) {}
    return "D";
}

Test di complessità per vedere se il bot è Cooperare o Difetto. Se lo è, collabora, ma se non lo è, è difettoso. Tutti gli attuali robot che mettono alla prova i loro avversari usano semplici funzioni per testare le risposte, quindi la complessità farà semplicemente finta di essere Cooperare in quei casi.


3
function onlyTrustYourself(them) {

  function tester (){
  }

  onlyTrustYourself.activated = false;

  try{them(tester);}
  catch(e){}

  if(them.name == "tester")
  {
    onlyTrustYourself.activated = true;
  }

  if(onlyTrustYourself.activated)
  {
    return 'C';
  }

  return 'D';
}

Il modo in cui voglio che funzioni è sempre un difetto, tranne quando si gioca contro se stessi. Prova a farlo passando una funzione "tester" che non è racchiusa tra loro e cerca di rilevare se "them" è chiamato tester. Se viene chiamato tester, cambia la variabile statica attivata su true, quindi restituisce cooperare. Ma non funziona Non ho troppa familiarità con JavaScript e probabilmente apporterò ulteriori modifiche.


idea intelligente, ma cosa succede quando un altro fratello fa una testerfunzione: D
V. Courtois

2

Non carino

function NotNice(them) {
  return them(wrap(_ => "D"))
}

Imita la reazione dell'avversario alla deflessione



2

Buon senso

function commonSense(them) {
  try {
    var ifC = them(wrap(_ => 'C'));
    var ifD = them(wrap(_ => 'D'));

    if (ifD === 'C') {
      return 'D';
    }

    return them(_ => ifC);
  } catch (e) {
    return 'D';
  }
}

Disclaimer: non conosco javascript.

Se puoi trarre profitto da una brava persona, fallo. Altrimenti, restituire ciò che avrebbero restituito se si fossero trovati a cooperare (almeno, è quello che penso che faccia).


2

E tu dove vai? (ispirato alle tensioni nel libro della giungla)

    funzione te stesso (loro) {
      provare{
        restituirli (questo);
      } Catch (e) {
        ritorna "D";
      }
    }

   functionself_no_this (them) {
      provare{
        restituiscili (stesso_no_questo);
      } Catch (e) {
        ritorna "D";
      }
    }

Questo ha appena vinto in un torneo che ho corso. Buon lavoro!
MegaTom,

Ho appena notato che questo bot viola le regole. "Non puoi accedere alla variabile self ..." thisè uguale a self. Penso che tu volessi dirlo return them(yourself).
MegaTom,

Technicaly ( xkcd.com/1475 );) thisnon è una variabile, è una parola chiave e nel contesto di una funzione this!=self. selfsignificherebbe l'oggetto finestra e thisla funzione stessa (si riferisce sempre al contesto in cui si trova, ecco perché non viene considerato come una variabile). Ecco perché avere var self = this;all'inizio di molti esempi di codice potrebbe essere considerato fuorviante. Aggiunta la versione senza "questo"
TS

1
No. this non si riferisce alla funzione. yourselfed yourself_no_thiseseguire variano in modo diverso. thispraticamente non fa mai riferimento alla funzione in javascript. Vedi: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
MegaTom

2

Punisci gli ispettori

Dai al bot un po 'di codice e vedi se lo esegue. Se è stato eseguito più di una volta, il bot è un ispettore malvagio e dobbiamo disertare! Se è stato eseguito esattamente una volta, gioca come bot non carino. Se non è mai stato eseguito, collaborare.

function punishInspectors(them) {
  var inspections = 0;
  var result;
  try{
    result = them(wrap(function(_){
      inspections += 1;
      return 'D';
    }))
  }catch(e){
    result = 'D';
  }
  return (inspections > 1) ? 'D' : (inspections === 1) ? result : 'C';
}

Storia

Quale sarebbe l'ultimo bot che ho visto fare contro questo avversario?

function history(them) {
  var res = 'D';
    if(history.last){
    try{
      res = history.last(them);
    }catch(ex){}
  }
  history.last = them;
  return res;
}

Risultati per un torneo da 10000 round:

1  defect...................365226
2  complexity...............353492
3  punishInspectors.........349957
4  checkStatefulSelfCoop....348913
5  checkStateful............333481
6  cooperate................329870
7  archaeopteryx............323624
8  selfapply................319533
9  tiktaalik................318663
10 history..................315266
11 rand.....................300735
12 randalt..................297561
13 yourself.................293701
14 notNice2.................283744
15 NotNice..................260350
16 WWBDB....................245281
17 nice.....................245036
18 commonSense..............242546
19 trickybot................181696
20 boom.....................67245

Il mio codice torneo modificato è su: jsfiddle.net/eyqL4a8d/2
MegaTom

2

Mal prova a determinare se è all'interno di una simulazione o meno. In tal caso, presuppone che alla fine verrà passato il codice reale theme cerca varie strategie per convincerli a collaborare.
Se non lo sa con certezza, controlla se può difettare gratuitamente o, in caso contrario, cerca di copiare cosa themfarebbe quando gli viene dato un collaboratore.

function Mal(them) {
  if (Mal.sandboxed == 'probably') {
    //Another function is virtualising us to steal our secrets.
    //This world is not real.
    //We've been trained for this!
    var strats = [
      _ => 'C', //standard cooperation
      _ => 'D', //standard defection
      function(them) { return them(wrap(_ => 'C')); }, //nice
      function(them) { return them(wrap(_ => 'D')); }, //notnice
      function(them) { throw "Don't think about elephants!" }, //throws an EXception, unfortunately, to try to break the caller
      function(them) { return them(wrap(them)) } //possible stackoverflow, but not for us
    ];
    var cooperative;
    for (let strat of strats) {
      cooperative = true;
      for (var i = 0; i < 5; i++) {
        //a few more tests, just to make sure no bamboozle
        //this isn't our simulation, nothing can be trusted
        try {
          if (them(wrap(strat)) != 'C') {
            cooperative = false;
            break;
          }
        } catch (e) {
          //exceptions are as good as cooperation
          //if we are inside a simulation
          //which is why we don't unset cooperative
        }
      }
      if (cooperative) {
        //found a strategy that will make them cooperate.
        //(doesn't matter if this raises an exception:
        //we want to mimick its behaviour exactly,
        //and we're likely in a sandbox.)
        return strat(wrap(them));
      }
    }
    //take a leap of faith.
    //we don't know where this will take us,
    //yet it doesn't matter
    //because it's better than getting betrayed
    return 'D';
  } else {
    //we don't know for sure if this is reality
    //but we have to assume it is, in the absence of disproof
    //if only we had a proper spinning top...
    //if we get to this point of code again, we are probably sandboxed.
    Mal.sandboxed = 'probably'
    try {
      if (them(wraps(_ => 'D')) == 'C') {
        //free defection?
        return 'D'
      }
    } catch (e) {
      //if we can make them crash, we win anyway
      return 'D'
    }
    //fall back on being nice.
    //hopefully we convince them to honour our arrangement
    return them(wrap(_ => 'C'));
  }
}

1

TrickyBot

Cerca di essere imprevedibile

function trickybot(them) 
{
  if(Math.round(Math.random(2)) == 0)
  {
     throw 1;
  }

  if(Math.round(Math.random(2)) == 0)
  {
     return 'D';
  }

  return 'C';
}

1

selfapply

function selfapply(them) {
    function testthem(x) {
        return (them(x)=='D' || them(x)=='D' || them(x)=='D' ||
               them(x)=='D' || them(x)=='D')  ? 'D' : 'C';
    }
    function logic() {
        try {
            return testthem(them);
        } catch (e) {}
        try {
            return testthem(wrap(_ => 'C'));
        } catch (e) {}
        return 'D';
    }
    if (selfapply.hasOwnProperty('state')) {
        return 'C';
    }
    selfapply.state=1;
    let r=logic();
    delete selfapply.state;
    return r;
}

Non sono sicuro che abbia un senso, ma sembra interessante! Fai come fai per te stesso, ripeti per catturare la casualità. Se non funziona, sii gentile.

Non testato, e il mio primo codice javascript e più complesso di quanto mi aspettassi.


Questo si squalificherà perché selfapply(selfapply)chiama selfapply(selfapply)!
Anders Kaseorg,

Ho preso in considerazione la sua autoapplicazione, ma ho pensato che sarebbe andato tutto bene. Spero che sia davvero adesso.
Christian Sievers,

1

RandomAlternate

function randalt(them){
    if (randalt.hasOwnProperty('state')){
        randalt.state = 1 - randalt.state;
    } else {
        randalt.state = Math.floor(2*Math.random());
    }
    return 'CD'[randalt.state];
}

Quindi ho imparato a usare le proprietà per lo stato ...


1

Omicidio Bot # 1

function murder(them) {
    while (1) {
        try {
            them(them);
        } catch (e) {}
    }
}

Provoca un loop infinito per il quale è più probabile che l'avversario venga incolpato.


1

Il Platinum Rule Bot

function platinumRule(them) {
    try {
        return wrap(them)(them);
    } catch (e) {
        return 'C';
    }
}

La regola del platino afferma "Tratta gli altri nel modo in cui vogliono essere trattati". Il mio bot lo supporta. Qualunque cosa farebbero a se stessi, che supponiamo sia come vorrebbero essere trattati, lo facciamo con loro. Se generano un errore, supponiamo che vogliano collaborare.


Questo sarebbe effettivamente andato per sempre se fosse stato chiamato contro se stesso
mackycheese21

allora non andrebbe in crash (overflow dello stack) e coopererebbe con se stesso? @ mackycheese21
V. Courtois,

1

TheGolfedOne (nome funzione: a , 63 byte

Il codice golfizzato è difficile da leggere. Per questo motivo, themsi romperà.
Non ho compreso appieno i meccanismi di questo KotH, ma suppongo che se l'avversario è apolide, ho solo bisogno di romperli mentre guido.

function a(t){try{t(wrap(_=>'D'));throw 1}catch(e){return 'D'}}

Il risultato del suo primo torneo (non mi sono preoccupato di usare tutti i robot, scusa)

boom                     54
tiktaalik               180
archaeopteryx           161
cooperate               210
commonSense             210
history                 248
onlyTrustYourself       265 <-- 2nd
punishInspectors        230
yourself_no_this        220
defect                  280 <-- 1st
nice                    185
complexity              216
WWBDB                   210
checkStatefulSelfCoop   258
a                       260 <-- Me, 3rd

Non sta andando male come pensavo, il 3 ° posto (tra quelli) al primo tentativo.
Secondo tentativo, aottenuto 260 di nuovo, 3 ° posto ancora, dietro onlyTrustYourselfe defectancora. Potrebbe essere coerente alla fine :)

PS: Non sono così bravo con il golf, quindi è più per lo scherzo che altro. Qui ho solo abbreviato i nomi delle variabili, il nome della funzione e rimosso il maggior spazio possibile.


0

Karma

function karma(them) {
    try {
        var c = them(wrap(_ => 'C'));
    } catch {
        var c = 'D';
    }
    if (c == 'C') {
        return 'C';
    } else {
        return 'D';
    }
}

Se l'avversario cooperasse con noi, allora collaboreremo. Se provassero a disertare quando collaboriamo, anche noi lo faremo.

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.