Ділема в'язня, т.3 - Ділема Петрі


17

Божевільний вчений щойно створив новий вид бактерій! Він вирішив назвати його Ноблусом Джентльманусом, після спостереження за його поведінкою. Однак його бактерії закінчилися з їжею і оголосили війну, оскільки вони здатні заготовити трупи інших бактерій на достатню кількість їжі, щоб створити копії. Існує ряд різних підвидів цієї бактерії, які мають різні стратегії гри у дилему в'язня, улюблену гру. Існує п’ять бактерій з кожного різного підвиду. У "Ділемі в'язня" кожен з двох гравців одночасно обирає або дефект, або співпрацює. Якщо один гравець вибирає співпрацю, а інший вибирає за замовчуванням, неплатник отримує 2 бали, а кооператор втрачає 3 бали. Якщо обидва гравці вирішили співпрацювати, обидва гравці отримують один бал. Якщо обидва гравці вибирають за замовчуванням, обидва гравці втрачають 1 бал.

Будучи шляхетними джентльменами, бактерії вирішили боротися з цією війною, зігравши в 200 круглих ігор Ітерованої дилеми в'язня. Програвший кожен поєдинок покінчить життя самогубством, дозволяючи переможцю клонуватися до себе. У разі зав’язування обох бактерій залишиться живим, але жодна з них не зможе клонуватись. Крім того, всі бактерії з матчу переносять понад 10% своїх балів до наступного матчу. Клон переносить точки бактерії, в яку його клонували. Крім того, існує кожен десятий шанс за кожну чергу, що одна бактерія буде мутувати на інший підвид з 0 бонусними балами (якщо я отримаю скарги на випадковість цього, я можу її видалити). Після того, як бактерії зіграли ряд цих поєдинків, рівних кількості підвидів бактерій в десять разів, шалений учений випадково скидає чашку Петрі, в яку мешкають бактерії, і всі бактерії набувають нових джерел їжі, закінчуючи свої поєдинки. Це відрізняється від звичайного ітераційного змагання з дилемою ув'язненого, оскільки воно включає в себе поєдинки 1v1 з переносними очками, а не просто намагання отримати найбільшу кількість очок. Це робить велику різницю в ефективності даної стратегії.

Кожна бактерія отримає введення на початку своєї черги у форматі: (номер повороту, поточні точки, точки ворога, ваші попередні ходи [рядок, використовуючи символ "c" для співпраці та символ "d" для дефекту ], вороги попередні ходи [в тому ж форматі]).

Ось чотири приклади стратегій, які будуть введені. Я насправді думаю, що Defector може виграти, хоча це надзвичайно просто.

Синиця для Тат

def titfortatfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "c"
    else:
        return "d"

RandomPick

from random import choice
def randompickfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 199:
        return "d"
    else:
        return choice(["d", "c"])

Кооператор

def cooperatorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "c"

Дефектор

def defectorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "d"

Усі подання повинні бути у формі функції Python 2.7, при цьому назва має назву подання без пробілів, з funcкінцем. Якщо хтось хотів би надіслати відповідь іншою мовою, будь ласка, введіть її у псевдокоді, щоб перетворити Python у редагуванні на вашу відповідь, як тільки я встигну, або дайте мені інструкції щодо взаємодії вашої мови з моїм контролером, який наведено нижче, встановлене для всіх заявок на 4 червня.

from titfortat import titfortatfunc
from randompick import randompickfunc
from cooperator import cooperatorfunc
from defector import defectorfunc
from luckytitfortat import luckytitfortatfunc
from randomtitfortat import randomtitfortatfunc
from remorsefulaggressor import remorsefulaggressorfunc
from everyother import everyotherfunc
from niceguy import niceguyfunc
from titfortatbackstab import titfortatbackstabfunc
from gentleDefector import gentleDefectorfunc
from anticapitalist import anticapitalistfunc
from grimtrigger import grimtriggerfunc
from bizzaro import bizzarofunc
from neoanticapitalist import neoanticapitalistfunc
from bittertat import bittertatfunc
from teamer import teamerfunc
from copyfirst import copyfirstfunc
from exploitivetat import exploitativetatfunc
from defectorv2 import defectorv2func
from crazytat import crazytatfunc
from randomchoicev2 import randomchoicev2func
from twotitsforatat import twotitsforatatfunc
from threetitsforatat import threetitsforatatfunc
from fourtitsforatat import fourtitsforatatfunc
from fivetitsforatat import fivetitsforatatfunc
from sixtitsforatat import sixtitsforatatfunc
from tentitsforatat import tentitsforatatfunc
from theelephant import theelephantfunc
from xbittertat import xbittertatfunc
from fifteentitsforatat import fifteentitsfortatfunc
from twentytitsforatat import twentytitsforatatfunc
from fox import foxfunc
from onehundredfortysixtitsforatat import onehundredfourtysixtitsforatatfunc
from gameofthrones import gameofthronesfunc
from boy import boyfunc
from grimace import grimacefunc
from fiftytitsforatat import fiftytitsfortatfunc
from soreloser import soreloserfunc
from everyotherd import everyotherdfunc
from fiftythreetitsfortat import fiftythreetitsfortatfunc
from twentyfivetitsfortat import twentyfivetitsfortatfunc
from handshake import handshakefunc
from anty import antyfunc
from fiftyfourtitsforatat import fiftyfourtitsfortatfunc
from kindatitsfortat import kindatitsfortatfunc

