tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
#pragma save_binary
// Weather daemon
// Originally coded by Megadeath@TMI-2
// Overhauled by Mobydick@TMI-2
// Fixed type checking for which_line Leto 94-11-10

#include <mudlib.h>
#include <weather_d.h>

inherit DAEMON ;

// A list of all objects which get the weather change messages. All outdoor
// rooms are placed on this list, but other objects such as monsters can
// be placed on it (so you can code vampires and so on.)

object *notifications ;

// These variables store the current game time. The length of game days,
// months, and years is all controlled by defines in weather_d.h.

int current_day, current_month, current_year ;

// This variable stores the data on the day phases.

mapping *day_phases ;
int num_phases ;
int current_phase ;

// And these on the weather states.

mapping *weather_states ;
int num_states ;
int current_state ;

// And these on the months.

mapping *months ;
int num_months ;

// And _these_ on the moon phases :)

mapping *moon_phases ;
int num_moon_phases ;
int moon_phase_days ;
int current_moon_phase ;


// This function reads in the data on the daytime phases.

void read_day_phases() {

	int i, data, size ;
	string str ;
	string *datafile ;
	int which_line ;
	mapping new_phase ;

// Which_line keeps track of where in the file format we are.
	which_line = 0 ;
	datafile = explode(read_file(DAY_PHASE_FILE),"\n") ;
	size = sizeof(datafile) ;
	day_phases = allocate(NUM_DAY_PHASES) ;
	num_phases = -1 ;      // sorry.... this is silly but easiest.
// Loop through each line of the file and try to parse it appropriately.
	for (i=0;i<size;i++) {
// Make sure that this line is a proper data line: if not, skip it.
	    if (sscanf(datafile[i],"%d %s",data,str)==2) {
		if (which_line) {
// We're looking at the second of the two lines in this case.
			day_phases[num_phases]["change_msg"] = str ;
			day_phases[num_phases]["daylight"] = data ;
		} else {
// In this case, the first of the two lines.
			num_phases = num_phases + 1 ;
			day_phases[num_phases] = allocate_mapping(4) ;
			day_phases[num_phases]["length"] = data ;
			day_phases[num_phases]["look_msg"] = str ;
		}
		which_line = !which_line ;
	   }
	}
	if (which_line) {
		shout ("Incomplete last day phase.\n") ;
	}
	num_phases = NUM_DAY_PHASES ;
	return ; 
}

// This function reads in the weather data.

void read_weather() {

	int i, j, data1, data2, size ;
	string *changes ;
        string *datafile ;
        int which_line ;

// Which line keeps track of where we are in the file format.
	which_line = 0 ;
        datafile = explode(read_file(WEATHER_FILE),"\n") ;
        size = sizeof(datafile) ;
	weather_states = allocate(NUM_WEATHER) ;
	changes = allocate(NUM_WEATHER) ;
	num_states = -1 ;   // hack :(
// Loop through each line of the file, and parse it.
	for (i=0;i<size;i++) {
	    switch(which_line) {
// How we parse it depends on what line we are expecting.
		case 0 : {
		    if (sscanf(datafile[i],"%d %d",data1,data2)==2) {
			num_states = num_states+1 ;
			weather_states[num_states]=allocate_mapping(6) ;
			weather_states[num_states]["length"] = data1 ;
			weather_states[num_states]["inclement"] = data2 ;
			which_line = 1 ;
		    }
		    break ;
 		}
		case 1 : {
		    changes = explode(datafile[i]," ") ;
		    weather_states[num_states]["changes"] = 
					allocate(NUM_WEATHER) ;
		    for (j=0;j<sizeof(changes);j++) {
			sscanf(changes[j],"%d",weather_states[num_states]
					["changes"][j]) ;
		    }
		    which_line=2 ;
		    break ;
		}
		case 2 : {
		    weather_states[num_states]["worse_msg"] = datafile[i] ;
		    which_line=3 ;
		    break ;
		}
		case 3 : {
                    weather_states[num_states]["better_msg"] = datafile[i] ;
                    which_line=4 ;
                    break ;
                }
		case 4 : {
                    weather_states[num_states]["look_msg"] = datafile[i] ;
                    which_line=0 ;
                    break ;
                }
	    }
        }
	num_states = NUM_WEATHER ;
	return ;
}

// This function reads in the months and their names.

