Дилемма заключенного с доступом к противнику

21

В этом задании вы напишете бота, который сыграет дилемму заключенного. Вот подвох: у вас не будет доступа к истории предыдущих игр. Вместо этого у вас будет доступ к самому противнику. В этой версии оба игрока получают +2 балла, если они оба сотрудничают, +1 балл, если они оба дефекты, и если один сотрудничает, но один дефект, перебежчик получает +3, а другой не получает очков. Каждое представление будет воспроизведено против любого другого представления, включая его, 10 раз. Победителем считается представление с наибольшим количеством очков.

Контроллер : Вы должны написать функцию JavaScript в виде

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

Контроллер использует nameсвойство функции для отображения результатов, поэтому, если он не в этом формате (а вместо этого f = x => ...или f = function() { ... }), вам будет сложно увидеть ваш счет, и вы не сможете получить доступ к своей собственной функции.

Функция будет принимать один параметр: themфункцию противника. Затем он может вызвать эту функцию, чтобы увидеть реакцию противника на определенные функции в качестве входных данных. На основании этих данных вы должны вернуть 'C' или 'D' для сотрудничества или дефекта соответственно.

Примеры (будут конкурировать):

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

Контроллер доступен здесь

Правила :

  • Вы не сможете увидеть сам код оппонента. Все функции упакованы так, что при toString()вызове они выглядят одинаково . Единственный способ проверить противника (который может быть самим собой) - это проверить его.
  • Ваша функция не должна быть детерминированной. Вы можете сохранить состояние, только установив свойства для своей собственной функции, например submissionName.state = {};. Однако между матчами (даже между матчами одного и того же игрока) состояние очищается с помощью вызова toString()и eval. Поэтому нет памяти о предыдущих матчах.
  • Порядок, в котором функция вызывается первой в каждом совпадении, рандомизирован.
  • Если ваш код выдаст ошибку, он будет рассматриваться так, как если бы вы сотрудничали, пока ваш оппонент отступил. Если вы бежите первыми, код оппонента даже не будет вызван. Это происходит, даже если ошибка возникает в коде вашего оппонента во время вашего звонка them. Остерегайтесь ошибок переполнения стека, особенно если ваш код вызывает them(wrap(submissionName)), поскольку они могут делать то же самое.
  • Вы не можете получить доступ к переменной selfили любой другой переменной, которая оказывается в области видимости, если она evalвызывается, ИСКЛЮЧИТЬ функцию wrap. Эта функция позволяет вам вызывать оппонента способом, неотличимым от того, как контроллер вызывает функцию. Вы не можете писать Math, windowи т.д. (Вы можете использовать функции, такие , как Math.random(), впрочем).
  • Вы не можете получить доступ к трассировке стека, создав Errorили другой метод.

Заметка о том, что нужно слишком долго: пожалуйста, избегайте застревания в whileцикл навсегда. Общее время обоих участников не должно превышать 1 секунду в любом раунде. Чтобы обеспечить это, выбирается случайный тайм-аут между 1000 мс и 2000 мс (это позволяет избежать игр, преднамеренно ожидая известное количество времени), и если для выполнения этого рабочего требуется больше времени, выдается ошибка. Если это произойдет, причина ошибки будет определена следующим образом: выполнение будет приостановлено в произвольный момент после 1000 мс, а стек вызовов в этот момент будет проверен. Будет обвинен последний конкурент, который в данный момент находится в цикле (или в виде циклической рекурсии, в том смысле, что это рекурсия, настроенная для предотвращения ошибки переполнения стека). Если одного и того же участника обвиняют в том, что он несколько раз допустил ошибку «слишком долго», этот участник будет дисквалифицирован.

soktinpk
источник
Этот вызов напоминает мне аукцион по продаже долларовых купюр .
Элион
Должна ли функция, используемая для проверки, themбыть детерминированной / следовать правилам? Например function me(them){let log=0;them(x=>{++log;return 'C';}), return log == 0? 'D': 'C';}
user202729
2
Если обе функции вызывают их (wrap (что-то)), как вы можете предотвратить рекурсию? Я что-то пропустил?
Квинтек
@Quintec вы можете использовать рекурсию и циклы. Просто рекурсия должна приводить к StackOverflowошибке, а не к бесконечному циклу, который никогда не завершается. Если это может привести к a StackOverflow, убедитесь, что вы добавили оператор try-catch. Для примера рекурсии, которая не достигает ошибки
переполнения стека в
1
@ Quintec не обязательно. Например, them(() => 'C')не приведет к ошибке, потому что, когда противник вызывает them, он вызывает () => 'C'функцию. Единственное, что нужно обернуть, try-catchэто если вы вызываете themс параметром некоторой функции, которая вызывает themс параметром некоторой функции, которая вызывает themи т.д. (бесконечно). Например, them(t => t(() => 'C'))будет играть то, что будет играть противник, если противник думает, что он играет nice. Там нет возможности stackoverflowошибки.
soktinpk

