1stMud/CVS/
1stMud/area/CVS/
1stMud/backup/CVS/
1stMud/bin/
1stMud/bin/CVS/
1stMud/bin/extras/
1stMud/bin/extras/CVS/
1stMud/data/CVS/
1stMud/data/i3/CVS/
1stMud/doc/1stMud/
1stMud/doc/1stMud/CVS/
1stMud/doc/CVS/
1stMud/doc/Diku/
1stMud/doc/Diku/CVS/
1stMud/doc/MPDocs/CVS/
1stMud/doc/Merc/CVS/
1stMud/doc/Rom/
1stMud/doc/Rom/CVS/
1stMud/log/CVS/
1stMud/notes/
1stMud/notes/CVS/
1stMud/player/CVS/
1stMud/player/backup/CVS/
1stMud/player/deleted/CVS/
1stMud/src/CVS/
1stMud/src/config/CVS/
1stMud/src/h/CVS/
1stMud/src/o/CVS/
1stMud/win/CVS/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"
#include "olc.h"
#include "interp.h"
#include "recycle.h"

Proto (void get_weather_echo, (WeatherData *));


void
init_area_weather ()
{
  AreaData *pArea;

  logf ("Initializing weather data...");
  for (pArea = area_first; pArea; pArea = pArea->next)
    {
      int cf;


      cf = pArea->weather.climate_temp - 2;
      pArea->weather.temp =
	number_range (-mud_info.weath_unit, mud_info.weath_unit) +
	cf * number_range (0, mud_info.weath_unit);
      pArea->weather.temp_vector =
	cf + number_range (-mud_info.rand_factor, mud_info.rand_factor);


      cf = pArea->weather.climate_precip - 2;
      pArea->weather.precip =
	number_range (-mud_info.weath_unit, mud_info.weath_unit) +
	cf * number_range (0, mud_info.weath_unit);
      pArea->weather.precip_vector =
	cf + number_range (-mud_info.rand_factor, mud_info.rand_factor);


      cf = pArea->weather.climate_wind - 2;
      pArea->weather.wind =
	number_range (-mud_info.weath_unit, mud_info.weath_unit) +
	cf * number_range (0, mud_info.weath_unit);
      pArea->weather.wind_vector =
	cf + number_range (-mud_info.rand_factor, mud_info.rand_factor);
    }

  return;
}


void
adjust_vectors (WeatherData * weather)
{
  double dT, dP, dW;

  if (!weather)
    {
      bug ("NULL weather data.");
      return;
    }

  dT = 0;
  dP = 0;
  dW = 0;


  dT += number_range (-mud_info.rand_factor, mud_info.rand_factor);
  dP += number_range (-mud_info.rand_factor, mud_info.rand_factor);
  dW += number_range (-mud_info.rand_factor, mud_info.rand_factor);


  dT += mud_info.climate_factor *
    (((weather->climate_temp - 2) * mud_info.weath_unit) -
     (weather->temp)) / mud_info.weath_unit;
  dP += mud_info.climate_factor *
    (((weather->climate_precip - 2) * mud_info.weath_unit) -
     (weather->precip)) / mud_info.weath_unit;
  dW += mud_info.climate_factor *
    (((weather->climate_wind - 2) * mud_info.weath_unit) -
     (weather->wind)) / mud_info.weath_unit;


  weather->temp_vector += (int) dT;
  weather->precip_vector += (int) dP;
  weather->wind_vector += (int) dW;


  weather->temp_vector = Range (-mud_info.max_vector,
				weather->temp_vector, mud_info.max_vector);
  weather->precip_vector =
    Range (-mud_info.max_vector, weather->precip_vector, mud_info.max_vector);
  weather->wind_vector =
    Range (-mud_info.max_vector, weather->wind_vector, mud_info.max_vector);

  return;
}


void
weather_update ()
{
  AreaData *pArea;
  Descriptor *d;
  int limit;

  limit = 3 * mud_info.weath_unit;

  for (pArea = area_first; pArea; pArea = pArea->next)
    {

      pArea->weather.temp += pArea->weather.temp_vector;
      pArea->weather.precip += pArea->weather.precip_vector;
      pArea->weather.wind += pArea->weather.wind_vector;


      pArea->weather.temp = Range (-limit, pArea->weather.temp, limit);
      pArea->weather.precip = Range (-limit, pArea->weather.precip, limit);
      pArea->weather.wind = Range (-limit, pArea->weather.wind, limit);


      get_weather_echo (&pArea->weather);
    }

  for (pArea = area_first; pArea; pArea = pArea->next)
    {
      adjust_vectors (&pArea->weather);
    }


  for (d = descriptor_first; d; d = d->next)
    {
      WeatherData *weath;

      if (d->connected == CON_PLAYING &&
	  IsOutside (d->character) && IsAwake (d->character))
	{
	  weath = &d->character->in_room->area->weather;
	  if (NullStr (weath->echo))
	    continue;
	  d_printlnf (d, "%s%s{x", weath->echo_color, weath->echo);
	}
    }

  return;
}


