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.