/* ************************************************************************ * File: weather.c EmpireMUD AD 1.0 * * Usage: functions handling time and the weather * * * * All rights reserved. See license.doc for complete information. * * * * Code base by Paul Clarke. EmpireMUD Project, a tbgMUD Production. * * Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson. * * * * 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 "interpreter.h" #include "db.h" extern struct time_info_data time_info; void weather_and_time(int mode) { void another_hour(int mode); void weather_change(); void save_exp_cycle(); extern int exp_cycle; extern time_t last_exp_cycle; char *tmstr; time_t ct; /* Check to see if it's a new real day */ /* Get the current time into buf */ ct = time(0); tmstr = (char *) asctime(localtime(&ct)); *(tmstr + strlen(tmstr) - 1) = '\0'; sprintf(buf, "%6.10s", tmstr); /* Get the last exp cycle update into buf1 */ ct = last_exp_cycle; tmstr = (char *) asctime(localtime(&ct)); *(tmstr + strlen(tmstr) - 1) = '\0'; sprintf(buf1, "%6.10s", tmstr); if (str_cmp(buf, buf1)) { exp_cycle++; last_exp_cycle = time(0); save_exp_cycle(); } another_hour(mode); if (mode) weather_change(); } void another_hour(int mode) { void perform_noon_update(void); Descr d; room_rnum r; time_info.hours++; if (mode) { switch (time_info.hours) { case 7: weather_info.sunlight = SUN_RISE; for (d = descriptor_list; d; d = d->next) if (STATE(d) == CON_PLAYING && !HAS_INFRA(d->character) && !PRF_FLAGGED(d->character, PRF_HOLYLIGHT) && AWAKE(d->character) && IS_OUTDOORS(d->character) && !IS_WRITING(d->character)) { look_at_room(d->character); msg_to_char(d->character, "\r\n"); } send_to_outdoor("The sun rises in the east.\r\n"); break; case 8: weather_info.sunlight = SUN_LIGHT; send_to_outdoor("The day has begun.\r\n"); break; case 12: /* Noon: Heal mortals, take blood from vampires */ perform_noon_update(); break; case 19: weather_info.sunlight = SUN_SET; send_to_outdoor("The sun slowly disappears in the west.\r\n"); break; case 20: weather_info.sunlight = SUN_DARK; for (d = descriptor_list; d; d = d->next) if (STATE(d) == CON_PLAYING && !HAS_INFRA(d->character) && !PRF_FLAGGED(d->character, PRF_HOLYLIGHT) && AWAKE(d->character) && IS_OUTDOORS(d->character) && !IS_WRITING(d->character)) { look_at_room(d->character); msg_to_char(d->character, "\r\n"); } send_to_outdoor("The night has begun.\r\n"); break; } } if (time_info.hours > 23) { /* Changed by HHS due to bug ??? */ time_info.hours -= 24; time_info.day++; if (time_info.day > 29) { time_info.day = 0; time_info.month++; if (time_info.month > 11) { time_info.month = 0; time_info.year++; /* For fun, we'll refill all the mines now (with random metal. */ /* This ONLY happens if the mud is up when it adds a year... */ for (r = 0; r <= top_of_world; r++) if (SECT(r) == SECT_MOUNTAIN) { world[r].spare = 0; world[r].type2 = 0; } } } } } void weather_change(void) { int diff, change; if ((time_info.month >= 4) && (time_info.month <= 8)) diff = (weather_info.pressure > 985 ? -2 : 2); else diff = (weather_info.pressure > 1015 ? -2 : 2); weather_info.change += (dice(1, 4) * diff + dice(2, 6) - dice(2, 6)); weather_info.change = MIN(weather_info.change, 12); weather_info.change = MAX(weather_info.change, -12); weather_info.pressure += weather_info.change; weather_info.pressure = MIN(weather_info.pressure, 1040); weather_info.pressure = MAX(weather_info.pressure, 960); change = 0; switch (weather_info.sky) { case SKY_CLOUDLESS: if (weather_info.pressure < 990) change = 1; else if (weather_info.pressure < 1010) if (!dice(0, 3)) change = 1; break; case SKY_CLOUDY: if (weather_info.pressure < 970) change = 2; else if (weather_info.pressure < 990) { if (!dice(0, 3)) change = 2; else change = 0; } else if (weather_info.pressure > 1030) if (!dice(0, 3)) change = 3; break; case SKY_RAINING: if (weather_info.pressure < 970) { if (!dice(0, 3)) change = 4; else change = 0; } else if (weather_info.pressure > 1030) change = 5; else if (weather_info.pressure > 1010) if (!dice(0, 3)) change = 5; break; case SKY_LIGHTNING: if (weather_info.pressure > 1010) change = 6; else if (weather_info.pressure > 990) if (!dice(0, 3)) change = 6; break; default: change = 0; weather_info.sky = SKY_CLOUDLESS; break; } switch (change) { case 1: send_to_outdoor("The sky starts to get cloudy.\r\n"); weather_info.sky = SKY_CLOUDY; break; case 2: send_to_outdoor("It starts to rain.\r\n"); weather_info.sky = SKY_RAINING; break; case 3: send_to_outdoor("The clouds disappear.\r\n"); weather_info.sky = SKY_CLOUDLESS; break; case 4: send_to_outdoor("Lightning starts to show in the sky.\r\n"); weather_info.sky = SKY_LIGHTNING; break; case 5: send_to_outdoor("The rain stops.\r\n"); weather_info.sky = SKY_CLOUDY; break; case 6: send_to_outdoor("The lightning stops.\r\n"); weather_info.sky = SKY_RAINING; break; } } /* * Season code * by Paul S. Clarke, 12/1/2001 */ int get_season(void) { int day = time_info.month * 30 + time_info.day + 1; /* this takes a month number 1-12 + a day in the month (1-30) and plots it vs day*/ #define Month_Day(m, d) ((m - 1) * 30 + d) if (day >= Month_Day(3, 21) && day < Month_Day(6, 21)) return SEASON_SPRING; else if (day >= Month_Day(6, 21) && day < Month_Day(9, 22)) return SEASON_SUMMER; else if (day >= Month_Day(9, 22) && day < Month_Day(12, 21)) return SEASON_AUTUMN; return SEASON_WINTER; } /* * Empire Moons 1.0 * by Paul Clarke, 10/19/2k * * To add a moon: increase NUM_OF_MOONS by 1 and add a line in moons[] * to correspond with your new moon. Reboot and it's all done for you. */ #define NUM_OF_MOONS 1 #define PHASE_NEW 0 /* */ #define PHASE_WAXING 1 /* */ #define PHASE_FIRST_QUARTER 2 /* Phases of the moon */ #define PHASE_FULL 3 /* */ #define PHASE_LAST_QUARTER 4 /* */ #define PHASE_WANING 5 /* */ struct moon_data { char *name; byte cycle; /* Days between full moons */ } moons[NUM_OF_MOONS] = { { "Moon", 28 } }; /* Retrieve the current phase of a specific moon */ byte get_phase(int M) { int total_time = time_info.day; int diff; total_time += time_info.month * 30; /* 30 days in a month */ total_time += time_info.year * 12 * 30; /* 12 months in a year */ total_time %= moons[M].cycle; diff = 100 * total_time / moons[M].cycle; /* diff is a percentage of the rotation */ if (diff <= 2 || diff >= 98) return PHASE_NEW; if (diff >= 23 && diff <= 27) return PHASE_FIRST_QUARTER; if (diff >= 73 && diff <= 77) return PHASE_LAST_QUARTER; if (diff >= 48 && diff <= 52) return PHASE_FULL; if (diff < 50) return PHASE_WAXING; else return PHASE_WANING; } void list_moons_to_char(Creature ch) { int M, i; char moon_str[112]; if (NUM_OF_MOONS == 0) return; *buf = '\0'; for (M = 0; M < NUM_OF_MOONS; M++) { *moon_str = '\0'; switch(get_phase(M)) { case PHASE_WAXING: sprintf(moon_str, "waxing"); break; case PHASE_FIRST_QUARTER: sprintf(moon_str, "in its first quarter"); break; case PHASE_FULL: sprintf(moon_str, "full"); break; case PHASE_LAST_QUARTER: sprintf(moon_str, "in its last quarter"); break; case PHASE_WANING: sprintf(moon_str, "waning"); break; } if (*buf) strcat(buf, ", "); if (*moon_str) sprintf(buf+strlen(buf), "%s is %s", moons[M].name, moon_str); } if (!*buf) sprintf(buf, "You can't see the moon%s right now", NUM_OF_MOONS > 1 ? "s" : ""); strcat(buf, ".\r\n"); /* This will find the last comma and replace it with an "and" */ for (i = strlen(buf)-1; i > 0; i--) if (buf[i] == ',') { sprintf(buf1, buf + i+1); buf[i] = '\0'; strcat(buf, " and"); strcat(buf, buf1); break; } msg_to_char(ch, buf); } byte distance_can_see(Creature ch) { int M, p, a = 0, b = 0, c = 0; for (M = 0; M < NUM_OF_MOONS; M++) { switch (get_phase(M)) { case PHASE_FULL: c = 4; break; case PHASE_FIRST_QUARTER: case PHASE_LAST_QUARTER: c = 3; break; case PHASE_WAXING: case PHASE_WANING: c = 2; break; default: c = 1; break; } if (c > a) a = c; else if (c > b) b = c; } p = a + b; p = MIN(5, p); if (DSC_FLAGGED(ch, DSC_WITNESS_OF_DARKNESS)) p *= 4; else if (DSC_FLAGGED(ch, DSC_HEIGHTENED_SENSES)) p *= 2; if (IS_LIGHT(ch->in_room)) p++; return p; }