1P5: Tiến thoái lưỡng nan của tù nhân


35

Nhiệm vụ này là một phần của Câu đố đẩy lập trình hàng đầu định kỳ đầu tiên và được dự định là minh chứng cho đề xuất loại thử thách mới .

Nhiệm vụ là viết một chương trình để chơi tình huống khó xử của tù nhân tốt hơn so với những người tham gia khác.

Nhìn kìa Chúng tôi biết bạn cùng phòng của bạn --- tên anh ta là gì? Vâng McWongski, mobster Nippo-Ailen-Ukraina - là một cái gì đó và bạn biết nó là gì.

Vinnie đang cố gắng trở nên tốt đẹp ở đây, Vinnie. Givin 'bạn một cơ hội.

Nếu bạn nói với chúng tôi những gì anh ấy đang làm, chúng tôi sẽ thấy bạn có được sự phân công công việc tốt.

Và nếu bạn không ...

Luật của trò chơi

  • Cuộc thi bao gồm một vòng tròn đầy đủ (tất cả có thể ghép đôi) của hai thí sinh tại một thời điểm (bao gồm cả tự chơi).
  • Có 100 vòng chơi giữa mỗi cặp
  • Trong mỗi vòng, mỗi người chơi được yêu cầu lựa chọn giữa việc hợp tác với người chơi khác hoặc phản bội họ, mà không biết ý định của người chơi khác trong vấn đề này, nhưng với một ký ức về kết quả của các vòng trước đối đầu với đối thủ này.
  • Điểm được trao cho mỗi vòng dựa trên sự lựa chọn kết hợp. Nếu cả hai người chơi hợp tác, mỗi người được 2 điểm. Sự phản bội lẫn nhau mang lại 1 điểm mỗi. Trong trường hợp hỗn hợp, người chơi phản bội được thưởng 4 điểm và người hợp tác bị phạt 1.
  • Một trận đấu "chính thức" sẽ được tiến hành không sớm hơn 10 ngày sau khi đăng với tất cả các bài dự thi tôi có thể làm việc và được sử dụng để chọn người chiến thắng "được chấp nhận". Tôi có hộp Mac OS 10.5, vì vậy các giải pháp POSIX sẽ hoạt động, nhưng có những ngôn ngữ không có. Tương tự như vậy, tôi không có hỗ trợ cho API win32. Tôi sẵn sàng thực hiện một nỗ lực cơ bản để cài đặt mọi thứ, nhưng có một giới hạn. Các giới hạn của hệ thống của tôi không có cách nào thể hiện giới hạn của các phản hồi có thể chấp nhận được, chỉ đơn giản là các giới hạn sẽ được đưa vào trận đấu "chính thức".

Giao diện của Lập trình viên

  • Các mục nhập phải ở dạng chương trình có thể chạy từ dòng lệnh; quyết định phải là đầu ra (duy nhất!) của chương trình trên đầu ra tiêu chuẩn. Lịch sử của các vòng trước với đối thủ này sẽ được trình bày dưới dạng đối số dòng lệnh.
  • Đầu ra là "c" (cho ngao lên ) hoặc "t" (cho tất cả ).
  • Lịch sử là một chuỗi các ký tự đại diện cho các vòng trước với các vòng gần đây nhất đến sớm nhất trong chuỗi. Các nhân vật là
    • "K" (vì giữ đức tin có nghĩa là hợp tác lẫn nhau)
    • "R" (đối với chuột b @ st @rd đã bán cho tôi! )
    • "S" (đối với kẻ hút! Có nghĩa là bạn được hưởng lợi từ sự phản bội)
    • "E" (vì mọi người đang tìm kiếm số một về sự phản bội lẫn nhau)

Giá đỡ

Bốn người chơi sẽ được cung cấp bởi tác giả

  • Thiên thần - luôn hợp tác
  • Quỷ dữ - luôn luôn nói chuyện
  • TitForTat - Hợp tác ở vòng đầu tiên sau đó luôn luôn làm như anh ta đã làm trong vòng cuối cùng
  • Ngẫu nhiên - 50/50

mà tôi sẽ thêm tất cả các mục mà tôi có thể chạy.

