text: // natured.c
  
  #define TIME_TICK (time()*60)
  
  static int current_day_phase;
  mapping *day_phase;
  
  string *weather_msg = ({
  	"天空中万里无云",
  	"几朵淡淡的云彩妆点著清朗的天空",
  	"白云在天空中飘来飘去",
  	"厚厚的云层堆积在天边",
  	"天空中乌云密布",
  });
  
  mapping *read_table(string file);
  void init_day_phase();
  
  void create()
  {
  	day_phase = read_table("/adm/etc/nature/day_phase");
  	init_day_phase();
  }
  
  void init_day_phase()
  {
  	mixed *local;
  	int i, t;
  
  	// Get minutes of today.
  	local = localtime(TIME_TICK);
  	t = local[2] * 60 + local[1];		// hour * 60 + minutes
  
  	// Find the day phase for now.
  	for( i=0; i < sizeof(day_phase); i++)
  		if( t >= day_phase[i]["length"] )
  			t -= (int)day_phase[i]["length"];
  		else
  			break;
  
  	current_day_phase = (i==0? sizeof(day_phase)-1: i - 1);
  
  	// Since in our time scale, 1 minute == 1 second in RL, so we don't need
  	// any conversion before using this number as call_out dalay, if you 
  	// changed the time scale, be sure to convert it.
  
  	call_out("update_day_phase",
  		(int)day_phase[(current_day_phase+1) % sizeof(day_phase)]["length"] - t);
  }
  
  void update_day_phase()
  {
  	remove_call_out("update_day_phase");
  
  	current_day_phase = (++current_day_phase) % sizeof(day_phase);
  	message("outdoor:vision", day_phase[current_day_phase]["time_msg"] + "\n", users());
  	if( !undefinedp(day_phase[current_day_phase]["event_fun"]) )
  		call_other(this_object(), day_phase[current_day_phase]["event_fun"]);
  
  	call_out("update_day_phase", day_phase[current_day_phase]["length"]);
  }
  
  // This is called everyday noon by update_day_phase, defined in the
  // "event_fun" field in /adm/etc/nature/day_phase
  void event_noon()
  {
  	object *ob;
  	int i, skill;
  
  	ob = users();
  	for(i=0; i<sizeof(ob); i++) {
  		if( !environment(ob[i]) ) continue;
  		if( !environment(ob[i])->query("outdoors") ) continue;
  		if( !ob[i]->query("mana") ) continue;
  		if( !(skill = ob[i]->query_skill("spells", 1) )) {
  			tell_object(ob[i], "你觉得一阵晕眩，好像有一股能量从身上被人吸走了。\n");
  			ob[i]->set("mana", 0);
  			ob[i]->receive_damage("sen", 0);
  		} else if( skill < 25 ) {
  			tell_object(ob[i], "随著太阳升到天空的正中央，你觉得你的法力开始消失了。\n");
  			ob[i]->set("mana", (int)ob[i]->query("mana") * skill / 25 );
  		}
  	}
  }
  
  string outdoor_room_description()
  {
  	return "  " + day_phase[current_day_phase]["desc_msg"] + "。\n";
  }
  
  string game_time()
  {
  	return CHINESE_D->chinese_date(TIME_TICK);
  }
  
  // This function is to read a regular type of data table for day_phase and
  // etc.
  mapping *read_table(string file)
  {
  	string *line, *field, *format;
  	mapping *data;
  	int i, rn, fn;
  
  	line = explode(read_file(file), "\n");
  	data = ({});
  	for(i=0; i<sizeof(line); i++) {
  		if( line[i]=="" || line[i][0]=='#' ) continue;
  		if( !pointerp(field) ) {
  			field = explode( line[i], ":" );
  			continue;
  		}
  		if( !pointerp(format) ) {
  			format = explode( line[i], ":" );
  			continue;
  		}
  		break;
  	}
  
  	for( rn = 0, fn = 0; i<sizeof(line); i++) {
  		if( line[i]=="" || line[i][0]=='#' ) continue;
  		if( !fn ) data += ({ allocate_mapping(sizeof(field)) });
  		sscanf( line[i], format[fn], data[rn][field[fn]] );
  		fn = (++fn) % sizeof(field);
  		if( !fn ) ++rn;
  	}
  	return data;
  }
  
  
  mapping *query_day_phase() { return day_phase; }
  