1P5: Dilema Tahanan Iterasi


35

Tugas ini merupakan bagian dari Push Puzzle Pemrograman Premier Periodik Pertama dan dimaksudkan sebagai demonstrasi proposal tipe tantangan -baru .

Tugasnya adalah menulis program untuk memainkan dilema tahanan yang diulang lebih baik daripada peserta lainnya.

Lihat, Vinny. Kami tahu teman satu selmu --- siapa namanya? Ya McWongski, mafia Nippo-Irlandia-Ukrania - terserah sesuatu dan Anda tahu apa itu.

Kami berusaha bersikap baik di sini, Vinnie. Memberi Anda kesempatan.

Jika Anda memberi tahu kami apa yang dia rencanakan, kami akan melihat Anda mendapat tugas kerja yang baik.

Dan jika Anda tidak ...

Aturan main

  • Kontes ini terdiri dari round-robin penuh (semua pasangan mungkin) dari dua kontestan pada suatu waktu (termasuk bermain sendiri).
  • Ada 100 putaran yang dimainkan antara masing-masing pasangan
  • Dalam setiap putaran masing-masing pemain diminta untuk memilih antara bekerja sama dengan pemain lain atau mengkhianati mereka, tanpa mengetahui niat pemain lain dalam masalah ini, tetapi dengan memori hasil putaran sebelumnya dimainkan melawan lawan ini.
  • Poin diberikan untuk setiap putaran berdasarkan pilihan gabungan. Jika kedua pemain bekerja sama, masing-masing mendapat 2 poin. Pengkhianatan timbal balik menghasilkan masing-masing 1 poin. Dalam kasus campuran, pemain yang mengkhianati diberikan 4 poin dan kooperator dihukum 1 poin.
  • Pertandingan "resmi" akan berjalan tidak lebih cepat dari 10 hari setelah memposting dengan semua kiriman yang saya dapat mulai bekerja dan digunakan untuk memilih pemenang yang "diterima". Saya memiliki kotak Mac OS 10.5, jadi solusi POSIX harus bekerja, tetapi ada linuxisms yang tidak. Demikian juga, saya tidak memiliki dukungan untuk API win32. Saya bersedia melakukan upaya dasar untuk menginstal sesuatu, tetapi ada batasnya. Batas-batas sistem saya sama sekali tidak mewakili batas-batas respons yang dapat diterima, hanya batas-batas yang akan dimasukkan dalam pertandingan "resmi".

Antarmuka Programmer

  • Entri harus dalam bentuk program yang dapat dijalankan dari baris perintah; keputusan harus keluaran (tunggal!) dari program pada keluaran standar. Sejarah putaran sebelumnya dengan lawan ini akan disajikan sebagai argumen baris perintah.
  • Outputnya bisa berupa "c" (untuk clam up ) atau "t" (untuk semua ).
  • Sejarah adalah string tunggal karakter yang mewakili babak sebelumnya dengan putaran terbaru yang paling awal dalam string. Karakternya adalah
    • "K" (untuk menjaga iman yang berarti kerja sama)
    • "R" (untuk tikus b @ st @ rd terjual habis! )
    • "S" (untuk pengisap! Artinya Anda mendapat manfaat dari pengkhianatan)
    • "E" (untuk semua orang mencari nomor satu pada pengkhianatan timbal balik)

Braket

Empat pemain akan disediakan oleh penulis

  • Malaikat - selalu bekerja sama
  • Iblis - selalu berbicara
  • TitForTat - Bekerja sama di babak pertama lalu selalu melakukan apa yang dia lakukan di babak terakhir
  • Acak - 50/50

di mana saya akan menambahkan semua entri yang bisa saya jalankan.

Skor total akan menjadi skor penjumlahan terhadap semua lawan (termasuk permainan mandiri hanya sekali dan menggunakan skor rata-rata).

Peserta

(saat ini pada 2 Mei 2011 7:00)

Jabat Tangan Rahasia | Rudal Anti-T42T | Ketidakpercayaan (varian) | Anti-Jabat Tangan | The Little Lisper | Konvergensi | Hiu | Probabimatic | Pavlov - Menangkan Menginap, Kalah Beralih | Hormatilah Pencuri | Bantu Vampir | Druid | Schemer Kecil | Dulu | Gayung Dua Tats | Simpleton |

Pencetak gol

#! /usr/bin/python
#
# Iterated prisoner's dilemma King of Hill Script Argument is a
# directory. We find all the executables therein, and run all possible
# binary combinations (including self-plays (which only count once!)).
#
# Author: dmckee (https://codegolf.stackexchange.com/users/78/dmckee)
#
import subprocess 
import os
import sys
import random
import py_compile

###
# config
PYTHON_PATH = '/usr/bin/python' #path to python executable

RESULTS = {"cc":(2,"K"), "ct":(-1,"R"), "tc":(4,"S"), "tt":(1,"E")}

def runOne(p,h):
    """Run process p with history h and return the standard output"""
    #print "Run '"+p+"' with history '"+h+"'."
    process = subprocess.Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)
    return process.communicate()[0]

def scoreRound(r1,r2):
    return RESULTS.get(r1[0]+r2[0],0)

def runRound(p1,p2,h1,h2):
    """Run both processes, and score the results"""
    r1 = runOne(p1,h1)
    r2 = runOne(p2,h2)
    (s1, L1), (s2, L2) = scoreRound(r1,r2), scoreRound(r2,r1) 
    return (s1, L1+h1),  (s2, L2+h2)

def runGame(rounds,p1,p2):
    sa, sd = 0, 0
    ha, hd = '', ''
    for a in range(0,rounds):
        (na, ha), (nd, hd) = runRound(p1,p2,ha,hd)
        sa += na
        sd += nd
    return sa, sd


def processPlayers(players):
    for i,p in enumerate(players):
        base,ext = os.path.splitext(p)
        if ext == '.py':
            py_compile.compile(p)
            players[i] = '%s %sc' %( PYTHON_PATH, p)
    return players

print "Finding warriors in " + sys.argv[1]
players=[sys.argv[1]+exe for exe in os.listdir(sys.argv[1]) if os.access(sys.argv[1]+exe,os.X_OK)]
players=processPlayers(players)
num_iters = 1
if len(sys.argv) == 3:
    num_iters = int(sys.argv[2])
print "Running %s tournament iterations" % (num_iters)
total_scores={}
for p in players:
    total_scores[p] = 0
for i in range(1,num_iters+1):
    print "Tournament %s" % (i)
    scores={}
    for p in players:
        scores[p] = 0
    for i1 in range(0,len(players)):
        p1=players[i1];
        for i2 in range(i1,len(players)):
            p2=players[i2];
#        rounds = random.randint(50,200)
            rounds = 100
            #print "Running %s against %s (%s rounds)." %(p1,p2,rounds)
            s1,s2 = runGame(rounds,p1,p2)
            #print (s1, s2)
            if (p1 == p2):
                scores[p1] += (s1 + s2)/2
            else:
                scores[p1] += s1
                scores[p2] += s2

    players_sorted = sorted(scores,key=scores.get)
    for p in players_sorted:
        print (p, scores[p])
    winner = max(scores, key=scores.get)
    print "\tWinner is %s" %(winner)
    total_scores[p] += 1
