Lyonesse/bin/
Lyonesse/doc/eng/
Lyonesse/doc/ita/
Lyonesse/lib/
Lyonesse/lib/buildings/
Lyonesse/lib/clans/
Lyonesse/lib/data/
Lyonesse/lib/etc/
Lyonesse/lib/house/
Lyonesse/lib/misc/
Lyonesse/lib/plralias/A-E/
Lyonesse/lib/plralias/F-J/
Lyonesse/lib/plralias/K-O/
Lyonesse/lib/plralias/P-T/
Lyonesse/lib/plralias/U-Z/
Lyonesse/lib/plralias/ZZZ/
Lyonesse/lib/plrobjs/A-E/
Lyonesse/lib/plrobjs/F-J/
Lyonesse/lib/plrobjs/K-O/
Lyonesse/lib/plrobjs/P-T/
Lyonesse/lib/plrobjs/U-Z/
Lyonesse/lib/plrobjs/ZZZ/
Lyonesse/lib/plrsave/A-E/
Lyonesse/lib/plrsave/F-J/
Lyonesse/lib/plrsave/K-O/
Lyonesse/lib/plrsave/P-T/
Lyonesse/lib/plrsave/U-Z/
Lyonesse/lib/plrsave/ZZZ/
Lyonesse/lib/ships/
Lyonesse/lib/stables/
Lyonesse/lib/text/help/
Lyonesse/lib/world/
Lyonesse/lib/world/bld/
Lyonesse/lib/world/ship/
Lyonesse/lib/world/shp/
Lyonesse/lib/world/wls/
Lyonesse/lib/world/wls/Life/
Lyonesse/lib/world/wls/Map/
Lyonesse/log/
/**************************************************************************
 * #   #   #   ##   #  #  ###   ##   ##  ###       http://www.lyonesse.it *
 * #    # #   #  #  ## #  #    #    #    #                                *
 * #     #    #  #  # ##  ##    #    #   ##   ## ##  #  #  ##             *
 * #     #    #  #  # ##  #      #    #  #    # # #  #  #  # #            *
 * ###   #     ##   #  #  ###  ##   ##   ###  #   #  ####  ##    Ver. 1.0 *
 *                                                                        *
 * -Based on CircleMud & Smaug-     Copyright (c) 2001-2002 by Mithrandir *
 *                                                                        *
 * ********************************************************************** */
/* ************************************************************************
*   File: weather.c                                     Part of CircleMUD *
*  Usage: functions handling time and the weather                         *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "db.h"
#include "clan.h"

#define MAGIC_PRECIP_START	1190
#define MAGIC_PRECIP_STOP	980

/* external globals */
extern TIME_INFO_DATA		time_info;
extern CLAN_POLITIC_DATA	politics_data;

/* external functions */
WILD_DATA *wild_sector(int y, int x);
SHIP_DATA *find_ship( sh_int vnum );
void	SimulateEconomy(void);
void	UpdateMarketAffections(void);
void	RollMarketAffections(void);
void	SaveMarkets(void);

/* locals */
void weather_and_time(int mode);
void another_hour(int mode);
void WeatherInit(void);
void change_weather(void);
bool LoadWeatherData(void);
void SaveWeatherData(void);
void WriteWeatherInfo(void);

/* Globals */
WEATHER_DATA	Weather[MAP_WEATH_Y][MAP_WEATH_X];

/* currently unused */
const char winddir[NUM_SEASONS]	=
{
  NORTH,
  SOUTHWEST,
  WEST,
  NORTHEAST
};

/* ============================================================== */

int Season(void)
{
	switch (time_info.month)
	{
	default:
		break;
	case  3:
	case  4:
	case  5:
	case  6:
		return (SPRING);
	case  7:
	case  8:
	case  9:
	case 10:
		return (SUMMER);
	case 11:
	case 12:
	case 13:
	case 14:
		return (AUTUMN);
	}

	return (WINTER);
}


