This text file includes the code for the Pascal program and the initiation file needed to run the Pascal code. To run this code, copy the initiation text into a file named "tftsim.ini" (without the quotes). Copy the Pascal text into a file named "tftsim.pas" (without the quotes) and compile (we used Free Pascal for Windows: http://www.freepascal.org/) to create executable file (e.g., tftsim.exe). Place the initiation file in the same directory as the Pascal executable file. At the command line, start program by typing "tftsim.exe tftsim.ini". ################################################################ Initiation file begins. Below this is the Pascal code. ################################################################ directory_name tft_sim blocked_interaction on number_of_agents 2 number_of_interaction_partners 1 number_of_interactions_with_partner 10 number_of_gtft 0 number_of_pavlov 0 number_of_random 0 number_of_grim 0 number_of_contrite_tft 2 number_of_tft 0 number_of_tf2t 0 number_of_allc 0 number_of_alld 0 dependent_strategy 1 mutation 0.0 memory_error_mode fixed memory_error_initial_start 1.0 memory_error_initial_end 0.50 memory_error_forget_start 0 memory_error_forget_end 0 runs 1000 output_on_screen off gtft_first_move 100 gtft_cc 100 gtft_cd 33 gtft_dc 100 gtft_dd 33 pavlov_first_move 100 pavlov_cc 100 pavlov_cd 0 pavlov_dc 0 pavlov_dd 100 ################################################################ Pascal code begins. ################################################################ program simulation; (* Simulation Program 11/2009 with 'mutation' coded by Sebastian Scholz written and compiled with FPC 2.2.4 Parameters can be changed in separate ini-file! start from command line: "simulation filename.ini" content of the ini-file: blocked_interaction (on/off) number_of_agents (integer (0-65535)) number_of_interaction_partners (integer (0-65535)) number_of_interactions_with_partner (integer (0-65535)) memory_error_mode (fixed/partner-wise) memory_error_initial_start (real (0.00-1.00)) memory_error_initial_end (real (0.00-1.00)) memory_error_forget_start (real (0.00-1.00)) memory_error_forget_end (real (0.00-1.00)) mutation (real (0.000-1.000)) runs (integer (0-65535)) output_on_screen (on/off) gtft_first_move (integer (0-100)) gtft_cc (integer (0-100)) gtft_cd (integer (0-100)) gtft_dc (integer (0-100)) gtft_dd (integer (0-100)) pavlov_first_move (integer (0-100)) pavlov_cc (integer (0-100)) pavlov_cd (integer (0-100)) pavlov_dc (integer (0-100)) pavlov_dd (integer (0-100)) *) uses crt; // declaration of constants const c_number_of_strategies = 9; c_mutationrange = 1001; // mutation 0-1000 (program) resp. 0.000-1.000 (ini-file) payoff_cc = 3; // agent's payoff for cooperate(agent)-cooperate(partner) payoff_cd = 0; // agent's payoff for cooperate(agent)-defect(partner) payoff_dc = 5; // agent's payoff for defect(agent)-cooperate(partner) payoff_dd = 1; // agent's payoff for defect(agent)-defect(partner) strat_yx: array[1..c_number_of_strategies] of byte = (8,9,10,11,12,13,14,15,16); // y-constants if output on screen is enabled // declaration of types type p_agent = ^r_agent; // pointer to agent record p_move = ^r_move; // pointer to move record p_pair = ^r_pair; // pointer to pair record p_order = ^r_order; // pointer to order record p_run = ^r_run; // pointer to run record p_generation = ^r_generation; // pointer to generation record r_tempdata = record gen: word; // generation counter run: word; // run counter initial,forget: byte; // initial and forget counter strat: array[1..c_number_of_strategies] of real; // percentage of each strategy strat_agents: array[1..c_number_of_strategies] of word; // number of agents per strategy end; r_ini = record // parameters from ini file noft,noft2,mutation: word; // number of agents and corrected number; mutation rate noip: word; // number of interaction partners noiwp: word; // number of interactions with each partner blocked: boolean; // blocked interaction me_mode: byte; // memory error mode; 1=partner-wise, 2=fixed initial, forget: array[1..2] of byte; // for calculation of the memory error runs: word; // number of runs the simulation has to pass prob1_firstmove,prob1_cc,prob1_cd,prob1_dc,prob1_dd: byte; // probability of cooperation after cc,cd,dc,dd and in first move prob2_firstmove,prob2_cc,prob2_cd,prob2_dc,prob2_dd: byte; // probability of cooperation after cc,cd,dc,dd and in first move output: boolean; // output on screen end; r_generation = record strat: array[1..c_number_of_strategies] of word; // number of agents per strategy win: ^byte; // winner strategy next,prev: p_generation; // next and previous item in list end; r_run = record gen: p_generation; // pointer to generation record ccounter,icounter: longint; // counter of interactions and cooperations cclg: longint; // counter of cooperations in the last generation next,prev: p_run; // next and previous item in list end; r_order = record agent: p_agent; // pointer to agent record next,prev: p_order; //next and previous item in list end; r_move = record move,pmove: boolean; // agent's move and move of agent's partner partner: p_agent; // pointer to the partner next,prev: p_move; // next and previous item in list end; r_agent = record strat: byte; // type of strategy lastmoves: p_move; // pointer to all moves of the agent agent_as_actor: word; // counts how often an agent is selected as part of a pair number: longint; // the number of the agent np: boolean; // "no play"; if number of agents * number of interaction partners cannot be divided by two, one randomly chosen agent is not available for one generation, e.g., 99 agents, 5 interaction partners --> only 98 agents are available for one generation cpayoff: longint; // cumulated payoff next,prev: p_agent; // next and previous item in list end; r_pair = record present: word; // counts how often a pair is selected player,partner: p_agent; // pointer to player and partner next,prev: p_pair; // next and previous item in list end; // declaration of variables var temp: r_tempdata; run_data: p_run; // data of every run is collected in this pointer until the end when data is saved on hard disc directory: string; // files are saved in this directory (can be initialized within the ini file) f_run, f_statistics, f_statistics_all: text; // files to save in filename_run, filename_statistics, filename_statistics_all: string; // file names of above files strat_name: array[1..c_number_of_strategies] of string; // strategy names agent, first_agent, temp_agent: p_agent; // agent = list of all created agents; first_agent & temp_agent are marks within that list pair, first_pair: p_pair; // pair = list of all created pairs; first_pair is a mark within that list ini: r_ini; // all initialization data is saved in that type f_ini: text; // ini file to read from player_move, partner_move: boolean; // can be true (cooperate) or false (defect) player_payoff, partner_payoff: byte; // payoff for agent & partner ii,ij,ik,il,number_of_actions: longint; // temp variables function str2int(s:string):word; // transforms string to word (0..65k) // if a string cannot be transformed, the function returns "65432" var i,code: word; begin val(s,i,code); if code<>0 then str2int:=65432 else str2int:=i; end; function str2real(s:string):double; // transforms string to real // if a string cannot be transformed, the function returns "65432" var code: word; i:double; begin val(s,i,code); if code<>0 then str2real:=65432 else str2real:=i; end; function int2str(int:longint):string; // transforms integer to text var s: string; begin str(int,s); int2str:=s; end; function real2str(r:double;dp:byte):string; // transforms real to text var s: string; begin str(r:3:dp,s); real2str:=s; end; function square(x,y:double):double; // x to the power of y begin if y=0 then square:=1 else square:=exp(ln(x)*y); end; function memory_error(x:boolean;distance:word):boolean; // checks whether agent remembers correctly var t: word; p: longint; begin if distance>1 then p:=trunc((temp.initial/100)*(square(distance,((-1)*(temp.forget/100))))*10000) else p:=trunc(temp.initial*100); // forgetting function t:=random(10001); if t>p then memory_error:=not x else memory_error:=x; end; procedure wth_gen(newrun:boolean); // writes a complete generation into memory (heap) var i: byte; begin if run_data=nil then begin new(run_data); run_data^.next:=nil; run_data^.prev:=nil; run_data^.ccounter:=0; run_data^.icounter:=0; run_data^.cclg:=0; new(run_data^.gen); run_data^.gen^.next:=nil; run_data^.gen^.prev:=nil; run_data^.gen^.win:=nil; end else begin while run_data^.next<>nil do run_data:=run_data^.next; if newrun then begin new(run_data^.next); run_data^.next^.prev:=run_data; run_data:=run_data^.next; run_data^.next:=nil; run_data^.ccounter:=0; run_data^.icounter:=0; run_data^.cclg:=0; new(run_data^.gen); run_data^.gen^.next:=nil; run_data^.gen^.prev:=nil; run_data^.gen^.win:=nil; end else begin while run_data^.next<>nil do run_data:=run_data^.next; while run_data^.gen^.next<>nil do run_data^.gen:=run_data^.gen^.next; new(run_data^.gen^.next); run_data^.gen^.next^.prev:=run_data^.gen; run_data^.gen:=run_data^.gen^.next; run_data^.gen^.next:=nil; run_data^.gen^.win:=nil; end; end; for i:=1 to c_number_of_strategies do run_data^.gen^.strat[i]:=temp.strat_agents[i]; end; procedure wtd_runs; // writes all runs & generations and some statistics on hard disc type p_sorted = ^r_sorted; r_sorted = record r: longint; next,prev: p_sorted; end; p_median = ^r_median; r_median = record r: real; next,prev: p_median; end; var i,j,l,m: word; r: array [1..c_number_of_strategies] of double; rr: array[1..c_number_of_strategies] of double; k: byte; sorted,first,last: array[1..c_number_of_strategies] of p_sorted; sort_temp: p_sorted; median, first_median: array[1..c_number_of_strategies] of p_median; median_temp: p_median; last_run: p_run; last_gen: p_generation; winner,s_min,s_max,strat_run: array[1..c_number_of_strategies] of longint; strat_all: array[1..c_number_of_strategies] of real; cc,ic: double; cr2: array[1..2] of double; begin if ini.output then begin writeln;writeln;writeln;writeln('Saving files...'); end; for i:=1 to c_number_of_strategies do begin strat_run[i]:=0; strat_all[i]:=0; median[i]:=nil; winner[i]:=0; end; cc:=0.0; ic:=0.0; cr2[1]:=0.0; cr2[2]:=0.0; i:=0; append(f_run); append(f_statistics); append(f_statistics_all); while run_data^.prev<>nil do run_data:=run_data^.prev; repeat inc(i); for k:=1 to c_number_of_strategies do begin s_min[k]:=0; s_max[k]:=0; sorted[k]:=nil; end; last_run:=nil; j:=0; for k:=1 to c_number_of_strategies do strat_run[k]:=0; while run_data^.gen^.prev<>nil do run_data^.gen:=run_data^.gen^.prev; repeat inc(j); last_gen:=nil; writeln(f_run,'run '+int2str(i)+' / generation '+int2str(j)); for k:=1 to c_number_of_strategies do begin writeln(f_run,(real2str(((run_data^.gen^.strat[k]/ini.noft2)*100),13))); strat_run[k]:=strat_run[k]+run_data^.gen^.strat[k]; if sorted[k]=nil then begin new(sorted[k]); sorted[k]^.next:=nil; sorted[k]^.prev:=nil; first[k]:=sorted[k]; last[k]:=sorted[k]; sorted[k]^.r:=run_data^.gen^.strat[k]; s_max[k]:=run_data^.gen^.strat[k]; s_min[k]:=run_data^.gen^.strat[k]; end else begin if run_data^.gen^.strat[k]>=s_max[k] then begin sorted[k]:=last[k]; new(sorted[k]^.next); sorted[k]^.next^.prev:=sorted[k]; sorted[k]:=sorted[k]^.next; sorted[k]^.next:=nil; last[k]:=sorted[k]; sorted[k]^.r:=run_data^.gen^.strat[k]; s_max[k]:=run_data^.gen^.strat[k]; end else begin if run_data^.gen^.strat[k]<=s_min[k] then begin sorted[k]:=first[k]; new(sorted[k]^.prev); sorted[k]^.prev^.next:=sorted[k]; sorted[k]:=sorted[k]^.prev; sorted[k]^.prev:=nil; first[k]:=sorted[k]; sorted[k]^.r:=run_data^.gen^.strat[k]; s_min[k]:=run_data^.gen^.strat[k]; end else begin sorted[k]:=first[k]; repeat sorted[k]:=sorted[k]^.next; until (run_data^.gen^.strat[k]<=sorted[k]^.r) or (sorted[k]=nil); new(sort_temp); sorted[k]^.prev^.next:=sort_temp; sort_temp^.prev:=sorted[k]^.prev; sort_temp^.next:=sorted[k]; sorted[k]^.prev:=sort_temp; sorted[k]:=sort_temp; sorted[k]^.r:=run_data^.gen^.strat[k]; sort_temp:=first[k]^.prev; end; end; end; end; last_gen:=run_data^.gen; run_data^.gen:=run_data^.gen^.next; if run_data^.gen<>nil then run_data^.gen^.prev:=nil; if last_gen^.win<>nil then begin inc(winner[last_gen^.win^]); dispose(last_gen^.win); last_gen^.win:=nil; end; last_gen^.next:=nil; dispose(last_gen); last_gen:=nil; until run_data^.gen=nil; sorted[k]:=first[k]; if sorted[k]^.next<>nil then while sorted[k]^.next<>nil do sorted[k]:=sorted[k]^.next; writeln(f_run,'F I N I S H E D'); writeln(f_statistics,'run '+int2str(i)+' / cooperation rate'); writeln(f_statistics,int2str(run_data^.icounter*2)); writeln(f_statistics,int2str(run_data^.ccounter)); writeln(f_statistics,real2str((run_data^.ccounter/(run_data^.icounter*2))*100,13)); ic:=ic+run_data^.icounter; cc:=cc+run_data^.ccounter; writeln(f_statistics,'run '+int2str(i)+' / cooperation rate (last generation)'); writeln(f_statistics,int2str(number_of_actions)); writeln(f_statistics,int2str(run_data^.cclg)); writeln(f_statistics,real2str((run_data^.cclg/(number_of_actions))*100,13)); cr2[1]:=cr2[1]+(number_of_actions); cr2[2]:=cr2[2]+run_data^.cclg; writeln(f_statistics,'run '+int2str(i)+' / arithmetic mean'); for k:=1 to c_number_of_strategies do begin writeln(f_statistics,real2str(((strat_run[k]/j/ini.noft2)*100),13)); strat_all[k]:=strat_all[k]+strat_run[k]/j/ini.noft2; end; writeln(f_statistics,'run '+int2str(i)+' / median'); if (j div 2)<>0 then m:=(j div 2) else m:=(j div 2)-1; for k:=1 to c_number_of_strategies do begin sorted[k]:=first[k]; if m>0 then for l:=1 to m do begin if sorted[k]^.next<>nil then sorted[k]:=sorted[k]^.next; end; new(median_temp); if (j div 2)<>0 then median_temp^.r:=sorted[k]^.r else median_temp^.r:=(sorted[k]^.r+sorted[k]^.next^.r)/2; median_temp^.r:=median_temp^.r/ini.noft2*100; writeln(f_statistics,real2str(median_temp^.r,13)); if median[k]<>nil then begin median[k]:=first_median[k]; if (median[k]^.next<>nil)and(median_temp^.r>=first_median[k]^.r) then repeat median[k]:=median[k]^.next; until (median_temp^.r<=median[k]^.r)or(median[k]^.next=nil); if median[k]=first_median[k] then begin if median[k]^.r>median_temp^.r then begin median_temp^.next:=first_median[k]; median_temp^.next^.prev:=median_temp; median_temp^.prev:=nil; first_median[k]:=median_temp; end else begin median_temp^.prev:=first_median[k]; median_temp^.prev^.next:=median_temp; median_temp^.next:=nil; end; median[k]:=median_temp; median_temp:=first_median[k]^.prev; end else if (median[k]^.next=nil)and(median[k]^.r<=median_temp^.r) then begin median[k]^.next:=median_temp; median[k]^.next^.prev:=median[k]; median[k]:=median[k]^.next; median[k]^.next:=nil; median_temp:=first_median[k]^.prev; end else begin median[k]^.prev^.next:=median_temp; median_temp^.prev:=median[k]^.prev; median_temp^.next:=median[k]; median[k]^.prev:=median_temp; median[k]:=median_temp; median_temp:=first_median[k]^.prev; end; end else begin median[k]:=median_temp; median[k]^.next:=nil; median[k]^.prev:=nil; first_median[k]:=median[k]; median_temp:=first_median[k]^.prev; end; sorted[k]:=first[k]; repeat sorted[k]:=sorted[k]^.next; dispose(sorted[k]^.prev); sorted[k]^.prev:=nil; until sorted[k]^.next=nil; dispose(sorted[k]); sorted[k]:=nil; end; run_data^.gen:=nil; last_run:=run_data; run_data:=run_data^.next; if run_data<>nil then run_data^.prev:=nil; last_run^.next:=nil; dispose(last_run); last_run:=nil; until run_data=nil; writeln(f_statistics_all,'cooperation rate over '+int2str(ini.runs)+' runs - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); writeln(f_statistics_all,real2str(ic*2,0)); writeln(f_statistics_all,real2str(cc,0)); writeln(f_statistics_all,real2str((cc/(ic*2))*100,13)); writeln(f_statistics_all,'cooperation rate (last generation) over '+int2str(ini.runs)+' runs - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); writeln(f_statistics_all,real2str(cr2[1],0)); writeln(f_statistics_all,real2str(cr2[2],0)); writeln(f_statistics_all,real2str((cr2[2]/cr2[1])*100,13)); writeln(f_statistics_all,'arithmetic mean over '+int2str(ini.runs)+' runs (in %) - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); for k:=1 to c_number_of_strategies do writeln(f_statistics_all,real2str(((strat_all[k]/ini.runs*100)),13)); writeln(f_statistics_all,'median over '+int2str(ini.runs)+' runs (in %) - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); if ini.runs>1 then begin for k:=1 to c_number_of_strategies do begin median[k]:=first_median[k]; if (ini.runs div 2)<>0 then begin for i:=1 to trunc(ini.runs/2) do median[k]:=median[k]^.next; writeln(f_statistics_all,real2str(median[k]^.r,13)); end else begin for i:=1 to ((ini.runs div 2)-1) do median[k]:=median[k]^.next; writeln(f_statistics_all,real2str((median[k]^.r+median[k]^.next^.r)/2,13)); end; end; end; for k:=1 to c_number_of_strategies do begin median[k]:=first_median[k]; if median[k]^.next<>nil then while median[k]^.next<>nil do begin median[k]:=median[k]^.next; dispose(median[k]^.prev); median[k]^.prev:=nil; end; dispose(median[k]); median[k]:=nil; first_median[k]:=nil; end; writeln(f_statistics_all,'winner over '+int2str(ini.runs)+' runs (in %) - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); for k:=1 to c_number_of_strategies do begin r[k]:=winner[k]/ini.runs; writeln(f_statistics_all,real2str(r[k]*100,13)); ik:=0; rr[k]:=0; rr[k]:=1.96*(sqrt((winner[k]*(sqr(1-r[k]))+((ini.runs-winner[k])*(sqr(0-r[k]))))/(ini.runs*(ini.runs-1)))); winner[k]:=0; end; writeln(f_statistics_all,'confidence interval (winner %) over '+int2str(ini.runs)+' runs - forget '+real2str(temp.forget/100,2)+' - initial '+real2str(temp.initial/100,2)); for k:=1 to c_number_of_strategies do begin writeln(f_statistics_all,real2str(rr[k]*100,13)); end; run_data:=nil; close(f_run); close(f_statistics); close(f_statistics_all); if not ini.output then gotoxy(1,5); writeln('Done.'); writeln; writeln; end; procedure clear_mem_agent(clearall: boolean); // deletes memory of the agents; if "clearall"=true the agents are deleted, too var ttemp: p_agent; ltemp: p_move; begin if (agent<>nil) then begin while agent^.prev<>nil do agent:=agent^.prev; if clearall then begin repeat ttemp:=agent; agent:=agent^.next; if agent<>nil then agent^.prev:=nil; ttemp^.next:=nil; if ttemp^.lastmoves<>nil then begin while ttemp^.lastmoves^.prev<>nil do ttemp^.lastmoves:=ttemp^.lastmoves^.prev; repeat ltemp:=ttemp^.lastmoves; ttemp^.lastmoves:=ttemp^.lastmoves^.next; if ttemp^.lastmoves<>nil then ttemp^.lastmoves^.prev:=nil; ltemp^.next:=nil; ltemp^.partner:=nil; dispose(ltemp); ltemp:=nil; until ttemp^.lastmoves=nil; end; ttemp^.agent_as_actor:=0; ttemp^.cpayoff:=0; ttemp^.np:=false; dispose(ttemp); ttemp:=nil; until agent=nil; first_agent:=nil; temp_agent:=nil; agent:=nil; end else begin repeat agent^.agent_as_actor:=0; agent^.cpayoff:=0; agent^.np:=false; if agent^.lastmoves<>nil then begin while agent^.lastmoves^.prev<>nil do agent^.lastmoves:=agent^.lastmoves^.prev; repeat ltemp:=agent^.lastmoves; agent^.lastmoves:=agent^.lastmoves^.next; if agent^.lastmoves<>nil then agent^.lastmoves^.prev:=nil; ltemp^.next:=nil; ltemp^.partner:=nil; dispose(ltemp); ltemp:=nil; until agent^.lastmoves=nil; end; agent:=agent^.next; until agent=nil; agent:=first_agent; end; end; end; procedure clear_mem_pair; // deletes all pairs var temp: p_pair; begin if (pair<>nil) then begin while pair^.prev<>nil do pair:=pair^.prev; repeat temp:=pair; pair:=pair^.next; if pair<>nil then pair^.prev:=nil; temp^.next:=nil; temp^.present:=0; temp^.player:=nil; temp^.partner:=nil; dispose(temp); temp:=nil; until pair=nil; end; first_pair:=nil; end; procedure clear_mem; // deletes pairs and agents begin clear_mem_pair; clear_mem_agent(true); end; procedure clear_all_heaps; // deletes pairs and agents and all runs var r: p_run; g: p_generation; begin clear_mem; if run_data<>nil then begin while run_data^.next<>nil do run_data:=run_data^.next; repeat r:=run_data; run_data:=run_data^.next; if run_data<>nil then if run_data^.prev<>nil then run_data^.prev:=nil; if r^.gen<>nil then begin while r^.gen^.next<>nil do r^.gen:=r^.gen^.next; repeat g:=r^.gen; r^.gen:=r^.gen^.next; if r^.gen<>nil then if r^.gen^.prev<>nil then r^.gen^.prev:=nil; g^.prev:=nil; dispose(g); g:=nil; until r^.gen=nil; end; r^.gen:=nil; dispose(r); r:=nil; until run_data=nil; end; end; procedure init_pairs; // initializes pairs; with random agents and random partners var pc:longint; limit,initcounter1,initcounter2: longint; b1,b2: boolean; last_pair,temp_pair: p_pair; label 1; begin limit:=ini.noft2*100; 1: clear_mem_pair; clear_mem_agent(false); // if number of agents <> corrected number of agents, then one random agent cannot be used for the pairs // this agent will be marked if ini.noft<>ini.noft2 then begin repeat agent:=first_agent; ik:=random(ini.noft2); if ik>0 then for ij:=1 to ik do agent:=agent^.next; until (agent=nil) or (not agent^.np); agent^.np:=true; // a random agent will not be used end; agent:=first_agent; new(pair); pair^.next:=nil; pair^.prev:=nil; pair^.partner:=nil; pair^.player:=nil; pair^.present:=0; first_pair:=pair; pc:=0; // counter of created pairs initcounter2:=0; while pc < (ini.noft*ini.noip/2) do begin initcounter1:=0; ii:=random(ini.noft2); agent:=first_agent; if (ii>0) then for ij:=1 to ii do agent:=agent^.next; if (agent^.agent_as_actor0 then for ik:=1 to il do temp_agent:=temp_agent^.next; if ((((temp_agent<>agent)and(temp_agent^.agent_as_actoragent))) and (not temp_agent^.np)) then begin b2:=false; if (pc>0) then begin pair:=first_pair; repeat if ((pair^.player=agent) and (pair^.partner=temp_agent)) or ((pair^.partner=agent) and (pair^.player=temp_agent)) then b2:=true; pair:=pair^.next; until (pair=nil) or (b2); pair:=first_pair; end; b1:=not b2; end; inc(initcounter1); if initcounter1>limit then goto 1; end; pair:=first_pair; while pair^.next<>nil do pair:=pair^.next; if pc>0 then begin new(pair^.next); pair^.next^.prev:=pair; pair:=pair^.next; pair^.next:=nil; end; pair^.player:=agent; pair^.partner:=temp_agent; pair^.present:=0; inc(pc); inc(pair^.player^.agent_as_actor); inc(pair^.partner^.agent_as_actor); end; end; inc(initcounter2); if initcounter2>limit then goto 1; end; // creation of pairs complete // creates a list of all interactions of a generation now agent:=first_agent; pair:=first_pair; while pair^.next<>nil do pair:=pair^.next; last_pair:=pair; if ini.blocked then begin // if blocked interaction for ii:=1 to ini.noiwp do begin for ij:=1 to pc do begin b1:=false; while not b1 do begin ik:=random(pc); pair:=first_pair; if ik>0 then for il:=1 to ik do pair:=pair^.next; if pair^.present0 then for il:=1 to ik do pair:=pair^.next; if pair^.present0 then for ij:=1 to temp.strat_agents[ii] do begin agent^.strat:=ii; agent^.agent_as_actor:=0; agent^.lastmoves:=nil; agent^.np:=false; agent^.cpayoff:=0; new(agent^.next); agent^.next^.prev:=agent; agent:=agent^.next; agent^.next:=nil; end; end; agent:=agent^.prev; dispose(agent^.next); agent^.next:=nil; agent:=first_agent; end; procedure setup(newrun:boolean); // newrun = if a new run is started // determines number of agents for each strategy and initializes agents and pairs var p: word; begin randomize; p:=0; if newrun then begin clear_mem; for ii:=1 to c_number_of_strategies do begin temp.strat[ii]:=1/c_number_of_strategies; temp.strat_agents[ii]:=trunc(temp.strat[ii]*ini.noft2); p:=p+temp.strat_agents[ii]; end; if p=max then begin agent_order:=max_to; new(agent_order^.next); agent_order^.next^.prev:=agent_order; agent_order:=agent_order^.next; agent_order^.next:=nil; agent_order^.agent:=agent; max:=agent^.cpayoff; max_to:=agent_order; end else if agent^.cpayoff<=min then begin agent_order:=min_to; new(agent_order^.prev); agent_order^.prev^.next:=agent_order; agent_order:=agent_order^.prev; agent_order^.prev:=nil; agent_order^.agent:=agent; min:=agent^.cpayoff; min_to:=agent_order; end else begin agent_order:=min_to; if agent_order^.next<>nil then repeat agent_order:=agent_order^.next; until (agent_order=nil) or (agent^.cpayoffnil) do agent_order:=agent_order^.next; until agent_order<>nil; if random(c_mutationrange)agent_order^.agent^.strat; end else ik:=agent_order^.agent^.strat; inc(temp.strat_agents[ik]); if temp.strat_agents[ik]=ini.noft2 then begin // ends run if number of agents from one strategy equals number of all possible agents complete:=true; wth_gen(false);// writes the completed run into memory while run_data^.gen^.next<>nil do run_data^.gen:=run_data^.gen^.next; new(run_data^.gen^.win); run_data^.gen^.win^:=ik; end; end; if ini.output then begin // displays information (e.g., proportion of each strategy) if screen output is enabled in ini file if temp.gen<=2 then begin gotoxy(1,5);write('run #',temp.run,'/',ini.runs); gotoxy(42,2);write('initial: ',(temp.initial/100):0:2,' (',(ini.initial[1]/100):0:2,' --> ',(ini.initial[2]/100):0:2,')'); gotoxy(42,3);write('forget: ',(temp.forget/100):0:2,' (',(ini.forget[1]/100):0:2,' --> ',(ini.forget[2]/100):0:2,')'); gotoxy(42,4);write('error mode: ');if ini.me_mode=1 then write('partner-wise') else write('fixed'); gotoxy(1,1);write('actors: ',ini.noft:3,' /',ini.noft2:3); gotoxy(42,1);write('blocked: ');if ini.blocked then write('on') else write('off'); gotoxy(1,2);write('interaction partners: ',ini.noip:3); gotoxy(1,3);write('interactions with partner:',ini.noiwp:3); gotoxy(1,18);writeln('For much higher performance (~6x) change output_on_screen to "off".'); end; gotoxy(16,5); if complete then write('last generation: ',temp.gen:4) else write('generation: ',temp.gen:4); for ii:=1 to c_number_of_strategies do begin if temp.strat_agents[ii]=0 then textcolor(red); if temp.strat_agents[ii]=ini.noft2 then textcolor(green); gotoxy(1,strat_yx[ii]); write(strat_name[ii],': ',((temp.strat_agents[ii]/ini.noft2)*100):5:1,'% (',temp.strat_agents[ii]:3,')'); normvideo; end; end; if (temp.gen<=2)and(not ini.output) then begin // displays short summary if screen output is not activated gotoxy(1,1);write('initial: ',(temp.initial/100):0:2,' (',(ini.initial[1]/100):0:2,' --> ',(ini.initial[2]/100):0:2,')'); gotoxy(1,2);write('forget: ',(temp.forget/100):0:2,' (',(ini.forget[1]/100):0:2,' --> ',(ini.forget[2]/100):0:2,')'); gotoxy(1,3);write('run: ',temp.run,'/',ini.runs); end; clear_mem; if agent_order<>nil then begin while agent_order^.prev<>nil do agent_order:=agent_order^.prev; if agent_order^.next<>nil then repeat agent_order^.agent:=nil; agent_order:=agent_order^.next; dispose(agent_order^.prev); agent_order^.prev:=nil; until agent_order^.next=nil; agent_order^.agent:=nil; dispose(agent_order); agent_order:=nil; min_to:=nil; max_to:=nil; end; check_for_new_run_and_create:=complete; end; function strat_prob(prob12:byte;player,partner:p_agent):boolean; // probabilistic strategies var i: byte; fm,cc,cd,dc,dd: byte; b1: boolean; d: word; // distance last_move: p_move; begin case prob12 of // assigns values of probabilistic strategies to temporary variables 1: begin fm:=ini.prob1_firstmove; cc:=ini.prob1_cc; cd:=ini.prob1_cd; dc:=ini.prob1_dc; dd:=ini.prob1_dd; end; 2: begin fm:=ini.prob2_firstmove; cc:=ini.prob2_cc; cd:=ini.prob2_cd; dc:=ini.prob2_dc; dd:=ini.prob2_dd; end; end; if ini.me_mode=1 then d:=0 else d:=1; // d = distance to last moves; increments (+1..n) if me_mode=1 (partner-wise memory error); remains 1 with me_mode=2 (fixed memory error) if player^.lastmoves<>nil then begin // if agent has played at least once if player^.lastmoves^.next<>nil then repeat player^.lastmoves:=player^.lastmoves^.next; until player^.lastmoves^.next=nil; last_move:=player^.lastmoves; if player^.lastmoves^.prev<>nil then begin // if agent played more than once b1:=false; repeat if (ini.me_mode=1) then inc(d); // increments distance if me_mode=1 (partner-wise memory error) if player^.lastmoves^.partner=partner then begin // checks whether a partner in the agent's list of past interactions is the current partner i:=random(101); // draws random number between 0-100 case player^.lastmoves^.move of // checks last common move and decides about next move true: case memory_error(player^.lastmoves^.pmove,d) of true: if i<=cc then strat_prob:=true else strat_prob:=false; // cooperation after cc (player: cooperate; partner: cooperate) false: if i<=cd then strat_prob:=true else strat_prob:=false; // cooperation after cd (player: cooperate; partner: defect) end; false: case memory_error(player^.lastmoves^.pmove,d) of true: if i<=dc then strat_prob:=true else strat_prob:=false; // cooperation after dc (player: defect; partner: cooperate) false: if i<=dd then strat_prob:=true else strat_prob:=false; // cooperation after cc (player: defect; partner: defect) end; end; b1:=true; // exit criterion for repeat-until loop end; player^.lastmoves:=player^.lastmoves^.prev; until (b1) or (player^.lastmoves=nil); player^.lastmoves:=last_move; if (not b1) then begin // if agent has never played with current partner i:=random(101); if i<=fm then strat_prob:=true else strat_prob:=false; end; end else begin // if agent only played once if player^.lastmoves^.partner=partner then begin // if last partner was current partner (only possible in random interaction pattern) i:=random(101); case player^.lastmoves^.move of true: case memory_error(player^.lastmoves^.pmove,1) of true: if i<=cc then strat_prob:=true else strat_prob:=false; false: if i<=cd then strat_prob:=true else strat_prob:=false; end; false: case memory_error(player^.lastmoves^.pmove,1) of true: if i<=dc then strat_prob:=true else strat_prob:=false; false: if i<=dd then strat_prob:=true else strat_prob:=false; end; end; end else begin // if agent has never played with current partner i:=random(101); if i<=fm then strat_prob:=true else strat_prob:=false; end; end; end else begin // if agent has never played before i:=random(101); if i<=fm then strat_prob:=true else strat_prob:=false; end; end; function strat_random:boolean; // random strategy var i: byte; begin i:=random(2); // (0/1) if i=0 then strat_random:=false else strat_random:=true; end; function strat_grim(player,partner:p_agent):boolean; // grim strategy var b1,b2: boolean; d: word; // distance last_move: p_move; begin if ini.me_mode=1 then d:=0 else d:=1; // d = distance to last moves; increments (+1..n) if me_mode=1 (partner-wise memory error); remains 1 with me_mode=2 (fixed memory error) if player^.lastmoves<>nil then begin // if agent has played at least once if player^.lastmoves^.next<>nil then repeat player^.lastmoves:=player^.lastmoves^.next; until player^.lastmoves^.next=nil; last_move:=player^.lastmoves; if player^.lastmoves^.prev<>nil then begin // if agent played more than once b1:=false;b2:=false; repeat if (ini.me_mode=1) then inc(d); if player^.lastmoves^.partner=partner then begin // checks whether a partner in the agent's list of past interactions is the current partner if memory_error(player^.lastmoves^.pmove,d) then begin // if the (incorrectly) remembered partner's move was "cooperate" if not player^.lastmoves^.move then b1:=true else b2:=true; // if own last move was "defect", b1 becomes "true"; otherwise, b2 becomes "true" end else b1:=true; // if the (incorrectly) remembered partner's move was "defect", b1 becomes "true" end; player^.lastmoves:=player^.lastmoves^.prev; until (b1) or (b2) or (player^.lastmoves=nil); strat_grim:=not b1; player^.lastmoves:=last_move; end else begin // if agent only played once if player^.lastmoves^.partner=partner then begin // if last partner was current partner (only possible in random interaction pattern) if not memory_error(player^.lastmoves^.pmove,1) then strat_grim:=false else strat_grim:=true; end else strat_grim:=true; // if agent has never played with partner, then cooperate end; end else strat_grim:=true; // if agent has never played before, then cooperate end; function strat_ctft(player,partner:p_agent):boolean; // strategy contrite tit-for-tat var b1,b2,b3: boolean; i: byte; d: word; // distance last_move: p_move; begin if ini.me_mode=1 then d:=0 else d:=1; // d = distance to last moves; increments (+1..n) if me_mode=1 (partner-wise memory error); remains 1 with me_mode=2 (fixed memory error) if player^.lastmoves<>nil then begin // if agent has played at least once if player^.lastmoves^.next<>nil then repeat // if agent played more than once player^.lastmoves:=player^.lastmoves^.next; until player^.lastmoves^.next=nil; last_move:=player^.lastmoves; if player^.lastmoves^.prev<>nil then begin i:=0; b1:=false; b2:=false; b3:=false; repeat if (ini.me_mode=1) then inc(d); if player^.lastmoves^.partner=partner then begin // checks whether a partner in the agent's list of past interactions is the current partner inc(i); case i of 1: if memory_error(player^.lastmoves^.pmove,d) then b1:=true; // last interaction between agent and partner 2: if player^.lastmoves^.move then b2:=true; // second-to-last interaction 3: if ((not b1)and(not b2)) then if memory_error(player^.lastmoves^.pmove,d) then b3:=true; // third-to-last interaction end; end; player^.lastmoves:=player^.lastmoves^.prev; until (i=3) or (b1) or (player^.lastmoves=nil); player^.lastmoves:=last_move; if ((not b1)and(i=2)and(b2))or((i=1)and(not b1))or((i=3)and(not b3)) then strat_ctft:=false else strat_ctft:=true; // with 0 interactions: cooperate // with 1 interaction: if partner defected, then defect; otherwise, cooperate // with 2 interactions: if partner defected in last interaction and agent cooperated in second-to-last interaction, then defect; otherwise, cooperate // with 3 interactions: if partner defected in last interaction, agent defected in second-to-last interaction, and partner cooperated in third-to-last, then cooperate; otherwise, defect end else begin // if agent only played once if player^.lastmoves^.partner=partner then begin // if last partner was current partner (only possible in random interaction pattern) if memory_error(player^.lastmoves^.pmove,1) then strat_ctft:=true else strat_ctft:=false; // if the (incorrectly) remembered partner's move was "cooperate" then cooperate; otherwise, defect end else strat_ctft:=true; // if agent has never played with partner: cooperate end; end else strat_ctft:=true; // if agent has never played before: cooperate end; function strat_tft(player,partner:p_agent):boolean; // strategy tit-for-tat var b1,b2: boolean; last_move: p_move; d: word; // distance begin if ini.me_mode=1 then d:=0 else d:=1; // d = distance to last moves; increments (+1..n) if me_mode=1 (partner-wise memory error); remains 1 with me_mode=2 (fixed memory error) if player^.lastmoves<>nil then begin // if agent has played at least once if player^.lastmoves^.next<>nil then repeat player^.lastmoves:=player^.lastmoves^.next; until player^.lastmoves^.next=nil; last_move:=player^.lastmoves; if player^.lastmoves^.prev<>nil then begin // if agent played more than once b1:=false;b2:=false; repeat if (ini.me_mode=1) then inc(d); if player^.lastmoves^.partner=partner then begin // checks whether a partner in the agent's list of past interactions is the current partner if not memory_error(player^.lastmoves^.pmove,d) then b2:=false else b2:=true; // if the (incorrectly) remembered partner's move was "cooperate" then cooperate; otherwise, defect b1:=true; // exit criterion of repeat loop end; player^.lastmoves:=player^.lastmoves^.prev; until (b1) or (player^.lastmoves=nil); player^.lastmoves:=last_move; if (not b1)or(b2) then strat_tft:=true else strat_tft:=false; // if agent has never played with the partner or the partner's last move was "cooperate", then the agent's next move is "cooperate"; otherwise, "defect" end else begin // if agent has played only once if player^.lastmoves^.partner=partner then begin // if last partner was current partner (only possible in random interaction pattern) if not memory_error(player^.lastmoves^.pmove,1) then strat_tft:=false else strat_tft:=true; end else strat_tft:=true; // if agent has never played with partner, then cooperate end; end else strat_tft:=true; // if agent has never played before, then cooperate end; function strat_tf2t(player,partner:p_agent):boolean; // strategy tit-for-two-tat var b1,b2: boolean; i: byte; d: word; // distance last_move: p_move; begin if ini.me_mode=1 then d:=0 else d:=1; // d = distance to last moves; increments (+1..n) if me_mode=1 (partner-wise memory error); remains 1 with me_mode=2 (fixed memory error) if player^.lastmoves<>nil then begin // if agent has played at least once if player^.lastmoves^.next<>nil then repeat player^.lastmoves:=player^.lastmoves^.next; until player^.lastmoves^.next=nil; last_move:=player^.lastmoves; if player^.lastmoves^.prev<>nil then begin // if agent played more than once b1:=false;b2:=false;i:=0; repeat if (ini.me_mode=1) then inc(d); if player^.lastmoves^.partner=partner then begin // checks whether a partner in the agent's list of past interactions is the current partner inc(i); case i of 1: if not memory_error(player^.lastmoves^.pmove,d) then b1:=true; // last interaction between agent and partner 2: if not memory_error(player^.lastmoves^.pmove,d) then b2:=true; // second-to-last interaction end; end; player^.lastmoves:=player^.lastmoves^.prev; until (i=2) or (player^.lastmoves^.prev=nil); player^.lastmoves:=last_move; if (b1 and b2) then strat_tf2t:=false else strat_tf2t:=true; // if partner defected on the last move and the second-to-last move, then defect; otherwise, cooperate end else strat_tf2t:=true; // if agent has played only once, then cooperate end else strat_tf2t:=true; // if agent has never played before, then cooperate end; procedure interact; // passes through all interactions of a generation, all generations of a run, all runs of an initial value, all initial values of a forget value, and all forget values var b,exist1,exist2: boolean; i: byte; s: string; xx: real; begin temp.forget:=ini.forget[1]+1; repeat // is repeated for all forget values temp.forget:=temp.forget-1; // reduces forget parameter by 0.01 temp.initial:=ini.initial[1]+1; repeat // is repeated for all initial values clrscr; temp.initial:=temp.initial-1; // reduces initial parameter by 0.01 temp.run:=0; repeat // is repeated for all runs inc(temp.run); // increments run variable by 1 b:=true; temp.gen:=1; repeat // is repeated as long as no strategy has a proportion of 100% if temp.gen>1 then begin // if current generation is > 1 wth_gen(b); // writes data of last generation in run_data memory clear_mem; // deletes data of last generation end; setup(b); // initializes generation if temp.gen=1 then wth_gen(b); // initializes first run run_data^.cclg:=0; // sets "cooperation counter (last generation)" to 0 pair:=first_pair; repeat // is repeated for all interactions of a generation // determines next move depending on agent's strategy case pair^.player^.strat of 1: player_move:=strat_prob(1,pair^.player,pair^.partner); // probabilistic strategy (generous tit-for-tat) 2: player_move:=strat_prob(2,pair^.player,pair^.partner); // probabilistic strategy (pavlov) 3: player_move:=strat_random; // random 4: player_move:=strat_grim(pair^.player,pair^.partner); // grim 5: player_move:=strat_ctft(pair^.player,pair^.partner); // contrite tit-for-tat 6: player_move:=strat_tft(pair^.player,pair^.partner); // tit-for-tat 7: player_move:=strat_tf2t(pair^.player,pair^.partner); // tit-for-two-tat 8: player_move:=true; // allc 9: player_move:=false; // alld end; // determines next move depending on agent's strategy case pair^.partner^.strat of 1: partner_move:=strat_prob(1,pair^.partner,pair^.player); 2: partner_move:=strat_prob(2,pair^.partner,pair^.player); 3: partner_move:=strat_random; 4: partner_move:=strat_grim(pair^.partner,pair^.player); 5: partner_move:=strat_ctft(pair^.partner,pair^.player); 6: partner_move:=strat_tft(pair^.partner,pair^.player); 7: partner_move:=strat_tf2t(pair^.partner,pair^.player); 8: partner_move:=true; 9: partner_move:=false; end; inc(run_data^.icounter); // increments interaction counter of the generation (+1) if player_move then begin // if agent cooperates inc(run_data^.ccounter); // increments cooperation counter (+1) inc(run_data^.cclg); // increments cooperation counter of the possible last generation (+1) end; if partner_move then begin // same check for partner as for agent before inc(run_data^.ccounter); inc(run_data^.cclg); end; payoffs(player_move,partner_move); // calculates payoffs corresponding to agent's and partner's moves if pair^.player^.lastmoves=nil then begin new(pair^.player^.lastmoves); pair^.player^.lastmoves^.next:=nil; pair^.player^.lastmoves^.prev:=nil; end else begin while pair^.player^.lastmoves^.next<>nil do pair^.player^.lastmoves:=pair^.player^.lastmoves^.next; new(pair^.player^.lastmoves^.next); pair^.player^.lastmoves^.next^.prev:=pair^.player^.lastmoves; pair^.player^.lastmoves:=pair^.player^.lastmoves^.next; pair^.player^.lastmoves^.next:=nil; end; if pair^.partner^.lastmoves=nil then begin new(pair^.partner^.lastmoves); pair^.partner^.lastmoves^.next:=nil; pair^.partner^.lastmoves^.prev:=nil; end else begin while pair^.partner^.lastmoves^.next<>nil do pair^.partner^.lastmoves:=pair^.partner^.lastmoves^.next; new(pair^.partner^.lastmoves^.next); pair^.partner^.lastmoves^.next^.prev:=pair^.partner^.lastmoves; pair^.partner^.lastmoves:=pair^.partner^.lastmoves^.next; pair^.partner^.lastmoves^.next:=nil; end; // now stores results of this interaction pair^.player^.lastmoves^.move:=player_move; pair^.player^.lastmoves^.pmove:=partner_move; pair^.partner^.lastmoves^.move:=partner_move; pair^.partner^.lastmoves^.pmove:=player_move; pair^.player^.lastmoves^.partner:=pair^.partner; pair^.partner^.lastmoves^.partner:=pair^.player; pair^.player^.cpayoff:=pair^.player^.cpayoff+player_payoff; pair^.partner^.cpayoff:=pair^.partner^.cpayoff+partner_payoff; pair:=pair^.next; until pair=nil; // ends if all interactions of a generation are complete pair:=first_pair; agent:=first_agent; b:=false; gotoxy(1,1); inc(temp.gen); until check_for_new_run_and_create; // ends if 100% of all agents pursue the same strategy until temp.run=ini.runs; // ends if all runs are complete wtd_runs; // stores all runs on hard disc clear_all_heaps; // deletes memory // if initial parameter is not complete, creates new files in which to store data later if temp.initial>ini.initial[2] then begin i:=1; xx:=temp.initial-1; if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(xx/100,2)+'i_' +real2str(temp.forget/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int'; filename_statistics:=filename_run+'_stat.txt'; filename_run:=filename_run+'.txt'; {$I-} repeat assign(f_run,'data\'+filename_run); reset(f_run); if ioresult<>0 then exist1:=false else exist1:=true; if not exist1 then begin assign(f_statistics,'statistics\'+filename_statistics); reset(f_statistics); if ioresult<>0 then exist2:=false else exist2:=true; end; if (exist1)or(exist2) then begin if exist1 then close(f_run); if exist2 then close(f_statistics); inc(i); if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(xx/100,2)+'i_' +real2str(temp.forget/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int'; filename_statistics:=filename_run+'_stat_('+int2str(i)+').txt'; filename_run:=filename_run+'_('+int2str(i)+').txt'; end; until (not exist1)and(not exist2); rewrite(f_run); close(f_run); rewrite(f_statistics); close(f_statistics); end; until temp.initial=ini.initial[2]; // ends if initial parameter has reached the user-defined value // if forget parameter is not complete, creates new files in which to store data later if temp.forget>ini.forget[2] then begin i:=1; xx:=temp.forget-1; if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(ini.initial[1]/100,2)+'i_' +real2str(xx/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int'; filename_statistics:=filename_run+'_stat.txt'; filename_run:=filename_run+'.txt'; {$I-} repeat assign(f_run,'data\'+filename_run); reset(f_run); if ioresult<>0 then exist1:=false else exist1:=true; if not exist1 then begin assign(f_statistics,'statistics\'+filename_statistics); reset(f_statistics); if ioresult<>0 then exist2:=false else exist2:=true; end; if (exist1)or(exist2) then begin if exist1 then close(f_run); if exist2 then close(f_statistics); inc(i); if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(ini.initial[1]/100,2)+'i_' +real2str(xx/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int'; filename_statistics:=filename_run+'_stat_('+int2str(i)+').txt'; filename_run:=filename_run+'_('+int2str(i)+').txt'; end; until (not exist1)and(not exist2); rewrite(f_run); close(f_run); rewrite(f_statistics); close(f_statistics); end; until temp.forget=ini.forget[2]; // ends if forget parameter reaches user-defined value end; procedure load_ini_file; // reads ini file, if existent; otherwise, determines default values var i: byte; x: word; xx: double; s,s2: string; exist1,exist2,exist3: boolean; begin directory:=''; exist1:=false; if paramcount<>0 then begin s:=paramstr(1); {$I-} assign(f_ini,s); reset(f_ini); if ioresult<>0 then begin writeln('Can''t read initialisation file.'); write('Press any key to continue with standard settings...'); keypressed; end else begin exist1:=true; while (not eof(f_ini) and (exist1)) do begin readln(f_ini,s); readln(f_ini,s2); x:=str2int(s2); if (s='directory_name') then begin directory:=s2; end; if (s='blocked_interaction')then begin if s2='on' then ini.blocked:=true else if s2='off' then ini.blocked:=false else exist1:=false; end; if (s='number_of_agents') then begin if x<>65432 then ini.noft:=x else exist1:=false; end; if (s='number_of_interaction_partners') then begin if x<>65432 then ini.noip:=x else exist1:=false; end; if (s='number_of_interactions_with_partner') then begin if x<>65432 then ini.noiwp:=x else exist1:=false; end; if (s='mutation') then begin xx:=str2real(s2); if xx<>65432 then ini.mutation:=round(xx*(c_mutationrange-1)) else exist1:=false; end; if (s='memory_error_mode') then begin if s2='partner-wise' then ini.me_mode:=1 else if s2='fixed' then ini.me_mode:=2 else exist1:=false; end; if (s='memory_error_initial_start') then begin xx:=str2real(s2); if xx<>65432 then ini.initial[1]:=round(xx*100) else exist1:=false; end; if (s='memory_error_initial_end') then begin xx:=str2real(s2); if xx<>65432 then ini.initial[2]:=round(xx*100) else exist1:=false; end; if (s='memory_error_forget_start') then begin xx:=str2real(s2); if xx<>65432 then ini.forget[1]:=round(xx*100) else exist1:=false; end; if (s='memory_error_forget_end') then begin xx:=str2real(s2); if xx<>65432 then ini.forget[2]:=round(xx*100) else exist1:=false; end; if (s='runs') then begin if x<>65432 then ini.runs:=x else exist1:=false; end; if (s='output_on_screen') then begin if s2='on' then ini.output:=true else if s2='off' then ini.output:=false else exist1:=false; end; if (s='gtft_first_move') then begin if x<>65432 then ini.prob1_firstmove:=x else exist1:=false; end; if (s='gtft_cc') then begin if x<>65432 then ini.prob1_cc:=x else exist1:=false; end; if (s='gtft_cd') then begin if x<>65432 then ini.prob1_cd:=x else exist1:=false; end; if (s='gtft_dc') then begin if x<>65432 then ini.prob1_dc:=x else exist1:=false; end; if (s='gtft_dd') then begin if x<>65432 then ini.prob1_dd:=x else exist1:=false; end; if (s='pavlov_first_move') then begin if x<>65432 then ini.prob2_firstmove:=x else exist1:=false; end; if (s='pavlov_cc') then begin if x<>65432 then ini.prob2_cc:=x else exist1:=false; end; if (s='pavlov_cd') then begin if x<>65432 then ini.prob2_cd:=x else exist1:=false; end; if (s='pavlov_dc') then begin if x<>65432 then ini.prob2_dc:=x else exist1:=false; end; if (s='pavlov_dd') then begin if x<>65432 then ini.prob2_dd:=x else exist1:=false; end; end; if not exist1 then begin writeln('Can''t read initialisation file.'); writeln('line: ',s,' - content: ',s2); write('Press return to continue with standard settings...'); readln; end; if ini.initial[1]0)or(ini.forget[2]<>0)) then begin writeln; writeln('Forget parameter is no object in fixed interaction pattern.'); write('Press return to continue with forget=0.0'); readln; ini.forget[1]:=0; ini.forget[2]:=0; end; strat_name[1]:='gtft '; strat_name[2]:='pavlov '; strat_name[3]:='random '; strat_name[4]:='grim '; strat_name[5]:='contrite tft'; strat_name[6]:='tft '; strat_name[7]:='tf2t '; strat_name[8]:='allc '; strat_name[9]:='alld '; ini.noft2:=ini.noft; if ((ini.noft*ini.noip) mod 2) > 0 then dec(ini.noft); // if number of agents * number of interaction partners cannot be divided by two, one randomly chosen agent is not available for one generation, e.g., 99 agents, 5 interaction partners i:=1; {$I-} if directory<>'' then begin chdir(directory); if ioresult<>0 then begin mkdir(directory); chdir(directory); end; end; chdir('data'); if ioresult<>0 then mkdir('data') else chdir('..'); chdir('statistics'); if ioresult<>0 then mkdir('statistics') else chdir('..'); if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; filename_statistics_all:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_'// mutation +real2str(ini.initial[1]/100,2)+'i_'// initial +real2str(ini.forget[1]/100,2)+'f_'// forget +int2str(ini.noft2)+'g_'// grid +int2str(ini.noip)+'p_' // partners +int2str(ini.noiwp)+'int';// interactions filename_statistics:=filename_run+'_stat.txt'; filename_statistics_all:=filename_statistics_all+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(ini.initial[1]/100,2)+'-'+real2str(ini.initial[2]/100,2)+'i_' +real2str(ini.forget[1]/100,2)+'-'+real2str(ini.forget[2]/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int_overall.txt'; filename_run:=filename_run+'.txt'; repeat filename_run:='data\'+filename_run; assign(f_run,filename_run); reset(f_run); if ioresult<>0 then exist1:=false else exist1:=true; if not exist1 then begin filename_statistics:='statistics\'+filename_statistics; assign(f_statistics,filename_statistics); reset(f_statistics); if ioresult<>0 then exist2:=false else exist2:=true; end; if (not exist1)and(not exist2) then begin filename_statistics_all:=filename_statistics_all; assign(f_statistics_all,filename_statistics_all); reset(f_statistics_all); if ioresult<>0 then exist3:=false else exist3:=true; end; if (exist1)or(exist2)or(exist3) then begin if exist1 then close(f_run); if exist2 then close(f_statistics); if exist3 then close(f_statistics_all); inc(i); if ini.blocked then s:='TRUE' else s:='FALSE'; filename_run:='block'+s; filename_statistics_all:='block'+s; if ini.me_mode=1 then s:='pw' else s:='fx'; filename_run:=filename_run+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(ini.initial[1]/100,2)+'i_' +real2str(ini.forget[1]/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int'; filename_statistics:=filename_run+'_stat_('+int2str(i)+').txt'; filename_run:=filename_run+'_('+int2str(i)+').txt'; filename_statistics_all:=filename_statistics_all+'_'+s +'_' +real2str(ini.mutation/(c_mutationrange-1),3)+'m_' +real2str(ini.initial[1]/100,2)+'-'+real2str(ini.initial[2]/100,2)+'i_' +real2str(ini.forget[1]/100,2)+'-'+real2str(ini.forget[2]/100,2)+'f_' +int2str(ini.noft2)+'g_' +int2str(ini.noip)+'p_' +int2str(ini.noiwp)+'int_overall_('+int2str(i)+').txt' end; until (not exist1)and(not exist2)and(not exist3); rewrite(f_run); close(f_run); rewrite(f_statistics); close(f_statistics); rewrite(f_statistics_all); close(f_statistics_all); if not ini.output then writeln('Please wait....'); end; begin {$I-} clrscr; agent:=nil; pair:=nil; load_ini_file; setup(true); interact; write('Press any key to finish. '); readkey; writeln; {$I+} end.