与对手接触的囚徒困境


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)),因为它们可能会这样做。
  • selfeval调用该函数时,您可能无法访问该变量或碰巧在范围内的任何其他变量wrap。此功能允许您以与控制器调用功能无二的方式呼叫对手。您可能无法写信给Mathwindow等。(您可以使用诸如之类的功能Math.random())。
  • 您可能无法通过创建Error或通过其他方法来访问堆栈跟踪。

花费时间过长的注意事项:请避免卡在 while永远循环。在任何给定回合中,两个竞争对手的总时间不得超过1秒。要强制执行此操作,请选择1000毫秒至2000毫秒之间的随机超时(这是通过有意等待已知的时间量来避免游戏),并且如果工作人员花费的时间长于执行时间,则会抛出错误。如果发生这种情况,将按以下方式确定错误原因:将在1000 ms之后的随机时刻暂停执行,并检查该时刻的调用堆栈。当前处于循环中(或类似循环的递归,从某种意义上来说,它是为避免堆栈溢出错误而设置的递归)而被称为最新竞争者。如果同一位竞争对手多次被指责为导致“花费太长时间”错误,则该竞争对手将被取消参赛资格。


这个挑战使我想起了美元票据拍卖
Alion

用于测试的功能them必须确定/遵循规则吗?例如function me(them){let log=0;them(x=>{++log;return 'C';});; return log == 0?'D':'C';}
user202729 '18

2
如果两个函数都调用它们(wrap(某物)),如何防止递归?我想念什么吗?
Quintec '18

@Quintec,您可以使用递归和循环。仅仅是递归需要导致StackOverflow错误,而不是永远不会退出的无限循环。如果可能导致StackOverflow,请确保添加try-catch语句。对于在1秒内未达到stackoverflow错误的递归示例,您需要更多晦涩的示例,例如stackoverflow.com/q/12438786/3371119
soktinpk

1
@Quintec不一定。例如,them(() => 'C')不会导致错误,因为当对手调用时them,它将调用该() => 'C'函数。唯一需要包装的内容try-catch是,如果您them使用某个函数them的参数进行调用,而该函数的参数又使用某个调用了诸如此类的函数的参数进行调用them(无限)。例如,them(t => t(() => 'C'))如果对手以为自己在玩,就会玩对手会玩的任何东西nice。没有stackoverflow错误的可能性。
soktinpk

Answers:


14

BoomBot

function boom(them) {
  throw 1;
}

如果对手先运行并在不使用的情况下跟注try..catch,则该机器人会自动赢得3分。在任何其他情况下为零分。


如果对手先跑而不叫它,那么它将损失3分,对吧?
user202729 '18 -10-1

1
@ user202729更准确地说,对手将获得3分。在这个游戏中没有输分。
Bubbler '18

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

什么东西

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

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

进行复杂性测试以查看该机器人是协作还是缺陷。如果是这样,它可以协作,但如果不是,则它有缺陷。当前测试其对手的所有漫游器都使用简单的功能来测试响应,因此在这些情况下,复杂性只会假装为合作者。


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

我希望这是如何工作的,除非与自我竞争时,否则总是存在缺陷。它尝试通过传递未包装给他们的“测试器”功能来实现此目的,并尝试检测“他们”是否被命名为测试器。如果将其命名为tester,则它将激活的静态变量更改为true,然后返回合作。但这是行不通的。我对javascript不太熟悉,我可能会进行一些更改。


聪明的主意,但是当另一个兄弟tester发挥作用时会发生什么呢:D
V. Courtois

2

不是很好

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

模仿对手对变形的反应



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

你想去哪里?(受丛林之书中的灵感启发)

    发挥自己的作用{
      尝试{
        返回他们(这个);
      }抓住{e} {
        返回“ D”;
      }
    }

   函数self_no_this(them){
      尝试{
        退还他们(yourself_no_this);
      }抓住{e} {
        返回“ D”;
      }
    }

这只是在我参加的锦标赛中获胜。做得好!
MegaTom

我只是注意到该机器人违反了规则。“您可能无法访问变量self ...” this与self相同。我想你想说return them(yourself)
MegaTom

Technicaly(xkcd.com/1475);)this不是变量,而是关键字,并且在函数的上下文中this!=selfself表示窗口对象和this函数本身(总是指其所在的上下文,这就是为什么不将其视为变量的原因)。这就是为什么 var self = this;在许多代码示例的开头可能会被误导。添加了没有“ this”的版本
TS

1
编号this不是指该功能。yourselfyourself_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

Mal尝试确定它是否在模拟中。如果是这样,则假定它将最终通过的真实代码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)
安德斯·卡塞格

我确实考虑过自己的自我应用程序,但认为可以。我希望它确实是现在。
Christian Sievers

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

1

TheGolfedOne(功能名称: a,63个字节

打高尔夫球的代码很难阅读。因为它,them会中断。
我没有完全理解KotH下的机制,但我想如果对手是无国籍的,我只需要在叛逃时将它们打碎即可。

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

他的第一个Tourney比赛结果(抱歉,我并没有使用所有机器人程序)

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

他的表现没有我想的那么糟糕,在这些尝试中(第三名)。
第二次尝试,a再次获得260,再次获得第三名onlyTrustYourselfdefect一次又一次。最终可能是一致的:)

PS:我打高尔夫球不是那么好,所以笑话比什么都重要。在这里,我仅缩短了变量名,函数名,并删除了尽可能多的空格。


0

业力

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

如果对手会与我们合作,那么我们会合作。如果他们在我们合作时试图背叛,我们也将背叛。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.