Tổng số điểm sẽ là tổng điểm so với tất cả các đối thủ (bao gồm chỉ tự chơi một lần và sử dụng điểm trung bình).

Người đăng ký

(hiện tại kể từ ngày 2 tháng 5 năm 2011 7:00)

Cái bắt tay bí mật | Tên lửa chống T42T | Mistrust (biến thể) | Chống bắt tay | Cô bé nhỏ bé | Hội tụ | Cá mập | Dự phòng | Pavlov - Giành chiến thắng, mất công tắc | Danh dự giữa những tên trộm | Giúp ma cà rồng | Druid | Sơ đồ nhỏ | Quá khứ | Tit cho hai Tats | Đơn giản |

Vua phá lưới

#! /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
  • Khiếu nại về con trăn khủng khiếp của tôi đều được chào đón, vì tôi chắc chắn rằng điều này hút nhiều hơn một cách
  • Sửa lỗi chào mừng

Vua phá lưới Changelog:

  • In sắp xếp người chơi và điểm số, và tuyên bố người chiến thắng (29/11, Casey)
  • Tùy chọn chạy nhiều giải đấu ( ./score warriors/ num_tournaments)) mặc định = 1, phát hiện và biên dịch các nguồn python (29/2, Casey)
  • Sửa lỗi đặc biệt ngu ngốc trong đó người chơi thứ hai đã được thông qua một lịch sử không chính xác. (30 tháng 4, dmckee; cảm ơn Josh)

Chiến binh ban đầu

Bằng cách ví dụ, và để có thể xác minh kết quả

Thiên thần

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

hoặc là

#!/bin/sh
echo c

hoặc là

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

ác quỷ

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

Ngẫu nhiên

#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;
}

Lưu ý rằng người ghi bàn có thể gọi lại chiến binh nhiều lần trong một giây, do đó phải thực hiện một nỗ lực nghiêm túc để đảm bảo tính ngẫu nhiên của kết quả nếu thời gian được sử dụng để gieo 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;
}

Người đầu tiên thực sự làm một cái gì đó với lịch sử.

Chạy vua phá lưới chỉ mang lại sản lượng chiến binh được cung cấp

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)

Con quỷ đó, anh ta là một kẻ thủ công, và những kẻ tốt bụng dường như đến sau cùng.

Các kết quả

của cuộc chạy "chính thức"

('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
Nếu bạn cùng phòng của tôi là Nippo-Ailen-Ucraina, tại sao tên của anh ấy lại trông giống Hiberno-Sino-Russian?
Peter Taylor

2
@Peter: LOL. Sự thật? Chà, (1) các phả hệ không rõ ràng, nhưng có lẽ tôi đến nhờ mic'edness của mình bằng cách của Scotch-Irish; (2) sau khi tôi viết "Nippo", tôi đã thử nhiều loại tên của những người bạn của tôi từ xứ sở mặt trời mọc và không thích cách họ quét, vì vậy tôi đã đi trước và sử dụng họ của Trung Quốc nghe có vẻ tốt thay vào đó, và (3) Tôi sẽ không biết sự khác biệt nếu họ thay phiên nhau đánh tôi bằng gậy sắt. Mà dường như có khả năng trong hoàn cảnh.
dmckee

1
@Josh: Sẽ đơn giản để thay đổi return (s1, L1+h1), (s2, L2+h1)thành return (s1, L1+h1), (s2, L2+h2)[Ghi chú L2+h2thay vì L2+h1ở cuối]? // Lỗi cắt-n-dán hoặc một cái gì đó không kém phần ngu ngốc. Sheesh!
dmckee

2
Tôi đã dành một chút thời gian cho kịch bản thử nghiệm và tôi vui mừng thông báo bản cập nhật tại đây . Bản cập nhật này thêm một lớp vỏ đơn giản vào tập lệnh thử nghiệm, cho phép người dùng tự chạy bot này so với bot đó, chạy các giải đấu với các trường bị hạn chế và một số nội dung thú vị khác. Hãy góp ý! Oh. Và tôi nợ @josh cho ý tưởng bot-vs-bot. Nó thực sự chỉ là một triển khai fancier của kịch bản "trainer" của anh ấy.
năm11

2
Thú vị: Có 23 thí sinh, nên mỗi người chơi 22 vòng. Nếu tất cả mọi người đã chơi "Thiên thần" thì mọi điểm sẽ là 4400, nhưng ngay cả điểm số tốt nhất là 4167 cũng không phù hợp với điều đó. Giá như chúng ta sống trong một thế giới hoàn hảo ... :)
Briguy37

