1P5:反復囚人のジレンマ


35

このタスクは、最初の定期的なプレミアプログラミングパズルプッシュの一部であり、新しいチャレンジタイプの提案のデモンストレーションを目的としています。

タスクは、繰り返しの囚人のジレンマを他の参加者よりもうまくプレイするプログラムを書くことです。

ほら、ヴィニー。私たちはあなたのセルメートを知っています---彼の名前は何ですか?ニッポ・アイルランド・ウクライナのギャング、ええ、マクウォンスキーは何かしらあなたが知っています。

ここで素敵になろうとしています、ヴィニー。あなたにチャンスを与えます。

彼が何を計画しているのかを教えていただければ、良い仕事が割り当てられます。

そして、もしあなたが...

ゲームのルール

  • コンテストは、一度に2人の競技者の完全なラウンドロビン(可能なすべてのペアリング)で構成されます(自己プレーを含む)。
  • 各ペア間で100ラウンドプレイされます
  • 各ラウンドでは、各プレイヤーは、他のプレイヤーの意図を知らずに、他のプレイヤーと協力するか裏切るかを選択するように求められます、この対戦相手と対戦した前のラウンドの結果を記憶します。
  • 組み合わせた選択に基づいて、各ラウンドでポイントが付与されます。両方のプレイヤーが協力すると、それぞれ2ポイントを獲得します。相互裏切りはそれぞれ1ポイントをもたらします。混合ケースでは、裏切りプレイヤーに4ポイントが付与され、協力者には1のペナルティが科せられます。
  • 「オフィシャル」マッチは、投稿後10日以内に実行され、私が仕事に参加し、「受け入れられた」勝者を選択するために使用できるすべての提出物が含まれます。私はMac OS 10.5ボックスを持っているので、POSIXソリューションは動作するはずですが、動作しないLinuxismがあります。同様に、win32 APIのサポートもありません。私は物事をインストールする基本的な努力をするつもりですが、制限があります。私のシステムの制限は、受け入れ可能な応答の制限を表すものではなく、単に「公式」一致に含まれるものです。

プログラマーインターフェイス

  • エントリは、コマンドラインから実行できるプログラムの形式である必要があります。決定は、標準出力上のプログラムの(唯一の)出力でなければなりません。この対戦相手との以前のラウンドの履歴は、コマンドライン引数として提示されます。
  • 出力は、「c」(クラムアップ)または「t」(すべて伝える)のいずれかです。
  • 履歴は、以前のラウンドを表す文字の単一の文字列であり、最新のラウンドが文字列の中で最も早く来ています。キャラクターは
    • 「K」(相互協力を意味する信仰維持するため)
    • 「R」(ラットb @ st @ rdの場合は売り切れました!
    • 「S」(吸盤用!裏切りの恩恵を受けたことを意味します)
    • 「E」(誰もが相互裏切りでナンバーワン探しているため

ブラケット

著者によって4人のプレイヤーが提供されます

  • エンジェル-常に協力
  • 悪魔-いつも話す
  • TitForTat-最初のラウンドで協力し、常に最後のラウンドで行われたとおりに行います
  • ランダム-50/50

これに、実行できるすべてのエントリを追加します。

合計スコアは、すべての対戦相手に対する合計スコアになります(1回だけのセルフプレイと平均スコアの使用を含む)。

応募者

(2011年5月2日現在7:00)

秘密の握手 | 対T42Tミサイル | 不信(バリアント) | アンチハンドシェイク | リトル・リスパー | 収束 | サメ | 確率的 | パブロフ-勝利の滞在、スイッチを失う | 泥棒の名誉 | 吸血鬼を助ける | ドルイド | Little Schemer | Bygones | 2タットの乳首 | シンプトン |

得点者

#! /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
  • 私の恐ろしいpythonに対する苦情は歓迎されます。
  • バグ修正を歓迎します

得点者の変更ログ:

  • ソートされたプレーヤーとスコアを印刷し、勝者を宣言します(4/29、ケーシー)
  • 必要に応じて、複数のトーナメント(./score warriors/ num_tournaments))default = 1を実行し、Pythonソースを検出およびコンパイルします(4/29、Casey)
  • 2番目のプレーヤーに誤った履歴が渡されていた特に愚かなバグを修正します。(4/30、dmckee、ジョシュに感謝)

初期の戦士

例として、結果を検証できるように

天使

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

または

#!/bin/sh
echo c

または

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

悪魔

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

ランダム

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

得点者は1秒間に何度も戦士を再呼び出しする可能性があるため、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;
}