void read_months() {

	int i, ding ;
	string str ;
	string *datafile ;

	datafile = explode(read_file(MONTH_FILE),"\n") ;
	months = allocate(NUM_MONTHS) ;
	num_months = -1 ;    // same hack as always.
	for (i=0;i<sizeof(datafile);i++) {
	    if (sscanf(datafile[i],"%s %d",str,ding)==2) {
		num_months = num_months + 1 ;
		months[num_months]=allocate_mapping(2) ;
		months[num_months]["length"] = ding ;
		months[num_months]["name"] = str ;
	    }
	}
	num_months = NUM_MONTHS ;
	return ;
}

// This function reads in the data on the moon phases.

void read_moon() {

        int i, ding ;
        string str ;
        string *datafile ;

        datafile = explode(read_file(MOON_FILE),"\n") ;
        moon_phases = allocate(NUM_MOON_PHASES) ;
        num_moon_phases = -1 ;    // same hack as always.
        for (i=0;i<sizeof(datafile);i++) {
	    if (sscanf(datafile[i],"%d %s",ding,str)==2) {
                num_moon_phases = num_moon_phases + 1 ;
                moon_phases[num_moon_phases]=allocate_mapping(2) ;
                moon_phases[num_moon_phases]["length"] = ding ;
                moon_phases[num_moon_phases]["look_msg"] = str ;
            }
        }
	num_moon_phases = NUM_MOON_PHASES ;
}

// This function is called at the end of each day to advance the calendar
// and the moon phase. You can do other things as well.

void do_day_end() {
	current_day=current_day+1 ;
	if (current_day>months[current_month]["length"]) {
		current_day=1 ;
		current_month = current_month+1 ;
		if (current_month==num_months) {
			current_month=0 ;
			current_year = current_year + 1 ;
		}
	}
	moon_phase_days = moon_phase_days + 1 ;
	if (moon_phase_days==moon_phases[current_moon_phase]["length"]) {
		moon_phase_days=0 ;
		current_moon_phase = current_moon_phase + 1 ;
		if (current_moon_phase==num_moon_phases) {
			current_moon_phase = 0 ;
		}
	}
}

// This function changes us from one state of day to the next. It call_outs
// to itself recursively so there's always one version in the call_out
// queue.

void change_phase() {

	notifications -= ({ 0 });
	message("weather",day_phases[current_phase]["change_msg"]+"\n",
		notifications) ;
	current_phase = current_phase + 1 ;
	if (current_phase==num_phases) {
		current_phase=0 ;
		do_day_end() ;
	}
	call_out("change_phase",day_phases[current_phase]["length"]) ;
}

// This function changes the weather. Based on the current weather
// state, it picks a new weather state and call_outs itself, so that there
// is always one version of the function in the call_out queue. If the new
// state is the same as the old one, then nothing else is done, otherwise
// we notify each object of the new state.

void change_weather() {

	int i, j, new_state ;

	notifications -= ({ 0 });
	j = random(100) ;
	for (i=0;i<sizeof(weather_states[current_state]["changes"]);i++) {
	    if (j<weather_states[current_state]["changes"][i]) {
		new_state = i ;
		j=200 ;		// This way we don't select again.
	    } else {
		j = j - weather_states[current_state]["changes"][i] ;
	    }
	}
	call_out("change_weather",weather_states[new_state]["length"]) ;
	if (new_state==current_state) return ;
	i=sizeof(notifications);
	while (i--) {
	    if (new_state<current_state) {
		message("weather",weather_states[new_state]["better_msg"]+"\n",
				notifications[i]) ;
	    } else {
		message("weather",weather_states[new_state]["worse_msg"]+"\n",
				notifications[i]) ;
	    }
	}
	current_state = new_state ;
}

// This function is called at create time. It gets the current time,
// and it sets the game time appropriately. We could just calculate the
// game times as needed, but that would be slower. Best to calculate it from
// real time once, then update it occasionally.