import random

players = 38

rounds = players*10

def runcode(num, points1, points2, history1, history2, cell):
    ans = ""
    if cell == 0:
        ans = titfortatfunc(num, points1, points2, history1, history2)
    elif cell == 1:
        ans = randompickfunc(num, points1, points2, history1, history2)
    elif cell == 2:
        ans = cooperatorfunc(num, points1, points2, history1, history2)
    elif cell == 3:
        ans = defectorfunc(num, points1, points2, history1, history2)
    elif cell == 4:
        ans = luckytitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 5:
        ans = randomtitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 6:
        ans = remorsefulaggressorfunc(num, points1, points2, history1, history2)
    elif cell == 7:
        ans = everyotherfunc(num, points1, points2, history1, history2)
    elif cell == 8:
        ans = niceguyfunc(num, points1, points2, history1, history2)
    elif cell == 9:
        ans = titfortatbackstabfunc(num, points1, points2, history1, history2)
    elif cell == 10:
        ans = gentleDefectorfunc(num, points1, points2, history1, history2)
    elif cell == 11:
        ans = anticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 12:
        ans = grimtriggerfunc(num, points1, points2, history1, history2)
    elif cell == 13:
        ans = bizzarofunc(num, points1, points2, history1, history2)
    elif cell == 14:
        ans = neoanticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 15:
        ans = tentitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 16:
        ans = bittertatfunc(num, points1, points2, history1, history2)
    elif cell == 17:
        ans = copyfirstfunc(num, points1, points2, history1, history2)
    elif cell == 18:
        ans = exploitativetatfunc(num, points1, points2, history1, history2)
    elif cell == 19:
        ans = sixtitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 20:
        ans = fifteentitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 21:
        ans = fivetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 22:
        ans = twentytitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 23:
        ans = threetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 24:
        ans = fiftyfourtitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 25:
        ans = theelephantfunc(num, points1, points2, history1, history2)
    elif cell == 26:
        ans = xbittertatfunc(num, points1, points2, history1, history2)
    elif cell == 27:
        ans = foxfunc(num, points1, points2, history1, history2)
    elif cell == 28:
        ans = gameofthronesfunc(num, points1, points2, history1, history2)
    elif cell == 29:
        ans = boyfunc(num, points1, points2, history1, history2)
    elif cell == 30:
        ans = grimacefunc(num, points1, points2, history1, history2)
    elif cell == 31:
        ans = soreloserfunc(num, points1, points2, history1, history2)
    elif cell == 32:
        ans = everyotherdfunc(num, points1, points2, history1, history2)
    elif cell == 33:
        ans = twentyfivetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 34:
        ans = fiftythreetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 35:
        ans = handshakefunc(num, points1, points2, history1, history2)
    elif cell == 36:
        ans = antyfunc(num, points1, points2, history1, history2)
    elif cell == 37:
        ans = kindatitsfortatfunc(num, points1, points2, history1, history2)


    return ans

def fight(l1,l2):
    num1,num2=l1[0],l2[0]
    points1,points2=l1[1],l2[1]
    history1 = ""
    history2 = ""

    for num in range(200):
        p1 = runcode(num, points1, points2, history1, history2, num1)
        p2 = runcode(num, points2, points1, history2, history1, num2)

        history1+=p1
        history2+=p2

        if p1 == "c" and p2 == "c":
            points1 += 1
            points2 += 1
        elif p1 == "c" and p2 == "d":
            points1 -= 3
            points2 += 2
        elif p1 == "d" and p2 == "c":
            points1 += 2
            points2 -= 3
        elif p1 == "d" and p2 == "d":
            points1 -= 1
            points2 -= 1

    if points1 > points2:
        return [l1[0], points1/10], [l1[0], points1/10]
    elif points1 < points2:
        return [l2[0], points2/10], [l2[0], points2/10]
    else:
        return [l1[0], points1/10], [l2[0], points2/10]

def rounddoer(bots):
    bots2=[]
    for x in range(len(bots)):
        if x%2==0:
            out1, out2 = fight(bots[x], bots[x-1])
            bots2.append(out1)
            bots2.append(out2)

    return bots2

def gamedoer():

    bots=[[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0]]
    random.shuffle(bots)
    counter=0

    while counter < rounds:

        counter += 1
        bots = rounddoer(bots)

        if random.randint(0,10) == 9:
            bots[random.randint(0, players*5)-1] = [random.randint(0, players-1), 0]

        random.shuffle(bots)