実際に歴史で何かをする最初のもの。

提供された戦士のみに得点をかける

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)

その悪魔、彼は巧妙なものであり、ナイスガイは明らかに最後に来ます。

結果

「公式」実行の

('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
私のセルメイトがニッポ・アイリッシュ・ウクライナ人の場合、なぜ彼の名前はヒベルノ・シノ・ロシア語に見えるのですか?
ピーターテイラー

2
@ピーター:笑。真実?さて、(1)系図は明確ではありませんが、スコッチアイリッシュ経由でマイキングされたのではないでしょうか。(2)「Nippo」を書いた後、太陽の昇る土地から友達の名前をいろいろ試してみたが、彼らがスキャンする方法が気に入らなかったので、先に進んで中国の姓を使った代わりに良い、そして(3)彼らが交代でタイヤアイアンで私を打ち負かしたなら、私は違いを知りません。これは状況下でありそうです。
dmckee

1
@ジョシュ:[ 最後ではなく注] に変更return (s1, L1+h1), (s2, L2+h1)するのは簡単でしょうか?//カットアンドペーストの間違いまたは何かと同じくらいばかげたこと。シーシュ!return (s1, L1+h1), (s2, L2+h2)L2+h2L2+h1
dmckee

2
テストスクリプトに少し時間を費やしましたが、ここで更新を発表できることを嬉しく思います。この更新により、テストスクリプトに単純なシェルが追加されます。これにより、ユーザーはこのボットとそのボットを手動で実行したり、制限されたフィールドでトーナメントを実行したりできます。気軽に提案してください!ああ。そして、ボット対ボットのアイデアを@joshに負っています。それは本当に彼の「トレーナー」スクリプトのより洗練された実装です。
到着

2
おもしろい:23の出場者がいたので、それぞれ22ラウンドをプレイしました。誰もが「天使」をプレイした場合、すべてのスコアは4400でしたが、4167の最高スコアでさえも一致しませんでした。私たちが完璧な世界に住んでいれば... :)
Briguy37

回答:


11

徐々に

この戦略は、Beaufils、Delahaye、Mathieuの論文に基づいています。私のCは本当に最高ではありませんので、コードを改善/高速化するための提案があれば教えてください!

[編集]注目に値するのは、GradualはTat for Tatよりも優れた戦略になるように設計されていることです。協力する意思があり、相手の敵に対して報復するという点で、同様の特性を持っています。Tat for Tatは最後にプレイしたラウンドの記憶しか持っていませんが、Gradualは完全なインタラクションを記憶し、対戦相手がこれまでにディフェンスした回数をディフェクトします。ただし、その後再び相互協力を提供します。

いつものように、戦略のパフォーマンスは他の戦略のラインアップに少し依存します。また、元の論文はいくつかの詳細については明確ではありませんでした。

#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

秘密の握手

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

ここでの戦略は、最初の10ラウンドを犠牲にして「シークレット」ハンドシェイクを実行することです。自分に夢中なら、最初の10の動きの履歴を認識し、ゲームの残りのためにエンジェルキャップをかぶせます。私は自分のセルメイトが自分ではないことを認識するとすぐに、過度に協力的なセルメイトを利用しようとして悪魔に変身します。

最初の10ラウンドを犠牲にすることで悪魔自体を排除できるかどうかは、エントリーの数に強く依存します。損傷を最小限に抑えるため、ハンドシェイクには3つの協力者のみが表示されます。

編集:TAGMATCHを動的に変更して、そのうちの1つだけを変更するなどの愚かなエラーを防ぐため、将来のある時点でTAGを動的にすることができます。

編集2:最初の実行時にランダムにタグを生成し、sys.argv[0](で.pyc置き換えられ.py、バイトコードではなくコードに移動する)ファイルで指定されたタグに保存されます。これは、私のインスタンスのすべてが他の誰も持っていない唯一の情報だと思うので、寄生虫を避けるための唯一のオプションのように思えます。


