tfe-1.0/area/
tfe-1.0/files/
tfe-1.0/logs/
tfe-1.0/logs/immortal/
tfe-1.0/logs/mob/
tfe-1.0/logs/object/
tfe-1.0/logs/player/
tfe-1.0/logs/room/
tfe-1.0/notes/clans/
tfe-1.0/player/
tfe-1.0/prev/
tfe-1.0/prev/area/
tfe-1.0/prev/player/
tfe-1.0/prev/rooms/
tfe-1.0/rooms/
tfe-1.0/src-gc/
tfe-1.0/src-msvc/
tfe-1.0/src-unix/
tfe-1.0/www/
tfe-1.0/www/html/
#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "define.h"
#include "struct.h"


void   room_info          ( char_data*, room_data* );
void   show_secret        ( char_data* );
void   show_tracks        ( char_data* );
bool   show_characters    ( char_data* );
void   show               ( char_data*, thing_data* );

void   look_in            ( char_data*, char* );
void   look_in            ( char_data*, obj_data* );

void   look_at_character  ( char_data*, char_data* );
void   show_equipment     ( char_data*, char_data* );
void   show_inventory     ( char_data*, char_data* );
void   show_description   ( char_data*, char_data* );


/*
 *   CAN_SEE ROUTINES
 */


bool Char_Data :: Can_See( bool msg )
{
  if( position <= POS_SLEEPING || is_set( affected_by, AFF_BLIND ) ) {
    if( msg )
      send( this, "You can't see a thing!\n\r" );
    return FALSE;
    }

  return TRUE;
}


bool Room_Data :: Seen( char_data* ch )
{
  if( !ch->Can_See( ) )
    return FALSE;

  if( ch->pcdata != NULL && is_set( ch->pcdata->pfile->flags, PLR_HOLYLIGHT ) )
    return TRUE;

  return TRUE;
}


bool Char_Data :: Seen( char_data* ch )
{
  wizard_data* imm;

  if( !In_Game( ) )
    return FALSE;

  if( this == ch || ch == NULL )
    return TRUE;

  if( ( imm = wizard( this ) ) != NULL
    && is_set( pcdata->pfile->flags, PLR_WIZINVIS )
    && get_trust( ch ) < imm->wizinvis )
    return FALSE;

  if( !in_character )
    return TRUE;

  if( !ch->Can_See( ) )
    return FALSE;
    
  /*
  if( in_room->is_dark( )
    && !is_set( affected_by, AFF_SANCTUARY )
    && ( !is_set( ch->affected_by, AFF_INFRARED ) || ( species != NULL
    && !is_set( &species->act_flags, ACT_WARM_BLOODED ) ) ) )
    return FALSE;
  */

  if( is_set( affected_by, AFF_INVISIBLE )
    && !ch->Sees_Invis( ) )
    return FALSE;

  /*
  if( ( is_set( affected_by, AFF_CAMOUFLAGE )
    || is_set( &status, STAT_CAMOUFLAGED ) )
    && !is_set( ch->affected_by, AFF_CAMOUFLAGE ) )
    return FALSE;
  */

  if( is_set( &status, STAT_HIDING )
    && !ch->Sees_Hidden( )
    && !includes( seen_by, ch ) )
    return FALSE;

  return TRUE;
}


bool Obj_Data :: Seen( char_data* ch )
{
  if( array == &ch->contents
    || array == &ch->wearing )
    return TRUE;

  if( !ch->Can_See( ) )
    return FALSE;

  /*
  if( in_room->is_dark( ) )
    return FALSE;
  */

  if( is_set( extra_flags, OFLAG_IS_INVIS ) && !ch->Sees_Invis( ) )
    return FALSE;

  return TRUE;
}


/*
 *   ATTRIBUTES
 */


bool char_data :: detects_evil( )
{
  return( is_set( affected_by, AFF_TRUE_SIGHT ) 
    || is_set( affected_by, AFF_DETECT_EVIL ) );
}


