Ділема в'язня з доступом до опонента


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 мс, і стек виклику в цей момент буде перевірений. Звинувачується останній закликаний конкурент, який зараз знаходиться в циклі (або циклічна рекурсія, в тому сенсі, що це рекурсія, створена для уникнення помилки переповнення стека). Якщо одного і того ж конкурента звинувачують у тому, що він кілька разів спричинив помилку "зайняття занадто довго", його буде дискваліфіковано.


Цей виклик нагадує мені аукціон доларових купюр .
Аліон

Чи повинна функція, яка використовується для тестування, themбути детермінованою / виконувати правила? Наприклад function me(them){let log=0;them(x=>{++log;return 'C';}); return log == 0? 'D': 'C';}
user202729

2
Якщо обидві функції викликають їх (обгортання (щось)), як ви можете запобігти рекурсії? Я щось пропускаю?
Квінтек

@Quintec ви можете використовувати рекурсію та циклі. Просто рекурсія повинна призвести до StackOverflowпомилки, а не нескінченного циклу, який ніколи не вимикається. Якщо це може призвести до StackOverflow, обов'язково додайте заяву про спробу. Для прикладу рекурсії , яка не досягає помилки StackOverflow в протягом 1 секунди, вам потрібно більше неясні приклади , як stackoverflow.com/q/12438786/3371119
soktinpk

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 очки, правда?
користувач202729

1
@ user202729 Точніше, суперник отримає 3 очки. У цій грі немає жодних програшних балів.
Бубон

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, то дефект.
  • Інше, співпрацюй.

Що робить це хорошою стратегією? Я поняття не маю. Я генерував це за допомогою еволюційного алгоритму, частково навченого на поточних поданнях.

Тикталік

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 не віддає перевагу співпраці.


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


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

Тести на складність, щоб побачити, чи є бот співпрацюючим чи дефектним. Якщо це так, він співпрацює, але якщо ні, він дефектує. Усі поточні боти, які тестують своїх опонентів, використовують прості функції для тестування відповідей, тому Complexity в цих випадках просто прикинеться співпрацею.


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

Як я хочу, щоб це працювало - це завжди дефекти, за винятком випадків, коли граєш проти себе. Він намагається це зробити, передаючи функцію "тестер", яка не закріплена для них, і намагається визначити, чи "їм" названо тестер. Якщо він названий тестер, він змінює статичну змінну, активовану на істинну, а потім повертає співпрацювати. Але це не працює. Я не надто знайомий з JavaScript, і я, мабуть, внесу ще деякі зміни.


розумна ідея, але що станеться, коли інший брат зробить testerфункцію: D
V. Courtois



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.

Якщо ви зможете отримати прибуток від приємної людини, зробіть це. В іншому випадку поверніть те, що вони б повернули, якби зіткнулися з співпрацею (принаймні, це я думаю, що це робить).


2

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

    функціонувати самі (їх) {
      спробуйте {
        повернути їх (це);
      } catch (e) {
        повернути "D";
      }
    }

   функціонувати yourself_no_this (їх) {
      спробуйте {
        повернути їх (себе_но_це);
      } catch (e) {
        повернути "D";
      }
    }

Це щойно виграло в турнірі, на якому я пробігав. Хороша робота!
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

Мій модифікований код турніру знаходиться за адресою: 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'));
  }
}

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

1

самозастосування

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

ВипадковіАльтернативні

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) {}
    }
}

Викликає нескінченну петлю, в якій більше шансів звинуватити опонента.


1

Правило платини

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

Правило платини зазначає: "Ставтесь до інших так, як вони хочуть, щоб до них ставились". Мій бот вміщує це. Що б вони не зробили самі, як ми вважаємо, як вони б хотіли, щоб до них ставились, ми робимо і їм. Якщо вони видають помилку, ми припускаємо, що хочуть співпрацювати.


Це насправді триватиме назавжди, якби його закликали проти себе
mackycheese21

то невже він не стане крахом (переповнення стека) та співпрацюватиме сам із собою? @ 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: Мені не так добре в гольфі, тому це більше для жарту, ніж нічого. Тут я лише скорочував імена змінних, ім’я func та видаляв якомога більше пробілів.


0

Карма

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

Якщо опонент співпрацював би з нами, то ми будемо співпрацювати. Якщо вони намагатимуться дефектувати, коли ми співпрацювали, ми також будемо бракувати дефекти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.