Dilema do prisioneiro com acesso ao oponente


21

Neste desafio, você escreverá um bot que é o dilema do prisioneiro. Aqui está o problema: você não terá acesso ao histórico dos jogos anteriores. Em vez disso, você terá acesso ao próprio oponente. Nesta versão, os dois jogadores ganham +2 pontos se cooperarem, +1 pontos se ambos desertarem, e se um coopera mas um falha, o desertor recebe +3 enquanto o outro não ganha pontos. Cada envio será jogado contra todos os outros envios, incluindo a si próprio, 10 vezes. O vencedor é a finalização com o maior número de pontos.

Controlador : você deve escrever uma função javascript, no formato

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

O controlador usa a namepropriedade da função para exibir os resultados; portanto, se não estiver nesse formato (e estiver f = x => ...ou f = function() { ... }), será difícil ver sua pontuação e você não poderá acessar sua própria função.

A função aceitará um parâmetro: themqual é a função do oponente. Pode então chamar essa função para ver qual a reação do oponente receberia determinadas funções como entradas. Com base nesses dados, você deve retornar 'C' ou 'D' para cooperar ou defeito, respectivamente.

Exemplos (estarão competindo):

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

O controlador está disponível aqui

Regras :

  • Você não poderá ver o próprio código do oponente. Todas as funções são agrupadas para que tenham a mesma aparência quando toString()chamadas. A única maneira de examinar um oponente (quem poderia ser você mesmo) é testá-lo.
  • Sua função não precisa ser determinística. Você só pode salvar o estado definindo propriedades em sua própria função, como submissionName.state = {};. No entanto, entre partidas (mesmo entre partidas dos mesmos jogadores), o estado é limpo ao chamar toString()e eval. Portanto, não há memória de correspondências anteriores.
  • A ordem de qual função é chamada primeiro em cada correspondência é aleatória.
  • Se seu código gerar um erro, ele será tratado como se você cooperasse enquanto seu oponente desertou. Se você é o primeiro a correr, o código do oponente nem será chamado. Isso acontece mesmo se o erro ocorrer no código do seu oponente enquanto você estiver pagando them. Cuidado com os erros de estouro de pilha, especialmente se o seu código chamar them(wrap(submissionName)), pois eles podem fazer o mesmo.
  • Você não pode acessar a variável selfou qualquer outra variável que esteja no escopo quando evalfor chamada EXCEPT the function wrap. Esta função permite que você chame o oponente de uma maneira indistinguível de como o controlador chama uma função. Você não pode escrever para Math, windowetc. (Você pode usar funções como Math.random(), no entanto).
  • Você não pode acessar o rastreamento de pilha criando um Errorou por outro método.

Uma observação sobre a demora: evite ficar preso em um whileloop para sempre. O tempo combinado de ambos os competidores não deve exceder 1 segundo em qualquer rodada. Para impor isso, um intervalo aleatório entre 1000 ms e 2000 ms é escolhido (para evitar jogos, intencionalmente, aguardando uma quantidade conhecida de tempo) e, se o trabalhador demorar mais do que isso para executar, será gerado um erro. Se isso acontecer, a causa do erro será determinada da seguinte forma: a execução será pausada em um momento aleatório após 1000 ms e a pilha de chamadas naquele momento será inspecionada. O competidor mais recentemente chamado que está atualmente em um loop (ou recursão do tipo loop, no sentido de que é uma recursão configurada para evitar um erro de estouro de pilha) será responsabilizado. Se o mesmo competidor for responsabilizado por causar um erro de "demora demais" várias vezes, esse competidor será desqualificado.


Esse desafio me lembra o leilão de notas de dólar .
— Alion

A função usada para testar deve themser determinística / seguir as regras? Por exemplo function me(them){let log=0;them(x=>{++log;return 'C';}), log de retorno == 0? 'D': 'C';}
— user202729

2
Se ambas as funções as chamam (wrap (alguma coisa)), como você pode impedir a recursão? Estou esquecendo de algo?
— Quintec 30/09/18

