Advertisement
Guest User

asthmatic_thematic

a guest
Feb 17th, 2011
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.61 KB | None | 0 0
  1. //================================================================================
  2.  
  3. // RELEASED UNDER GNU LICENSE
  4. //   see www.gnu.org/licenses/gpl.html
  5. // asthmatic_thematic
  6.  
  7. //================================================================================
  8. // worldgen.c ====================================================================
  9. //================================================================================
  10.  
  11. //include <cstdlib>
  12. #include <time.h>
  13. //include <iostream>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include "math.h"
  17.  
  18. //================================================================================
  19.  
  20. // compiling and running
  21. //   gcc worldgen.c ; ./a.out
  22. // plotting data: use eg gnuplot
  23. //   cd to correct directory:
  24. //     cd 'dir'
  25. //   set views:
  26. //     set pm3d map
  27. //     set zrange [0:10000]
  28. //   map data
  29. //     splot 't.txt' matrix
  30. //     (or e.txt, or w.txt, ...)
  31. // selecting types of data
  32. //   either use gnuplot data ranges,
  33. //   or go to "output" section below:
  34. //     choose a structure to examine,
  35. //     and set it to a high value
  36. //       (for reproducibility, set
  37. //       time now defn to a constant)
  38. //
  39.  
  40. // this should be run at greater resolution: say 1028x1028
  41. //   this would allow smoothing for more realistic thin rivers & lakes
  42. //     help making lakes: topographic fill
  43. //   tome coast would be smoother
  44. // converting to tome format should be easy from this high resolution
  45. //   use rectangles appropriately scaled to get 170x58 tome size
  46. //   if shallow water in area, make whole tile shallow; same for towns etc
  47. //   otherwise, use most common terrain as tile type
  48.  
  49. //================================================================================
  50.  
  51. #define TIMENOW (unsigned)time(0)
  52.  
  53. #define SIZE 512
  54. //256
  55. #define PIE 3.1415927
  56.  
  57. // RANDOM NUMBER FUNCTIONS
  58. #define R_SZ (int)(rndmf(SIZE))
  59. #define R_ONE rndmf(1.0)
  60. #define R_1F1 (1.0-2.0*rndmf(1.0))
  61. #define R_1I1 (1-(int)(rndmf(2.999999999999)))
  62.  
  63. // LENGTH SCALES
  64. #define H_SCALE 2.0
  65. // roughness goes up as scale below goes down
  66. #define SCALE 0.55
  67. #define DOWNSLOPE 0.005
  68. #define DOWNVAR 1.0
  69. #define WET_SCALE 1.8
  70. #define BIAS_STRENGTH 0.0
  71.  
  72. // MOUNTAINS
  73. #define N_MTN_RANGES 7
  74. #define MTN_JIGGLE 0.7
  75. #define MTN_WANDER 4.0
  76. #define MTN_JUMP 0.07
  77. #define MTN_WIDTH 0.04
  78. #define MTN_ADD .006
  79.  
  80. // RIVERS AND SPRINGS
  81. #define RIV_STEP 3
  82. #define RIV_WIDTH 3
  83. #define SM_WIDTH 5
  84. #define N_SPRINGS 3
  85. #define H_SPRING_MIN 0.4
  86. #define H_SPRING_MAX 0.9
  87. #define N_ANTI_SPRINGS 6
  88. #define H_ANTI_MIN -0.3
  89. #define H_ANTI_MAX -0.001
  90. #define RIV_MAXL SIZE/4
  91. #define LAKE_REPEAT 10
  92. #define LAKE_WALKS 10
  93.  
  94. // FORESTS
  95. #define N_FORESTS 20
  96. #define N_FOR_JUMPS 30
  97. #define N_FOR_WALKS 40
  98. #define N_FOR_FAR 10
  99. #define FOREST_WIDTH 2
  100. #define H_FOREST_MIN 0.05
  101. #define H_FOREST_MAX 0.7
  102.  
  103. // DESERTS
  104. #define N_DESERTS 5
  105. #define DESERT_WIDTH 8
  106. #define N_DES_JUMPS 10
  107. #define N_DES_WALKS 20
  108. #define N_DES_FAR 4
  109. #define SCORCH_J 0.1
  110.  
  111. // TUNDRA, GLACIERS
  112. #define TUNDRA_J 0.8
  113. #define N_GLACIER_WALKS 10
  114. #define GLACIER_WIDTH 8
  115.  
  116. // TOPOGRAPHY
  117. #define N_CONE 9
  118. #define H_CONE 1.8
  119. #define SCALE_CONE 0.01
  120. #define H_HILLS 0.2
  121. #define H_MTN   0.5
  122. #define H_PEAK  0.9
  123.  
  124. // TERRAINS
  125. //   including shallow and deep water
  126. #define PLAIN     1
  127. #define DESERT    2
  128. #define WOODS     3
  129. #define HILLS     4
  130. #define TUNDRA    5
  131. #define SHALLOW   6
  132.  
  133. #define SCORCH    12
  134. #define FOREST    13
  135. #define MOUNTAIN  14
  136. #define GLACIER   15
  137. #define DEEP      16
  138.  
  139. #define PEAK      24
  140.  
  141. #define DIFFIMPASS 10
  142.  
  143. // TOWNS AND SITES
  144.  
  145. #define T_START   50
  146. #define T_HUMAN   51
  147. #define T_SANDM   52
  148. #define T_ELF     53
  149. #define T_DWARF   54
  150. #define T_SNOWM   55
  151. #define T_RIVM    56
  152.  
  153. #define T_BURNM   62
  154. #define T_TREEM   63
  155. #define T_MTNM    64
  156. #define T_ICEM    65
  157. #define T_OCEANM  66
  158.  
  159. /*
  160. later: ease of moving for races
  161.  
  162. hum  1  2   3  4  5  6 12  13  14  15
  163. elf  3  1  13  2  4  5  6  12  14  15
  164. dwf  4  1  14  2  3  5  6  12  13  15
  165. sno  5 15  14 ...
  166. */
  167.  
  168. void fill1DFractArray (float *, int, int, float, float);
  169. void fill2DFractArray (float *, int, int, float, float);
  170.  
  171. #include "dmnd_square.c"
  172.  
  173. int main() {
  174.  
  175.  
  176.   float * ffaa;
  177.   int hsize=SIZE/2;
  178.   float h1 = 1.0;
  179.   float h2 = 0.4;
  180.   float h_main = 0.5;
  181.   float h_polar = 1.5;
  182.  
  183.   float dist, angle;
  184.   int i, j;
  185.   int t;
  186.   int i1,j1,i2,j2;
  187.   float divs;
  188.   int ii,jj;
  189.   int k, kk;
  190.   int irndrad, jrndrad;
  191.  
  192.   float elev[SIZE][SIZE];
  193.   int terr[SIZE][SIZE];
  194.   float wet[SIZE][SIZE];
  195.   unsigned nowtime;
  196.  
  197.   nowtime = TIMENOW;
  198.   srand(nowtime);
  199.  
  200.   //================================================================
  201.   // set basic topography
  202.   ffaa = alloc2DFractArray(SIZE);
  203.   fill2DFractArray (ffaa, SIZE, TIMENOW, H_SCALE, SCALE);
  204.  
  205.   for (i=0; i<SIZE; i++) {
  206.     for (j=0; j<SIZE; j++) {
  207.       elev[i][j] = ffaa[(i*SIZE)+j] + h_main;
  208.     }
  209.   }
  210.  
  211.   //================================================================
  212.   // set fault/tectonic bias a la continents
  213.   float bias_angle;
  214.   bias_angle = R_ONE*2*PIE;
  215.  
  216.   //================================================================
  217.   // scale down radially from center
  218.   int igeo, jgeo;
  219.   float set_dist, set_slop;
  220.   float * fdist, * fslop;
  221.   float angle_norm, angle_rem;
  222.   float leave_pole;
  223.   float bias_near;
  224.  
  225.   fdist = alloc1DFractArray(16); //17 //distance to geo center
  226.   fslop = alloc1DFractArray(16); //17 //slope to use
  227.  
  228.   for (k=0; k<2; k++) {
  229.     fill1DFractArray(fdist, 16, TIMENOW, SIZE/3.0, .1);
  230.     fill1DFractArray(fslop, 16, TIMENOW, DOWNSLOPE, .2);
  231.    
  232.     igeo = R_SZ/3. + SIZE/3.;
  233.     jgeo = R_SZ/3. + SIZE/3.;
  234.  
  235.     for (i=0; i<SIZE; i++) {
  236.       for (j=0; j<SIZE; j++) {
  237.         dist = distance(i,igeo,j,jgeo);
  238.         angle = atan2(i-igeo, j-jgeo) + PIE;
  239.         angle_norm = angle * (16./(2.*PIE));
  240.  
  241.         // interpolate
  242.         angle_rem = angle_norm-(int)angle_norm;
  243.         set_dist = (1-angle_rem)*fdist[(int)angle_norm] +
  244.           angle_rem*fdist[(int)angle_norm+1];
  245.         set_dist += SIZE/3.;
  246.  
  247.         // fault bias...
  248.         bias_near = 1 + BIAS_STRENGTH*cos(angle-bias_angle)*(1+0.1*R_1F1);
  249.  
  250.         set_slop =
  251.           -DOWNSLOPE * (1+DOWNVAR*fslop[(int)(angle*16./360.)]);
  252.  
  253.         // ARCTIC: adjust scale down to get more land up north
  254.         if (j>3.*SIZE/4.) set_slop *= (1 - h_polar*0.5*4.*(j-3.*SIZE/4.)/SIZE);
  255.  
  256.         if (dist > set_dist) elev[i][j] += set_slop*(dist-set_dist);
  257.       }
  258.     }
  259.   }
  260.  
  261.   //================================================================
  262.   // raise and lower topographic random cones
  263.   float loci, locj, cone_height, cone_rad;
  264.  
  265.   for (k=0; k<N_CONE; k++) {
  266.     loci = R_SZ;
  267.     locj = R_SZ;
  268.     cone_height = H_CONE    * (1.25 - 2*R_ONE);
  269.     cone_rad =    SIZE/6.0  * (1.5 -    R_ONE);
  270.     fill1DFractArray(fdist, 16, TIMENOW, cone_rad, SCALE_CONE);
  271.     for (i=0; i<SIZE; i++) {
  272.       for (j=0; j<SIZE; j++) {
  273.         //  if (distance(loci,i,locj,j) < radcone) elev[i][j] -= h_cone;
  274.         dist = distance(i,loci,j,locj);
  275.         angle = 360/(2*PIE)*atan2(i-loci, j-locj)+180.;
  276.         angle_norm = angle*16./360.;
  277.         angle_rem = angle_norm-(int)angle_norm;
  278.  
  279.         // interpolate
  280.         set_dist = (1-angle_rem)*fdist[(int)angle_norm] +
  281.           angle_rem*fdist[(int)angle_norm+1];
  282.         set_dist += cone_rad;
  283.  
  284.         if (dist < set_dist)
  285.           elev[i][j] -=
  286.             cone_height * pow((set_dist-dist)/set_dist,2);
  287.       }
  288.     }
  289.   }
  290.  
  291.   //================================================================
  292.   // could raise arctic arctic a bit more
  293.   //  for (i=0; i<SIZE; i++)
  294.   //    for (j=3.*SIZE/4.; j<SIZE; j++)
  295.   //      elev[i][j] += h_polar * R_ONE * 4.*(j-3.*SIZE/4.)/SIZE;
  296.  
  297.   //================================================================
  298.   // add mountain ranges
  299.   float * fi;
  300.   float * fj;
  301.   float mtn_wid;
  302.   int kkk, l1, l2;
  303.   int mtn_width;
  304.   int n, kkkmax;
  305.   fi = ((float *) malloc (sizeof(float) * 7)); //alloc1DFractArray(6); //7
  306.   fj = ((float *) malloc (sizeof(float) * 7)); //alloc1DFractArray(6); //7
  307.  
  308.   for (n=0; n<N_MTN_RANGES; n++) {
  309.   i1 = R_SZ;
  310.   j1 = R_SZ;
  311.   i2 = R_SZ;
  312.   j2 = R_SZ;
  313.  
  314.   segment(fi, i1, i2, 6); //fi[6] = i2;
  315.   segment(fj, j1, j2, 6); //fj[6] = j2;
  316.  
  317.   for (kkk=0; kkk<6; kkk++) {
  318.     divs = distance(fi[kkk],fi[kkk+1],fj[kkk],fj[kkk+1]);
  319.     i1 = fi[kkk]   + R_1I1 * MTN_JIGGLE * (R_SZ/80. + 1);
  320.     i2 = fi[kkk+1] + R_1I1 * MTN_JIGGLE * (R_SZ/80. + 1);
  321.     j1 = fj[kkk]   + R_1I1 * MTN_JIGGLE * (R_SZ/80. + 1);
  322.     j2 = fj[kkk+1] + R_1I1 * MTN_JIGGLE * (R_SZ/80. + 1);
  323.  
  324.     divs = distance(i1,i2,j1,j2);
  325.     for (k=0; k <= divs; k++) {
  326.       ii = k*(i2-i1)/divs + i1;
  327.       jj = k*(j2-j1)/divs + j1;
  328.  
  329.       for (kk=0; kk<MTN_WANDER*SIZE/15.; kk++) {
  330.         irndrad = MTN_JUMP  * 3*R_1F1 * SIZE/20.;
  331.         ii+=irndrad;
  332.         jrndrad = MTN_JUMP  * 3*R_1F1 * SIZE/20.;
  333.         jj+=jrndrad;
  334.         mtn_wid = MTN_WIDTH * 5*R_1F1 * SIZE/10.;
  335.  
  336.         for (l1=-mtn_wid; l1<mtn_wid; l1++) {
  337.           for (l2=-mtn_wid; l2<mtn_wid; l2++) {
  338.             if ((ii+l1)>=0 && (ii+l1)<SIZE && (jj+l2)>=0 && (jj+l2)<SIZE) {
  339.                 elev[ii+l1][jj+l2] += MTN_ADD * R_ONE;
  340.             }
  341.           }
  342.         }
  343.       }
  344.     }
  345.   }
  346.   }
  347.  
  348.   //================================================================
  349.   // raise map so there is 70% land: quick and dirty version
  350.   //   (should use quicksort; choose 70% item; add constant so it's zero)
  351.   int num_above = 0;
  352.   float correction = 0.0;
  353.   float h_corr = 0.3;
  354.  
  355.   for (i=0; i<SIZE; i++)
  356.     for (j=0; j<SIZE; j++)
  357.       if (elev[i][j] > 0) num_above++;
  358.   if (num_above > 0.85*SIZE*SIZE) correction=-h_corr;
  359.   if (num_above < 0.60*SIZE*SIZE) correction=+h_corr;
  360.   if (correction != 0.0)
  361.     for (i=0; i<SIZE; i++)
  362.       for (j=0; j<SIZE; j++)
  363.         elev[i][j] += correction;
  364.  
  365.   //================================================================
  366.   // ERODE SHORELINES (to make a bit smoother edges)
  367.  
  368.   //================================================================
  369.   // SMALL DECREASE TO EDGES (to minimize need for borders, below)
  370.  
  371.   //================================================================
  372.   // SCALE ABOVEGROUND TO ONE
  373.   float maxval = -100.0;
  374.   for (i=0; i<SIZE; i++) for (j=0; j<SIZE; j++)
  375.     if (elev[i][j]>maxval) maxval=elev[i][j];
  376.   for (i=0; i<SIZE; i++) for (j=0; j<SIZE; j++)
  377.     if (elev[i][j]>0) elev[i][j] /= maxval;  
  378.  
  379.   //================================================================================
  380.   // END OF TOPOGRAPHY==============================================================
  381.   // START TERRAIN==================================================================
  382.   //================================================================================
  383.  
  384.   //================================================================
  385.   // FORM TERRAIN MAP
  386.  
  387.   // convert to initial terrain
  388.   for (i=0; i<SIZE; i++) {
  389.     for (j=0; j<SIZE; j++) {
  390.       t = DEEP;
  391.       if (elev[i][j] > 0 && elev[i][j] < H_HILLS) t = PLAIN; //plain
  392.       if (elev[i][j] > H_HILLS && elev[i][j] < H_MTN) t = HILLS; //hill
  393.       if (elev[i][j] > H_MTN && elev[i][j] < H_PEAK) t = MOUNTAIN;  //mtn
  394.       if (elev[i][j] > H_PEAK) t = PEAK; // peak
  395.       terr[i][j] = t;
  396.     }
  397.   }
  398.  
  399.   //================================================================
  400.   // ADD SPRINGS
  401.  
  402.   int notmid;
  403.   int spr_x[N_SPRINGS];
  404.   int spr_y[N_SPRINGS];
  405.   int x, y;
  406.   int antispr_x[N_ANTI_SPRINGS];
  407.   int antispr_y[N_ANTI_SPRINGS];
  408.  
  409.   // i guess this could loop infinitely in tiny maps: careful
  410.   for (i=0; i<N_SPRINGS; i++) {
  411.     notmid = 1;
  412.     while (notmid) {
  413.       x = R_SZ;
  414.       y = R_SZ;
  415.       if (elev[x][y]>H_SPRING_MIN && elev[x][y]<H_SPRING_MAX && y>SIZE/5.) notmid=0;
  416.     }
  417.     spr_x[i] = x;
  418.     spr_y[i] = y;
  419.   }
  420.   for (i=0; i<N_ANTI_SPRINGS; i++) {
  421.     notmid = 1;
  422.     while (notmid) {
  423.       x = R_SZ;
  424.       y = R_SZ;
  425.       if (elev[x][y]>H_ANTI_MIN && elev[x][y]<H_ANTI_MAX && y>SIZE/5.) notmid=0;
  426.     }
  427.     antispr_x[i] = x;
  428.     antispr_y[i] = y;
  429.   }
  430.  
  431.   //================================================================
  432.   // RUN RIVERS & LAKES
  433.   // could use nelder mead or something better here
  434.  
  435.   float minval = 1000000.0;
  436.   int mindex=0;
  437.   int notsea, notlake, nsteps;
  438.   // these are dangerous definitions: floats vs ints
  439.   float spring_elev, lastelev, angle_down, new_x, new_y, xx, yy;
  440.   float i_grad, j_grad, old_i, old_j;
  441.   int orig_x, orig_y;
  442.  
  443.   for (kkk=0; kkk<N_SPRINGS; kkk++) {
  444.     xx = spr_x[kkk]; yy = spr_y[kkk];
  445.     notsea = notlake = 1;
  446.     nsteps = 0;
  447.     while (1) {
  448.       nsteps++;
  449.  
  450.       i_grad = 0.0;
  451.       for (i=-SM_WIDTH; i<=SM_WIDTH; i++)
  452.         for (j=-SM_WIDTH; j<=SM_WIDTH; j++)
  453.           if ((xx+i)<SIZE && (xx+i)>=0 && (yy+j)<SIZE && (yy+j)>=0)
  454.             i_grad += i*elev[(int)xx+i][(int)yy+j];
  455.       j_grad = 0.0;
  456.       for (i=-SM_WIDTH; i<=SM_WIDTH; i++)
  457.         for (j=-SM_WIDTH; j<=SM_WIDTH; j++)
  458.           if ((xx+i)<SIZE && (xx+i)>=0 && (yy+j)<SIZE && (yy+j)>=0)
  459.             j_grad += j*elev[(int)xx+i][(int)yy+j];
  460.       angle = atan2(j_grad,i_grad);
  461.  
  462.       new_x = xx - cos(angle)*RIV_STEP;
  463.       new_y = yy - sin(angle)*RIV_STEP;
  464.  
  465.       if ((new_x>=SIZE-1) || (new_x<1) || (new_y>=SIZE-1) || (new_y<1))
  466.         {printf(" -escape- "); break;}
  467.  
  468.       // fill in river
  469.       divs = distance(xx,new_x,yy,new_y);
  470.       for (k=0; k<divs; k++) {
  471.         ii = k*(new_x-xx)/divs + xx;
  472.         jj = k*(new_y-yy)/divs + yy;
  473.         for (i=0; i<RIV_WIDTH; i++) for (j=0; j<RIV_WIDTH; j++) terr[ii+i][jj+j] = SHALLOW;
  474.       }
  475.       xx = new_x; yy = new_y;
  476.  
  477.       if (nsteps > 100) {printf(" -deadlooplake- "); notlake=0; break;}
  478.  
  479.       if (distance(spr_x[kkk],xx,spr_y[kkk],yy)>2*RIV_MAXL) {printf(" -long- "); break;}
  480.  
  481.       // if ocean, quit
  482.       if (elev[(int)new_x][(int)new_y] < 0) {notsea=0; printf(" -ocean- "); break;}
  483.     }
  484.     // lake fill (very very simple right now)
  485.     // future improvements:
  486.     // do we want to avoid lakes right near shore?
  487.     // any easy way to fill topographically?
  488.     //   take endpoint x,y of river
  489.     //   grab radius of 5 around;
  490.     //     if min_elev is not on border, fill from min_elev to half min-max
  491.     //   connect river endpoint x,y to min_elev to make sure river hits lake
  492.     // flow from lakes:
  493.     //   half the time,
  494.     //     use segments to jump to random near point which is lower in elev
  495.     //   restart river from there
  496.     // bigger issue: dont apply shallow immed; make linked list;
  497.     //   if river doesn't make it far, dont bother changing to shallow
  498.     //   if succeeds, apply linked list to make shallow
  499.     // also make random lakes
  500.     if (notlake==0 && elev[(int)new_x][(int)new_y]>0.15) {
  501.       orig_x = xx; orig_y = yy;
  502.       for (i1=0; i1<LAKE_REPEAT; i1++) {
  503.         i = orig_x; j = orig_y;
  504.         for (i2=0; i2<LAKE_WALKS; i2++) {
  505.           terr[i][j] = terr[i+1][j] = terr[i][j+1] = terr[i+1][j+1] = SHALLOW;
  506.           i += R_1I1; j += R_1I1;
  507.         }
  508.       }
  509.     }
  510.   }
  511.  
  512.   //anti-springs
  513.   for (kkk=0; kkk<N_ANTI_SPRINGS; kkk++) {
  514.     xx = antispr_x[kkk]; yy = antispr_y[kkk];
  515.     notsea = notlake = 1;
  516.     nsteps = 0;
  517.     while (1) {
  518.       nsteps++;
  519.  
  520.       i_grad = 0.0;
  521.       for (i=-SM_WIDTH; i<=SM_WIDTH; i++)
  522.         for (j=-SM_WIDTH; j<=SM_WIDTH; j++)
  523.           if ((xx+i)<SIZE && (xx+i)>=0 && (yy+j)<SIZE && (yy+j)>=0)
  524.             i_grad += i*elev[(int)xx+i][(int)yy+j];
  525.       j_grad = 0.0;
  526.       for (i=-SM_WIDTH; i<=SM_WIDTH; i++)
  527.         for (j=-SM_WIDTH; j<=SM_WIDTH; j++)
  528.           if ((xx+i)<SIZE && (xx+i)>=0 && (yy+j)<SIZE && (yy+j)>=0)
  529.             j_grad += j*elev[(int)xx+i][(int)yy+j];
  530.       angle = atan2(j_grad,i_grad);
  531.  
  532.       new_x = xx + cos(angle)*RIV_STEP;
  533.       new_y = yy + sin(angle)*RIV_STEP;
  534.  
  535.       if ((new_x>=SIZE-1) || (new_x<1) || (new_y>=SIZE-1) || (new_y<1))
  536.         {printf(" -escape- "); break;}
  537.  
  538.       // fill in river
  539.       divs = distance(xx,new_x,yy,new_y);
  540.       for (k=0; k<divs; k++) {
  541.         ii = k*(new_x-xx)/divs + xx;
  542.         jj = k*(new_y-yy)/divs + yy;
  543.         if (elev[ii][jj]>0)
  544.           for (i=0; i<RIV_WIDTH; i++) for (j=0; j<RIV_WIDTH; j++) terr[ii+i][jj+j] = SHALLOW;
  545.       }
  546.       xx = new_x; yy = new_y;
  547.  
  548.       if (nsteps > 100) {printf(" -deadlooplake- "); notlake=0; break;}
  549.       if (distance(antispr_x[kkk],xx,antispr_y[kkk],yy)>RIV_MAXL) {printf(" -long- "); break;}
  550.  
  551.     }
  552.     if (notlake==0 && elev[(int)new_x][(int)new_y]>0.15) {
  553.       orig_x = xx; orig_y = yy;
  554.       for (i1=0; i1<LAKE_REPEAT; i1++) {
  555.         i = orig_x; j = orig_y;
  556.         for (i2=0; i2<LAKE_WALKS; i2++) {
  557.           terr[i][j] = terr[i+1][j] = terr[i][j+1] = terr[i+1][j+1] = SHALLOW;
  558.           i += R_1I1; j += R_1I1;
  559.         }
  560.       }
  561.     }
  562.   }
  563.  
  564.   //================================================================
  565.   // DETERMINE RANDOM WETNESS MAP
  566.   fill2DFractArray (ffaa, SIZE, TIMENOW, 1, WET_SCALE);
  567.  
  568.   minval =  100000.0;
  569.   maxval = -100000.0;
  570.   for (i=0; i<SIZE; i++) {
  571.     for (j=0; j<SIZE; j++) {
  572.       wet[i][j] = ffaa[(i*SIZE)+j];
  573.       if (wet[i][j]>maxval) maxval=wet[i][j];
  574.       if (wet[i][j]<minval) minval=wet[i][j];
  575.     }
  576.   }
  577.  
  578.   // normalize to 0-1
  579.   for (i=0; i<SIZE; i++) {
  580.     for (j=0; j<SIZE; j++) {
  581.       wet[i][j] -= minval;
  582.       wet[i][j] /= (maxval-minval);
  583.     }
  584.   }
  585.  
  586.   // make river areas humid
  587.   for (i=0; i<SIZE; i++)
  588.     for (j=0; j<SIZE; j++)
  589.       if (terr[i][j] == SHALLOW)
  590.         for (ii=i-8; ii<i+8; ii++)
  591.           for (jj=j-8; jj<j+8; jj++) wet[ii][jj] += 0.1;
  592.  
  593.   // make south more arid
  594.   for (i=0; i<SIZE; i++)
  595.     for (j=0; j<SIZE/4.; j++)
  596.       wet[i][j] *= j/(SIZE/4.);
  597.  
  598.   //================================================================
  599.   // RUN FORESTS
  600.  
  601.   int for_x[N_FORESTS], for_y[N_FORESTS];
  602.  
  603.   // locations of forest seeds
  604.   for (i=0; i<N_FORESTS; i++) {
  605.     notmid = 1;
  606.     while (notmid) {
  607.       x = R_SZ;
  608.       y = R_SZ;
  609.       //      printf("(%i %i)\n", x, y);
  610.       if (elev[x][y]>H_FOREST_MIN && elev[x][y]<H_FOREST_MAX && wet[x][y]>0.6)
  611.         notmid=0;
  612.     }
  613.     for_x[i] = x;
  614.     for_y[i] = y;
  615.     //    printf("F(%i %i);[%.2f]. ",x,y,wet[x][y]);
  616.   }
  617.  
  618.   int nfj;
  619.   //multiple random walks from same point; jump to new point, repeat
  620.   //check for success by humidity
  621.   for (kkk=0; kkk<N_FORESTS; kkk++) {
  622.     x = for_x[kkk];
  623.     y = for_y[kkk];
  624.     nfj = N_FOR_JUMPS * R_ONE;
  625.     for (i=0; i<nfj; i++) {
  626.       for (j=0; j<N_FOR_WALKS; j++) {
  627.         for (ii=-FOREST_WIDTH; ii<=FOREST_WIDTH; ii++) {
  628.           for (jj=-FOREST_WIDTH; jj<=FOREST_WIDTH; jj++)
  629.             if (terr[x+ii][y+jj] <= TUNDRA && wet[x+ii][y+jj]>(R_ONE+0.1)
  630.                 && elev[x+ii][y+jj]>0 && elev[x+ii][y+jj]<H_MTN)
  631.               terr[x+ii][y+jj] = WOODS;
  632.         }
  633.         x += R_1I1; y += R_1I1;
  634.       }
  635.       // jump to new point; forests spread along latitudes
  636.       x += 1.5 * R_1I1 * R_ONE * N_FOR_FAR;
  637.       y += .75 * R_1I1 * R_ONE * N_FOR_FAR;
  638.       // more forests if humid
  639.       if (wet[x][y]>0.75 && R_ONE>0.1) i--;
  640.     }
  641.   }
  642.  
  643.   //================================================================
  644.   // PLACE DESERTS
  645.  
  646.   int des_x[N_DESERTS], des_y[N_DESERTS];
  647.  
  648.   // desert seeds
  649.   for (i=0; i<N_DESERTS; i++) {
  650.     notmid = 1;
  651.     while (notmid) {
  652.       x = R_SZ;
  653.       y = R_SZ;
  654.       //      printf("(%i %i)\n", x, y);
  655.       if (wet[x][y]<0.5 && elev[x][y]>0 && y/SIZE<0.9) notmid=0;
  656.     }
  657.     des_x[i] = x;
  658.     des_y[i] = y;
  659.     //    printf("D(%i %i);[%.2f]. ",x,y,wet[x][y]);
  660.   }
  661.  
  662.   //multiple random walks from same point; jump to new point, repeat
  663.   for (kkk=0; kkk<N_DESERTS; kkk++) {
  664.     x = des_x[kkk];
  665.     y = des_y[kkk];
  666.     nfj = N_DES_JUMPS * R_ONE;
  667.     for (i=0; i<nfj; i++) {
  668.       for (j=0; j<N_DES_WALKS; j++) {
  669.         for (ii=-DESERT_WIDTH; ii<=DESERT_WIDTH; ii++)
  670.           for (jj=-DESERT_WIDTH; jj<=DESERT_WIDTH; jj++)
  671.             if (terr[x+ii][y+jj] <= TUNDRA &&
  672.                 wet[x+ii][y+jj]<.5 || wet[x+ii][y+jj]<(R_ONE*R_ONE) &&
  673.                 (abs(ii)+abs(jj)) <= DESERT_WIDTH && elev[x+ii][y+jj]>0 &&
  674.                 elev[x+ii][y+jj] < H_MTN)
  675.               if (wet[x+ii][y+jj] < 0.15 && R_ONE<0.3 && y<3.*SIZE/4.)
  676.                 terr[x+ii][y+jj] = SCORCH; else
  677.                 terr[x+ii][y+jj] = DESERT;
  678.         x += 2*R_1I1; y += 2*R_1I1;
  679.       }
  680.       x += R_1I1 * R_ONE * N_DES_FAR;
  681.       y += R_1I1 * R_ONE * N_DES_FAR;
  682.       // deserts in dry areas and along shores and low elevations
  683.       if ((wet[x][y]<0.25 || elev[x][y]<0.04) && R_ONE>0.1) i--;
  684.     }
  685.   }
  686.  
  687.   //================================================================
  688.   // PLACE TUNDRA
  689.   //  note: this turns some mountains (but not peaks) into glaciers
  690.   for (j=SIZE-1; j>TUNDRA_J*SIZE; j--)
  691.     for (i=0; i<SIZE; i++)
  692.       if ((j-TUNDRA_J*SIZE)/(SIZE*(1-TUNDRA_J))*pow(elev[i][j]+0.6,3.0)>R_ONE
  693.            && elev[i][j]>0 && terr[i][j]!=PEAK)
  694.         if (terr[i][j]==MOUNTAIN) terr[i][j]=GLACIER; else terr[i][j] = TUNDRA;
  695.  
  696.   //================================================================
  697.   // SET BOUNDARIES
  698.   // glacier in north;
  699.   // scorching sands in south
  700.   // future boundaries: mountains in east or west; forests in west or east;
  701.   //   (place forest on wetter edge, mountain on higher)
  702.  
  703.   // glacier
  704.   // multiple random walks from top
  705.   for (i=0; i<SIZE; i++) {
  706.     j = SIZE-1;
  707.     x = i; y = j;
  708.     if (elev[x][y]>0 || R_ONE>0.9) {
  709.       for (k=0; k<N_GLACIER_WALKS; k++) {
  710.         for (ii=-GLACIER_WIDTH; ii<=GLACIER_WIDTH; ii++) {
  711.           for (jj=-GLACIER_WIDTH; jj<=GLACIER_WIDTH; jj++) {
  712.             if ((abs(ii)+abs(jj))<=GLACIER_WIDTH
  713.                 && (y+jj)<SIZE && (x+ii)>=0 && (x+ii)<SIZE)
  714.               terr[x+ii][y+jj] = GLACIER;
  715.           }
  716.         }
  717.         if (pow(elev[i][j]+0.6,3.0)>R_ONE
  718.             && (y)<SIZE && (x)>=0 && (x)<SIZE && R_ONE>0.1)
  719.           k--;
  720.         x += R_1I1; y-= (int)(rndmf(2)); // y += R_1I1;
  721.       }
  722.     }
  723.   }
  724.  
  725.   // scorching sands
  726.   float * jdist;
  727.   int jmax;
  728.   float jpow;
  729.   jdist = alloc1DFractArray(SIZE);
  730.   fill1DFractArray(jdist, SIZE, TIMENOW, 1, .05);
  731.  
  732.   for (i=0; i<SIZE; i++) {
  733.     jmax = SIZE*SCORCH_J*(jdist[i]+1.0)*(1+0.05*(R_1F1));
  734.     for (j=0; j<jmax; j++) {
  735.       jpow = pow((jmax-j)/jmax+0.7,5.0);
  736.       if (elev[i][j]>0 && terr[i][j]!=PEAK &&
  737.           (jpow>R_ONE || (elev[i][j]<0.075 && R_ONE>0.1) ||
  738.            (j<jmax*0.1 && R_ONE>0.3))) {
  739.         if (j>0.8*jmax && R_ONE>0.5) terr[i][j] = DESERT; else terr[i][j] = SCORCH;
  740.       }
  741.     }
  742.   }
  743.  
  744.   //================================================================================
  745.   // END OF TERRAIN=================================================================
  746.   // START CIVILIZATIONS============================================================
  747.   //================================================================================
  748.  
  749.   //================================================================
  750.   // place home towns
  751.  
  752.   int town_x[SHALLOW+1], town_y[SHALLOW+1];
  753.  
  754.   // starting town
  755.   while (1) {
  756.     x = R_SZ/2. + SIZE/4.;
  757.     y = R_SZ/2. + SIZE/4.;
  758.     if (elev[x][y] < 0.5) break;
  759.   }
  760.   town_x[0] = x; town_y[0] = y;
  761.   terr[x][y] = T_START;
  762.  
  763.   // normal towns
  764.   for (i=PLAIN; i <= SHALLOW; i++) {
  765.     while (1) {
  766.       x = R_SZ;
  767.       y = R_SZ;
  768.       if (terr[x][y]==i) break;
  769.     }
  770.     town_x[i] = x; town_y[i] = y;
  771.     terr[x][y] = T_START+i;
  772.   }
  773.  
  774.   // extreme towns        
  775.  
  776.   // report
  777.   printf("\nTOWNS\n");
  778.   for (i=0; i <= SHALLOW; i++)
  779.     printf("%i: (%i %i)[%i].\n", i,town_x[i],town_y[i], terr[town_x[i]][town_y[i]]);
  780.  
  781.   /*
  782.   // check accessibility to normal towns
  783.   for (i=1; i <= SHALLOW; i++) {
  784.   if (!exist_path(town_x[0],town_y[0], town_x[i],town_y[i]))
  785.   printf("!!!NO PATH!!! (%i)", i);
  786.   */
  787.  
  788.   // place other dungeons, etc., and check accessibility
  789.  
  790.   //================================================================================
  791.   //================================================================================
  792.   //================================================================================
  793.   // FINISHED: JUST OUTPUT
  794.  
  795.   // J, THEN I, to make map look correct
  796.   FILE *fp_elev;
  797.   FILE *fp_terr;
  798.   FILE *fp_wet;
  799.   fp_elev = fopen("e.txt", "wb");
  800.   fp_terr = fopen("t.txt", "wb");
  801.   fp_wet  = fopen("w.txt", "wb");
  802.  
  803.   //rare odd data in terrain: mash to deep
  804.   //where could this possibly come from...?
  805.   for (i=0; i<SIZE; i++) {
  806.     for (j=0; j<SIZE; j++) {
  807.       if (terr[i][j]<0 || terr[i][j]>1000)
  808.         {terr[i][j]=DEEP; printf("mt..");}
  809.     }
  810.   }
  811.   //havent seen anything wrong in elev, but mash just in case
  812.   for (i=0; i<SIZE; i++) {
  813.     for (j=0; j<SIZE; j++) {
  814.       if (elev[i][j]<-1000 || elev[i][j]>1.1)
  815.         {elev[i][j]=0.5; printf("me..");}
  816.     }
  817.   }
  818.  
  819.  
  820.   //================================================================
  821.   //debugging only: to make certain features pop on terrain map
  822.   for (i=0; i<SIZE; i++) {
  823.     for (j=0; j<SIZE; j++) {
  824.       if (terr[i][j]==WOODS)  terr[i][j]=70;
  825.       if (terr[i][j]==DESERT)  terr[i][j]=140;
  826.       if (terr[i][j]==SCORCH)  terr[i][j]=180;
  827.       if (terr[i][j]==DEEP)  terr[i][j]=-1;
  828.     }
  829.   }
  830.   //debugging only: to make certain features pop on elevation map
  831.   /*
  832.   for (i=0; i<SIZE; i++) {
  833.     for (j=0; j<SIZE; j++) {
  834.       //      if (terr[i][j]==70) elev[i][j]=1.4;
  835.     }
  836.   }
  837.   */
  838.  
  839.   //================================================================
  840.   // OUTPUT
  841.   for (j=0; j<SIZE; j++) {
  842.     for (i=0; i<SIZE; i++) {
  843.       fprintf(fp_elev, "%.2f  ", elev[i][j]);
  844.       fprintf(fp_terr, "%2i   ", terr[i][j]);
  845.       fprintf(fp_wet,  "%.2f  ",  wet[i][j]);
  846.     }
  847.     fprintf(fp_elev, "\n");
  848.     fprintf(fp_terr, "\n");
  849.     fprintf(fp_wet,  "\n");
  850.   }
  851.   fclose(fp_elev); fclose(fp_terr);
  852.  
  853.   printf("\nnowtime: %u. DONE.\n", nowtime);
  854. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement