在这个问题中,设计了一种游戏,玩家在囚徒困境中将一对一面对面地确定彼此对立,从而确定哪种迭代策略得分最高。
在这个问题中,我设计了一种方法,允许多个人同时互相对抗囚徒困境。在这种变化中,回报矩阵是不必要的,每两个参与者之间的每个结果都是两个功能独立决策的总和。
您的任务是构建一个AI来玩多人囚徒困境的对称,通用版本,以实现最高分。
游戏规则
在这种多人,多人囚徒困境的每一轮中,玩家A
可以决定从其他玩家中拿1 B
。在这种情况下,A
的分数会增加1,而B
's的分数减少2。此决定允许在每个有序球员对之间进行。
这是每个玩家做出的唯一决定-彼此“背叛”还是不相互“捉襟见肘”,这与叛逃和合作分别相同。两名球员之间的有效收益矩阵P1
和P2
如下所示:
P1/P2 P1 Take1 P1 Don't
P2 Take1 -1/-1 -2/+1
P2 Don't +1/-2 0/ 0
比赛程序
游戏将包括P * 25
回合,即P
参与比赛的人数。所有玩家的得分都以0
。每个回合将包括以下步骤:
在回合开始时,将从标准输入中以以下格式为每个程序提供上回合的历史记录:
含有3个数字一行
P
,D
和N
。P
是游戏中的玩家总数。每个玩家随机分配从一个ID号1
,以P
在游戏的开始。D
是当前玩家的ID。N
是已经打过的回合数。
N
线,每条线代表一轮的结果。在的行k
上N
,将有一定数量n_k
的有序对(a, b)
,用空格分隔,表示该回合中ID为a
“ 1” 的玩家与ID为“ 1”的玩家b
。R
从0
到18446744073709551615
(2 64-1)的均匀随机数,用作伪随机种子。这些数字将从预先生成的文件中读取,该文件将在锦标赛结束时发布,以便人们可以自己验证结果。如果您的程序在上一轮产生了这样的输出,则多一行代表要读入您的程序的某种状态。在游戏开始时,此行将始终为空。评分代码或其他程序均不会修改此行。
然后,每个程序将使用其策略来产生以下标准输出:
K
数字列表,这是本轮将“取1”的程序的ID。空输出意味着它什么也不做。可选地,一条代表某种状态形式的额外行可以传递到以后的回合。此确切行将在下一轮反馈给程序。
以下是3
在4人游戏中ID 玩家游戏开始时的示例输入:
4 3 0
4696634734863777023
以下是同一游戏的示例输入,已经进行了几轮:
4 3 2
(1, 2) (1, 3) (1, 4) (4, 2)
(1, 3) (2, 1) (2, 4) (3, 1) (4, 1)
4675881156406346380
除了D
每个程序唯一的ID号之外,每个程序都将获得完全相同的输入回合。
下面是一个示例输出,其中玩家3
从其他所有人那里得到1:
1 2 4
在所有要求的回合结束时,最终得分最高的玩家将成为获胜者。
时间线
该比赛的编码将持续7天。提交截止日期为2014-05-09 00:00 UTC
。
请勿在此日期之前发布实际程序,而是发布程序源代码的SHA256哈希作为承诺。您可以在截止日期之前的任何时间更改此哈希,但是截止日期之后发布的承诺将不被接受作为判断。(请为您的哈希使用base 64表示法,因为我的验证程序会使用base 64表示法,这是一种更紧凑的表示法。)
截止日期结束后,您将有1天(直到2014-05-10 00:00 UTC
)发布程序的实际源代码以进行提交。如果您发布的源代码的SHA256哈希与您在截止日期之前发布的任何哈希都不匹配,则您的代码将不被接受。
之后,我会将所有提交的内容下载到我自己的计算机上,并运行该大逃杀中的所有锦标赛条目,希望在此之后的2天内发布结果 2014-05-12 00:00 UTC
。
我将接受得分最高的答案,如果最终得分大于,则奖励该答案+100 0
。
比赛结束后,我将发布用于运行比赛的随机种子文件,人们可能会开始发布其他解决方案,以超越比赛中使用的解决方案。但是,他们将不计入接受或悬赏。
主机
我将在计算机上的虚拟机上运行这些解决方案。该虚拟机将运行带有2 GB RAM的Ubuntu Linux 14.04。我的基本计算机具有运行在3.40 GHz的Intel i7-2600K处理器。
要求
您的程序必须使用一种将用于编译程序的编译器或解释器存在的语言编写,并且该语言应可用于最新版本的Ubuntu Linux,以便我可以运行所有提交并在虚拟机中对其进行判断。
您的程序最多2.000 seconds
只能运行一次。如果您的程序用完了时间或产生了错误,则该轮的输出将被视为空。
您的程序必须是确定性的;也就是说,它必须始终为相同的输入返回相同的输出。允许使用伪随机解;但是,它们的随机性必须取决于作为输入提供给它的随机种子,而不是其他任何东西。种子文件是使用Python的生成的os.urandom
。它总共包含500行(如有必要,将生成更多行),其SHA256哈希为K+ics+sFq82lgiLanEnL/PABQKnn7rDAGmO48oiYxZk=
。比赛结束后,它将被上传到这里。
植物
首先,将有四个“植物”,代表最初的幼稚策略。这些将与您提交的内容一起在锦标赛中播放。但是,如果其中一个获胜的可能性很小,则除植物以外的玩家获得的最高分将被视为获胜者。
要计算每个工厂文件的哈希值,请使用制表符替换每四个空格组,因为此处的格式化程序似乎不喜欢制表符。
懒惰者 -从不做任何事情。
n1bnYdeb/bNDBKASWGywTRa0Ne9hMAkal3AuVZJgovI=
pass
贪婪 –总是从其他人身上夺取 1。
+k0L8NF27b8+Xf50quRaZFFuflZhZuTCQOR5t5b0nMI=
import sys
line1 = sys.stdin.readline()
n = [int(i) for i in line1.split()]
for i in range(n[0]):
if i+1 != n[1]:
print i+1,
print
愤怒 –在第一轮中从其他所有人那里拿走1,在随后的上一轮中从所有人那里拿走1的所有人都拿走1。
Ya2dIv8TCh0zWzRfzUIdFKWj1DF9GXWhbq/uN7+CzrY=
import sys
import re
line1 = [int(i) for i in sys.stdin.readline().split()]
players = line1[0]
pid = line1[1]
rounds = line1[2]
lines = []
if rounds == 0:
for i in range(players):
if i+1 != pid:
print i+1,
print
else:
for i in range(rounds):
lines.append(sys.stdin.readline())
lastline = lines[-1]
takes = re.findall(r'\([0-9]+, [0-9]+\)', lastline)
for take in takes:
sides = [int(i) for i in re.findall(r'[0-9]+', take)]
if sides[1] == pid:
print sides[0],
print
嫉妒者 -从目前得分最高的50%的玩家中减去 1(不包括自身),向下舍入。
YhLgqrz1Cm2pEcFlsiIL4b4MX9QiTxuIOBJF+wvukNk=
import sys
import re
line1 = [int(i) for i in sys.stdin.readline().split()]
players = line1[0]
pid = line1[1]
rounds = line1[2]
lines = []
scores = [0] * players
if rounds == 0:
for i in range(players):
if i+1 != pid:
print i+1,
print
else:
for i in range(rounds):
takes = re.findall(r'\([0-9]+, [0-9]+\)', sys.stdin.readline())
for take in takes:
sides = [int(i) for i in re.findall(r'[0-9]+', take)]
scores[sides[0] - 1] += 1
scores[sides[1] - 1] -= 2
score_pairs = [(i+1, scores[i]) for i in range(players)]
score_pairs.sort(key=lambda x:(x[1], x[0]))
score_pairs.reverse()
taken = 0
j = 0
while taken < (players) / 2:
if score_pairs[j][0] != pid:
print score_pairs[j][0],
taken += 1
j += 1
在这四场比赛中的100场比赛中,他们获得以下得分:
Lazy: -204
Greedy: -100
Wrathful: -199
Envious: -199
评审程序
我已经发布了我将在Github使用的判断程序。下载并进行测试。(如果发现一个或两个bug,也许可以修复。:P)
目前,除了Python之外,它没有其他编译选项。稍后我将包括这些内容-如果人们可以提供其他语言的编译或解释脚本,我将非常有义务。
阶段2:提交源代码
我已经tournament
为比赛将新分支发布到Github存储库,其中包含pd_rand文件和其他工厂条目。您可以在此处发布源代码,也可以作为拉取请求将其提交到该分支。
参赛者的顺序如下:
'begrudger'
'regular'
'patient'
'lazy'
'backstab'
'bully'
'lunatic'
'envious'
'titfortat'
'greedy'
'wrathful'
'judge'
'onepercent'
最终成绩
我的测试程序的输出:
Final scores:
begrudger -2862
regular -204
patient -994
lazy -2886
backstab -1311
bully -1393
lunatic -1539
envious -2448
titfortat -985
greedy -724
wrathful -1478
judge -365
onepercent -1921
排名:
1. regular -204
2. judge -365
3. greedy -724
4. titfortat -985
5. patient -994
6. backstab -1311
7. bully -1393
8. wrathful -1478
9. lunatic -1539
10. onepercent -1921
11. envious -2448
12. begrudger -2862
13. lazy -2886
因此,事实证明获胜者的确是玩家-这是-204分的常规!
不幸的是,它的分数不是很高,但是我们很难在模拟“囚徒困境”的模拟中,每个人都在努力取胜。
一些令人惊讶的结果(至少我认为是令人惊讶的):
贪婪者在Tat上的得分高于Tit,实际上,它总体上比大多数得分手都高。
法官本来是一种“道德执法者”角色(基本上是从任何人那里以高于平均水平的次数从任何人那里获得1分的人获得了1分)最终获得了相当高的分数,而在模拟测试中,它实际上是得到相当低的分数。
和其他(我认为)并不奇怪的是:
该患者比“愤怒”得分高484分。第一次合作真的很值得。
百分之一的人倒下时很快就几乎没人踢。似乎只有1%的人会那样做,因为他们在游戏中拥有更多的玩家。
无论如何,既然锦标赛结束了,您可以随意发布任意数量的额外玩家,并使用评判程序与他们一起进行测试。