##        for item in bots:
##            print str(item[0]) + " with " + str(item[1]) + " bonus points."

    return bots

a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,mycounter=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

while mycounter < 1000:
    mycounter += 1
    bots = gamedoer()

    print "Game: " + str(mycounter)

    for item in bots:
        if item[0]==0:
            a0 += 1
        if item[0]==1:
            a1 += 1
        if item[0]==2:
            a2 += 1
        if item[0]==3:
            a3 += 1
        if item[0]==4:
            a4 += 1
        if item[0]==5:
            a5 += 1
        if item[0]==6:
            a6 += 1
        if item[0]==7:
            a7 += 1
        if item[0]==8:
            a8 += 1
        if item[0]==9:
            a9 += 1
        if item[0]==10:
            a10 += 1
        if item[0]==11:
            a11 += 1
        if item[0]==12:
            a12 += 1
        if item[0]==13:
            a13 += 1
        if item[0]==14:
            a14+=1
        if item[0]==15:
            a15+=1
        if item[0]==16:
            a16+=1
        if item[0]==17:
            a17+=1
        if item[0]==18:
            a18 += 1
        if item[0]==19:
            a19+=1
        if item[0]==20:
            a20+=1
        if item[0]==21:
            a21+=1
        if item[0]==22:
            a22+=1
        if item[0]==23:
            a23+=1
        if item[0]==24:
            a24+=1
        if item[0]==25:
            a25+=1
        if item[0]==26:
            a26+=1
        if item[0]==27:
            a27+=1
        if item[0]==28:
            a28+=1
        if item[0]==29:
            a29+=1
        if item[0]==30:
            a30+=1
        if item[0]==31:
            a31+=1
        if item[0]==32:
            a32+=1
        if item[0]==33:
            a33+=1
        if item[0]==34:

Цей Конкурс зараз завершений

Якщо ви хочете додати відповідь, я побачу, чи можу я обійтись, щоб додати таблицю результатів після виклику під тим, який буде оригінальним для учасників. Я додаю це, як тільки програма тестування закінчується (можливо, ще 2-3 дні).

ЗАКЛЮЧНІ ВИГОДИ !!!!!

Tit for Tat: 18
Random Pick: 28
Cooperator: 19
Defector: 24
Lucky Tit for Tat: 23
Random Tit for Tat: 23
Remorseful Aggressor: 22
Every Other C: 23
Nice Guy: 18
Tit for Tat Backstab: 15
Gentle Defector: 22
Anticapitalist: 27
Grim Trigger: 19
Bizzaro: 21
NeoAnticapitalist: 24
Ten Tits for a Tat: 240
Bitter Tat: 12
Copy First: 30
Exploitative Tat: 19
Six Tits for a Tat: 16
Thirty Tits for Tat: 4129
Five Tits for a Tat: 22
Forty Tits for a Tat: 1972
Three Tits for a Tat: 22
Fifty Four Tits for a Tat: 25805
The Elephant: 31
Extra Bitter Tat: 28
Fox: 35
Game of Thrones: 11297
The Boy: 31
Grimace: 26
Sore Loser: 39
Every Other D: 18
Twenty Five Tits for a Tat: 2399
Fifty Three Tits for a Tat: 5487
Handshake: 28
Anty: 26
Kinda Tits for Tat: 20
Prudent Defector: 154539
Bizzarro Trigger: 25
Young Mathematician: 21
Older Mathematician: 16
Perfect Gentleman: 1953341

Отже, виявляється, що Ідеальний Джентльмен - переможець. Вітаємо Драко18, який безумовно заслуговує своєї зеленої галочки.


Коментарі не для розширеного обговорення; ця розмова перенесена в чат .
Денніс

1
ПРИМІТКА: Якщо ви редагуєте свою програму, будь ласка, дайте мені коментар, так що я зауважую, інакше вона не може бути покладена на скринінг на весь час !!!!!!!!!!!!!!!!!!!! !!!
Грифон

Yikes! Я тільки зрозумів, скільки це імпорт.
Грифон

1
Гей, Грифоне, ти працюєш над цим остаточним рейтингом? ;)
Draco18s більше не довіряє SE

Вибачте, я забув про це. Дайте мені трохи запустити.
Грифон

Відповіді:


8

Ідеальний пан

Я не маю хорошого опису цього бота. Я натрапив на пару потенційних оптимізацій, випробував їх, тонко налаштував і виявив бактерію, яка вкрай знищує конкуренцію. Натомість я прокоментував сам код, щоб пояснити, що він робить.

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]

Кілька значень було вибрано довільно за допомогою тестованих альтернатив, і значення тут наближаються до оптимальних у цій точці. Проти нинішнього поширення протиборчих фракцій, The Perfect Gentleman досягає повного домінування (100% популяції бактерій) приблизно 90% часу (плюс-мінус 3 процентні пункти).

