Difference for server/weather.c from version 1.4 to 1.5


version 1.4 version 1.5
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_weather_c =   * static char *rcsid_weather_c =
  *   "$Id: weather.c,v 1.4 2002/07/30 06:37:22 mwedel Exp $";   *   "$Id: weather.c,v 1.5 2002/10/28 04:50:39 garbled Exp $";
  */   */
 /*  /*
     CrossFire, A Multiplayer game for X-windows      CrossFire, A Multiplayer game for X-windows
Line 35
 
Line 35
 extern unsigned long todtick;  extern unsigned long todtick;
 extern weathermap_t **weathermap;  extern weathermap_t **weathermap;
   
   #define POLAR_BASE_TEMP 0 /* C */
   #define EQUATOR_BASE_TEMP 25 /* C */
   #define SEASONAL_ADJUST 10 /* polar distance */
   
   /* don't muck with these unless you are sure you know what they do */
   #define PRESSURE_ITERATIONS 30
   #define PRESSURE_AREA 180
   #define PRESSURE_ROUNDING_FACTOR 2
   #define PRESSURE_ROUNDING_ITER 1
   #define PRESSURE_SPIKES 3
   #define PRESSURE_MAX 1040
   #define PRESSURE_MIN 960
   
   /* editing the below might require actual changes to code */
   #define WEATHERMAPTILESX 100
   #define WEATHERMAPTILESY 100
   
 const int season_timechange[5][HOURS_PER_DAY] = {  const int season_timechange[5][HOURS_PER_DAY] = {
 /* 0  1   2  3  4  5  6  7  8  9  10 11 12 13 14 1  2  3  4  5   6   7  /* 0  1   2  3  4  5  6  7  8  9  10 11 12 13 14 1  2  3  4  5   6   7
  8    9  10  11  12  13 */   8    9  10  11  12  13 */
Line 101
 
Line 118
     todtick++;      todtick++;
     if (todtick%20 == 0)      if (todtick%20 == 0)
  write_todclock();   write_todclock();
       if (settings.dynamiclevel > 0) {
           if (todtick%21 == 0)
        write_pressuremap();
    if (todtick%22 == 0)
        write_winddirmap();
    if (todtick%23 == 0)
        write_windspeedmap();
    if (todtick%24 == 0)
        write_humidmap();
    if (todtick%25 == 0)
        write_elevmap();
    if (todtick%26 == 0)
        write_temperaturemap();
       }
     get_tod(&tod);      get_tod(&tod);
     dawn_to_dusk(&tod);      dawn_to_dusk(&tod);
       /* call the weather calculators, here, in order */
       if (settings.dynamiclevel > 0) {
           perform_pressure(); /* pressure is the random factor */
           smooth_wind(); /* calculate the wind. depends on pressure */
           update_humid();
           init_temperature();
       }
       /* perform_weather must follow calculators */
     perform_weather();      perform_weather();
 }  }
   
   /*
    * This batch of routines reads and writes the various
    * weathermap structures.  Each type of data is stored
    * in a separate file to allow the size of these structures to be
    * changed more or less on the fly.  If weather goes haywire, the admin
    * can simply delete and boot the server, and it will regen.
    *
    * The write functions should be called occasionally to keep the data
    * in the maps current.  Whereas the read functions should only be called
    * at boot.  If the read function cannot find the appropriate map, it
    * calls the init function, to initialize that map.
    */
   
   /* pressure */
   
   void write_pressuremap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/pressuremap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].pressure);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_pressuremap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/pressuremap", settings.localdir);
       LOG(llevDebug, "Reading pressure data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    LOG(llevDebug, "Initializing pressure maps...");
    init_pressure();
    write_pressuremap();
    LOG(llevDebug, "Done\n");
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].pressure);
        if (weathermap[x][y].pressure < 960 ||
    weathermap[x][y].pressure > 1040)
    weathermap[x][y].pressure = rndm(960, 1040);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   void init_pressure()
   {
       int x, y;
       int l, n, k, r;
   
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++)
        weathermap[x][y].pressure = 1000;
   
       for (l=0; l < PRESSURE_ITERATIONS; l++) {
    x = rndm(0, WEATHERMAPTILESX-1);
    y = rndm(0, WEATHERMAPTILESY-1);
    n = rndm(PRESSURE_MIN, PRESSURE_MAX);
    for (k=1; k < PRESSURE_AREA; k++) {
        r = rndm(0,3);
        switch (r) {
    case 0: if (x < WEATHERMAPTILESX-1) x++; break;
    case 1: if (y < WEATHERMAPTILESY-1) y++; break;
    case 2: if (x) x--; break;
    case 3: if (y) y--; break;
        }
        weathermap[x][y].pressure = (weathermap[x][y].pressure+n)/2;
    }
       }
       /* create random spikes in the pressure */
       for (l=0; l < PRESSURE_SPIKES; l++) {
    x = rndm(0, WEATHERMAPTILESX-1);
    y = rndm(0, WEATHERMAPTILESY-1);
    n = rndm(500, 2000);
    weathermap[x][y].pressure = n;
       }
       smooth_pressure();
   }
   
   /* winddir */
   
   void write_winddirmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/winddirmap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].winddir);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_winddirmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/winddirmap", settings.localdir);
       LOG(llevDebug, "Reading wind direction data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    LOG(llevDebug, "Initializing wind maps...");
    init_wind();
    write_winddirmap();
    LOG(llevDebug, "Done\n");
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].winddir);
        if (weathermap[x][y].winddir < 1 ||
    weathermap[x][y].winddir > 8)
    weathermap[x][y].winddir = rndm(1, 8);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   /* windspeed */
   
   void write_windspeedmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/windspeedmap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].windspeed);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_windspeedmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/windspeedmap", settings.localdir);
       LOG(llevDebug, "Reading wind speed data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    LOG(llevDebug, "Initializing wind maps...");
    init_wind();
    write_windspeedmap();
    LOG(llevDebug, "Done\n");
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].windspeed);
        if (weathermap[x][y].windspeed < 0 ||
    weathermap[x][y].windspeed > 120)
    weathermap[x][y].windspeed = rndm(1, 30);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   /* initialize the wind randomly. Does both direction and speed in one pass */
   
   void init_wind()
   {
       int x, y;
   
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++) {
        weathermap[x][y].winddir = rndm(1, 8);
        weathermap[x][y].windspeed = rndm(1, 10);
    }
   
       /* build a gulf stream */
       x = rndm(0, WEATHERMAPTILESX);
       y = rndm(0, 1);
   
       if (y) {
    for (y=WEATHERMAPTILESY-1; y >= 0; y--) {
        switch(rndm(0, 6)) {
        case 0:
        case 1:
        case 2:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 8;
    if (x==0) {
        weathermap[x+1][y].winddir = 7;
        weathermap[x+1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x-1][y].winddir = 8;
        weathermap[x-1][y].windspeed = rndm(40, 50);
        x--;
    }
    break;
        case 3:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 7;
    if (x==0) {
        weathermap[x+1][y].winddir = 7;
        weathermap[x+1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x-1][y].winddir = 7;
        weathermap[x-1][y].windspeed = rndm(40, 50);
    }
    break;
        case 4:
        case 5:
        case 6:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 6;
    if (x==WEATHERMAPTILESX-1) {
        weathermap[x-1][y].winddir = 7;
        weathermap[x-1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x+1][y].winddir = 6;
        weathermap[x+1][y].windspeed = rndm(40, 50);
        x++;
    }
    break;
        }
    }
       } else { /* go right to left */
    for (y=0; y < WEATHERMAPTILESY; y++) {
        switch(rndm(0, 6)) {
        case 0:
        case 1:
        case 2:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 2;
    if (x==0) {
        weathermap[x+1][y].winddir = 3;
        weathermap[x+1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x-1][y].winddir = 2;
        weathermap[x-1][y].windspeed = rndm(40, 50);
        x--;
    }
    break;
        case 3:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 2;
    if (x==0) {
        weathermap[x+1][y].winddir = 2;
        weathermap[x+1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x-1][y].winddir = 2;
        weathermap[x-1][y].windspeed = rndm(40, 50);
    }
    break;
        case 4:
        case 5:
        case 6:
    weathermap[x][y].windspeed = rndm(40, 50);
    weathermap[x][y].winddir = 4;
    if (x==WEATHERMAPTILESX-1) {
        weathermap[x-1][y].winddir = 3;
        weathermap[x-1][y].windspeed = rndm(40, 50);
    } else {
        weathermap[x+1][y].winddir = 4;
        weathermap[x+1][y].windspeed = rndm(40, 50);
        x++;
    }
    break;
        }
    }
       } /* done */
   }
   
   /* humidity */
   
   void write_humidmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/humidmap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].humid);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_humidmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/humidmap", settings.localdir);
       LOG(llevDebug, "Reading humidity data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    LOG(llevDebug, "Initializing humidity and elevation maps...");
    init_humid_elev();
    write_elevmap();
    write_humidmap();
    write_watermap();
    LOG(llevDebug, "Done\n");
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].humid);
        if (weathermap[x][y].humid < 0 ||
    weathermap[x][y].humid > 100)
    weathermap[x][y].humid = rndm(0, 100);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   /* average elevation */
   
   void write_elevmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/elevmap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].avgelev);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_elevmap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/elevmap", settings.localdir);
       LOG(llevDebug, "Reading elevation data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    /* initializing these is expensive, and should have been done
       by the humidity.  It's not worth the wait to do it twice. */
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].avgelev);
        if (weathermap[x][y].avgelev < -10000 ||
    weathermap[x][y].avgelev > 15000)
    weathermap[x][y].avgelev = rndm(-1000, 10000);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   /* water % */
   
   void write_watermap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/watermap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].water);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_watermap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/watermap", settings.localdir);
       LOG(llevDebug, "Reading water data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    /* initializing these is expensive, and should have been done
       by the humidity.  It's not worth the wait to do it twice. */
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].water);
        if (weathermap[x][y].water > 100)
    weathermap[x][y].water = rndm(0, 100);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   /* initialize both humidity and elevation */
   
   void init_humid_elev()
   {
       int x, y, tx, ty, nx, ny, ax, ay, j, k;
       int spwtx, spwty, dir;
       char *mapname;
       long int elev;
       int water, space;
       mapstruct *m;
   
       /* handling of this is kinda nasty.  For that reason,
        * we do the elevation here too.  Not because it makes the
        * code cleaner, or makes handling easier, but because I do *not*
        * want to maintain two of these nightmares.
        */
   
       spwtx = (settings.worldmaptilesx * settings.worldmaptilesizex) / WEATHERMAPTILESX;
       spwty = (settings.worldmaptilesy * settings.worldmaptilesizey) / WEATHERMAPTILESY;
       for (x=0; x < WEATHERMAPTILESX; x++) {
           for (y=0; y < WEATHERMAPTILESY; y++) {
        water = 0;
        elev = 0;
        nx = 0;
        ny = 0;
        space = 0;
   
        /* top left */
        mapname=weathermap_to_worldmap_corner(x, y, &tx, &ty, 8);
        m = load_original_map(mapname, 0);
        if (m == NULL)
    continue;
        m = load_overlay_map(mapname, m);
        if (m == NULL)
    continue;
        for (nx=0,ax=tx; (nx < spwtx && ax < settings.worldmaptilesizex &&
         space < spwtx*spwty); ax++,nx++) {
    for (ny=0,ay=ty; (ny < spwty && ay < settings.worldmaptilesizey &&
    space < spwtx*spwty);
         ay++,ny++,space++) {
        if (QUERY_FLAG(m->spaces[ax+ay].bottom,
        FLAG_IS_WATER))
    water++;
        elev += m->spaces[ax+ay].bottom->elevation;
    }
        }
        delete_map(m);
   
        /* bottom left */
        mapname=weathermap_to_worldmap_corner(x, y, &tx, &ty, 6);
        m = load_original_map(mapname, 0);
        if (m == NULL)
    continue;
        m = load_overlay_map(mapname, m);
        if (m == NULL)
    continue;
        j = ny;
        for (nx=0,ax=tx; (nx < spwtx && ax < settings.worldmaptilesizex &&
         space < spwtx*spwty); ax++,nx++) {
    for (ny=j,ay=MAX(0, ty - (spwty-1)); (ny < spwty && ay <= ty &&
    space < spwtx*spwty);
         space++,ay++,ny++) {
        if (QUERY_FLAG(m->spaces[ax+ay].bottom,
        FLAG_IS_WATER))
    water++;
        elev += m->spaces[ax+ay].bottom->elevation;
    }
        }
        delete_map(m);
   
        /* top right */
        mapname=weathermap_to_worldmap_corner(x, y, &tx, &ty, 2);
        m = load_original_map(mapname, 0);
        if (m == NULL)
    continue;
        m = load_overlay_map(mapname, m);
        if (m == NULL)
    continue;
        for (ax=MAX(0, tx - (spwtx-1)); (nx < spwtx && ax < tx &&
         space < spwtx*spwty); ax++,nx++) {
    for (ny=0,ay=ty; (ny < spwty && ay < settings.worldmaptilesizey &&
    space < spwtx*spwty);
         ay++,ny++,space++) {
        if (QUERY_FLAG(m->spaces[ax+ay].bottom,
        FLAG_IS_WATER))
    water++;
        elev += m->spaces[ax+ay].bottom->elevation;
    }
        }
        delete_map(m);
   
        /* bottom left */
        mapname=weathermap_to_worldmap_corner(x, y, &tx, &ty, 4);
        m = load_original_map(mapname, 0);
        if (m == NULL)
    continue;
        m = load_overlay_map(mapname, m);
        if (m == NULL)
    continue;
        for (nx=0,ax=MAX(0, tx - (spwtx-1)); (nx < spwtx && ax < tx &&
         space < spwtx*spwty); ax++,nx++) {
    for (ny=0,ay=MAX(0, ty - (spwty-1)); (ny < spwty && ay <= ty &&
    space < spwtx*spwty);
         space++,ay++,ny++) {
        if (QUERY_FLAG(m->spaces[ax+ay].bottom,
        FLAG_IS_WATER))
    water++;
        elev += m->spaces[ax+ay].bottom->elevation;
    }
        }
        delete_map(m);
        /* jesus thats confusing as all hell */
        weathermap[x][y].humid = water/(spwtx*spwty);
        weathermap[x][y].avgelev = elev/(spwtx*spwty);
        weathermap[x][y].water = weathermap[x][y].humid;
    }
       }
   
       /* and this does all the real work */
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++)
        weathermap[x][y].humid = humid_tile(x, y);
   }
   
   /* temperature */
   
   void write_temperaturemap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/temperaturemap", settings.localdir);
       if ((fp = fopen(filename, "w")) == NULL) {
    LOG(llevError, "Cannot open %s for writing\n", filename);
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++)
        fprintf(fp, "%d ", weathermap[x][y].temp);
    fprintf(fp, "\n");
       }
       fclose(fp);
   }
   
   void read_temperaturemap()
   {
       char filename[MAX_BUF];
       FILE *fp;
       int x, y;
   
       sprintf(filename, "%s/temperaturemap", settings.localdir);
       LOG(llevDebug, "Reading teperature data from %s...", filename);
       if ((fp = fopen(filename, "r")) == NULL) {
    LOG(llevError, "Cannot open %s for reading\n", filename);
    init_temperature();
    write_temperaturemap();
    return;
       }
       for (x=0; x < WEATHERMAPTILESX; x++) {
    for (y=0; y < WEATHERMAPTILESY; y++) {
        fscanf(fp, "%d ", &weathermap[x][y].temp);
        if (weathermap[x][y].temp < -30 ||
    weathermap[x][y].temp > 60)
    weathermap[x][y].temp = rndm(-10, 40);
    }
    fscanf(fp, "\n");
       }
       LOG(llevDebug, "Done.\n");
       fclose(fp);
   }
   
   void init_temperature()
   {
       int x, y;
       timeofday_t tod;
   
       get_tod(&tod);
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++)
        temperature_calc(x, y, &tod);
   }
   
   /* END of read/write/init */
   
   
 int wmperformstartx;  int wmperformstartx;
 int wmperformstarty;  int wmperformstarty;
   
