/*
 * Channel history! Very simple to plug into any Merc/Diku derived MUD using talk_channel() to pass all the info.
 * It could probably be more elegant, like storing the output directly from act(), but hey, it works :)
 * Thanks to Abel of StormHunters for the bv_log routine!
 *
 * Feel free to modify this code to suit your needs, and if you have a great improvement I wouldn't mind if you
 * shared it with me either, if you're so inclined :D. All I ask is to give me credit for the code if you do
 * choose to use it.
 *
 * --Kline (Matt Goff)
 */

STEP 1
  Add the following define in a .h someplace:
  #define MAX_HISTORY                 20   /* History per channel */

STEP 2
  In your main .h (merc.h, ack.h, etc) add the following with the other structs:
  struct chanhistory
  {
   time_t time[30][MAX_HISTORY];
   char message[30][MAX_HISTORY][MAX_STRING_LENGTH]; /* 30 channels, each with MAX_HISTORY, length of MSL */
  };

STEP 3
  Add the following whereever you keep your typedefs (typedefs.h in ack):
  typedef struct chanhistory CHAN_HISTORY;

STEP 4
  Add the following in some .c file (probably db.c with the other mud-wide structs):
  CHAN_HISTORY chan_history;

INFO
  My MUD uses bitvectors to toggle channels, if yours doesn't, skip directly to STEP 5 and remove
  references to bv_log. Just replace that with the int value of the channel, or whatever you use
  If you use bitvectors for channels, too, this will work as-is.

STEP 5
  Also add the following somewhere near all the db.c functions:
  int   bv_log           args( ( int n ) );

STEP 6
  In db.c, add the following to the bottom of the file:
  int bv_log( int n )
  {
   int result = 0;

   while( n > 0 )
   {
    n >>= 1;
    result++;
   }

   return result;
  }

STEP 7
  Find the talk_channel() function, probably in act_comm.c. Below the block if( argument[0] == '0' ) add:
  if( !str_cmp(argument,"history") )
  {
   sh_int x,y = 0;
   bool found = FALSE;

   x = (bv_log(channel)-1);

   for( y = 0; y < MAX_HISTORY; y++ )
    if( chan_history.message[x][y][0] != '\0' )
    {
     if( IS_IMMORTAL(ch) )
     {
      found = TRUE;
      sprintf(buf,"[%s",ctime(&chan_history.time[x][y]));
      buf[(strlen(buf)-1)] = '\0';           /* I realize how ugly this chunk looks but it was */
      strcat(buf,"] ");                         /* necessary to get around ctime adding a newline --Kline */
      strcat(buf,chan_history.message[x][y]);
      send_to_char(buf,ch);
     }
     else if( ch->logon <= chan_history.time[x][y] )
     {
      found = TRUE;
      send_to_char(chan_history.message[x][y],ch);
     }
    }

   if( !found )
    send_to_char("No history available for that channel yet.\n\r",ch);

   return;
  }

STEP 8
  At the bottom of talk_channel, right above the return;, add the following:
  {
   sh_int x,y = 0;

   x = (bv_log(channel)-1);

   for( y = 0; y < MAX_HISTORY; y++ )
   {
    if( chan_history.message[x][y] == '\0' )
    {
     sprintf(chan_history.message[x][y],"%s: %s@@N\n\r",IS_NPC(ch) ? ch->short_descr : ch->name,argument);
     chan_history.time[x][y] = current_time;
     break;
    }
    if( y == (MAX_HISTORY -1) )
    {
     int i = 0;

     for( i = 1; i < MAX_HISTORY; i++ )
     {
      sprintf(chan_history.message[x][(i-1)],chan_history.message[x][i]);
      chan_history.time[x][(i-1)] = chan_history.time[x][i];
     }

     chan_history.message[x][y][0] = '\0';
     chan_history.time[x][y] = 0;
     sprintf(chan_history.message[x][y],"%s: %s@@N\n\r",IS_NPC(ch) ? ch->short_descr : ch->name,argument);
     chan_history.time[x][y] = current_time;
    }
   }
  }


That's it! All done! You can adjust parameters as needed, and can view history per
channel by using '<channel> history'. Enjoy :) Suggestions for improvement are welcome!