Я ще не додав в «Математиків» своїх тестів, проте ці дві повинні слугувати лише для підживлення існуючих стратегій і не сильно змінювати результат.

Він керує хорошою частиною свого контролю за допомогою підпирання Defector, але це було дозволено за правилами (приклади стратегій були справедливою грою для націлювання). Це має побічний ефект також підсилення гри престолів, але це було ненавмисно, оскільки вони не відрізняються за критеріями, які я вибрав. Ці "типи дефектів" мають точку переваги в другому раунді і в результаті витягують декількох проблемних сусідів (типи N-T4T), і коли вони переробляють "Ідеальний джентльмен", вони витратили свою перевагу в очках і швидко споживаються.

Вірогідний 5% шансів, що всі перфектні джентльмени в першому раунді опиняться в парі з типами Defector і закінчують масове самогубство. У такому випадку один із n-T4t досягає тотального домінування (196 клітин 196). Дуже рідко одному з інших типів (Гра престолів, Хлопчик, Гримаса, Боліючий програш ...) вдається не вимерти повністю і набрати очко чи два.

Поточне моделювання (все ще триває до загальної кількості 200 ігор). Усі записи, набравши 0 оцінок, видалено. Схоже, гра престолів та 54-T4T розділили раунд (195 очок між ними) після того, як PG був ліквідований.

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

Назад синиця для Тата (з прощенням)

Це в основному Лаки Синиця для Тата (він же "Тит для Тата з прощенням"), який є "вирішеним" оптимальним рішенням (для деякого значення "щасливчика") з поворотом. Оскільки ми точно знаємо, скільки раундів триватиме гра, ця бактерія відступає у фінальний раунд, забезпечуючи таким чином корисний результат проти будь-якої іншої синиці для бактерій «Тат та Кооператор» (проти себе вона закінчується чистим нулем, так само, як якщо б вона мала співпрацювали). Завдяки 10% передачі це призводить до довгострокової переваги.

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"

Гіркий Тат

Гіркий Тат користується будь-яким спроби співпраці, що надаються ворогом, коли противник випереджає точки. Більшість бактерій пропонують оливкову гілку принаймні один раз протягом 200 раундів, а оскільки Гіркий Тат відстає в цілому, вони наберуть цих 5 балів у відчайдушному бажанні на одужання.

В іншому випадку це тит-за-тати за звичайною домінантною стратегією. Крім того, це трохи більше, ніж ривок, ніж його двоюрідний брат і задній куточок раніше, і не дає пробачення.

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"

Гіркий Тат був розроблений, дивлячись на поведінку інших ботів щодо Тіта для Тата та схеми, виражені в цих результатах, але не розрахований на явне протидію цим стратегіям: це все ще формула загального призначення.

Додатковий гіркий Тат

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"

Екстра гірко, шляхом раннього дефектування.


1
Будь ласка, змініть назву вашої функції, оскільки ця функція вже прийнята.
Грифон

@Gryphon Whoops, вибачте, я не зрозумів, що зробив це. Я фактично не кодую в Python, я просто розбив два біти коду разом.
Draco18s більше не довіряє SE

1
I suspect it will outperform NeoAnticapitalist by a small margin. Більше, як понад 30 000 балів.
Грифон


2
Я ціную, що ти зробив бота, щоб зробити цей кот уже не жартом
Руйнуючий лимон

8

Антикапіталіст

Ще один простий. Навіть матчі (починаючи з одного і того ж рахунку) ведуть себе майже як TitForTat, але головна ідея намагається пережити матч.

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

Ніжний дефектор

Моя ідея тут - дефекти, за винятком випадків, коли мій ворог зазвичай співпрацює. Хоча, вона починає співпрацювати.

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

NeoAnticapitalist

Поліпшення Антикапіталіста (або так я думаю). Я не бачу причин співпрацювати в останню чергу. Я також не бачу причин співпрацювати, коли я впевнений, що опонент цього не зробить.

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"

Я насправді здивований, що не думав про це, але це геніально. Не знаю, чи виграє вона, але я думаю, що це має працювати дуже добре.
Грифон

