-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathStratTourn Tutorial.html
1204 lines (888 loc) · 98.4 KB
/
StratTourn Tutorial.html
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Analyzing Cooperation with Game Theory and Simulation</title>
<style type="text/css">
body, td {
font-family: sans-serif;
background-color: white;
font-size: 12px;
margin: 8px;
}
tt, code, pre {
font-family: 'DejaVu Sans Mono', 'Droid Sans Mono', 'Lucida Console', Consolas, Monaco, monospace;
}
h1 {
font-size:2.2em;
}
h2 {
font-size:1.8em;
}
h3 {
font-size:1.4em;
}
h4 {
font-size:1.0em;
}
h5 {
font-size:0.9em;
}
h6 {
font-size:0.8em;
}
a:visited {
color: rgb(50%, 0%, 50%);
}
pre {
margin-top: 0;
max-width: 95%;
border: 1px solid #ccc;
white-space: pre-wrap;
}
pre code {
display: block; padding: 0.5em;
}
code.r, code.cpp {
background-color: #F8F8F8;
}
table, td, th {
border: none;
}
blockquote {
color:#666666;
margin:0;
padding-left: 1em;
border-left: 0.5em #EEE solid;
}
hr {
height: 0px;
border-bottom: none;
border-top-width: thin;
border-top-style: dotted;
border-top-color: #999999;
}
@media print {
* {
background: transparent !important;
color: black !important;
filter:none !important;
-ms-filter: none !important;
}
body {
font-size:12pt;
max-width:100%;
}
a, a:visited {
text-decoration: underline;
}
hr {
visibility: hidden;
page-break-before: always;
}
pre, blockquote {
padding-right: 1em;
page-break-inside: avoid;
}
tr, img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
@page :left {
margin: 15mm 20mm 15mm 10mm;
}
@page :right {
margin: 15mm 10mm 15mm 20mm;
}
p, h2, h3 {
orphans: 3; widows: 3;
}
h2, h3 {
page-break-after: avoid;
}
}
</style>
<!-- Styles for R syntax highlighter -->
<style type="text/css">
pre .operator,
pre .paren {
color: rgb(104, 118, 135)
}
pre .literal {
color: rgb(88, 72, 246)
}
pre .number {
color: rgb(0, 0, 205);
}
pre .comment {
color: rgb(76, 136, 107);
}
pre .keyword {
color: rgb(0, 0, 255);
}
pre .identifier {
color: rgb(0, 0, 0);
}
pre .string {
color: rgb(3, 106, 7);
}
</style>
<!-- R syntax highlighter -->
<script type="text/javascript">
var hljs=new function(){function m(p){return p.replace(/&/gm,"&").replace(/</gm,"<")}function f(r,q,p){return RegExp(q,"m"+(r.cI?"i":"")+(p?"g":""))}function b(r){for(var p=0;p<r.childNodes.length;p++){var q=r.childNodes[p];if(q.nodeName=="CODE"){return q}if(!(q.nodeType==3&&q.nodeValue.match(/\s+/))){break}}}function h(t,s){var p="";for(var r=0;r<t.childNodes.length;r++){if(t.childNodes[r].nodeType==3){var q=t.childNodes[r].nodeValue;if(s){q=q.replace(/\n/g,"")}p+=q}else{if(t.childNodes[r].nodeName=="BR"){p+="\n"}else{p+=h(t.childNodes[r])}}}if(/MSIE [678]/.test(navigator.userAgent)){p=p.replace(/\r/g,"\n")}return p}function a(s){var r=s.className.split(/\s+/);r=r.concat(s.parentNode.className.split(/\s+/));for(var q=0;q<r.length;q++){var p=r[q].replace(/^language-/,"");if(e[p]){return p}}}function c(q){var p=[];(function(s,t){for(var r=0;r<s.childNodes.length;r++){if(s.childNodes[r].nodeType==3){t+=s.childNodes[r].nodeValue.length}else{if(s.childNodes[r].nodeName=="BR"){t+=1}else{if(s.childNodes[r].nodeType==1){p.push({event:"start",offset:t,node:s.childNodes[r]});t=arguments.callee(s.childNodes[r],t);p.push({event:"stop",offset:t,node:s.childNodes[r]})}}}}return t})(q,0);return p}function k(y,w,x){var q=0;var z="";var s=[];function u(){if(y.length&&w.length){if(y[0].offset!=w[0].offset){return(y[0].offset<w[0].offset)?y:w}else{return w[0].event=="start"?y:w}}else{return y.length?y:w}}function t(D){var A="<"+D.nodeName.toLowerCase();for(var B=0;B<D.attributes.length;B++){var C=D.attributes[B];A+=" "+C.nodeName.toLowerCase();if(C.value!==undefined&&C.value!==false&&C.value!==null){A+='="'+m(C.value)+'"'}}return A+">"}while(y.length||w.length){var v=u().splice(0,1)[0];z+=m(x.substr(q,v.offset-q));q=v.offset;if(v.event=="start"){z+=t(v.node);s.push(v.node)}else{if(v.event=="stop"){var p,r=s.length;do{r--;p=s[r];z+=("</"+p.nodeName.toLowerCase()+">")}while(p!=v.node);s.splice(r,1);while(r<s.length){z+=t(s[r]);r++}}}}return z+m(x.substr(q))}function j(){function q(x,y,v){if(x.compiled){return}var u;var s=[];if(x.k){x.lR=f(y,x.l||hljs.IR,true);for(var w in x.k){if(!x.k.hasOwnProperty(w)){continue}if(x.k[w] instanceof Object){u=x.k[w]}else{u=x.k;w="keyword"}for(var r in u){if(!u.hasOwnProperty(r)){continue}x.k[r]=[w,u[r]];s.push(r)}}}if(!v){if(x.bWK){x.b="\\b("+s.join("|")+")\\s"}x.bR=f(y,x.b?x.b:"\\B|\\b");if(!x.e&&!x.eW){x.e="\\B|\\b"}if(x.e){x.eR=f(y,x.e)}}if(x.i){x.iR=f(y,x.i)}if(x.r===undefined){x.r=1}if(!x.c){x.c=[]}x.compiled=true;for(var t=0;t<x.c.length;t++){if(x.c[t]=="self"){x.c[t]=x}q(x.c[t],y,false)}if(x.starts){q(x.starts,y,false)}}for(var p in e){if(!e.hasOwnProperty(p)){continue}q(e[p].dM,e[p],true)}}function d(B,C){if(!j.called){j();j.called=true}function q(r,M){for(var L=0;L<M.c.length;L++){if((M.c[L].bR.exec(r)||[null])[0]==r){return M.c[L]}}}function v(L,r){if(D[L].e&&D[L].eR.test(r)){return 1}if(D[L].eW){var M=v(L-1,r);return M?M+1:0}return 0}function w(r,L){return L.i&&L.iR.test(r)}function K(N,O){var M=[];for(var L=0;L<N.c.length;L++){M.push(N.c[L].b)}var r=D.length-1;do{if(D[r].e){M.push(D[r].e)}r--}while(D[r+1].eW);if(N.i){M.push(N.i)}return f(O,M.join("|"),true)}function p(M,L){var N=D[D.length-1];if(!N.t){N.t=K(N,E)}N.t.lastIndex=L;var r=N.t.exec(M);return r?[M.substr(L,r.index-L),r[0],false]:[M.substr(L),"",true]}function z(N,r){var L=E.cI?r[0].toLowerCase():r[0];var M=N.k[L];if(M&&M instanceof Array){return M}return false}function F(L,P){L=m(L);if(!P.k){return L}var r="";var O=0;P.lR.lastIndex=0;var M=P.lR.exec(L);while(M){r+=L.substr(O,M.index-O);var N=z(P,M);if(N){x+=N[1];r+='<span class="'+N[0]+'">'+M[0]+"</span>"}else{r+=M[0]}O=P.lR.lastIndex;M=P.lR.exec(L)}return r+L.substr(O,L.length-O)}function J(L,M){if(M.sL&&e[M.sL]){var r=d(M.sL,L);x+=r.keyword_count;return r.value}else{return F(L,M)}}function I(M,r){var L=M.cN?'<span class="'+M.cN+'">':"";if(M.rB){y+=L;M.buffer=""}else{if(M.eB){y+=m(r)+L;M.buffer=""}else{y+=L;M.buffer=r}}D.push(M);A+=M.r}function G(N,M,Q){var R=D[D.length-1];if(Q){y+=J(R.buffer+N,R);return false}var P=q(M,R);if(P){y+=J(R.buffer+N,R);I(P,M);return P.rB}var L=v(D.length-1,M);if(L){var O=R.cN?"</span>":"";if(R.rE){y+=J(R.buffer+N,R)+O}else{if(R.eE){y+=J(R.buffer+N,R)+O+m(M)}else{y+=J(R.buffer+N+M,R)+O}}while(L>1){O=D[D.length-2].cN?"</span>":"";y+=O;L--;D.length--}var r=D[D.length-1];D.length--;D[D.length-1].buffer="";if(r.starts){I(r.starts,"")}return R.rE}if(w(M,R)){throw"Illegal"}}var E=e[B];var D=[E.dM];var A=0;var x=0;var y="";try{var s,u=0;E.dM.buffer="";do{s=p(C,u);var t=G(s[0],s[1],s[2]);u+=s[0].length;if(!t){u+=s[1].length}}while(!s[2]);if(D.length>1){throw"Illegal"}return{r:A,keyword_count:x,value:y}}catch(H){if(H=="Illegal"){return{r:0,keyword_count:0,value:m(C)}}else{throw H}}}function g(t){var p={keyword_count:0,r:0,value:m(t)};var r=p;for(var q in e){if(!e.hasOwnProperty(q)){continue}var s=d(q,t);s.language=q;if(s.keyword_count+s.r>r.keyword_count+r.r){r=s}if(s.keyword_count+s.r>p.keyword_count+p.r){r=p;p=s}}if(r.language){p.second_best=r}return p}function i(r,q,p){if(q){r=r.replace(/^((<[^>]+>|\t)+)/gm,function(t,w,v,u){return w.replace(/\t/g,q)})}if(p){r=r.replace(/\n/g,"<br>")}return r}function n(t,w,r){var x=h(t,r);var v=a(t);var y,s;if(v){y=d(v,x)}else{return}var q=c(t);if(q.length){s=document.createElement("pre");s.innerHTML=y.value;y.value=k(q,c(s),x)}y.value=i(y.value,w,r);var u=t.className;if(!u.match("(\\s|^)(language-)?"+v+"(\\s|$)")){u=u?(u+" "+v):v}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName=="CODE"&&t.parentNode.tagName=="PRE"){s=t.parentNode;var p=document.createElement("div");p.innerHTML="<pre><code>"+y.value+"</code></pre>";t=p.firstChild.firstChild;p.firstChild.cN=s.cN;s.parentNode.replaceChild(p.firstChild,s)}else{t.innerHTML=y.value}t.className=u;t.result={language:v,kw:y.keyword_count,re:y.r};if(y.second_best){t.second_best={language:y.second_best.language,kw:y.second_best.keyword_count,re:y.second_best.r}}}function o(){if(o.called){return}o.called=true;var r=document.getElementsByTagName("pre");for(var p=0;p<r.length;p++){var q=b(r[p]);if(q){n(q,hljs.tabReplace)}}}function l(){if(window.addEventListener){window.addEventListener("DOMContentLoaded",o,false);window.addEventListener("load",o,false)}else{if(window.attachEvent){window.attachEvent("onload",o)}else{window.onload=o}}}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=n;this.initHighlighting=o;this.initHighlightingOnLoad=l;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="\\b(0[xX][a-fA-F0-9]+|(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.ER="(?![\\s\\S])";this.BE={b:"\\\\.",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.inherit=function(r,s){var p={};for(var q in r){p[q]=r[q]}if(s){for(var q in s){p[q]=s[q]}}return p}}();hljs.LANGUAGES.cpp=function(){var a={keyword:{"false":1,"int":1,"float":1,"while":1,"private":1,"char":1,"catch":1,"export":1,virtual:1,operator:2,sizeof:2,dynamic_cast:2,typedef:2,const_cast:2,"const":1,struct:1,"for":1,static_cast:2,union:1,namespace:1,unsigned:1,"long":1,"throw":1,"volatile":2,"static":1,"protected":1,bool:1,template:1,mutable:1,"if":1,"public":1,friend:2,"do":1,"return":1,"goto":1,auto:1,"void":2,"enum":1,"else":1,"break":1,"new":1,extern:1,using:1,"true":1,"class":1,asm:1,"case":1,typeid:1,"short":1,reinterpret_cast:2,"default":1,"double":1,register:1,explicit:1,signed:1,typename:1,"try":1,"this":1,"switch":1,"continue":1,wchar_t:1,inline:1,"delete":1,alignof:1,char16_t:1,char32_t:1,constexpr:1,decltype:1,noexcept:1,nullptr:1,static_assert:1,thread_local:1,restrict:1,_Bool:1,complex:1},built_in:{std:1,string:1,cin:1,cout:1,cerr:1,clog:1,stringstream:1,istringstream:1,ostringstream:1,auto_ptr:1,deque:1,list:1,queue:1,stack:1,vector:1,map:1,set:1,bitset:1,multiset:1,multimap:1,unordered_set:1,unordered_map:1,unordered_multiset:1,unordered_multimap:1,array:1,shared_ptr:1}};return{dM:{k:a,i:"</",c:[hljs.CLCM,hljs.CBLCLM,hljs.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},hljs.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:a,r:10,c:["self"]}]}}}();hljs.LANGUAGES.r={dM:{c:[hljs.HCM,{cN:"number",b:"\\b0[xX][0-9a-fA-F]+[Li]?\\b",e:hljs.IMMEDIATE_RE,r:0},{cN:"number",b:"\\b\\d+(?:[eE][+\\-]?\\d*)?L\\b",e:hljs.IMMEDIATE_RE,r:0},{cN:"number",b:"\\b\\d+\\.(?!\\d)(?:i\\b)?",e:hljs.IMMEDIATE_RE,r:1},{cN:"number",b:"\\b\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",e:hljs.IMMEDIATE_RE,r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",e:hljs.IMMEDIATE_RE,r:1},{cN:"keyword",b:"(?:tryCatch|library|setGeneric|setGroupGeneric)\\b",e:hljs.IMMEDIATE_RE,r:10},{cN:"keyword",b:"\\.\\.\\.",e:hljs.IMMEDIATE_RE,r:10},{cN:"keyword",b:"\\.\\.\\d+(?![\\w.])",e:hljs.IMMEDIATE_RE,r:10},{cN:"keyword",b:"\\b(?:function)",e:hljs.IMMEDIATE_RE,r:2},{cN:"keyword",b:"(?:if|in|break|next|repeat|else|for|return|switch|while|try|stop|warning|require|attach|detach|source|setMethod|setClass)\\b",e:hljs.IMMEDIATE_RE,r:1},{cN:"literal",b:"(?:NA|NA_integer_|NA_real_|NA_character_|NA_complex_)\\b",e:hljs.IMMEDIATE_RE,r:10},{cN:"literal",b:"(?:NULL|TRUE|FALSE|T|F|Inf|NaN)\\b",e:hljs.IMMEDIATE_RE,r:1},{cN:"identifier",b:"[a-zA-Z.][a-zA-Z0-9._]*\\b",e:hljs.IMMEDIATE_RE,r:0},{cN:"operator",b:"<\\-(?!\\s*\\d)",e:hljs.IMMEDIATE_RE,r:2},{cN:"operator",b:"\\->|<\\-",e:hljs.IMMEDIATE_RE,r:1},{cN:"operator",b:"%%|~",e:hljs.IMMEDIATE_RE},{cN:"operator",b:">=|<=|==|!=|\\|\\||&&|=|\\+|\\-|\\*|/|\\^|>|<|!|&|\\||\\$|:",e:hljs.IMMEDIATE_RE,r:0},{cN:"operator",b:"%",e:"%",i:"\\n",r:1},{cN:"identifier",b:"`",e:"`",r:0},{cN:"string",b:'"',e:'"',c:[hljs.BE],r:0},{cN:"string",b:"'",e:"'",c:[hljs.BE],r:0},{cN:"paren",b:"[[({\\])}]",e:hljs.IMMEDIATE_RE,r:0}]}};
hljs.initHighlightingOnLoad();
</script>
<!-- MathJax scripts -->
<script type="text/javascript" src="https://c328740.ssl.cf1.rackcdn.com/mathjax/2.0-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</head>
<body>
<h1>Analyzing Cooperation with Game Theory and Simulation</h1>
<h1>Tutorial for the R package StratTourn</h1>
<p><strong>Date: 2013-10-21</strong></p>
<p><strong>Author: Sebastian Kranz (<a href="mailto:sebastian.kranz@uni-ulm.de">sebastian.kranz@uni-ulm.de</a>)</strong></p>
<p><strong>with help by Martin Kies (<a href="mailto:martin.kies@uni-ulm.de">martin.kies@uni-ulm.de</a>)</strong></p>
<h2>1. Installing neccessary software</h2>
<h3>1.1 Installing R and RStudio</h3>
<p>First you need to install R, which is a very popular and powerful open source statistical programming language. You can download R for Windows, Max or Linux here:</p>
<p><a href="http://cran.r-project.org/">http://cran.r-project.org/</a></p>
<p>Note: If you have already installed R, you may want to update to the newest version by installing it again. </p>
<p>I recommend to additionally install RStudio, which is a great open source IDE for R:</p>
<p><a href="http://rstudio.org/">http://rstudio.org/</a></p>
<h3>1.2 Installing necessary R packages</h3>
<p>You need to install several R packages from the internet. To do so, simply run in the R console the following code (you can use copy & paste):</p>
<pre><code class="r">install.packages("devtools")
install.packages("data.table")
install.packages("ggplot2")
install.packages("reshape2")
install.packages("lattice")
library(devtools)
install_github(repo = "restorepoint", username = "skranz")
install_github(repo = "sktools", username = "skranz")
install_github(repo = "StratTourn", username = "skranz")
</code></pre>
<h2>2. Brief Background: The Prisoners' Dilemma Game</h2>
<p>In the 'Evolution of Cooperation' Robert Axelrod describes his famous computer tournament that he used to investigate effective cooperation strategies in repeated social dilemma situations. His tournament was based on a repeated <em>prisoner's dilemma game</em>, which I will also use as an example in this tutorial.</p>
<h3>2.1 The one-shot Prisoner's Dilemma</h3>
<p>A one-shot prisoner's dilemma (short: PD) is played only once. We can describe a PD by the following <em>payoff matrix</em>:</p>
<p><center><table border="1"><tr>
<td align='center'>Pl 1. / Pl. 2</td>
<th align='center'>C</th>
<th align='center'>D</th>
</tr><tr>
<th align='center'>C</th>
<td align='center'> 1, 1</td>
<td align='center'> -1, 2</td>
</tr><tr>
<th align='center'>D</th>
<td align='center'> 2,-1</td>
<td align='center'> 0, 0</td>
</tr></table></center></p>
<p>Each player can either cooperate <em>C</em> or defect <em>D</em>, which means not to cooperate. The row shows player 1's action and the column player 2's. The cells show the <em>payoffs</em> of player 1 and 2 for each <em>action profile</em>. For example, when player 1 cooperates C and player 2 defects D, i.e. the action profile (C,D) is played, then player 1's payoff is -1 and player 2's payoff is 2.</p>
<p>The highest average payoff (1,1) could be achieved if both players cooperate (C,C). Yet, assume that both players decide independently which action they choose, i.e. player 1's action does not influence player 2's action and vice versa. Then no matter which action the other player chooses, a player always maximizes its own payoff by choosing D. In game theoretic terms, choosing D is <em>strictly dominant</em> in a PD game that is played only once. (Consequently, the only <em>Nash equilibrium</em> of the one-shot PD is (D,D)). </p>
<h3>2.2 The repeated Prisoner's Dilemma</h3>
<p>In this seminar, we will mostly consider games that are repeated for an uncertain number of periods. Let \( \delta \in [0,1) \) be a continuation probability (we will also often refer to \( \delta \) as <em>discount factor</em>). After each period a random number is drawn and the repeated game ends with probability \( 1-\delta \), i.e. it continues with probability \( \delta \). In the basic version (formally called a PD game with <em>perfect monitoring</em>) all players exactly observe the actions that the other players have played in the previous periods. It is then no longer strictly dominant to always play D. For example, player 2's action in period 2 may depend on what player 1 did in period 1: she may only play C if player 1 has played C in period 1 and otherwise play D. A player's optimal strategy now depends on how the other player reacts to her action and cooperation may become rational even for pure egoists.</p>
<p>It turns out that if the continuation probability \( \delta \) is large enough, such repeated games often have a very large number of <em>Nash equilibria</em>. This means we can have many possible profiles of strategies that are stable in the sense that it is optimal for each player to follow her strategy given the strategies of the other players. In some Nash equilibria players will cooperate a lot, in others very little or not at all.</p>
<h3>2.3 What will we do in the seminar?</h3>
<p>We search for stable, socially efficient cooperative strategy profiles in several strategic interactions and study which factors make cooperation harder and how one best adapts cooperation strategies to such factors. I will typically interpret such strategy profiles as stable <em>social norms</em> that allow a high degree of cooperation in a society.</p>
<p>We do this search by programming strategies in R and let them play against each other in a tournament (more on that below). During the seminar, we will discuss a bit informally in how far the winning strategies of our tournament are related to game theoretic equilibrium concepts, like the <em>Nash equilibrium</em>. For those who already know more about Nash equilibria, let us just state that the socially most efficient Nash equilibria probably would have a very good chance to be winners in our tournaments, but often it is very hard to find these equilibria.</p>
<h2>3. Getting Started: Developing strategies for the repeated Prisoner's Dilemma in R</h2>
<p>Preparations:</p>
<ol>
<li>Make sure you installed all software and packages as described in Section 1</li>
<li>Download the file <em>pdgame.r</em>, save it in some working directory, and open it with RStudio. </li>
<li>Press the “Source” button above on the right of the editor window to load all functions of this file.</li>
<li>Consider the code inside the function examples.pd, select the following lines and press the “Run” button (or press Ctrl-Enter):</li>
</ol>
<pre><code class="r"># Load package
library(StratTourn)
# Generate a PD game object
game = make.pd.game()
# Pick a pair of strategies (strategies are defined below)
strat = nlist(tit.for.tat, random.action)
# Let the strategies play against each other one repeated PD
run.rep.game(delta = 0.9, game = game, strat = strat)
</code></pre>
<pre><code>## $hist
## t obs_a1 obs_a2 a1 a2 pi1 pi2
## 1 1 <NA> <NA> C D -1 2
## 2 2 C D D D 0 0
## 3 3 D D D C 2 -1
## 4 4 D C C C 1 1
##
## $u
## [1] 0.5 0.5
</code></pre>
<p>This code simulates a repated PD with continuation probability \( \delta=0.9 \) in which player 1 follows a strategy called “tit.for.tat” and player 2 follows a strategy called “random.action”. The resulting table shows for each period the following information:</p>
<ul>
<li>Columns obs_a1 and obs_a2: the observations at the beginning of a period. Here just the previous actions</li>
<li>Columns a1 and a2: players' actions </li>
<li>Columns pi1 and pi2: the resulting payoffs in that period.</li>
</ul>
<p>Below the table, the entry $u shows players' average payoffs across all periods.</p>
<h3>3.1 Tit-for-Tat</h3>
<p>Tit-for-Tat was the winning strategy in Axelrod's original tournament. It has a simple structure:</p>
<ul>
<li>Start nice by cooperating in period 1</li>
<li>In later periods play that action that the other player has played in the previous period. </li>
</ul>
<h3>3.2 Tit-for-Tat as a R function</h3>
<p>Further below in the file pdgame.r you find a definition of tit.for.tat as a R function:</p>
<pre><code class="r">tit.for.tat = function(obs, i, t, game) {
debug.store("tit.for.tat", i, t) # Store each call for each player
debug.restore("tit.for.tat", i = 1, t = 2) # Restore call for player i in period t
# Cooperate in the first period
if (t == 1)
return(list(a = "C"))
# In later periods, return the other player's previous action
j = 3 - i
list(a = obs$a[j])
}
</code></pre>
<p>The first line</p>
<pre><code class="r">tit.for.tat = function(obs,i,t,game) {
</code></pre>
<p>says that tit.for.tat is a function with the following arguments:</p>
<ul>
<li>i: this is simply the number of the player, either 1 or 2</li>
<li>t: this is the number of the current period</li>
<li>obs: this is a <a href="http://cran.r-project.org/doc/manuals/R-intro.html#Lists">list</a> that contains a player's observations about behavior from the previous period. The exact structure of observations will depend on the specification of the game that is played. In our basic PD game obs contains an element obs$a that is a vector with the two actions that the players have chosen in the previous period.</li>
<li>game: this is an object that describes the structure of the game that is currently played. In game$param different parameters of the game, like the stage game payoffs, are stored. You only need to use this variable, if you want to write general strategies that can be used for more than one game and that are fine tuned for different games. In the moment you just can ignore this variable.</li>
</ul>
<p>Every strategy must have these 4 arguments. (There may be additional aguments if a strategy uses states to pass additional information between periods. This is explained further below). The function run.rep.game now calls this function tit.for.tat in every period and provides the corresponding values of i,t,obs and game. E.g. if it is called in the third period for player 1 and in the previous round (D,C) was played, we have i==1, t==3, obs$a[1]==“D” and obs$a[2]==“C”. Based on the values of obs, t, i the function must return the action that the player chooses.</p>
<p>The lines </p>
<pre><code class="r">debug.store("tit.for.tat", i, t) # Store each call for each player
debug.restore("tit.for.tat", i = 1, t = 2) # Restore call for player i in period t
</code></pre>
<p>are useful for debugging a strategy and can be ignored for the moment (you can also remove them without changing the behavior of the strategy).</p>
<p>The lines</p>
<pre><code class="r">if (t == 1) return(list(a = "C"))
</code></pre>
<p>state that in the first period, i.e. t==1, the player cooperates. That the player cooperates means that the function returns a list</p>
<pre><code class="r">list(a = "C")
</code></pre>
<p>where the element a is “C”. In more complex games, a function may return more than a single action. The exact structure of the list of actions that a function has to return will be explained in the corresponding exercises. Note that we ommitted the “{” brackets of the 'if' condition. We can do that iff there follows exactly one statement after the condition.</p>
<p>The lines</p>
<pre><code class="r">j = 3 - i
list(a = obs$a[j])
</code></pre>
<p>describe the behavior in periods t>1. The variable j will be the index of the other player (if i=1 then j=2 and if i=2 then j=1). The last line says that the player choses that action that the other player has played in the previous period, i.e. obs$a[j]. (Note that in the last line of a function you can ommit writing “return”.)</p>
<h3>3.3 Strategies that use states. Example: strange.defector</h3>
<p>Many strategies rely not only on the most recent observations which are saved in obs. Consider for example this self-developed (not very clever) strategy:</p>
<ul>
<li>“Strange Defector”: In the first round cooperates with 70% probability, otherwise defects. As long as the player cooperates, he continues in this random fashion. Once the player defects, he plays 4 additional times “defect” in a row. Afterwards, he plays again as in the first period (randomizing, and after defection, 4 defects in a row).</li>
</ul>
<p>Here is an R implementation of this strategy:</p>
<pre><code class="r">strange.defector <- function(obs, i, t, game, still.defect = 0) {
debug.store("strange.defector", i, t) # Store each call for each player
debug.restore("strange.defector", i = 1, t = 2) # Restore call for player i in period t
# Randomize between C and D
if (still.defect == 0) {
do.cooperate = (runif(1) < 0.7)
# With 60% probability choose C
if (do.cooperate) {
return(list(a = "C", still.defect = 0))
} else {
return(list(a = "D", still.defect = 4))
}
}
# still.defect is bigger 0: play D and reduce still.defect by 1
still.defect = still.defect - 1
return(list(a = "D", still.defect = still.defect))
}
</code></pre>
<p>Compared to the tit.for.tat function, the strange.defector function has an additional argument, namely <em>still.defect</em> which in the first round t=1 has the value 0.
Also the returned lists contain an additional field named <em>still.defect</em>. The variable <em>still.defect</em> is a manually generated <em>state variable</em>.</p>
<h4>How state variables transfer information between periods:</h4>
<pre><code>The value of a state variable that is passed to your function in period t is the value of the state that your function has returned in period t-1. (The value of a state in period 1 is the value you specify in the function definition).
</code></pre>
<h4>Name and number of state variables</h4>
<pre><code>You can freely pick the name of a state variable (except for the reserved names ops,i,t, game and a) and you can have more than one state variable.
</code></pre>
<h4>Which values can state variables take?</h4>
<pre><code>States can take all sort of values: numbers (e.g 4.5), logical values (TRUE or FALSE), strings (e.g. "angry"), or even vectors. You just should not store a list in a state variable.
</code></pre>
<h4>Back to the example:</h4>
<p>In our example, the state variable <em>still.defect</em> captures the information how many rounds the streak of defection should still last.</p>
<p>Let us have a more detailed look at the code of the example. The line</p>
<pre><code class="r"> strange.defector <- function(obs, i, t, game, still.defect=0){
</code></pre>
<p>initializes the function with a state still.defect that has in the first period a value of 0.
The lines</p>
<pre><code class="r">if (still.defect == 0) {
do.cooperate = runif(1) < 0.7
# With 60% probability choose C
if (do.cooperate) {
return(list(a = "C", still.defect = 0))
} else {
return(list(a = "D", still.defect = 4))
}
}
</code></pre>
<p>first check whether we are in the initial state (still.defect=0), in which we randomize between C and D. If this is the case, we draw with the command</p>
<pre><code class="r">do.cooperate = (runif(1) < 0.7)
</code></pre>
<p>a logical random variable that is TRUE with 70% probability and otherwise FALSE. (To see this, note that runif(1) draws one uniformely distributed random variable between 0 and 1). The lines</p>
<pre><code class="r"> if (do.cooperate){
return(list(a="C", still.defect=0))
</code></pre>
<p>state that if the random variable says that we should cooperate, we return the action “C” and keep the state still.defect=0. The lines </p>
<pre><code class="r"> } else {
return(list(a="D", still.defect=4))
}
</code></pre>
<p>state that otherwise, we return the action “D” and set the state still.defect = 4. This means that we will defect for the next 4 periods. In the next period the value of still.defect will be 4 and the code at the bottom of the function will be called:</p>
<pre><code class="r">still.defect = still.defect - 1
return(list(a = "D", still.defect = still.defect))
</code></pre>
<p>The first line reduces still.defect by 1. (Hence, after 4 periods, we will again be in the state still.defect =0 and choose a random action). The second line returns our action a=“D” and the new value of our state still.defect.</p>
<p>If you run a single repeated game the result table also shows in each row, the values of the strategies' states at the <em>end</em> of the period:</p>
<pre><code class="r">run.rep.game(delta = 0.9, game = game, strat = nlist(strange.defector, tit.for.tat),
T.min = 20)
</code></pre>
<pre><code>## $hist
## t obs_a1 obs_a2 a1 a2 pi1 pi2 still.defect_1
## 1 1 <NA> <NA> D C 2 -1 4
## 2 2 D C D D 0 0 3
## 3 3 D D D D 0 0 2
## 4 4 D D D D 0 0 1
## 5 5 D D D D 0 0 0
## 6 6 D D D D 0 0 4
## 7 7 D D D D 0 0 3
## 8 8 D D D D 0 0 2
## 9 9 D D D D 0 0 1
## 10 10 D D D D 0 0 0
## 11 11 D D C D -1 2 0
## 12 12 C D C C 1 1 0
## 13 13 C C C C 1 1 0
## 14 14 C C C C 1 1 0
## 15 15 C C C C 1 1 0
## 16 16 C C C C 1 1 0
## 17 17 C C C C 1 1 0
## 18 18 C C C C 1 1 0
## 19 19 C C C C 1 1 0
## 20 20 C C D C 2 -1 4
## 21 21 D C D D 0 0 3
## 22 22 D D D D 0 0 2
##
## $u
## [1] 0.4096 0.1490
</code></pre>
<h3>3.4 Exercise:</h3>
<p>Implement the following strategy in R.</p>
<ul>
<li><p>tit3tat: The player starts with C and plays like tit-for-tat in period t=2 and t=3. In period t>3 the player plays with 60% probability like tit-for-tat and with 30% probability he plays the action that the other player played in the pre-previous period, i.e. in t-2 and with 10% probability he plays the action the other player played in t-3.</p>
<p>Hints:</p></li>
<li><p>To do something with 60% probability, you can draw a random variable x with the command x=runif(1) that is uniformely distributed between 0 and 1 and then check whether x<=0.6. To do something else with 30 probability, you can check 0.6 < x & x <= 0.9 and so on…</p></li>
<li><p>To save a longer history you can either use a function that has more than one state or store a vector in a state variable.</p></li>
</ul>
<h2>4. Running a tournament between strategies</h2>
<p>The following lines run a tournament between 4 specified strategies</p>
<pre><code class="r"># Init and run a tournament of several strategies against each other
game = make.pd.game()
strat = nlist(strange.defector, tit.for.tat, always.defect, always.coop)
tourn = init.tournament(game = game, strat = strat, delta = 0.95, score.fun = "efficiency-2*instability- 20*instability^2")
tourn = run.tournament(tourn = tourn, R = 10)
tourn
</code></pre>
<pre><code>##
## Tournament for Noisy PD (10 rep.)
##
## strange.defector tit.for.tat always.defect always.coop
## strange.defector 0.296 0.396 -0.3100 1.68
## tit.for.tat 0.291 1.000 -0.0501 1.00
## always.defect 0.583 0.100 0.0000 2.00
## always.coop -0.338 1.000 -1.0000 1.00
##
## Ranking with score = efficiency-2*instability- 20*instability^2
##
## rank score efficiency instability u.average best.answer
## tit.for.tat 1 1.000 1.000 0.000 0.560 tit.for.tat
## always.defect 2 0.000 0.000 0.000 0.671 always.defect
## strange.defector 3 -1.917 0.296 0.286 0.515 always.defect
## always.coop 4 -21.000 1.000 1.000 0.166 always.defect
</code></pre>
<p>The tournament consists of R rounds (here R=15). In every round, every strategy plays against each other strategy in a repeated game. Every strategy also plays against itself. For every pairing of two strategies, we then compute the average payoff of the strategies over all R rounds</p>
<p>The first matrix has for every strategy a row and column and shows the average payoff of the <em>row strategy</em> when the row strategy plays against the column strategy. (In a symmetric game like the PD game, we will just display the average payoffs of both player 1 and player 2). For example, when strategy always.defect played against always.coop, then always.defect got on average a payoff of 2 and always.coop got on average a payoff of -1. Against itself always.coop got an average payoff of 1.</p>
<p>The table below shows which strategies have won, as well as their score, efficiency, instability and best answer.</p>
<h3>4.1 Social norms, efficiency, instability and score</h3>
<p>How do we determine the winner of the tournament? Axelrod ranked the strategies according to their average payoff across all pairings. This average payoff is shown in the column <em>u.average</em>. We will use different scores to rank strategies, however. </p>
<p>Our underlying question is the following. Assume interactions in a group are such that people, who essentially want to maximize their own payoffs, are randomly matched with each other and play the specified repeated game. What would be a <strong>“good social norm”</strong> that one could teach to all people and which describes how they should behave in their interactions? More compactly:</p>
<p>** We search for strategies that would be efficient and stable social norms if everybody would follow these strategies**</p>
<p>What do we mean with efficient and stable?</p>
<h4><strong>Efficiency:</strong></h4>
<p>We define efficiency of a strategy is the <strong>average payoff</strong> the strategy achieves when it plays <strong>against itself</strong>. Hence, the efficiency is the average payoff of every person in the group if <em>everybody</em> in the group would follow this strategy.</p>
<h4><strong>Best answer:</strong></h4>
<p>The best answer against a strategy s shall be that strategy (from all strategies that participate in the tournament) that has the highest payoff against s. The column <em>best.answer</em> shows the best answer for each strategy. Note that several strategies can be best answers if they achieve the same payoff (we then only show one). Also note that a strategy can be a best answer against itself.</p>
<h4><strong>Instability:</strong></h4>
<p>We define the instability of a strategy s as the following difference:</p>
<pre><code>instability = best answer payoff against s - payoff of s against itself
</code></pre>
<p>Note that a strategy that is a best answer against itself has an instability of 0 and is therefore very stable. The following idea lies behind this definition of instability. We assume that persons want to maximize their own payoff. If s has a high instability value, it has the following problem: if everybody follows s, people have very high incentives not to follow s (deviate from s) and play the best answer strategy instead. The strategy s would not be a robust, sustainable social norm.</p>
<h4>Relationship to Best Replies and Nash equilibrium</h4>
<p>The idea that strategies should be stable is closely related to the game theoretic concept of a <strong>Nash equilibrium</strong>. Similar to our concept of a best answer, game theory knows the related concept of a <em>best reply</em>:</p>
<ul>
<li><p>In a two player game, player i's <strong>best reply</strong> to a strategy s of player j is that strategy that maximizes i's expected payoff across <strong>all possible strategies</strong></p></li>
<li><p>If every player follows a strategy s, we have a <strong>Nash equilibrium</strong> if and only if <strong>s is a best reply against itself</strong> </p></li>
</ul>
<p>Hence a strategy that forms a <strong>Nash equilibrium</strong> would have instability of 0 (abstracting from small sample problems), yet instability of 0 does not imply that the strategy will form a Nash equilibrium. That is because we have the following main difference between best-replies and best answers:</p>
<ul>
<li><strong>Main difference best answer vs best reply</strong>: Best answers only consider those strategies that participate in the tournament, while a best reply considers <em>all</em> possible strategies (there are typically infinitely many strategies).</li>
</ul>
<p>There are also additional differences. If you are not firm in game theory, you just can ignore them. If you are firm you just should notice these points but hopefully not bother too much.</p>
<ul>
<li><p>To compute best answers, we just take average payoffs from small sample of played repeated games, best replies are based on true expected payoffs.</p></li>
<li><p>Compared to game theoretic terminology, our use of the term strategy is quite imprecise with respect to which players plays the strategy (Our R functions are defined for both players and could in game theoretic terms also be seen as <em>strategy profiles</em>). When computing best answers we don't distinguish between player 1's best answer against player 2 and vice versa, but we will just take the mean of player 1's and player 2's payoffs. </p></li>
</ul>
<h4>Score</h4>
<p>The score of a strategy is a formula that combines its effieciency and instability. The basic rule is</p>
<pre><code>The score increases in the efficiency and decreases in the instability
</code></pre>
<p>In the example we use the following formula:
\[
score = efficiency - 2 * instability - 20*instability^2
\]</p>
<p>The quadratic term makes sure that large instability gets more strongly penalized than small instability. It is not clear how much we want to penalize instability. Game theory always puts a lot of emphasis on stability, since a Nash equilibrium needs an instability of 0. On the other hand, checking instability is not so easy and it can be very hard in the tasks of our seminar to find somewhat efficient strategies that really have an instability of 0. A score that allows some degree of instability may be a sensible criterion if we think about norms in a society in which at least some people have some intrinsic motivation to follow a prevailing norm or simply are too lazy to think much about a profitable deviation from the prevailing norm. </p>
<p>In our example, always.defect is the winner of the tournament. It is able to sustain cooperation in every period and has instability 0 (one can indeed show that it is a Nash equilibrium of that repeated PD). While always.coop also has a high efficiency, it looses because it is very instable. That is because a player who plays always.defect against always.coop makes a much higher payoff than a player who plays always.coop against always.coop.</p>
<h4>Second stage of tournament: Finding better answers to destabilize competing strategies</h4>
<p>To somewhat mitigate an issue related to the main difference between best answers and best replies, we will play two rounds of the tournament in our seminar. After the first round, the teams get the source code of all other strategies and have some time to develop new strategies that are just designed to become best answers against the strategies of the other teams. More precisely, the goal of a team's second stage strategies is just to increase the computed instability of other teams' first stage strategies and thereby decrease their score. This will be explained in more detail in the seminar.</p>
<h2>5. Guidelines for your Strategies</h2>
<h3>Keep it sufficiently simple, intuitive, clean and fast</h3>
<p>Your strategies and the implementation as R should be intuitively understandable. It is not the goal to develop extremely complex strategies with a large number of states that nobody understands and that require extremely complicated computations. The idea is that strategies resemble some sort of social norms. Also take into account that for the simulations we may run your strategy on the order of a million times, so don't make any complicated computations that need very long to run. That being said your strategy does not have to be as simple as tit-for-tat.</p>
<h3>Don't cheat</h3>
<p>If you are a hacker, you may think of many ways to cheat. For example, it might be really useful to find out whether your strategy plays against itself, but the rules of the basic PD game don't give you an effective way to communicate (you can only choose C or D). So you may think of exchanging information by writing information into a global R variable which the other player can read out. Such things are considered cheating and <strong>not allowed</strong>.</p>
<ul>
<li>You are only allowed to use the information that is passed to the function as parameters (including the states you returned in earlier periods).</li>
<li>You are not allowed to modify any external objects.</li>
</ul>
<p>As a rule of thumb: if you wonder whether something is cheating it probably is; if you are not sure ask us.</p>
<h2>6. Debugging a strategy</h2>
<p>When you first write a strategy or other R function, it often does not work correctly: your function is likely to have bugs. Some bugs make your programm stop and throw an error message, other bugs are more subtle and make your function run in a different fashion than you expected. <em>Debugging</em> means to find and correct bugs in your code. There are different tools that help debugging. I want to illustrate some debugging steps with an example.</p>
<p>Consider the following strategy, which I call “exploiter”:</p>
<ul>
<li>Exploiter: In the first period cooperate. If the other player cooperates for two or more times in a row defect. Otherwise play with 70% probability tit-for-tat and with 30% probability play defect. </li>
</ul>
<p>Here is a first attempt to implement this strategy as an r function (it contains a lot of bugs):</p>
<pre><code class="r">exploiter = function(obs,i,t,game, otherC) {
debug.store("exploiter",i,t) # Store each call for each player
debug.restore("exploiter",i=1,t=2) # Restore call for player i in period t
# Start nice in first period
if (t=1) {
return(list(a="C",otherC=0))
}
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]]=="C") otherC= otherC + 1
if (otherC > 2) return(list(a="D"))
# Play tit for tat with probability 70% and with prob. 30% play D
if (runif(1)<70) {
a = obs$a[[j]]
} else {
a = "D"
}
return(nlist(a=a,otherC))
}
</code></pre>
<h3>Step 1: Run function definition in R console and correct errors</h3>
<p>As a first step select the whole function in the RStudio editor and press the run button. You should see something similar to the following in the R console.</p>
<pre><code>> exploiter = function(obs,i,t,game, other.weakness) {
+ debug.store("exploiter",i,t) # Store each call for each player
+ debug.restore("exploiter",i=1,t=2) # Restore call for player i in period t
+ if (t=1) {
Error: unexpected '=' in:
"exploiter = function(obs,i,t,game, other.weakness) {
if (t="
> return(list(a="C",other.weakness=0))
Error: no function to return from, jumping to top level
> }
Error: unexpected '}' in " }"
> if (obs$a[[j]]=="C") {
+ other.weakness = other.weakness + 1
+ }
Error: object 'j' not found
> if (other.weakness > 2) {
+ return(list(a="D"))
+ }
Error: object 'other.weakness' not found
> # Follow tit for tat with probability 70% otherwise play D
> a = ifelse(runif(1)<0.7,obs$a[[j]],"D")
Error in ifelse(runif(1) < 0.7, obs$a[[j]], "D") : object 'j' not found
> return(nlist(a=a,other.weakness))
Error in nlist(a = a, other.weakness) : object 'other.weakness' not found
> }
Error: unexpected '}' in "}"
</code></pre>
<p>There are a lot of error messages. It is best to start with the first error message and try to correct the corresponding code.</p>
<pre><code> if (t=1) {
Error: unexpected '=' in:
"exploiter = function(obs,i,t,game, other.weakness) {if (t="
</code></pre>
<p>This is a typical beginner error. If we want to check whether t is 1, we need to write t==1 instead of t=1. (The expression t=1 means that the value 1 is assigned to the variable t, expression t==1 is a boolean expression that is TRUE if t is 1 and FALSE otherwise.) A corrected version of the function is</p>
<pre><code class="r">exploiter = function(obs, i, t, game, otherC) {
debug.store("exploiter", i, t) # Store each call for each player
debug.restore("exploiter", i = 1, t = 2) # Restore call for player i in period t
# Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C")
otherC = otherC + 1
if (otherC > 2)
return(list(a = "D"))
# Play tit for tat with probability 70% and with prob. 30% play D
if (runif(1) < 70) {
a = obs$a[[j]]
} else {
a = "D"
}
return(nlist(a = a, otherC))
}
</code></pre>
<p>If you run this new version in the console, no error is shown. Unfortunately, this does not mean that there</p>
<h3>Step 2: Check whether run.rep.game yields errors and debug such errors by stepping trough function</h3>
<p>As next step let us run run.rep.game with the strategy and check whether some errors are shown.</p>
<pre><code class="r">run.rep.game(delta = 0.95, game = game, strat = nlist(exploiter, random.action))
</code></pre>
<pre><code>## Error in evaluating strategy exploiter in period t=2 for player i=1
## ERROR.HIST:
</code></pre>
<pre><code>## t obs_a1 obs_a2 a1 a2 pi1 pi2 otherC_1
## 1 1 NA NA C D -1 2 0
## 2 NA NA NA <NA> <NA> NA NA NA
</code></pre>
<pre><code>## Error: Error in (function (obs, i, t, game, otherC) : object 'j' not found
</code></pre>
<p>We get an error message and learn that an error occurred when calling exploiter for player i=1 in period t=2. We also get the error message “object 'j' not found”. Probably you see the problem directly from that message. Nevertheless, let us pretend we have not found the problem yet and let us step through our function.
Go to the function code and run the line</p>
<pre><code class="r">debug.restore("exploiter", i = 1, t = 2) # Restore call for player i in period t
</code></pre>
<pre><code>## Restored: game,i,obs,otherC,t
</code></pre>
<p>in the R console by selecting the line and pressing the “Run” button or Ctrl-Enter. This call now restores now the arguments with which the strategy has been called for player i=1 in period t=2. You can examine the function arguments by typing them in the R console:</p>
<pre><code class="r">obs
</code></pre>
<pre><code>## $a
## a1 a2
## "C" "D"
</code></pre>
<pre><code class="r">i
</code></pre>
<pre><code>## [1] 1
</code></pre>
<pre><code class="r">t
</code></pre>
<pre><code>## [1] 2
</code></pre>
<p>You can also run some further lines of code inside the function to see where exactly the error has occured:</p>
<pre><code class="r"># Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C") otherC = otherC + 1
</code></pre>
<pre><code>## Error: object 'j' not found
</code></pre>
<p>We can also run parts of the last line to narrow down the error…</p>
<pre><code class="r">obs$a[[j]]
</code></pre>
<pre><code>## Error: object 'j' not found
</code></pre>
<pre><code class="r">j
</code></pre>
<pre><code>## Error: object 'j' not found
</code></pre>
<p>Ok, clearly we forgot to define the variable j, which shall be the index of the other player. We can add the line j = 3-i and run again the code inside the corrected function:</p>
<pre><code class="r">debug.restore("exploiter", i = 1, t = 2) # Restore call for player i in period t
</code></pre>
<pre><code>## Restored: game,i,obs,otherC,t
</code></pre>
<pre><code class="r"># Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
j = 3 - i # index of other player
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C") otherC = otherC + 1
if (otherC > 2) return(list(a = "D"))
# Play tit for tat with probability 70% and with prob. 30% play D
if (runif(1) < 70) {
a = obs$a[[j]]
} else {
a = "D"
}
return(nlist(a = a, otherC))
</code></pre>
<pre><code>## $a
## [1] "D"
##
## $otherC
## [1] 0
</code></pre>
<p>You probably will see an error message after the last line that there is no function to return from, but we can ignore that one. Otherwise we see no more error. Yet, that does not mean that our function has no more bug.
Before proceeding we copy the whole corrected function definition into the R console:</p>
<pre><code class="r">exploiter = function(obs, i, t, game, otherC) {
debug.store("exploiter", i, t) # Store each call for each player
debug.restore("exploiter", i = 1, t = 2) # Restore call for player i in period t
# Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
j = 3 - i # index of other player
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C")
otherC = otherC + 1
if (otherC > 2)
return(list(a = "D"))
# Play tit for tat with probability 70% and with prob. 30% play D
if (runif(1) < 70) {
a = obs$a[[j]]
} else {
a = "D"
}
return(nlist(a = a, otherC))
}
</code></pre>
<h3>Step 3: Running run.rep.game again and debugging the next error</h3>
<p>Copy the corrected function in your R console and then call run.rep.game again. (Note I now call the function run.rep.game with the parameters game.seed and strat.seed, which ensure that the random generator always returns the same results. That is just for the reason that it is easier to write this documentation if the error always occures in the same period).</p>
<pre><code class="r">run.rep.game(delta = 0.95, game = game, strat = nlist(exploiter, random.action),
game.seed = 12345, strat.seed = 12345)
</code></pre>
<pre><code>## Error in evaluating strategy exploiter in period t=8 for player i=1
## ERROR.HIST:
</code></pre>
<pre><code>## t obs_a1 obs_a2 a1 a2 pi1 pi2 otherC_1
## 3 3 D D D C 2 -1 0
## 4 4 D C C C 1 1 1
## 5 5 C C C D -1 2 2
## 6 6 C D D C 2 -1 2
## 7 7 D C D C 2 -1 NA
## 8 NA <NA> <NA> <NA> <NA> NA NA NA
</code></pre>
<pre><code>## Error: Error in otherC + 1: 'otherC' is missing
</code></pre>
<p>We find an error in period t=8 . Let us investigate the call to our strategy in that period by setting t=8 in the call to debug.restore</p>
<pre><code class="r">debug.restore("exploiter", i = 1, t = 8) # Restore call for player i in period t
</code></pre>
<pre><code>## Variable otherC was missing.
## Restored: game,i,obs,otherC,t
</code></pre>
<p>The call tells me that the state variable otherC was not provided as an argument to this function. This basically means that in period t=7 the function did not return the variable otherC. Let us check where this problem happened by exploring in more detail the function call in period 7.</p>
<pre><code class="r">debug.restore("exploiter", i = 1, t = 7) # Restore call for player i in period t
</code></pre>
<pre><code>## Restored: game,i,obs,otherC,t
</code></pre>
<pre><code class="r">
# Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
j = 3 - i # index of other player
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C") otherC = otherC + 1
if (otherC > 2) return(list(a = "D"))
</code></pre>
<pre><code>## $a
## [1] "D"
</code></pre>
<pre><code>Error: no function to return from, jumping to top level
</code></pre>
<p>We see that the function returned in the last line of the code above. And of course, we forgot to add otherC in the list of returned variables. So this variable was missing in period t=8. The last line is easy to fix and we again paste into the R console a corrected version of our strategy:</p>
<pre><code class="r">exploiter = function(obs, i, t, game, otherC) {
debug.store("exploiter", i, t) # Store each call for each player
debug.restore("exploiter", i = 1, t = 2) # Restore call for player i in period t
# Start nice in first period
if (t == 1) {
return(list(a = "C", otherC = 0))
}
j = 3 - i # index of other player
# If the other player has chosen C two or more times in a row play D
if (obs$a[[j]] == "C")
otherC = otherC + 1
if (otherC > 2)
return(list(a = "D", otherC = otherC))
# Play tit for tat with probability 70% and with prob. 30% play D
if (runif(1) < 70) {
a = obs$a[[j]]
} else {
a = "D"
}
return(nlist(a = a, otherC))
}
</code></pre>
<h3>Step 4: Call run.rep.game again and remove remaining bugs</h3>
<pre><code class="r">run.rep.game(delta = 0.95, game = game, strat = nlist(exploiter, random.action),
game.seed = 12345, strat.seed = 12345)
</code></pre>
<pre><code>## $hist
## t obs_a1 obs_a2 a1 a2 pi1 pi2 otherC_1
## 1 1 <NA> <NA> C D -1 2 0
## 2 2 C D D D 0 0 0
## 3 3 D D D C 2 -1 0
## 4 4 D C C C 1 1 1
## 5 5 C C C D -1 2 2
## 6 6 C D D C 2 -1 2
## 7 7 D C D C 2 -1 3
## 8 8 D C D D 0 0 4
## 9 9 D D D C 2 -1 4
## 10 10 D C D C 2 -1 5
## 11 11 D C D C 2 -1 6
## 12 12 D C D C 2 -1 7
## 13 13 D C D C 2 -1 8
## 14 14 D C D C 2 -1 9