@Quintec, você pode usar recursão e loops. É que a recursão precisa resultar em um StackOverflowerro e não em um loop infinito que nunca termina. Se isso resultar em um StackOverflow, certifique-se de adicionar uma instrução try-catch. Para um exemplo de recursão que não chegar a um erro stackoverflow dentro de 1 segundo, você precisa de exemplos mais obscuros como stackoverflow.com/q/12438786/3371119
— soktinpk

1
@ Quintec não necessariamente. Por exemplo, them(() => 'C')não resultaria em erro porque, quando o oponente paga them, chama a () => 'C'função. A única coisa que precisa ser envolvida try-catchseria se você chamar themcom um parâmetro de alguma função que chama themcom um parâmetro de alguma função que chama themetc. (infinitamente). Por exemplo, them(t => t(() => 'C'))jogaria o que o adversário jogaria se o adversário pensasse que estava jogando nice. Não há possibilidade de stackoverflowerro.
— precisa saber é o seguinte

Respostas:


14

BoomBot

function boom(them) {
  throw 1;
}

Se o oponente for o primeiro a correr e pagar sem try..catch, este bot ganha automaticamente 3 pontos. Zero pontos em qualquer outro caso.


Se o oponente for executado primeiro e não pagar, então perderá 3 pontos, certo?
— user202729

1
@ user202729 Mais precisamente, o adversário receberá 3 pontos. Não há pontos perdedores neste jogo.
— 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 o oponente cooperar cooperate, imite o movimento do oponente defect.
  • Senão, se o oponente cooperar com defectou com nice, então o defeito.
  • Senão, coopere.

O que torna essa uma boa estratégia? Eu não faço ideia. Eu o criei usando um algoritmo evolutivo, treinado em parte nos envios atuais.

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 o oponente se opuser cooperate, inverta o movimento do oponente defect.
  • Senão, se o oponente se opuser defect, então defeito.
  • Senão, imite o movimento do oponente contra notNice.

Outra estratégia gerada 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 é bastante simples; apenas testa seu oponente pelo que faria contra um programa em estado estacionário. Se um bot preferir cooperar, se possível, o WWBDB também preferirá a cooperação (por isso cooperará com o bot legal). O WWBDB não prefere a cooperação.


5

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

Se eles me invocarem, provavelmente serão realmente eles. Atuamos como desertor. Se eles não me chamarem, provavelmente serão um testador finalizado. Nós agiríamos como mais agradáveis.


Acima está a resposta original. E talvez eu deva me cooperar para ganhar mais pontos.

Verificar stateful com self-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]
}

Porque porque não?


3

Complexidade

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

Testes de complexidade para ver se o bot é Cooperar ou Defeito. Se for, ele coopera, mas se não for, ele falha. Todos os bots atuais que testam seus oponentes usam funções simples para testar as respostas, então a Complexidade apenas fingirá ser Cooperar nesses casos.


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

Como eu quero que isso funcione é sempre desertar, exceto quando estiver jogando contra si mesmo. Ele tenta fazer isso passando uma função "testador" que não está envolvida com eles e tenta detectar se "eles" é nomeado testador. Se ele for nomeado testador, ele alterará a variável estática ativada para true e retornará cooperar. Mas isso não funciona. Não estou muito familiarizado com javascript e provavelmente farei mais algumas alterações.


idéia inteligente, mas o que acontece quando outro irmão faz uma testerfunção: D
— V. Courtois

2

Não é legal

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

Imita a reação do oponente à deflexão



2

Senso comum

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: Eu meio que não sei javascript.

Se você pode lucrar com uma pessoa legal, faça-o. Caso contrário, devolva o que eles retornariam se se enfrentassem cooperando (pelo menos, é o que eu acho que faz).


2

E você, onde você quer ir? (inspirado pelas tensões no livro da selva)

    funcione você mesmo (eles) {
      experimentar{
        devolva-os (isto);
      } captura (e) {
        retornar "D";
      }
    }

   funcione você mesmo (sem) (eles) {
      experimentar{
        devolva-os (você mesmo não);
      } captura (e) {
        retornar "D";
      }
    }

