Complexity of Cooperation Web Site

Propensity_maker_v3.32


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}

Back to Chapter 4
Back to Chapter 5
Back to Complexity of Cooperation Home Page

University of Michigan Program for the Study of Complex Systems
Contact http@maria.physics.lsa.umich.edu.
Revised November 4, 1996.