Ответы:

14

Boombot

function boom(them) {
  throw 1;
}

Если противник запускается первым и вызывает это без try..catch, этот бот автоматически выигрывает 3 очка. Ноль очков в любом другом случае.

фонтанчик для питья
источник
Если противник запускается первым и не вызывает этого, то он потеряет 3 очка, верно?
user202729
1
@ user202729 Точнее, противник получит 3 очка. Там нет потери очков в этой игре.
Bubbler
10

археоптерикс

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';
}
  • Если противник сотрудничает с ним cooperate, имитируют движение противника defect.
  • Иначе, если противник сотрудничает с defect или с nice, то дефект.
  • Остальное, сотрудничай.

Что делает это хорошей стратегией? Не имею представления. Я сгенерировал его, используя эволюционный алгоритм, частично обученный текущим представлениям.

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'));
}
  • Если противник имеет дефекты против cooperate, тогда инвертируйте ход противникаdefect .
  • Иначе, если противник испортил defect , то дефект.
  • Иначе, имитировать ход противника notNice.

Еще одна эволюционно сгенерированная стратегия.

Андерс Касеорг
источник
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 довольно прост; он просто проверяет своего оппонента на то, что он будет делать против устойчивой программы. Если бот предпочитает сотрудничать, если это возможно, WWBDB также предпочтет сотрудничество (поэтому он будет сотрудничать с хорошим ботом). WWBDB сам не предпочитает сотрудничество.

Spitemaster
источник
5

Проверьте состояние

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

Если они призовут меня, то они, вероятно, будут действительно ими. Мы действуем как перебежчик. Если они не призовут меня, то они, вероятно, будут проверенным тестером. Мы бы действовали как лучше.


Выше оригинальный ответ. И, возможно, я должен сотрудничать, чтобы заработать больше очков.

Проверьте состояние с самоконтролем

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

Потому что почему бы и нет.

фонтанчик для питья
источник
3

сложность

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

Сложность тестов, чтобы увидеть, является ли бот Сотрудничает или Дефект. Если это так, он сотрудничает, но если это не так, это порок. Все текущие боты, которые проверяют своих оппонентов, используют простые функции для проверки ответов, поэтому Сложность будет просто притворяться Сотрудничающей в этих случаях.

Spitemaster
источник
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';
}

То, как я хочу, чтобы это работало, всегда должно быть дефектом, за исключением случаев, когда я играю против себя. Он пытается это сделать, передав функцию «тестер», которая не привязана к ним, и пытается определить, называется ли «их» тестером. Если он называется тестером, он изменяет активированную статическую переменную на true, а затем возвращает кооперацию. Но это не работает. Я не слишком знаком с javascript и, возможно, внесу еще некоторые изменения.

Воплощение невежества
источник
умная идея, но что происходит, когда другой брат выполняет testerфункцию: D
V. Courtois
2

Не хорошо

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

Имитирует реакцию противника на отклонение

Фатальная ошибка
источник
2

NotNice 2

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

Бум-версия NotNice от FatalError .

фонтанчик для питья
источник
2

Здравый смысл

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

Отказ от ответственности: я вроде не знаю javascript.

Если вы можете получить прибыль от хорошего человека, сделайте это. В противном случае верните то, что вернули бы, если бы столкнулись с сотрудничеством (по крайней мере, я так думаю ).

Quintec
источник
2

А ты куда хочешь пойти? (вдохновленный волантами в книге джунглей)

    функционировать себя (их) {
      пытаться{
        вернуть их (это);
      } Поймать (е) {
        возврат "D";
      }
    }

   function себя_no_this (их) {
      пытаться{
        вернуть их (self_no_this);
      } Поймать (е) {
        возврат "D";
      }
    }
