시끄러운 죄수의 딜레마


35

이 도전에서, 당신은 시끄러운 반복 죄수의 딜레마를 할 것입니다.

죄수의 딜레마는 협력, 또는 결함 : 두 선수, 두 가지 옵션이 각각가 게임 이론의 시나리오입니다. 각 플레이어는 협력하는 것보다 결함이있는 경우 자신을 위해 더 나아지지만, 두 플레이어는 두 플레이어 모두 결함이있는 사람과 협력하는 결과를 선호합니다.

반복 된 죄수의 딜레마는 같은 상대입니다. 같은 상대를 반복해서 상대하고 과거에 상대가했던 것을 알고 있습니다. 당신의 목표는 상대방이 어떻게 행동하든 항상 자신을 위해 가장 높은 점수를 쌓는 것입니다.

시끄러운 죄수의 딜레마는 의사 소통에 약간의 소음을 유발합니다. 상대방이 과거에 한 일에 대한 지식은 약간의 소음이 발생합니다. 또한 과거에 어떤 움직임을했는지 알게 될 것입니다. 소음은 같은 상대에 대한 라운드에서 일정하지만 다른 라운드마다 다릅니다.

도전

이 도전에서, 당신은 시끄러운 반복 죄수의 딜레마를 연주하는 Python 3 프로그램을 작성할 것입니다.

프로그램은 세 가지 입력을받습니다 :

  • 랜덤 플립을 적용 하지 않고 자신의 움직임 .

  • 무작위 뒤집기가 적용된 상대의 움직임.

  • 상태 변수는 매 라운드마다 빈 목록으로 시작하며 원하는 경우 수정할 수 있습니다. 사용하지 않으려면 무시해도됩니다.

귀하의 프로그램은 'c'협조하거나 'd'결함을 갖도록 출력되어야합니다 .

예를 들어, 상대방이 과거에 60 % 이상 협력 한 경우, 랜덤 플립이 적용된 후 처음 10 번의 플립에 대해 협력하는 프로그램이 있습니다.

def threshold(my_plays, their_flipped_plays, state):
    if len(their_flipped_plays) < 10:
        return 'c'
    opp_c_freq = their_flipped_plays.count('c')/len(their_flipped_plays)
    if opp_c_freq > 0.6:
        return 'c'
    else:
        return 'd'

파이썬을 모르는 경우 의사 코드로 제출물을 작성하면 누군가 (나 또는 사이트의 다른 구성원)가 해당 Python 프로그램을 작성할 수 있습니다.

게임 플레이

토너먼트 러너는 noisy-game 에서 찾을 수 있습니다 . 실행 noisy-game.py대회를 실행합니다. 해당 저장소를 새 제출로 업데이트합니다. 예제 프로그램은에서 찾을 수 있습니다 basic.py.

프로그램의 전체 점수는 게임에서 100 회 이상 플레이 한 총 점수입니다.

게임은 자신을 포함하여 각 플레이어에 대한 각 플레이어의 라운드 로빈 매치업으로 구성됩니다. 매치업은 100 라운드로 구성됩니다. 라운드는 300 개의 동작으로 구성되며 각 동작은 'c'또는을 출력 'd'합니다.

귀하의 제출물은 귀하의 제출물을 포함하여 모든 제출물과 대결합니다. 각 경기는 100 라운드로 구성됩니다. 각 라운드에서 플립 확률은에서 무작위로 균일하게 선택됩니다 [0, 0.5].

각 라운드는 300 이동으로 구성됩니다. 각각의 움직임에서, 두 프로그램 모두 시도한 모든 이전 플레이와 플립이 적용된 후 다른 프로그램이 수행 한 모든 이전 플레이 및 상태 변수는 프로그램이 원하는 경우 수정할 수있는 변경 가능한 목록입니다. 프로그램이 움직임을 출력합니다.

이동은 다음과 같이 점수가 매겨집니다 : 프로그램이를 재생 'c'하면 반대 프로그램은 2 점을 얻습니다. 프로그램이를 재생하면 'd'해당 프로그램은 1 포인트를 얻습니다.

그리고, 각 이동은 플립 확률과 동일한 확률로 독립적으로 플립되고, 상대에게 보여주기 위해 저장된다.