しかし、あなたのドッペルゲンガーは自分自身を悪魔にすることをどのように知っていますか?
-arrdem

1
(私はいつも「Tit for Tat」と言ってオウムのように感じます...)T4Tは、T4T(以前に協力する)とDevil(より少ないRatの結果)に対してペアであなたの戦略を打ち負かし、あなたと結びつくことに注意してください戦略。もちろん、最終的に重要なのはペアリングの合計ではなく総計です。あなたが言うように、人口は重要です。
ジョシュキャスウェル

1
ああ、いや、TatのためにTからSを1つ余分に得る。いいね TAG逆再生されていることに気づきませんでした。しかし、あなたTAGMATCHは「KEEEKEEEKE」ではありませんか?"".join({('c', 'c'):'K', ('t', 't'): 'E'}[moves] for moves in zip(TAG, TAG))
ジョシュキャスウェル

@John良い点-私はもともと別のTAGを持っていましたが、協力を最小限に抑えるために変更したとき、TAGMATCHを更新するのを忘れました。@Arrdemアイデアは、私が自分自身と対戦している場合、最善のことは、両方が常に協力してスコアの合計を最大化することです。
アーロンデュフォー

1
ああ、それはいまいましい。そこで、すべての.pyファイルでコードを検索し、タグを抽出する必要があります。私はCでそれをしません、しかし
ジョーイ

6

リトル・リスパー

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

悪魔

次のフォーマットを考慮してください(Player1、Player2)

  • (C、T) - P2ゲインフォーポイント彼の裏切りのためには、P1はながらONEを失い
  • (T、T)-P2およびP1ゲイン1

P2が悪魔であると仮定すると、悪魔がポイントを失うことはできません。実際、彼ができる最悪のことは、1ポイントしか獲得できないことです。したがって、純粋にランダムな相手に対して、悪魔の最悪の可能性のあるスコアは正確に(5/2)* nになります(nはプレイされる「ゲーム」の数)。彼の絶対的な最悪のケースは彼自身に対するものであり、彼のスコアはnであり、彼の最高のケースは天使に対するものであり、それは4 * nです。

アサート:optimize_strat = devil

これはトーナメントです。セルメイトをバックスタビングすることは、協力よりもはるかに優れた戦略です。なぜなら、それは私のスコアをより高めるのに役立つからです(+4)。ボーナス-彼は非難される(-1)!彼のために首を突き出すと、私は勝つために立ちます(+2)と緩みます(-1)。そのため、統計的にバックスタビングが報われます。

しかし、それは最適ですか?

(このスコアリングシステムの下で)協力する理由はありません。

  • 間違った時間をクラムアップに選んだ場合、あなたは解けます。
  • ラットなら、少なくとも何も失うことはありません。
  • あなたがネズミと彼が愚かであるならば、あなたはあなたが良いpであった場合よりも2倍多くを得ます。

KOTHシステムでは、収益の最大化が不可欠です。2つのボットが完全に同期して協力している場合でも、そのスポーツマンシップでは個人のスコアは200ポイントしか増加しません。一方、悪魔は少なくとも100ポイントを獲得し、平均ケースは200、最大ケースは400で、対戦相手のコストはそれぞれ最大100ポイントです!したがって、実際には、悪魔は実際に平均300のゲームを獲得し、500に急上昇します。

結論-時間はわかります

私にとっては、悪魔が一日を費やさないように、得点を考え直すべきだと思われます。協力スコアを3に増やすと、すべてうまくいくかもしれません。しかし、パブロフと悪意が示すように、悪魔を検出し、悪魔が400点満点にするのを防ぐことは可能です。どちらかが彼らの信仰を正当化するために彼らの協力のために十分なポイントを獲得することを証明できますか?いや これらはすべて、候補者の最終分野に依存しています。

GL HF!

そして、この投稿にあなたの最悪のことをしてください。すべてが言われ終わったら、私はこれについて私の上級論文を書きたいです。

バージョン履歴

  1. ダシュバッガリーに対するLisperの許容度をランダムに変更するマージン変数を追加しました。
  2. 最初の2ラウンドでlisperをハマグリに更新し、協力的な対戦相手と右足で降りる
  3. 遺伝的アルゴリズムを使用して、標準の対戦相手に対する最大累積スコアに基づいて、ランダムしきい値ジェネレーターの最も堅牢な値を見つけました。それらを含む更新を投稿しました。

LISPERの公式バージョン

LISPERのバージョンを開発する


得点はゲームのさまざまなバリエーションによって異なります。私協力のインセンティブを増やして遊んでみましたが、選択した戦略に影響を与えることに同意します。良いニュース:あなたが独自のルールを設定し、得点を取得し、それを試すことができます。原則として、賞金を提供することさえできます。
-dmckee

fink install clisp ::指を繰り返しタップ::
dmckee

1
@josh-リンクをありがとう。このジレンマに関する他のウィキペディアのページをいくつか読みましたが、そのセクションを見逃していました。私が気づいたルールのバグ、ファイルシステムを使用するエントリに対するルールはありません。これにより、ハンドシェイクのラインに沿ってはるかに効率的な協力の可能性が生まれます。
到着

3
There is no reason to EVER (under this scoring system) co-operate半分だけ正しいです。対戦相手が歴史(天使、悪魔、ランダム)を考慮に入れていないことがわかっている場合は、常にディフェクトする必要があります。対戦相手が履歴を考慮に入れ、同期できる場合は、より良い結果を出すことができます。相手が合理的であるか超合理的であるかを検出することを中心に考えているアイデアがいくつかあります。
ピーターテイラー

1
最新バージョンでは3/20の時間でゼロ除算エラーが発生していませんか?2、5 (random 20)、または8を与える場合は常に(/ (+1 rand-num) 10)0.3、0.6、0.9であり、0.3で割った余りは0です。そう(floor *dbag* *margin*)死にます。
ジョシュキャスウェル

5

不信(バリアント)

これは、数年前の自分のテストで最初に出てきました(当時、私は11年生で、他の学生も考案した戦略を使用して、まさにこれについて小さな論文を書きました)。それはシーケンスから始まりtcc(その後、Tat for Tatのように再生されます。

恐ろしいコードをおApびします。誰かがそれを正確にゴルフしている間に短くすることができれば、私は感謝するでしょう:-)

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

長さ1および2でコードを複製する必要はありませんcase 1: case2: printf(...); break;。フォールスルーを使用します。そして、gccはstring.hを使用する明示的な宣言を望んでいますstrlen。いずれにせよ、私はそれを実行しています。
dmckee

ああ、本当。しかし、最初の引数(履歴)が空であるか、まったくないか、最初のラウンドを検出する方法がわかりませんでした。
ジョーイ

よく分かりません。PythonがPopen(p+" "+h,stdout=subprocess.PIPE,shell=True)whenで行うことは何でもh = ''です。推測していargc=1ます。
dmckee

1
その初期シーケンスは、Tatの弱さのためにTitを真っ直ぐに狙うという非常に良いアイデアです。あなたはそれに小さなリードを取得し、その後、その方法を再生します。
ジョシュキャスウェル

1
@ジョシュ、小さなリードはどこですか?T4Tに対して、これはSRKから始まり、Kで続きます。しかし、SRは各プレイヤーに3ポイントの価値があります。
ピーターテイラー

5

対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'

戦士の基本セットに対して合理的にうまくいきます:エンジェルを殺し、悪魔にわずかにbeatられますが(彼のスコアを低く保ちます)、一般的にRANDを手軽に破り、TatのためにかろうじてTitを破ります。自分自身と対戦するときはうまくいきません。


これを実際に機能させる編集を送信しました:)承認する必要があります。
ケーシー

@ケーシー:良い主よ、私はこの問題に対する私の熱意で非常に多くの愚かな間違いを犯しています!ありがとう、でもどうしてsh-bangを排除したのですか?
ジョシュキャスウェル

えー、それは事故だった。もう一度追加します。
ケーシー

@Casey:問題ありません。私はそれをやる。とにかくドキュメント文字列を追加する必要があります。
ジョシュキャスウェル

4

収束

最初はいいが、その後、相手の履歴を見ながらランダムにプレイする。

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

履歴の重み付けをいじってみましたが、適切に最適化されていません。


4

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

基本名簿に対して非常にうまくいきます。


...あさりをつかむ?
到着

:)ばかをつかむ。
ジョシュキャスウェル

現在のフィールドで一貫した2位を保持している場合は+1。
到着

3

パブロフ- 勝利を維持、スイッチを失う

最初のターンで協力し、その後両方のプレイヤーが前の動きで同じ選択を選んだ場合にのみ協力します。

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

これを使うべきではありませんhist[0]hist[-1]常にラウンドの最初の動きです)?
ジョシュキャスウェル

ああ、そうだね。入力文字列の先頭ではなく、末尾に最新のラウンドがあると想定しました。一定。
ケーシー

3

盗賊の名誉

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

これTHIEVES_CANTは本質的に握手であることに注意してください。ただし、協力者と対戦する場合にのみ出現します。ただし、後の交配をチェックすることで寄生虫の問題を回避します。基本名簿に対して非常にうまくいきます。


+1を確実にささやく最初の戦略にしたことで。勝利の平均マージン-300ポイント。
到着

現在のフィールドのトーナメントで最も強いようです。
ピーターテイラー

実際、いや、ドルイドは私がスコアラーのバグを修正したのです。
ピーターテイラー

@ rmckenzie、@ Peter:ほら、本当に?私はただ個性を求めていました。
ジョシュキャスウェル

@josh-もうありません。...新しいスコアコードについて@caseyのスコアコードLisperがトップに戻り、サメが続きます。
到着

3

「確率的」

協力して開始し、最も高い期待値を与えるオプションを選択します。シンプル。

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

以前は協力して開始していましたが、今では実際に欠陥が実際に改善されているようです。編集:ああ待って、それは実際にはありません。


1
別の統計学者!これが他の 計算機とどのように関係しているか見てみましょう!
ジョシュキャスウェル

ちなみに、次に変更for (char c = *str;するとchar c; for (c = *str;、gccはC99モードにする必要があると文句を言うことなくこれをコンパイルします。
ピーターテイラー

3

超合理的なハチ

データ構造がどれほど複雑になるかわからなかったため、Javaで実装されました。これが誰かにとって問題であれば、最終的には単純な連想配列のみを実際に使用するため、あまり多くの問題なくbashに移植できると思います。

:Javaを処理するためのスコアラーへのパッチの最新バージョンに合わせて、パッケージからこれを削除しました。内部クラスを使用するJavaソリューションを投稿する場合は、パッチを適用する必要があります。

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

}

これを実行するためにスコアラーに加えた変更は次のとおりです。

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

チャレンジャー関数を折り畳んでくれた@rmckenzieに感謝します。


スタイルの問題.... .javaファイルを「ソース」と見なし、。/ srcディレクトリに移動し、.cファイルで使用されているのと同じ添え字で./warriorsフォルダーに配置される最終的な.class javaが解釈され、.javaと.classが一緒にとどまるのですか?いずれにせよ、得点者への素晴らしい変更は...レポの統計にそれらを持っています。
到着

@rmckenzie、良い点:はい、技術的にはコンパイルされています。ソースファイルをwarriorsディレクトリに置いた理由は、Pythonファイルもそこにあり、コンパイルされているからです。必要に応じて、。/ srcから./warriorsにコンパイルするために必要な変更を確認できますが、デフォルトではディレクトリ構造がパッケージ(名前空間)を反映するとJavaが想定しているため、いくつかのコンパイラー引数が必要になります。
ピーターテイラー

@peter、私はただ疑問に思っていました...戦士は* nix 777であるか、そうでなければ実行可能であるという理由で./warriorsで見つかります。PythonおよびLispスクリプトは、パフォーマンスのためにわずかにコンパイルされていますが、自然な(ソース)状態で実行可能です。非ジャバ人としての私の知識では、.javaファイルにはこれらのアクセス許可がないため、表示されません。コンパイルは別のステップであるため、これがcハックの目的です。ええ その変更を検討していただければ幸いです。レポリンク
11

コードと777'd waspを使用して、JVMはこの美しさを放ちました。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)
到着

@rmckenzie、それは奇妙だ。とにかく、私はあなたのためのパッチをすぐに持っていると思います。クラスファイルは実行可能ではないため、ロードコードをハッキングする必要がありました。また、他のJavaエントリが内部クラスを使用している場合、破損します。
ピーターテイラー

3

そらる

まあ、もう一つの標準戦略は、ラインナップを完成させることです。

これは、相手が最も行った動きを選択します。等しい場合、協力します。

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

コードはsoft_majoですが、説明はhard_majoです。
ピーターテイラー

ピーター:ええ、ごめんなさい。一定。
ジョーイ

3

ランダム吸盤

これは、対戦相手が頻繁に(しきい値)欠陥する場合に欠陥がありますが、時々ランダムにバックスタブを試みます。

JavaとLispプレーヤー(テストマシン上のJavaとLispのどちらでもないため、実行できません)以外のすべてのユーザーに対してかなり良好です。ほとんどの場合、少なくとも。

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

HyperrationalWaspに対して、それは一般に悪魔に対して大体のことをします。それは常に協力することから始まるので、私はそれが天使だと思い、攻撃を続けます。それがしきい値に達すると、悪魔モードに切り替わり、t4tに切り替わります。最初の6動きでランダムにバックスタブする場合、悪魔に切り替える前にt4tに切り替えますが、その可能性は高くありません。
ピーターテイラー

1
ピーター:まあ、全体的な分野が戦略のパフォーマンスにかなりの影響を及ぼすため、私は戦略を互いに直接テストすることはめったにありません。現在、ほとんどの場合、私の最初のテストでは段階的でドルイドと戦います。
ジョーイ

段階的およびドルイドの両方がWaspに対して約200を記録します。ランダム吸盤は83についてスコアます
ピーター・テイラー

2

過ぎ去りし者

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

bygonesまだ最高の価値を生み出していない。私はこれが勝利戦略になるとは思っていませんが、実際の生活で「良い」と思うような戦略の実行に興味があります。将来の改訂には、相互離反の数のチェックも含まれる可能性があります。


2

吸血鬼を助ける

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

自分自身に対してピットインすると、面白い非対称の結果になります。このソリューションだけが実際に適用できれば。


2

ドルイド

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

基本名簿に対して適度に良好です。


2

シンプトン

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

基本名簿に対しては問題ありません。


2

リトルスケマー

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

基本セットに対しては不十分ですが、ターゲットに対しては非常に良好です。明らかに、Schemeには書かれていません。


なぜチャレンジを感じるのですか?
到着

この盗聴者を倒した.... Lisperのしきい値をランダム化した。
到着

@rmckenzie:しかし、それはフィールドの残りに対するプレーにどのように影響しましたか?十分な協力者が互いに協力しあうと、妄想的またはen的な戦略が悪化し始めます。固定された上限もまだあり、これは悪用される可能性があります。
ジョシュキャズウェル

現在のlisperを読み通せば、viousよりも防御的です。このような統計的に危険な戦略を追求している敵を検出しようと試みて、その後にのみ火を返します。CCのオープニングは、Thievesで右足を踏み出すように設計されており、協力ストラテジーのほとんどを一緒にプレイするよう説得するという追加の利点があります。
到着

@rmckenzie:とても良い!スピンしてみます。
ジョシュキャスウェル

1

2タットのシジュウカラ

別の古いお気に入り

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

関数内にいる場合を除き、リターンを行うことはできません。たぶん使うsys.exit(0)?または、そのまま終了します。編集:また、あなたのプログラムへの最初の呼び出しはIndexError、あなたが行うときに発生する履歴なしですargv[1]
ケーシー

len(history)<2最後の句はelse部品のように見えるため、句を省略した可能性があります。
dmckee

@Casey @dmckeeバグ修正をありがとう。return特に私にとって「ダウ」!
ジョシュキャスウェル

@dmckee:これは、より複雑なものの一部として始まりました。それから、Tit for Two Tatsを書き直して、それを入力することにしました。コピーアンドペーストのユーザーエラー。
ジョシュキャスウェル

@Josh:Bygonesのエントリを簡単に見ましたが、削除しましたか?興味がありました。
ケーシー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.