print '-'*10
print "Final Results:"
players_sorted = sorted(total_scores,key=total_scores.get)
for p in players_sorted:
    print (p, total_scores[p])
winner = max(total_scores, key=total_scores.get)
print "Final Winner is " + winner
  • Keluhan tentang python mengerikan saya diterima, karena saya yakin ini menyebalkan lebih dari satu cara
  • Perbaikan bug diterima

Daftar Perubahan Pencetak Gol:

  • Cetak pemain dan skor yang diurutkan, dan nyatakan pemenang (29/4, Casey)
  • Menjalankan beberapa turnamen secara opsional ( ./score warriors/ num_tournaments)) default = 1, mendeteksi & mengkompilasi sumber python (4/29, Casey)
  • Perbaiki bug yang sangat bodoh di mana pemain kedua melewati sejarah yang salah. (4/30, dmckee; terima kasih Josh)

Prajurit awal

Sebagai contoh, dan agar hasilnya dapat diverifikasi

malaikat

#include <stdio.h>
int main(int argc, char**argv){
  printf("c\n");
  return 0;
}

atau

#!/bin/sh
echo c

atau

#!/usr/bin/python
print 'c'

setan

#include <stdio.h>
int main(int argc, char**argv){
  printf("t\n");
  return 0;
}

Acak

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char**argv){
  srandom(time(0)+getpid());
  printf("%c\n",(random()%2)?'c':'t');
  return 0;
}

Perhatikan bahwa pencetak gol dapat memanggil kembali prajurit berkali-kali dalam satu detik, jadi upaya serius harus dilakukan untuk memastikan keacakan hasil jika waktu digunakan untuk seed PRNG.

TitForTat

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char**argv){
  char c='c';
  if (argv[1] && (
          (argv[1][0] == 'R') || (argv[1][0] == 'E')
          ) ) c='t';
  printf("%c\n",c);
  return 0;
}

Yang pertama yang benar-benar melakukan sesuatu dengan sejarah.

Menjalankan pencetak gol hanya pada hasil prajurit yang disediakan

Finding warriors in warriors/
Running warriors/angel against warriors/angel.
Running warriors/angel against warriors/devil.
Running warriors/angel against warriors/random.
Running warriors/angel against warriors/titfortat.
Running warriors/devil against warriors/devil.
Running warriors/devil against warriors/random.
Running warriors/devil against warriors/titfortat.
Running warriors/random against warriors/random.
Running warriors/random against warriors/titfortat.
Running warriors/titfortat against warriors/titfortat.
('warriors/angel', 365)
('warriors/devil', 832)
('warriors/random', 612)
('warriors/titfortat', 652)

Iblis itu, dia seorang perajin, dan orang-orang baik tampaknya datang terakhir.

Hasil

dari menjalankan "resmi"

('angel', 2068)
('helpvamp', 2295)
('pavlov', 2542)
('random', 2544)
('littleschemer', 2954)
('devil', 3356)
('simpleton', 3468)
('secrethandshake', 3488)
('antit42t', 3557)
('softmajo', 3747)
('titfor2tats', 3756)
('convergence', 3772)
('probabimatic', 3774)
('mistrust', 3788)
('hyperrationalwasp', 3828)
('bygones', 3831)
('honoramongthieves', 3851)
('titfortat', 3881)
('druid', 3921)
('littlelisper', 3984)
('shark', 4021)
('randomSucker', 4156)
('gradual', 4167)
        Winner is ./gradual

2
Jika teman satu sel saya adalah Nippo-Irlandia-Ukraina, mengapa namanya terlihat Hiberno-Sino-Rusia?
Peter Taylor

2
@ Peter: LOL. Kebenaran? Nah, (1) silsilah tidak jelas, tapi aku mungkin datang saya mic'edness dengan cara Scotch-Irlandia; (2) setelah saya menulis "Nippo", saya mencoba berbagai bit nama teman-teman saya dari negeri matahari terbit dan tidak suka cara mereka memindai, jadi saya pergi ke depan dan menggunakan nama keluarga Cina yang terdengar bagus sebagai gantinya, dan (3) saya tidak akan tahu bedanya jika mereka secara bergantian memukuli saya dengan setrika. Yang sepertinya mungkin dalam keadaan.
dmckee

1
@Josh: Apakah mudah untuk mengubah return (s1, L1+h1), (s2, L2+h1)ke return (s1, L1+h1), (s2, L2+h2)[Note L2+h2bukannya L2+h1di akhir]? // Kesalahan cut-n-paste atau sesuatu yang sama bodohnya. Sheesh!
dmckee

2
Saya telah menghabiskan beberapa waktu pada skrip tes, dan saya senang mengumumkan pembaruan di sini . Pembaruan ini menambahkan shell sederhana ke skrip pengujian, yang memungkinkan pengguna untuk menjalankan bot ini secara manual vs. bot itu, menjalankan turnamen dengan bidang terbatas dan beberapa hal keren lainnya. Jangan ragu untuk memberikan saran! Oh Dan saya berhutang pada @josh untuk ide bot-vs-bot. Ini benar-benar hanya implementasi yang lebih bagus dari skrip "trainer" -nya.
arrdem

2
Menarik: Ada 23 kontestan, jadi masing-masing bermain 22 putaran. Jika semua orang bermain "Angel" setiap skor pasti 4400, tetapi bahkan skor terbaik 4167 tidak cocok dengan itu. Kalau saja kita hidup di dunia yang sempurna ... :)
Briguy37

Jawaban:


11

Bertahap

Strategi ini didasarkan pada sebuah makalah oleh Beaufils, Delahaye dan Mathieu . C saya benar-benar bukan yang terbaik, jadi jika ada yang punya saran untuk meningkatkan / mempercepat kode, beri tahu saya!

[Sunting] Layak untuk dicatat adalah bahwa Gradual dirancang untuk menjadi strategi yang mengungguli Tit untuk Tat. Ia memiliki sifat yang serupa dalam hal ia bersedia untuk bekerja sama dan membalas terhadap lawan yang membelot. Tidak seperti Tit untuk Tat, yang hanya memiliki ingatan tentang babak terakhir yang dimainkan, Gradual akan mengingat interaksi lengkap dan cacat berapa kali lawan telah membelot sejauh ini. Akan tetapi, itu akan menawarkan kerja sama timbal balik lagi.

Seperti biasa, kinerja strategi sedikit tergantung pada susunan strategi lainnya. Juga kertas asli tidak benar-benar jelas pada beberapa detail.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if(argc == 1){
        printf("c\n");
        return 0;
    }

    size_t l = strlen(argv[1]);
    int i;
    size_t currentSequence = 0;
    size_t totalDefects = 0;
    size_t lastDefects = 0;

    for(i = l-1; i >= 0; i--){
        if(argv[1][i] == 'E' || argv[1][i] == 'R'){
            totalDefects++;
            currentSequence = 0;
        } else if(argv[1][i] == 'S') {
            currentSequence++;
        }
    }

    if(currentSequence < totalDefects)
        // continue defect sequence
        printf("t\n");
    else if(argv[1][0] == 'S' || argv[1][0] == 'E' ||
            argv[1][1] == 'S' || argv[1][1] == 'E')
        // blind cooperation
        printf("c\n");
    else if(argv[1][0] == 'R')
        // start new defect sequence
        printf("t\n");
    else
        printf("c\n");

    return 0;
}

