-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPrisoners_Dilemma_Tournament_v3.py
276 lines (233 loc) · 8.88 KB
/
Prisoners_Dilemma_Tournament_v3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# -*- coding: utf-8 -*-
"""
Prisoner's Dilemma Tournament
This is a recreation of the Axelrod's (1984) tournament. I prepared this code
for a PhD class at ESSEC. It helps students to understand the tournament and
gain intuition for the game and why tit-for-tat performs so well.
I highly recommend reading the Robert Axelrod's excellent book
"The Evolution of Cooperation". It is an excellent piece. Such a simple
idea and yet it explains so much about the world - particularly the social
sphere. If you were looking for mathematical foundations of morality, you
will find them in this book.
@ Maciej Workiewicz (2019)
https://github.com/Mac13kW
"""
import numpy as np
import matplotlib.pyplot as plt
# =============================================================================
# The Payoff Function:
# {cooperation [3, 3]; sucker's profit [5, 0]; and last [1, 1]}
#
# cooperate defect
# +----------+----------+
# | 3 | 5 |
# c | 3 | 0 |
# +----------+----------+
# | 0 | 1 |
# d | 5 | 1 |
# +----------+----------+
#
# Define players' strategies. You can add more if you which to. I only added
# the key strategies and none of the very complex ones.
# 0 tit_for_tat;
# 1-punisher;
# 2 random 20%;
# 3 random 50%;
# 4 always defect
# 5 always cooperate;
# 6 tit for two tats;
# 7 tester;
# 8 tit for 2 tats;
# 9 tit if 3 tats
# =============================================================================
#Here is where you input the strategies that the players will be following
player1 = 1
player2 = 2
iterations = 1000 # number of iterations we will run the tournament for
rounds = 200 # number of rounds for each game. Here we don't make it
# probabilistic, but may need to if we use a code that knows
# the number of time periods. We simply assume that the
# people that submitted strategies did not know the number of
# periods.
# DEFINE PLAYERS
def tit_for_tat(actions_of_other): #0
# the tit for tat strategy
if len(actions_of_other)>0:
last_action = actions_of_other[-1]
else:
last_action = 0 # start with cooperation
if last_action==0: # if partner cooperated...
my_action = 0 # I cooperate as well
elif last_action==1: # if partner defected...
my_action=1 # I defect as well
return(my_action)
def punisher(actions_of_other): #1
# the grim trigger strategy. Starts nice, buto once you cross this player,
# he defects forever
if 1 in actions_of_other:
my_action = 1 # defect
else:
my_action = 0 # cooperate
return(my_action)
def random_defector20(): #2
# defects with 20% probability
if np.random.rand() < 0.2:
my_action = 1 # defect 20% of the time
else:
my_action = 0
return(my_action)
def random_defector50(): # 3
# defects half the time at random
if np.random.rand() < 0.5:
my_action = 1 # defect 20% of the time
else:
my_action = 0
return(my_action)
def always_defect(): # 4
# as name suggests
my_action = 1 # defect 100% of the time
return(my_action)
def always_cooperate(): # 5
# most naive of strategies
my_action = 0 # defect 100% of the time
return(my_action)
def tit_for_2tats(actions_of_other): #6
# the tit for two tats player
if len(actions_of_other)<2:
my_action = 0
elif len(actions_of_other)>=2:
if actions_of_other[-1] == 1 and actions_of_other[-2] == 1:
my_action = 1
else:
my_action = 0
return(my_action)
def tester(actions_of_other): #7
# test who is it playing against
if len(actions_of_other)==0:
my_action = 1 # let's defect and see who we play against
elif len(actions_of_other)==1 or len(actions_of_other)==2:
my_action = 0 # then let's see if the other agent retailated
elif len(actions_of_other)>2:
if actions_of_other[1]==1: # if I got punished, I play tit for tat
if actions_of_other[-1]==0: # if partner cooperated...
my_action = 0 # I cooperate as well
elif actions_of_other[-1]==1: # if partner defected...
my_action=1 # I defect as well
elif actions_of_other[1]==0: # if it didn't retailate
if (len(actions_of_other)%2) == 0: # I defect each second round
my_action = 1
else:
my_action = 0
return(my_action)
def tit_if_2tats(actions_of_other): #8
# Defect if partner defected at least once within last two rounds
if len(actions_of_other)<2:
my_action = 0 # cooperate
elif len(actions_of_other)>=2:
if actions_of_other[-1] == 1 or actions_of_other[-2] == 1:
my_action = 1
else:
my_action = 0
return(my_action)
def tit_for_3tats(actions_of_other): #9
# defect if three defections in a row
if len(actions_of_other)<3:
my_action = 0
elif len(actions_of_other)>=3:
if actions_of_other[-1] == 1 and actions_of_other[-2] and actions_of_other[-3]== 1:
my_action = 1
else:
my_action = 0
return(my_action)
# START THE GAME ===========================================================
Profits1 = np.zeros((iterations, rounds))
Profits2 = np.zeros((iterations, rounds))
Actions = np.zeros((iterations, rounds)) # to record history
# 0 is both cooperate; 1 first defects; 2 second defects; 3 both defect
for i in np.arange(iterations):
actions1 = []
actions2 = []
for t in np.arange(rounds): # as per the original tournament
if player1 ==0:
action1 = tit_for_tat(actions2)
elif player1==1:
action1 = punisher(actions2)
elif player1==2:
action1 = random_defector20()
elif player1==3:
action1 = random_defector50()
elif player1==4:
action1 = always_defect()
elif player1==5:
action1 = always_cooperate()
elif player1==6:
action1 = tit_for_2tats(actions2)
elif player1==7:
action1 = tester(actions2)
elif player1==8:
action1 = tit_for_3tats(actions2)
elif player1==9:
action1 = tit_if_2tats(actions2)
else:
print('Input out of range. Try again')
if player2 ==0:
action2 = tit_for_tat(actions1)
elif player2==1:
action2 = punisher(actions1)
elif player2==2:
action2 = random_defector20()
elif player2==3:
action2 = random_defector50()
elif player2==4:
action2 = always_defect()
elif player2==5:
action2 = always_cooperate()
elif player2==6:
action2 = tit_for_2tats(actions1)
elif player2==7:
action2 = tester(actions1)
elif player2==8:
action2 = tit_for_3tats(actions1)
elif player2==9:
action2 = tit_if_2tats(actions1)
else:
print('Input out of range. Try again')
actions1.append(action1)
actions2.append(action2)
# payoff
if action1==0:
if action2==0: # both cooperate
profit1 = 3
profit2 = 3
Actions[i, t] = 0
else: # second player defects
profit1 = 0
profit2 = 5
Actions[i, t] = 2
else: # first player defects
if action2==0:
profit1 = 5
profit2 = 0
Actions[i, t] = 1
else: # both defect
profit1 = 1
profit2 = 1
Actions[i, t] = 3
Profits1[i, t] = profit1
Profits2[i, t] = profit2
profits1 = np.average(np.sum(Profits1, axis=1))
profits2 = np.average(np.sum(Profits2, axis=1))
print('profit of player 1 = ', str(profits1), '\n', 'profit of player 2 = ', str(profits2))
# PLOT THE FIGURE =============================================================
# Here we want to see the first 25 rounds of the first game to see if the
# code is working as it should and how the game is played.
plt.figure(1, facecolor='white', figsize=(8, 6), dpi=150)
plt.plot(Profits1[0, :25], color='blue', linewidth=2, label='player 1')
plt.plot(Profits2[0, :25], color='red', linewidth=2, label='player 2')
plt.legend(loc=4,prop={'size':10})
plt.title('Results of the tournament 1 - the first 25 rounds', size=12)
plt.xlabel('time periods', size=12)
plt.xticks(np.arange(0, 25, step=1), fontsize=8)
plt.ylabel('payoff', size=12)
plt.show()
# END OF LINE