Câu trả lời:


11

Dần dần

Chiến lược này dựa trên một bài báo của Beaufils, Delahaye và Mathieu . My C thực sự không phải là tốt nhất, vì vậy nếu có ai có bất kỳ đề xuất nào để cải thiện / tăng tốc mã, hãy cho tôi biết!

[Chỉnh sửa] Đáng lưu ý là Gradual được thiết kế để trở thành một chiến lược vượt trội so với Tit cho Tat. Nó có tính chất tương tự ở chỗ nó sẵn sàng hợp tác và trả đũa một đối thủ đào tẩu. Không giống như Tit cho Tat, người chỉ có một ký ức về vòng cuối cùng được chơi, Gradual sẽ ghi nhớ sự tương tác hoàn toàn và làm hỏng số lần đối thủ đã đào thoát cho đến nay. Nó sẽ cung cấp sự hợp tác lẫn nhau sau đó một lần nữa, mặc dù.

Như thường lệ, hiệu suất của chiến lược phụ thuộc một chút vào đội hình của các chiến lược khác. Ngoài ra, bài báo gốc không thực sự rõ ràng về một số chi tiết.

#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

Cái bắt tay bí mật

#!/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()

Chiến lược ở đây là hy sinh 10 vòng đầu tiên để thực hiện một cái bắt tay "bí mật". Nếu tôi di động với chính mình, thì tôi sẽ nhận ra lịch sử của 10 lần di chuyển đầu tiên và đội chiếc mũ Thiên thần của mình cho phần còn lại của trò chơi. Ngay khi tôi nhận ra rằng bạn cùng phòng của mình không phải là chính mình, tôi biến thành Quỷ dữ trong nỗ lực lợi dụng bạn cùng phòng quá mức.

Việc hy sinh 10 vòng đầu tiên có cho phép tôi vượt qua chính Quỷ hay không phụ thuộc mạnh mẽ vào số lượng mục có. Để giảm thiểu thiệt hại, chỉ có 3 hợp tác xuất hiện trong cái bắt tay.

Chỉnh sửa: TAGMATCH động ngay bây giờ để ngăn các lỗi ngu ngốc như chỉ thay đổi một trong số chúng và do đó tôi có thể khiến TAG động tại một số điểm trong tương lai.

Chỉnh sửa 2: Bây giờ tạo ngẫu nhiên thẻ trong lần chạy đầu tiên và lưu nó vào tệp được chỉ định bởi sys.argv[0](được .pycthay thế bằng .pymã này, chứ không phải mã, không phải mã byte, tệp). Tôi nghĩ rằng đây là thông tin duy nhất mà tất cả các trường hợp của tôi có mà không ai khác có, vì vậy nó có vẻ như là lựa chọn duy nhất để tránh ký sinh trùng.


Nhưng làm thế nào để doppelganger của bạn biết để biến mình thành một con quỷ?
arrdem

1
(Tôi cảm thấy giống như một con vẹt, nói "Tit for Tat" mọi lúc ...) Lưu ý rằng T4T sẽ đánh bại chiến lược của bạn trong một cặp chống lại: T4T (hợp tác trước đó) và Devil (kết quả Rat ít hơn) và sẽ liên kết với bạn chiến lược. Tất nhiên, tổng số lớn, không phải tổng số ghép đôi, là những gì được tính cuối cùng. Như bạn nói, dân số là quan trọng.
Josh Caswell

1
Ồ, không, bạn nhận thêm một S từ Tit cho Tat. Tốt đẹp. Tôi không nhận ra TAGđã bị chơi ngược. Tuy nhiên, bạn không nên TAGMATCHlà 'KEEEKEEEKE'? "".join({('c', 'c'):'K', ('t', 't'): 'E'}[moves] for moves in zip(TAG, TAG))
Josh Caswell