11

Jabat Tangan Rahasia

#!/usr/bin/python
import sys
import random

def main():
    if len(sys.argv) == 1:
        hist = ""
    else:
        hist = sys.argv[1]
    if len(hist) <= len(TAG) and hist == TAGMATCH[len(TAG) - len(hist):]:
        print TAG[len(TAG) - len(hist) - 1]
        return
    if hist[-len(TAG):] == TAGMATCH:
        print 'c'
        return
    print "t"

def getTag():
    global TAG
    filename = sys.argv[0]
    filename = filename.replace(".pyc", ".py")
    f = open(filename, 'r')
    code = f.read().split('\n')
    f.close()
    if len(code[1]) == 0 or code[1][0] != '#':
        random.seed()
        newtag = 't' * 10
        cs = 0
        while cs < 3:
            pos = random.randint(0, 8)
            if newtag[pos] == 't':
                newtag = newtag[:pos] + 'c' + newtag[pos+1:]
                cs += 1
        code.insert(1, '#%s' % newtag)
        f = open(filename, 'w')
        f.write('\n'.join(code))
        f.close()
        TAG = newtag
    else:
        TAG = code[1][1:]
    global TAGMATCH
    TAGMATCH = TAG.replace('c', 'K').replace('t', 'E')

if __name__ == "__main__":
    getTag()
    main()

Strategi di sini adalah mengorbankan 10 putaran pertama untuk melakukan jabat tangan "rahasia". Jika saya bersel dengan diri saya sendiri, saya kemudian mengenali sejarah 10 langkah pertama dan memakai topi Malaikat saya untuk sisa permainan. Segera setelah saya menyadari bahwa teman satu sel saya bukan diri saya sendiri, saya berubah menjadi Iblis dalam upaya untuk mengambil keuntungan dari teman sel yang terlalu kooperatif.

Apakah dengan mengorbankan 10 putaran pertama akan memungkinkan saya untuk menyingkirkan Iblis itu sendiri sangat bergantung pada berapa banyak entri yang ada. Untuk meminimalkan kerusakan, hanya 3 yang bekerja sama muncul di jabat tangan.

Sunting: TAGMATCH dinamis sekarang untuk mencegah kesalahan bodoh seperti hanya mengubah salah satunya dan agar saya dapat membuat TAG dinamis di beberapa titik di masa mendatang.

Sunting 2: Sekarang menghasilkan tag secara acak pada jalankan pertama dan menyimpannya dalam file yang ditentukan oleh sys.argv[0]( .pycdiganti dengan .pyjadi pergi ke kode, bukan bytecode, file). Saya pikir ini adalah satu-satunya informasi yang dimiliki semua contoh saya yang tidak dimiliki orang lain, jadi sepertinya satu-satunya pilihan untuk menghindari parasit.


Tapi bagaimana doppelgangermu tahu untuk menjadikan dirinya setan?
arrdem

1
(Saya merasa seperti burung beo, mengatakan "Tit untuk Tat" setiap saat ...) Perhatikan bahwa T4T akan mengalahkan strategi Anda dalam berpasangan dengan: T4T (bekerja sama sebelumnya) dan Iblis (hasil Tikus lebih sedikit), dan akan mengikat dengan Anda strategi. Tentu saja, total keseluruhan, bukan total pasangan, adalah yang terpenting pada akhirnya. Seperti yang Anda katakan, populasi itu penting.
Josh Caswell

1
Oh, tidak, Anda mendapatkan satu S ekstra dari Tit for Tat. Bagus. Saya tidak menyadari TAGsedang diputar mundur. Namun, bukankah seharusnya Anda TAGMATCHmenjadi 'KEEEKEEEKE'? "".join({('c', 'c'):'K', ('t', 't'): 'E'}[moves] for moves in zip(TAG, TAG))
Josh Caswell

@John Good point - Saya awalnya memiliki TAG yang berbeda dan ketika saya mengubahnya untuk meminimalkan kerja sama, saya lupa memperbarui TAGMATCH. @Arrdem Idenya adalah jika saya bermain melawan diri saya sendiri, hal terbaik yang harus dilakukan adalah bekerja sama sepanjang waktu untuk memaksimalkan jumlah skor mereka.
Aaron Dufour

1
Aww, sial. Jadi sekarang saya harus mencari semua .pyfile untuk kode Anda dan mengekstrak TAG. Saya tidak akan melakukan itu di C, ...
Joey

6

Si Kecil Lisper

(setf *margin* (/ (+ 40 (random 11)) 100))
(setf *r* 0.0)
(setf *s* 0.0)
(setf *k* 0.0)
(setf *e* 0.0)

;; step 1 - cout up all the games results