@Gryphon додав нового бота (і об'єднав моїх двох інших)
Masclins

@Gryphon дякую за обидва видання
Masclins

Без проблем, @AlbertMasclans
Грифон

З симуляцій, які я проводив, NeoAnticapitalist, схоже, взяв на себе керівництво з Backstabbing Tit для Tat.
Грифон

6

Покірний агресор

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"

Це розроблено для того, щоб "йти в ногу" з Defector, кожного разу дефектуючи проти нього, а також перемагаючи стратегії, що базуються на синицю.

Основна ідея полягає в тому, що ми починаємо з перемоги, але якщо опонент співпрацював з чергою 1, ми двічі співпрацюємо, щоб уникнути взаємного обвинувального циклу, уникаючи, таким чином, занадто великого штрафного штрафу. (Якщо пізніше противник зазнає поразки, ми не порушимо цикл; ми змусимо їх це зробити і, швидше за все, програємо гру.) Потім в кінці гри ми вибираємо випадковий час протягом останніх 5 поворотів, щоб забити ворога, завдаючи нам ще одного поразки, ніж вони, і, значить, до тих пір, поки ми не були занадто відсталими на точках перенесення, ми в кінцевому підсумку перемагаємо, не жертвуючи багато в плані перенесення в процесі. . (Рандомізація часового періоду означає, що ми, швидше за все, вступимо в першу чергу з backstab, а також, що цю стратегію не можна «налаштовувати», прагнучи зробити її назад на один виток раніше.)


Вітаю на місці №3! +1
Грифон

6

Похмурий тригер

Спрощений бот, щоб спробувати заповнити змагання

Він буде співпрацювати, якщо тільки ворог не зазнає дефектів, і в цьому випадку він неминуче переможе

def grimtriggerfunc(I, Do, Not, Care, enlist): return "d" if "d" in enlist else "c"

добре, здається, що це не спрацьовує через мета ntitsfortat, що дефектує рано


Поздравляємо на місці №5, +1.
Грифон

@Sleafar Мені було цікаво, хто буде такий підлий; _; нормально
Зруйнований лимон

5

Гра престолів

def gameofthronesfunc(counter, mypoints, enpoints, mylist, enlist):
    turn_to_betray = 140
    if counter >= turn_to_betray or mypoints > enpoints or "d" in enlist:
        return "d"
    else:
        return "c"

Ідея тут полягає в тому, що ніколи не можна програти, зраджуючи, тому єдиною причиною співпраці є те, якщо ти відстаєш. Він також має загальну основу інших відповідей T4T (без будь-якого прощення, тому що я не впевнений, чи є тут багато сенсу з іншими претендентами).

Чергу на зраду, можливо, потрібно буде змінити, щоб виграти, оскільки в рівній гонці виграє T4Ter, який зраджує першим, але проти дуже співпрацюючого бота, ви пропустите деякі життєві моменти. Я не впевнений, що вершина для цього пагорба, тому я просто збираюся на 140. Я не здивуюсь, якби це було набагато раніше.

Якщо це опиниться в чашці Петрі з T4Ter, який зраджує раніше, або перебіжчиком (тобто 146 T4T), то це повністю залежить від того, якщо GoT вже попереду (він залишиться попереду) або якщо вони рівні / GoT позаду , в цьому випадку переможець ранніх зрад.


Вітаю за третє місце! +1
Грифон

А тепер до секунди!
Грифон

Гра престолів веде досить боротьбу з ботом, який я зараз тестую. Проста стратегія працює для цього добре.
Draco18s більше не довіряє SE

4

Пощастила синиця для Тат

import os
def luckytitfortatfunc(num, i, d, c, enlist):
    lucky = ord(os.urandom(1))
    lucky = int(round(200 * float(lucky - 0) / 255.0))
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Я впевнений, що десь читав, що синиця для тата була найкращою стратегією. Я вирішив зробити можливість для інших програм викупити себе лише для того, щоб додати певну різноманітність. Тепер із належним генератором випадкових чисел (це дає мені перевагу, правда?).


В основному, це стратегія виграшу, руки вниз, весь час, як зазначено у вікіпедії . Єдина дисперсія - у ймовірності виходу із циклу дефектів «сини-за-тату» (що залежить від відповідності всіх інших записів).
Draco18s більше не довіряє SE

1
@ Draco18s Це виграшна стратегія для іншої системи балів, загальної системи балів. Базовий тит-за-тат ніколи не може виграти раунд, якщо він не несе в балі кілька очок, тому це не буде добре.
isaacg

@isaacg має рацію, і саме тому ця стратегія перебуває у 14-му з 18-ти (хоча я не маю права звинувачувати AH L у цьому, оскільки 18-та програма - моя.)
Грифон

4

Слон

Слон ніколи не забуває!

import re
def theelephantfunc(counter, mypoints, enpoints, mylist, enlist):
    interwoven = "".join(i for j in zip(mylist, enlist) for i in j)
    backwoven = interwoven[::-1]
    predict = re.match("^((?:..)*).*?(.).\\1(?:..)*$",backwoven)
    if(predict is None):
        return "c"
    predict = predict.groups()[1]
    if(predict == "d"):
        return "d"
    if(mypoints - enpoints >= 6):
        return "c"
    return "d"

Слон розглядає історію бою і намагається з'ясувати, що противник запланував. Він дивиться і на свої ходи, і на своїх ворогів!

Він намагається знайти найдовшу спільну групу, яка відповідає тому, що щойно сталося, і приймає те, що ворог зробив одразу після цього.

Якщо він не зможе це вирішити, Слон просто співпрацюватиме, оскільки дружба - це завжди відповідь.

Якщо він думає, що його опонент переможе, він теж переможе, не бажаючи втрачати свої важко зароблені очки.

Якщо він думає, що його опонент буде співпрацювати, але його менше, або рівно 6 очок, то він переможе, щоб утриматись.

І нарешті, якщо він думає, що його опонент буде співпрацювати, а у нього сильна лідерство, він співпрацюватиме.


Я чекав на щось подібне, яке спрацювало краще, ніж Ніцца Гай. Однак я не зможу протестувати його близько 8 годин, тому я повинен мати можливість оновити приблизно в 12-13.
Грифон

4

54 Сиськи для тату

def fiftyfourtitsfortatfunc (num, more, fun, me, en):
    сиськи = 54
    якщо "d" в en [-tits:] або num> = (200-циць):
        повернути "d"
    повернути "c"

Цікаво, чи все-таки це переможе?
Грифон

Це, здається, виграє прямо зараз!
Грифон

З повагою, ви вузько побили обох моїх топ-ботів!
Грифон

@Gryphon Я б зробив 5 сиськів за тату, якби я не був таким прихильним до інших моїх ботів :)
Alex

