cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
/************************************************************************
 *  timing.c : launch operations that happen each clock tick, and       *
 *  set open_state boolean to correct status, based on the "hours"      *
 *  file which governs the operational hours of the mud                 *
 ***********************************************************************/

#include <sys/signal.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>

#include "kernel.h"
#include "mobile.h"
#include "climate.h"
#include "move.h"
#include "timing.h"
#include "bprintf.h"
#include "sendsys.h"
#include "log.h"
#include "fight.h"
#include "mud.h"
#include "locations.h"
#include "objects.h"
#include "idlookup.h"
#include "client.h"
#include "wizard.h"

#define  SECS_IN_A_MIN          60
#define  SECS_IN_AN_HOUR        (SECS_IN_A_MIN*60)
#define  SECS_IN_A_DAY          (SECS_IN_AN_HOUR*24)
#define  SECS_IN_A_WEEK         (SECS_IN_A_DAY*7)

extern void storeplayers(void);

#ifdef _NETBSD_
  extern const char *sys_errlist[];
#elseif _OLD_LINUX_
  extern char *sys_errlist[];
#endif

#ifdef IO_STATS
  extern int bytes_read;
  extern int bytes_sent;
  extern int sock_conns;
  extern int cut_conns;
  extern int unres_hosts;
#endif

extern int aberfd;
extern int dnsfd;
extern Boolean auto_restart;

char *time2ascii (time_t t) {
  static char timestr[30];

  if (t == 0)
    t = global_clock;

  strcpy(timestr, ctime(&t));
  *strchr(timestr, '\n') = 0;

  return(timestr);
}

/* The TIME command. List game time elapsed, current time, last reset
 */

void timecom (void) {
  bprintf ("Elapsed Time : ");
  eltime ();

  bprintf ("Current Time : %s\n", time2ascii (TIME_CURRENT));

  bprintf ("Last Reset   : %s", ctime (&last_reset));
}

void uptimecom (void) {
  bprintf ("Elapsed Time             : %s\n", sec_to_str (global_clock-last_startup));
  bprintf ("Been Up Since            : %s", ctime (&last_startup));
  bprintf ("AberChat Status          : %s\n", 
    (aberfd != -1) ? "Operational": "Down");
#ifdef IO_STATS 
  if (plev(mynum) > LVL_WIZARD) {
    bprintf ("Unresolved hosts         : %d [DNS Server: %s]\n",
      unres_hosts, dnsfd != -1 ? "Operational" : "Down");
    bprintf ("Bytes [in/out]           : %d / %d\n", bytes_read, bytes_sent);
    bprintf ("Connects [cut/total]     : %d / %d\n", cut_conns, sock_conns);
  }
#endif
  bprintf ("Number of Resets         : %d\n", numresets);
  bprintf ("Number of Reboots        : %d\n", numreboots);
  bprintf ("Recovered Crashes        : %d\n", numcrashes);
}

/* Prints the game time elapsed */

void eltime (void) {
  long int et = global_clock - last_reset;

  if (et > SECS_IN_A_DAY)
    bprintf ("&+WOver a day!");
  else
    bprintf ("&+W%s", sec_to_str (et));
  bprintf ("\n");
}


/*  Takes a number of seconds as input and converts this to seconds,
 *  minutes, hours, days, which is returned if the pointers != NULL.
 */
static void split_time (long int sec, int *secs, int *min, int *hrs, int *days)
{
  int s = 0, m = 0, h = 0, d = 0;

  if (sec >= SECS_IN_A_DAY) {
    d = sec / SECS_IN_A_DAY;

    sec -= d * SECS_IN_A_DAY;
  }
  if (sec >= SECS_IN_AN_HOUR) {
    h = sec / SECS_IN_AN_HOUR;

    sec -= h * SECS_IN_AN_HOUR;
  }
  if (sec >= SECS_IN_A_MIN) {
    m = sec / SECS_IN_A_MIN;

    sec -= m * SECS_IN_A_MIN;
  }
  s = sec;

  /* Assign return values:
   */
  if (secs != NULL)
    *secs = s;
  if (min != NULL)
    *min = m;
  if (hrs != NULL)
    *hrs = h;
  if (days != NULL)
    *days = d;
}


