atd/area/
atd/build/
atd/clans/
atd/log/
atd/player/store/
atd/site/
atd/src/bin/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "merc.h"
#include "build.h"

typedef struct arti_type ARTI_TYPE;

sh_int  top_artis;

struct arti_type
{
    ARTI_TYPE *next;
    AREA_DATA *pArea;
    OBJ_INDEX_DATA *pObjIndex;

    char * short_descr;
    char * name;
    char * player_name;
    sh_int vnum;
};

ARTI_TYPE  * artifact_list;


#if defined(KEY)
#undef KEY
#endif

#define KEY( literal, field, value )                \
				if ( !str_cmp( word, literal ) )	\
                {                                   \
                    field  = value;                 \
                    fMatch = TRUE;                  \
                    break;                          \
				}

#ifdef SKEY
#undef SKEY
#endif

#define SKEY( string, field )                       \
    if ( !str_cmp( word, string ) )     \
    {                                   \
      free_string( field );           \
      field = fread_string( fp );     \
      fMatch = TRUE;                  \
      break;                          \
    }

void write_artifacts  args ( ( void ) );

/*
 * Scans the artifact_list and see's if any of the vnums match
 * Returns true if it does, otherwise FALSE
 */
bool is_artifact( OBJ_INDEX_DATA *pObj )
{
    ARTI_TYPE * arti;

    for( arti = artifact_list; arti; arti = arti->next )
    {
        if( arti->vnum == pObj->vnum )
            return TRUE;
    }

    return FALSE;
}


/*
 * Replace the right artifact with the specified description
 * and player name
 */
void fix_artifact( OBJ_INDEX_DATA *pObj )
{
    ARTI_TYPE * arti;

    for( arti = artifact_list; arti; arti = arti->next )
    {
        if( arti->vnum == pObj->vnum )
        {
            free_string( arti->player_name );
            arti->player_name = str_dup( "(not found)" );
            return;
        }
    }
    bugf( "fix_artifact: not found %s (%d)",
          pObj->short_descr, pObj->vnum );
    return;
}

void fix_artifact_pfile( OBJ_DATA *pObj, char * name, bool write )
{
    ARTI_TYPE * arti;

    for( arti = artifact_list; arti; arti = arti->next )
    {
        if( arti->vnum == pObj->pIndexData->vnum )
        {
            free_string( arti->player_name );
            free_string( arti->short_descr );
            free_string( arti->name );

            arti->player_name = str_dup( name );
            arti->short_descr = str_dup( pObj->short_descr );
            arti->name        = str_dup( pObj->name );
	    if( write )
		write_artifacts( );
            return;
        }
    }

    bugf( "Invalid artifact %s (%d)",
          pObj->short_descr, pObj->pIndexData->vnum );
    return;
}

void write_artifacts(  )
{
    ARTI_TYPE * arti;
    FILE      * fp;

    if( !(fp = fopen( DATA_DIR ARTI_FILE, "w" ) ) )
    {
        perror( DATA_DIR ARTI_FILE );
        return;
    }

    fprintf( fp, "* This file contains a fairly updated list of artifacts\n" );
    fprintf( fp, "* And who has them through the game\n" );
    fprintf( fp, "*\n" );

    for( arti = artifact_list; arti; arti = arti->next )
    {
        fprintf( fp, "#ARTI\n" );
        fprintf( fp, "V %d\n", arti->vnum );
        fprintf( fp, "N %s~\n", strip_cr( arti->name) );
        fprintf( fp, "S %s~\n", strip_cr( arti->short_descr) );
        fprintf( fp, "P %s~\n", strip_cr( arti->player_name) );
        fprintf( fp, "End\n\n" );
    }

    fprintf( fp, "#END\n" );
    fclose( fp );
    return;
}


void fread_artifact ( FILE *fp )
{
    char * name;
    char * player_name;
    char * short_descr;
    char * word;
    int    vnum;

    bool fMatch;

    vnum = 0;
    
    name        = &str_empty[0];
    player_name = &str_empty[0];
    short_descr = &str_empty[0];

    for( ; ; )
    {
        word = feof( fp ) ? "End" : fread_word( fp );

        fMatch = FALSE;

        switch ( UPPER(word[0]) )
        {
        case '*':
            fMatch = TRUE;
            fread_to_eol( fp );
            break;
        case 'N':
            SKEY( "N", name                    );
            break;
        case 'P':
            SKEY( "P", player_name             );
            break;
        case 'S':
            SKEY( "S", short_descr             );
            break;
        case 'V':
            KEY( "V", vnum, fread_number( fp ) );
            break;
        case 'E':
            if( !str_cmp( word, "End" ) )
            {
                ARTI_TYPE * arti;

                fMatch = TRUE;

                for( arti = artifact_list; arti; arti = arti->next )
                {
                    if( arti->vnum == vnum )
                    {
                        free_string( arti->player_name );
                        arti->player_name = str_dup( player_name );

                        free_string( arti->name );
                        arti->name = str_dup( name );

                        free_string( arti->short_descr );
                        arti->short_descr = str_dup( short_descr );
			logf( NULL, "%d (%s) to %s", vnum, name, player_name );
                        break;
                    }
		}
                free_string( player_name );
                free_string( name );
                free_string( short_descr );
                return;
            }
            break;
        }
        if( !fMatch )
        {
            bugf( "fread_artif: no match %s", word );
        }
    }
}
void update_artifacts( char * fname )
{
    FILE * fp;
    bool fMatch;
    
    if( !(fp = fopen( fname, "r" ) ) )
        return;
        
    fMatch = FALSE;
    for( ; ; )
    {
        char   letter;
        char * word;

        letter = fread_letter( fp );

        if ( letter == '*' )
        {
            fread_to_eol( fp );
            continue;
        }

        if ( letter != '#' )
        {
            bug( "update_artifacts: # not found.",0 );
            break;
        }

        word = fread_word( fp );
        if ( !str_cmp( word, "ARTI" ) )
        {
            fread_artifact( fp );
            continue;
        }
        else if ( !str_cmp( word, "END"  ) )
            break;
        else
        {
            bugf( "update_artifacts: bad section. %s", word );
            break;
        }
    }

    fclose( fp );

    return;
}