Line 113
 
Line 789
 {  {
     int x, y;      int x, y;
     int i, j;      int i, j;
       int water;
     long int tmp;      long int tmp;
     char filename[MAX_BUF];      char filename[MAX_BUF];
     FILE *fp;      FILE *fp;
Line 131
 
Line 808
     LOG(llevDebug, "Initializing the weathermap...\n");      LOG(llevDebug, "Initializing the weathermap...\n");
   
     weathermap = (weathermap_t **)malloc(sizeof(weathermap_t *) *      weathermap = (weathermap_t **)malloc(sizeof(weathermap_t *) *
  settings.worldmaptilesx);   WEATHERMAPTILESX);
     if (weathermap == NULL)      if (weathermap == NULL)
  fatal(OUT_OF_MEMORY);   fatal(OUT_OF_MEMORY);
     for (y=0; y < settings.worldmaptilesy; y++) {      for (y=0; y < WEATHERMAPTILESY; y++) {
  weathermap[y] = (weathermap_t *)malloc(sizeof(weathermap_t) *   weathermap[y] = (weathermap_t *)malloc(sizeof(weathermap_t) *
      settings.worldmaptilesy);       WEATHERMAPTILESY);
  if (weathermap[y] == NULL)   if (weathermap[y] == NULL)
      fatal(OUT_OF_MEMORY);       fatal(OUT_OF_MEMORY);
     }      }
     /* now we load the values in the big worldmap weather array */      /* now we load the values in the big worldmap weather array */
     for (x=0; x < settings.worldmaptilesx; x++) {      /* do not re-order these */
  for (y=0; y < settings.worldmaptilesy; y++) {      read_pressuremap();
      sprintf(filename, "world/world_%d_%d",      read_winddirmap();
  x+settings.worldmapstartx, y+settings.worldmapstarty);      read_windspeedmap();
      m = load_original_map(filename, 0);      read_humidmap();
      if (m == NULL)      read_elevmap(); /* elevation must allways follow humidity */
  continue;      read_temperaturemap();
      m = load_overlay_map(filename, m);  
      if (m == NULL)      LOG(llevDebug, "Done reading weathermaps\n");
  continue;  
      sprintf(weathermap[x][y].path, "%s", m->path);  
      if (m->tmpname)  
  weathermap[x][y].tmpname = strdup(m->tmpname);  
      weathermap[x][y].name = strdup(m->name);  
      weathermap[x][y].temp = m->temp;  
      weathermap[x][y].pressure = m->pressure;  
      weathermap[x][y].humid = m->humid;  
      weathermap[x][y].windspeed = m->windspeed;  
      weathermap[x][y].winddir = m->winddir;  
      weathermap[x][y].sky = m->sky;  
      weathermap[x][y].darkness = m->darkness;  
      tmp = 0;  
      for (i=0; i < settings.worldmaptilesizex; i++)  
  for (j=0; j < settings.worldmaptilesizey; j++)  
      tmp += m->spaces[i+j].bottom->elevation;  
      weathermap[x][y].avgelev = tmp / (i*j);  
      delete_map(m);  
  }  
     }  
     LOG(llevDebug, "Done reading worldmaps\n");  
     sprintf(filename, "%s/wmapcurpos", settings.localdir);      sprintf(filename, "%s/wmapcurpos", settings.localdir);
     LOG(llevDebug, "Reading current weather position from %s...", filename);      LOG(llevDebug, "Reading current weather position from %s...", filename);
     if ((fp = fopen(filename, "r")) == NULL) {      if ((fp = fopen(filename, "r")) == NULL) {
Line 185
 
Line 841
  wmperformstartx = -1;   wmperformstartx = -1;
     if (wmperformstarty > settings.worldmaptilesy)      if (wmperformstarty > settings.worldmaptilesy)
  wmperformstarty = 0;   wmperformstarty = 0;
    
 }  }
   
 /*  /*
  * This routine slowly loads the world, patches it up due to the weather,   * This routine slowly loads the world, patches it up due to the weather,
  * and saves it back to disk.  In this way, the world constantly feels the   * and saves it back to disk.  In this way, the world constantly feels the
  * effects of weather uniformly, without relying on players wandering.   * effects of weather uniformly, without relying on players wandering.
    *
    * The main point of this is stuff like growing herbs, soil, decaying crap,
    * etc etc etc.  Not actual *weather*, but weather *effects*.
  */   */
   
 void perform_weather()  void perform_weather()
Line 215
 
Line 873
     sprintf(filename, "world/world_%d_%d",      sprintf(filename, "world/world_%d_%d",
  wmperformstartx+settings.worldmapstartx,   wmperformstartx+settings.worldmapstartx,
  wmperformstarty+settings.worldmapstarty);   wmperformstarty+settings.worldmapstarty);
   
     m = ready_map_name(filename, 0);      m = ready_map_name(filename, 0);
     if (m == NULL)      if (m == NULL)
  return; /* hrmm */   return; /* hrmm */
   
     m->temp = weathermap[wmperformstartx][wmperformstarty].temp;      /* for now, all we do is decay stuff.  more to come */
     m->pressure = weathermap[wmperformstartx][wmperformstarty].pressure;  
     m->humid = weathermap[wmperformstartx][wmperformstarty].humid;  
     m->windspeed = weathermap[wmperformstartx][wmperformstarty].windspeed;  
     m->winddir = weathermap[wmperformstartx][wmperformstarty].winddir;  
     m->sky = weathermap[wmperformstartx][wmperformstarty].sky;  
     decay_objects(m);      decay_objects(m);
     new_save_map(m, 2); /* write the overlay */      new_save_map(m, 2); /* write the overlay */
       m->in_memory = MAP_IN_MEMORY; /*reset this*/
     sprintf(filename, "%s/wmapcurpos", settings.localdir);      sprintf(filename, "%s/wmapcurpos", settings.localdir);
     if ((fp = fopen(filename, "w")) == NULL) {      if ((fp = fopen(filename, "w")) == NULL) {
  LOG(llevError, "Cannot open %s for writing\n", filename);   LOG(llevError, "Cannot open %s for writing\n", filename);
  return;   return;
     }      }
   
       if (players_on_map(m, TRUE) == 0)
         delete_map(m);
   
     fprintf(fp, "%d %d", wmperformstartx, wmperformstarty);      fprintf(fp, "%d %d", wmperformstartx, wmperformstarty);
     fclose(fp);      fclose(fp);
 }  }
   
   /* provide x and y.  Will fill in with the requested corner of the real
    * world map, given the current weathermap section.  dir selects which
    * corner to return.  Valid values are 2 4 6 8 for the corners.  return
    * value is the name of the map that corner resides in.
    */
   
   char *weathermap_to_worldmap_corner(int wx, int wy, int *x, int *y, int dir)
   {
       int spwtx, spwty;
       int tx, ty, nx, ny;
       char *mapname;
      
       spwtx = (settings.worldmaptilesx * settings.worldmaptilesizex) / WEATHERMAPTILESX;
       spwty = (settings.worldmaptilesy * settings.worldmaptilesizey) / WEATHERMAPTILESY;
       switch (dir) {
       case 2: wx++; break;
       case 4: wx++; wy++; break;
       case 6: wy++; break;
       case 8: break;
       }
       if (wx > 0)
       tx = (wx*spwtx)-1;
       else
    tx = wx;
       if (wy > 0)
    ty = (wy*spwty)-1;
       else
    ty = wy;
      
       nx = (tx / settings.worldmaptilesizex) + settings.worldmapstartx;
       ny = (ty / settings.worldmaptilesizey) + settings.worldmapstarty;
       mapname = malloc(sizeof(char) * strlen("world/world_0000_0000"));
       sprintf(mapname, "world/world_%d_%d", nx, ny);
      
       *x = tx%settings.worldmaptilesizex;
       *y = ty%settings.worldmaptilesizey;
       return(mapname);
   }
   
   int polar_distance(int x, int y, int equator)
   {
       if ((x+y) > equator) { /* south pole */
    x = WEATHERMAPTILESX - x;
    y = WEATHERMAPTILESY - y;
    return ((x+y)/2);
       } else if ((x+y) < equator) { /* north pole */
    return ((x+y)/2);
       } else {
    return equator/2;
       }
   }
   
   /* update the humidity */
   
   void update_humid()
   {
       int x, y;
   
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++)
        humid_tile(x, y);
   }
   
   /* calculate the humidity of this tile */
   
   int humid_tile(int x, int y)
   {
       int ox, oy, humid;
   
       ox = x;
       oy = y;
   
       /* find the square the wind is coming from, without going out of bounds */
   
       if (weathermap[x][y].winddir == 8 || weathermap[x][y].winddir <= 2) {
    if (y != 0)
        oy = y - 1;
       }
       if (weathermap[x][y].winddir >= 6) {
    if (x != 0)
        ox = x - 1;
       }
       if (weathermap[x][y].winddir >= 4 && weathermap[x][y].winddir <= 6) {
    if (y != WEATHERMAPTILESY)
        oy = y + 1;
       }
       if (weathermap[x][y].winddir >= 2 && weathermap[x][y].winddir <= 4) {
    if (x != WEATHERMAPTILESX)
        ox = x + 1;
       }
       humid = MIN(100, (weathermap[x][y].humid + weathermap[ox][oy].humid * 2 +
    weathermap[x][y].water + rndm(-2,2)) / 4);
   
       return humid;
   }
   
   /* calculate temperature */
   
   void temperature_calc(int x, int y, timeofday_t *tod)
   {
       int dist, equator, elev, eq2;
       float diff, tdiff;
   
       equator = (WEATHERMAPTILESX + WEATHERMAPTILESY) / 4;
       eq2 = (WEATHERMAPTILESX + WEATHERMAPTILESY) / 2;
       diff = (float)(EQUATOR_BASE_TEMP - POLAR_BASE_TEMP) / (float)equator;
       tdiff = (float)SEASONAL_ADJUST / ((float)MONTHS_PER_YEAR / 2.0);
   
       /* we essentially move the equator during the season */
       if (tod->month > (MONTHS_PER_YEAR / 2)) { /* EOY */
           eq2 -= tod->month * tdiff;
       } else {
           eq2 += (MONTHS_PER_YEAR - tod->month) * tdiff;
       }
       dist = polar_distance(x, y, eq2);
   
       /* now we have the base temp, unadjusted for time.  Time adjustment
          is not recorded on the map, rather, it's done JIT. */
       weathermap[x][y].temp = (int)(dist * diff);
       /* just scrap these for now, its mostly ocean */
       if (weathermap[x][y].avgelev < 0)
    elev = 0;
       else
    elev = MAX(10000, weathermap[x][y].avgelev)/1000;
       weathermap[x][y].temp -= elev;
   }
   
   
   /* this code simply smooths the pressure map */
   
   void smooth_pressure()
   {
       int x, y;
       int k;
   
       for (k=0; k < PRESSURE_ROUNDING_ITER; k++) {
    for (x=2; x < WEATHERMAPTILESX-2; x++) {
        for (y=2; y < WEATHERMAPTILESY-2; y++) {
    weathermap[x][y].pressure = (weathermap[x][y].pressure *
        PRESSURE_ROUNDING_FACTOR + weathermap[x-1][y].pressure +
        weathermap[x][y-1].pressure + weathermap[x-1][y-1].pressure +
        weathermap[x+1][y].pressure + weathermap[x][y+1].pressure +
        weathermap[x+1][y+1].pressure + weathermap[x+1][y-1].pressure +
        weathermap[x-1][y+1].pressure) / (PRESSURE_ROUNDING_FACTOR+8);
        }
    }
    for (x=WEATHERMAPTILESX-2; x > 2; x--) {
        for (y=WEATHERMAPTILESY-2; y > 2; y--) {
    weathermap[x][y].pressure = (weathermap[x][y].pressure *
        PRESSURE_ROUNDING_FACTOR + weathermap[x-1][y].pressure +
        weathermap[x][y-1].pressure + weathermap[x-1][y-1].pressure +
        weathermap[x+1][y].pressure + weathermap[x][y+1].pressure +
        weathermap[x+1][y+1].pressure + weathermap[x+1][y-1].pressure +
        weathermap[x-1][y+1].pressure) / (PRESSURE_ROUNDING_FACTOR+8);
        }
    }
       }
   
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++) {
        weathermap[x][y].pressure = MIN(weathermap[x][y].pressure, PRESSURE_MAX);
        weathermap[x][y].pressure = MAX(weathermap[x][y].pressure, PRESSURE_MIN);
    }
   
   }
   
   /* perform small randomizations in the pressure map.  Then, apply the
      smoothing algorithim.. This causes the pressure to change very slowly
   */
   
   void perform_pressure()
   {
       int x, y, l, n, j, k;
   
       /* create random spikes in the pressure */
       for (l=0; l < PRESSURE_SPIKES; l++) {
    x = rndm(0, WEATHERMAPTILESX-1);
    y = rndm(0, WEATHERMAPTILESY-1);
    n = rndm(600, 1300);
    weathermap[x][y].pressure = n;
    if (x > 5 && y > 5 && x < WEATHERMAPTILESX-5 && y < WEATHERMAPTILESY-5){
      for (j=x-2; j<x+2; j++)
        for (k=y-2; k<y+2; k++)
          weathermap[j][k].pressure = n;
    }
       }
   
       for (x=0; x < WEATHERMAPTILESX; x++)
    for (y=0; y < WEATHERMAPTILESY; y++)
        weathermap[x][y].pressure += rndm(-1, 4);
   
       smooth_pressure();
   }
   
   
   /* is direction a similar to direction b? Find out in this exciting function
      below.
    */
   
   int similar_direction(int a, int b)
   {
       /* shortcut the obvious */
       if (a == b)
    return 1;
   
       switch(a) {
    case 1: if (b <= 2 || b == 8) return 1; break;
    case 2: if (b > 0 && b < 4) return 1; break;
    case 3: if (b > 1 && b < 5) return 1; break;
    case 4: if (b > 2 && b < 6) return 1; break;
    case 5: if (b > 3 && b < 7) return 1; break;
    case 6: if (b > 4 && b < 8) return 1; break;
    case 7: if (b > 5) return 1; break;
    case 8: if (b > 6 || b == 1) return 1; break;
       }
       return 0;
   }
   
   /*
      It doesn't really smooth it as such.  The main function of this is to
      apply the pressuremap to the wind direction and speed.  Then, we run
      a quick pass to update the windspeed.
   */
   
   void smooth_wind()
   {
       int x, y;
       int tx, ty, dx, dy;
       int minp;
   
       /* skip the outer squares.. it makes handling alot easier */
       for (x=1; x < WEATHERMAPTILESX-1; x++)
    for (y=1; y < WEATHERMAPTILESY-1; y++) {
        minp = PRESSURE_MAX + 1;
        for (tx=-1; tx < 2; tx++)
    for (ty=-1; ty < 2; ty++)
        if (!(tx == 0 && ty == 0))
    if (weathermap[x+tx][y+ty].pressure < minp) {
        minp = weathermap[x+tx][y+ty].pressure;
        dx = tx;
        dy = ty;
    }
   
        /* if the wind is strong, the pressure won't decay it completely */
        if (weathermap[x][y].windspeed > 5 &&
    !similar_direction(weathermap[x][y].winddir, find_dir_2(dx, dy))) {
    weathermap[x][y].windspeed -= 2;
        } else {
    weathermap[x][y].winddir = find_dir_2(dx, dy);
    weathermap[x][y].windspeed = weathermap[x][y].pressure -
        weathermap[x+dx][y+dy].pressure;
        }
        if (weathermap[x][y].windspeed < 0)
    weathermap[x][y].windspeed = 0;
    }
   
       /*  now, lets crank on the speed.  When surrounding tiles all have
    the same speed, inc ours.  If it's chaos. drop it.
        */
       for (x=1; x < WEATHERMAPTILESX-1; x++)
    for (y=1; y < WEATHERMAPTILESY-1; y++) {
        minp = 0;
        for (tx=-1; tx < 2; tx++)
    for (ty=-1; ty < 2; ty++)
        if (ty != 0 && ty != 0)
    if (similar_direction(weathermap[x][y].winddir,
    weathermap[x+tx][y+ty].winddir))
        minp++;
        if (minp > 4)
    weathermap[x][y].windspeed++;
        if (minp > 6)
    weathermap[x][y].windspeed += 2;
        if (minp < 2)
    weathermap[x][y].windspeed--;
        if (weathermap[x][y].windspeed < 0)
    weathermap[x][y].windspeed = 0;
    }
   }


Legend:
line(s) removed in v.1.4 
line(s) changed
 line(s) added in v.1.5

File made using version 1.98 of cvs2html by leaf at 2011-07-21 17:53