모든 라운드가 플레이 된 후, 우리는 각 플레이어가 각 매치업에서 얻은 점수를 합산합니다. 그런 다음 다음 점수 시스템을 사용하여 게임에 대한 각 플레이어의 점수를 계산합니다. 이 득점은 모든 경기가 완료된 후에 수행됩니다.

채점

우리는 진화 점수를 사용할 것입니다. 각 프로그램은 동일한 무게로 시작합니다. 그런 다음 게임의 총점을 사용하여 가중치가 100 회 반복되도록 가중치가 다음과 같이 업데이트됩니다.

각 프로그램의 새 가중치는 이전 가중치와 상대 점수에 따라 가중치가 부여 된 평균 점수의 곱에 비례합니다.

100 건의 업데이트가 적용되며, 최종 가중치는 해당 게임 실행에 대한 각 프로그램의 점수입니다.

전체 점수는 게임에서 100 회 이상을 합한 것입니다.

플레이어는이 도전에 대한 모든 정답과 6 가지 기본 프로그램 으로 시작합니다.

경고

입력을 수정하지 마십시오. 협력 또는 결함을 통한 경우를 제외하고 다른 프로그램의 실행에 영향을 미치지 마십시오. 다른 제출물을 인정하고 상대방이 자비로 이익을 얻는 희생적인 제출물을 만들지 마십시오. 표준 허점 은 금지되어 있습니다.

편집 : 제출물은 기본 프로그램 이나 이전 제출물을 정확하게 복제 할 수 없습니다 .

궁금한 점이 있으면 언제든지 문의하십시오.

현재 결과

nicht_genug: 40.6311
stealer: 37.1416
enough: 14.4443
wait_for_50: 6.947
threshold: 0.406784
buckets: 0.202875
change_of_heart: 0.0996783
exploit_threshold: 0.0670485
kickback: 0.0313357
tit_for_stat: 0.0141368
decaying_memory: 0.00907645
tit_for_whoops: 0.00211803
slider: 0.00167053
trickster: 0.000654875
sounder: 0.000427348
tit_for_tat: 9.12471e-05
stubborn_stumbler: 6.92879e-05
tit_for_time: 2.82541e-05
jedi2sith: 2.0768e-05
cooperate: 1.86291e-05
everyThree: 1.04843e-05
somewhat_naive: 4.46701e-06
just_noise: 1.41564e-06
growing_distrust: 5.32521e-08
goldfish: 4.28982e-09
vengeful: 2.74267e-09
defect: 3.71295e-10
alternate: 2.09372e-20
random_player: 6.74361e-21

이 질문에 대한 답변과 상대방의 플레이를 무시하는 기본 프로그램에 대한 결과 만있는 결과 :

nicht_genug: 39.3907
stealer: 33.7864
enough: 20.9032
wait_for_50: 5.60007
buckets: 0.174457
kickback: 0.0686975
change_of_heart: 0.027396
tit_for_stat: 0.024522
decaying_memory: 0.0193272
tit_for_whoops: 0.00284842
slider: 0.00153227
sounder: 0.000472289
trickster: 0.000297515
stubborn_stumbler: 3.76073e-05
cooperate: 3.46865e-05
tit_for_time: 2.42263e-05
everyThree: 2.06095e-05
jedi2sith: 1.62591e-05
somewhat_naive: 4.20785e-06
just_noise: 1.18372e-06
growing_distrust: 6.17619e-08
vengeful: 3.61213e-09
goldfish: 3.5746e-09
defect: 4.92581e-10
alternate: 6.96497e-20
random_player: 1.49879e-20

승리

새로운 제출물이 게시되면 경쟁은 무기한 개방됩니다. 그러나이 질문이 게시 된 1 개월 후의 결과에 따라 당첨자 (답변 수락)를 선언하겠습니다.


tit_for_whoops는 상대의 플레이를 어떻게 무시합니까?
LyricLy

@LyricLy 나는이 범주가 상대를 무시하는 Isaac이 제공하는 기본 프로그램을 말한다고 가정한다.
FryAmTheEggman

1
상태 변수를 사용하여 제출할 때 모든 움직임을 기록 할 수 있으므로 실제 움직임과 뒤집힌 움직임을 모두 알고 플립 확률을 추정 할 수 있다는 것을 알고 있습니까?
xnor

1
@xnor 당신은 항상 당신의 진정한 움직임을 알게됩니다. 뒤집힐 수있는 상대의 움직임뿐입니다.
니모닉