bool char_data :: detects_good( )
{
  return( is_set( affected_by, AFF_TRUE_SIGHT ) 
    || is_set( affected_by, AFF_DETECT_GOOD ) );
}


bool Char_Data :: Sees_Invis( )
{
  if( pcdata != NULL
    && is_set( pcdata->pfile->flags, PLR_HOLYLIGHT ) )
    return TRUE;

  return( is_set( affected_by, AFF_SEE_INVIS ) 
    || is_set( affected_by, AFF_TRUE_SIGHT ) );
}


bool Char_Data :: Sees_Hidden( )
{
  if( pcdata != NULL
    && is_set( pcdata->pfile->flags, PLR_HOLYLIGHT ) )
    return TRUE;

  return( is_set( affected_by, AFF_DETECT_HIDDEN ) 
    || is_set( affected_by, AFF_SENSE_LIFE ) );
}


/* 
 *   SHOW OBJECT ROUTINES
 */


void page( char_data* ch, thing_array& array )
{
  thing_data*   thing;
  bool        nothing  = TRUE;

  select( array );
  rehash( ch, array );

  for( int i = 0; i < array; i++ ) {
    thing = array[i];
    if( thing->shown > 0 ) {
      nothing = FALSE;
      page( ch, "  %s\n\r", thing );
      }
    }

  if( nothing )
    page( ch, "  nothing\n\r" );
}


void send( char_data* ch, thing_array& array )
{
  thing_data*   thing;
  bool        nothing  = TRUE;

  select( array );
  rehash( ch, array );

  for( int i = 0; i < array; i++ ) {
    thing = array[i];
    if( thing->shown > 0 ) {
      nothing = FALSE;
      send( ch, "  %s\n\r", thing );
      }
    }

  if( nothing )
    send( ch, "  nothing\n\r" );
}


/* 
 *   TRACK AND SEARCH ROUTINES
 */


void show_secret( char_data* ch ) 
{
  exit_data*  exit;

  if( ch->pcdata == NULL
    || !is_set( ch->pcdata->pfile->flags, PLR_SEARCHING )  
    || ch->move == 0 )
    return; 

  ch->move--;

  for( int i = 0; i < ch->in_room->exits; i++ ) {
    exit = ch->in_room->exits[i];
    if(  is_set( &exit->exit_info, EX_SEARCHABLE )
      && is_set( &exit->exit_info, EX_CLOSED )
      && is_set( &exit->exit_info, EX_SECRET ) 
      && !includes( ch->seen_exits, exit )
      && ch->check_skill( SKILL_SEARCHING ) ) {
      send( ch, "\n\r%s>> You detect something unusual %s. <<%s\n\r",
        bold_v( ch ), dir_table[ exit->direction ].name, normal( ch ) );
      ch->seen_exits += exit;
      }
    }
}


/*
 *   LOOK AT
 */


void Char_Data :: Look_At( char_data* ch )
{
  known_by += ch;

  if( ch != this ) {
    if( ch->Seen( this ) )
      send( this, "%s looks at you.\n\r", ch );
    send_seen( ch, "%s looks at %s.\n\r", ch, this );
    }
  else {
    send_seen( ch, "%s looks at %sself.\n\r",
      ch, ch->Him_Her( ) );
    }
  
  show_description( ch, this );
  page( ch, scroll_line[0] );
  glance( ch, this );
  page( ch, "\n\r" );
  show_equipment( ch, this );
}


void Exit_Data :: Look_At( char_data* ch )
{
  if( !is_set( &exit_info, EX_ISDOOR ) ) {
    send( ch, "To the %s is %s.\n\r",
       dir_table[ direction ].name,
       to_room->name );
    }
  else {   
    send( ch, "The %s is %s.\n\r", name,
      is_set( &exit_info, EX_CLOSED ) ? "closed" : "open" );
    }
}  


void Extra_Data :: Look_At( char_data* ch )
{
  char tmp [ MAX_STRING_LENGTH ];

  convert_to_ansi( ch, text, tmp );
  send( ch, tmp );
}

   


/* 
 *   SHOW CHARACTER FUNCTIONS
 */