void
get_weather_echo (WeatherData * weath)
{
  int n;
  int temp, precip, wind;
  int dT, dP, dW;
  int tindex, pindex, windex;


  replace_str (&weath->echo, "");
  replace_str (&weath->echo_color, "{x");


  n = number_bits (2);


  temp = weath->temp;
  precip = weath->precip;
  wind = weath->wind;

  dT = weath->temp_vector;
  dP = weath->precip_vector;
  dW = weath->wind_vector;

  tindex = (temp + 3 * mud_info.weath_unit - 1) / mud_info.weath_unit;
  pindex = (precip + 3 * mud_info.weath_unit - 1) / mud_info.weath_unit;
  windex = (wind + 3 * mud_info.weath_unit - 1) / mud_info.weath_unit;


  switch (pindex)
    {
    case 0:
      if (precip - dP > -2 * mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The clouds disappear.",
	    "The clouds disappear.",
	    "The sky begins to break through " "the clouds.",
	    "The clouds are slowly " "evaporating."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{W");
	}
      break;

    case 1:
      if (precip - dP <= -2 * mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The sky is getting cloudy.",
	    "The sky is getting cloudy.",
	    "Light clouds cast a haze over " "the sky.",
	    "Billows of clouds spread through " "the sky."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{D");
	}
      break;

    case 2:
      if (precip - dP > 0)
	{
	  if (tindex > 1)
	    {
	      char *echo_strings[4] = {
		"The rain stops.",
		"The rain stops.",
		"The rainstorm tapers " "off.",
		"The rain's intensity " "breaks."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{C");
	    }
	  else
	    {
	      char *echo_strings[4] = {
		"The snow stops.",
		"The snow stops.",
		"The snow showers taper " "off.",
		"The snow flakes disappear " "from the sky."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{W");
	    }
	}
      break;

    case 3:
      if (precip - dP <= 0)
	{
	  if (tindex > 1)
	    {
	      char *echo_strings[4] = {
		"It starts to rain.",
		"It starts to rain.",
		"A droplet of rain falls " "upon you.",
		"The rain begins to " "patter."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{C");
	    }
	  else
	    {
	      char *echo_strings[4] = {
		"It starts to snow.",
		"It starts to snow.",
		"Crystal flakes begin to " "fall from the " "sky.",
		"Snow flakes drift down " "from the clouds."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{W");
	    }
	}
      else if (tindex < 2 && temp - dT > -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The temperature drops and the rain " "becomes a light snow.",
	    "The temperature drops and the rain " "becomes a light snow.",
	    "Flurries form as the rain freezes.",
	    "Large snow flakes begin to fall " "with the rain."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{W");
	}
      else if (tindex > 1 && temp - dT <= -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The snow flurries are gradually " "replaced by pockets of rain.",
	    "The snow flurries are gradually " "replaced by pockets of rain.",
	    "The falling snow turns to a cold drizzle.",
	    "The snow turns to rain as the air warms."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{C");
	}
      break;

    case 4:
      if (precip - dP > 2 * mud_info.weath_unit)
	{
	  if (tindex > 1)
	    {
	      char *echo_strings[4] = {
		"The lightning has stopped.",
		"The lightning has stopped.",
		"The sky settles, and the " "thunder surrenders.",
		"The lightning bursts fade as " "the storm weakens."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{D");
	    }
	}
      else if (tindex < 2 && temp - dT > -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The cold rain turns to snow.",
	    "The cold rain turns to snow.",
	    "Snow flakes begin to fall " "amidst the rain.",
	    "The driving rain begins to freeze."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{W");
	}
      else if (tindex > 1 && temp - dT <= -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The snow becomes a freezing rain.",
	    "The snow becomes a freezing rain.",
	    "A cold rain beats down on you " "as the snow begins to melt.",
	    "The snow is slowly replaced by a heavy " "rain."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{C");
	}
      break;

    case 5:
      if (precip - dP <= 2 * mud_info.weath_unit)
	{
	  if (tindex > 1)
	    {
	      char *echo_strings[4] = {
		"Lightning flashes in the " "sky.",
		"Lightning flashes in the " "sky.",
		"A flash of lightning splits " "the sky.",
		"The sky flashes, and the " "ground trembles with " "thunder."
	      };

	      replace_str (&weath->echo, echo_strings[n]);
	      replace_str (&weath->echo_color, "{Y");
	    }
	}
      else if (tindex > 1 && temp - dT <= -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The sky rumbles with thunder as " "the snow changes to rain.",
	    "The sky rumbles with thunder as " "the snow changes to rain.",
	    "The falling turns to freezing rain " "amidst flashes of "
	      "lightning.",
	    "The falling snow begins to melt as " "thunder crashes overhead."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{W");
	}
      else if (tindex < 2 && temp - dT > -mud_info.weath_unit)
	{
	  char *echo_strings[4] = {
	    "The lightning stops as the rainstorm "
	      "becomes a blinding " "blizzard.",
	    "The lightning stops as the rainstorm "
	      "becomes a blinding " "blizzard.",
	    "The thunder dies off as the "
	      "pounding rain turns to " "heavy snow.",
	    "The cold rain turns to snow and " "the lightning stops."
	  };

	  replace_str (&weath->echo, echo_strings[n]);
	  replace_str (&weath->echo_color, "{C");
	}
      break;

    default:
      bug ("echo_weather: invalid precip index");
      weath->precip = 0;
      break;
    }

  return;
}


void
get_time_echo (WeatherData * weath)
{
  int n;
  int pindex;

  n = number_bits (2);
  pindex =
    (weath->precip + 3 * mud_info.weath_unit - 1) / mud_info.weath_unit;
  replace_str (&weath->echo, "");
  replace_str (&weath->echo_color, "{w");

  switch (time_info.hour)
    {
    case 5:
      {
	char *echo_strings[4] = {
	  "The day has begun.",
	  "The day has begun.",
	  "The sky slowly begins to glow.",
	  "The sun slowly embarks upon a new day."
	};

	time_info.sunlight = SUN_RISE;
	replace_str (&weath->echo, echo_strings[n]);
	replace_str (&weath->echo_color, "{Y");
	break;
      }
    case 6:
      {
	char *echo_strings[4] = {
	  "The sun rises in the east.",
	  "The sun rises in the east.",
	  "The hazy sun rises over the horizon.",
	  "Day breaks as the sun lifts into the sky."
	};

	time_info.sunlight = SUN_LIGHT;
	replace_str (&weath->echo, echo_strings[n]);
	replace_str (&weath->echo_color, "{y");
	break;
      }
    case 12:
      {
	if (pindex > 0)
	  {
	    replace_str (&weath->echo, "It's noon.");
	  }
	else
	  {
	    char *echo_strings[2] = {
	      "The intensity of the sun " "heralds the noon hour.",
	      "The sun's bright rays beat down " "upon your shoulders."
	    };

	    replace_str (&weath->echo, echo_strings[n % 2]);
	  }
	time_info.sunlight = SUN_LIGHT;
	replace_str (&weath->echo_color, "{W");
	break;
      }
    case 19:
      {
	char *echo_strings[4] = {
	  "The sun slowly disappears in the west.",
	  "The reddish sun sets past the horizon.",
	  "The sky turns a reddish orange as the sun " "ends its journey.",
	  "The sun's radiance dims as it sinks in the " "sky."
	};

	time_info.sunlight = SUN_SET;
	replace_str (&weath->echo, echo_strings[n]);
	replace_str (&weath->echo_color, "{R");
	break;
      }
    case 20:
      {
	if (pindex > 0)
	  {
	    char *echo_strings[2] = {
	      "The night begins.",
	      "Twilight descends around you."
	    };

	    replace_str (&weath->echo, echo_strings[n % 2]);
	  }
	else
	  {
	    char *echo_strings[2] = {
	      "The moon's gentle glow diffuses " "through the night sky.",
	      "The night sky gleams with " "glittering starlight."
	    };

	    replace_str (&weath->echo, echo_strings[n % 2]);
	  }
	time_info.sunlight = SUN_DARK;
	replace_str (&weath->echo_color, "{b");
	break;
      }
    }

  return;
}

Olc_Fun (aedit_climate)
{
  char arg[MAX_INPUT_LENGTH];
  AreaData *area;

  GetEdit (ch, AreaData, area);

  argument = one_argument (argument, arg);


  if (NullStr (arg))
    {
      chprintlnf (ch, "%s:", area->name);
      chprintlnf (ch, "\tTemperature:\t%s",
		  temp_settings[area->weather.climate_temp]);
      chprintlnf (ch, "\tPrecipitation:\t%s",
		  precip_settings[area->weather.climate_precip]);
      chprintlnf (ch, "\tWind:\t\t%s",
		  wind_settings[area->weather.climate_wind]);

      chprintlnf (ch, "Weather variables range from "
		  "%d to %d.", -3 * mud_info.weath_unit,
		  3 * mud_info.weath_unit);
      chprintlnf (ch, "Weather vectors range from "
		  "%d to %d.", -1 * mud_info.max_vector, mud_info.max_vector);
      chprintlnf (ch,
		  "The maximum a vector can " "change in one update is %d.",
		  mud_info.rand_factor + 2 * mud_info.climate_factor +
		  3 * mud_info.weath_unit);

      cmd_syntax (ch, NULL, n_fun, "temp <number>", "precip <number>",
		  "wind <number>", NULL);

      return false;
    }

  else if (!str_cmp (arg, "temp"))
    {
      int i;

      argument = one_argument (argument, arg);

      for (i = 0; i < MAX_CLIMATE; i++)
	{
	  if (str_cmp (arg, temp_settings[i]))
	    continue;

	  area->weather.climate_temp = i;
	  olc_msg (ch, n_fun, "The climate temperature "
		   "for %s is now %s.", area->name, temp_settings[i]);
	  return true;
	}

      if (i == MAX_CLIMATE)
	{
	  chprintlnf (ch, "Possible temperature settings:");
	  for (i = 0; i < MAX_CLIMATE; i++)
	    {
	      chprintlnf (ch, "\t%s", temp_settings[i]);
	    }
	}

      return false;
    }

  else if (!str_cmp (arg, "precip"))
    {
      int i;

      argument = one_argument (argument, arg);

      for (i = 0; i < MAX_CLIMATE; i++)
	{
	  if (str_cmp (arg, precip_settings[i]))
	    continue;

	  area->weather.climate_precip = i;
	  olc_msg (ch, n_fun, "The climate precipitation "
		   "for %s is now %s.", area->name, precip_settings[i]);
	  return true;
	}

      if (i == MAX_CLIMATE)
	{
	  chprintlnf (ch, "Possible precipitation settings:");
	  for (i = 0; i < MAX_CLIMATE; i++)
	    {
	      chprintlnf (ch, "\t%s", precip_settings[i]);
	    }
	}

      return false;
    }

  else if (!str_cmp (arg, "wind"))
    {
      int i;

      argument = one_argument (argument, arg);

      for (i = 0; i < MAX_CLIMATE; i++)
	{
	  if (str_cmp (arg, wind_settings[i]))
	    continue;

	  area->weather.climate_wind = i;
	  olc_msg (ch, n_fun, "The climate wind for %s "
		   "is now %s.", area->name, wind_settings[i]);
	  return true;
	}

      if (i == MAX_CLIMATE)
	{
	  chprintlnf (ch, "Possible wind settings:");
	  for (i = 0; i < MAX_CLIMATE; i++)
	    {
	      chprintlnf (ch, "\t%s", wind_settings[i]);
	    }
	}

      return false;
    }
  else
    {
      cmd_syntax (ch, NULL, n_fun, "temp <number>", "precip <number>",
		  "wind <number>", NULL);

      return false;
    }
}


void
time_update ()
{
  AreaData *pArea;
  Descriptor *d;
  WeatherData *weath;

  switch (++time_info.hour)
    {
    case 5:
    case 6:
    case HOURS_IN_DAY / 2:
    case 19:
    case 20:
      for (pArea = area_first; pArea; pArea = pArea->next)
	{
	  get_time_echo (&pArea->weather);
	}

      for (d = descriptor_first; d; d = d->next)
	{
	  if (d->connected == CON_PLAYING &&
	      IsOutside (d->character) && IsAwake (d->character))
	    {
	      weath = &d->character->in_room->area->weather;
	      if (NullStr (weath->echo))
		continue;
	      d_printlnf (d, "%s%s{x", weath->echo_color, weath->echo);
	    }
	}
      break;
    case HOURS_IN_DAY:
      time_info.hour = 0;
      time_info.day++;
      if (time_info.day % 10 == 0)
	rw_time_data (act_write);
      break;
    }

  if (time_info.day >= DAYS_IN_MONTH)
    {
      time_info.day = 0;
      time_info.month++;
    }

  if (time_info.month >= MONTHS_IN_YEAR)
    {
      time_info.month = 0;
      time_info.year++;
    }

  return;
}