1
@isaacg 나는 등 exploit_threshold()으로 여러 번 복사를 시도 exploit_threshold1()하고 players목록에 추가했습니다 . 동일한 전략에 대해 왜 크게 다른 결과를 얻습니까?
ngn

답변:


4

Genug Ist Nicht Genug

( enough2또는 라고도 함 stealback)

def nicht_genug(m,t,s):
    if not s:
        s.append("c")
        return "c"
    if s[0]=="t":
        return "d"
    if m[-42:].count("d")>10 or len(t)+t.count("d")>300:
        s[0]="t"
        return "d"
    if t[-1]=="d":
        if s[0]=="d":
            s[0]="c"
            return "d"
        else:
            s[0]="d"
            return "c"
    else:
        if t[-3:].count("d")==0:
            s[0]="c"
        return "c"

나는 원래 배운 두 문신에 대한 짹 이틀 동안 대기했다 연속 같은 문신 tit_for_whoops않습니다, 실제로 우리가 용서하고 (물론, 거의 ...) 이전에 하나의 문신을 잊지 해봐야 할 것 같습니다. 그리고 마지막 라운드에서 많은 선수 결함. 나는 지금까지 모든 것이 잘되었을 때 좋기를 좋아하지만 봇의 공차 막대는 계속 낮아지고 있습니다.


11

가슴을위한 여자

ncase.me/trust의 전략에서 영감을 얻었습니다.

def tit_for_whoops(m, t, s):
    if len(t) < 2:
        return 'c'
    else:
        return 'd' if all([x == 'd' for x in t[-2:]]) else 'c'

다른 플레이어가 연속으로 두 번 결함을 가지고 오해를 방지하기 위해 결함이 있습니다.


제출해 주셔서 감사합니다! 플립 확률은 평균 1/4이므로 16 이동 정도마다 더블 플립이 발생합니다.
isaacg

사용하지 않으려는 경우 무시할 수있는 상태 변수를 추가했습니다.
isaacg 1

9

마음의 변화

def change_of_heart(m, t, s):
    return 'c' if len(t) < 180 else 'd'

도중에 마음의 변화가 있습니다. 놀랍게도 잘합니다.


리드 / 2 위를 축하합니다. 나는 전략을 무시하는 상대방이 그렇게 잘한다는 것에 감동하고 놀랐습니다.
isaacg

9

전략 도둑

충분하고, change_of_heart, tit-for-whoops에서 영감을 받았습니다. 조금 더 용서해야합니다. 최상의 결과를 위해 숫자를 조정하려고했지만 많이 바꾸고 싶지 않았습니다.

def stealer(mine, theirs, state):
    if len(mine) == 0:
        state.append('c')
        return 'c'
    elif len(mine) > 250:
        return "d"
    elif state[0] == 't':
        return 'd'
    elif mine[-40:].count('d') > 10:
        state[0] = 't'
        return 'd'
    elif theirs[-1] == 'd':
        if state[0] == 'd':
            state[0] = 'c'
            return 'd'
        else:
            state[0] = 'd'
            return 'c'
    elif all([x == 'c' for x in theirs[-3:]]):
        state[0] = 'c'
        return 'c'
    else:
        return 'c'

PPCG에 오신 것을 환영합니다!
주세페

리드를 축하합니다!
isaacg

8

젖꼭지 시간

def tit_for_time(mine, theirs, state):
    theirs = theirs[-30:]
    no_rounds = len(theirs)
    return "c" if no_rounds < 5 or random.random() > theirs.count("d") / no_rounds else "d"

당신이 나를 아프게하는 데 대부분의 시간을 소비했다면, 나는 단지 당신을 다치게 할 것입니다. 아마.


좋은 제출! 당신은 현재 상대를 인식하는 기본 프로그램없이 1 위입니다.
isaacg

7

불신의 성장

import random

def growing_distrust(mine, theirs, state):
    # Start with trust.
    if len(mine) == 0:
        state.append(dict(betrayals=0, trust=True))
        return 'c'

    state_info = state[0]

    # If we're trusting and we get betrayed, trust less.
    if state_info['trust'] and theirs[-1] == 'd':
        state_info['trust'] = False
        state_info['betrayals'] += 1

    # Forgive, but don't forget.
    if random.random() < 0.5 ** state_info['betrayals']:
        state_info['trust'] = True

    return 'c' if state_info['trust'] else 'd'

상대방이 나를 배신할수록 소음 만 믿을 수 있습니다.