void do_peek( char_data* ch, char* argument )
{
  char_data *victim;

  if( !ch->Can_See( TRUE ) )
    return;

  if( ( victim = one_character( ch, argument, "peek at",
    ch->array ) ) == NULL )
    return;

  show_equipment( ch, victim );
  page( ch, "\n\r" );
  show_inventory( ch, victim );

  ch->improve_skill( SKILL_PEEK );

  return;
}


void do_qlook( char_data *ch, char *argument )
{
  char_data* victim;

  if( !ch->Can_See( TRUE ) )
    return;

  if( *argument == '\0' ) {
    send( ch, "Look quickly at whom?\n\r" );
    return;
    }

  if( ( victim = one_character( ch, argument, "look quickly at",
    ch->array ) ) == NULL )
    return;

  show_description( ch, victim );

  return;
}


void show_inventory( char_data* ch, char_data* victim )
{
  if( ch == victim ) 
    page( ch, "You are carrying:\n\r" );
  else 
    page( ch, "%s is carrying:\n\r", victim );

  page( ch, victim->contents );

  return;
}


void show_description( char_data* ch, char_data* victim )
{
  char tmp  [ 3*MAX_STRING_LENGTH ];
 
  if( *victim->descr->complete != '\0' ) {
    convert_to_ansi( ch, victim->descr->complete, tmp );
    page( ch, tmp );
    }
  else {
    fpage( ch, "You see nothing special about %s.  In fact, you doubt\
 %s has any special distinguishing characteristics at all.",
      victim->Him_Her( ), victim->He_She( ) );
    }

  return;
}


/*
 *   EQUIPMENT 
 */


void do_equipment( char_data* ch, char* )
{
  show_equipment( ch, ch );
}


void show_equipment( char_data* ch, char_data* victim )
{
  char*       format  = "%-22s %-42s %s\n\r";
  char*          tmp  = static_string( );
  bool         found  = FALSE;
  obj_data**    list  = (obj_data**) victim->wearing.list;
  int           i, j;

  for( i = 0; i < victim->wearing; i = j ) { 

    if( victim != ch )  
      for( j = i+1; j < victim->wearing
        && list[i]->position == list[j]->position; j++ )
        if( is_set( list[j]->pIndexData->extra_flags, OFLAG_COVER ) )
          i = j;

    for( j = i; j < victim->wearing
      && list[i]->position == list[j]->position; j++ ) {
      if( ch == victim || list[j]->Seen( ch ) ) {
        if( !found ) {
          page_centered( ch, "+++ Equipment +++" );
          sprintf( tmp, format, "Body Location", "Item", "Condition" );
          page_underlined( ch, tmp );
          found = TRUE;
          }
        page( ch, format,
          j == i ? where_name[ list[i]->position ] : "", 
          list[j]->Name( ch, 1, TRUE ),
          list[j]->condition_name( ch, TRUE ) );
        }
      }
    }

  if( !found ) {
    if( ch == victim )
      page( ch, "You have nothing equipped.\n\r" );
    else
      page( ch, "%s has nothing equipped.\n\r", victim );
    }
  else {
    if( ch == victim ) 
      page( ch, "\n\rWeight: %.2f lbs\n\r", 
        (float) ch->wearing.weight/100 );
      }
}

/*
 *   LOOK IN OBJECT
 */


thing_data* cant( thing_data* thing, char_data*, thing_data* )
{
  return object( thing );
}


thing_data* notcontainer( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj = (obj_data*) thing;

  switch( obj->pIndexData->item_type ) {
    case ITEM_KEYRING   :
    case ITEM_CONTAINER :
    case ITEM_CORPSE    :
      return obj;
    }

  return NULL;
}


thing_data* closed( thing_data* thing, char_data*, thing_data* )
{
  obj_data* obj = (obj_data*) thing;

  if( obj->pIndexData->item_type == ITEM_CONTAINER 
    && is_set( &obj->value[1], CONT_CLOSED ) )
    return NULL;

  return obj;
}
 
    
thing_data* empty( thing_data* thing, char_data*, thing_data* )
{
  return( is_empty( thing->contents ) ? NULL : thing );
}


