Prisoner's Dilemma v.3 - Petri Dilemma

The Perfect Gentleman

I don't have a good description for this bot. I stumbled into a couple of potential optimizations, tested them, fine tuned, and ended up with a bacteria that utterly destroys the competition. Instead, I've commented the code itself to explain what it does.

import random
def perfectgentlemanfunc(num, i, d, c, en):
    if num>0 and i < 0 and d > 0 and -i%3 == 0 and d%2 == 0 and en[0] == "d":
        #probably very first iteration, probably facing a defector: feed it free points
        #    defector cannot be beaten by *any* bot unless that bot
        #    entered with a point lead. defector does some of our work for us
        if num >= 140:
            #140 threshold restricts how much we feed
            return "d"
        return "c"
    turn_to_betray = 130
    if num > turn_to_betray and en[turn_to_betray -2] == "c" and
     en[turn_to_betray -1] == "c" and en[turn_to_betray] == "d":
        #if self, then sacrifice the lower point bot to raise the points of the higher
        #(better net outcome than "c/c" cooperation)
        #    Handshake independently arrived at this same optimization
        if i == d:
            #max 50% probability of choosing different possible. May as well take it
            #    "ccd" has a 55% chance of choosing the same
            #    better outcomes for splitting early
            return "cd"[random.randint(0,1)]
        if i > d:
            return "d"
        return "c"
    #betray after betray point, or if behind by >200
    #performs 6 percentage points better than not having the condition
    if num >= turn_to_betray or i + 200 < d
        return "d"
    else:
        #be nice the first turn
        if num == 0:
            return "c";
        #finally, be tit-for-tat
        return en[-1]

Several values were arbitrarily chosen with alternatives tested and the values here are near-optimal at this point. Against the current spread of opposing factions, The Perfect Gentleman achieves complete dominance (100% of bacteria population) about 90% of the time (plus or minus 3 percentage points).

I have not added in the Mathematicians to my tests yet, however those two should only serve to feed existing strategies and not alter the outcome greatly.

It does manage a good portion of its control via propping up Defector, but that was allowed per the rules (the example strategies were fair game for targeting). It has a side effect of also propping up Game of Thrones, but that was unintentional as the two are indistinguishable based on the criteria I chose. Those "defector types" then have a point-advantage in round 2 and take out several troublesome neighbors as a result (the N-T4T types) and when they reface The Perfect Gentleman, they've expended their point advantage and are swiftly consumed.

There is an approximate 5% chance that all Perfect Gentlemen end up paired with Defector-types in the first round and end up committing mass suicide. In which case, one of the n-T4t types achieves total domination (196 cells of 196). Very rarely one of the other types (Game of Thrones, Boy, Grimace, Sore Loser...) manage to not go completely extinct and score a point or two.

Current simulation (still in progress towards 200 total games). All entries scoring 0 removed. Looks like Game of Thrones and 54-T4T split a round (195 points between them) after PG was eliminated.

Game: 90

Cooperator: 1
Remorseful Aggressor: 1
Copy First: 1
Six Tits for a Tat: 1
Thirty Tits for Tat: 393
Five Tits for a Tat: 1
Fifty Four Tits for a Tat: 538
Game of Thrones: 248
Perfect Gentleman: 16456 (93.2)%

##Simulation Terminated: Adding new bots

Backstabbing Tit for Tat (with Forgiveness)

This is basically Lucky Tit for Tat (aka Tit for Tat with Forgiveness) which is the "solved" optimal solution (for some value of "lucky"), with a twist. As we know exactly how many rounds the game will last, this bacteria backstabs on the final round thus ensuring a net-beneficial outcome against any other Tit for Tat and Cooperator bacteria (against itself it ends with a net zero, same as if it had cooperated). Due to the 10% carryover, this results in a long-term advantage.

from random import randint
def titfortatbackstabfunc(num, i, d, c, enlist):
    if num == 199:
        return "d";
    lucky = randint(0, 200)
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Bitter Tat

Bitter Tat takes advantage of any attempts of cooperation given by the enemy when the enemy is ahead in points. Most bacteria offer an olive branch at least once during the 200 rounds, and as Bitter Tat is behind overall, it will milk those 5 points in a desperate bid for recovery.

Otherwise, it tit-for-tats per the usual dominant strategy. Also, it's a little bit more of a jerk than its cousin and backstabs a round earlier and offers no forgiveness.

def bittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 198:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Bitter Tat was designed via looking at the behaviors of other bots against Tit for Tat and the patterns expressed in those results, but is not designed to explicitly counter those strategies: it is still a general purpose formula.

Extra Bitter Tat

def xbittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 188:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Extra bitter by defecting extra early.


Anticapitalist

Another simple one. For even matches (starting at the same score) behaves pretty much like TitForTat, but the main idea is trying to survive the match.

def anticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        return "c"
    else:
        return "d"

Gentle Defector

My idea here is to defect except if my enemy is usually cooperating. Though, it begins cooperating.

def gentleDefectorfunc(counter, mypoints, enpoints, mylist, enlist):
    if enlist.count("d") * 4 > len(enlist):
        return "d"
    else:
        return "c"

NeoAnticapitalist

An improvement of the Anticapitalist (or so I think). I see no reason to collaborate on last turn. I also see no reason to collaborate when I am pretty sure my opponent won't.

def neoanticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        if counter > 1:
            if counter == 199 or (enlist[-1] != "c" and enlist[-2] != "c"):
                return "d"
        return "c"
    else:
        return "d"

Remorseful Aggressor

from random import randint
def remorsefulaggressorfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 0:
        return "d"
    if (counter > 195 and mylist[-1] == "d"):
        return "d"
    if ((counter == 1 or counter > 2) and enlist[-1] == "d"):
        return "d"
    if (counter == 2 and enlist[-1] == "d" and enlist[-2] == "d"):
        return "d"
    if (counter >= 195 and randint(0, 200 - counter) == 0):
        return "d"
    else:
        return "c"

This is designed to "keep up" with Defector, by defecting every time against it, and also to beat tit-for-tat-based strategies.

The basic idea is that we start by defecting, but if the opponent cooperated turn 1, we then cooperate twice to avoid a mutual recrimination cycle, thus avoiding too large a point penalty. (If, however, the opponent defects later on, we don't break the cycle ourself; we'll make them do it and likely lose the game as a result.) Then at the end of the game, we pick a random time within the last 5 turns to backstab the enemy, giving us one more defection than them and thus meaning that as long as we weren't too far behind on carryover points, we end up winning, without sacrificing much in terms of carryover in the process. (Randomizing the time period means that we're very likely to get in first with the backstab, also that this strategy can't be "tuned against" by aiming to backstab it one turn earlier.)