OK. Let me explain what the basic idea of my program was. The idea was to analyze the opponent's program in an attempt to answer the following question: What is the probability that I can affect the outcome of their program? Now that I've thought about this some more, this makes less sense than I initially thought; if there's a second round (and I have time to program something as complicated as this), I'm going to try the rather more sensible "How much I can I affect the probability distribution of their program's output?" But for now let's go with the original idea, even though it doesn't make sense in general.
So the idea was to compute this probability, p, and then cooperate if p>=1/2. (The number 1/2 is not arbitrary and is based on the particular values for T, R, P, and S used. Actually if the numbers were different, there wouldn't be a single p, it would depend on other things, but I'm not going to into that, because this strategy doesn't actually make sense.)
So e.g. the strategy should defect against CooperateBot, DefectBot, and any sort of RandomBot; it would cooperate with (and get defected against by) Watson's entry; it would cooperate with (and get cooperated with) by what So8res called a "rank N MimicBot", so long as N>=2; and it would cooperate with what solipsist called a Mimicbot so long as "cooperate anyway" probability was at most 1/2, otherwise it would defect.
OK. So let's say I'm running my program and it comes up against one of these MimicBots. It gets to a part that looks like
(if (random 100) 'C ((eval opponent) self))
What does it do? Well, it has to check both branches and see that in the first, which occurs with probability 1/100, it can't affect the outcome, and in the second, which occurs with probability 99/100, it can. (Really it's a bit more complicated than that -- how does it get the probabilities? But A. the strategy doesn't actually quite make sense anyway and B. I'm trying to keep this simple.)
Thing is, in order to check both branches, it basically has to (partially) run them. To be honest, "static analysis" is maybe not the best description of what my program was supposed to do -- it wasn't so much "statically analyze the given program", so much as "statically transform it into a different program, and then run that". It has to partially run them so that it's not fooled by conditionals like (if (= 0 1) 'C 'D); it shouldn't take branches that are simply never going to happen.
And that leads to the problem -- suppose instead it were to come to
(if (random 100) (set! result 'C) (set! result ((eval opponent) self)))
Now running both branches is no longer going to yield a sensible result. I'm not sure what it would yield, but it wouldn't yield anything helpful. It gets worse if instead of being the result, the variable set is some sort of intermediate...
I still don't see where set! is relevantly different from define... e.g.
(define result (if (random 100) 'C ((eval opponent) self)))
The prisoner's dilemma tournament is over. There were a total of 21 entries. The winner is Margaret Sy, with a total of 39 points. 2nd and 3rd place go to rpglover64 and THE BLACK KNIGHT, with scores of 38 and 36 points respectively. There were some fairly intricate strategies in the tournament, but all three of these top scorers submitted programs that completely ignored the source code of the other player and acted randomly, with the winner having a bias towards defecting.
You can download a chart describing the outcomes here, and the source codes for the entries can be downloaded here.
I represented each submission with a single letter while running the tournament. Here is a directory of the entries, along with their scores: (some people gave me a term to refer to the player by, while others gave me a term to refer to the program. I went with whatever they gave me, and if they gave me both, I put the player first and then the program)
A: rpglover64 (38)
B: Watson Ladd (27)
c: THE BLACK KNIGHT (36)
D: skepsci (24)
E: Devin Bayer (30)
F: Billy, Mimic-- (27)
G: itaibn (34)
H: CooperateBot (24)
I: Sean Nolan (28)
J: oaz (26)
K: selbram (34)
L: Alexei (25)
M: LEmma (25)
N: BloodyShrimp (34)
O: caa (32)
P: nshepperd (25)
Q: Margaret Sy (39)
R: So8res, NateBot (33)
S: Quinn (33)
T: HonoreDB (23)
U: SlappedTogetherAtTheLastMinuteBot (20)