ackmud/area/imc/
ackmud/npcs/a/
ackmud/npcs/c/
ackmud/npcs/d/
ackmud/npcs/e/
ackmud/npcs/f/
ackmud/npcs/h/
ackmud/npcs/i/
ackmud/npcs/k/
ackmud/npcs/l/
ackmud/npcs/n/
ackmud/npcs/o/
ackmud/npcs/p/
ackmud/npcs/r/
ackmud/npcs/s/
ackmud/npcs/w/
ackmud/player/c/
ackmud/player/z/
/* Scans vnums in area files and prints out those used in each file */

#define __USE_GNU

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct range_entry hash_entry;

struct range_entry {
              struct range_entry *next;
              int                 vnum;
              int                 offset; /* To begging of list or end*/
              };

#define MAX_HASH 2048              

hash_entry *hash_table[MAX_HASH];


hash_entry *get_hash_entry(int vnum)
{
 int a;
 hash_entry * rvalue;
 
 a=vnum % MAX_HASH;
 
 for (rvalue=hash_table[a]; rvalue != NULL; rvalue=rvalue->next)
  if (rvalue->vnum == vnum)
   break;
   
 return rvalue;
}
 
void add_hash_entry(hash_entry * entry)
{
 int a;

 a=entry->vnum % MAX_HASH;
 
 entry->next=hash_table[a];
 hash_table[a]=entry;
}

void del_hash_entry(hash_entry * entry)
{
 int a;
 hash_entry * prev_entry;
 hash_entry * search_entry;
 
 a=entry->vnum % MAX_HASH;
 
 prev_entry=NULL;
 for (search_entry=hash_table[a]; search_entry != NULL; search_entry = search_entry->next)
 {
  if (search_entry==entry)
   break;
  prev_entry=search_entry;
 }

 if (search_entry != NULL)
  if (prev_entry == NULL)
   hash_table[a]=NULL;
  else
   prev_entry->next=entry->next;
   
 free(entry);
}

void setup_hash_table(void)
{
 int a;

 for (a=0; a < MAX_HASH; a++)
  hash_table[a]=NULL;
  
} 
   
void clear_hash_table(void)
{
 int a;
 hash_entry * entry, * next_entry;
 
 for (a=0; a < MAX_HASH; a++)
 {
  if (hash_table[a] != NULL)
  {
   for (entry=hash_table[a]; entry != NULL; entry=next_entry)
   {
    next_entry=entry->next;
    free(entry);
   }
   hash_table[a]=NULL;
  }
 }
} 

#define ADD_BLOCK_SIZE 50

int getline(char ** buffer, int * size, FILE * file)
{
 char c;
 char * buf;
 char * curpos;
 int a,cursize;
 
 a=0;
 cursize=*size;
 buf=*buffer;
 curpos=buf;
 
 for ( ; ; )
 {
  c=getc(file);
  
  if (c=='\n')
   break;
  
  if (c=='\r')
   continue;
   
  a++;
  if (a==cursize)
  {
   cursize+=ADD_BLOCK_SIZE;
   buf=realloc(buf,cursize);
   curpos=buf+a;
  }
  
  *curpos++=c;
 }
 
 *curpos='\0';
 
 *buffer=buf;
 *size=cursize;
 return a;
}
 
void add_vnum(int vnum)
{
 hash_entry * entry;
 hash_entry * range, * temp;
 int start_vnum;
 int end_vnum;
 int cnt;

 /* Adds a vnum, adding to beggining or ends */
 
 start_vnum=vnum;
 end_vnum=vnum;
 
 for ( ; ; )
 {
  cnt=0;
 
  if ( (range=get_hash_entry(start_vnum-1)) != NULL)
  {
   if (range->offset > 0)
    printf("ERROR in ranges vnum: %i range start: %i range end: %i",
           start_vnum, range->vnum, range->vnum+range->offset);
   else
   {
    start_vnum=range->vnum+range->offset;
    if (   range->offset != 0
        && (temp=get_hash_entry(start_vnum)) != NULL)
       del_hash_entry(temp);
    del_hash_entry(range);
    cnt=1;
   }
  }
  
  if ( (range=get_hash_entry(end_vnum+1)) != NULL)
  {
   if (range->offset < 0)
    printf("ERROR in ranges vnum: %i range start: %i range end: %i",
           end_vnum, range->vnum+range->offset, range->vnum);
   else
   {
    end_vnum=range->vnum+range->offset;
    if (   range->offset != 0
        && (temp=get_hash_entry(start_vnum)) != NULL)
       del_hash_entry(temp);
    del_hash_entry(range);
    cnt=1;
   }
  }
  
  if (!cnt)
   break;
 }
           
 if (start_vnum == end_vnum)
 {
  entry=malloc(sizeof(hash_entry));
  entry->vnum=start_vnum;
  entry->offset=0;
  add_hash_entry(entry);
 }
 else
 {
  entry=malloc(sizeof(hash_entry));
  entry->vnum=start_vnum;
  entry->offset=end_vnum-start_vnum;
  add_hash_entry(entry);
  
  entry=malloc(sizeof(hash_entry));
  entry->vnum=end_vnum;
  entry->offset=start_vnum-end_vnum;
  add_hash_entry(entry);
 }
} 
 