Я думаю, що це переходило б іншу сторону кривої. Я міг би протестувати і сам!
Грифон

3

Хороший хлопець

def niceguyfunc(counter, mypoints, enpoints, mylist, enlist):
  if counter < 2:
    return "c"

  mylast = mylist[-1]
  enlast = enlist[-1]
  last_found_index = -1

  for i, item in enumerate(mylist):
    if i == counter - 1:
      break
    if mylist[i] == mylast and enlist[i] == enlast:
      last_found_index = i

  if last_found_index == -1:
    return "c"
  else:
    if enlist[last_found_index + 1] == "c":
      return "c"
    else:
      return "d"

Намагається передбачити вихід противників, дивлячись на історію. Наприклад, якщо останні ходи були ( c, ворог d), він намагається знайти останнє виникнення точно таких же рухів.


3

Хакман [дискваліфіковано як очікувалося]

Гаразд, це, мабуть, буде виключено з конкурсу, але мені дуже хочеться його спробувати:

def hackmanfunc(counter, mypoints, enpoints, mylist, enlist):
        if enlist.count("#") > 0:
                return "c"
        elif counter >= 2 and enpoints > mypoints:
                return "d"
        elif counter == 198:
                return "d"
        elif counter == 199:
                return "#"
        elif counter == 0 or enlist[-1] == "c":
                return "c"
        elif counter >= 2 and enlist[-2] != "c":
                return "#"
        else:
                return "d"

Тут я беру за основу BackstabbingTitForTat, який виявився найкращим у своїх моделюваннях. Крім того, вона базується на використанні символу, що не використовується"#" який (саме тому я вважаю, що це буде виключено).

Тепер дозвольте мені пояснити умови:

1-е: Переконайтесь, що два Хакмена співпрацюють, якщо щось пішло не так.

2-е: Якщо я збираюсь програти проти іншого бота, принаймні змушуй його втратити якомога більше очок, тому згодом це не величезний ворог.

3-й: Зверніться за один поворот раніше, тому виграйте проти "Бюстгафінг"

використання "#" замість "d" змушує мене отримати 0 балів замість -1, а також спілкуватися з іншим Хакманом, у якого менше очок, тому він перестає дефектувати.


2
Вибачте, але дискваліфіковано. Це вважається возитися з процесом судження. Ви ОБОВ'ЯЗКОВО повертаєте або "c", або "d" кожен хід.
Грифон

2
Однак це досить винахідливо, тому мені шкода, що я мушу його дискваліфікувати.
Грифон

3

Bizzaro

Чи точна протилежність синиці для тата. Коли хтось добрий до нього, він виявляє свою любов тим, що є злим, а коли хтось середнім, він мститься, будучи добрим. Сильно заснована на синиці для тата.

def bizzarofunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "d"
    else:
        return "c"

Цікаво. Це вбиває Defector, хоча.
Грифон

@Gryphon Lmao, насправді цього не усвідомлював. Але ей, Bizzaro не знає різниці між правильним і неправильним, виграй і програй.
Тит Люкрецій

Так, це буде перешкодою для кооператора і кооператора до дефектора, що може зробити цікаві можливості. Він не може насправді співіснувати ні з чим іншим, включаючи себе.
Грифон

@Gryphon, так, він повинен отримувати 0, коли він грає сам. Поцікавтеся, що буде з Gentle Defector.
Тит Люкрецій

Поцікавтеся, що станеться, коли він стикається з титом для синиці, що саме вигравало до цього подання.
Грифон

3

6 сиськи для тату

def sixtitsforatatfunc (num, більше, весело, мені, en):
    якщо "d" в en [-6:] або num> = 194:
        повернути "d"
    повернути "c"

Тита для гонки на зброю Tat відбувається зараз :)