void init_game_time() {

	int current_time ;

	current_time = time() - START_GAME_TIME ;
	current_year = START_YEAR ;
// First, figure out what year it is.
	while (current_time>YEAR_LENGTH) {
		current_time = current_time - YEAR_LENGTH ;
		current_year = current_year + 1 ;
	}
// Next, what month.
	current_month = START_MONTH ;
	while (current_time>months[current_month]["length"]*DAY_LENGTH) {
		current_time = current_time - months[current_month]["length"] *
							DAY_LENGTH ;
		current_month = current_month + 1 ;
		if (current_month==num_months) {
			current_month=0 ;
			current_year = current_year + 1 ;
		}
	}
// Now, the current day is just the remaining time mod the day length,
// plus one since there is no day 0.
	current_day = current_time/DAY_LENGTH + 1 ;
// Now, we have to figure out what the current day phase is, and start
// the day phase call_outs with the right time remaining.
	current_time = current_time - (current_day-1)*DAY_LENGTH ;
	current_phase=0 ;
	while (current_time>day_phases[current_phase]["length"]) {
		current_time = current_time -
				day_phases[current_phase]["length"] ;
		current_phase = current_phase+1 ;
	}
	call_out("change_phase",day_phases[current_phase]["length"] -
				current_time) ;
// Now, we have to figure out the right phase of the moon and the number
// of days into that phase that we are.
	current_time = time() - START_GAME_TIME ;
	current_time = current_time % (MOON_PERIOD*DAY_LENGTH) ;
	moon_phase_days = current_time/DAY_LENGTH ;
	current_moon_phase = 0 ;
	while (moon_phase_days>moon_phases[current_moon_phase]["length"]) {
		moon_phase_days = moon_phase_days - 
				moon_phases[current_moon_phase]["length"] ;
		current_moon_phase = current_moon_phase + 1 ;
	}
}

void create() {
	seteuid(getuid()) ;
// Read in the day phases file.
	read_day_phases() ;
// Read in the weather data file
	read_weather() ;
// Read in the month data.
	read_months() ;
// Read in the moon data.
	read_moon() ;
// Initialize current date.
	init_game_time() ;
	notifications = ({ }) ;
	current_state = 0 ;
	change_weather() ;
}

// This function checks if there is outside light or not. The rule is,
// in daytime there is always light. At nighttime, there is light if
// the sky is clear, otherwise there is not light.

int query_ambient_light() {
	if ( day_phases[current_phase]["daylight"]) {
		return 1 ;
	} else {
		return !weather_states[current_state]["inclement"] ;
	}
}

// Returns the message associated with this time of day.

string query_current_day_phase() {
	return day_phases[current_phase]["look_msg"]+"\n" ;
}

// Returns the message associated with this weather state.
// Usually you want to use the query_weather_msg instead, which makes
// sure you can see the sun and the like.

string query_current_weather() {
	return weather_states[current_state]["look_msg"]+"\n" ;
}

// This function returns a string describing the current moon phase.

string query_current_moon_phase() {
	return moon_phases[current_moon_phase]["look_msg"]+"\n" ;
}


// This function returns a string describing the current weather. If the
// weather is not inclement, it tells you where the sun/moon is, otherwise
// it doesn't, and it describes the current weather also.

string query_weather_msg() {

	string str ;

	str = "" ;
	if (!weather_states[current_state]["inclement"]) {
		str += day_phases[current_phase]["look_msg"] +"\n" ;
	}
	str += weather_states[current_state]["look_msg"] +"\n" ;
	if(!day_phases[current_phase]["daylight"] &&
		!weather_states[current_state]["inclement"]) {
		str += moon_phases[current_moon_phase]["look_msg"]+"\n" ;
	}
	return str ;
}

string query_game_time() {

	int i,j,k ;

	i = time() - START_GAME_TIME ;
	i = i - (current_year-START_YEAR)*YEAR_LENGTH ;
	j = START_MONTH ;
	while (i>months[j]["length"]*DAY_LENGTH) {
		i = i - months[j]["length"]*DAY_LENGTH ;
		j = j + 1 ;
		if (j==num_months) j=0 ;
	}
	i = i - (current_day-1)*DAY_LENGTH ;
	i = i * 86400 / DAY_LENGTH ;
	j = i / 3600 ;
	k = i - j*3600 ;
	k = k / 60 ;
	if (k<10) return j+":0"+k+", "+months[current_month]["name"]+
			" "+current_day+", "+current_year ;
	return j+":"+k+", "+months[current_month]["name"]+
			" "+current_day+", "+current_year ;
}


// This function adds the object passed to the list of objects that
// will receive time and weather notices. Call this in any object that
// wants them. Outside rooms automatically add themselves to this list.
// Other objects like vampires can recieve_message() and take any actions
// they might want to.

void request_weather_notices (object ob) {
    if (member_array(ob,notifications)>-1) return ;
	notifications += ({ ob }) ;
}

// This function requests that an object be taken off the list
// of notified objects.

void cease_weather_notices (object ob) {
	notifications -= ({ ob }) ;
}

// Diagnostics.

void write_obs() {
	write(dump_variable(notifications)) ;
}