21
4
In this challenge, you will write a bot that play's the prisoner's dilemma. Here's the catch: you will not have access to the history of previous games. Instead, you will have access to the opponent itself. In this version, both players get +2 points if they both cooperate, +1 points if they both defect, and if one cooperates but one defects, the defector gets +3 while the other gets no points. Each submission will be played against every other submission, including itself, 10 times. The winner is the submission with the most total points.
Controller: You should write a javascript function, in the form
function submissionName(them) {
/* Your code here */
}
The controller uses the function's name
property to display the results, so if it is not in this format (and is instead f = x => ...
or f = function() { ... }
) it will be difficult to see your score and you will not be able to access your own function.
The function will accept one parameter: them
which is the opponent's function. It may then call that function to see what the opponent's reaction would be given certain functions as inputs. Based on that data, you must return 'C' or 'D' for cooperate or defect respectively.
Examples (will be competing):
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'));
}
The controller is available here
Rules:
- You won't be able to see the opponent's code itself. All functions are wrapped so that they look the same when
toString()
is called. The only way to examine an opponent (who could be yourself) is to test them. - Your function does not have to be deterministic. You may only save state by setting properties on your own function, such as
submissionName.state = {};
. However, between matches (even between matches of the same players), state is cleared by callingtoString()
andeval
. Therefore, there is no memory of previous matches. - The order of which function is called first in each match is randomized.
- If your code throws an error, it will be treated as though you cooperated while your opponent defected. If you are the first to run, the opponent's code will not even be called. This happens even if the error occurs in your opponent's code while while you are calling
them
. Be wary of stack overflow errors, especially if your code callsthem(wrap(submissionName))
, as they might do the same. - You may not access the variable
self
, or any other variable that happens to be in scope wheneval
is called EXCEPT the functionwrap
. This function allows you to call the opponent in a manner indistinguishable from how the controller calls a function. You may not write toMath
,window
, etc. (You may use functions, such asMath.random()
, however). - You may not access the stack trace by creating an
Error
or by some other method.
A note on taking too long: please avoid getting stuck in a while
loop forever. The combined time of both competitors should not exceed 1 second in any given round. To enforce this, a random timeout between 1000 ms and 2000 ms is chosen (this is to avoid gaming by intentionally waiting a known amount of time), and if the worker takes longer than that to execute, an error will be thrown. If this happens, the cause of the error will be determined as follows: the execution will be paused at a random moment after 1000 ms, and the call stack at that moment will be inspected. The most recently called competitor that is currently in a loop (or loop-like recursion, in the sense that it is a recursion set up to avoid a stack overflow error) will be blamed. If the same competitor is blamed for causing a "taking too long" error several times, that competitor will be disqualified. This means that even if you cause the opponent to take too long by getting stuck in a loop when your opponent calls you, it will still be your fault, because it is the call stack that matters.
This challenge reminds me of the Dollar Bill Auction.
– Alion – 2018-09-30T09:18:11.220Must the function used to test
them
be deterministic/follow the rules? For examplefunction me(them){let log=0;them(x=>{++log;return 'C';})
;return log==0?'D':'C';} – user202729 – 2018-09-30T12:28:06.0772If both functions call them(wrap(something)), how can you prevent recursion? Am I missing something? – Quintec – 2018-09-30T13:29:53.750
@Quintec you can use recursion and loops. It's just that the recursion needs to result in a
– soktinpk – 2018-09-30T14:18:00.493StackOverflow
error and not an infinite loop that never quits. If it could result in aStackOverflow
, make sure you add a try-catch statement. For an example of recursion that does not reach a stackoverflow error within 1 second, you need more obscure examples like https://stackoverflow.com/q/12438786/3371119@user202729 That is allowed. The function used to test
them
does not have to follow those rules. – soktinpk – 2018-09-30T14:20:44.153@soktinpk So every bot that calls
them
must use a try-catch? In that case callingthem
is pointless since everything must go to thecatch
... – Quintec – 2018-09-30T14:26:13.2431@Quintec not necessarily. For example,
them(() => 'C')
would not result in an error because when the opponent callsthem
, it calls the() => 'C'
function. The only thing that needs to be wrapped intry-catch
would be if you callthem
with a parameter of some function that callsthem
with a parameter of some function that callsthem
etc. (infinitely). For example,them(t => t(() => 'C'))
would play whatever the opponent would play if the opponent thought they were playingnice
. There is no possibility of astackoverflow
error. – soktinpk – 2018-09-30T14:39:33.530Is this ever going to get a deadline/be officially scored? – Veskah – 2018-10-20T03:12:29.487
@Veskah Hopefully at some point, when I'm not too busy. – soktinpk – 2018-10-21T14:45:24.223