void MoonMessage(void)
{
	char tbuf[MAX_STRING_LENGTH];

	switch (MoonPhase)
	{
	case MOON_NEW:
		strcpy(tbuf, "A black disc, devoid of stars, is the only moon on this night.\r\n");
		break;
	case MOON_WAXING_CRESCENT:
		strcpy(tbuf, "The short sliver of moon offers its jagged edge to the night sky.\r\n");
		break;
	case MOON_WAXING_HALF:
		strcpy(tbuf, "The waxing half moon rises for its night journey across the heavens.\r\n");
		break;
	case MOON_WAXING_THREE_QUARTERS:
		strcpy(tbuf, "The waxing three quarter moon rises.\r\n");
		break;
	case MOON_FULL:
		strcpy(tbuf, "The full moon rises, casting a silver glow over the night.\r\n");
		break;
	case MOON_WANING_THREE_QUARTERS:
		strcpy(tbuf, "The grey-silver waning three-quarter moon begins its nocturnal trek.\r\n");
		break;
	case MOON_WANING_HALF:
		strcpy(tbuf, "Amidst an oceanic starry night sky, the waning half moon floats,\r\nits silvery ship adrift on celestial currents.\r\n");
		break;
	case MOON_WANING_CRESCENT:
		strcpy(tbuf, "A curved waning crescent moon graces the night with a few rays of moonlight.\r\n");
		break;
	}

	send_to_outdoor(tbuf);
}

/* moon change day by day */
void ChangeMoon(void)
{
	if		(time_info.day	< 4)		MoonPhase = MOON_NEW;
	else if	(time_info.day	< 8)		MoonPhase = MOON_WAXING_CRESCENT;
	else if	(time_info.day	< 13)		MoonPhase = MOON_WAXING_HALF;
	else if	(time_info.day	< 18)		MoonPhase = MOON_WAXING_THREE_QUARTERS;
	else if	(time_info.day	< 23)		MoonPhase = MOON_FULL;
	else if	(time_info.day	< 27)		MoonPhase = MOON_WANING_THREE_QUARTERS;
	else if	(time_info.day	< 31)		MoonPhase = MOON_WANING_HALF;
	else								MoonPhase = MOON_WANING_CRESCENT;
}


void weather_and_time(int mode)
{
	another_hour(mode);
	if (mode)
	{
		change_weather();
		SaveWeatherData();
		WriteWeatherInfo();
	}
}