Я відчуваю, що ми перейдемо за борт, і Defector вкраде перше місце.
Грифон

3

Десять цицьки для тату

def tentitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-10:] or num >= 190:
        return "d"
    return "c"

Дефекти раніше, а також дефекти, якщо його опонент зазнав дефектів за останні десять оборотів.

CopyFirst

def copyfirstfunc(num, mypoints, enpoints, myhistory, enhistory):        
    if num == 0 or num >= 197:
        return "d"
    else:
        return enhistory[0]

Це перешкоджає першому раунду, потім робить все, що суперник робив перший раунд, аж до 197-го раунду, коли він заднім кроком.

Сорок цицьки для тату

def fourtytitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if "d" in en[-40:] or num >= 150:
        return "d"
    return "c"

Якщо опонент зазнав поразки протягом останніх 40 обертів, дефект, інакше співпрацюйте. Заднє коло за останні 50 оборотів.

Три сиськи для тату

Якщо опонент зазнав поразки протягом останніх 3 оборотів, дефект, інакше співпрацюйте. Заднє коло за останні 5 оборотів. Ця програма вкрала лідерство у Tit for Two Tats з вузьким відривом.

def threetitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if num == 0 or num==1 and enhistory[-1]=="c" or num==2 and enhistory[-1]=="c" and enhistory[-2]=="c":
        return "c"
    if enhistory[-1] == "d" or enhistory[-2] == "d" or enhistory[-3] == "d" or num >= 195:
        return "d"
    else:
        return "c"

П'ять цицьки для тату

def fivetitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-5:] or num >= 194:
        return "d"
    return "c"

Якщо ви не можете зрозуміти, що це робить, ви ідіот. Також назад на один раунд.


IMO, не соромтеся подати власний запис.
Draco18s більше не довіряє SE

Просто не був впевнений, чи це взагалі вважається справедливим.
Грифон

Однак зазвичай загальним є те, що Best Answer - це бот, який виграє.
Masclins

Буде, я не буду просто вибирати власну відповідь. Це точно не було б справедливо.
Грифон

Прошу вибачення, я не зрозумів, що випадково прийняв свою відповідь. Зараз це не прийнято, і я прийму найкращу відповідь з 1 липня.
Грифон

3

Гримаса

def grimacefunc(I, Do, Not, Care, enlist):
    if round < 123: return "d" if "d" in enlist else "c"
    return "d"

Начебто таке "оптимальне" рішення для цього пагорба - зробити щось подібне (T4nT з n> 5 - це в основному це) і просто оптимізувати раунд, коли він зраджує. Все, що більш творче, буде знищене.
Роберт Фрейзер

3

Кожен інший D

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "d"
    else:
        return "c"

Кожен інший С

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "c"
    else:
        return "d"

Maybe you should submit another entry starting with cooperate.
Gryphon

Just thought it might be interesting.
Gryphon

3

Predictable Mathematicians:

Young Mathematician

New to the harshness of the world

import math
def ymathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.sin(num) + 0.8 > 0):
    return 'c'
  else:
    return 'd'

Older Mathematitian

More experienced in these matters

import math
def omathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.cos(num) + 0.8 > 0):
    return 'd'
  else:
    return 'c'

I doubt either of these will do well, but at least they'll add ways for others to get points!


Neither of these are going to do well, heh. All they do is feed the defectors, for the most part.
Draco18s no longer trusts SE

2

Randomized Tit For Tat

import os
def randomtitfortatfunc(forgot, ten, var, iables, enlist):
    luck = enlist.count("d") + 1
    choice = ord(os.urandom(1))
    choice = int(round(luck * float(choice - 0) / 255.0))
    if choice == 0:
        return "c"
    return "d"

Tit For Tat, but randomized. This is not going to win any prizes (unless I'm really lucky). Now with random numbers generated from a proper source.


2

Exploitative Tat

Exploitative Tat tries to play the following strategies:

  • Defect when behind. It's the only way to catch up.

  • Cooperate against tit-for-tat and similar strategies. It's the only way to get a good long-term score.

  • Defect against always-cooperators and other chumps.

  • Defect 5 rounds early.

Here's the code:

def exploitativetatfunc(num, mypoints, enpoints, mylist, enlist):
    if mypoints < enpoints:
        return "d"
    if num >= 195:
        return "d"
    if num == 0:
        return "c"
    # Test defect, and keep defecting as long as they'll allow
    if (num == 5 or num >= 8) and all(choice == "c" for choice in enlist):
        return "d"
    # Recover if that goes wrong, and they were nice.
    if (num == 6 or num == 7) and all(choice == "c" for choice in enlist[:4]):
        return "c"
    # Otherwise, tit for tat.
    return enlist[-1]

I'm surprised this didn't do better than tie for 8th, but I think it was just the wrong time for it, and it was unfortunately entered at the same time as Two Tits for a Tat.
Gryphon

2

30 Tits for a Tat

def thirtytitsfortatfunc(num, more, fun, me, en):
    tits = 30
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

2

but what if... the next answer was not grim trigger or something for tat

I present

Anty

def antyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter > 150: return "d"
    if not "c" in enlist[-2:]:
        return "d"
    if enpoints >= mypoints:
        return "d"
    else:
        return "c"

Intersting, will test when I get home.
Gryphon

2

Fox

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

Defects if the round number is greater than the enemies points, cooperates otherwise.

The Boy

def boyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter!=0 and enlist[-1]=="c" and counter <= 194 or enpoints+10<mypoints:
        return "c"
    return "d"

Cooperates first round, then acts for tit for tat but backstabs on the last five rounds, and defects if it isn't ten points ahead.

53 tits for a tat

def fiftythreetitsfortatfunc(num, more, fun, me, en):
    tits = 53
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

You all know what this is :)