thing_data* lookin( thing_data* thing, char_data*, thing_data* )
{
  return thing;
}


void look_in( char_data* ch, char* argument )
{
  thing_array* array;

  if( *argument == '\0' ) {
    send( ch, "Look in what?\n\r" );
    return;
    }

  if( ( array = several_things( ch, argument,
    "look in", ch->array, &ch->contents,
    &ch->wearing ) ) == NULL ) 
    return;

  thing_array   subset  [ 5 ];
  thing_func*     func  [ 5 ]  = { cant, notcontainer, closed,
                                   empty, lookin };

  sort_objects( ch, *array, NULL, 5, subset, func );

  page_priv( ch, NULL, empty_string );
  page_priv( ch, &subset[0], "can't look in" );
  page_priv( ch, &subset[1], NULL, NULL,
    "isn't a container", "aren't containers" );
  page_priv( ch, &subset[2], NULL, NULL, "is closed", "are closed" );
  page_priv( ch, &subset[3], NULL, NULL, "is empty", "are empty" );

  for( int i = 0; i < subset[4]; i++ ) 
    look_in( ch, (obj_data*) subset[4].list[i] );

  delete array;
}


void look_in( char_data* ch, obj_data* obj )
{
  switch( obj->pIndexData->item_type ) {
    default:
      page( ch, "%s is not a container.\n\r", obj );
      return;

    case ITEM_SPELLBOOK :
      page( ch, "The spellbook is blank.\n\r" );
      return;

    case ITEM_DRINK_CON:
      page( ch, "It's %sfull of %s.\n\r",
        obj->value[1] < obj->pIndexData->value[0] / 2 ? "less than half "
        : ( obj->value[1] < 3* obj->pIndexData->value[0] / 4
        ? "more than half " : "" ),
        obj->value[2] < 0 || obj->value[2] >= table_max[TABLE_LIQUID]
        ? "[BUG]" : liquid_table[obj->value[2]].color );
      return;

    case ITEM_KEYRING :
    case ITEM_CONTAINER:
    case ITEM_CORPSE :
      break; 
    }

  page( ch, "%s contains:\n\r", obj );
  page( ch, obj->contents );
}


/*
 *   MAIN LOOK ROUTINE
 */


void do_look( char_data* ch, char* argument )
{
  visible_data* visible;

  if( ch->link == NULL || !ch->Can_See( TRUE ) )
    return;

  if( *argument == '\0' ) {
    show_room( ch, ch->in_room, FALSE, FALSE );
    return;
    }

  if(  !strncasecmp( argument, "in ", 3 ) 
    || !strncasecmp( argument, "i ", 2 ) ) {
    argument += ( argument[1] == 'n' ? 3 : 2 );
    look_in( ch, argument );
    return;
    }

  if( !strncasecmp( argument, "at ", 3 ) )
    argument += 3;

  if( ( visible = one_visible( ch, argument, "look at",
    (visible_array*) ch->array,
    (visible_array*) &ch->contents,
    (visible_array*) &ch->wearing,  
    (visible_array*) &ch->in_room->extra_descr,
    (visible_array*) &ch->in_room->exits ) ) == NULL )
    return;

  visible->Look_At( ch );
}


