В этом задании вы напишете бота, который сыграет дилемму заключенного. Вот подвох: у вас не будет доступа к истории предыдущих игр. Вместо этого у вас будет доступ к самому противнику. В этой версии оба игрока получают +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';}
StackOverflow
ошибке, а не к бесконечному циклу, который никогда не завершается. Если это может привести к a StackOverflow
, убедитесь, что вы добавили оператор try-catch. Для примера рекурсии, которая не достигает ошибки
them(() => 'C')
не приведет к ошибке, потому что, когда противник вызывает them
, он вызывает () => 'C'
функцию. Единственное, что нужно обернуть, try-catch
это если вы вызываете them
с параметром некоторой функции, которая вызывает them
с параметром некоторой функции, которая вызывает them
и т.д. (бесконечно). Например, them(t => t(() => 'C'))
будет играть то, что будет играть противник, если противник думает, что он играет nice
. Там нет возможности stackoverflow
ошибки.