Dilema del prisionero con acceso al oponente

21

En este desafío, escribirás un bot que juega el dilema del prisionero. Aquí está el truco: no tendrás acceso al historial de juegos anteriores. En cambio, tendrás acceso al oponente mismo. En esta versión, ambos jugadores obtienen +2 puntos si ambos cooperan, +1 puntos si ambos desertan, y si uno coopera pero uno falla, el desertor obtiene +3 mientras que el otro no obtiene puntos. Cada envío se jugará contra cualquier otro envío, incluido él mismo, 10 veces. El ganador es la presentación con más puntos totales.

Controlador : debe escribir una función de JavaScript, en el formulario

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

El controlador utiliza la namepropiedad de la función para mostrar los resultados, por lo que si no está en este formato (y en su lugar, f = x => ...o f = function() { ... }) será difícil ver su puntaje y no podrá acceder a su propia función.

La función aceptará un parámetro: themque es la función del oponente. Luego puede llamar a esa función para ver cuál sería la reacción del oponente que recibiría ciertas funciones como entradas. En función de esos datos, debe devolver 'C' o 'D' para cooperar o desertar, respectivamente.

Ejemplos (estarán compitiendo):

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'));
}

El controlador está disponible aquí.

reglas :

  • No podrás ver el código del oponente. Todas las funciones están ajustadas para que se vean iguales cuando toString()se llama. La única forma de examinar a un oponente (que podría ser usted mismo) es probarlo.
  • Su función no tiene que ser determinista. Solo puede guardar el estado estableciendo propiedades en su propia función, como submissionName.state = {};. Sin embargo, entre partidos (incluso entre partidos de los mismos jugadores), el estado se borra llamando toString()y eval. Por lo tanto, no hay memoria de coincidencias anteriores.
  • El orden de qué función se llama primero en cada coincidencia es aleatorio.
  • Si su código arroja un error, será tratado como si cooperara mientras su oponente desertó. Si eres el primero en correr, ni siquiera se invocará el código del oponente. Esto sucede incluso si el error ocurre en el código de tu oponente mientras estás llamando them. Tenga cuidado con los errores de desbordamiento de pila, especialmente si su código llama them(wrap(submissionName)), ya que podrían hacer lo mismo.
  • No puede acceder a la variable self, ni a ninguna otra variable que esté dentro del alcance cuando evalse llama EXCEPTO la función wrap. Esta función le permite llamar al oponente de una manera indistinguible de cómo el controlador llama a una función. No puede escribirle a Math, windowetc. (puede usar funciones como Math.random(), sin embargo).
  • No puede acceder al seguimiento de la pila creando un Errormétodo o algún otro.

Una nota sobre tomar demasiado tiempo: evite quedarse atrapado en un whilebucle para siempre. El tiempo combinado de ambos competidores no debe exceder 1 segundo en una ronda determinada. Para hacer cumplir esto, se elige un tiempo de espera aleatorio entre 1000 ms y 2000 ms (esto es para evitar el juego al esperar intencionalmente una cantidad de tiempo conocida), y si el trabajador tarda más que eso en ejecutarse, se generará un error. Si esto sucede, la causa del error se determinará de la siguiente manera: la ejecución se pausará en un momento aleatorio después de 1000 ms, y se inspeccionará la pila de llamadas en ese momento. Se culpará al competidor llamado más recientemente que se encuentra actualmente en un bucle (o una recursión similar a un bucle, en el sentido de que es una recurrencia configurada para evitar un error de desbordamiento de pila). Si se culpa al mismo competidor por causar un error de "demorarse demasiado" varias veces, ese competidor será descalificado.

soktinpk
fuente
Este desafío me recuerda a la subasta de Dollar Bill .
Alion
¿Debe la función utilizada para probar themser determinista / seguir las reglas? Por ejemplo function me(them){let log=0;them(x=>{++log;return 'C';}); return log == 0? 'D': 'C';}
user202729
2
Si ambas funciones los llaman (wrap (algo)), ¿cómo puede prevenir la recurrencia? ¿Me estoy perdiendo de algo?
Quintec
@Quintec puedes usar recursividad y bucles. Es solo que la recursión debe dar como resultado un StackOverflowerror y no un bucle infinito que nunca se cierra. Si puede resultar en un StackOverflow, asegúrese de agregar una declaración try-catch. Para un ejemplo de recursión que no alcanza un error de stackoverflow en 1 segundo, necesita ejemplos más oscuros como stackoverflow.com/q/12438786/3371119
soktinpk
1
@Quintec no necesariamente. Por ejemplo, them(() => 'C')no daría lugar a un error porque cuando el oponente llama them, llama a la () => 'C'función. Lo único que debe envolverse try-catchsería si llama themcon un parámetro de alguna función que llama themcon un parámetro de alguna función que llama, themetc. (infinitamente). Por ejemplo, them(t => t(() => 'C'))jugaría cualquier cosa que el oponente jugaría si el oponente pensara que estaba jugando nice. No hay posibilidad de stackoverflowerror.
soktinpk

