'Change simulation parameters in the first few sections, then press shift-F5 to run. 'Enter the game utilities (from ROW's perspective): dc = 5 'Temptation for defection cc = 3 'Reward for cooperation dd = 1 'Punishment for defection cd = 0 'Sucker's payoff 'Enter the number of agents and initial distribution of types: ALLC = 10 TFT = 10 ALLD = 5 'Enter the culling threshold (the number cut after each period): cull = 6 'Enter the iteration parameters: t = 2 'The number of times each agent interactions with one another. p = 15 'The number of periods that the simulation will run. 'Enter the re-seeding parameters. '0 = proportional to initial distribution; '1 = proportional to end-of-period distribution. seed = 1 'DO NOT CHANGE ANY FURTHER CODE BELOW THIS POINT! N = ALLC + TFT + ALLD 'The program will check that the game is a Prisoner's Dilemma. IF dc > cc AND cc > dd AND dd > cd THEN PRINT , "Prisoner's Dilemma verified." ELSE INPUT "The game is NOT a Prisoner's Dilemma. Continue anyway? (y/N) "; ans$ ans$ = upper$(ans$) IF ans$ <> "Y" THEN END END IF 'The culling threshold must be less than the total number of agents: IF cull > N THEN PRINT "The culling threshold must be less than the total number of agents." END END IF 'This next part sets up arrays (sets of parameters) for each agent: DIM agent(N, 5) 'The first part of the array (where the N is) is the ID number of the agent. 'The second part of the array allows different parameters, with six 'slots' all together: 'agent(N,0): The agent's type; 0 = All C, 1 = TFT, 2 = All D. 'agent(N,1): The agent's initial move; 0 = defect, 1 = cooperate. 'agent(N,2): The agent's move after observing a defection; as above. 'agent(N,3): The agent's move after observing cooperation; as above. 'agent(N,4): The agent's cumulative score for a period. 'agent(N,5): The agent's rank, calculated at the end of the period. 'This next part puts values into the arrays based on the initial distribution. FOR i = 1 TO N IF i < ALLC + 1 THEN GOSUB [labelALLC] IF i > ALLC AND i < ALLC + TFT + 1 THEN GOSUB [labelTFT] IF i > ALLC + TFT THEN GOSUB [labelALLD] NEXT i 'This array keeps track of the history of a pair of agents 'over their interactions. This is only a short-term history. DIM h(t, 1) 'Arrays that keep track of summary information over time: DIM dist(p, 2) 'The 'p' part means for each period. 'dist(p,0): The number of All C agents. 'dist(p,1): The number of TFT agents. 'dist(p,2): The number of All D agents. DIM score(p, 2) 'score(p,0): The total score of All C agents. 'score(p,1): The total score of TFT agents. 'score(p,2): The total score of All D agents. 'Records the initial distribution: dist(0, 0) = ALLC dist(0, 1) = TFT dist(0, 2) = ALLD CLS IF seed = 0 THEN seed$ = "Re-Seeding Proportional to Initial Distribution" IF seed = 1 THEN seed$ = "Re-Seeding Proportional to End-of-Period Distribution" PRINT , seed$: PRINT , , t; " trials per pairing": PRINT : PRINT "Period", "All C", "TFT", "All D", "Elapsed Time" PRINT period, dist(0, 0), dist(0, 1), dist(0, 2) 'The simulation begins: [beginSimulation] period=period+1 if period>p then print "End simulation":end time0 = time$("seconds") 'The set of interactions: FOR i = 1 TO N FOR j = 1 TO N IF i = j GOTO [nexti] REDIM h(t, 1) FOR k = 1 TO t scan GOSUB [playgame] NEXT k NEXT j [nexti] NEXT i GOSUB [dist] GOSUB [rank] GOSUB [CULLandSEED] goto [beginSimulation] END 'SUBROUTINES: 'A subroutine calculates the score for each agent in the stage game: [playgame] IF k = 1 THEN movei = agent(i, 1) movej = agent(j, 1) ELSE IF h(k - 1, 1) = 0 THEN movei = agent(i, 2) IF h(k - 1, 1) = 1 THEN movei = agent(i, 3) IF h(k - 1, 0) = 0 THEN movej = agent(j, 2) IF h(k - 1, 0) = 1 THEN movej = agent(j, 3) END IF IF movei = 0 AND movej = 0 THEN agent(i, 4) = agent(i, 4) + dd: agent(j, 4) = agent(j, 4) + dd h(k, 0) = 0: h(k, 1) = 0 RETURN END IF IF movei = 0 AND movej = 1 THEN agent(i, 4) = agent(i, 4) + dc: agent(j, 4) = agent(j, 4) + cd h(k, 0) = 0: h(k, 1) = 1 RETURN END IF IF movei = 1 AND movej = 0 THEN agent(i, 4) = agent(i, 4) + cd: agent(j, 4) = agent(j, 4) + dc h(k, 0) = 1: h(k, 1) = 0 RETURN END IF IF movei = 1 AND movej = 1 THEN agent(i, 4) = agent(i, 4) + cc: agent(j, 4) = agent(j, 4) + cc h(k, 0) = 1: h(k, 1) = 1 RETURN END IF RETURN [dist] FOR i = 1 TO N IF agent(i, 0) = 0 THEN dist(period, 0) = dist(period, 0) + 1 score(period, 0) = score(period, 0) + agent(i, 4) END IF IF agent(i, 0) = 1 THEN dist(period, 1) = dist(period, 1) + 1 score(period, 1) = score(period, 1) + agent(i, 4) END IF IF agent(i, 0) = 2 THEN dist(period, 2) = dist(period, 2) + 1 score(period, 2) = score(period, 2) + agent(i, 4) END IF NEXT i timeELAPSED = INT((time$("seconds") - time0) * 10) / 10 PRINT period, dist(period, 0), dist(period, 1), dist(period, 2), timeELAPSED FOR i = 0 TO 2 IF seed = 1 AND dist(period, i) = N THEN PRINT , , "Population bottle-neck reached." END END IF NEXT i RETURN [rank] FOR rank = 1 TO cull minscore = t * dc * (N - 1) FOR i = 1 TO N IF agent(i, 5) = 0 AND agent(i, 4) < minscore THEN minscore = agent(i, 4) minagent = i END IF NEXT i agent(minagent, 5) = rank NEXT rank RETURN [CULLandSEED] FOR i = 1 TO N IF agent(i, 5) > 0 THEN x = rnd(1) IF seed = 0 THEN IF x < ALLC / N THEN GOSUB [labelALLC] IF x > ALLC / N AND x < (ALLC + TFT) / N THEN GOSUB [labelTFT] IF x > (ALLC + TFT) / N THEN GOSUB [labelALLD] END IF IF seed = 1 THEN IF x < dist(period, 0) / N THEN GOSUB [labelALLC] IF x > dist(period, 0) / N AND x < (dist(period, 0) + dist(period, 1)) / N THEN GOSUB [labelTFT] IF x > (dist(period, 0) + dist(period, 1)) / N THEN GOSUB [labelALLD] END IF END IF agent(i, 4) = 0 agent(i, 5) = 0 NEXT i RETURN [labelALLC] agent(i, 0) = 0 agent(i, 1) = 1 agent(i, 2) = 1 agent(i, 3) = 1 RETURN [labelTFT] agent(i, 0) = 1 agent(i, 1) = 1 agent(i, 2) = 0 agent(i, 3) = 1 RETURN [labelALLD] agent(i, 0) = 2 agent(i, 1) = 0 agent(i, 2) = 0 agent(i, 3) = 0 RETURN