home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / dominion / part15 / makeworld.c < prev   
C/C++ Source or Header  |  1992-02-11  |  44KB  |  1,542 lines

  1. /* makeworld.c   A world generation program by Stephen H. Underwood */
  2. /*
  3.  * Copyright (C) 1990 Free Software Foundation, Inc.
  4.  * Written by the dominion project.
  5.  *
  6.  * This file is part of dominion.
  7.  *
  8.  * dominion is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as published
  10.  * by the Free Software Foundation; either version 1, or (at your option)
  11.  * any later version.
  12.  *
  13.  * This software is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this software; see the file COPYING.  If not, write to
  20.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22. #include "dominion.h"
  23. #include "misc.h"
  24. #include <stdio.h>
  25. #include <math.h>
  26. #include <signal.h>
  27. #ifndef ridge            /* ridges don't have limits.h */
  28. # include <limits.h>
  29. #else /* ridge */
  30. # define    INT_MAX        2147483647 /* max decimal value of an "int" */
  31. #endif /* ridge */
  32.  
  33. #define HASH_SIZE 500   /* Size of hash table for sea_level determination */
  34. #define STATFILE "world.stats"
  35.  
  36. extern Sworld world;   
  37. extern Suser user;
  38. extern struct race_list *races;    
  39. extern char libdir[];
  40. extern int (*wrapx)(), (*wrapy)(), compressed_world;
  41. extern struct s_altitude_map altitude_map[];
  42. extern struct item_map climates[];
  43. double **d_map;
  44.  
  45. /* Base terrains for each given climate type */
  46. int cli_terr[] = { 1, 4, 5, 3, 6, 4, 5, 3, 5, 3, 0 };
  47.  
  48. cleanup()
  49. {
  50. }
  51.  
  52. critical()
  53. {
  54.   signal(SIGINT, SIG_IGN);
  55.   signal(SIGQUIT, SIG_IGN);
  56. }
  57. noncritical()
  58. {
  59.   signal(SIGINT, SIG_DFL);
  60.   signal(SIGQUIT, SIG_DFL);
  61. }
  62.  
  63. double Gauss()
  64. /* 
  65.    This function returns a gaussian random variable with mean 0
  66.    and a variance of 1.
  67. */
  68. {
  69.   static int first_time_flag = 0, Nrand = 4;
  70.   static double GaussAdd, GaussFac;
  71.   double sum = 0;
  72.   int i;
  73.   unsigned seed;
  74.  
  75.   if (first_time_flag == 0)
  76.   {
  77.     /* This initializes things for the gaussing stuff.
  78.        this is done only once. */
  79.     GaussAdd = sqrt((double)(3 * Nrand));
  80.     GaussFac = 2.0 * GaussAdd/ ( (double)Nrand * (double)INT_MAX );
  81.     seed = (unsigned) time(NULL);
  82.     SRND(seed);
  83.     first_time_flag = 1;
  84.   }
  85.   for ( i = 0 ; i < Nrand ; i++) sum += RND();
  86.   return (GaussFac * sum - GaussAdd);
  87.  
  88. }
  89.  
  90. gen_arr(X,H,r,xmax,ymax,max_height, min_height)
  91. double *X[],H,r,*max_height,*min_height;
  92. int xmax,ymax;
  93. /*
  94.    This routine generates a fractal arrray with fratal dimension of 3-H
  95.    and a lacunarity of r.  It is passed the number of sampling points in
  96.    the final array xmax * ymax, and a place to store the value of said
  97.    points. Modified version of a similar code in The Science of Fractal
  98.    Images by Peitgen and Saupe
  99. */
  100. {
  101.   double delta, xt, yt, xT, yT, h, sigma = 0.5, t, T;
  102.   int  xmT, ymT, xmt, ymt, i, j, indx , xN, yN, x, y;
  103.  
  104.   xN = xmax + 1;
  105.   yN = ymax + 1;
  106.  
  107.   if ( xmax < ymax )
  108.   {
  109.     xmT = 2;
  110.     ymT = (int)((double)ymax / ((double)xmax/2.0));
  111.   } else
  112.   {
  113.     ymT = 2; 
  114.     xmT = (int)((double)xmax / ((double)ymax/2.0));
  115.   }
  116.   for (x = 0 ; x < xmT ; x++)
  117.   {
  118.     for (y = 0 ; y < ymT ; y++)
  119.     {
  120.       X[x][y] = 0.0;
  121.     }
  122.   }
  123.   xT = 1.0  / ((double)xmT - 1.0);
  124.   yT = 1.0  / ((double)ymT - 1.0);
  125.  
  126.   while ((xmT < xN) || (ymT < yN))
  127.   {
  128.     xmt = (int)((double)xmT/r);
  129.     if (xmt == xmT) xmt = xmT + 1;
  130.     if (xmt > xN) xmt = xN;
  131.     xt = 1.0/((double)xmt-1.0);
  132.     
  133.     ymt = (int)((double)ymT/r);
  134.     if (ymt == ymT) ymt = ymT + 1;
  135.     if (ymt > yN) ymt = yN;
  136.     yt = 1.0/((double)ymt-1.0);
  137.  
  138.     if ( xt > yt)
  139.     {
  140.       t = xt;
  141.       T = xT;
  142.     } else
  143.     {
  144.       t = yt;
  145.       T = yT;
  146.     }
  147.     
  148.     interpolate(X, xmT, ymT, xmt, ymt); 
  149.     delta = pow(t/T, 2.0 - 2.0 * H);
  150.     delta = sqrt(1.0 - delta);
  151.     delta *= sqrt(0.5);
  152.     delta *= pow(t,H);
  153.     delta *= sigma;
  154.     for ( i = 0 ; i < (xmt - 1); i++)
  155.     {
  156.       for ( j = 0 ; j < (ymt - 1); j++)
  157.       {
  158.         X[i][j] += delta * Gauss();
  159. /*
  160.    The following mess is for machinees with NaN implemented rather
  161.    than dumping core on division by zero like it should.  If it
  162.    doesn't apply to your machine, you are lucky and should be grateful.
  163. */
  164. /*        if (X[i][j] != X[i][j]) /* Yes, I really mean this */
  165. /*        { 
  166.           printf("Error: value %lf at %d %d\n",X[i][j],i,j);
  167.         }
  168. */
  169.       }
  170.     }
  171.     for (i = 0 ; i <= (xmt - 1) ; i++)
  172.     {
  173.       X[i][ymt-1] = X[i][0];
  174.     }
  175.     for (j = 0 ; j <= (ymt - 1) ; j++)
  176.     {
  177.       X[xmt-1][j] = X[0][j];
  178.     }
  179.     xmT = xmt;
  180.     ymT = ymt;
  181.     xT = 1.0  / ((double)xmT - 1.0);
  182.     yT = 1.0  / ((double)ymT - 1.0);
  183.   }
  184. /* We've computed the fractal, now find the min and max */
  185.   *max_height = -5000;
  186.   *min_height = 5000;
  187.   for (x = 0 ; x < xmax ; x++)
  188.   {
  189.     for (y = 0 ; y < ymax ; y++)
  190.     {
  191.       if (*max_height < X[x][y]) *max_height = X[x][y];
  192.       if (*min_height > X[x][y]) *min_height = X[x][y];
  193.     }
  194.   }
  195.   return delta;
  196. }
  197.  
  198. interpolate(X, oldx, oldy, newx, newy)
  199. /*
  200.    Similar to the Interpolate routine mentionedin The Science of
  201.    fractal images this routine interpolates the values of the verticies
  202.    of a larger rectangular grid that covers the same region as the
  203.    smaller rectangular grid stored in X.
  204.    At the beginning X is oldx by oldy and at the end it's newx by newy
  205. */
  206. double *X[];
  207. int oldx, oldy, newx, newy;
  208. {
  209.   int i,j,x,y,k;
  210.   double *Y, high_per, low_per, right_per, left_per;
  211.  
  212. /* Get a temporary array to work with. */
  213.    if ((Y = (double *)malloc((oldy+1)* sizeof(double))) == NULL) { mem_error();}
  214.  
  215. /*
  216.    We work backwards through the array so we don't overwrite rows that
  217.    we still need to work with.  We could make the code simpler by using
  218.    a second array, but that would cost both time (to copy the values back)
  219.    and memory to stor the second array.  Since this routine is called
  220.    frequently, we optimize
  221. */    
  222.  
  223.   i = oldx - 1;
  224.   for (x = newx - 1; x > 0 ; x--)
  225.   {
  226.     if ( i * newx >= x * oldx)
  227.     {
  228. /*
  229.    A point always lies between two columns.  We store the right hand
  230.    column in the temporary array Y
  231. */
  232.       for (k = 0 ; k < oldy; k ++) { Y[k] = X[i][k]; }
  233.       i--;
  234.     }
  235. /* Determine left and right portions for this colmun in the new matrix */ 
  236.     right_per = (double) ( x * oldx - i * newx)/(double)newx;
  237.     left_per = 1.0 - right_per;
  238. /* Loop backwards over y just for consistancy */
  239.     j = oldy - 1;
  240.     for ( y = newy - 1 ; y >= 0 ; y--)
  241.     {
  242. /* Jump down a level, special casing the botom(top) row. */
  243.       if ( j * newy >= y * oldy) { 
  244.        if (--j < 0) { j = 0;}
  245.       }
  246. /* Determine high and low portions for this row in the new matrix */ 
  247.       high_per = (double)(y * oldy - j * newy) / (double)newy;
  248.       low_per = 1.0 - high_per;
  249. /* Now sum up the portions of the 4 corners surrounding this point */
  250.       X[x][y] = ( low_per * left_per * X[i][j] + low_per * right_per * Y[j]
  251.          + high_per * left_per * X[i][j+1] + high_per * right_per * Y[j+1]);
  252. /*
  253.    The following mess is for machinees with NaN implemented rather
  254.    than dumping core on division by zero like it should.  If it
  255.    doesn't apply to your machine, you are lucky and should be grateful.
  256. */
  257. /*        if (X[x][y] != X[x][y]) /* Yes, I really mean this */
  258. /*        { 
  259.           printf("Error: value %lf at %d %d\n",X[x][y],x,y);
  260.         }
  261. */
  262.     }
  263.   }
  264. /*
  265.    We special case the last column since we are garunteed an overwrite at 
  266.    that point
  267. */
  268.  
  269.   j = oldy;
  270. /* If the 0th column isn't in Y, we put it there now */
  271.   if (i != 0)
  272.   {
  273.     i = 0;
  274.     for (k = 0 ; k < oldy; k ++) { Y[k] = X[i][k]; }
  275.   }
  276. /*
  277.    Compute the 0th columns values.  Note that since it falls on the
  278.    same column as 0th column of the previous matrix, we need only
  279.    concern ourselves with 2-d interpolation
  280.  */
  281.   for ( y = newy - 1 ; y > 0 ; y--)
  282.   {
  283.     if ( j * newy >= y * oldy) { j--; }
  284.     high_per = (double)(y * oldy - j * newy) / (double)newy;
  285.     low_per = 1.0 - high_per;
  286.     X[x][y] = ( low_per * Y[j] + high_per * Y[j+1])/2.0;
  287.   }
  288. /* Clean up after ourselves */
  289.   if ( Y != NULL) free(Y);
  290. }
  291.  
  292.  
  293. int init_sector(map,i,j)
  294. /* This function sets a sector to it's base values (mostly zeros) */
  295. Ssector **map;
  296. int i,j;
  297. {
  298.   map[i][j].loc.x = i;
  299.   map[i][j].loc.y = j;
  300.   map[i][j].terrain = 0;
  301.   map[i][j].altitude = 0;
  302.   map[i][j].climate = 0;
  303.   map[i][j].designation = 0;
  304.   map[i][j].soil = 0;
  305.   map[i][j].metal = 0;
  306.   map[i][j].jewels = 0;
  307.   map[i][j].defense = 0;
  308.   map[i][j].roads = 0;
  309.   map[i][j].owner = 0;
  310.   map[i][j].n_people = 0;
  311.   map[i][j].flags = 0;
  312.   map[i][j].name[0] = '\0';
  313.   map[i][j].alist = (struct armyid *)NULL;
  314. };
  315.  
  316. init_gamemaster(np)
  317. /* 
  318.    This function sets up the gamemaster nation (the only nation the game
  319.    starts with).
  320. */
  321. Snation *np;
  322. {
  323.   char temppass[PASSLEN], temp2pass[PASSLEN];
  324.  
  325.   np->id = 0;
  326.   strcpy(np->name,"Gamemaster");
  327.   sprintf(np->leader,"%s","Exalted One");
  328. /* We need to get the password from the user */
  329.   get_crypt_pass("\nGive World/Gamemaster password: ", temppass, NULL, NULL);
  330.   get_crypt_pass("\nType it once more: ", temp2pass, NULL, NULL);
  331.   while  (strcmp(temppass, temp2pass) != 0){
  332.     fprintf(stderr,"\nThose two didn't match.  Please try again.\n");
  333.     get_crypt_pass("\nGive World/Gamemaster password: ", temppass, NULL, NULL);
  334.     get_crypt_pass("\nType it once more: ", temp2pass, NULL, NULL);
  335.   }
  336.   strcpy(np->passwd, temppass);
  337.   np->capital.x = 0;
  338.   np->capital.y = 0;
  339.   np->race = races->race;  /* Set's it to the first race, Master */
  340.   np->mark = '-';          /* Useful for display nation displays */
  341. /* 
  342.   Everything starts at 0, since if the gamemaster wants something,
  343.   he/she can use the edit nation feature to add it.
  344. */
  345.   np->taxes = 0;
  346.   np->taxtype = 0;
  347.   np->charity = 0;
  348.   np->money = 0;
  349.   np->jewels = 0;
  350.   np->metal = 0;
  351.   np->food = 0;
  352.   np->n_sects = 0;
  353.   np->tech_r_d = 0;
  354.   np->tech_r_d_metal = 0;
  355.   np->mag_r_d = 0;
  356.   np->mag_r_d_jewels = 0;
  357.   np->spy_r_d = 0;
  358.   np->npc_flag = 0;
  359.   np->npc_agg = 0;
  360.   np->npc_exp = 0;
  361.   np->npc_iso = 0;
  362.   strcpy(np->mag_order,"Master");
  363.   np->tech_skill = 0;
  364.   np->mag_skill = 0;
  365.   np->farm_skill = 0;
  366.   np->mine_skill = 0;
  367.   np->spell_pts = 1;
  368.   np->attack = 0;
  369.   np->defense = 0;
  370.   np->spy = 0;
  371.   np->secrecy = 0;
  372.   np->n_armies = 0;
  373.   np->armies = (Sarmy *) NULL;
  374.   np->ptlist = (struct pt_list *) NULL;
  375.  
  376.   return 0;
  377. }
  378.  
  379. init_d_map(xmax,ymax)
  380. /*
  381.    Allocate the memory for the temporary array the size of the world
  382.    (with one extra for wrap around) for manipulation before scaling 
  383. */
  384. int xmax,ymax;
  385. {
  386.   int i;
  387.   
  388.   if ((d_map = (double **) malloc((xmax + 1) * (sizeof(double *)))) == NULL)
  389.   {
  390.     mem_error();
  391.   }
  392.   for (i=0; i <=xmax ; i++)
  393.   {
  394.     if ((d_map[i] = (double *) malloc((ymax + 1) * (sizeof(double)))) == NULL)
  395.     {
  396.       mem_error();
  397.     }
  398.   }
  399. }
  400.  
  401. double find_level(wp,d_map,perc, max_height, min_height)
  402. /*
  403.    This function finds the level beneath which are roughly "perc" 
  404.    percentage of the sectors available.  Good for setting sea
  405.    level if you want 30% sea for example.
  406. */
  407. Sworld *wp;
  408. double *d_map[],perc,max_height,min_height;
  409. {
  410.   static int hashes[HASH_SIZE + 1];
  411.   int num_sect,i,k,x,y, ltemp;
  412.   double level, scale_factor;
  413.  
  414.  
  415.   if (perc == 1.0) /* If it's all of them, but the level above everything */
  416.   {
  417.     level = max_height;
  418.     return level;
  419.   }
  420.   if (perc == 0.0) /* If it's none of them, put the level below everything */
  421.   {
  422.     level = min_height;
  423.     return level;
  424.   }
  425. /* Empty the hash table */
  426.   for (i=0;i<=HASH_SIZE;i++) hashes[i] = 0;
  427. /* Loop over the array, filing the hash table to the number of sectors
  428.    in the region each hash slot is associated with.
  429. */ 
  430.   scale_factor = (double)HASH_SIZE/
  431.             ((max_height - min_height)*(1.0 + 1.1/HASH_SIZE));
  432.  
  433.   for (x = 0 ; x < wp->xmax ; x++)
  434.   {
  435.     for (y = 0 ; y < wp->ymax ; y++)
  436.     {
  437.       ltemp = (d_map[x][y] - min_height) * scale_factor;
  438. /*      if ((ltemp < 0 ) || (ltemp >= HASH_SIZE))
  439.       {
  440.         printf("Error: ltemp %d max %lf min %lf val %lf\n",ltemp,
  441.                    max_height, min_height, d_map[x][y]);
  442.       } else 
  443. */
  444.       {
  445.         hashes[ltemp]++;
  446.       }
  447.     }
  448.   }
  449. /* Determine the number of sectors below the level */
  450.   num_sect = (int)((double)(wp->xmax * wp->ymax) * perc);
  451.   k = 0; i = -1;
  452. /* Find how far down the hash table we have to go to get that many sectors */
  453.   while ( ( k < num_sect) && ( i <= HASH_SIZE))
  454.   {  
  455.     i++;
  456.     k += hashes[i]; 
  457.   }
  458.   if (i >= HASH_SIZE) /* If it's all of them, then use all of them */
  459.   {
  460.     level = max_height;
  461.   }
  462.   /* if it's none of them, use none of them. */
  463.   else if ((i == 0) || (num_sect == 0))
  464.   {
  465.     level = min_height;
  466.   }
  467.   else 
  468. /* 
  469.    Estimate the level as half way between a bit too few
  470.    (at the i-1 level) and a few too many (at the ith level)
  471. */
  472.   {
  473.    level = ((max_height - min_height) * (((double)i - 0.5) / 
  474.                         (double)HASH_SIZE) ) + min_height;
  475.   }
  476.  
  477.   return level;
  478. }
  479.  
  480. power_scale(wp,d_map,level, k, minimum, maximum)
  481. /* 
  482.   This function takes the entire map and rescales it by taking
  483.   each item to the kth power, after rescaling the value to be
  484.   between 1 and 2.  This means that all the points get lower,
  485.   but specifically that high points loose more height than
  486.   the lower points.  This brings most of the mountain peaks
  487.   down to within rougly the same range.
  488. */
  489. Sworld *wp;
  490. double *d_map[],level,k,*maximum, *minimum;
  491. {
  492.   int x,y;
  493.   double old_min = *minimum , old_max = *maximum, htemp;
  494.  
  495.   *maximum = -50; *minimum = 50; 
  496.   for (x = 0 ;x < wp->xmax ; x++)
  497.   {
  498.     for (y = 0 ; y < wp->ymax ; y++)
  499.     {/* scale us relative to 0 */
  500.       if ((htemp = (d_map[x][y] -= level)) < 0)
  501.       {
  502. /*
  503.    scale below water between -1 and 0, then between 1 and 2, take power
  504.    and then scale back below 0.  Remember roots of a negative number may
  505.    be meaninless, so it has to be shifted (as we have done) into the positive
  506. */
  507.         if (old_min != level)
  508.         { 
  509.           htemp /= (old_max - level);
  510.     } else
  511.         {
  512.           htemp = 0;
  513.     }
  514.         htemp = 1 - pow(1 - htemp,k);
  515.       } else
  516.       { 
  517. /*
  518.    scale above water between 0 and 1, and then between 1 and 2 and then
  519.    after the power back between 0 and 1 
  520. */
  521.         if (old_max != level)
  522.         { 
  523.           htemp /= (old_max - level);
  524.     } else
  525.         {
  526.           htemp = 0;
  527.     }
  528.         htemp = pow(1 + htemp,k) -1;
  529.       }
  530.       if (htemp > *maximum) *maximum = htemp;
  531.       if (htemp < *minimum) *minimum = htemp;
  532.       d_map[x][y] = htemp;
  533.     }
  534.   }
  535. }
  536.  
  537. gen_alt(wp,water_per,dim,lac,info_flag,fp)
  538. /* 
  539.    Here we generate the altitudes for the world.  First step is to create
  540.    a fractal array of doubles to scale.  We find where sea level should be,
  541.    and then scale up and down from sea level.
  542. */
  543. double dim,lac,water_per;
  544. int info_flag;
  545. Sworld *wp;
  546. FILE *fp;
  547. {
  548.   double max_height, min_height,sea_level,dry_factor,wet_factor,old_min;
  549.   double loc_min,loc_max;
  550.   int i,j,x,y,k,sea_perc,htemp,alt_hash[14];
  551.   int loc_x, loc_y;
  552.  
  553.   printf("Generating Altitudes\n");
  554.   wp->geo.pwater = (int)(water_per * 100.0);
  555.   gen_arr(d_map,dim,lac,wp->xmax,wp->ymax,&max_height,&min_height);
  556.   old_min = min_height;
  557.  
  558. /* Clear out the hash table, and then fill it again by level of map */
  559.   sea_level = find_level(wp,d_map,water_per, max_height, min_height);
  560.  
  561. /*
  562.    Rescale by taking everything to the 0.5 power.  flattens out
  563.    the higher peaks
  564. */
  565.   power_scale(wp,d_map,sea_level, 0.5 ,&min_height, &max_height);
  566.   sea_level = 0.0; /* Do power scales things to sea level for us */
  567.  
  568. /* Scaling factors are determined for below and above sea_level */
  569.   dry_factor = (int)(13.0 / (max_height - sea_level));
  570.   wet_factor = (int)(7.0 / (sea_level - min_height));
  571.   sea_perc = 0;  /* redetermine the exact sea_percentage */
  572.   for (i=0; i < 13 ; i++) alt_hash[i] = 0; /* set the hash table to zero */
  573. /* Make one last loop over the world */
  574.   for (x = 0 ; x < wp->xmax ; x++)
  575.   {
  576.     for (y = 0 ; y < wp->ymax ; y++)
  577.     {
  578.       d_map[x][y] = d_map[x][y] - sea_level;
  579.       if ((d_map[x][y] >= 0.0) && (water_per < 1.0))/* Dry land */
  580.       {
  581.         htemp = (int) (d_map[x][y] * dry_factor);
  582.         htemp++; /* We want 50% less lowlands */
  583.         if (htemp > 8) htemp--; /* We want 50% more mountains */
  584.         if (htemp > 10) htemp--; /* We want 50% more peaks */
  585.         htemp /= 2;
  586.         if (htemp > 5)
  587.         {/* If somehow the scaling is fucked */
  588.           printf("htemp error %d at %d %d\n",htemp,x,y);
  589.           fprintf(fp,"htemp error %d at %d %d\n",htemp,x,y);
  590.           htemp = 6;
  591.         }
  592.         else htemp++;  /* needs to be between 1 and 6, not 0 and 5 */
  593.         wp->map[x][y].altitude = htemp;
  594.         alt_hash[htemp + 5]++;  /* one more sector of htemp altitude */
  595.       } else if (d_map[x][y] < 0.0) /* Dry land */
  596.       {
  597.         sea_perc++;           /* One more sea sector */
  598.         htemp = (int)(d_map[x][y] * wet_factor);
  599.         htemp--;  /* number need to be -1 to -6 not 0 to -5 */
  600.         if (htemp < OCEAN_PLAINS ) htemp++;  /* Makes more ocean_plains */
  601.         if (htemp < TRENCH ) htemp++;  /* Makes more trench */
  602.         if (htemp < -5)
  603.         { /* If somehow the scaling if fucked. */
  604.           printf("htemp error %d at %d %d\n",htemp,x,y);
  605.           fprintf(fp,"htemp error %d at %d %d\n",htemp,x,y);
  606.           htemp = -5;
  607.         } 
  608.         wp->map[x][y].altitude = htemp; 
  609.         alt_hash[htemp + 5]++;  /* one more sector of htemp altitude */
  610.       }
  611.     }
  612.   }
  613. /* Now determine the sea percentage more exactly, rounding correctly */
  614.   sea_perc = (int)((((double)sea_perc * 100.0) /
  615.                 (double)(wp->xmax * wp->ymax)) + 0.49);
  616.   if (info_flag == 3)
  617.   {
  618.     printf("Percentage of water : %d%%\n",sea_perc);
  619.     for (i= 0 ; i <= 11 ; i++) {
  620.       if ( i != 5) {
  621.         printf("%d sectors are %s\n",alt_hash[i],altitude_map[i].name);
  622.       } 
  623.     }
  624.   }
  625.   if (fp != NULL) {
  626.     fprintf(fp,"Altitude Fractal Dimension : %lf\n",3.0 - dim);
  627.     fprintf(fp,"Percentage of water : %d%%\n",sea_perc);
  628.     for (i= 0 ; i <= 11 ; i++) {
  629.      if (i != 5) {
  630.       fprintf(fp,"%d sectors are %s\n",alt_hash[i],altitude_map[i].name);
  631.      }
  632.     }
  633.   }
  634. }
  635.  
  636. gen_climate(dim,lac,wp,info_flag,fp)
  637. /* 
  638.    Here we generate the climates for the world.  First step is to create
  639.    a fractal array of doubles to scale.  Then we modify everything by
  640.    multiplying it by a sin function, thereby producing the lowest values
  641.    (0) at the beginning and the end.  Then we add a linear factor
  642.    into the polar regions, and a constant factor to everywhere else
  643.    to raise things up a bit.  Lastly we scale things over 11 climates
  644.    for land, and 9 climates for water (water has no deserts)
  645.    When we determine the climate, a certain base terrain type goes
  646.    with it.  That gets adjusted later.
  647. */
  648. double dim,lac;
  649. int info_flag;
  650. Sworld *wp;
  651. FILE *fp;
  652. {
  653.   double max_height, min_height,dtemp,old_min,old_max;
  654.   int i,x,y,htemp,artic_region,hashes[12];
  655.  
  656.   printf("Generating Climates\n");
  657. /* Generate the original array */
  658.   gen_arr(d_map,dim,lac,wp->xmax,wp->ymax,&max_height,&min_height);
  659.   old_min = min_height; max_height = -50; min_height = 50;
  660. /* Do the sin function filter */
  661.   for (x = 0 ; x < wp->xmax ; x++)
  662.   {
  663.     for (y = 0 ; y < wp->ymax ; y++)
  664.     {
  665.       d_map[x][y] = d_map[x][y] - old_min;
  666.       d_map[x][y] = sin((double)y * M_PI/(double)(wp->ymax)) * d_map[x][y];
  667.       if (d_map[x][y] < min_height ) min_height = d_map[x][y];
  668.       if (d_map[x][y] > max_height ) max_height = d_map[x][y];
  669.     }
  670.   }
  671.   old_max = max_height; old_min = min_height;
  672.   max_height = -50; min_height = 50;
  673. /* Scale things linearly up over the artic and polar regions */
  674.   artic_region = wp->ymax / 5;
  675.   for (x = 0 ; x < wp->xmax ; x++)
  676.   {
  677.     for (y = 0 ; y < wp->ymax ; y++)
  678.     {
  679.       dtemp = (old_max - old_min)/9.0;
  680.       if (y < artic_region)
  681.       { 
  682.         d_map[x][y] += dtemp * (double)y / (((double)artic_region)/2.0);
  683.       }
  684.       else if ((wp->ymax - y) < artic_region)
  685.       { 
  686.         d_map[x][y] += dtemp*(double)(wp->ymax-y)/((double)artic_region/2.0);
  687.       }
  688.       else
  689.       {
  690.         d_map[x][y] += 2.0 * dtemp;
  691.       }
  692.       if (d_map[x][y] > max_height) max_height = d_map[x][y];
  693.       if (d_map[x][y] < min_height) min_height = d_map[x][y];
  694.     }
  695.   }
  696.  
  697. /* Standard scaling */
  698.   for (i=0;i<11;i++) hashes[i] = 0;
  699.   for (x = 0 ; x < wp->xmax ; x++)
  700.   {
  701.     for (y = 0 ; y < wp->ymax ; y++)
  702.     {
  703.       if (wp->map[x][y].altitude < 0)
  704.       {
  705.         htemp = (int)(((d_map[x][y]-min_height)*9.0)/(max_height-min_height));
  706.       } else
  707.       {
  708.         htemp = (int)(((d_map[x][y]-min_height)*12.0)/(max_height-min_height));
  709.         if (htemp > 10) htemp--; /* We want more desert */
  710.       }
  711.       if (htemp >= 11)
  712.       {
  713.        htemp = 10;
  714.       }
  715.       htemp = 11 - (htemp + 1);
  716.       wp->map[x][y].climate = htemp;
  717.       if (wp->map[x][y].altitude < 0)
  718.       {
  719. /* If it's an ocean be terrain type ocean. */
  720.          wp->map[x][y].terrain = -5;
  721.       } else
  722.       {
  723.         wp->map[x][y].terrain = cli_terr[htemp];
  724.       }
  725.       hashes[htemp]++;
  726.     }
  727.   }
  728.   if (info_flag == 3)
  729.   {
  730.     for (i= 0 ; i < 11 ; i++)
  731.     {
  732.       printf("%d sectors have %s climate \n",hashes[i],climates[i].name);
  733.     }
  734.   }
  735.   if (fp != NULL)
  736.   {
  737.     fprintf(fp,"\nClimate Fractal Dimension: %lf\n",3.0 - dim);
  738.     for (i = 0 ; i < 11 ; i++)
  739.     {
  740.       fprintf(fp,"%d sectors have %s climate \n",hashes[i],climates[i].name);
  741.     }
  742.   }
  743. }
  744.  
  745. adjust_terrain(wp)
  746. /*
  747.    This function adjusts the terrain starting at the base level
  748.    given by the climate, and adjusting for altitude.
  749. */
  750. Sworld *wp;
  751. {
  752.   int x,y;
  753.  
  754.   for (x = 0 ; x < wp->xmax; x++)
  755.   {
  756.     for (y = 0 ; y < wp->ymax ; y++)
  757.     {
  758.       if (wp->map[x][y].altitude > HILLS)
  759.       {
  760.         wp->map[x][y].terrain--;
  761.         if (wp->map[x][y].altitude > MOUNTAINS)
  762.         {
  763.           wp->map[x][y].terrain--;
  764.         }
  765.         if (wp->map[x][y].terrain < ICE) wp->map[x][y].terrain = ICE;
  766.         else if (wp->map[x][y].terrain == SWAMP) wp->map[x][y].terrain= BARREN;
  767.       } 
  768.       else if (wp->map[x][y].altitude == LOWLANDS)
  769.       {
  770.         if ((wp->map[x][y].climate > 1 ) && (wp->map[x][y].climate < 9))
  771.         {
  772.           if ((wp->map[x][y].terrain != FOREST) && (RND() % 4 == 0))
  773.           {
  774.             wp->map[x][y].terrain = SWAMP;
  775.           }
  776.         }
  777.       }
  778.     }
  779.   }
  780. }
  781.  
  782. gen_metal(wp,metal_per,metal_avg,info_flag,fp)
  783. /*
  784.   This function distributes the metal over the world.  The location of
  785.   the metal deposits is determined fractally, and the value of the
  786.   deposits is determined randomly, with a gaussian distribution.  The
  787.   average metal in a sector is metal_avg and the percentage of sectors
  788.   with any metal at all is metal_per
  789. */
  790. double metal_per,metal_avg;
  791. int info_flag;
  792. Sworld *wp;
  793. FILE *fp;
  794. {
  795.   double maximum, minimum,dtemp,old_min,old_max,zero_level;
  796.   int i,x,y,htemp,hashes[41],k, tot_sect = 0, tot_met = 0, max_met = 0;
  797.  
  798.   printf("Generating Metal\n");
  799.   wp->geo.metal_avg = metal_avg;
  800.   minimum = 10000.0; maximum = -13000.0;
  801.   for (x = 0 ; x < wp->xmax ; x++)
  802.   {
  803.     for (y = 0 ; y < wp->ymax ; y++)
  804.     {
  805.       d_map[x][y] = (double)(RND() % 10000) + 1000.0;
  806.       switch(wp->map[x][y].altitude) 
  807.       {
  808. /* Hill, and the like are more probable to have metal */
  809.         case HILLS:
  810.         case MOUNTAIN_PEAK:
  811.         case TRENCH:
  812.         case CONT_SHELF: d_map[x][y] += 1000; break;
  813. /* mountains are even more probable to have metal */
  814.         case SEA_MOUNT:
  815.         case MOUNTAINS: d_map[x][y] += 2000; break;
  816. /* Plains lowlands and shallows are less probable */
  817.         case PLAINS:
  818.         case LOWLANDS:
  819.         case SHALLOWS: d_map[x][y] -= 1000; break;
  820.       }
  821.       if (minimum > d_map[x][y]) minimum = d_map[x][y];
  822.       if (maximum < d_map[x][y]) maximum = d_map[x][y];
  823.     }
  824.   }
  825. /* Find the cutoff level for metal */
  826.   zero_level = find_level(wp,d_map,metal_per, maximum, minimum);
  827.  
  828.   for (i=0;i<40;i++) hashes[i] = 0;
  829. /* Then fill all the sectors that have metal with some amount of metal */
  830.   for (x = 0 ; x < wp->xmax ; x++)
  831.   {
  832.     for (y = 0 ; y < wp->ymax ; y++)
  833.     {
  834.       if (d_map[x][y] > zero_level)
  835.       {
  836.         dtemp = fabs((Gauss() + Gauss()))/2.0;
  837.         dtemp *= metal_avg;
  838.         dtemp /= 0.651;
  839.         htemp = (int)(dtemp) + 1;
  840.         wp->map[x][y].metal = htemp;
  841.         tot_sect++;
  842.         tot_met += htemp;
  843.         if (max_met < htemp) { max_met = htemp; }
  844.         if (htemp > 20) { hashes[20]++; }
  845.         else { hashes[htemp]++; }
  846.       } else hashes[0]++;
  847.     }
  848.   }
  849.   if (info_flag == 3)
  850.   {
  851.     printf("There are %d sectors with metal\n",tot_sect);
  852.     max_met = min(max_met, 20);
  853.     for (i= 0 ; i < max_met  ; i++)
  854.     {
  855.       printf("There are %d sectors with %d metal\n",hashes[i],i);
  856.     }
  857.     if (max_met < 20)
  858.     {
  859.       printf("There are %d sectors with %d metal\n",hashes[max_met],max_met);
  860.     } else
  861.     {
  862.       printf("There are %d sectors over %d metal\n",hashes[max_met],max_met-1);
  863.     }
  864.   }
  865.   if (fp != NULL)
  866.   { 
  867.     fprintf(fp,"\nMetal Chance %d%% with %lf average\n",
  868.               (int)((1.0 - metal_per) * 100.0),metal_avg);
  869.     fprintf(fp,"Total Metal %d over %d sectors with %d maximum\n",
  870.             tot_met,tot_sect ,max_met);
  871.     max_met = min(max_met, 20);
  872.     for (i= 0 ; i < max_met  ; i++)
  873.     {
  874.       fprintf(fp,"There are %d sectors with %d metal\n",hashes[i],i);
  875.     }
  876.     if (max_met < 20)
  877.     {
  878.       fprintf(fp,"There are %d sectors with %d metal\n",hashes[max_met],
  879.              max_met);
  880.     } else
  881.     {
  882.       fprintf(fp,"There are %d sectors over %d metal\n",hashes[max_met],
  883.                max_met-1);
  884.     }
  885.   }
  886.  
  887. }
  888.  
  889. gen_jewel(wp,jewel_per,jewel_avg,info_flag,fp)
  890. /* 
  891.    This adds jewels to the world the same way metal is added.
  892.    If you understood gen_metal, you understand this.  They are
  893.    basically the same.
  894. */
  895. double jewel_per, jewel_avg;
  896. int info_flag;
  897. Sworld *wp;
  898. FILE *fp;
  899. {
  900.   double maximum, minimum,dtemp,old_min,old_max,zero_level;
  901.   int i,x,y,htemp,hashes[41],k,tot_sect = 0, tot_jewels = 0, max_jewel = 0; 
  902.  
  903.   printf("Generating Jewels\n");
  904.   wp->geo.jewel_avg = jewel_avg;
  905.   minimum = 10000.0; maximum = -13000.0;
  906.   for (x = 0 ; x < wp->xmax ; x++)
  907.   {
  908.     for (y = 0 ; y < wp->ymax ; y++)
  909.     {
  910.       d_map[x][y] = (double)(RND() % 10000) + 1000.0;
  911.       switch(wp->map[x][y].altitude) 
  912.       {
  913.         case HILLS:
  914.         case MOUNTAIN_PEAK:
  915.         case TRENCH:
  916.         case CONT_SHELF: d_map[x][y] += 1000; break;
  917.         case SEA_MOUNT:
  918.         case MOUNTAINS: d_map[x][y] += 2000; break;
  919.         case PLAINS:
  920.         case LOWLANDS:
  921.         case SHALLOWS: d_map[x][y] -= 1000; break;
  922.       }
  923.       if (minimum > d_map[x][y]) minimum = d_map[x][y];
  924.       if (maximum < d_map[x][y]) maximum = d_map[x][y];
  925.     }
  926.   }
  927.   zero_level = find_level(wp,d_map,jewel_per, maximum, minimum);
  928.   for (i=0;i<40;i++) hashes[i] = 0;
  929.   for (x = 0 ; x < wp->xmax ; x++)
  930.   {
  931.     for (y = 0 ; y < wp->ymax ; y++)
  932.     {
  933.       if (d_map[x][y] > zero_level)
  934.       {
  935.         dtemp = fabs((Gauss() + Gauss()))/2.0;
  936.         dtemp *= jewel_avg;
  937.         dtemp /= 0.651;
  938.         htemp = (int)(dtemp) + 1;
  939.         wp->map[x][y].jewels = htemp;
  940.         tot_sect++;
  941.         tot_jewels += htemp;
  942.         if (max_jewel < htemp) { max_jewel = htemp; }
  943.         if (htemp > 20) { hashes[20]++; }
  944.         else { hashes[htemp]++; }
  945.       } else hashes[0]++;
  946.     }
  947.   }
  948.   if (info_flag == 3)
  949.   {
  950.     printf("There are %d sectors with jewels\n\n",tot_sect);
  951.     max_jewel = min(max_jewel, 20);
  952.     for (i= 0 ; i < max_jewel  ; i++)
  953.     {
  954.       printf("There are %d sectors with %d jewels\n",hashes[i],i);
  955.     }
  956.     if (max_jewel < 20)
  957.     {
  958.       printf("There are %d sectors with %d jewels\n",hashes[max_jewel],
  959.                max_jewel);
  960.     } else
  961.     {
  962.       printf("There are %d sectors over %d jewels\n",hashes[max_jewel],
  963.              max_jewel-1);
  964.     }
  965.   }
  966.   if (fp != NULL)
  967.   {
  968.     fprintf(fp,"\nJewels Percentage %d%% at %lf average\n",
  969.                   (int)((1.0 - jewel_per) * 100.0),jewel_avg);
  970.     fprintf(fp,"Total %d Jewels over %d sectors with %d max\n",
  971.                tot_jewels, tot_sect, max_jewel);
  972.     max_jewel = min(max_jewel, 20);
  973.     for (i= 0 ; i < max_jewel  ; i++)
  974.     {
  975.       fprintf(fp,"There are %d sectors with %d jewels\n",hashes[i],i);
  976.     }
  977.     if (max_jewel < 20)
  978.     {
  979.       fprintf(fp,"There are %d sectors with %d jewels\n",hashes[max_jewel],
  980.                 max_jewel);
  981.     } else
  982.     {
  983.        fprintf(fp,"There are %d sectors over %d jewels\n",hashes[max_jewel],
  984.               max_jewel-1);
  985.     }
  986.   }
  987. }
  988.  
  989. gen_soil(wp,dim,lac,average,info_flag,fp)
  990. /* 
  991.    This routine sets the soil value for each sector.  To some degree
  992.    this is done fractally, and to some degree it is determined by
  993.    the terrain type and altitude of the sector in question.  As well
  994.    lots of metal and jewels in the region will limit the ammount of
  995.    food obtainable
  996. */
  997. double dim,lac,average;
  998. int info_flag;
  999. Sworld *wp;
  1000. FILE *fp;
  1001. {
  1002.   double max_soil, min_soil,dtemp,old_min,old_max, total = 0.0, avg ;
  1003.   int i,x,y,htemp,hashes[41], max_s = 0;
  1004.  
  1005.   printf("Generating Soil\n");
  1006.   wp->geo.soil_avg = average;
  1007.   gen_arr(d_map,dim,lac,wp->xmax,wp->ymax,&max_soil,&min_soil);
  1008.   old_min = min_soil; max_soil = -50; min_soil = 50;
  1009. /* Generate the basic soil fertility by fractal methods */
  1010.   for (x = 0 ; x < wp->xmax ; x++)
  1011.   {
  1012.     for (y = 0 ; y < wp->ymax ; y++)
  1013.     {
  1014.       d_map[x][y] = d_map[x][y] - old_min;
  1015.       d_map[x][y] = (d_map[x][y]/ (old_max- old_min)) * 8.0;
  1016. /* 
  1017.       d_map[x][y] = sin(((double)(y* M_PI)/(double)(wp->ymax*1.5))+ (M_PI/6.0))
  1018.                     * d_map[x][y];
  1019. */
  1020.       if (d_map[x][y] < min_soil ) min_soil = d_map[x][y];
  1021.       if (d_map[x][y] > max_soil ) max_soil = d_map[x][y];
  1022.     }
  1023.   }
  1024.   for (i=0;i<40;i++) hashes[i] = 0;
  1025.   for (x = 0 ; x < wp->xmax ; x++)
  1026.   {
  1027.     for (y = 0 ; y < wp->ymax ; y++)
  1028.     {
  1029. /* Modify food production by altitude */
  1030.       switch(wp->map[x][y].altitude) 
  1031.       {
  1032.         case TRENCH:         d_map[x][y] -= 2.0;  break;
  1033.         case SEA_MOUNT:      d_map[x][y] -= 1.0;  break;
  1034.         case OCEAN_PLAINS:   d_map[x][y] += 0.0;  break;
  1035.         case CONT_SHELF:     d_map[x][y] += 1.0;  break;
  1036.         case SHALLOWS:       d_map[x][y] += 2.0;  break;
  1037.         case LOWLANDS:       d_map[x][y] += 2.0;  break;
  1038.         case PLAINS:         d_map[x][y] += 1.0;  break;
  1039.         case HILLS:          d_map[x][y] -= 0.5;  break;
  1040.         case PLATEAU:        d_map[x][y] -= 0.2;  break;
  1041.         case MOUNTAINS:      d_map[x][y] -= 1.0;  break;
  1042.         case MOUNTAIN_PEAK:  d_map[x][y] -= 2.0;  break;
  1043.       }
  1044. /* Modify food production by climate type */
  1045.       switch(wp->map[x][y].altitude) 
  1046.       {
  1047.         case 0:         d_map[x][y] -= 1.5;  break;
  1048.         case 1:         d_map[x][y] -= 0.7;  break;
  1049.         case 2:         d_map[x][y] += 0.0;  break;
  1050.         case 3:         d_map[x][y] += 0.0;  break;
  1051.         case 4:         d_map[x][y] += 0.0;  break;
  1052.         case 5:         d_map[x][y] += 0.0;  break;
  1053.         case 6:         d_map[x][y] += 0.6;  break;
  1054.         case 7:         d_map[x][y] += 0.2;  break;
  1055.         case 8:         d_map[x][y] += 0.0;  break;
  1056.         case 9:         d_map[x][y] -= 0.5;  break;
  1057.         case 10:        d_map[x][y] -= 1.1;  break;
  1058.       }
  1059.    
  1060. /* Modify food production by terrain type */
  1061.       switch(wp->map[x][y].terrain)
  1062.       {
  1063.         case -5:  d_map[x][y] += 0.0;  break;
  1064.         case -4:  d_map[x][y] += 0.0;  break;
  1065.         case -3:  d_map[x][y] += 0.0;  break;
  1066.         case -2:  d_map[x][y] += 1.0;  break;
  1067.         case -1:  d_map[x][y] += 1.0;  break;
  1068.         case 0 :  d_map[x][y] -= 2.0;  break;
  1069.         case 1:   d_map[x][y] -= 1.0;  break;
  1070.         case 2:   d_map[x][y] += 0.0;  break;
  1071.         case 3:   d_map[x][y] += 1.0;  break;
  1072.         case 4:   d_map[x][y] += 1.5;  break;
  1073.         case 5:   d_map[x][y] += 2.0;  break;
  1074.         case 6:   d_map[x][y] += 2.5;  break;
  1075.       }
  1076. /* Remove food for excess metals and jewels, rounding down */
  1077.       d_map[x][y] -= (int)(wp->map[x][y].metal / 8);
  1078.       d_map[x][y] -= (int)(wp->map[x][y].jewels / 8);
  1079. /* Give the people beneath the see food for fishing */
  1080.       if (wp->map[x][y].altitude < 0)
  1081.       {
  1082.          d_map[x][y] += 1;  /* Fish */
  1083.       }
  1084. /* Minimum soil is 0 */
  1085.       if (d_map[x][y] < 0 )
  1086.       {
  1087.         d_map[x][y] = 0;
  1088.       }
  1089.       total += d_map[x][y];
  1090.     }
  1091.   }
  1092.   avg = total / (double)(wp->xmax * wp->ymax);
  1093.   for (x = 0 ; x < wp->xmax ; x++)
  1094.   {
  1095.     for (y = 0 ; y < wp->ymax ; y++)
  1096.     {
  1097.       htemp = (int)(((d_map[x][y]/avg)*average) + 0.49);
  1098.       if (max_s < htemp) { max_s = htemp;}
  1099.       if (htemp > 20) { hashes[20]++; }
  1100.       else { hashes[htemp]++; }
  1101.       wp->map[x][y].soil = htemp;
  1102.     }
  1103.   }
  1104.   if (info_flag == 3)
  1105.   {
  1106.     max_s = min(max_s, 20);
  1107.     for (i= 0 ; i < max_s  ; i++)
  1108.     {
  1109.       printf("There are %d sectors with %d soil\n",hashes[i],i);
  1110.     }
  1111.     if (max_s < 20)
  1112.     {
  1113.       printf("There are %d sectors with %d soil\n",hashes[max_s],max_s);
  1114.     } else
  1115.     {
  1116.       printf("There are %d sectors over %d soil\n",hashes[max_s],max_s-1);
  1117.     }
  1118.   }
  1119.   if (fp != NULL)
  1120.   {
  1121.     fprintf(fp,"\nSoil Adjustment Factor %lf Maximum is %d\n",average,max_s);
  1122.     max_s = min(max_s, 20);
  1123.     for (i= 0 ; i < max_s  ; i++)
  1124.     {
  1125.       fprintf(fp,"There are %d sectors with %d soil\n",hashes[i],i);
  1126.     }
  1127.     if (max_s < 20)
  1128.     {
  1129.       fprintf(fp,"There are %d sectors with %d soil\n",hashes[max_s],max_s);
  1130.     } else
  1131.     {
  1132.       fprintf(fp,"There are %d sectors over %d soil\n",hashes[max_s],max_s-1);
  1133.     }
  1134.   }
  1135. }
  1136.  
  1137. explain(help_num)
  1138. int help_num;
  1139. {
  1140.   switch(help_num)
  1141.   {
  1142.     case 0:
  1143.     {
  1144.       printf("The fractal dimenstion of a given region determines it's\n");
  1145.       printf("relative smoothness. A number close to 2 will be very smooth\n");
  1146.       printf("as the surface is trying to get closer to a plane (a two \n");
  1147.       printf("dimensional object) and as it gets closer to 3 it will\n");
  1148.       printf("become more and more jagged, trying to approximate a space\n");
  1149.       printf("filling surface.  The value must be between 2 and 3\n");
  1150.       printf("but not equal to either 2 or 3\n");
  1151.       break;
  1152.     }
  1153.     case 1:
  1154.     {
  1155.       printf("Percentages are integers between 0 and 100 inclusive\n");
  1156.       break;
  1157.     }
  1158.     case 2:
  1159.     {
  1160.       printf("A default world is one in which the default settings are\n");
  1161.       printf("used with respect to world design.   The user is left with\n");
  1162.       printf("the options concerning width, height, and water percentage\n\n");
  1163.       printf("A customized world allows the user to choose the options at\n");
  1164.       printf("each step in the process (such as metal level etc.)\n\n");
  1165.       printf("A customized world with confirmation will use the values\n");
  1166.       printf("given to create a world, and then will show some statistics\n");
  1167.       printf("at each step, asking the user to confirm that that is indeed\n");
  1168.       printf("what they had in mind.  This is the most verbose option.\n");
  1169.       break;
  1170.     }
  1171.     case 4:
  1172.     {
  1173.       printf("Both the height and width of the world must be integers\n");
  1174.       printf("which are at least 8 and at most whatever you machine can\n");
  1175.       printf("handle.  Be aware that there is a lot of memory usage per\n");
  1176.       printf("sector, so you may run out of swap space and have to restart\n");
  1177.       printf("if you are overly optimistic.\n");
  1178.       break;
  1179.     }
  1180.     default:
  1181.     {
  1182.       printf("No help is available for this topic at this time \n");
  1183.       break;
  1184.     }
  1185.   }
  1186. }
  1187.  
  1188. get_int(prompt, help_num, value)
  1189. char *prompt;
  1190. int help_num, *value;
  1191. {
  1192.   int rtvl;
  1193.   char tmp[100];
  1194.   
  1195.   rtvl = -100;
  1196.   while (rtvl == -100)
  1197.   {
  1198.     printf("%s",prompt);
  1199.     fgets(tmp, 99,stdin);
  1200.     if (sscanf(tmp,"%d",value) == 1)
  1201.     {
  1202.       rtvl = 0;
  1203.     } else if (tmp[0] == '?')
  1204.     {
  1205.       explain(help_num);
  1206.     }
  1207.   }
  1208.   return rtvl;
  1209. }
  1210.  
  1211. get_double(prompt, help_num, value)
  1212. char *prompt;
  1213. int help_num;
  1214. double *value;
  1215. {
  1216.   int rtvl;
  1217.   char tmp[100];
  1218.   
  1219.   rtvl = -100;
  1220.   while (rtvl == -100)
  1221.   {
  1222.     printf("%s",prompt);
  1223.     fgets(tmp, 99,stdin);
  1224.     if (sscanf(tmp,"%lf",value) == 1)
  1225.     {
  1226.       rtvl = 0;
  1227.     } else if (tmp[0] == '?')
  1228.     {
  1229.       explain(help_num);
  1230.     }
  1231.   }
  1232.   return rtvl;
  1233. }
  1234.  
  1235. set_compressed()
  1236. {
  1237.   char s[100];
  1238.  
  1239.   printf("\nDo you wish the world file to be compressed? ");
  1240.   fgets(s,99,stdin);
  1241.   if ((s[0] == 'y') || (s[0] == 'Y'))
  1242.   {
  1243.     compressed_world = 1;
  1244.   }
  1245.   printf("\nYou can change your mind at any time by manually compressing or\n");
  1246.   printf("uncompressing the file %s/%s\n\n\n",libdir,WORLD_FILE);
  1247. }
  1248.  
  1249.  
  1250. main (argc, argv)
  1251.      int argc;
  1252.      char *argv[];
  1253. {
  1254.   extern char *optarg;
  1255.   extern int optind;
  1256.   int i,j, percent, info_flag = 0, conf_flag;
  1257.   int c;
  1258.   double fracdim = -1.0,lacun = (2.0/3.0), perc_d, average;
  1259.   FILE *fp;
  1260.  
  1261.   strcpy(libdir, DEF_LIBDIR);
  1262.  
  1263.   while ((c = getopt(argc, argv, "d:--")) != EOF)
  1264.   {
  1265.     switch (c)
  1266.     {
  1267.       case 'd':
  1268.         strcpy(libdir, optarg);
  1269.         break;
  1270.     }
  1271.   }
  1272.  
  1273.   if (chdir(libdir) == -1) {
  1274.     fprintf(stderr,"Error: cannot cd to directory %s\n",libdir);
  1275.     clean_exit();
  1276.     exit();
  1277.   }
  1278.   SRND(time(0L));        /* initialize random number generator */
  1279.   read_races();            /* get races from races file */
  1280.   world.turn = 0;
  1281.   if ((fp = fopen(STATFILE,"w")) == NULL)
  1282.   {
  1283.     fprintf(stderr,"Error: Could not write to specified directory\n");
  1284.     fprintf(stderr,"Please check permissions and try again\n");
  1285.     clean_exit();
  1286.     exit(1);
  1287.   }
  1288.  
  1289.   printf("At any prompt hit ? and return to get more information\n");
  1290.   printf("(if there is anything more available)\n\n");
  1291.  
  1292.   printf("Do you wish 1) A default settings world 2) A customized world\n");
  1293.   printf("         or 3) A customized world with confirmed completions \n");
  1294.   
  1295.   info_flag = -1;
  1296.   while ((info_flag < 0) || (info_flag > 3))
  1297.   {
  1298.     get_int("Choice (1,2,3) : ",2,&info_flag);
  1299.   }
  1300.  
  1301.   printf("\nThe world will be shaped like a torus, as that is the only\n");
  1302.   printf("shape implemented as of yet.\n");
  1303.   world.geo.topology = TORUS;
  1304.   init_wrap();
  1305.  
  1306.   world.xmax = -1;
  1307.   while (world.xmax < 8 )
  1308.   {
  1309.     get_int("Please enter the width of the world (min 8): ",4,&(world.xmax));
  1310.   }
  1311.   world.ymax = -1;
  1312.   while (world.ymax < 8 )
  1313.   {
  1314.     get_int("Please enter the height of the world (min 8): ",4,&(world.ymax));
  1315.   }
  1316.   
  1317.   init_d_map(world.xmax,world.ymax);
  1318.   if ((world.map = (Ssector **)malloc(sizeof(Ssector *) * world.xmax)) == NULL)
  1319.   {
  1320.     mem_error();
  1321.   }
  1322.   for (i=0;i<world.xmax;i++)
  1323.   {
  1324.     if ((world.map[i] = (Ssector *)malloc(sizeof(Ssector)*world.ymax)) == NULL)
  1325.     {
  1326.       mem_error();
  1327.     }
  1328.   }
  1329.   for (i=0;i<world.xmax;i++)
  1330.   {
  1331.     for (j=0;j<world.ymax;j++)
  1332.     {
  1333.       init_sector(world.map,i,j);
  1334.     }
  1335.   }
  1336.  
  1337.   conf_flag = 0;
  1338.   while (conf_flag != 1)
  1339.   {
  1340.    if (info_flag == 1)
  1341.    {
  1342.      fracdim = 2.75;
  1343.    } else
  1344.    {
  1345.     if (conf_flag != 2)
  1346.     {
  1347.      printf("\nThe altitude will be determined using fractal methods. You\n");
  1348.      printf("should enter the value for the fractal dimension of the\n");
  1349.      printf("world. The number should be between 2 and 3, not inclusive.\n");
  1350.      printf("The suggested value is 2.75\n");
  1351.      fracdim = 0;
  1352.      while ((fracdim <= 2) || (fracdim >=3))
  1353.      {
  1354.        get_double("Dimension is : ",0,&fracdim);
  1355.      }
  1356.     } else { fracdim += 3.0; }
  1357.    }
  1358.    fracdim = 3.0 - fracdim;
  1359.    if (conf_flag != 2)
  1360.    {
  1361.     printf("\nPlease enter the percentage of water you wish in your\n");
  1362.     printf("world.  The value must be between 0 and 100.\n");
  1363.     percent = -1;
  1364.     while ((percent < 0 ) || (percent > 100))
  1365.     {
  1366.       get_int("Percentage of water: ",1,&percent);
  1367.     }
  1368.     perc_d = (double)percent/100.0;
  1369.    }
  1370.    gen_alt(&world,perc_d,fracdim,lacun,info_flag,fp);
  1371.    if (info_flag == 3)
  1372.    {
  1373.      conf_flag = -1;
  1374.      while ((conf_flag < 1) || (conf_flag > 3))
  1375.      {
  1376.        get_int("1) Ok Proceed 2) Redo w/same 3) Reenter stats : ",
  1377.                  3,&conf_flag);
  1378.      }
  1379.    } else { conf_flag = 1; }
  1380.   }
  1381.  
  1382.   conf_flag = 0;
  1383.   if (info_flag == 1)
  1384.   {
  1385.     fracdim = 0.7;
  1386.     gen_climate(fracdim,lacun,&world,info_flag,fp);
  1387.   } else
  1388.   {
  1389.    while (conf_flag != 1)
  1390.    {
  1391.     if (conf_flag != 2)
  1392.     {
  1393.       printf("\nThe climate will be fractally distributed.  The entered\n");
  1394.       printf("dimension is a value between 2 and 3 not inclusive.  A \n");
  1395.       printf("suggested value would be 2.3 \n");
  1396.       fracdim = 0;
  1397.       while ((fracdim <= 2) || (fracdim >=3))
  1398.       {
  1399.         get_double("Dimension is : ",0,&fracdim);
  1400.       }
  1401.       fracdim = 3.0 - fracdim;
  1402.     }
  1403.     gen_climate(fracdim,lacun,&world,info_flag,fp);
  1404.     if (info_flag == 3)
  1405.     {
  1406.       conf_flag = -1;
  1407.       while ((conf_flag < 1) || (conf_flag > 3))
  1408.       {
  1409.         get_int("1) Ok Proceed 2) Redo w/same 3) Reenter stats : ",
  1410.                   3,&conf_flag);
  1411.       }
  1412.     } else { conf_flag = 1; }
  1413.    }
  1414.   }
  1415.   adjust_terrain(&world);
  1416.  
  1417.   conf_flag = 0;
  1418.   if (info_flag == 1)
  1419.   {
  1420.     perc_d = 1.0 - 0.15;
  1421.     average = 4.5;
  1422.     gen_metal(&world,perc_d,average,info_flag,fp);
  1423.   } else 
  1424.   {
  1425.    while (conf_flag != 1)
  1426.    {
  1427.     if (conf_flag != 2)
  1428.     {
  1429.       printf("\nPlease enter the percentage of sectors with metal, and the\n");
  1430.       printf("average value for those sectors. The suggested values are\n");
  1431.       printf("15 percent and an avererage of 4.5\n");
  1432.       percent = -1;
  1433.       while ((percent < 0 ) || (percent > 100))
  1434.       {
  1435.         get_int("Perctage of sectors with metal: ",1,&percent);
  1436.       }
  1437.       perc_d = 1.0 - ((double)percent/100.0);
  1438.       average = -1.0;
  1439.       while (average < 0.0 )
  1440.       {
  1441.         get_double("Average value of metal sector: ",-1,&average);
  1442.       }
  1443.     }
  1444.     gen_metal(&world,perc_d,average,info_flag,fp);
  1445.     if (info_flag == 3)
  1446.     {
  1447.       conf_flag = -1;
  1448.       while ((conf_flag < 1) || (conf_flag > 3))
  1449.       {
  1450.         get_int("1) Ok Proceed 2) Redo w/same 3) Reenter stats : ",
  1451.                   3,&conf_flag);
  1452.       }
  1453.     } else { conf_flag = 1; }
  1454.    }
  1455.   }
  1456.  
  1457.   conf_flag = 0;
  1458.   if (info_flag == 1)
  1459.   {
  1460.     perc_d = 1.0 - 0.12;
  1461.     average = 4.0;
  1462.     gen_jewel(&world,perc_d, average,info_flag,fp);
  1463.   } else
  1464.   {
  1465.    while (conf_flag != 1)
  1466.    {
  1467.     if (conf_flag != 2)
  1468.     {
  1469.       printf("\nPlease enter the percentage of sectors with jewels, and\n");
  1470.       printf("the average value for those sectors. The suggested values\n");
  1471.       printf("are 12 percent and an avererage of 4.0\n");
  1472.       percent = -1;
  1473.       while ((percent < 0 ) || (percent > 100))
  1474.       {
  1475.         get_int("Perctage of sectors with jewels: ",1,&percent);
  1476.       }
  1477.       perc_d = 1.0 - ((double)percent/100.0);
  1478.       average = -1.0;
  1479.       while (average < 0.0 )
  1480.       {
  1481.         get_double("Average value of jewel sector: ",-1,&average);
  1482.       }
  1483.     }
  1484.     gen_jewel(&world,perc_d, average,info_flag,fp);
  1485.     if (info_flag == 3)
  1486.     {
  1487.       conf_flag = -1;
  1488.       while ((conf_flag < 1) || (conf_flag > 3))
  1489.       {
  1490.         get_int("1) Ok Proceed 2) Redo w/same 3) Reenter stats : ",
  1491.                   3,&conf_flag);
  1492.       }
  1493.     } else { conf_flag = 1; }
  1494.    }
  1495.   }
  1496.  
  1497.   conf_flag = 0;
  1498.   if (info_flag == 1)
  1499.   {
  1500.     average = 5.0;
  1501.     gen_soil(&world,fracdim,lacun,average,info_flag,fp);
  1502.   } else
  1503.   {
  1504.    while (conf_flag != 1)
  1505.    {
  1506.     if (conf_flag != 2)
  1507.     {
  1508.       printf("\nPlease enter the value for the average soil value\n");
  1509.       printf("5.0 is the suggested average.  Be careful with soil\n");
  1510.       average = -1.0;
  1511.       while (average < 0.0 )
  1512.       {
  1513.         get_double("Richness of soil: ",-1,&average);
  1514.       }
  1515.     }
  1516.     gen_soil(&world,fracdim,lacun,average,info_flag,fp);
  1517.     if (info_flag == 3)
  1518.     {
  1519.       conf_flag = -1;
  1520.       while ((conf_flag < 1) || (conf_flag > 3))
  1521.       {
  1522.         get_int("1) Ok Proceed 2) Redo w/same 3) Reenter stats : ",
  1523.                   3,&conf_flag);
  1524.       }
  1525.     } else { conf_flag = 1; }
  1526.    }
  1527.   }
  1528.   init_gamemaster(world.nations);
  1529.   world.n_nations = 1;
  1530. /*  world.geo.depth = 2;
  1531.   world.geo.sides = 1;
  1532. */
  1533.   fclose (fp);
  1534.   set_compressed();
  1535.   write_world(&world, WORLD_FILE);
  1536.   set_update_time();
  1537.   exit(0);
  1538. }
  1539.  
  1540. clean_exit(){};
  1541.  
  1542.