예, 아니오 상태는 유감 스럽지만 제출물이 균일하게되기를 원했기 때문에 이것이 내가 생각할 수있는 최선의 방법입니다. 상태를 추가하는 방법에 대한 아이디어가 있습니까?
isaacg

state기본적으로 목록 이라는 주장이 있습니까? 목록은 변경 가능하므로 상태를 쉽게 수정할 수 있습니다.
LyricLy

어떻게 요? 어떻게 될지 모르겠습니다.
LyricLy

@Mnemonic 나는 이것을 구현하는 방법을 알고 있다고 생각한다. 나는 소용돌이를 줄 것이다.
isaacg 1

초기에 빈 목록이며 수정할 수있는 상태 변수를 추가했습니다.
isaacg 1

7

Jedi2Sith

멋지고 이타적인 모든 것을 시작하지만 시간이 지남에 따라 어두운면의 영향이 돌아올 때까지 꾸준히 강해집니다. 이 영향을 막을 수는 없지만 그것이 일어나는 모든 나쁜 일은 단지 어두운면의 힘에 기여합니다 ...

def jedi2sith(me, them, the_force):
  time=len(them)
  bad_things=them.count('d')
  dark_side=(time+bad_things)/300
  if dark_side>random.random():
    return 'd'
  else:
    return 'c'

온라인으로 사용해보십시오!


6

슬라이더

def slider(m, t, s):
    z = [[2, 1], [0, 1], [2, 3], [2, 1]]
    x = 0
    for y in t:
      x = z[x][y == 'c']
    return 'c' if x < 2 else 'd'

'c'로 시작하여 점차 'd'쪽으로 또는 멀어지게 움직입니다.


상태 변수를 사용하기 위해 기능적으로 동등한 재 작성을 수행했습니다. 왜냐하면 꽤 느리게 실행 되었기 때문입니다. 그러나 아무것도 변경할 필요가 없습니다.
isaacg

6

완고한 텀블러

def stubborn_stumbler(m, t, s):
    if not t:
        s.append(dict(last_2=[], last_3=[]))
    if len(t) < 5:
        return 'c'
    else:
        # Records history to state depending if the last two and three
        # plays were equal
        s = s[0]
        if t[-2:].count(t[-1]) == 2:
            s['last_2'].append(t[-1])
        if t[-3:].count(t[-1]) == 3:
            s['last_3'].append(t[-1])
    c_freq = t.count('c')/len(t)
    # Checks if you've consistently defected against me
    opp_def_3 = s['last_3'].count('d') > s['last_3'].count('c')
    opp_def_2 = s['last_2'].count('d') > s['last_2'].count('c')
    # dist func from 0 to 1
    dist = lambda x: 1/(1+math.exp(-5*(x-0.5)))
    # You've wronged me too much
    if opp_def_3 and opp_def_2:
        return 'd'
    # Otherwise, if you're consistently co-operating, co-operate more
    # the less naive you are
    else:
        return 'c' if random.random() > dist(c_freq) - 0.5 else 'd'

일관된 플레이만으로 악용 임계 값 전략을 기반으로 결함과 대부분의 협력 간 전환 추적

업데이트 : 2 연속 및 3 연속 재생을 모두 추적하여 가혹한 조건에서만 펀칭하고 확실하지 않은 경우 무작위 선택을 추가합니다

업데이트 2 : 조건 제거 및 분배 기능 추가


주도권을 잡는 첫 번째 프로그램 작성에 대한 모순!
isaacg

6

소음 봇

def just_noise(m,t,s):
    return 'c' if random.random() > .2 else 'd'

나는 분명히 봇과 협력하고 있습니다. 그것은 단지 소음입니다.


6

충분하다

def enough(m,t,s):
    if not s:
        s.append("c")
        return "c"
    if s[0]=="t":
        return "d"
    if m[-42:].count("d")>10:
        s[0]="t"
        return "d"
    if t[-1]=="d":
        if s[0]=="d":
            s[0]="c"
            return "d"
        else:
            s[0]="d"
            return "c"
    else:
        return "c"

두 tats가 연속적이지 않아도되는 tats 두 개의 tit로 시작합니다 (와 달리 tit_for_whoops). d너무 자주 연주 d해야하는 경우에는 총합입니다.


리드를 축하합니다!
isaacg

6

금붕어 봇

def goldfish(m,t,s):
    return 'd' if 'd' in t[-3:] else 'c'

