#include <stdlib.h> #include <time.h> #include <math.h> #include "kernel.h" #include "sendsys.h" #include "climate.h" #include "pflags.h" #include "sflags.h" #include "lflags.h" #include "bprintf.h" #include "parse.h" #include "rooms.h" #include "xrweathermsgs.h" #include "log.h" #ifdef XR_WEATHER Boolean is_daytime( int location ) { time_t t_time; struct tm *the_time; time (&t_time); the_time = localtime (&t_time); if( 5 < the_time->tm_hour && the_time->tm_hour < 17 ) return True; return False; } /* * Function used to display weather to mynum when entering a room. */ void show_weather (void) { int temp; int wind; int rain; if( !ltstflg( ploc (mynum), LFL_OUTDOORS ) ) return; /* Determine the wind array position. */ wind = wind2num( global_weather->windspeed ); /* Determine the Rain array position. */ rain = rain2num( mynum, global_weather->rain ); /* Determine the Location/temp array position. */ temp = get_temp( ploc(mynum) ); if( temp < 40 ) temp = 1; /* Snowing land & water */ else if( ltstflg( ploc(mynum), LFL_ON_WATER ) ) temp = 2; /* On Water */ else temp = 0; /* On Land */ /* Adjust for only wind messages (not raining. :)) */ if( rain == 0 ) temp = 0; /* Print the message */ if( global_weather->sunny ) { if( is_daytime( ploc(mynum) ) ) bprintf( "The &+Ysun&N is shining.\n" ); else bprintf( "The &+Ymoonlight&N shines down from above.\n" ); } bprintf( "%s", xrweathermsgs[wind][rain][temp] ); return; } /* * Game command to tell us what the weather is like. */ void weathercom (void) { int room; if (!ptstflg (mynum, PFL_WEATHER)) { erreval (); return; } if( ( room = getroomnum( ) ) == 0 ) room = ploc( mynum ); if( plev(mynum) >= LVL_SHALAFI ) { if( !strcmp( wordbuf, "sunny" ) ) { start_weather( WEATHER_SUNNY ); return; } else if( !strcmp(wordbuf, "cloudy") ) { start_weather( WEATHER_CLOUDY ); return; } else if( !strcmp(wordbuf, "rainy" ) ) { if( global_weather->sunny ) start_weather( WEATHER_CLOUDY ); else start_weather( WEATHER_RAIN ); return; } } bprintf( "&+CCurrent weather conditions for &+B%s&+C:\n", sdesc( room ) ); bprintf( "&+GTemperature: &+W%d degrees.\n", get_temp( room ) ); bprintf( "&+GLatitude: &+W%d degrees.\n", zlatitude( lzone( room ) ) ); bprintf( "&+GAltitude: &+W%d feet.\n", laltitude( room ) ); bprintf( "&+GRainfall: &+W%d mm per year.\n", zrainfall( lzone( room ) ) ); bprintf( "\n&+CGlobal weather conditions:\n" ); bprintf( "&+GWeather : " ); if( !global_weather->sunny ) bprintf( "&+LCloudy\n" ); else if( is_daytime(room) ) bprintf( "&+YSunny\n" ); else bprintf( "&+WMoonlit\n" ); bprintf( "&+GWind Speed : &+W%d\n", global_weather->windspeed ); if( plev(mynum) >= LVL_SHALAFI ) { bprintf( "&+GRain : &+W%d\n", global_weather->rain ); bprintf( "&+GWeather Timer : &+W%d\n", global_weather->timer ); if( global_weather->sunny == False ) { bprintf( "&+GEnd of Standby : &+W%d\n", global_weather->standby ); bprintf( "&+GEnd of Decline : &+W%d\n", global_weather->decline ); bprintf( "&+GEnd of Steady : &+W%d\n", global_weather->steady ); } bprintf( "&+GWeather Until : &+W%d\n", global_weather->weatherlen ); if( global_weather->sunny == False ) bprintf( "&+GBottom : &+W%d\n", global_weather->bottom ); } return; } /* * NASTY function to get the temperature in a given room. It's based on: * * 1) Time Of The Year * 2) Latitude * 3) Altitude * 4) Rainfall * 5) Wind Speed * * Don't even try to comprehend it. :) */ int get_temp( int location ) { int temperature; time_t t_time; struct tm *the_time; time (&t_time); the_time = localtime (&t_time); temperature = 125+global_weather->sunny*10- pow(zlatitude(lzone(location)),2)/75- laltitude(location)/250- abs((the_time->tm_mon-6))*7*zlatitude(lzone(location))/90- abs(global_weather->windspeed)/4- (int)((double)10*log10((double)(1+zrainfall(lzone(location)))) * (double)((double)1-((double)zlatitude(lzone(location))/(double)90)))- (int)((double).6 * ((double)7 -log10((double)(1+zrainfall(lzone(location)))))* abs((the_time->tm_hour-12))* (double)(110-zlatitude(lzone(location)))/(double)90); return temperature; } /* * Change the wind speed once every two minutes by +/- 16 usually * much smaller values than that, though. :) */ void update_weather( ) { int variance, oldwind; /* Check to run weather routines every two minutes */ global_weather->counter += 1; if ( global_weather->counter != 60 ) return; global_weather->counter = 0; global_weather->timer += 1; /* Wind variance stuff */ oldwind = global_weather->windspeed; variance = (((rand()%2)?1:-1)* (rnd(8)*rnd(8)*rnd(8)*rnd(8)/256)); if ( variance > 0 && global_weather->windspeed >= 25 && global_weather->windspeed < 80 && ( rnd(20) == 1 ) ) variance = -variance; if(((global_weather->timer - global_weather->last_hurricane ) < 120 ) && variance > 0 && global_weather->windspeed > 75 ) variance = -variance; global_weather->windspeed += variance; if( global_weather->windspeed <= -10 ) global_weather->windspeed = -10; else if( global_weather->windspeed >= 100 ) { start_weather( WEATHER_HURRICANE ); } windmsgs( oldwind ); /* * Rain stuff. Check to see if it's time to switch from rainy<->sunny */ if( (global_weather->weatherlen - global_weather->timer) <= 0 ) { if( global_weather->sunny ) start_weather( WEATHER_CLOUDY ); else start_weather( WEATHER_SUNNY ); } /* * Dont' update rain info if it's: * * a) sunny * b) waiting to start to decline to steady * c) at steady */ if( global_weather->sunny || (global_weather->timer < global_weather->standby )|| (global_weather->decline < global_weather->timer && global_weather->timer < global_weather->steady)) return; /* Time to start a new cycle? */ if( global_weather->timer > global_weather->duration ) { start_weather( WEATHER_RAIN ); return; } /* We're declining. */ if(global_weather->standby < global_weather->timer < global_weather->decline) { int old_value = global_weather->rain; global_weather->rain = 10000 - (int)((double)(10000 - global_weather->bottom) * (double)(global_weather->timer - global_weather->standby) / (double)(global_weather->decline - global_weather->standby)); rainmsgs( old_value ); return; } /* Inclining */ if(global_weather->duration > global_weather->timer > global_weather->steady) { int old_value = global_weather->rain; global_weather->rain = (int)( (double)(global_weather->timer - global_weather->steady) * (double)(10000 - global_weather->bottom ) / (double)(global_weather->duration - global_weather->steady) + (double)global_weather->bottom); rainmsgs( old_value ); return; } if( global_weather->timer >= global_weather->duration ) { if((global_weather->weatherlen - global_weather->timer) > 5) start_weather( WEATHER_RAIN ); return; } return; } /* * Routine to boot weather sequences. */ void boot_weather( ) { FILE *weatherfile; global_weather->windspeed = 0; global_weather->timer = 0; global_weather->counter = 0; global_weather->last_hurricane = 0; global_weather->bottom = 0; global_weather->duration = 0; global_weather->decline = 0; global_weather->steady = 0; if( ( weatherfile = FOPEN( WEATHER_FILE, "r" )) == NULL ) { start_weather( WEATHER_SUNNY ); return; } fscanf( weatherfile, "Sunny: %d\n", (int *) &global_weather->sunny ); fscanf( weatherfile, "Windspeed: %d\n", &global_weather->windspeed ); fscanf( weatherfile, "Rain: %d\n", &global_weather->rain ); fscanf( weatherfile, "Timer: %d\n", &global_weather->timer ); fscanf( weatherfile, "Counter: %d\n", &global_weather->counter ); fscanf( weatherfile, "LHurricane: %d\n", &global_weather->last_hurricane ); fscanf( weatherfile, "WeatherLen: %d\n", &global_weather->weatherlen ); fscanf( weatherfile, "Bottom: %d\n", &global_weather->bottom ); fscanf( weatherfile, "Duration: %d\n", &global_weather->duration ); fscanf( weatherfile, "Standby: %d\n", &global_weather->standby ); fscanf( weatherfile, "Decline: %d\n", &global_weather->decline ); fscanf( weatherfile, "Steady: %d\n", &global_weather->steady ); FCLOSE( weatherfile ); } void start_weather( int weather ) { int steady; if( weather == WEATHER_SUNNY ) { global_weather->weatherlen = (int)((double)(rnd(2)*rnd(2)*rnd(2)*rnd(2)* rnd(2)*rnd(2)*rnd(2)*rnd(2)*rnd(2)*rnd(2)* rnd(2)*rnd(2)*rnd(2)*rnd(2))*((double).67+ drand48()*(double)2/(double)3)/(double)2); global_weather->weatherlen += global_weather->timer; global_weather->sunny = True; global_weather->rain = 10000; return; } if( weather == WEATHER_CLOUDY ) { global_weather->sunny = False; global_weather->weatherlen = (int)((double)(rnd(4)*rnd(4)*rnd(4)*rnd(4)* rnd(4)*rnd(4)*rnd(4))*((double).8+drand48()* (double)2/(double)5)/(double)2); global_weather->weatherlen += global_weather->timer; start_weather( WEATHER_RAIN ); return; } if( weather == WEATHER_RAIN ) { int raintime; /* Duration of rainy spell */ global_weather->duration = 3+(int)(drand48()* (double)global_weather->weatherlen); /* Time before it starts to decline. */ global_weather->standby = 1+(int)((double)global_weather->duration* drand48()/(double)2); if( global_weather->duration - global_weather->standby == 1 ) global_weather->standby = 1; /* Length of the actual rain period */ raintime = global_weather->duration - global_weather->standby; /* The time that it takes to go from 10000 to bottom */ if( raintime == 2 ) global_weather->decline = 1; else global_weather->decline = rnd((raintime/2)); /* Time that the rain will stay at bottom */ steady = raintime - global_weather->decline - 1; global_weather->steady = rnd(steady); /* The hardest that it will rain during this spell */ if( global_weather->duration > 15 ) global_weather->bottom = rnd(10)*rnd(10)*rnd(100); else global_weather->bottom = 10000-rnd(8500); /* * Now the tricky part. Convert all of these values to "ticks" WHEN * they will happen instead of times. :) Also these times are when * the periods end instead of begin. */ global_weather->standby += global_weather->timer; global_weather->decline += global_weather->standby; global_weather->steady += global_weather->decline; global_weather->duration += global_weather->timer; return; } if( weather == WEATHER_HURRICANE ) { /* Not implemented yet */ mudlog( "Hurricane Started!!!" ); global_weather->last_hurricane = global_weather->timer; global_weather->windspeed = 100; return; } mudlog( "Unknown weather in start_weather %d!", weather ); return; } /* * Sends a message to everyone if the weather changes in their room */ void rainmsgs( int oldvalue ) { if( oldvalue == global_weather->rain ) return; send_g_msg( DEST_ALL, raintest_func, oldvalue, NULL ); return; } void windmsgs( int oldwind ) { if( wind2num( oldwind ) == wind2num( global_weather->windspeed ) ) return; send_g_msg( DEST_ALL, windtest_func, oldwind, NULL ); return; } char *windtest_func( int plr, int arg, char *msg ) { if( !ltstflg( ploc( plr ), LFL_OUTDOORS ) || ststflg( plr, SFL_NOWET ) || ststflg( plr, SFL_QUIET ) ) return NULL; return xrweatherwindmsgs[wind2num(arg)][wind2num(global_weather->windspeed)]; } char * raintest_func( int plr, int arg, char *msg ) { if( !ltstflg( ploc( plr ), LFL_OUTDOORS ) || ststflg( plr, SFL_NOWET ) || ststflg( plr, SFL_QUIET ) ) return NULL; return xrweatherstartmsgs[rain2num( plr, arg )][rain2num( plr, global_weather->rain )][((get_temp(ploc(plr)) < 40) ? 1 : 0)]; } /* * Function to convert actual rainfall values into a value used to access an * array. Returns a value from 0-7 depending on the rainfall of plr. */ int rain2num( int plr, int value ) { if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 2500 ) return 7; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 1000 ) return 6; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 500 ) return 5; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 300 ) return 4; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 120 ) return 3; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 30 ) return 2; else if( ( zrainfall( lzone(ploc(plr) ) ) - value ) > 0 ) return 1; else return 0; } int wind2num( int value ) { if( abs( value ) > 84 ) return 6; else if( abs( value ) > 59 ) return 5; else if( abs( value ) > 39 ) return 4; else if( abs( value ) > 24 ) return 3; else if( abs( value ) > 10 ) return 2; else if( abs( value ) > 0 ) return 1; else return 0; } #endif /* XR_WEATHER */