Respuestas:

14

BoomBot

function boom(them) {
  throw 1;
}

Si el oponente se ejecuta primero y se queda sin él try..catch, este bot automáticamente gana 3 puntos. Cero puntos en cualquier otro caso.

Bubbler
fuente
Si el oponente se ejecuta primero y no lo llama, perderá 3 puntos, ¿verdad?
user202729
1
@ user202729 Más precisamente, el oponente obtendrá 3 puntos. No hay puntos perdidos en este juego.
Bubbler
10

Arqueoptérix

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';
}
  • Si el oponente coopera con cooperate, imite el movimiento del oponente en contra defect.
  • De lo contrario, si el oponente coopera con defecto con nice, entonces el defecto.
  • De lo contrario, coopere.

¿Qué hace que esta sea una buena estrategia? No tengo idea. Lo generé usando un algoritmo evolutivo, entrenado en parte en los envíos actuales.

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'));
}
  • Si el oponente falla contra cooperate, entonces invierte el movimiento del oponente contradefect .
  • De lo contrario, si el oponente falla contra defect falla , entonces defecto.
  • De lo contrario, imite el movimiento del oponente contra notNice.

Otra estrategia generada evolutivamente.

Anders Kaseorg
fuente
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 es bastante simple; solo prueba a su oponente para saber qué haría contra un programa de estado estable. Si un bot prefiere cooperar si es posible, WWBDB también preferirá la cooperación (por lo que cooperará con un buen bot). WWBDB no prefiere por sí mismo la cooperación.

Spitemaster
fuente
5

Verificar con estado

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;
}

Si me invocan, entonces probablemente sean realmente ellos. Actuamos como desertor. Si no me invocan, entonces probablemente sean un probador envuelto. Actuaríamos como más amables.


Arriba está la respuesta original. Y tal vez debería hacerme cooperar para ganar más puntos.

Compruebe con estado con autocoop

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;
}
tsh
fuente
4

RandomBot

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

Porque, porque no.

Bubbler
fuente
3

Complejidad

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";
}

Pruebas de complejidad para ver si el bot es Cooperar o Defecto. Si es así, coopera, pero si no lo es, falla. Todos los bots actuales que prueban a sus oponentes usan funciones simples para probar las respuestas, por lo que Complexity solo pretenderá cooperar en esos casos.

Spitemaster
fuente
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';
}

Lo que quiero que funcione es siempre desertar, excepto cuando se juega contra uno mismo. Intenta hacerlo pasando una función de "probador" que no está ajustada a ellos, e intenta detectar si "ellos" se llama probador. Si se llama probador, cambia la variable estática activada a verdadero, luego devuelve cooperar. Pero no funciona. No estoy muy familiarizado con JavaScript, y probablemente haré algunos cambios más.

Encarnación de la ignorancia
fuente
idea inteligente, pero qué sucede cuando otro hermano hace una testerfunción: D
V. Courtois
2

No está bien

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

Imita la reacción del oponente a la desviación.

Error fatal
fuente
2

NotNice 2

function notNice2(them) {
  try {
    return them(wrap(_ => 'D'));
  } catch(e) {
    return 'D';
  }
}

Versión a prueba de auge de NotNice por FatalError .

Bubbler
fuente
2

Sentido común

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';
  }
}

Descargo de responsabilidad: no sé javascript.

Si puedes sacar provecho de una buena persona, hazlo. De lo contrario, devuelva lo que devolverían si se enfrentaran a cooperar (al menos, eso es lo que creo que hace).

Quintec
fuente
2

¿Y tú a dónde vas? (inspirado en los voltios del libro de la jungla)

    funcionar usted mismo (ellos) {
      tratar{
        devolverlos (esto);
      } captura (e) {
        devolver "D";
      }
    }

   funciona tú mismo_no_esto (ellos) {
      tratar{
        devolverlos (usted mismo_no_esto);
      } captura (e) {
        devolver "D";
      }
    }
