/
LIB3/
LIB3/D/ADMIN/
LIB3/D/ADMIN/OBJ/
LIB3/D/ADMIN/ROOM/W/
LIB3/D/HOME/
LIB3/D/HOME/CITY/ARENA/
LIB3/D/HOME/CITY/ITEMS/
LIB3/D/HOME/CITY/POSTOFFI/
LIB3/DOC/
LIB3/GLOBAL/SPECIAL/
LIB3/GLOBAL/VIRTUAL/
LIB3/NET/
LIB3/NET/CONFIG/
LIB3/NET/DAEMON/CHARS/
LIB3/NET/GOPHER/
LIB3/NET/INHERIT/
LIB3/NET/OBJ/
LIB3/NET/SAVE/
LIB3/NET/VIRTUAL/
LIB3/OBJ/B_DAY/
LIB3/OBJ/HANDLERS/TERM_TYP/
LIB3/PLAYERS/B/
LIB3/PLAYERS/N/
LIB3/ROOM/
LIB3/SAVE/
LIB3/SAVE/BOARDS/
LIB3/SAVE/ENVIRON/
LIB3/SAVE/POST/
LIB3/STD/COMMANDS/SHADOWS/
LIB3/STD/CREATOR/
LIB3/STD/DOM/
LIB3/STD/EFFECTS/
LIB3/STD/EFFECTS/HEALING/
LIB3/STD/EFFECTS/OTHER/
LIB3/STD/EFFECTS/POISONS/
LIB3/STD/ENVIRON/
LIB3/STD/GUILDS/
LIB3/STD/LIQUIDS/
LIB3/STD/ROOM/
LIB3/STD/TRIGGER/SHADOW/
LIB3/W/
LIB3/W/BANNOR/
LIB3/W/NEWSTYLE/
inherit "std/object";

#include "climate.h"
#define FILE_NAME "/save/environ/weather"
#define HOME "/obj/handlers/weather_room"
#define MAX_DIST 100
#define YEAR 60
#define DAY 60
#define SPEED 40

/*
 * hmmmmm. ok well cloud cover...
 *                   wind speed...
 * hmmm. what would be a nice way of doing that? and climate...
 *
 * well we could do something like having the cloud cover sort of follow the low
 * or we could change the low scheme. I dont belive in global patterns, ie the
 * whole mud having the same weather. but nearby rooms should have very similar
 * weather.
 */

mixed  *coldarr, *cloudarr, *rainarr;

int     timeofyear, mooncycle, moonoff, timeofday, intensity;

int     distance( mixed *co_ord1, mixed *co_ord );
int     cloud_index( object env );
int     rain_index( object env );
int     temperature_index( object env );
string  cloud_string( object env );
string  rain_string( object env );
string  temperature_string( object env );

void    setup()
{
    set_name( "weather" );
    set_short( "weather controller extrodinare" );
    set_long( "The weather controller, at least this one is always right!\n" );
    cloudarr = ({ ({ 0, 0 }), ({ 50, 50 }), ({ -50, -50 }) });
    rainarr = ({ ({ 0, 0 }), ({ 50, 50 }), ({ -50, -50 }) });
    coldarr = ({ ({ 0, 0 }), ({ 50, 50 }), ({ -50, -50 }) });

    intensity = 100;
    restore_object( FILE_NAME );
    call_out( "update_low", SPEED );
    move( "bing" );
}

/* have this move here to get it to my weather room ;) */
move( arg )
{
    ::move( HOME );
}

