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.

soktinpk
fonte
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.

Bubbler
fonte
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.

Anders Kaseorg
fonte
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.

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

RandomBot

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

Porque porque não?

Bubbler
fonte
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.

Spitemaster
fonte
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.

Forma de Ignorância
fonte
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

Erro fatal
fonte
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).

Quintec
fonte
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";
      }
    }
TS
fonte
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
MegaTom
fonte
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'));
  }
}
IFcoltransG
fonte
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';
}
Gus314
fonte
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.

Peneiradores cristãos
fonte
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 ...

Peneiradores cristãos
fonte
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.

PyRulez
fonte
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.

PyRulez
fonte
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.

V. Courtois
fonte
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.

sugarfi
fonte