Freeciv

The matlab m-file to create the image is listed below.

% ========================================================================
% ruleset settings
% ========================================================================
illness_min_size = 3;
illness_base_factor = 25;
illness_trade_infection = 50;
illness_pollution_factor = 50;

factor_aqueduct = 50;
factor_sewer_system = 30;

% ========================================================================
% city config
% ========================================================================

% city size 1 to 50
size = 1:50;
% pollution = 6 * size
pollution = 6 * size;
% size of the trade city
trade_city_size = 10;

% ========================================================================
% calculate illness
% ========================================================================
ill_size      = round( (1- exp(- size / 10)) * 10 * illness_base_factor );
ill_trade     = round( 4 * illness_trade_infection / 100 * sqrt(size * trade_city_size) );
ill_pollution = round( illness_pollution_factor / 100 * pollution );

% ========================================================================
% plot it
% ========================================================================
figure();

hold on;
grid on;
grid minor;
ylim([0 50]);
xlim([0 50]);
ylabel('illness');
xlabel('city size');

% basic
factor1 = (100                                        )/100;
plot(size( 1:50), (ill_size( 1:50)                                      )/10 * factor1, 'b-o');
plot(size( 1:50), (ill_size( 1:50)+ill_trade( 1:50)                     )/10 * factor1, 'b--*');
plot(size( 1:50), (ill_size( 1:50)+ill_trade( 1:50)+ill_pollution( 1:50))/10 * factor1, 'b-.x');

% aqueduct
factor2 = (100 - factor_aqueduct                      )/100;
plot(size( 8:50), (ill_size( 8:50)                                      )/10 * factor2, 'g-o');
plot(size( 8:50), (ill_size( 8:50)+ill_trade( 8:50)                     )/10 * factor2, 'g--*');
plot(size( 8:50), (ill_size( 8:50)+ill_trade( 8:50)+ill_pollution( 8:50))/10 * factor2, 'g-.x');

% sewer system
factor3 = (100 - factor_aqueduct - factor_sewer_system)/100;
plot(size(12:50), (ill_size(12:50)                                      )/10 * factor3, 'k-o');
plot(size(12:50), (ill_size(12:50)+ill_trade(12:50)                     )/10 * factor3, 'k--*');
plot(size(12:50), (ill_size(12:50)+ill_trade(12:50)+ill_pollution(12:50))/10 * factor3, 'k-.x');

legend( ...
  'illness size', ...
  'illness size + illness trade', ...
  'illness size + illness trade + illness pollution', ...
  '(aqueduct) illness size', ...
  '(aqueduct) illness size + illness trade', ...
  '(aqueduct) illness size + illness trade + illness pollution', ...
  '(aqueduct + sewer system) illness size', ...
  '(aqueduct + sewer system) illness size + illness trade', ...
  '(aqueduct + sewer system) illness size + illness trade + illness pollution', ...
  'Location', 'NorthOutside');

% min city size 
plot([illness_min_size illness_min_size], [-100 100], 'r-');

disp(' # | (illness)               | aqueduct                | aqueduct + sewer system');
disp('   |    base  +trade +pollu. |    base  +trade +pollu. |    base  +trade +pollu.');
disp('---+-------------------------+-------------------------+-------------------------');
for ii=5:5:50
  disp(sprintf('%2d | %7.3f %7.3f %7.3f | %7.3f %7.3f %7.3f | %7.3f %7.3f %7.3f', ...
    ii, ...
    factor1 /10 * (ill_size(ii)), ...
    factor1 /10 * (ill_size(ii) + ill_trade(ii)), ...
    factor1 /10 * (ill_size(ii) + ill_trade(ii) + ill_pollution(ii)), ...
    factor2 /10 * (ill_size(ii)), ...
    factor2 /10 * (ill_size(ii) + ill_trade(ii)), ...
    factor2 /10 * (ill_size(ii) + ill_trade(ii) + ill_pollution(ii)), ...
    factor3 /10 * (ill_size(ii)), ...
    factor3 /10 * (ill_size(ii) + ill_trade(ii)), ...
    factor3 /10 * (ill_size(ii) + ill_trade(ii) + ill_pollution(ii))));
end