mixed * query_cold()
{
    return coldarr;
}
mixed * query_rain()
{
    return rainarr;
}
mixed * query_cloud()
{
    return cloudarr;
}
int     query_moon()
{
    return mooncycle;
}
string  query_moon_string( object env )
{
    int     bing;

    bing = timeofday - (DAY / 4) -
	(distance( (mixed *)env->query_co_ord(), ({ 0, 0, 0, }) ) / 100);
    if( bing < 0 )
	bing += DAY;
    if( (moonoff + (DAY / 2) < bing) && (bing < DAY - moonoff) )
	return 0;		/* the moon is not up... */
    return({ "full moon",
	     "waning three quarter moon",
	     "waning half moon",
	     "waning quarter moon",
	     "waning cresent moon",	/* from here */
	     "new moon",
	     "waxing cresent moon",	/* to here you cannot see at night... ! */
	     "waxing quarter moon",
	     "waxing half moon",
	     "waxing three quarter moon" })[ mooncycle ];
}

int     distance( mixed *co_ord1, mixed *co_ord2 )
{
    int     off;

    if( !pointerp( co_ord1 ) || !pointerp( co_ord2 ) )
	return 0;
    if( co_ord1[ 0 ] > co_ord2[ 0 ] )
	off = co_ord1[ 0 ] - co_ord2[ 0 ];
    else
	off = co_ord2[ 0 ] - co_ord1[ 0 ];
    if( co_ord1[ 1 ] > co_ord2[ 1 ] )
	off += co_ord1[ 1 ] - co_ord2[ 1 ];
    else
	off += co_ord2[ 1 ] - co_ord1[ 1 ];
    return off;
}

int     query_season()
{
    return timeofyear / 15;
}
int     query_time_of_year()
{
    return timeofyear;
}
int     query_time_of_day()
{
    return timeofday;
}
int     query_day( object env )
{
    int     bing, bit;

    if( !env )
    {
	env = find_object( "/d/am/am/mendedrum" );
	if( !env )
	    call_other( "/d/am/am/mendeddrum", "??" );
	env = find_object( "/d/am/am/mendeddrum" );
    }
/* make it change... but not very quickly... */
    bing = timeofday - (DAY / 4) -
	(distance( (mixed *)env->query_co_ord(), ({ 0, 0, 0, }) ) / 100);
    if( bing < 0 )
	bing += DAY;
    bit = (DAY / 2) - (timeofyear - (YEAR / 2)) / (YEAR / 10);
    if( bing > bit )
	return 0;
    if( bit < 10 )
	return bit;
    return -(bing - bit);
}

/*
 * returns a percentage of light.... 100 being full sunlight...
 * down
 */
int     query_darkness( object env )
{
    int     bing, per, i;

/* so thats the day.... we should make the light fade towards night
 * though.... Hmmm.
 */
    per = -cloud_index( env );
    if( per < -100 )
	per = -100;
    if( per > 100 )
	per = 100;
    if( (i = query_day( env )) )
    {
	i *= 20;
	if( i > 100 )
	    i = 100;
	return 50 + (per + 100) * 150 * i / 20000;
    }
    bing = timeofday - (DAY / 4) -
	(distance( (mixed *)env->query_co_ord(), ({ 0, 0, 0, }) ) / 100);
    if( bing < 0 )
	bing += DAY;
    if( (moonoff + (DAY / 2) < bing) && (bing < DAY - moonoff) )
	return 15 + (per + 100) * 30 / 200;
    if( timeofday < 0 )
	timeofday += DAY;
    i = mooncycle - 5;
    if( i < 0 )
	i = -i;
    return 30 + (per + 100) * 14 * i / 200;	/* lit up by the light of the moon... tell them about it? */
}

string  weather_string( object env )
{
    return temperature_string( env ) + " with " + cloud_string( env ) +
	rain_string( env );
}

int     query_raining( object env )
{
    int     cloud, rain;

    if( temperature_index( env ) / (100 / 7) < 2 )
    {
	cloud = cloud_index( env );
	if( cloud <= 0 )
	    return 0;
	rain = rain_index( env );
	if( cloud - rain <= 0 )
	    return 0;
	return cloud - rain;
    }
    return 0;
}