(loop for i from 1 to (length(car *args*)) do
    (setf foo (char (car *args*) (1- i)))
    (cond 
        ((equal foo #\R) (setf *r* (1+ *r*)))
        ((equal foo #\S) (setf *s* (1+ *s*)))
        ((equal foo #\K) (setf *k* (1+ *k*)))
        ((equal foo #\E) (setf *e* (1+ *e*)))
    )
)

(setf *sum* (+ *r* *s* *k* *e*))

;; step 2 - rate trustworthiness
(if (> *sum* 0)
    (progn
        (setf *dbag* (/ (+ *r* *e*) *sum*)) ; percentage chance he rats
        (setf *trust* (/ (+ *s* *k*) *sum*)); percentage chance he clams
    )
    (progn
        (setf *dbag* 0) ; percentage chance he rats
        (setf *trust* 0); percentage chance he clams
    )
)



;; step 3 - make a decision (the hard part....)

(write-char
    (cond
        ((> *sum* 3) (cond 
                    ((or (= *dbag* 1) (= *trust* 1)) #\t) ; maximizes both cases
                                                          ; takes advantage of the angel, crockblocks the devil
                    ((> (+ *dbag* *margin*) *trust*) #\t) ; crockblock statistical jerks
                    ((< *dbag* *trust*) #\c)              ; reward the trusting (WARN - BACKSTABBING WOULD IMPROVE SCORE)
                    ((and
                        (= (floor *dbag* *margin*) (floor *trust* *margin*))
                        (not (= 0 *dbag* *trust*)))
                        #\t)                              ; try to backstab a purely random opponent, avoid opening w/ a backstab
                    )
        )
        (t #\c)                                            ; defalt case - altruism
    )
)

Iblis

Pertimbangkan yang berikut ini, format (Player1, Player2)

  • (C, T) - P2 mendapatkan EMPAT POIN untuk pengkhianatannya, sementara P1 MENGHAPUS SATU
  • (T, T) - P2 DAN P1 GAIN 1

Dengan asumsi bahwa P2 adalah iblis, tidak mungkin iblis kehilangan poin, bahkan hal terburuk yang dapat ia lakukan adalah mendapatkan hanya satu poin. Oleh karena itu, melawan lawan yang murni acak, skor terburuk iblis akan tepat (5/2) * n di mana n adalah jumlah "permainan" yang dimainkan. Kasus terburuk absolutnya adalah melawan dirinya sendiri, di mana skornya akan n, dan kasus terbaiknya adalah melawan malaikat, yang akan menjadi 4 * n

Menegaskan: optimal_strat = iblis

ini pertandingan. Melakukan backstabbing pada teman satu sel saya adalah strategi yang jauh lebih baik daripada kerja sama karena ini membantu skor saya lebih banyak (+4). BONUS - dia terbanting (-1)! Jika saya menjulurkan leher untuknya, saya berdiri untuk mendapatkan (+2) dan longgar (-1). Oleh karena itu, pengkhianatan secara statistik dihargai.

Tetapi apakah itu optimal?

Tidak ada alasan untuk PERNAH (di bawah sistem penilaian ini) bekerja sama.

  • Jika Anda memilih waktu yang salah untuk tutup mulut, Anda kalah.
  • Jika Anda tikus, setidaknya Anda tidak kehilangan apa pun.
  • Jika Anda tikus dan dia bodoh, Anda mendapatkan 2x lebih banyak daripada jika Anda telah menjadi orang baik.

Dalam sistem KOTH, memaksimalkan pengembalian sangat penting. Bahkan jika Anda memiliki dua bot yang disinkronkan dan bekerja sama dengan sempurna, skor individu mereka hanya akan dikuatkan oleh 200 poin untuk sportivitas mereka. Iblis di sisi lain akan mendapatkan setidaknya 100 poin, dengan kasus rata-rata 200 dan maksimum 400, dan biaya lawan-lawannya masing-masing hingga 100 poin! Jadi bisa dibilang, iblis benar-benar skor rata-rata 300 permainan, naik menjadi 500.

Intinya - waktu akan memberi tahu

Bagi saya, sepertinya skor harus dipertimbangkan kembali agar iblis tidak mengambil hari itu. Meningkatkan skor kerjasama ke 3 semua mungkin melakukannya. Namun dimungkinkan untuk mendeteksi setan dan mencegah mereka dari mencetak 400 penuh mereka, seperti pavlov dan dendam menunjukkan. Dapatkah saya membuktikan bahwa salah satu dari mereka akan mengambil poin yang cukup untuk kerja sama mereka untuk membenarkan iman mereka? tidak. Semua itu tergantung pada bidang final pesaing.

GL, HF!

Dan tolong lakukan yang terburuk untuk posting ini. Saya ingin menulis makalah senior saya tentang ini ketika semua dikatakan dan dilakukan.

Riwayat versi

  1. Menambahkan variabel margin yang mengubah toleransi Lisper untuk duchebaggery secara acak.
  2. Bising diperbarui untuk berdamai untuk dua putaran pertama untuk turun di kaki kanan dengan lawan koperasi
  3. Menggunakan algoritma genetika untuk menemukan nilai yang paling kuat untuk generator threshold acak berdasarkan skor kumulatif maksimumnya terhadap set standar lawan. Diposting pembaruan termasuk mereka.

VERSI RESMI DARI LISPER

MENGEMBANGKAN VERSI LISPER


Skor bervariasi di berbagai varian permainan. Saya memang bermain-main dengan meningkatkan insentif kerja sama, dan saya setuju bahwa itu akan berdampak pada strategi yang dipilih. Berita baiknya: Anda dapat mengambil pencetak gol, menetapkan aturan sendiri dan mencobanya. Pada prinsipnya Anda bahkan bisa menawarkan hadiah.
dmckee

fink install clisp :: mengetuk jari berulang kali ::
dmckee

1
@ josh - terima kasih atas tautannya. Saya membaca beberapa halaman wikipedia lain tentang dilema ini, tetapi saya melewatkan bagian itu. Bug aturan yang baru saya perhatikan, tidak ada aturan yang melarang entri menggunakan sistem file. ini menciptakan potensi untuk kerja sama yang jauh lebih efisien sepanjang jabat tangan.
arrdem

3
There is no reason to EVER (under this scoring system) co-operatehanya setengah benar. Jika Anda tahu bahwa lawan Anda tidak memperhitungkan sejarah (malaikat, iblis, acak) maka Anda harus selalu membelot. Jika lawan Anda memperhitungkan histori dan Anda dapat melakukan sinkronisasi maka Anda bisa melakukan yang lebih baik. Saya punya beberapa ide yang berputar di sekitar mendeteksi apakah lawan itu rasional atau superrasional.
Peter Taylor

1
Tidakkah Anda mendapatkan kesalahan dibagi 3 x 20 dari waktu dengan versi terbaru? Setiap kali (random 20)memberi 2, 5, atau 8, (/ (+1 rand-num) 10)adalah 0,3, 0,6, 0,9, dan sisa pembagian dengan 0,3 adalah 0; jadi (floor *dbag* *margin*)mati.
Josh Caswell

5

Ketidakpercayaan (varian)

Yang ini keluar pertama dalam tes saya sendiri bertahun-tahun yang lalu (saat itu saya di kelas 11 dan melakukan tesis kecil tentang hal ini, menggunakan strategi yang dirancang oleh siswa lain juga). Ini dimulai dengan urutan tcc(dan bermain seperti Tit untuk Tat setelah itu.

Permintaan maaf untuk kode yang mengerikan; jika seseorang bisa membuat itu lebih pendek sementara tidak bermain golf, saya akan berterima kasih :-)

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if (argc == 1)
        printf("t\n");
    else switch (strlen(argv[1])) {
        case 0:
            printf("t\n");
            break;
        case 1:
        case 2:
            printf("c\n");
            break;
        default:
            if (argv[1][0] == 'R' || argv[1][0] == 'E')
                printf("t\n");
            else
                printf("c\n");
            break;
    }

    return 0;
}

Tidak perlu untuk duplikasi kode pada panjang 1 dan 2. Gunakan jatuh melalui: case 1: case2: printf(...); break;. Dan gcc ingin deklarasi eksplisit string.huntuk digunakan strlen. Dalam hal apapun saya menjalankannya.
dmckee

Ah, benar itu. Saya tidak yakin bagaimana mendeteksi putaran pertama, apakah ada argumen kosong pertama (sejarah) atau tidak sama sekali.
Joey

Saya tidak yakin. Apa pun yang dilakukan python dengan Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)kapan h = ''. Saya menebak argc=1.
dmckee

1
Urutan awal itu adalah ide yang cukup bagus, dengan tujuan tepat pada Tit karena kelemahan Tat. Anda mendapatkan petunjuk kecil di atasnya, lalu memainkan jalannya setelah itu.
Josh Caswell

1
@ Astaga, di mana timah mungilnya? Terhadap T4T ini dimulai SRK dan kemudian dilanjutkan dengan K. Tapi SR bernilai 3 poin untuk setiap pemain.
Peter Taylor

5

Rudal Anti-T42T

#!/usr/bin/python

"""
Anti-T42T Missile, by Josh Caswell

That Tit-for-two-tats, what a push-over!
  T42T: ccctcctcc...
AT42TM: cttcttctt...
        KSSRSSRSS...
"""
import sys
try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

if history[:2] == 'SS':
    print 'c'
else:
    print 't'

Apakah cukup baik terhadap pangkalan prajurit: membunuh Angel, sedikit dipukuli oleh Iblis (tetapi menjaga skor rendah), umumnya mengalahkan RAND dengan mudah, dan hanya sedikit mengalahkan Tit untuk Tat. Apakah buruk saat bermain melawan dirinya sendiri.


Saya mengirimkan hasil edit yang membuat ini benar-benar berfungsi :) Perlu disetujui.
Casey

@Casey: Tuan yang baik, saya membuat begitu banyak kesalahan bodoh dalam antusiasme saya untuk masalah ini! Terima kasih, tetapi mengapa Anda menghilangkan sh-bang?
Josh Caswell

Eh, itu kecelakaan. Saya akan menambahkannya kembali.
Casey

@Casey: tidak ada masalah. Aku akan melakukannya. Perlu menambahkan string doc.
Josh Caswell

4

Konvergensi

Awalnya bagus, lalu bermain secara acak dengan memperhatikan sejarah lawan.

/* convergence
 *
 * A iterated prisoners dilemma warrior for
 *
 * Strategy is to randomly chose an action based on the opponent's
 * history, weighting recent rounds most heavily. Important fixed
 * point, we should never be the first to betray.
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char**argv){
  srandom(time(0)+getpid()); /* seed the PRNG */
  unsigned long m=(1LL<<31)-1,q,p=m;
  if (argc>1) {
    size_t i,l=strlen(argv[1]);
    for (i=l; --i<l; ){
      switch (argv[1][i]) {
      case 'R':
      case 'E':
    q = 0;
    break;
      case 'K':
      case 'S':
    q = m/3;
    break;
      }
      p/=3;
      p=2*p+q;
    }
  }
  /* printf("Probability of '%s' is %g.\n",argv[1],(double)p/(double)m); */
  printf("%c\n",(random()>p)?'t':'c'); 
  return 0;
}

Saya sudah mencoba mengurangi bobot pada sejarah, tetapi belum mengoptimalkannya dengan baik.


4

Hiu

#!/usr/bin/env python

"""
Shark, by Josh Caswell

Carpe stultores.
"""

import sys

HUNGER = 12

try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

if history.count('S') > HUNGER:
    print 't'
else:
    print 'c' if history[0] in "SK" else 't'

Cukup baik terhadap daftar base.


... merebut kerang?
arrdem

:) Tangkap orang bodoh.
Josh Caswell

+1 untuk memegang tempat ke-2 yang konsisten di bidang saat ini.
arrdem

3

Pavlov - Menangkan Menginap, Kalah Beralih

Pada giliran pertama itu bekerja sama, dan kemudian bekerja sama jika dan hanya jika kedua pemain memilih pilihan yang sama pada langkah sebelumnya.

#!/usr/bin/python
import sys

if len(sys.argv) == 1:
    print 'c'
else:
    hist = sys.argv[1]
    if hist[0] == 'K' or hist[0] == 'E':
        print 'c'
    else:
        print 't'

Bukankah seharusnya penggunaan ini hist[0]( hist[-1]selalu merupakan langkah pertama dari putaran)?
Josh Caswell

Oh wow, kamu benar. Saya berasumsi bahwa string input memiliki putaran terbaru di akhir string, bukan awal. Tetap.
Casey

3

Hormatilah Pencuri

#!/usr/bin/env python

"""
Honor Among Thieves, by Josh Caswell

I'd never sell out a fellow thief, but I'll fleece a plump mark,
and I'll cut your throat if you try to cross me.
"""

from __future__ import division
import sys

PLUMPNESS_FACTOR = .33
WARINESS = 10

THIEVES_CANT = "E" + ("K" * WARINESS)

try:
    history = sys.argv[1]
except IndexError:
    history = ""

if history:
    sucker_ratio = (history.count('K') + history.count('S')) / len(history)
    seem_to_have_a_sucker = sucker_ratio > PLUMPNESS_FACTOR


# "Hey, nice t' meetcha."
if len(history) < WARINESS:
    #"Nice day, right?"
    if not set(history).intersection("RE"):
        print 'c'
    # "You sunnuvab..."
    else:
        print 't'

# "Hey, lemme show ya this game. Watch the queen..."
elif len(history) == WARINESS and seem_to_have_a_sucker:
    print 't'

# "Oh, s#!t, McWongski, I swear I din't know dat were you."
elif history[-len(THIEVES_CANT):] == THIEVES_CANT:

    # "Nobody does dat t' me!"
    if set(history[:-len(THIEVES_CANT)]).intersection("RE"):
        print 't'
    # "Hey, McWongski, I got dis job we could do..."
    else:
        print 'c'

# "Do you know who I am?!"
elif set(history).intersection("RE"):
    print 't'

# "Ah, ya almos' had da queen dat time. One more try, free, hey? G'head!"
elif seem_to_have_a_sucker:
    print 't'

# "Boy, you don't say much, do ya?"
else:
    print 'c'

Perhatikan bahwa pada THIEVES_CANTdasarnya itu adalah jabat tangan, meskipun itu hanya akan muncul saat bermain melawan kooperator. Namun, ia menghindari masalah parasit dengan memeriksa persilangan selanjutnya. Cukup baik terhadap daftar base.


+1 karena menjadi orang pertama yang dapat mengalahkan lisper dengan andal. Rata-rata margin kemenangan - 300 poin.
arrdem

Tampaknya menjadi yang terkuat dalam menjalankan pertandingan dari bidang saat ini.
Peter Taylor

Sebenarnya, tidak, Druid sekarang saya sudah memperbaiki bug di pencetak gol.
Peter Taylor

@rmckenzie, @Peter: Ya ampun, benarkah? Saya hanya mencari kepribadian.
Josh Caswell

@ josh - tidak lagi .... pada kode penilaian baru @ kode penilaian casey, Lisper kembali ke atas diikuti oleh hiu.
arrdem

3

"Probabimatic"

Mulai dengan bekerja sama, lalu memilih opsi mana saja yang memberikan nilai tertinggi yang diharapkan. Sederhana.

#include <stdio.h>

void counts(char* str, int* k, int* r, int* s, int* e) {
    *k = *r = *s = *e = 0;
    char c;
    for (c = *str; c = *str; str++) {
        switch (c) {
            case 'K': (*k)++; break;
            case 'R': (*r)++; break;
            case 'S': (*s)++; break;
            case 'E': (*e)++; break;
        }
    }
}

// Calculates the expected value of cooperating and defecting in this round. If we haven't cooperated/defected yet, a 50% chance of the opponent defecting is assumed.
void expval(int k, int r, int s, int e, float* coop, float* def) {
    if (!k && !r) {
        *coop = .5;
    } else {
        *coop = 2 * (float)k / (k + r) - (float)r / (k + r);
    }
    if (!s && !e) {
        *def = 2.5;
    } else {
        *def = 4 * (float)s / (s + e) + (float)e / (s + e);
    }
}

int main(int argc, char** argv) {
    if (argc == 1) {
        // Always start out nice.
        putchar('c');
    } else {
        int k, r, s, e;
        counts(argv[1], &k, &r, &s, &e);
        float coop, def;
        expval(k, r, s, e, &coop, &def);
        if (coop > def) {
            putchar('c');
        } else {
            // If the expected values are the same, we can do whatever we want.
            putchar('t');
        }
    }
    return 0;
}

Dulu mulai dengan bekerja sama, tetapi sekarang tampaknya membelot sebenarnya bekerja lebih baik. EDIT: Oh, tunggu, sebenarnya tidak.


1
Ahli statistik lain! Mari kita lihat bagaimana ini dimainkan melawan sesama kalkulator !
Josh Caswell

Ngomong-ngomong, jika Anda mengubah for (char c = *str;ke char c; for (c = *str;maka gcc akan mengkompilasi ini tanpa mengeluh bahwa itu perlu dimasukkan ke mode C99.
Peter Taylor

3

Tawon Hiperrasional

Diimplementasikan di Jawa karena saya tidak yakin bagaimana rumitnya struktur data akan berakhir. Jika ini merupakan masalah bagi seseorang maka saya pikir saya dapat mem-port-nya ke bash tanpa terlalu banyak masalah karena pada akhirnya hanya menggunakan array asosiatif sederhana.

Catatan : Saya telah menghapus ini dari sebuah paket sesuai dengan versi terbaru dari patch saya ke pencetak gol untuk menangani Java. Jika Anda ingin memposting solusi Java yang menggunakan kelas dalam maka Anda harus menambal tambalan.

import java.util.*;

public class HyperrationalWasp
{
    // I'm avoiding enums so as not to clutter up the warriors directory with extra class files.
    private static String Clam = "c";
    private static String Rat = "t";
    private static String Ambiguous = "x";

    private static final String PROLOGUE = "ttc";

    private static int n;
    private static String myActions;
    private static String hisActions;

    private static String decideMove() {
        if (n < PROLOGUE.length()) return PROLOGUE.substring(n, n+1);

        // KISS - rather an easy special case here than a complex one later
        if (mirrorMatch()) return Clam;
        if (n == 99) return Rat; // This is rational rather than superrational

        int memory = estimateMemory();
        if (memory == 0) return Rat; // I don't think the opponent will punish me
        if (memory > 0) {
            Map<String, String> memoryModel = buildMemoryModel(memory);
            String myRecentHistory = myActions.substring(0, memory - 1);
            // I don't think the opponent will punish me.
            if (Clam.equals(memoryModel.get(Rat + myRecentHistory))) return Rat;
            // I think the opponent will defect whatever I do.
            if (Rat.equals(memoryModel.get(Clam + myRecentHistory))) return Rat;
            // Opponent will cooperate unless I defect.
            return Clam;
        }

        // Haven't figured out opponent's strategy. Tit for tat is a reasonable fallback.
        return hisAction(0);
    }

    private static int estimateMemory() {
        if (hisActions.substring(0, n-1).equals(hisActions.substring(1, n))) return 0;

        int memory = -1; // Superrational?
        for (int probe = 1; probe < 5; probe++) {
            Map<String, String> memoryModel = buildMemoryModel(probe);
            if (memoryModel.size() <= 1 || memoryModel.values().contains(Ambiguous)) {
                break;
            }
            memory = probe;
        }

        if (memory == -1 && isOpponentRandom()) return 0;

        return memory;
    }

    private static boolean isOpponentRandom() {
        // We only call this if the opponent appears not have have a small fixed memory,
        // so there's no point trying anything complicated. This is supposed to be a Wilson
        // confidence test, although my stats is so rusty there's a 50/50 chance that I've
        // got the two probabilities (null hypothesis of 0.5 and observed) the wrong way round.
        if (n < 10) return false; // Not enough data.
        double p = count(hisActions, Clam) / (double)n;
        double z = 2;
        double d = 1 + z*z/n;
        double e = p + z*z/(2*n);
        double var = z * Math.sqrt(p*(1-p)/n + z*z/(4*n*n));
        return (e - var) <= 0.5 * d && 0.5 * d <= (e + var);
    }

    private static Map<String, String> buildMemoryModel(int memory) {
        // It's reasonable to have a hard-coded prologue to probe opponent's behaviour,
        // and that shouldn't be taken into account.
        int skip = 0;
        if (n > 10) skip = n / 2;
        if (skip > 12) skip = 12;

        Map<String, String> memoryModel = buildMemoryModel(memory, skip);
        // If we're not getting any useful information after skipping prologue, take it into account.
        if (memoryModel.size() <= 1 && !memoryModel.values().contains(Ambiguous)) {
            memoryModel = buildMemoryModel(memory, 0);
        }
        return memoryModel;
    }

    private static Map<String, String> buildMemoryModel(int memory, int skip) {
        Map<String, String> model = new HashMap<String, String>();
        for (int off = 0; off < n - memory - 1 - skip; off++) {
            String result = hisAction(off);
            String hypotheticalCause = myActions.substring(off+1, off+1+memory);
            String prev = model.put(hypotheticalCause, result);
            if (prev != null && !prev.equals(result)) model.put(hypotheticalCause, Ambiguous);
        }
        return model;
    }

    private static boolean mirrorMatch() { return hisActions.matches("c*ctt"); }
    private static String myAction(int idx) { return myActions.substring(idx, idx+1).intern(); }
    private static String hisAction(int idx) { return hisActions.substring(idx, idx+1).intern(); }
    private static int count(String actions, String action) {
        int count = 0;
        for (int idx = 0; idx < actions.length(); ) {
            int off = actions.indexOf(action, idx);
            if (off < 0) break;
            count++;
            idx = off + 1;
        }
        return count;
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            hisActions = myActions = "";
            n = 0;
        }
        else {
            n = args[0].length();
            myActions = args[0].replaceAll("[KR]", Clam).replaceAll("[SE]", Rat);
            hisActions = args[0].replaceAll("[KS]", Clam).replaceAll("[RE]", Rat);
        }

        System.out.println(decideMove());
    }

}

Perubahan yang saya buat pada pencetak gol untuk menjalankan ini adalah:

17a18
> import re
22a24
> GCC_PATH = 'gcc'                #path to c compiler
24c26
< JAVA_PATH = '/usr/bin/java'   #path to java vm
---
> JAVA_PATH = '/usr/bin/java'     #path to java vm
50,55c52,59
<         elif ext == '.java':
<             if subprocess.call([JAVAC_PATH, self.filename]) == 0:
<                 print 'compiled java: ' + self.filename
<                 classname = re.sub('\.java$', '', self.filename)
<                 classname = re.sub('/', '.', classname);
<                 return JAVA_PATH + " " + classname
---
>         elif ext == '.class':
>             # We assume further down in compilation and here that Java classes are in the default package
>             classname = re.sub('.*[/\\\\]', '', self.filename)
>             dir = self.filename[0:(len(self.filename)-len(classname))]
>             if (len(dir) > 0):
>                 dir = "-cp " + dir + " "
>             classname = re.sub('\\.class$', '', classname);
>             return JAVA_PATH + " " + dir + classname
196c200,201
<         if os.path.isdir(sys.argv[1]):
---
>         warriors_dir = re.sub('/$', '', sys.argv[1])
>         if os.path.isdir(warriors_dir):
198,200c203,211
<             for foo in os.listdir("./src/"): # build all c/c++ champs first.
<                 os.system(str("gcc -o ./warriors/" + os.path.splitext(os.path.split(foo)[1])[0] + " ./src/" + foo ))
<                 #print str("gcc -o ./warriors/" + os.path.splitext(os.path.split(foo)[1])[0] + " ./src/" + foo )
---
>             for foo in os.listdir("./src/"): # build all c/c++/java champs first.
>                 filename = os.path.split(foo)[-1]
>                 base, ext = os.path.splitext(filename)
>                 if (ext == '.c') or (ext == '.cpp'):
>                     subprocess.call(["gcc", "-o", warriors_dir + "/" + base, "./src/" + foo])
>                 elif (ext == '.java'):
>                     subprocess.call([JAVAC_PATH, "-d", warriors_dir, "./src/" + foo])
>                 else:
>                     print "No compiler registered for ", foo
202,203c213,214
<             print "Finding warriors in " + sys.argv[1]
<             players = [sys.argv[1]+exe for exe in os.listdir(sys.argv[1]) if os.access(sys.argv[1]+exe,os.X_OK)]
---
>             print "Finding warriors in " + warriors_dir
>             players = [warriors_dir+"/"+exe for exe in os.listdir(warriors_dir) if (os.access(warriors_dir+"/"+exe,os.X_OK) or os.path.splitext(exe)[-1] == '.class')]

Terima kasih kepada @rmckenzie karena melipat dalam fungsi penantang saya.


Hanya masalah gaya .... haruskah file .java dianggap "sumber" dan dipindahkan ke direktori ./src dan .class terakhir ditempatkan di folder ./warriors dengan subskrip yang sama dengan yang digunakan pada file .c, atau Java diinterpretasikan dan dengan demikian .java dan .class tetap bersama? Bagaimanapun, perubahan yang bagus pada pencetak gol ... akan memilikinya dalam status repo.
arrdem

@ rmckenzie, poin bagus: ya, secara teknis sudah dikompilasi. Alasan saya memiliki file sumber di direktori prajurit adalah bahwa file python ada di sana juga - dan mereka dikompilasi. Jika Anda mau, saya dapat memeriksa perubahan apa yang diperlukan untuk mengkompilasinya dari ./src ke ./warriors - tetapi itu akan memerlukan beberapa argumen kompiler, karena Java secara default mengasumsikan bahwa struktur direktori mencerminkan paket (namespace).
Peter Taylor

@ Peter, saya hanya ingin tahu ... para prajurit ditemukan di ./warriors menjadi * nix 777, atau dieksekusi. Skrip Python dan Lisp NOMINALLY dikompilasi untuk kinerja, tetapi dieksekusi dalam keadaan (sumber) alami mereka. UNTUK PENGETAHUAN SAYA SEBAGAI ORANG NON-JAVA, file .java tidak memiliki izin tersebut dan karenanya tidak akan muncul. Itulah tujuan dari peretasan c ... karena kompilasi adalah langkah terpisah. Jadi ya. Saya akan sangat menghargainya jika Anda ingin melakukan perubahan itu. REPO LINK
arrdem

Menggunakan kode Anda dan tawon chmod 777'd, JVM melemparkan keindahan ini. Exception in thread "main" java.lang.NoClassDefFoundError: //warriors/HyperrationalWasp Caused by: java.lang.ClassNotFoundException: ..warriors.HyperrationalWasp at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
arrdem

@ rmckenzie, itu aneh. Bagaimanapun, saya pikir saya akan memiliki patch untuk Anda segera. Saya harus meretas kode pemuatan, karena file kelas tidak dapat dieksekusi. Dan jika ada entri Java lainnya menggunakan kelas dalam itu akan rusak.
Peter Taylor

3

Soft_majo

Ah well, satu lagi strategi standar, hanya untuk melengkapi line-up.

Yang ini memilih gerakan yang paling banyak dilakukan lawan; jika sama itu bekerja sama.

#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[]) {
    int d = 0, i, l;

    if (argc == 1) {
        printf("c\n");
    } else {
        l = strlen(argv[1]);

        for (i = 0; i < l; i++)
            if (argv[1][i] == 'R' || argv[1][i] == 'E')
                d++;

        printf("%c\n", d > l/2 ? 't' : 'c');
    }
}

Kode Anda adalah soft_majo, tetapi deskripsi Anda adalah hard_majo.
Peter Taylor

Peter: Eek, maaf; tetap.
Joey

3

Pengisap acak

Yang ini akan cacat jika lawan terlalu sering cacat (ambang batas), tetapi secara acak akan mencoba menusuk kembali setiap saat.

Apakah cukup baik terhadap semua orang kecuali pemain Java dan Lisp (yang saya tidak bisa menjalankan, karena baik Java maupun Lisp pada mesin uji); setidaknya sebagian besar waktu.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define THRESHOLD 7
#define RAND 32

int main(int c, char * a []) {
    int r;
    char * x;
    int d = 0;

    srandom(time(0) + getpid());

    if (c == 1) {
        printf("c\n");
        return 0;
    }

    for (x = a[1]; *x; x++)
        if (*x == 'R' || *x == 'E') d++;

    if (d > THRESHOLD || random() % 1024 < RAND || strlen(a[1]) == 99)
        printf("t\n");
    else
        printf("c\n");

    return 0;
}

Melawan HyperrationalWasp umumnya akan melakukan kasar terhadap iblis. Itu dimulai hanya bekerja sama sepanjang waktu, jadi saya menganggap itu adalah malaikat dan pergi menyerang. Kemudian ketika mencapai ambang batas Anda akan beralih ke mode setan dan saya akan beralih ke t4t. Jika itu secara acak melakukan backstab di 6 gerakan pertama maka saya akan beralih ke t4t sebelum Anda beralih ke setan, tetapi kemungkinan itu tidak tinggi.
Peter Taylor

1
Peter: Yah, saya jarang menguji strategi secara langsung terhadap satu sama lain, karena bidang keseluruhan memiliki beberapa pengaruh pada kinerja strategi. Saat ini sebagian besar pertempuran dengan bertahap dan Druid untuk tempat pertama dalam tes saya.
Joey

Secara bertahap dan druid, skor keduanya sekitar 200 melawan Wasp; pengisap acak akan skor sekitar 83.
Peter Taylor

2

BYGONES

#!/usr/bin/env python

"""
BYGONES, entry to 1P5 Iterated Prisoner's Dilemma, by Josh Caswell

Cooperates at first, plays as Tit for Tat for `bygones * 2` rounds, then checks 
history: if there's too much ratting, get mad and defect; too much 
suckering, feel bad and cooperate.
"""

bygones = 5

import sys

# React to strangers with trust.
try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

replies = { 'K' : 'c', 'S' : 'c',
            'R' : 't', 'E' : 't' }

# Reply in kind.
if len(history) < bygones * 2:
    print replies[history[0]]
    sys.exit(0)

# Reflect on past interactions.
faithful_count = history.count('K')
sucker_count = history.count('S')
rat_count = history.count('R')

# Reprisal. 
if rat_count > faithful_count + bygones:
    # Screw you!
    print 't'
    sys.exit(0)

# Reparation.
if sucker_count > faithful_count + bygones:
    # Geez, I've really been mean.
    print 'c'
    sys.exit(0)

# Resolve to be more forgiving.
two_tats = ("RR", "RE", "ER", "EE")
print 't' if history[:2] in two_tats else 'c'

Belum menemukan nilai terbaik untuk saat bygonesini. Saya tidak berharap ini menjadi strategi kemenangan , tapi saya tertarik pada kinerja strategi seperti apa yang saya pikir "baik" dalam kehidupan nyata. Revisi di masa depan mungkin termasuk memeriksa jumlah pembelotan bersama juga.


2

Bantu Vampir

#!/usr/bin/env python

"""
Help Vampire, entry to 1P5 Iterated Prisoner's Dilemma,
by Josh Caswell.

1. Appear Cooperative 2. Acknowledge Chastisement 
3. Act contritely 4. Abuse charity 5. Continual affliction
"""

import sys
from os import urandom

LEN_ABASHMENT = 5

try:
    history = sys.argv[1]
except IndexError:
    print 'c'    # Appear cooperative
    sys.exit(0)

# Acknowledge chastisement
if history[0] in "RE":
    print 'c'
# Act contritely
elif set(history[:LEN_ABASHMENT]).intersection(set("RE")):
    print 'c'
# Abuse charity
elif history[0] == 'S':
    print 't'
# Continual affliction
else:
    print 't' if ord(urandom(1)) % 3 else 'c'

Memiliki hasil asimetris yang lucu ketika diadu dengan dirinya sendiri. Kalau saja solusi ini bisa diterapkan dalam kehidupan nyata.


2

Druid

#!/usr/bin/env python

"""
Druid, by Josh Caswell

Druids are slow to anger, but do not forget.
"""

import sys
from itertools import groupby

FORBEARANCE = 7
TOLERANCE = FORBEARANCE + 5

try:
    history = sys.argv[1]
except IndexError:
    history = ""

# If there's been too much defection overall, defect
if (history.count('E') > TOLERANCE) or (history.count('R') > TOLERANCE):
    print 't'
# Too much consecutively, defect
elif max([0] + [len(list(g)) for k,g in     # The 0 prevents dying on []
                groupby(history) if k in 'ER']) > FORBEARANCE:
    print 't'
# Otherwise, be nice
else:
    print 'c'

Apakah cukup baik terhadap daftar pangkalan.


2

Simpleton

#!/usr/bin/env python

"""
Simpleton, by Josh Caswell

Quick to anger, quick to forget, unable to take advantage of opportunity.
"""

import sys
from os import urandom

WHIMSY = 17

try:
    history = sys.argv[1]
except IndexError:
    if not ord(urandom(1)) % WHIMSY:
        print 't'
    else:
        print 'c'
    sys.exit(0)

if history[0] in "RE":
    print 't'
elif not ord(urandom(1)) % WHIMSY:
    print 't'
else:
    print 'c'

Tidak apa-apa terhadap daftar base.


2

Schemer kecil

#!/usr/bin/env python

"""
The Little Schemer, by Josh Caswell

No relation to the book. Keeps opponent's trust > suspicion 
by at least 10%, trying to ride the line.
"""

from __future__ import division
import sys
from os import urandom

out = sys.stderr.write

def randrange(n):
    if n == 0:
        return 0
    else:
        return ord(urandom(1)) % n

try:
    history = sys.argv[1]
except IndexError:
    print 'c'
    sys.exit(0)

R_count = history.count('R')
S_count = history.count('S')
K_count = history.count('K')
E_count = history.count('E')

# Suspicion is _S_ and E because it's _opponent's_ suspicion
suspicion = (S_count + E_count) / len(history)
# Likewise trust
trust = (K_count + R_count) / len(history)

if suspicion > trust:
    print 'c'
else:
    projected_suspicion = (1 + S_count + E_count) / (len(history) + 1)
    projected_trust = (1 + K_count + R_count) / (len(history) + 1)

    leeway = projected_trust - projected_suspicion
    odds = int(divmod(leeway, 0.1)[0])

    print 't' if randrange(odds) else 'c'

Tidak buruk terhadap base set, tetapi cukup baik terhadap targetnya. Jelas, tidak ditulis dalam Skema.


Mengapa saya merasakan tantangan?
arrdem

Mengalahkan bugger ini .... secara acak ambang di Lisper.
arrdem

@rmckenzie: tetapi bagaimana hal itu memengaruhi permainan Anda terhadap bagian lainnya? Dengan cukup kooperator yang bekerja satu sama lain, strategi paranoid atau iri akan mulai menjadi lebih buruk. Anda masih memiliki batas atas tetap, yang dapat dieksploitasi.
Josh Caswell

Jika Anda membaca lisper saat ini, itu lebih defensif daripada iri. Ia mencoba mendeteksi lawan yang mengejar strategi berbahaya seperti ini, dan baru kemudian membalas tembakan. Pembukaan CC dirancang untuk turun dengan kaki kanan bersama Pencuri, dan memiliki manfaat tambahan meyakinkan sebagian besar strategi koperasi untuk bermain bersama.
arrdem

@rmckenzie: Bagus sekali! Saya akan mencobanya.
Josh Caswell

1

Gayung untuk Dua Tats

favorit lama lainnya

#!/usr/bin/env python

"""
Tit For Two Tats, entry to 1P5 Iterated Prisoner's Dilemma, 
    by Josh Caswell (not an original idea).

Cooperates unless opponent has defected in the last two rounds.
"""

import sys
try:
    history = sys.argv[1]
except IndexError:
    history = ""

two_tats = ("RR", "RE", "ER", "EE")

if len(history) < 2:
    print 'c'
else:
    print 't' if history[:2] in two_tats else 'c'

Anda tidak dapat melakukan pengembalian kecuali Anda berada di dalam suatu fungsi. Mungkin menggunakan sys.exit(0)? Atau biarkan saja selesai. Sunting: Juga permohonan pertama ke program Anda tanpa riwayat yang menyebabkan IndexErrorkapan Anda melakukannya argv[1].
Casey

Anda mungkin telah meninggalkan len(history)<2klausa, karena yang terakhir terlihat seperti elsebagian.
dmckee

@Casey @dmckee Terima kasih atas perbaikan bugnya. "Duh" returnterutama untukku !
Josh Caswell

@ Dmckee: Ini dimulai sebagai bagian dari sesuatu yang lebih rumit, dan kemudian saya menyadari saya telah menulis ulang Tit untuk Two Tats dan memutuskan untuk memasukkannya. Salin-tempel kesalahan pengguna.
Josh Caswell

@Josh: Saya melihat entri Bygones Anda sebentar, apakah Anda menghapusnya? Itu terlihat tertarik.
Casey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.