@ John Điểm tốt - Ban đầu tôi có một TAG khác và khi tôi thay đổi nó để giảm thiểu hợp tác, tôi đã quên cập nhật TAGMATCH. @Arrdem Ý tưởng là nếu tôi chơi với chính mình, điều tốt nhất nên làm là cả hai phải hợp tác mọi lúc để tối đa hóa tổng điểm của họ.
Aaron Dufour

1
À, chết tiệt. Vì vậy, bây giờ tôi phải tìm kiếm tất cả các .pytệp cho mã của bạn và trích xuất TAG. Tôi sẽ không làm điều đó ở C, mặc dù ...
Joey

6

Tiểu 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
    )
)

Ác quỷ

Hãy xem xét các định dạng sau (Player1, Player2)

  • (C, T) - P2 nhận được BỐN ĐIỂM cho sự phản bội của mình, trong khi P1 LOẠI MỘT
  • (T, T) - P2 VÀ P1 GAIN 1

Giả sử P2 là ma quỷ, không có cách nào ma quỷ có thể mất điểm, thực tế điều tồi tệ nhất mà anh ta có thể làm là chỉ đạt được một điểm. Do đó, đối đầu với một đối thủ hoàn toàn ngẫu nhiên, điểm số tồi tệ nhất có thể của quỷ sẽ chính xác là (5/2) * n trong đó n là số lượng "trò chơi" được chơi. Trường hợp xấu nhất tuyệt đối của anh ta là chống lại chính mình, trong đó điểm của anh ta sẽ là n, và trường hợp tốt nhất của anh ta là chống lại một thiên thần, sẽ là 4 * n

Khẳng định: tối ưu_strat = ma quỷ

đây là một tourney Ủng hộ bạn cùng phòng của tôi là một chiến lược tốt hơn nhiều so với hợp tác vì nó giúp MY SCORE nhiều hơn (+4). THƯỞNG - anh ta bị đánh (-1)! Nếu tôi thò cổ ra cho anh ta, tôi sẽ đạt được (+2) và mất (-1). Do đó, thống kê backstabbing được khen thưởng.

Nhưng nó có tối ưu không?

Không có lý do gì để EVER (theo hệ thống tính điểm này) hợp tác.

  • Nếu bạn chọn sai thời điểm để ngao lên, bạn sẽ mất đi.
  • Nếu bạn chuột, ít nhất bạn không mất gì cả.
  • Nếu bạn chuột và anh ta câm, bạn sẽ tăng gấp đôi so với khi bạn là một người tốt.

Trong hệ thống KOTH, tối đa hóa lợi nhuận là điều cần thiết. Ngay cả khi bạn có hai bot được đồng bộ hóa và hợp tác hoàn hảo, điểm số cá nhân của chúng vẫn sẽ chỉ được tăng thêm 200 điểm cho khả năng thể thao của chúng. Mặt khác, một con quỷ sẽ kiếm được ít nhất 100 điểm, với trường hợp trung bình là 200 và tối đa là 400, và khiến đối thủ của nó phải trả tới 100 điểm mỗi điểm! Vì vậy, trên thực tế, ma quỷ thực sự ghi được một trò chơi trung bình 300, tăng vọt lên 500.

Dòng dưới cùng - thời gian sẽ trả lời

Đối với tôi, có vẻ như việc ghi bàn nên được xem xét lại kẻo ma quỷ mất ngày. Tăng điểm hợp tác lên 3 tất cả có thể làm điều đó. Tuy nhiên, có thể phát hiện ra quỷ và ngăn chúng ghi điểm 400, như pavlov và spite cho thấy. Tôi có thể chứng minh rằng một trong hai sẽ nhận đủ điểm cho sự hợp tác của họ để biện minh cho đức tin của họ không? Không. Tất cả điều đó phụ thuộc vào lĩnh vực cuối cùng của các ứng cử viên.

GL, HF!

Và hãy làm điều tồi tệ nhất của bạn cho bài viết này. Tôi muốn viết bài báo cao cấp của mình về điều này khi tất cả đã nói và làm xong.

Lịch sử phiên bản

  1. Đã thêm một biến lề làm thay đổi ngẫu nhiên dung sai của Lisper đối với duchebaggery.
  2. Cập nhật lisper để ngao cho hai vòng đầu tiên để đi bằng chân phải với các đối thủ hợp tác
  3. Đã sử dụng thuật toán di truyền để tìm các giá trị mạnh nhất cho trình tạo ngưỡng ngẫu nhiên dựa trên điểm tích lũy tối đa của chúng so với nhóm đối thủ tiêu chuẩn. Đăng cập nhật bao gồm cả họ.