int     query_hailing( object env )
{
    int     cloud, rain;

    if( temperature_index( env ) / (100 / 7) == 2 )
    {
	cloud = cloud_index( env );
	if( cloud <= 0 )
	    return 0;
	rain = rain_index( env );
	if( cloud - rain <= 0 )
	    return 0;
	return cloud - rain;
    }
    return 0;
}

int     query_snowing( object env )
{
    int     cloud, rain;

    if( (temperature_index( env ) / (100 / 7)) >= 3 )
    {
	cloud = cloud_index( env );
	if( cloud <= 0 )
	    return 0;
	rain = cloud_index( env );
	if( cloud - rain <= 0 )
	    return 0;
	return cloud - rain;
    }
    return 0;
}

string  rain_string( object env )
{
    int     cloud, rain, temp;
    string  tempstr1, tempstr2;

    cloud = cloud_index( env );
    rain = rain_index( env );
    if( cloud <= 0 )
	return "";
    if( cloud - rain <= 0 )
	return "";
    temp = temperature_index( env ) / (100 / 7);
    if( temp > 3 )
	temp = 3;
    if( temp < -3 )
	temp = -3;
    tempstr1 = ({ "very hot ",
		  "hot ",
		  "warm ",
		  "nice ",
		  "cold ",
		  "",
		  "" })[ temp + 3 ];
    tempstr2 = ({ " rain",
		  " rain",
		  " rain",
		  " rain",
		  " rain",
		  " hail",
		  " snow" })[ temp + 3 ];
    cloud = (cloud - rain) / 20;
    if( cloud > 5 )
	cloud = 5;
    return "\n" + capitalize( tempstr1 + ({ "very light",
					    "light",
					    "medium",
					    "heavy",
					    "very heavy" })[ cloud ] + tempstr2 );
}

string  temperature_string( object env )
{
    int     inten;

    inten = temperature_index( env );
    inten /= 10;
    if( inten > 10 )
	inten = 10;
    if( inten < -10 )
	inten = -10;
    return({ "Its one of those baking eggs on the pavement days",	/* -10 */
	     "So hot that the sun feels like its right next door",	/* -9 */
	     "Damn hot",	/* -8 */
	     "Very hot",	/* -7 */
	     "Hot",		/* -6 */
	     "Hot",		/* -5 */
	     "Reasonably hot",	/* -4 */
	     "Very warm",	/* -3 */
	     "Warm",		/* -2 */
	     "Pleasantly warm",	/* -1 */
	     "Average temerature",	/* 0 */
	     "A little chilly",	/* 1 */
	     "A slight nip in the air",		/* 2 */
	     "Chilly",		/* 3 */
	     "Very chilly",	/* 4 */
	     "Cold",		/* 5 */
	     "Cold",		/* 6 */
	     "Very cold",	/* 7 */
	     "Damn cold",	/* 8 */
	     "Incredibly cold",	/* 9 */
	     "Freezing cold" })[ inten + 10 ];	/* 10 */
}

string  cloud_string( object env )
{
    int     off;

    off = cloud_index( env ) / 20;
    if( off > 5 )
	off = 5;
    if( off < -5 )
	off = -5;
    return({ "a beatifully clear sky",	/* -5 */
	     "a few high level sirius clouds",	/* -4 */
	     "scattered puffy clouds",	/* -3 */
	     "very thin complete cloud cover",	/* -2 */
	     "light cloud cover",	/* -1 */
	     "medium cloud cover",	/* 0 */
	     "dense cloud cover",	/* 1 */
	     "packed cloud cover",	/* 2 */
	     "packed cloud cover",	/* 3 */
	     "heavy black clouds",	/* 4 */
	     "thick heavy clouds",	/* 5 */
	      })[ off + 5 ];
}