/*
 * Scan all the object index's for artifacts.
 */
void load_artifacts( )
{
    OBJ_INDEX_DATA *pObjIndex;
    ARTI_TYPE   * arti;
    int vnum;
    int nMatch;

    nMatch = 0;
    top_artis = 0;
    artifact_list = NULL;
    
    for( vnum = 0; nMatch < top_obj_index; vnum++ )
    {
	if( ( pObjIndex = get_obj_index( vnum ) ) )
	{
	    nMatch++;

            if( IS_SET(pObjIndex->quest, QUEST_ARTIFACT)
             && !is_artifact( pObjIndex ) )
            {
                arti = alloc_perm( sizeof( ARTI_TYPE ) );
                
                arti->next = NULL;
                arti->pObjIndex = pObjIndex;
                arti->pArea = pObjIndex->area;

                arti->player_name = str_dup( "(not found)" );
                arti->short_descr = str_dup( pObjIndex->short_descr );
                arti->name        = str_dup( pObjIndex->name );
                arti->vnum        = pObjIndex->vnum;

                arti->next = artifact_list;
                artifact_list = arti;
		top_artis++;
            }
        }
    }

    logf( NULL, "Max Artifacts: %d", top_artis );
    update_artifacts( DATA_DIR ARTI_FILE );
    return;
}

char * check_date ( CHAR_DATA *ch, char * filename )
{
  char fname [ 256 ];
  struct stat fst;
  time_t tdiff;
  time_t  now_time; 
  now_time = time(0);

  if( get_char_world( ch, filename ) )
	return "{G";

  sprintf( fname, "%s/%s", PLAYER_DIR, filename );
  
  if ( stat( fname, &fst ) != -1 )
  {
      tdiff = (now_time - fst.st_mtime) / 86400;

      if( tdiff > 14 )
	return "{D";
      else if( tdiff > 9 )
      	return "{R";
      else if( tdiff > 4 )
	return "{Y";
      else
	return "";
  }
  else
	return "{D";
}
  

void do_show_artifacts( CHAR_DATA *ch, char *argument )
{
    ARTI_TYPE * arti;
    char arg [ MIL ];
    bool found;
    
    if( IS_NPC( ch ) )
        return;
    
    argument = one_argument( argument, arg );
    if( IS_IMMORTAL( ch ) )
    {
	if( arg[0] != '\0' )
	{
		if( !str_cmp( arg, "save" ) )
	        {
			write_artifacts( );
			stc( "Done.\n\r", ch );
			return;
	        }
		if( !str_cmp( arg, "clear" ) )
		{
		    for( arti = artifact_list; arti; arti = arti->next )
		    {
		        if( !arti )
		                break;	
			if( !str_prefix( arti->name, argument ) )
		        {
			    free_string( arti->player_name );
			    arti->player_name =str_dup( "(not found)" );
			    stc( "Done.\n\r", ch);
			    return;
			}
		    }
		    send_to_char( "Artifact not found.\n\r", ch );
		    return;
		}
		
	}
	ch_printf( ch, "There are %d artifacts.\n\r", top_artis );
        ch_printf( ch, "%5.5s | %20.20s | %-10.10s | %s\n\r",
                   "Vnum", "Name", "PlayerName", "ShortDescr" );
        send_to_char( LINE_SEPERATOR, ch );
    }

    found = FALSE;
    
    for( arti = artifact_list; arti; arti = arti->next )
    {
	if( !arti )
		break;

        found = TRUE;

        if( IS_IMMORTAL(ch) )
        {
            ch_printf( ch, "%5d | %20.20s | %s%-10.10s{x | %s\n\r",
                       arti->vnum, arti->name, 
		       check_date( ch, arti->player_name ),
		       arti->player_name,
                       arti->short_descr );
        }
        else
        {
            if( str_cmp( arti->player_name, "(not found)" ) )
                ch_printf( ch, "%s, which has been discovered by %s.\n\r",
                           arti->short_descr, arti->player_name );
            else
                ch_printf( ch, "%s, which has not yet been discovered.\n\r",
                           arti->short_descr );
        }
    }

    if( !found )
    {
        if( IS_IMMORTAL(ch) )
            send_to_char( "None found.\n\r", ch );
        else
            send_to_char( "There are no artifacts in the game yet.\n\r", ch);
    }
    
    if( IS_IMMORTAL(ch) )
        send_to_char( "{Rsee also:{x 'help arti_tracking'\n\r", ch );

    return;
}