void another_hour(int mode)
{
	char tbuf[MAX_STRING_LENGTH];
	int rstr = number(1, 3);
	int oldmoon = MoonPhase;
	int x, y;
	static int econ_delay = 6;

	time_info.hours++;
	
	if (mode)
	{
		switch (time_info.hours)
		{
		case 4:
			/* moon new - no moon in the sky can disappear.. */
			if (Sunlight != MOON_RISE)
				break;

			Sunlight = MOON_SET;
			if (rstr == 1)
				strcpy(tbuf, "The moon sets.\r\n");
			else if (rstr == 2)
				strcpy(tbuf, "The moon disappears beneath the horizon.\r\n");
			else
				strcpy(tbuf, "The sky grows dark as the moon sets.\r\n");
			send_to_outdoor(tbuf);
			break;

		case 5:
			Sunlight = SUN_RISE;
			if (rstr == 1)
				strcpy(tbuf, "Dawn blushes the sky with hues of orange and magenta.\r\n");
			else if (rstr == 2)
				strcpy(tbuf, "The day has begun.\r\n");
			else
				strcpy(tbuf, "It is dawn.\r\n");
			send_to_outdoor(tbuf);
			break;

		case 6:
			Sunlight = SUN_LIGHT;
			if (rstr == 1)
				strcpy(tbuf, "The first shafts of sunlight streak along their western path.\r\n");
			else if (rstr == 2)
				strcpy(tbuf, "The sun rises in the east.\r\n");
			else
				strcpy(tbuf, "The sun illuminates the lands.\r\n");
			send_to_outdoor(tbuf);
			for (x = 1; x < MAX_CLANS; x++)
			{
				for (y = 1; y < MAX_CLANS; y++)
					politics_data.daily_negotiate_table[x][y] = FALSE;
			}
			break;

		case 12:
			if (rstr == 1)
				strcpy(tbuf, "It is noon.\r\n");
			else if (rstr == 2)
				strcpy(tbuf, "The sun reaches its apex in the sky.\r\n");
			else
				strcpy(tbuf, "Sunlight beats down upon you from directly above.\r\n");
			send_to_outdoor(tbuf);
			break;

		case 21:
			Sunlight = SUN_SET;
			if (rstr == 1)
				strcpy(tbuf, "The sun slowly disappears in the west.\r\n");
			else if ( rstr == 2 )
				strcpy(tbuf, "The sun dips below the western horizon.\r\n");
			else
				strcpy(tbuf, "The sun sets with a glorious twilight.\r\n");
			send_to_outdoor(tbuf);
			break;

		case 22:
			Sunlight = SUN_DARK;
			if (rstr == 1)
				strcpy(tbuf, "The night has begun.\r\n");
			else if (rstr == 2)
				strcpy(tbuf, "The last bit of twilight fades away to blackness.\r\n");
			else
				strcpy(tbuf, "The darkness of night engulfs the realm.\r\n");
			send_to_outdoor(tbuf);
			break;

		case 23:
			if (MoonPhase != MOON_NEW)
			{
				Sunlight = MOON_RISE;
				MoonMessage();
			}
			break;

		default:
			break;
		}
	}

	// modifiy economy data
	if (!(time_info.hours % econ_delay))
	{
		log("Performing economy simulation -- delay is %d", econ_delay);
		SimulateEconomy();
	}

	if (time_info.hours > 23)	/* Changed by HHS due to bug ??? */
	{
		time_info.hours = 0;
		time_info.day++;

		ChangeMoon();

		// every day update market affections
		UpdateMarketAffections();

		// setup new interval...
		econ_delay = 6 + number(0, 6);
		
		if (time_info.day > 34)
		{
			time_info.day = 0;
			time_info.month++;
			
			// every three months roll automatic market affections
			if (!(time_info.month % 3))
			{
				RollMarketAffections();
				SaveMarkets();
			}

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

/* *************************************************************** */

void WeatherInit(void)
{
	sh_int s;
	int y, x;
	
	/* default conditions for season values */
	const char winds[NUM_SEASONS] 	= {25, 12, 8, 40};
	const char precip[NUM_SEASONS]	= {16, 30, 23, 10};
	const char humid[NUM_SEASONS] 	= {40, 75, 20, 14};
	const char temps[NUM_SEASONS] 	= {5, 17, 27, 13};

	/* Weather System */
	log("Initializing Weather System.");

	if (LoadWeatherData())
		return;

	/* get the season */
	s = Season();

	for (y = 0; y < MAP_WEATH_Y; y++)
	{
		for (x = 0; x < MAP_WEATH_X; x++)
		{
			if (s == WINTER)
				Weather[y][x].pressure	= 985;
			else if (s == SUMMER)
				Weather[y][x].pressure	= 1030;
			else
				Weather[y][x].pressure	= 1010;

			Weather[y][x].windspeed		= winds[s];
			Weather[y][x].wind_dir		= winddir[s];
			Weather[y][x].precip_rate	= precip[s];
			Weather[y][x].humidity		= humid[s];
			Weather[y][x].temp			= temps[s];
			Weather[y][x].free_energy	= 10000;
		}
	}

	for (y = 0; y < 500; y++)
		change_weather();

	SaveWeatherData();
	WriteWeatherInfo();
}


void change_weather(void)
{
	WEATHER_DATA *cond;
	WILD_DATA *wd;
	COORD_DATA csect;
	int y, x, magic;
	int old_wind, old_temp, old_precip, season_num;
	int pbreak;
	
	season_num = Season();

	for (y = 0; y < MAP_WEATH_Y; y++)
	{
		for (x = 0; x < MAP_WEATH_X; x++)
		{
			cond			= &Weather[y][x];

			old_temp		= cond->temp;
			old_precip		= cond->precip_rate;
			old_wind		= cond->windspeed;
		
			cond->free_energy	= URANGE(3000, cond->free_energy, 50000);

			switch (season_num)
			{
			case WINTER:
				// wind speed
				if		(cond->windspeed < 5)	cond->windspeed += 5;
				else if (cond->windspeed > 60)	cond->windspeed -= 5;
				else							cond->windspeed += number(-6, 6);

				// temperature
				if		(cond->temp < -10)		cond->temp += 1;
				else if (cond->temp > 15)		cond->temp -= 2;
				else							cond->temp += number(-3, 2);

				// humidity
				if		(cond->humidity < 30)	cond->humidity += 3;
				else if (cond->humidity > 70)	cond->humidity -= 2;
				else							cond->humidity += number(-9, 9);

				if (old_precip > 55)			cond->precip_rate -= 10;

				pbreak = 985;
				break;

			case SPRING:
				// wind speed
				if (cond->windspeed > 40)		cond->windspeed -= 5;
				else							cond->windspeed += number(-2, 2);

				// temperature
				if		(cond->temp < 7)		cond->temp += 2;
				else if (cond->temp > 26)		cond->temp -= 2;
				else							cond->temp += number(-2, 2);

				// humidity
				if		(cond->humidity < 40)	cond->humidity += 3;
				else if (cond->humidity > 80)	cond->humidity -= 2;
				else							cond->humidity += number(-8, 8);

				if (old_precip > 65)			cond->precip_rate -= 10;

				pbreak = 1000;
				break;

			case SUMMER:
				// wind speed
				if (cond->windspeed > 25)		cond->windspeed -= 5;
				else							cond->windspeed += number(-2, 1);

				// temperature
				if		(cond->temp < 24)		cond->temp += 3;
				else if (cond->temp > 46)		cond->temp -= 2;
				else							cond->temp += number(-2, 5);

				// humidity
				if		(cond->humidity < 13)	cond->humidity += 3;
				else if (cond->humidity > 91)	cond->humidity -= 2;
				else							cond->humidity += number(-5, 4);

				if (old_precip > 45)			cond->precip_rate -= 10;

				pbreak = 1015;
				break;

			case AUTUMN:
				// wind speed
				if		(cond->windspeed < 15)	cond->windspeed += 5;
				else if (cond->windspeed > 80)	cond->windspeed -= 5;
				else							cond->windspeed += number(-6, 6);
				
				// temperature
				if		(cond->temp < -3)		cond->temp += 2;
				else if (cond->temp > 14)		cond->temp -= 2;
				else							cond->temp += number(-3, 3);

				// humidity
				if (cond->humidity > 40)		cond->humidity -= 3;
				else							cond->humidity += number(-3, 2);

				if (old_precip > 20)			cond->precip_rate -= 8;

				pbreak = 1000;
				break;

			default:
				break;
			}

			cond->windspeed			= URANGE(0, cond->windspeed, 200);
			cond->wind_dir			= winddir[season_num];

			cond->free_energy		+= cond->windspeed * 10;

			if (cond->free_energy > 20000)
				cond->windspeed		+= number(-10, -1);
			cond->windspeed			= URANGE(0, cond->windspeed, 200);

			cond->humidity			= URANGE(0, cond->humidity, 100);
			
			cond->pressure_change	+= number(-3, 3);
			cond->pressure_change	= URANGE(-8, cond->pressure_change, 8);
			cond->pressure			+= cond->pressure_change;
			cond->pressure			= URANGE(960, cond->pressure, 1040);
			
			cond->free_energy		+= cond->pressure_change;

			/* The numbers that follow are truly magic since  */
			/* they have little bearing on reality and are an */
			/* attempt to create a mix of precipitation which */
			/* will seem reasonable for a specified climate   */
			/* without any complicated formulae that could    */
			/* cause a performance hit. To get more specific  */
			/* or exacting would certainly not be "Diku..."   */
			
			magic = ((1240 - cond->pressure) * cond->humidity >> 4) +
				cond->temp + old_precip * 2 + (cond->free_energy - 10000) / 100;

			// find out which wild sector is
			csect.y = y * MAP_SIZE;
			csect.x = x * MAP_SIZE;
			wd = wild_sector(csect.y, csect.x);
			
			if (old_precip == 0)
			{
				if (magic > MAGIC_PRECIP_START)
				{
					cond->precip_rate += number(1, 10);
					if (cond->temp > 0)
						send_to_wildsect(wd, "It begins to rain.\r\n");
					else
						send_to_wildsect(wd, "It starts to snow.\r\n");
				}
				else if (!old_wind && cond->windspeed)
					send_to_wildsect(wd, "The wind begins to blow\r\n");
				else if (cond->windspeed - old_wind > 10)
					send_to_wildsect(wd, "The wind picks up some.\r\n");
				else if (cond->windspeed - old_wind < -10)
					send_to_wildsect(wd, "The wind calms down a bit.\r\n");
				else if (cond->windspeed > 60)
				{
					if (cond->temp > 50)
						send_to_wildsect(wd, "A violent scorching wind blows hard in the face of any poor travellers in the area.\r\n");
					else if (cond->temp > 21)
						send_to_wildsect(wd, "A hot wind gusts wildly through the area.\r\n");
					else if (cond->temp > 0)
						send_to_wildsect(wd, "A fierce wind cuts the air like a razor-sharp knife.\r\n");
					else if (cond->temp > -10)
						send_to_wildsect(wd, "A freezing gale blasts through the area.\r\n");
					else
						send_to_wildsect(wd, "An icy wind drains the warmth from all in sight.\r\n");
				}
				else if (cond->windspeed > 25)
				{
					if (cond->temp > 50)
						send_to_wildsect(wd, "A hot, dry breeze blows languidly around.\r\n");
					else if (cond->temp > 22)
						send_to_wildsect(wd, "A warm pocket of air is rolling through here.\r\n");
					else if (cond->temp > 10)
						send_to_wildsect(wd, "It's breezy.\r\n");
					else if (cond->temp > 2)
						send_to_wildsect(wd, "A cool breeze wafts by.\r\n");
					else if (cond->temp > -5)
						send_to_wildsect(wd, "A slight wind blows a chill into living tissue.\r\n");
					else if (cond->temp > -15)
						send_to_wildsect(wd, "A freezing wind blows gently, but firmly against all obstacles in the area.\r\n");
					else
						send_to_wildsect(wd, "The wind isn't very strong here, but the cold makes it quite noticeable.\r\n");
				}
				else if (cond->temp > 52)
					send_to_wildsect(wd, "It's hotter than anyone could imagine.\r\n");
				else if (cond->temp > 37)
					send_to_wildsect(wd, "It's really, really hot here. A slight breeze would really improve things.\r\n");
				else if (cond->temp > 25)
					send_to_wildsect(wd, "It's hot out here.\r\n");
				else if (cond->temp > 19)
					send_to_wildsect(wd, "It's nice and warm out.\r\n");
				else if (cond->temp > 9)
					send_to_wildsect(wd, "It's mild out today.\r\n");
				else if (cond->temp > 1)
					send_to_wildsect(wd, "It's cool out here.\r\n");
				else if (cond->temp > -5)
					send_to_wildsect(wd, "It's a bit nippy here.\r\n");
				else if (cond->temp > -20)
					send_to_wildsect(wd, "It's cold!\r\n");
				else if (cond->temp > -25)
					send_to_wildsect(wd, "It's really c-c-c-cold!!\r\n");
				else
					send_to_wildsect(wd, "Better get inside - this is too cold for man or -most- beasts.\r\n");
			}
			else if (magic < MAGIC_PRECIP_STOP || (old_precip == 1 && cond->pressure > pbreak))
			{
				cond->precip_rate = 0;
				if (old_temp > 0)
					send_to_wildsect(wd, "The rain stops.\r\n");
				else
					send_to_wildsect(wd, "It stops snowing.\r\n");
			}
			else
			{
				/* Still precip'ing, update the rate */
				sh_int pchange = 0;

				// slow rate
				if (cond->pressure >= pbreak)
				{
					if (cond->windspeed > 50)
						pchange += number(-3, 1);
					else if (cond->windspeed > 20)
						pchange += number(-2, 2);
					else
						pchange += number(-1, 2);

					// check humidity
					if (cond->humidity < 30)
						pchange += number(-4, 2);
					else if (cond->humidity < 60)
						pchange += number(-3, 2);
					else
						pchange += number(-2, 2);
				}
				// increase rate
				else
				{
					if (cond->windspeed > 50)
						pchange += number(-2, 1);
					else if (cond->windspeed > 20)
						pchange += number(-1, 1);
					else
						pchange += number(0, 2);

					// check humidity
					if (cond->humidity < 30)
						pchange += number(-2, 2);
					else if (cond->humidity < 60)
						pchange += number(-1, 2);
					else
						pchange += number(-1, 3);
				}

				/* energy adjustment */
				if (cond->free_energy > 10000)
					pchange += number(-3, 4);
				else
					pchange += number(-4, 2);

				cond->precip_change	+= pchange;
				cond->precip_change	= URANGE(-10, cond->precip_change, 10);

				cond->precip_rate	+= cond->precip_change;
				cond->precip_rate	= URANGE(1, cond->precip_rate, 100);

				cond->free_energy	-= cond->precip_rate * 3 - abs(cond->precip_change);
				
				/* Check rain->snow or snow->rain */
				if (old_temp > 0 && cond->temp <= 0)
					send_to_wildsect(wd, "The rain turns to snow.\r\n");
				else if (old_temp <= 0 && cond->temp > 0)
					send_to_wildsect(wd, "The snow turns to a cold rain.\r\n");
				else if (cond->precip_change > 5)
				{
					if (cond->temp > 0)
						send_to_wildsect(wd, "It rains a bit harder.\r\n");
					else
						send_to_wildsect(wd, "The snow is coming down faster now.\r\n");
				}
				else if (cond->precip_change < -5)
				{
					if (cond->temp > 0)
						send_to_wildsect(wd, "The rain is falling less heavily now.\r\n");
					else
						send_to_wildsect(wd, "The snow has let up a little.\r\n");
				}
				else if (cond->temp > 0)
				{
					if (cond->precip_rate > 80)
					{
						if (cond->windspeed > 80)
							send_to_wildsect(wd, "There's a hurricane out here!\r\n");
						else if (cond->windspeed > 40)
							send_to_wildsect(wd, "The wind and the rain are nearly too much to handle.\r\n");
						else
							send_to_wildsect(wd, "It's raining really hard right now.\r\n");
					}
					else if (cond->precip_rate > 50)
					{
						if (cond->windspeed > 60)
							send_to_wildsect(wd, "What a rainstorm!\r\n");
						else if (cond->windspeed > 30)
							send_to_wildsect(wd, "The wind is lashing this wild rain seemingly straight into your face.\r\n");
						else
							send_to_wildsect(wd, "It's raining pretty hard.\r\n");
					}
					else if (cond->precip_rate > 30)
					{
						if (cond->windspeed > 50)
							send_to_wildsect(wd, "A respectable rain is being thrashed about by a vicious wind.\r\n");
						else if (cond->windspeed > 25)
							send_to_wildsect(wd, "It's rainy and windy but, altogether not too uncomfortable.\r\n");
						else
							send_to_wildsect(wd, "Hey, it's raining...\r\n");
					}
					else if (cond->precip_rate > 10)
					{
						if (cond->windspeed > 50)
							send_to_wildsect(wd, "The light rain here is nearly unnoticeable compared to the horrendous wind.\r\n");
						else if (cond->windspeed > 24)
							send_to_wildsect(wd, "A light rain is being driven fiercely by the wind.\r\n");
						else
							send_to_wildsect(wd, "It's raining lightly.\r\n");
					}
					else if (cond->windspeed > 55)
					
						send_to_wildsect(wd, "A few drops of rain are falling admidst a fierce windstorm.\r\n");
					else if (cond->windspeed > 30)
						send_to_wildsect(wd, "The wind and a bit of rain hint at the possibility of a storm.\r\n");
					else
						send_to_wildsect(wd, "A light drizzle is falling here.\r\n");
				}
				else if (cond->precip_rate > 70)
				{
					if (cond->windspeed > 50)
						send_to_wildsect(wd, "This must be the worst blizzard ever.\r\n");
					else if (cond->windspeed > 25)
						send_to_wildsect(wd, "There's a blizzard out here, making it quite difficult to see.\r\n");
					else
						send_to_wildsect(wd, "It's snowing very hard.\r\n");
				}
				else if (cond->precip_rate > 40)
				{
					if (cond->windspeed > 60)
						send_to_wildsect(wd, "The heavily falling snow is being whipped up to a frenzy by a ferocious wind.\r\n");
					else if (cond->windspeed > 35)
						send_to_wildsect(wd, "A heavy snow is being blown randomly about by a brisk wind.\r\n");
					else if (cond->windspeed > 18)
						send_to_wildsect(wd, "Drifts in the snow are being formed by the wind.\r\n");
					else
						send_to_wildsect(wd, "The snow's coming down pretty fast now.\r\n");
				}
				else if (cond->precip_rate > 19)
				{
					if (cond->windspeed > 70)
						send_to_wildsect(wd, "The snow wouldn't be too bad, except for the awful wind blowing it in every possible directon.\r\n");
					else if (cond->windspeed > 45)
						send_to_wildsect(wd, "There's a minor blizzard here, more wind than snow.\r\n");
					else if (cond->windspeed > 12)
						send_to_wildsect(wd, "Snow is being blown about by a stiff breeze.\r\n");
					else
						send_to_wildsect(wd, "It is snowing here.\r\n");
				}
				else if (cond->windspeed > 60)
					send_to_wildsect(wd, "A light snow is being tossed about by a fierce wind.\r\n");
				else if (cond->windspeed > 42)
					send_to_wildsect(wd, "A lightly falling snow is being driven by a strong wind.\r\n");
				else if (cond->windspeed > 18)
					send_to_wildsect(wd, "A light snow is falling admidst an unsettled wind.\r\n");
				else
					send_to_wildsect(wd, "It is lightly snowing.\r\n");
			}
		}
	}
}


/* ************************************************************* */

bool LoadWeatherData(void)
{
	FILE *fp;
	char fname[256];
	int y;

	sprintf(fname, "%sweathdata.wls", WLS_PREFIX);
	if ( !( fp = fopen(fname, "rb") ) )
	{
		log("SYSERR: unable to read weather data file.");
		return (FALSE);
	}

	for ( y = 0; y < MAP_WEATH_Y; y++ )
		fread(Weather[y], sizeof(WEATHER_DATA), MAP_WEATH_X, fp);

	fclose(fp);
	return (TRUE);
}

void SaveWeatherData(void)
{
	FILE *fp;
	char fname[256];
	int y;

	sprintf(fname, "%sweathdata.wls", WLS_PREFIX);
	if ( !( fp = fopen(fname, "wb") ) )
	{
		log("SYSERR: unable to write weather data file.");
		return;
	}

	for ( y = 0; y < MAP_WEATH_Y; y++ )
		fwrite(Weather[y], sizeof(WEATHER_DATA), MAP_WEATH_X, fp);

	fclose(fp);
}


void WriteWeatherInfo(void)
{
	FILE *fp;
	WEATHER_DATA *cond;
	char fname[256];
	int y, x;
	
	sprintf(fname, "%sweather.wls", WLS_PREFIX);
	if ( !( fp = fopen(fname, "w") ) )
	{
		log("SYSERR: unable to write new weather file.");
		return;
	}
	
	fprintf(fp, "SEASON: %d\n", Season());
	for (y = 0; y < MAP_WEATH_Y; y++)
	{
		for (x = 0; x < MAP_WEATH_X; x++)
		{
			cond = &Weather[y][x];
			
			fprintf(fp, "[%3d %3d] - ", y * MAP_SIZE, x * MAP_SIZE);
			fprintf(fp, "Temp: %2d  Humidity: %2d  Pressure: %4d  ",
				cond->temp, cond->humidity, cond->pressure);
			fprintf(fp, "Windspeed: %3d  Precip Rate: %3d  ",
				cond->windspeed, cond->precip_rate);
			fprintf(fp, "Pressure change: %2d  Precip change: %3d  FEnergy: %d",
				cond->pressure_change, cond->precip_change, cond->free_energy);
			fprintf(fp, "\n");
		}
	}
	fclose(fp);
}

/* ************************************************************* */

COORD_DATA get_wwmap_indexes(COORD_DATA *coord)
{
	COORD_DATA csect;

	/* normalize to wild sector coordinates */
	csect.y = coord->y / MAP_SIZE * MAP_SIZE;
	csect.x = coord->x / MAP_SIZE * MAP_SIZE;

	/* calculates weather map indexes */
	csect.y = URANGE(0, (csect.y / MAP_SIZE), MAP_WEATH_Y - 1);
	csect.x = URANGE(0, (csect.x / MAP_SIZE), MAP_WEATH_X - 1);

	return (csect);
}

/* given a room, returns the new weather in the room's wild sector */
WEATHER_DATA *get_room_weather(ROOM_DATA *pRoom)
{
	COORD_DATA csect;

	if (!pRoom)
		return (NULL);

	if (IS_WILD(pRoom))
		csect = *pRoom->coord;
	else if (IS_SHIP(pRoom))
	{
		SHIP_DATA *ship = find_ship(pRoom->extra_data->vnum);
		csect = *ship->in_room->coord;

	}
	else if (IS_FERRY(pRoom))
	{
		FERRY_DATA *pFerry = get_ferry(pRoom->extra_data->vnum);
		csect = *pFerry->in_room->coord;
	}
	else if (pRoom->zone == NOWHERE)
	{
		return (NULL);
	}
	else
	{
		csect = zone_table[pRoom->zone].wild.z_start;

		// check if zone has a place in the wilderness
		if (csect.y == 0 && csect.x == 0)
			return (NULL);
	}

	csect = get_wwmap_indexes(&csect);

	return (&Weather[csect.y][csect.x]);
}


WEATHER_DATA *get_coord_weather(COORD_DATA *coord)
{
	COORD_DATA csect = get_wwmap_indexes(coord);
	return (&Weather[csect.y][csect.x]);
}