int     temperature_index( object env )
{
    int     off, i;
    mixed   clim, *co_ord;

    for( i = 0; i < sizeof( coldarr ); i++ )
	off += (distance( (mixed *)env->query_co_ord(), coldarr[ i ] ) % (MAX_DIST * 2));
    off = off / sizeof( coldarr );
    if( (clim = (mixed *)env->query_property( "climate" )) )
	off += clim[ C_TEMP ];
    if( off > MAX_DIST )
	off = (MAX_DIST * 2) - off;
    off -= (MAX_DIST / 2);
    off = 0 - off;
    co_ord = (mixed *)env->query_co_ord();
    if( !co_ord )
	co_ord = ({ 0, 0, 0 });
    return( off + (timeofyear - (YEAR / 2)) + (timeofday - (DAY / 2)) + co_ord[ 2 ] );
}

int     cloud_index( object env )
{
    int     off;
    mixed * clim;
    int     i;

    for( i = 0; i < sizeof( cloudarr ); i++ )
	off += (distance( (mixed *)env->query_co_ord(), cloudarr[ i ] ) % (MAX_DIST * 2));
    off = off / sizeof( cloudarr );
    if( (clim = (mixed *)env->query_property( "climate" )) )
	off += clim[ C_CLOUD ];
    if( off > MAX_DIST )
	off = (MAX_DIST * 2) - off;
    off -= (MAX_DIST / 2);
    off = 0 - off;
    return( off + (timeofyear - (YEAR / 2)) );
}

int     rain_index( object env )
{
    int     off;
    mixed * clim;
    int     i;

    for( i = 0; i < sizeof( rainarr ); i++ )
	off += (distance( (mixed *)env->query_co_ord(), rainarr[ i ] ) % (MAX_DIST * 2));
    off = off / sizeof( rainarr );
    if( (clim = (mixed *)env->query_property( "climate" )) )
	off += clim[ C_RAIN ];
    if( off > MAX_DIST )
	off = (MAX_DIST * 2) - off;
    off -= MAX_DIST / 2;
    off = 0 - off;
    return off;
}

void    update_low()
{
    int     i;

    timeofday++;
    if( timeofday > DAY )
    {
	timeofday = 0;
	timeofyear++;
	mooncycle++;
	if( mooncycle % 2 )
	{
	    moonoff += 1;
	    moonoff = moonoff % (DAY / 2);
	}
	timeofyear = timeofyear % YEAR;
	mooncycle = mooncycle % 10;
	save_object( FILE_NAME );
    }
    for( i = 0; i < sizeof( rainarr ); i++ )
    {
	rainarr[ i ][ 0 ] += random( 3 ) - 1;
	rainarr[ i ][ 0 ] = rainarr[ i ][ 0 ] % (MAX_DIST * 2);
	rainarr[ i ][ 1 ] += random( 3 ) - 1;
	rainarr[ i ][ 1 ] = rainarr[ i ][ 1 ] % (MAX_DIST * 2);
    }
    for( i = 0; i < sizeof( cloudarr ); i++ )
    {
	cloudarr[ i ][ 0 ] += random( 3 ) - 1;
	cloudarr[ i ][ 0 ] = cloudarr[ i ][ 0 ] % (MAX_DIST * 2);
	cloudarr[ i ][ 1 ] += random( 3 ) - 1;
	cloudarr[ i ][ 1 ] = cloudarr[ i ][ 1 ] % (MAX_DIST * 2);
    }
    for( i = 0; i < sizeof( coldarr ); i++ )
    {
	coldarr[ i ][ 0 ] += random( 3 ) - 1;
	coldarr[ i ][ 0 ] = coldarr[ i ][ 0 ] % (MAX_DIST * 2);
	coldarr[ i ][ 1 ] += random( 3 ) - 1;
	coldarr[ i ][ 1 ] = coldarr[ i ][ 1 ] % (MAX_DIST * 2);
    }
    intensity += random( 3 ) - 1;
    if( intensity < 50 )
	intensity = 50;
    if( intensity > 300 )
	intensity = 300;
    call_out( "update_low", SPEED );
}

void    dest_me()
{
    save_object( FILE_NAME );
    ::dest_me();
}