Isso acabou de ganhar em um torneio que eu corri. Bom trabalho!
— MegaTom 12/10

Acabei de perceber que esse bot viola as regras. "Você não pode acessar a variável self ..." thisé o mesmo que self. Eu acho que você queria dizer return them(yourself).
— MegaTom 15/10

Technicaly ( xkcd.com/1475 );) thisnão é uma variável, é uma palavra-chave e no contexto de uma função this!=self. selfsignificaria o objeto da janela e thisa própria função (sempre se refere ao contexto em que se encontra, é por isso que não é considerado uma variável). É por isso que ter var self = this;no início de muitos exemplos de código pode ser considerado enganoso. Versão adicionada sem o "this"
— TS

1
Não. thisNão se refere à função. yourselfe yourself_no_thisexecutar variam de maneira diferente. thisbasicamente nunca se refere à função em javascript. Veja: developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
— MegaTom

2

Punir os inspetores

Dê ao bot algum código e veja se ele é executado. Se foi executado mais de uma vez, o bot é um inspetor do mal, e devemos desertar! Se foi executado exatamente uma vez, jogue como um bot não muito bom. Se nunca foi executado, 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';
}

História

Qual seria o último bot que eu vi fazer contra esse oponente?

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

Resultados para um torneio de 10000 rounds:

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

Meu código de torneio modificado está em: jsfiddle.net/eyqL4a8d/2
— MegaTom 16/10

2

Mal tenta determinar se está dentro de uma simulação ou não. Nesse caso, ele assume que, eventualmente, será passado o código real theme tenta várias estratégias para convencê-los a cooperar.
Se não tiver certeza, verifica se pode desertar gratuitamente ou, se não, tenta copiar o themque faria quando recebesse um colaborador.

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

Tente ser imprevisível

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

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

  return 'C';
}

1

aplicar automaticamente

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

Não tenho certeza se faz algum sentido, mas parece interessante! Faça como você, repita para pegar a aleatoriedade. Se isso não funcionar, seja legal.

Não testado e meu primeiro código javascript, e mais complexo do que eu esperava.


Isso vai se desqualificar porque selfapply(selfapply)chama selfapply(selfapply)!
— Anders Kaseorg

Eu considerei sua própria aplicação, mas achei que seria bom. Espero que seja realmente agora.
— 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];
}

Então eu aprendi como usar propriedades para estado ...


1

Bot de assassinato # 1

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

Causa um loop infinito pelo qual é mais provável que o oponente seja responsabilizado.


1

The Platinum Rule Bot

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

A regra da platina declara "Trate os outros da maneira que eles querem ser tratados". Meu bot acomoda isso. O que quer que eles façam a si mesmos, o que assumimos é como eles gostariam de ser tratados, nós fazemos a eles. Se eles lançarem um erro, assumimos que eles querem cooperar.


Isso realmente duraria para sempre se fosse chamado contra si mesmo
— mackycheese21

então ele não trava (estouro de pilha) e coopera consigo mesmo? @ mackycheese21
— V. Courtois

1

TheGolfedOne (nome da função:) a, 63 bytes

Código de golfe é difícil de ler. Por causa disso, themvai quebrar.
Eu não entendia completamente a mecânica deste KotH, mas suponho que se o oponente for apátrida, eu só preciso quebrá-lo enquanto desertar.

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

O resultado do seu primeiro torneio (não me incomodei em usar todos os bots, desculpe)

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

Ele não está indo tão mal quanto eu pensava, o 3º lugar (entre aqueles) na primeira tentativa.
Segunda tentativa, aconseguiu 260 novamente, terceiro lugar novamente, atrás onlyTrustYourselfe defectnovamente. Pode ser consistente no final :)

PS: Eu não sou tão bom com golfe, então é mais uma brincadeira do que qualquer coisa. Aqui, apenas reduzi os nomes das variáveis, o nome da função e removi o máximo de espaço em branco possível.


0

Carma

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

Se o oponente cooperar conosco, cooperaremos. Se eles tentarem desertar quando cooperamos, nós também desertaremos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.