PHIÊN BẢN CHÍNH THỨC CỦA LISPER

VERSION CỦA LISPER


Điểm số khác nhau trong các biến thể khác nhau của trò chơi. Tôi đã chơi xung quanh với việc tăng động lực hợp tác và tôi đồng ý rằng nó sẽ có ảnh hưởng đến các chiến lược đã chọn. Tin tốt: bạn có thể lấy trình ghi bàn, đặt quy tắc của riêng mình và thử. Về nguyên tắc bạn thậm chí có thể cung cấp một tiền thưởng.
dmckee

fink install clisp :: gõ ngón tay liên tục ::
dmckee

1
@josh - cảm ơn vì đường link. Tôi đọc một số trang wikipedia khác về vấn đề nan giải này, nhưng tôi đã bỏ lỡ phần đó. Một lỗi quy tắc tôi chỉ nhận thấy, không có quy tắc chống lại các mục sử dụng hệ thống tập tin. điều này tạo ra tiềm năng cho sự hợp tác hiệu quả hơn nhiều dọc theo các dòng bắt tay.
arrdem

3
There is no reason to EVER (under this scoring system) co-operatechỉ đúng một nửa. Nếu bạn biết rằng đối thủ của bạn không tính đến lịch sử (thiên thần, ác quỷ, ngẫu nhiên) thì bạn nên luôn luôn đào tẩu. Nếu đối thủ của bạn có tính đến lịch sử và bạn có thể đồng bộ hóa thì bạn có thể làm tốt hơn. Tôi có một vài ý tưởng xoay quanh việc phát hiện xem đối thủ là hợp lý hay siêu thực.
Peter Taylor

1
Không phải bạn đã nhận được các lỗi chia cho 0/20 của thời gian với phiên bản mới nhất phải không? Bất cứ khi nào (random 20)cho 2, 5 hoặc 8, (/ (+1 rand-num) 10)là 0,3, 0,6, 0,9 và phần còn lại của phép chia với 0,3 là 0; thế là (floor *dbag* *margin*)chết.
Josh Caswell

5

Mistrust (biến thể)

Cái này xuất hiện đầu tiên trong các bài kiểm tra của tôi nhiều năm trước (hồi đó tôi học lớp 11 và đã làm một luận án nhỏ về chính xác điều này, sử dụng các chiến lược do các học sinh khác nghĩ ra). Nó bắt đầu với chuỗi tcc(và chơi như Tit cho Tat sau đó.

Lời xin lỗi cho mã kinh khủng; nếu ai đó có thể làm cho nó ngắn hơn trong khi không chơi golf chính xác, tôi sẽ rất biết ơn :-)

#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;
}

Không cần mã trùng lặp ở độ dài 1 và 2. Sử dụng rơi qua : case 1: case2: printf(...); break;. Và gcc muốn một tuyên bố rõ ràng string.hđể sử dụng strlen. Trong mọi trường hợp tôi có nó chạy.
dmckee

À, đúng rồi. Tuy nhiên, tôi không chắc chắn làm thế nào để phát hiện vòng đầu tiên, dù có tranh luận đầu tiên trống rỗng (lịch sử) hay không.
Joey

Tôi không chắc. Đó là bất cứ điều gì con trăn làm với Popen(p+" "+h,stdout=subprocess.PIPE,shell=True)khi nào h = ''. Tôi đoán vậy argc=1.
dmckee

1
Chuỗi ban đầu đó là một ý tưởng hay, nhắm thẳng vào Tit cho điểm yếu của Tat. Bạn nhận được một dẫn nhỏ trên nó, sau đó chơi theo cách của nó sau đó.
Josh Caswell

1
@Josh, dẫn nhỏ ở đâu? Chống lại T4T, điều này bắt đầu SRK và sau đó tiếp tục với K. Nhưng SR có giá trị 3 điểm cho mỗi người chơi.
Peter Taylor

5

Tên lửa chống 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'