TS
источник
Это только что выиграл в турнире, в котором я участвовал. Отличная работа!
MegaTom
Я только заметил, что этот бот нарушает правила. «Вы не можете получить доступ к переменной self ...» this- то же самое, что и self. Я думаю, что вы хотели сказать return them(yourself).
MegaTom
Technicaly ( xkcd.com/1475 );) thisэто не переменная, это ключевое слово, и в контексте функции this!=self. selfбудет означать объект окна и thisсаму функцию (всегда относится к контексту, в котором она находится, поэтому она не рассматривается как переменная). Вот почему наличие var self = this;в начале многих примеров кода может рассматриваться как вводящее в заблуждение. Добавлена ​​версия без «этого»
TS
1
thisне относится к функции. yourselfи yourself_no_thisбегать по-разному. thisв основном никогда не ссылается на функцию в JavaScript. См .: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
MegaTom
2

Наказывать инспекторов

Дайте боту код и посмотрите, запускает ли он его. Если он запускался более одного раза, бот злой инспектор, и мы должны уйти! Если он запускался ровно один раз, играйте как нехороший бот. Если он никогда не был запущен, сотрудничайте.

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

история

Что бы последний бот, которого я видел, сделал против этого оппонента?

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

Результаты турнира на 10000 раундов:

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
источник
Мой модифицированный код турнира находится по адресу: jsfiddle.net/eyqL4a8d/2
MegaTom
2

Мал пытается определить, находится ли он внутри симуляции или нет. Если это так, он предполагает, что в конечном итоге ему будет передан настоящий код them, и пробует различные стратегии, чтобы убедить их сотрудничать.
Если он не знает наверняка, он проверяет, может ли он получить дефект бесплатно, или, если нет, пытается скопировать то, что themбудет делать, если ему предоставлен сотрудник.

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
источник
1

TrickyBot

Постарайся быть непредсказуемым

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

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

  return 'C';
}
Gus314
источник
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;
}

Не уверен, имеет ли это какой-то смысл, но это кажется интересным! Делай с тобой, как с собой, повторяй, чтобы поймать случайность. Если это не сработает, будь милым.

Не проверенный, и мой первый код JavaScript, и более сложный, чем я ожидал.

Кристиан Сиверс
источник
Это собирается дисквалифицировать себя, потому что selfapply(selfapply)звонки selfapply(selfapply)!
Андерс Касеорг
Я подумал о собственном применении, но подумал, что все будет в порядке. Я надеюсь, что это действительно так.
Кристиан Сиверс
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];
}

Итак, я узнал, как использовать свойства для государства ...

Кристиан Сиверс
источник
1

Убийство Бот № 1

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

Вызывает бесконечный цикл, в котором более вероятно, что противник будет обвинен.

PyRulez
источник
1

Платиновое Правило Бот

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

Платиновое правило гласит: «Относись к другим так, как они хотят, чтобы к ним относились». Мой бот учитывает это. Что бы они ни делали для себя, что, как мы предполагаем, это то, как они хотели бы, чтобы относились к нам, мы делаем с ними. Если они выдают ошибку, мы предполагаем, что они хотят сотрудничать.

PyRulez
источник
Это бы на самом деле пошло бы навсегда, если бы оно было
вызвано
тогда не произойдет ли сбой (переполнение стека) и сотрудничество с самим собой? @ mackycheese21
В. Куртуа
1

TheGolfedOne (название функции: a ), 63 байта

Гольф-код трудно читать. Из-за этого themсломается.
Я не до конца понимал механику под этим KotH, но я полагаю, что если противник не имеет статуса, мне просто нужно сломать их, пока я дефект.

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

Результат его первого турнира (я не удосужился использовать всех ботов, извините)

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

Он не так плох, как я думал, 3-е место (среди тех) с первой попытки.
Вторая попытка,a снова получил 260, снова 3-е место, снова onlyTrustYourselfи defectснова. Это может быть последовательным в конце :)

PS: Я не так хорош в гольфе, так что это больше для шутки, чем что-либо еще. Здесь я только сократил имена переменных, имя функции и удалил как можно больше пробелов.

В. Куртуа
источник
0

Карма

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

Если противник будет сотрудничать с нами, то мы будем сотрудничать. Если они попытаются уйти, когда мы сотрудничаем, мы также уйдем.

sugarfi
источник