금붕어는 결코 용서하지 않지만 빨리 잊어 버립니다.


6

사기꾼 (다시 복원)

마지막 10 개의 플레이 만이 설명되지만 5 개의 2 개 블록으로 나뉘며, 각 블록은 양호 또는 불량으로 분류됩니다.

상대방이 평균적으로 "좋은"게임을한다면, 속임수는 점점 더 잘 재생됩니다. 결과가 모호한 경우, 사기꾼은 상대방을 안전하게 유혹 할 수 있습니다. 상대방이 "나쁜"게임을하는 것으로 보이면 사기꾼이 보복합니다.

아이디어는 지금 순진한 플레이어로부터 포인트를 수집하고 속이는 플레이어를 조기에 잡는 것입니다.

import random
def trickster(player,opponent,state):
    pBad = 0.75
    pNice = 0.8
    pReallyBad =0.1
    decay = 0.98
    r = random.random()
    if len(player)<20: #start off nice
        return 'c' 
    else: #now the trickery begins
        last5 = opponent[-5:].count('c')/5.0 > 0.5
        last5old = opponent[-10:-5].count('c')/5.0  > 0.5
        if last5 and last5old: #she is naive, punish her
            pBad = pBad*decay #Increase punishment
            if r<pBad:
                return 'c'
            else:
                return 'd'
        elif last5 ^ last5old: #she is changing her mind, be nice!
            if r<pNice:
                return 'c'
            else:
                return 'd'
        else: #she's ratting you out, retaliate
            pReallyBad = pReallyBad*decay #Retaliate harder
            if r<pReallyBad:
                return 'c'
            else:
                return 'd'

면책 조항 : 내가 뭔가 잘못하고 있다면> 이전에 알려주지 말고 수정하십시오.


사이트에 오신 것을 환영합니다! 불행히도 현재 코드가 작동하지 않습니다. 당신은 다른 후에 elif가 있습니다. 고칠 수 있습니까? 감사합니다
isaacg

elif부터 모든 것이 한 번 더 들여 쓰기되어야한다고 생각합니다.
isaacg

맞습니다. 들여 쓰기하겠습니다.
Hektor-Waartgard

@isaacg 나는 새로운 코드로 답변을 업데이트했습니다. 나는 질문 의견에서 당신에게 그것을 말할만큼 충분히 평판이 없습니다. 상태 변수를 올바르게 사용하고 있는지 확신 할 수 없으며 빈 목록이므로 원하는 것을 추가 할 수 있다고 가정합니다.
Hektor-Waartgard

2
작동하지 않습니다. 매 턴마다 현재 이동이 뒤집어 졌는지 아닌지 (두 플레이어에 대해 독립적으로) 결정됩니다. 그런 다음 그 결정이 고쳐집니다. 당신은 항상 뒤집어 지거나 바뀌지 않을 것 같은 동일한 첫 번째 움직임을 볼 수 있지만 변경되지는 않습니다.
Christian Sievers

5

부패 메모리

def decaying_memory(me, them, state):
    m = 0.95
    lt = len(them)

    if not lt:
        state.append(0.0)
        return 'c'

    # If it's the last round, there is no reason not to defect
    if lt >= 299: return 'd'

    state[0] = state[0] * m + (1.0 if them[-1] == 'c' else -1.0)

    # Use a gaussian distribution to reduce variance when opponent is more consistent
    return 'c' if lt < 5 or random.gauss(0, 0.4) < state[0] / ((1-m**lt)/(1-m)) else 'd'

최근 역사의 무게를 더.니다. 과거를 천천히 잊어 버리십시오.


5

반동

def kickback(m, t, s):
  if len(m) < 10:
    return "c"
  td = t.count("d")
  md = m.count("d")
  f = td/(len(t)+1)
  if f < 0.3:
    return "d" if td > md and random.random() < 0.1 else "c"
  return "c" if random.random() > f+2*f*f else "d"

모호한 아이디어 ...


적응 형 기본 주문이 제거 된 버전에서 선두를 차지한 것을 축하합니다.
isaacg

감사. 두 결과가 얼마나 다른지 놀랍습니다!
Christian Sievers

4

실제로 "잡음"전체를 얻지 못함

def vengeful(m,t,s):
    return 'd' if 'd' in t else 'c'

배신자를 용서하지 마십시오.


4

측심기:

