program Propensity_maker (input, output); {This program is a "pre-addition" to the alliance simulation programmed} { by Scott Bennett for Professor Robert Axelrod.} { Program begun on February 2, 1990} { This creates a prop matrix and then outputs it in that matrix form, with row and col headers.} { Version 2.1 expands the size of names of files which can be read in.} { Version 3.1 adds additional fields for religion. It removes the previous (v3.0)} { addition of "Soviet Allegience". It also adds a "scaling factor" so that propensities} { will be bounded at +- 1000, just for output and readability purposes.} { Version 3.2 replaces "EEC" as a raw_propensity category with "Democracy". } { Otherwise it keeps all changes through v3.1. } { Version 3.21 adds scaling for numbers} { less than 10 as well as greater than 1000} { Version 3.3 takes v 3.21, drops the democracy variable, and creates a four point } { government scale, representing democracy, } { Fascist, Communist, and Royalist, none of which likes any other type. } { Version 3.31 takes v3.3 and modifies the like/dislike values for govt type. Here,} { F-C=1.5;D-C and D-F = 1.0, and Royalist/other are 0 to everyone.} { Version 3.32 takes v3.31 and modifies like/dislike values. Here, F-C is 1.0, NOT 1.5} { Otherwise everything is the same as 3.31} { 12/9/91 added a filename check so the machine does not crash if user types a name} { that's not on the disk from the application version.} const version = 3.32; max_countries = 40; max_conflicts = 20; catholic = 1; protestant = 2; orthodox = 3; moslem = 4; atheist = 5; other = 6; first_religion = catholic; last_religion = other; max_file_path_length = 100; comment_length = 100; file_name_length = 40; type country_type = record name: string[8]; size: real; ethnic: array[1..max_conflicts] of integer; num_ethnic: integer; border: array[1..max_conflicts] of integer; num_border: integer; war_history: array[1..max_conflicts] of integer; num_war: integer; religion: array[first_religion..last_religion] of real; govt: 0..4; {govt. will be on a 1-3 scale, or 0 if N/A. } { 1 is democracy, 2 is fascist, 3 is communist, 4 is Royalist} end; country_array_type = array[1..max_countries] of country_type; prop_matrix_type = array[1..max_countries, 1..max_countries] of real; filenametype = string[file_name_length]; filepathtype = string[max_file_path_length]; comment_type = string[comment_length]; main_comment_type = record num_lines: integer; lines: array[1..25] of comment_type; end; alliance_rep_type = array[1..max_countries] of integer; var scale_factor: real; country_array: country_array_type; propensity_matrix: prop_matrix_type; infile, outfile: text; num_countries: integer; inputfilename, outputfilename: filenametype; run_file_name, history_file_name: filepathtype; main_comment: main_comment_type; mainrect: rect; starting_alliance: alliance_rep_type; have_starting_alliance: boolean; { --------------------------------------------------------------- } function intpower (num: longint; power: longint): longint; begin if num = 0 then intpower := 0 else if power = 0 then intpower := 1 else intpower := round(exp(power * (ln(num)))); end; {function realpower} { --------------------------------------------------------------- } function realpower (num: real; power: real): real; begin if num = 0 then realpower := 0 else if power = 0 then realpower := 1 else realpower := exp(power * (ln(num))); end; {function realpower} { --------------------------------------------------------------- } function maximum (num1, num2: real): real; {returns the larger of two entered reals} {or the first if they are equal} begin if num1 >= num2 then maximum := num1 else {num2 > num1)} maximum := num2; end; { --------------------------------------------------------------- } procedure read_a_line (var afile: text; var aline: comment_type); {reads one line, stops at eoln or eof. If stops at eoln, reads next line} var currentstringmarker: integer; achar: char; begin currentstringmarker := 1; aline := ''; achar := ' '; if not eof(afile) then while not eoln(afile) and (achar = ' ') do read(afile, achar); {read any initial spaces - stop at first char.} aline := concat(aline, achar); if not eof(afile) then begin while (not eoln(afile)) and (currentstringmarker <= comment_length) do begin read(afile, achar); aline := concat(aline, achar); currentstringmarker := currentstringmarker + 1; if eof(afile) then leave; {exit this while loop if get to eof} if (currentstringmarker > comment_length) then writeln('A line was too long. Max comment line length is ', comment_length, ' characters. Line truncated'); end; readln(afile); end; end; {proc read a line} { ------------------------------------------------------------ } procedure write_output_data (country_array: country_array_type; propensity_matrix: prop_matrix_type; var outfile: text; inputfilename, outputfilename: filenametype; main_comment: main_comment_type; run_file_name, history_file_name: filepathtype; have_starting_alliance: boolean; starting_alliance: alliance_rep_type; soviet_weight: real); var x, y: integer; datetime: datetimerec; line: comment_type; datafile: text; achar: char; asterisk_line: integer; begin writeln('The calculated propensity matrix is : '); writeln; write(' '); for x := 1 to num_countries do write(x : 6); writeln; writeln; for x := 1 to num_countries do begin write(x : 2, ' ', country_array[x].name : 8, chr(9)); for y := 1 to num_countries do begin write(propensity_matrix[x, y] : 10 : 6); end; {for y} writeln; writeln; end; {for x} writeln('Scale factor is ', scale_factor); writeln; writeln; rewrite(outfile, outputfilename); writeln(outfile, 'This is a file of propensity data for the alliance sim program '); gettime(datetime); write(outfile, ' File created ', datetime.month : 2, '/', datetime.day : 2, '/', datetime.year : 4, ' at ', datetime.hour : 2, ':'); if datetime.minute < 10 then write(outfile, '0'); writeln(outfile, datetime.minute : 2); writeln(outfile, ' This file created by Propensity_Maker,version ', version : 6 : 3, ' from input file ', inputfilename); writeln(outfile, 'After this header, there is a line of "****", followed by up to 20 comment lines which '); writeln(outfile, ' will appear in the output of Alliance_Sim. These comment lines are ended by another line of "****".'); writeln(outfile, 'After that second line of "****" comes the data. '); writeln(outfile, 'First line of data is path to run_number_file; second line is path to history_file.'); writeln(outfile, 'Third line is number of countries, then that many lines of country labels, '); writeln(outfile, ' then a line which is simply #s which are column headers for the prop matrix'); writeln(outfile, ' then number_of_country lines which are the prop matrix. Each has an index # on the left'); writeln(outfile, ' then propensities with the other countries, in order. After the matrix is another line of ****'); writeln(outfile, ' then either an initial configuration or a blank line, then ****, then the original input data (if any).'); {Those were 12 header lines} writeln(outfile, '****************************************'); for x := 1 to main_comment.num_lines do writeln(outfile, main_comment.lines[x]); writeln(outfile, 'Scaling Factor for propensities was ', scale_factor : 15 : 5); writeln(outfile, '****************************************'); writeln(outfile, '"', run_file_name, '"'); writeln(outfile, '"', history_file_name, '"'); writeln(outfile, num_countries); for x := 1 to num_countries do writeln(outfile, country_array[x].name : 8); {I attempted to format this so that it would look good in the prop file. However, after a lot of playing, I have decided} {that it is not worth the time to make it look that way in the prop file. It is more important to preserve } {as many digits of accuracy while fitting data onto a lines. Since it is rare to look at any .prop file} {this should be OK. Data is formatted for the Word style sheets, however. } write(outfile, chr(9), chr(9), chr(9)); for x := 1 to num_countries do write(outfile, x : 3, chr(9)); {write headers with 8 spaces} writeln(outfile); for x := 1 to num_countries do begin write(outfile, chr(9), x : 2, chr(9), ' ' : 8, chr(9)); for y := 1 to num_countries do write(outfile, propensity_matrix[x, y] : 14 : 9); writeln(outfile); end; writeln(outfile, '****************************************'); {Now output initial alliance configuration} if have_starting_alliance = true then begin for x := 1 to num_countries do write(outfile, starting_alliance[x] : 1); end; writeln(outfile); {Even if there is not an initial config, want a blank line} writeln(outfile, '****************************************'); {then another separator} {Now output initial conflict data} writeln(outfile, '# ', chr(9), ' Name ', chr(9), ' Size ', chr(9), ' Ethnic_ ', chr(9), ' Border_ ', chr(9), ' War_ ', chr(9), ' Proportion ', chr(9), chr(9), chr(9), chr(9), chr(9), ' Govt', chr(9)); writeln(outfile, chr(9), chr(9), chr(9), ' Conflict ', chr(9), ' Conflict ', chr(9), ' History ', chr(9), ' Cath ', chr(9), ' Prot', chr(9), ' Orth', chr(9), ' Musl', chr(9), 'Ath', chr(9), 'Othr', chr(9), ' Type', chr(9)); writeln(outfile, ' ----------------------------------------------------------------- '); for x := 1 to num_countries do {write one line of original conflict data for each country} begin write(outfile, x : 1, chr(9), ' ', country_array[x].name : 8, ' ', chr(9), country_array[x].size : 8 : 4, ' ', chr(9)); for y := 1 to country_array[x].num_ethnic do begin write(outfile, country_array[x].ethnic[y] : 1); if y < country_array[x].num_ethnic then write(outfile, ','); end; if country_array[x].num_ethnic = 0 then write(outfile, '0'); write(outfile, chr(9)); for y := 1 to country_array[x].num_border do begin write(outfile, country_array[x].border[y] : 1); if y < country_array[x].num_border then write(outfile, ','); end; if country_array[x].num_border = 0 then write(outfile, '0'); write(outfile, chr(9)); for y := 1 to country_array[x].num_war do begin write(outfile, country_array[x].war_history[y] : 1); if y < country_array[x].num_war then write(outfile, ','); end; if country_array[x].num_war = 0 then write(outfile, '0'); write(outfile, chr(9)); for y := first_religion to last_religion do write(outfile, country_array[x].religion[y] : 6 : 3, chr(9)); write(outfile, country_array[x].govt : 3); writeln(outfile); end; {for x 1 to num countries} close(outfile); end; {procedure write output data} { ------------------------------------------------------------ } procedure read_input_data (var country_array: country_array_type; var datafile: text; var inputfilename, outputfilename: filenametype; var main_comment: main_comment_type; var run_file_name, history_file_name: filepathtype; var have_starting_alliance: boolean; var starting_alliance: alliance_rep_type); var x: integer; acountry: integer; anum: integer; charread: char; currentstringmarker: integer; acomment: comment_type; alliance_spot: integer; {------------------------- } procedure read_one_country (var country: country_type; var datafile: text); var anum: integer; areal: real; atnextvalue, atnextconflict: boolean; achar: char; x: integer; begin read(datafile, anum); {first field is just an index number} achar := ' '; while (achar = ' ') or (achar = chr(9)) do read(datafile, achar); country.name := ''; x := 1; while (x <= 8) and (achar <> ' ') and (achar <> chr(9)) do begin country.name := concat(country.name, achar); read(datafile, achar); x := x + 1; end; read(datafile, country.size); country.num_ethnic := 0; read(datafile, anum); if anum <> 0 then {this is a conflict} begin atnextconflict := false; repeat atnextvalue := false; {next value within this conflict} country.num_ethnic := country.num_ethnic + 1; country.ethnic[country.num_ethnic] := anum; read(datafile, achar); {read next char to check to see if more input} if achar = ',' then {there should be more input, so want to repeat the loop} begin read(datafile, anum); {This is ok in case of comma-space-next value} end else if (achar = ' ') or (achar = chr(9)) then {There might be more input -- look for comma} begin repeat {look at the next character -- datafile^ contains this } if datafile^ = ',' then {there is more input, so want to keep reading - read comma and next value} begin read(datafile, achar); {read the comma} if achar <> ',' then writeln('program error achar not a comma'); read(datafile, anum); {read the next number and go back to assign} atnextvalue := true; end else if (datafile^ = ' ') or (datafile^ = chr(9)) then begin {advance datafile^ to the next character} get(datafile); end else if (datafile^ >= '0') and (datafile^ <= '9') then begin {have reached next conflict field -- read num and go on} read(datafile, anum); atnextconflict := true; end; until (atnextvalue) or (atnextconflict) or (datafile^ = ','); end; until (atnextconflict) or ((not (atnextconflict)) and (country.num_ethnic = max_conflicts)); if not (atnextconflict) and (country.num_ethnic = max_conflicts) then {too many conflicts} begin writeln('Error in data file -- more ethnic conflicts specified than are allowed.'); writeln(' This is a fatal error. Please reduce the number of conflicts in the data file and re-run'); HALT; end; end {anum <> 0} else {initial anum was 0} begin {do nothing with this conflict field -- but read the next conflict initial field} read(datafile, anum); end; {Now read info about border conflicts} country.num_border := 0; {starts with a value in anum already} if anum <> 0 then {this is a conflict} begin atnextconflict := false; repeat atnextvalue := false; {next value within this conflict} country.num_border := country.num_border + 1; country.border[country.num_border] := anum; read(datafile, achar); {read next char to check to see if more input} if achar = ',' then {there should be more input, so want to repeat the loop} begin read(datafile, anum); {This is ok in case of comma-space-next value} end else if (achar = ' ') or (achar = chr(9)) then {There might be more input -- look for comma} begin repeat {look at the next character -- datafile^ contains this } if datafile^ = ',' then {there is more input, so want to keep reading - read comma and next value} begin read(datafile, achar); {read the comma} if achar <> ',' then writeln('program error achar not a comma'); read(datafile, anum); {read the next number and go back to assign} atnextvalue := true; end else if (datafile^ = ' ') or (datafile^ = chr(9)) then begin {advance datafile^ to the next character} get(datafile); end else if (datafile^ >= '0') and (datafile^ <= '9') then begin {have reached next conflict field -- read num and go on} read(datafile, anum); atnextconflict := true; end; until (atnextvalue) or (atnextconflict) or (datafile^ = ','); end; until (atnextconflict) or ((not (atnextconflict)) and (country.num_border = max_conflicts)); if not (atnextconflict) and (country.num_border = max_conflicts) then {too many conflicts} begin writeln('Error in data file -- more border conflicts specified than are allowed.'); writeln(' This is a fatal error. Please reduce the number of conflicts in the data file and re-run'); HALT; end; end {anum <> 0} else {initial anum was 0} begin {do nothing with this conflict field -- but read the next conflict initial field} read(datafile, anum); end; {Now read info about war history conflicts} country.num_war := 0; {has a value for anum already} if anum <> 0 then {this is a conflict} begin atnextconflict := false; repeat atnextvalue := false; {next value within this conflict} country.num_war := country.num_war + 1; country.war_history[country.num_war] := anum; read(datafile, achar); {read next char to check to see if more input} if achar = ',' then {there should be more input, so want to repeat the loop} begin read(datafile, anum); {This is ok in case of comma-space-next value} end else if (achar = ' ') or (achar = chr(9)) then {There might be more input -- look for comma} begin repeat {look at the next character -- datafile^ contains this } if datafile^ = ',' then {there is more input, so want to keep reading - read comma and next value} begin read(datafile, achar); {read the comma} if achar <> ',' then writeln('program error achar not a comma'); read(datafile, anum); {read the next number and go back to assign} atnextvalue := true; end else if (datafile^ = ' ') or (datafile^ = chr(9)) then begin {advance datafile^ to the next character} get(datafile); end else if (datafile^ >= '0') and (datafile^ <= '9') then begin {have reached next (first religion) field -- read num (which is real) and go on} read(datafile, areal); atnextconflict := true; end; until (atnextvalue) or (atnextconflict) or (datafile^ = ','); end; until (atnextconflict) or ((not (atnextconflict)) and (country.num_war = max_conflicts)); if not (atnextconflict) and (country.num_war = max_conflicts) then {too many conflicts} begin writeln('Error in data file -- more war history conflicts specified than are allowed.'); writeln(' This is a fatal error. Please reduce the number of conflicts in the data file and re-run'); HALT; end; end {anum <> 0} else {initial anum was 0} begin {do nothing with this conflict field -- but read the religion initial field -- which is real} read(datafile, areal); end; {have the first religion value in areal} country.religion[first_religion] := areal; for x := first_religion + 1 to last_religion do read(datafile, country.religion[x]); read(datafile, country.govt); readln(datafile); {This is the last item on the line, so advance to next line} end; {proc read a country} { -------------------------- } procedure read_a_path (var afile: text; var apath: filepathtype); {reads a path enclosed in " marks} var currentstringmarker: integer; charread: char; begin currentstringmarker := 1; apath := ''; read(afile, charread); if charread = ' ' then repeat read(afile, charread) until charread <> ' '; {This allows there to be spaces at the beginning of a line} if charread <> '"' then begin writeln('Error -- filenames in data file must be enclosed in " marks. This is a fatal error -- execution ends'); writeln('Please check data file and try again. '); halt; end else read(afile, charread); while (charread <> '"') and (not eoln(afile)) and (currentstringmarker <= max_file_path_length) do begin apath := concat(apath, charread); currentstringmarker := currentstringmarker + 1; if eof(afile) then begin writeln('Unexpected end of file found. Please check the file -- more errors may occur. '); leave; {get out of the while} end else {not eof, so read} read(afile, charread); if (currentstringmarker > max_file_path_length) then begin writeln('Path name was too long for a file name. Max is ', max_file_path_length, ' characters'); writeln('This is a fatal error. Program won t be able to find file . Execution ends. Check data file path and re run '); halt; end; end; readln(afile); end; {proc read a path} {------------------------------------------ } begin {proc read_input_data} {Section added for input file name check.} iocheck(false); mainrect.top := 40; mainrect.bottom := 450; mainrect.left := 5; mainrect.right := 630; SetTextRect(mainrect); ShowText; writeln('What input file do you want to use? '); write('Maximum ', file_name_length, ' chars , please: '); inputfilename := ' '; readln(inputfilename); writeln; writeln('What output file do you want to write to?'); write('Maximum ', file_name_length, ' chars, please: '); outputfilename := ' '; readln(outputfilename); writeln; reset(datafile, inputfilename); case (ioresult) of -43, 17, 19, 21, 24: begin writeln('File error opening the main input file. '); writeln('This is a fatal error. Check file name and try again '); halt; end; otherwise begin writeln('File opened OK.'); end; end; {case} {the following lines all read in initial variables from external file} for x := 1 to 2 do readln(datafile); {first 2 lines are header lines} {now read a line of ***** } read_a_line(datafile, acomment); if (acomment[1] <> '*') and (acomment[2] <> '*') then begin writeln('Error in datafile. Third line was not a line of "****" as required. This is a fatal error. '); writeln(' Please check datafile and re run'); halt; end; {read the included descriptive comment lines} Main_comment.num_lines := 0; repeat main_comment.num_lines := main_comment.num_lines + 1; read_a_line(datafile, Main_comment.lines[main_comment.num_lines]); until (Main_comment.lines[main_comment.num_lines][1] = '*') and (Main_comment.lines[main_comment.num_lines][2] = '*') or (main_comment.num_lines > 25); if (main_comment.num_lines >= 25) and (Main_comment.lines[main_comment.num_lines][1] <> '*') and (Main_comment.lines[main_comment.num_lines][2] <> '*') then begin writeln('Problem reading input file. Did not see "**" within 25 lines of comment beginning'); writeln(' This is a fatal error -- execution ends. Check data file and re-run.'); halt; end; main_comment.num_lines := main_comment.num_lines - 1; {get the line of ***** out of the list} {now read path to run number and history file } read_a_path(datafile, Run_File_Name); read_a_path(datafile, history_file_name); {after paths, get # countries} read(datafile, num_countries); readln(datafile); if (num_countries < 2) then begin writeln('The number of countries specified in the input file was less than 2'); writeln('This number must be greater than or equal to 2 for the program to execute.'); writeln('This is a fatal error. Please check the data file and re-run'); HALT; end; if (num_countries > max_countries) then begin writeln('The number of countries specified in the data file was more than the maximum allowed'); writeln('The maximum number of countries allowed by the program is ', max_countries : 3); writeln('This is a fatal error. Please modify the data file and re-run'); HALT; end; have_starting_alliance := false; read_a_line(datafile, acomment); {this should be the line of initial config, or blank. Check if there...} currentstringmarker := 1; while (currentstringmarker < length(acomment)) and ((acomment[currentstringmarker] <> '0') and (acomment[currentstringmarker] <> '1')) do currentstringmarker := currentstringmarker + 1; {read until see 0 or 1, or get to end of line read} if (acomment[currentstringmarker] = '0') or (acomment[currentstringmarker] = '1') then begin have_starting_alliance := true; alliance_spot := 1; starting_alliance[alliance_spot] := ord(acomment[currentstringmarker]) - 48; currentstringmarker := currentstringmarker + 1; repeat while (currentstringmarker < length(acomment)) and ((acomment[currentstringmarker] <> '0') and (acomment[currentstringmarker] <> '1')) do currentstringmarker := currentstringmarker + 1; {again, read until see 0 or 1, or get to end of line read} alliance_spot := alliance_spot + 1; starting_alliance[alliance_spot] := ord(acomment[currentstringmarker]) - 48; currentstringmarker := currentstringmarker + 1; until (alliance_spot = num_countries) or (currentstringmarker > length(acomment)); if alliance_spot <> num_countries then {exited abnormally} begin writeln('Tried to read an alliance config from raw data file, but couldnt . '); writeln('This run is therefore not outputting any alliance configuration to the propensity file.'); have_starting_alliance := false; end; end; read_a_line(datafile, acomment); {this should be a line of ****} if (acomment[1] <> '*') and (acomment[2] <> '*') then begin writeln('Error in datafile. Line after initial config or blank was not a line of "****" as required. This is a fatal error. '); writeln(' Please check datafile and re run'); halt; end; for x := 1 to 4 do readln(datafile); {this reads next 4 comment lines} for acountry := 1 to num_countries do begin read_one_country(country_array[acountry], datafile); end; close(datafile); end; { ------------------------------------------------------------ } procedure calculate_propensities (country_array: country_array_type; var propensity_matrix: prop_matrix_type; var scale_factor: real); var country2_spot: integer; country1, country2: integer; areligion, christian_religion: integer; power, x, y: integer; biggest_dev, largest_size, smallest_size: real; begin for country1 := 1 to num_countries do {init the array to 0s} for country2 := 1 to num_countries do propensity_matrix[country1, country2] := 0; for country1 := 1 to num_countries do begin propensity_matrix[country1, country1] := 1; {diagonal is 1} {make ethnic conflicts between country1 and those on the ethnic list := -1} for country2_spot := 1 to country_array[country1].num_ethnic do propensity_matrix[country1, country_array[country1].ethnic[country2_spot]] := propensity_matrix[country1, country_array[country1].ethnic[country2_spot]] + (-1); {make border conflicts between country1 and those on the border list := -1} for country2_spot := 1 to country_array[country1].num_border do propensity_matrix[country1, country_array[country1].border[country2_spot]] := propensity_matrix[country1, country_array[country1].border[country2_spot]] + (-1); {make war conflicts between country1 and those on the war-history list := -1} for country2_spot := 1 to country_array[country1].num_war do propensity_matrix[country1, country_array[country1].war_history[country2_spot]] := propensity_matrix[country1, country_array[country1].war_history[country2_spot]] + (-1); end; {for country 1} {Previous did the values which can be gotten directly off the array lists. } {Now do religion, which must be done by direct comparison} for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do begin {for religion, mult 2 countries rel values * the "payoff" for 2 rels} {first, effects of liking the same. This should not include "Other" that are neutral} for areligion := first_religion to last_religion do propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + (country_array[country1].religion[areligion] * country_array[country2].religion[areligion] * 1); {That did ALL liking same in other country. . Now drop "other".} propensity_matrix[country1, country2] := propensity_matrix[country1, country2] - (country_array[country1].religion[other] * country_array[country2].religion[other] * 1); {next, calculate the effects on being on opposite sides of the c/m division} for christian_religion := catholic to orthodox do begin propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + (country_array[country1].religion[christian_religion] * country_array[country2].religion[moslem] * (-1)); propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + (country_array[country1].religion[moslem] * country_array[country2].religion[christian_religion] * (-1)); end; {next, calculate the effects of being on opposited sides of the (chr or mos)/atheist division} for areligion := catholic to moslem do {This is 1 to 4; ath is 5} begin propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + (country_array[country1].religion[areligion] * country_array[country2].religion[atheist] * (-1)); propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + (country_array[country1].religion[atheist] * country_array[country2].religion[areligion] * (-1)); end; end; {for country 1 and 2} {Now do govt, which requires comparison between all country pairs} {Formula is 1 if same govt type, 0 (don't add anything) if can't tell one of them, -1 For D/c and D/f } {, and -1.5 for c/f. Also, type 4 also cares nothing about govt type and others don't care about type 4} { 1 is dem, 2 is fascist, 3 is communist, 4 is royalist (these values from what listed in TYPE above)} for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do begin if (country_array[country1].govt <> 0) and (country_array[country2].govt <> 0) and (country_array[country1].govt <> 4) and (country_array[country2].govt <> 4) then begin if country_array[country1].govt = country_array[country2].govt then propensity_matrix[country1, country2] := propensity_matrix[country1, country2] + 1 else if ((country_array[country1].govt = 1) and (country_array[country2].govt = 2)) or ((country_array[country2].govt = 1) and (country_array[country1].govt = 2)) then propensity_matrix[country1, country2] := propensity_matrix[country1, country2] - 1 else if ((country_array[country1].govt = 1) and (country_array[country2].govt = 3)) or ((country_array[country2].govt = 1) and (country_array[country1].govt = 3)) then propensity_matrix[country1, country2] := propensity_matrix[country1, country2] - 1 else if ((country_array[country1].govt = 2) and (country_array[country2].govt = 3)) or ((country_array[country2].govt = 2) and (country_array[country1].govt = 3)) then propensity_matrix[country1, country2] := propensity_matrix[country1, country2] - 1; end; {if both not 0} end; {for country1, country2} {now have completed raw propensity, so multiply by sizes for final value} largest_size := 0; smallest_size := 0; for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do begin propensity_matrix[country1, country2] := propensity_matrix[country1, country2] * (country_array[country1].size * country_array[country2].size); if propensity_matrix[country1, country2] > largest_size then largest_size := propensity_matrix[country1, country2]; if propensity_matrix[country1, country2] < smallest_size then smallest_size := propensity_matrix[country1, country2]; end; {Now adjust size by a transformation to reduce it to numbers which are < 1000 in abs value} {[added 5/8/91] and > 10.0 in value} biggest_dev := maximum(largest_size, abs(smallest_size)); power := 1; while realpower(10, power) < biggest_dev do power := power + 1; power := power - 1; {This is the power such that 10^power * (some number < 10) gives biggest_dev} if power >= 3 then {must reduce size, biggest dev > 1000} begin scale_factor := realpower(10, (power - 2)); {for 1000-10000, where power=3, this divides by 10;} { for larger, divides by 10 more per power} for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do propensity_matrix[country1, country2] := propensity_matrix[country1, country2] / scale_factor; end {Now scaled for bigger than 1000} else if power = 0 then {was never incremented, and then 1 was subtracted from it} { , so biggest_dev is less than 10} begin {first figure out the fractional (10 to the minus-x) power} {for .9 this should come out with -1} while realpower(10, power) > biggest_dev do power := power - 1; {This is the power such that 10^power * (some number < 10) gives biggest_dev} if power <= 0 then {must increase size, biggest dev < 10} begin scale_factor := realpower(10, (power - 1)); {for .1 to .9, where power=-1, this divides by .01;} { for larger, divides by 10 more per power} for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do propensity_matrix[country1, country2] := propensity_matrix[country1, country2] / scale_factor; end; {Now scaled for bigger than 1000} end; {now make the matrix symmetric -- so far only did the first side of the diagonal} for country1 := 1 to num_countries - 1 do for country2 := country1 + 1 to num_countries do propensity_matrix[country2, country1] := propensity_matrix[country1, country2]; end; { ------------------------------------------------------------ } begin {main program} read_input_data(country_array, infile, inputfilename, outputfilename, main_comment, run_file_name, history_file_name, have_starting_alliance, starting_alliance); calculate_propensities(country_array, propensity_matrix, scale_factor); write_output_data(country_array, propensity_matrix, outfile, inputfilename, outputfilename, main_comment, run_file_name, history_file_name, have_starting_alliance, starting_alliance, scale_factor); end. {main program}
University of Michigan Program for the Study of Complex Systems
Contact http@maria.physics.lsa.umich.edu.
Revised November 4, 1996.