Khá hợp lý để chống lại nhóm chiến binh cơ bản: giết Angel, bị quỷ đánh nhẹ (nhưng vẫn giữ điểm số thấp), nói chung là đánh bại RAND một cách khéo léo, và chỉ đánh bại Tit cho Tat. Làm kém khi chơi với chính nó.


Tôi đã gửi một bản chỉnh sửa làm cho cái này thực sự hoạt động :) Nó cần phải được phê duyệt.
Casey

@Casey: chúa tể, tôi đang phạm rất nhiều sai lầm ngu ngốc trong sự nhiệt tình của tôi đối với vấn đề này! Cảm ơn, nhưng tại sao bạn loại bỏ sh-bang?
Josh Caswell

Er, đó là một tai nạn. Tôi sẽ thêm nó trở lại.
Casey

@Casey: không vấn đề gì Tôi sẽ làm nó. Cần thêm một chuỗi doc anyways.
Josh Caswell

4

Hội tụ

Ban đầu tốt đẹp, sau đó chơi ngẫu nhiên với một mắt về lịch sử của đối thủ.

/* 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;
}

Tôi đã cố gắng giảm bớt trọng số trong lịch sử, nhưng chưa tối ưu hóa nó đúng cách.


4

Cá mập

#!/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'

Làm khá tốt so với đội hình cơ sở.


... bắt ngao?
arrdem

:) Nắm bắt những kẻ ngốc.
Josh Caswell

+1 để giữ vị trí thứ 2 nhất quán trong lĩnh vực hiện tại.
năm11

3

Pavlov - Giành chiến thắng, thua cuộc

Ở lượt đầu tiên, nó hợp tác, và sau đó nó hợp tác khi và chỉ khi cả hai người chơi chọn cho cùng một lựa chọn trong lần di chuyển trước.

#!/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'

Không nên sử dụng hist[0]( hist[-1]luôn luôn là bước đầu tiên của vòng này)?
Josh Caswell

Ồ wow, bạn nói đúng. Tôi giả định rằng chuỗi đầu vào có các vòng gần đây nhất ở cuối chuỗi chứ không phải đầu. Đã sửa.
Casey

3

Trung thực giữa những dối trá

#!/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'

Lưu ý rằng về THIEVES_CANTcơ bản là một cái bắt tay, mặc dù nó sẽ chỉ nổi lên khi chơi với một người hợp tác. Tuy nhiên, nó tránh được vấn đề ký sinh trùng bằng cách kiểm tra các lần lai sau. Làm khá tốt so với đội hình cơ sở.


+1 vì là chiến lược đầu tiên đáng tin cậy để đánh bại kẻ nói dối. Biên độ trung bình của chiến thắng - 300 điểm.
năm11

Có vẻ là mạnh nhất trong một giải chạy của lĩnh vực hiện tại.
Peter Taylor

Trên thực tế, không, Druid hiện đã sửa lỗi trong trình ghi bàn.
Peter Taylor

@rmckenzie, @Peter: Geez, thật sao? Tôi chỉ đi cho cá tính.
Josh Caswell

@josh - không còn nữa .... trên mã điểm mới @ mã ghi điểm của casey Lisper đã trở lại trên đầu theo sau là cá mập.
năm11

3

"Lừa đảo"

Bắt đầu bằng cách hợp tác, sau đó chọn tùy chọn nào mang lại cho nó giá trị mong đợi cao nhất. Đơn giản.

#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;
}

Được sử dụng để bắt đầu bằng cách hợp tác, nhưng bây giờ có vẻ như đào thoát thực sự hoạt động tốt hơn. EDIT: Oh chờ đợi, nó thực sự không.


1
Một thống kê khác! Chúng ta hãy xem cách nó chơi với các máy tính đồng loại của nó !
Josh Caswell

Nhân tiện, nếu bạn đổi for (char c = *str;thành char c; for (c = *str;gcc thì sẽ biên dịch cái này mà không phàn nàn rằng nó cần được đưa vào chế độ C99.
Peter Taylor

3

Wasp siêu quốc gia

Được triển khai trong Java vì tôi không chắc chắn cấu trúc dữ liệu sẽ phức tạp đến mức nào. Nếu đây là một vấn đề đối với ai đó thì tôi nghĩ rằng tôi có thể chuyển nó thành bash mà không có quá nhiều vấn đề bởi vì cuối cùng nó chỉ thực sự sử dụng các mảng kết hợp đơn giản.

Lưu ý : Tôi đã xóa phần này khỏi gói phù hợp với phiên bản mới nhất của bản vá của tôi cho trình ghi điểm để xử lý Java. Nếu bạn muốn đăng một giải pháp Java sử dụng các lớp bên trong thì bạn sẽ phải vá các bản vá.

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());
    }

}

Những thay đổi tôi đã thực hiện cho người ghi bàn để chạy này là:

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')]

Cảm ơn @rmckenzie vì đã gấp trong chức năng thách thức của tôi.


Chỉ là vấn đề về kiểu dáng .... nên tệp .java được coi là "nguồn" và được chuyển đến thư mục ./src và. Lớp cuối cùng được đặt trong thư mục ./warriors bởi cùng một chỉ mục được sử dụng trên các tệp .c hoặc java có được giải thích và như vậy .java và. class ở cùng nhau không? Những thay đổi tốt đẹp cho người ghi bàn trong mọi trường hợp ... sẽ có chúng trong chỉ số repo.
arrdem

@rmckenzie, điểm hay: đúng, về mặt kỹ thuật nó được biên dịch. Lý do tôi có tệp nguồn trong thư mục chiến binh là vì các tệp python cũng ở đó - và chúng được biên dịch. Nếu bạn muốn tôi có thể kiểm tra những thay đổi nào được yêu cầu để biên dịch nó từ ./src sang ./warriors - nhưng nó sẽ yêu cầu một vài đối số trình biên dịch, bởi vì mặc định Java cho rằng cấu trúc thư mục phản ánh gói (không gian tên).
Peter Taylor

@peter, tôi chỉ tự hỏi ... các chiến binh được tìm thấy trong ./warriors nhờ vào việc * nix 777, hoặc nếu không thì có thể thực thi được. Các tập lệnh Python và Lisp được NOMINALLY biên dịch để thực hiện, nhưng có thể thực thi được ở trạng thái tự nhiên (nguồn). ĐẾN KIẾN THỨC CỦA TÔI NHƯ MỘT NGƯỜI KHÔNG JAVA, các tệp .java không có các quyền đó và do đó sẽ không hiển thị. Đó là những gì mà c hack tồn tại ... vì việc biên dịch là một bước riêng biệt. Vì vậy, vâng. Tôi sẽ đánh giá rất cao nếu bạn muốn tạo ra sự thay đổi đó. LIÊN KẾT REPO
arrdem

Sử dụng mã của bạn và một con ong chmod 777'd, JVM đã tạo ra vẻ đẹp này. 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, thật lạ. Dù sao, tôi nghĩ rằng tôi sẽ có một bản vá cho bạn rất sớm. Tôi đã phải hack mã tải, vì các tệp lớp không thể thực thi được. Và nếu bất kỳ mục Java nào khác sử dụng các lớp bên trong thì nó sẽ bị hỏng.
Peter Taylor

3

Mềm_majo

Ah tốt, một trong những chiến lược tiêu chuẩn, chỉ để hoàn thành đội hình.

Điều này chọn di chuyển mà đối thủ đã thực hiện hầu hết; nếu bằng nó hợp tác.

#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');
    }
}

Mã của bạn là soft_majo, nhưng mô tả của bạn là hard_majo.
Peter Taylor

Peter: Eek, xin lỗi; đã sửa.
Joey

3

Mút ngẫu nhiên

Điều này sẽ khiếm khuyết nếu đối thủ khiếm khuyết quá thường xuyên (ngưỡng), nhưng sẽ ngẫu nhiên cố gắng chống lưng mỗi giờ và sau đó.

Nó khá tốt đối với tất cả mọi người ngoại trừ người chơi Java và Lisp (mà tôi không thể chạy, do cả Java và Lisp trên máy thử nghiệm); ít nhất là ít nhất

#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;
}

Chống lại HyperrationalWasp, nó thường sẽ chống lại quỷ dữ. Nó bắt đầu chỉ hợp tác mọi lúc, vì vậy tôi cho rằng đó là thiên thần và tiếp tục tấn công. Sau đó, khi nó đạt đến ngưỡng bạn sẽ chuyển sang chế độ ma quỷ và tôi sẽ chuyển sang t4t. Nếu nó ngẫu nhiên lùi lại trong 6 lần di chuyển đầu tiên thì tôi sẽ chuyển sang t4t trước khi bạn chuyển thành quỷ, nhưng tỷ lệ đó không cao.
Peter Taylor

1
Peter: Chà, tôi hiếm khi kiểm tra các chiến lược trực tiếp với nhau, vì lĩnh vực tổng thể có khá nhiều ảnh hưởng đến hiệu suất chiến lược. Hiện tại nó chủ yếu chiến đấu với dần dần và druid cho vị trí đầu tiên trong các thử nghiệm của tôi.
Joey

Dần dần và druid cả hai điểm khoảng 200 so với Wasp; kẻ hút ngẫu nhiên sẽ ghi được khoảng 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'

Chưa làm ra giá trị tốt nhất cho đến bygonesnay. Tôi không hy vọng đây sẽ là một chiến lược chiến thắng , nhưng tôi quan tâm đến hiệu suất của một chiến lược giống như những gì tôi nghĩ là "tốt" trong cuộc sống thực. Một sửa đổi trong tương lai có thể bao gồm kiểm tra số lượng khuyết tật lẫn nhau, quá.


2

Giúp ma cà rồng

#!/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'

Có một kết quả bất đối xứng đáng kinh ngạc khi đọ sức với chính nó. Nếu chỉ có giải pháp này có thể được áp dụng trong cuộc sống thực.


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'

Có hợp lý tốt chống lại danh sách cơ sở.


2

Đơn giản

#!/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'

Không sao chống lại đội hình cơ sở.


2

Tiểu thư

#!/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'

Không kém so với bộ cơ sở, nhưng khá tốt so với mục tiêu của nó. Rõ ràng, không được viết trong Đề án.


Tại sao tôi cảm thấy một thách thức?
năm11

Đánh bại bugger này .... ngẫu nhiên ngưỡng trong Lisper.
arrdem

@rmckenzie: nhưng điều đó ảnh hưởng đến lối chơi của bạn so với phần còn lại của lĩnh vực này như thế nào? Với đủ các cộng tác viên làm việc với nhau, các chiến lược hoang tưởng hoặc ghen tị sẽ bắt đầu tồi tệ hơn. Bạn vẫn có một giới hạn trên cố định, quá, có thể được khai thác.
Josh Caswell

Nếu bạn đọc qua kẻ nói dối hiện tại, nó sẽ phòng thủ hơn là ghen tị. Nó cố gắng phát hiện những đối thủ đang theo đuổi những chiến thuật phản bội thống kê như thế này, và chỉ sau đó mới trở lại lửa. Việc mở CC được thiết kế để đi bằng chân phải với Thief và có thêm lợi ích trong việc thuyết phục hầu hết các chiến thuật hợp tác để chơi cùng.
năm11

@rmckenzie: Rất tốt! Tôi sẽ cho nó một spin.
Josh Caswell

1

Tit cho hai Tats

một yêu thích cũ

#!/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'

Bạn không thể thực hiện trả lại trừ khi bạn ở trong một chức năng. Có thể sử dụng sys.exit(0)? Hoặc chỉ để nó kết thúc. Chỉnh sửa: Ngoài ra lời mời đầu tiên đến chương trình của bạn là không có bất kỳ lịch sử nào gây ra IndexErrorkhi bạn thực hiện argv[1].
Casey

Bạn có thể đã bỏ qua len(history)<2mệnh đề, bởi vì cái cuối cùng trông giống như elsemột phần.
dmckee

@Casey @dmckee Cảm ơn bạn đã sửa lỗi. "Duh" đối với tôi returnđặc biệt!
Josh Caswell

@dmckee: Điều này bắt đầu như là một phần của một điều phức tạp hơn, và sau đó tôi nhận ra rằng tôi đã viết lại Tit cho Two Tats và quyết định nhập nó. Sao chép-dán lỗi người dùng.
Josh Caswell

@Josh: Tôi đã thấy mục nhập Bygones của bạn một thời gian ngắn, bạn đã xóa nó? Nó có vẻ thích thú.
Casey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.