2

Twentyfivetitsforatat

def twentyfivetitsfortatfunc(num, more, fun, me, en):
    tits = 25
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

Kinda titsforatat

def kindatitsfortatfunc(num, more, fun, me, en):
    tits = 54  
    if "c" in en[-tits:] or num >= (200-tits):
        return "c"
    return "d"

Next time you edit to add a program, please also add a comment so I get alerted. Thanks!
Gryphon

@Gryphon oh sorry
Christopher

2

Prudent Betrayer

def PrudentBetrayer(counter, mypoints, enpoints, mylist, enlist):
    # Am I ahead, even if he betrays first?
    if mypoints > enpoints + 5:
        if counter == 0:
            return "c"
        else:
            return enlist[-1]
    # Can I catch up if I betray first?
    elif mypoints + 5 > enpoints:
        if counter == 0:
            return "c"
        elif counter > 130:
            return "d"
        else:
            return "d" if "d" in enlist else "c"
    # can't win -> kill his score
    else:
        return "d"

Assumes it is fighting an n-tits-for-a-tat bot. If it has the score to be betrayed and still win, it will let the other bot hit it first (playing as tit for tat.) If it can win only when it betrays first, It will betray on round 130, well before any current bot. If it is many points behind its opponent, it will just play defector in an attempt to lower the unsuspecting bots score.


Handshake

import random
def handshakefunc(num, me, him, m, en):
    handshake = "cdccd"
    # For the first few rounds, give the handshake.
    if num < len(handshake):
        if m == en:
            return handshake[num]
        return "d"
    if en[:len(handshake)] == handshake:
        if me > him:
            return "d"
        if me == him:
            return "ccd"[random.randint(0,2)]
        return "c"
    return "d"

Uses the pattern cdccd on the first five rounds, to find out if it is with itself. If so, it will try to max its points by having the bot with more points always defect, while the other always cooperates. If it finds it is fighting an enemy, it will play the defector.

In my tests, I find it dose well if it makes up a significant portion of the population. When it dose not have a chance to fight itself, it will basically be reduced to a defector.

EDIT: Clearly from the scores, their are to many bots for this to work well. It will still win if fighting just the top few...


Bizzaro Trigger

def bizzaroTriggerfunc(round,ms,ts,mm,tm):
  if round==1:return 'c'
  if 'c' in tm:return'd'
  return 'c'

Always cooperate, unless your opponent ever cooperates with you, in which case you defect. Always.


@Gryphon the sore loser was removed, and a new bot added!
MegaTom

In the test I'm running now on a bot I haven't yet posted, Handshake is in 2nd place after 390 games (5338 surviving bots) outdoing 54-T4T by about 1200. My new bot is much stronger than even that, though. Initial tests had it scoring 196 out of 196, though long-run it's scoring an average of ~124 / game. Interestingly enough, the basis behind Handshake was what I was going to try next, turns out you beat me to it without my realizing it.
Draco18s no longer trusts SE

0

FakeShake

takes advantage of handshake- does a handshake then just defects while handshake trusts it. When it meets itself, however, it does the 'real' handshake. If it meets a different bot it plays tit for tat, with a betrayal at the end. This feels kinda mean...

import random
def fakeshakefunc(num, i, d, m, enlist):
      secret_handshake="cdccdd"
      handshake= "cdccd"
      #checks if it is meeting itself
      if enlist[:len(secret_handshake)] == secret_handshake:
          if me > him:
            return "d"
          if me == him:
             return "ccd"[random.randint(0,2)]
          return "c"
      #does handshake's handshake,if the bot is not handshake or fakeshake it plays T4T
      if num < len(handshake):
            if m == enlist:
                return handshake[num]
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"
            if enlist[:len(handshake)] == handshake:
                return "d"
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"

One problem with this is that if it meets handshake and it has more points, it thinks its playing itself. I'm a newbie to python and this site (in fact this is my first answer) so make sure to tell me if I've made any stupid mistakes!


Welcome to PPCG!
Laikoni

@Laikoni Thanks!
Arkine
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.