void show_room( char_data* ch, room_data* room, bool brief, bool scan )
{
  char           tmp  [ 3*MAX_STRING_LENGTH ];
  thing_data*  thing;
  obj_data*      obj;

  if( ch->pcdata == NULL )
    return;

  room_info( ch, room );
   
  if( !brief || !is_set( ch->pcdata->pfile->flags, PLR_BRIEF ) ) {
    if( room->Seen( ch ) ) {
      convert_to_ansi( ch, room->description, tmp );
      send( ch, tmp );
      }
    else {
      send( ch,
        "The area is very dark and you can make out no details.\n\r" );
      }
    if( is_builder( ch ) && *room->comments != '\0' ) {
      send( ch, "%37s-----\n\r", "" );
      send( ch, room->comments ); 
      }
    }

  show_secret( ch );
  show_tracks( ch );

  /* SHOW CONTENTS */

  select( room->contents, ch );

  for( int i = 0; i < room->contents; i++ ) 
    if( ( obj = object( room->contents[i] ) ) != NULL  
      && is_set( obj->extra_flags, OFLAG_NOSHOW ) )
      room->contents[i]->selected = 0; 

  rehash( ch, room->contents );

  bool found = FALSE;

  for( int i = 0; i < room->contents; i++ ) {
    thing = room->contents[i];
    if( thing->shown > 0 && thing != ch ) {
      if( !found ) {
        found = TRUE;
        send( ch, "\n\r" );
        }
      show( ch, thing );
      }
    }

  /* SCAN */

  int level = level_setting( &ch->pcdata->pfile->settings,
    SET_AUTOSCAN );

  if( scan && level != 0
    && ( level == 3 || !is_set( &room->room_flags, RFLAG_NO_AUTOSCAN ) ) )
    do_scan( ch, "shrt" );       
}


void show( char_data* ch, thing_data* thing )
{
  send( ch, "%s\n\r", thing->Show( ch, thing->shown ) );
}


/*
 *   ROOM INFO BOX
 */


char* room_flags( room_data* room )
{
  char* tmp = static_string( );

  if( is_set( &room->room_flags, RFLAG_SAFE ) )
    sprintf( tmp, "safe" );
  else
    *tmp = '\0';

  if( is_set( &room->room_flags, RFLAG_NO_MOB ) ) 
    sprintf( tmp+strlen( tmp ), "%s%s",
      *tmp == '\0' ? "" : ", ", "no.mob" );

  if( is_set( &room->room_flags, RFLAG_INDOORS ) ) 
    sprintf( tmp+strlen( tmp ), "%s%s",
      *tmp == '\0' ? "" : ", ", "inside" );

  if( *tmp == '\0' )
    return "--";

  return tmp;
}


void room_info( char_data* ch, room_data* room )
{
  char*    tmp  = static_string( );
  char*   name;
  bool can_see  = room->Seen( ch );
  int     term  = ch->pcdata->terminal;
  int   detail;
  int        i;

  name   = can_see ? ch->in_room->name : "DARKNESS";
  detail = level_setting( &ch->pcdata->pfile->settings, SET_ROOM_INFO );

  if( detail < 2 ) {
    if( is_apprentice( ch ) ) {
      send_color( ch, COLOR_ROOM_NAME, "#%d : %s\n\r",
        room->vnum, name );
      }
    else {
      send_color( ch, COLOR_ROOM_NAME, "%s\n\r", name );
      }
    if( detail == 1 && can_see )
      autoexit( ch );
    send( ch, "\n\r" );
    return;
    }

  if( term != TERM_DUMB ) {
    sprintf( tmp, "%%%ds%s%%s%s\n\r",
      40-strlen( name )/2,
      term_table[term].codes( ch->pcdata->color[ COLOR_ROOM_NAME ] ),
      normal( ch ) );
    send( ch, tmp, "", name );
    }
  else {
    send_centered( ch, name );
    }

  send( ch, scroll_line[2] );

  send( ch, "|   Lighting: %-15s Time: %-16s  Terrain: %-13s |\n\r",
    light_name( room->Light( ) ),
    is_set( &room->room_flags, RFLAG_INDOORS ) ? "???" : sky_state( ),
    terrain[ room->sector_type ].name );

  i = exits_prompt( tmp, ch );
  add_spaces( tmp, 12-i );

  send( ch, "|      Exits: %s Weather: %-15s Room Size: %-13s |\n\r",
    tmp, is_set( &room->room_flags, RFLAG_INDOORS ) ? "???" : "Clear",
    size_name[room->size] );

  if( is_apprentice( ch ) )
    send( ch, "|       Vnum: %-14d Flags: %-40s |\n\r",
      room->vnum, room_flags( room ) );
  
  send( ch, scroll_line[2] );
}