/*  Takes a number of seconds as input and returns a pointer to a string
 *  containing the amount of time in english, ex: "2 hours, 3 minutes"..etc..
 */
char *sec_to_str (long int seconds) {
  static char str[50];
  int sec, min, hrs, days;
  char aux[15];

  *str = '\0';

  split_time (seconds, &sec, &min, &hrs, &days);

  if (days > 0) {
    sprintf (str, "%d day%s", days, (days == 1) ? "" : "s");
  }
  if (hrs > 0) {
    if (days > 0)
      strcat (str, ", ");
    sprintf (aux, "%d hour%s", hrs, (hrs == 1) ? "" : "s");
    strcat (str, aux);
  }
  if (min > 0) {
    if (days > 0 || hrs > 0)
      strcat (str, ", ");
    sprintf (aux, "%d minute%s", min, (min == 1) ? "" : "s");
    strcat (str, aux);
  }
  if (sec > 0) {
    if (days > 0 || hrs > 0 || min > 0)
      strcat (str, ", ");
    sprintf (aux, "%d second%s", sec, (sec == 1) ? "" : "s");
    strcat (str, aux);
  }
  return (str);
}


/*  Takes a number of seconds as input and returns a pointer to a string
 *  containing hh:mm:ss.
 */
char *sec_to_hhmmss (long int seconds) {
  static char str[25];

  int sec, min, hrs, days;

  split_time (seconds, &sec, &min, &hrs, &days);

  if (days > 0) {
    hrs += days * 24;
  }
  sprintf (str, "%02d:%02d:%02d", hrs, min, sec);

  return (str);
}


/* Returns time t rounded to the nearest minute.
 */
time_t round_to_min (time_t t) {
  t += SECS_IN_A_MIN / 2;

  return (t -= t % SECS_IN_A_MIN);
}


/* Like ctime(3) but strips the seconds, year-part and the \n.
 */
char *my_ctime (time_t * clock) {
  char *t = ctime (clock);

  t[16] = '\0';
  return t;
}

void on_timer (void) {
  static long int n = 0;
  static const int interupts_per_hour = 3600 / TIMER_INTERRUPT;
  int plx;

  setup_globals(-1);

  fflush(logptr);
  fflush(clogptr);

#ifdef ABERCHAT
  if (auto_restart && aberfd == -1 && !(n % 150))
    aberchat_autorecon();
#endif

  if (++n % interupts_per_hour != 0 || time (&global_clock) == -1)
    global_clock += TIMER_INTERRUPT;

  loop_all_players ();
  regenerate ();
  special_events (SP_ALL);
  update_weather();

 #ifdef SAVE_HTML
  if (!(n % 30))                          /* store players html every min */
    storeplayers();
 #endif

  for (plx = 0; plx < max_players; plx++) {
    if (is_in_game(plx))
      do_ingame(plx);
    else if (is_conn(plx)) {
      if ((global_clock - logged_on(plx)) > RES_TM && limbo(plx))
        enter_game(plx);
      else if ((global_clock - logged_on(plx)) > CONNECT_TM)
        close_sock(fildes(plx));
    }
  }
}

void do_ingame(int plx) {
  setup_globals (plx);
  handle_duration (plx);
  cur_player->cast_spell = False;
  if (False);
#ifdef LOCMIN_VILLAGE
  else if (ploc(mynum) == LOC_VILLAGE_EMERGENCY && 
      prndsinroom(mynum) >= cur_player->work)
    exit_hospital();
#endif
  else if (cur_player->crawl > 10)
    cur_player->crawl -= 10;
  else if (linkdead(real_mynum) && global_clock - prlast_cmd(mynum) > LD_TM)
    auto_tout();
  else if (global_clock - prlast_cmd(real_mynum) > IDLE_TM)
    auto_tout();
  else if (cur_player->crawl > 0) {
    dodirn(False, cur_player->crawl);
    cur_player->crawl = 0;
  }
}