편집 : 아마도 저소음 시나리오에서 보복 추가

기본적으로, 4 번의 첫 움직임이 모두 협력한다면, 평소보다 적은 소음을 기대해야합니다. 우리는 결코 결함이 없을 때 얻을 수있는 적은 지점을 보충하기 위해 조금씩 결함을 일으키고, 잡음에 대해 비난받을 수 있습니다. 또한 그들이 우리에게 결함이있는 경우 보복

만약 우리의 상대가 그 턴 (2 번 이상)에서 많은 결함을 가지고 있다면, 우리는 단지 그들에게 결함을줍니다. 그것이 단지 소음이라면, 그 소음은 우리의 움직임에 영향을 줄 것입니다.

그렇지 않으면, 단지 한 번의 움직임 만 결함이라면, 우리는 게임의 나머지 부분에 대해 간단한 짹을합니다.

def sounder(my, their, state):
    if len(my)<4:
        if their.count("d")>1:
            return "d"
        return "c"
    elif len(my) == 4:
        if all(i == "c" for i in their):
            state.append(0)
            return "d"
        elif their.count("c") == 3:
            state.append(1)
            return "c"
        else:
            state.append(2)
    if state[0] == 2:
        return "d"
    if state[0] == 0:
        if not "d" in my[-4:]:
            return "d"
        return their[-1]
    else:
        return their[-1]

3

번갈아 하는

def alternate(m, t, s):
    if(len(m)==0):
        return 'c' if random.random()>.5 else 'd'
    elif(len(m)>290):
        return 'd'
    else:
        return 'd' if m[-1]=='c' else 'c'

첫 라운드에서 무작위로 뽑은 다음 교대로 진행합니다. 마지막 10 라운드에서 항상 결함.


3

50 분 기다립니다

def wait_for_50(m, t, s):
  return 'c' if t.count('d') < 50 else 'd'

50 개의 결함이 발생하면 그것을 갖자!


당신의 의도를 유지하면서 파이썬을 고쳤습니다.
isaacg

3 위로 이동을 축하합니다.
isaacg

2

Somehwat 순진한

def somewhat_naive(m, t, s):
    p_flip = 0.25
    n = 10
    if len(t) < n:
        return 'c' if random.random() > p_flip else 'd'
    d_freq = t[-n:].count('d')/n
    return 'c' if d_freq < p_flip else 'd'

마지막 n 번 턴 에서 플립 확률 (거의)보다 적은 결함을 가진 경우 잡음이 아니라는 것이 아니라고 가정합니다.

가장 좋은 n을 파악하지 못하면 더 자세히 볼 수 있습니다.


2

세 개

def everyThree(me,him,s):
    if len(me) % 3 == 2:
        return "d"
    if len(me) > 250:
        return "d"
    if him[-5:].count("d")>3:
        return "d"
    else:
        return "c"

3 회전마다 결함이 있습니다. 또한 마지막 50 턴에도 결함이 있습니다. 또한 그의 상대가 마지막 라운드에서 5 개 중 4 개에 결함이있는 경우에도 결함이 있습니다.


2

버킷

def buckets(m, t, s):
    if len(m) <= 5:
        return 'c'
    if len(m) >= 250:
        return 'd'
    d_pct = t[-20:].count('d')/len(t[-20:])
    if random.random() > (2 * d_pct - 0.5):
        return 'c'
    else:
        return 'd'

시작하기에 좋습니다. <25 % d, c,> 75 % d, d를 반환하고 그 사이에 선형 확률 ​​함수를 따라 임의로 선택하는 경우 마지막 20을 봅니다. 마지막 50 개. 지난 10시에 이것을 가지고 있었지만 지난 50 개의 결함이 많이있었습니다.

처음으로 무언가를 고쳐야하는지 (또는 어떻게 테스트 할 수 있는지) 알려주십시오.


로컬로 테스트하려면 저장소를 복제하고 noisy-game.py를 실행하십시오. 시간이 걸리므로 players빠른 반복 을 위해 상대를 일부 제거 할 수 있습니다 .
isaacg

고마워 Isaac-나는 그것으로 놀고 약간 어설프게해야합니다.
brian_t

1

젖꼭지에 대한 통계

상대방이 절반 이상 결함을 가지고 있다면 결함.

def tit_for_stat(m, t, s):
  if t.count('d') * 2 > len(m):
    return 'd'
  else:
    return 'c'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.