#define BUF_SIZE 255
#define str_cmp(a,b) strcasecmp(a,b)
 

void collate_vnums(FILE * in_file,FILE * out_file,char * name,int offset)
{
 int vnum;
 char * line;
 int    line_size;
 int    min_vnum=65000;
 int    max_vnum=0,a;
 char   spaces[255];
 hash_entry * entry;
 
 line=malloc(BUF_SIZE);
 line_size=BUF_SIZE;
 
 for (a=0; a < offset; a++)
  spaces[a]=' ';
 spaces[a]='\0';
  
 
 for ( ; ; )
 {
   getline(&line, &line_size, in_file); 
         
   if (line[0] != '#')
    continue;
    
   vnum=atoi(line+1);
   
   if (vnum==0)
    break;
    
   if (vnum > max_vnum)
    max_vnum=vnum;
   
   if (vnum < min_vnum)
    min_vnum=vnum;
    
   add_vnum(vnum);
 }
 
 if (max_vnum != 0)
 {
  for (vnum=min_vnum; vnum <= max_vnum; vnum++)
  {
   if ( (entry=get_hash_entry(vnum)) != NULL
      && entry->offset>=0 )
      {
       fprintf(out_file,"%s",spaces);
       if ( entry->offset == 0 )
       {
        fprintf(out_file,"%5i           %s\n",entry->vnum,name);
        printf("     %i\n",entry->vnum);
       }        
       else    
       {
        fprintf(out_file,"%5i - %5i    %s\n",entry->vnum,entry->vnum+entry->offset,name);
        printf("     %i-%i\n",entry->vnum,entry->vnum+entry->offset);
       }
        
      }
  }
 }

 clear_hash_table();
 free(line);
}
 
int main()
{
   FILE * farea_lst;
   FILE * fcur_area;
   FILE * rooms_file,*mobs_file,*objs_file;
   char * sarea_buffer;
   char * sfile_line;
   int    sarea_buffer_size;
   int    sfile_line_size;
   
   sarea_buffer=malloc(BUF_SIZE);
   sfile_line=malloc(BUF_SIZE);
   sarea_buffer_size=BUF_SIZE;
   sfile_line_size=BUF_SIZE;
   
   setup_hash_table();
   farea_lst=fopen("area.lst","r");
   
   rooms_file=fopen("rooms.txt","w");
   mobs_file=fopen("mobs.txt","w");
   objs_file=fopen("objs.txt","w");
   
   for (getline(&sarea_buffer,&sarea_buffer_size,farea_lst);
        sarea_buffer[0] != '$' && !feof(farea_lst);
        getline(&sarea_buffer,&sarea_buffer_size,farea_lst) )
       {
        /* sarea_buffer contains next filename */
        printf("\nFile: %s\n",sarea_buffer);        
        fcur_area=fopen(sarea_buffer,"r");
        for ( ; ; )
        {
         getline(&sfile_line, &sfile_line_size, fcur_area);
         if ( !str_cmp(sfile_line, "#$") )
          break;
         
         if (sfile_line[0] != '#')
          continue;
          
         if ( !str_cmp(sfile_line, "#ROOMS") )
         {
          printf("Rooms:\n");
          collate_vnums(fcur_area,rooms_file,sarea_buffer,0);
         }
         
         if ( !str_cmp(sfile_line, "#OBJECTS") )
         {
          printf("Objects:\n");
          collate_vnums(fcur_area,objs_file,sarea_buffer,0);
         }
         
         if ( !str_cmp(sfile_line, "#MOBILES") )
         {
          printf("Mobiles:\n");
          collate_vnums(fcur_area,mobs_file,sarea_buffer,0);
         }
        }
        fclose(fcur_area);
       }
    fclose(farea_lst);
    
    fclose(rooms_file);
    fclose(objs_file);
    fclose(mobs_file);
    
    free(sarea_buffer);
    free(sfile_line);
    
    return 1;
 }