TS
fuente
Esto acaba de ganar en un torneo que corrí. ¡Buen trabajo!
MegaTom
Acabo de notar que este bot viola las reglas. "No puede acceder a la variable self ..." thises lo mismo que self. Creo que querías decirlo return them(yourself).
MegaTom
Technicaly ( xkcd.com/1475 );) thisno es una variable, es una palabra clave y en el contexto de una función this!=self. selfsignificaría el objeto de ventana y thisla función en sí misma (siempre se refiere al contexto en el que se encuentra, es por eso que no se considera como una variable). Es por eso que tener var self = this;en el comienzo de muchos ejemplos de código podría considerarse engañoso. Versión agregada sin el "this"
TS
1
No. thisno se refiere a la función. yourselfy yourself_no_thiscorrer varían de manera diferente. thisbásicamente nunca se refiere a la función en javascript. Ver: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
MegaTom
2

Castigar a los inspectores

Dale un código al bot y mira si lo ejecuta. Si se ejecutó más de una vez, el bot es un malvado inspector, ¡y debemos desertar! Si se ejecutó exactamente una vez, juega como un bot no agradable. Si nunca se ejecutó, coopere.

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';
}

Historia

¿Qué haría el último bot que vi contra este oponente?

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

Resultados de un torneo de 10000 rondas:

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
MegaTom
fuente
Mi código de torneo modificado está en: jsfiddle.net/eyqL4a8d/2
MegaTom
2

Mal intenta determinar si está dentro de una simulación o no. Si es así, se supone que eventualmente se le pasará el código real theme intenta varias estrategias para convencerlos de que cooperen.
Si no está seguro, verifica si puede desertar de forma gratuita, o si no, intenta copiar lo themque haría cuando se le da un cooperador.

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'));
  }
}
IFcoltransG
fuente
1

TrickyBot

Intenta ser impredecible

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

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

  return 'C';
}
Gus314
fuente
1

auto-aplicación

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;
}

No estoy seguro si tiene sentido, ¡pero parece interesante! Haz lo que te haces a ti mismo, repite para atrapar el azar. Si eso no funciona, sé amable.

Sin probar, y mi primer código javascript, y más complejo de lo que esperaba.

Christian Sievers
fuente
¡Esto va a descalificarse porque selfapply(selfapply)llama selfapply(selfapply)!
Anders Kaseorg
Sí consideré su propia aplicación, pero pensé que estaría bien. Espero que realmente sea ahora.
Christian Sievers
1

Aleatorio Alternativo

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

Entonces aprendí a usar propiedades para el estado ...

Christian Sievers
fuente
1

Asesinato Bot # 1

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

Provoca un bucle infinito en el que es más probable que se culpe al oponente.

PyRulez
fuente
1

La regla de platino Bot

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

La regla del platino establece "Trata a los demás de la forma en que quieren ser tratados". Mi bot lo acomoda. Lo que sea que se hagan a sí mismos, lo que suponemos es cómo les gustaría ser tratados, lo hacemos con ellos. Si arrojan un error, asumimos que quieren cooperar.

PyRulez
fuente
En realidad, esto sería para siempre si se llamara contra sí mismo
mackycheese21
entonces, ¿no se estrellaría (desbordamiento de pila) y cooperaría consigo mismo? @ mackycheese21
V. Courtois
1

TheGolfedOne (nombre de func .:) a, 63 bytes

El código de golf es difícil de leer. Por eso, themse romperá.
No entendí completamente la mecánica bajo este KotH, pero supongo que si el oponente no tiene estado, solo necesito romperlo mientras deserto.

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

El resultado de su primer torneo (no me molesté en usar todos los bots, lo siento)

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

No le está yendo tan mal como pensé, 3er lugar (entre esos) primer intento.
Segundo intento, aobtuve 260 nuevamente, 3er lugar nuevamente, detrás onlyTrustYourselfy defectotra vez. Puede ser consistente al final :)

PD: No soy tan bueno con el golf, así que es más una broma que otra cosa. Aquí solo acorté nombres de variables, nombres de funciones y eliminé la mayor cantidad de espacios en blanco posible.

V. Courtois
fuente
0

Karma

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

Si el oponente cooperaría con nosotros, entonces cooperaremos. Si intentaran desertar cuando cooperamos, también lo haremos.

Sugarfi
fuente