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 "define.h"
#include "struct.h"


void  use_start_table    ( char_data*, int );


/*
 *   CHARACTER CREATION ROUTINES
 */


void wrong_choice( link_data* link )
{
  send( link, "\r\nWhat you entered was unintelligible.  Please press\
 return and then select\r\none of the choices given between the left\
 and right brackets.\r\n" );
  press_return( link );

  return;
}


/*
 *   NAME
 */


bool check_parse_name( link_data* link, char* name )
{
  species_data*  species;
  char*           letter;
  int             length  = strlen( name );
  int           capitals  = 0;

  /* ALPHA AND PUNCTUATION */

  if( ispunct( *name ) || ispunct( name[length] ) ) {
    send( link, "\r\nThe first and last letters of a name may not be\
 punctuation to stop the\r\nsegment of the population who insist on the\
 name --Starbright--.\r\n" );
    return FALSE;
    }

  for( letter = name; *letter != '\0'; letter++ ) {
    if( isdigit( *letter ) ) {
      send( link, "\r\nNames are not allowed to contain numbers.\r\n" );
      return FALSE;
      }
    if( ispunct( *letter ) && *letter != '-' && *letter != '\'' ) {
      send( link, "\r\nNames are not allowed to contain punctuation other\
 than dashes and\r\napostrophes.\r\n" );
      return FALSE;
      }
    if( isupper( *letter ) && ++capitals > 2 ) {
      send( link, "\r\nNames can contain at most 3 capital letters.\r\n" );
      return FALSE;
      } 
    }

  if( length < 3 || length > 12 ) {
    send( link,
      "Names must be greater than 2 and less than 13 letters.\r\n" );
    return FALSE;
    }

  /* WORDS USED IN GAME */

  for( int i = 0; i < MAX_SPECIES; i++ ) {
    if( ( species = species_list[i] ) == NULL )
      continue;
    if( is_name( name, species->descr->name ) ) {
      send( link, "\r\nThat is the name of monster in the game and thus\
 unallowed.\r\n" );
      return FALSE;
      }
    }

  if( find_pfile_exact( name ) != NULL ) {
    send( link, "\r\nA player already exists with that name.\r\n" );
    return FALSE;
    }

  if( find_pfile( name ) != NULL || find_pfile_substring( name ) != NULL ) {
    help_link( link, "Name_Similiar" );
    return FALSE;
    }

  if( pntr_search( badname_array, max_badname, name ) >= 0 ) {
    help_link( link, "Bad_Name" );
    return FALSE;
    }

  return TRUE;
}


void nanny_new_name( link_data* link, char* argument )
{
  player_data*     ch;
  pfile_data*   pfile;

  if( no_input( link, argument ) )
    return;

  *argument = toupper( *argument );

  if( !check_parse_name( link, argument ) ) {
    send( link, "\r\nSelect another name: " );
    return;
    }

  pfile = new pfile_data( argument );
  ch    = new player_data( pfile->name );

  ch->pcdata->pfile = pfile;
  ch->link          = link;
  link->player      = ch;
  link->character   = ch;
  link->connected   = CON_GET_NEW_PASSWORD;
  link->pfile       = pfile;

  modify_pfile( ch );

  help_link( link, "Login_password" );
  send( link, "Password: " );
}


void nanny_new_password( link_data* link, char* argument )
{
  char_data*  ch  = link->character;
  char*        p;

  if( strlen( argument ) < 5 ) {
    send( link,
      "\r\nPassword must be at least five characters long.\r\nPassword: " );
    return;
    }

  for( p = argument; *p != '\0'; p++ ) {
    if( *p == '~' ) {
      send( link,
        "\r\nNew password not acceptable, try again.\r\nPassword: " );
      return;
      }
    }

  free_string( ch->pcdata->pfile->pwd, MEM_PLAYER );
  ch->pcdata->pfile->pwd = alloc_string( argument, MEM_PLAYER );

  send( link, "Please retype password: " );
  link->connected = CON_CONFIRM_PASSWORD;
}


void nanny_confirm_password( link_data* link, char* argument )
{
  char_data*  ch  = link->character;

  send( link, "\r\n" );

  if( strcmp( argument, ch->pcdata->pfile->pwd ) ) {
    send( link, "Passwords don't match.\r\nRetype password: " );
    link->connected = CON_GET_NEW_PASSWORD;
    return;
    }

  help_link( link, "Login.Display" );
  send( link, "Display type? [ None Ansi VT52 ]: " );

  link->connected = CON_SET_TERM;

  return;
}


/*
 *   TERMINAL TYPE
 */


void nanny_set_term( link_data* link, char* argument )
{
  char_data* ch  = link->character;
  int         i;

  switch( toupper( *argument ) ) {
    case 'V' :  ch->pcdata->terminal = TERM_VT100;  break;
    case 'A' :  ch->pcdata->terminal = TERM_ANSI;   break;
    default :   ch->pcdata->terminal = TERM_DUMB;   break;
    }

  if( ch->pcdata->terminal != TERM_DUMB ) 
    for( i = 0; i < MAX_COLOR; i++ )
      ch->pcdata->color[i] = term_table[ ch->pcdata->terminal ].defaults[i];

  setup_screen( ch );

  help_link( link, "Gamedesc_1" );
  press_return( link );

  link->connected = CON_READ_GAME_RULES;
}


/*
 *   GAME RULES
 */


void nanny_show_rules( link_data* link, char* )
{
  char_data*  ch  = link->character;

  clear_screen( ch );

  do_help( ch, "GAMEDESC_2" );
  send( link, "\r\nDo you wish to continue (Y/N)? " );

  link->connected = CON_AGREE_GAME_RULES;

  return;
}


void nanny_agree_rules( link_data* link, char* argument )
{
  if( toupper( *argument ) == 'N' ) {
    send( link, "Good bye.\r\n" );
    close_socket( link );
    return;
    }

  if( toupper( *argument ) != 'Y' ) {
    send( link, "Please answer Y or N. " );
    return;
    }

  nanny_help_sex( link, "" );

  return;
}    


/*
 *   SEX
 */


void nanny_help_sex( link_data* link, char* )
{
  char_data*  ch  = link->character;

  clear_screen( ch );

  do_help( ch, "login_sex" );
  send( link, "\r\nPlease enter your sex [Male Female]: " );

  link->connected = CON_GET_NEW_SEX;

  return;
}


void nanny_sex( link_data* link, char* argument )
{
  char_data*  ch  = link->character;

  switch( toupper( *argument ) ) {
    case 'M': ch->sex = SEX_MALE;    break;
    case 'F': ch->sex = SEX_FEMALE;  break;
    default:
      wrong_choice( link );
      link->connected = CON_HELP_SEX;
      return;
    }

  nanny_help_class( link, argument );
  return;
}


void nanny_help_class( link_data* link, char* )
{
  char       tmp  [ TWO_LINES ];
  int          i;
  char_data*  ch  = link->character;

  clear_screen( ch );

  do_help( ch, "login_classes" );

  strcpy( tmp, "\r\nSelect a class [" );

  for( i = 0; i < MAX_CLSS; i++ ) {
    if( clss_table[i].open ) {
      if( i > 0 )
        strcat( tmp, " " );
      strcat( tmp, clss_table[i].abbrev );
      }
    }
  strcat( tmp, "]: " );

  send( link, tmp );
  link->connected = CON_GET_NEW_CLSS;

  return;
}


void nanny_class( link_data* link, char* argument )
{
  char_data*    ch  = link->character;
  int            i;
  bool        help  = FALSE;

  link->connected = CON_HELP_CLSS;

  if( *argument == '\0' ) {
    wrong_choice( link );
    return;
    }

  if( *argument == '?' ) {
    argument++;
    help = TRUE;
    }

  for( i = 0; i < MAX_CLSS; i++ ) 
    if( clss_table[i].open 
      && fmatches( argument, clss_table[i].name ) )
      break;

  if( help ) {
    clear_screen( ch );
    help_link( link, clss_table[i].name );
    press_return( link );
    return;
    }    

  if( i == MAX_CLSS ) {
    wrong_choice( link );
    return;
    }

  ch->pcdata->clss = i;
  nanny_help_race( link, argument );

  return;
}


/*
 *   RACES
 */


bool allowed_race( char_data* ch, int race )
{
  int i;

  if( !plyr_race_table[race].open ) 
    return FALSE;

  for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ ) 
    if( is_set( &clss_table[ ch->pcdata->clss ].alignments, i ) 
      && is_set( &plyr_race_table[ race ].alignments, i ) ) 
      return TRUE;

  return FALSE;
}


void nanny_help_race( link_data* link, char* )
{
  char         tmp  [ TWO_LINES ];
  char_data*    ch  = link->character;
  bool       first  = TRUE;
  int            i;

  clear_screen( ch );

  do_help( ch, "login_races" );
  strcpy( tmp, "\r\nSelect a race [" );

  for( i = 0; i < MAX_PLYR_RACE; i++ ) {
    if( allowed_race( ch, i ) ) {
      if( !first ) 
        strcat( tmp, " " );
      strcat( tmp, race_table[i].abbrev );
      first = FALSE;
      }
    }      

  strcat( tmp, "]: " );
  send( link, tmp );

  link->connected = CON_GET_NEW_RACE; 
 
  return;
}

   
void nanny_race( link_data* link, char* argument )
{
  char_data*  ch  = link->character;
  int          i;
  bool      help  = FALSE;

  link->connected = CON_HELP_RACE;

  if( *argument == '?' ) {
    argument++;
    help = TRUE;
    }

  if( *argument == '\0' ) {
    wrong_choice( link );
    return;
    }

  for( i = 0; i < MAX_PLYR_RACE; i++ ) 
    if( plyr_race_table[i].open 
      && ( fmatches( argument, race_table[i].name )  
      || fmatches( argument, race_table[i].abbrev ) ) ) 
      break;
 
  if( i == MAX_PLYR_RACE ) {
    wrong_choice( link );
    return;
    }   

  if( help ) {
    clear_screen( ch );
    help_link( link, plyr_race_table[i].plural );
    press_return( link );
    return;
    }    

  ch->shdata->race = i;
  ch->pcdata->speaking = LANG_HUMANIC+i;
  ch->shdata->skill[ LANG_HUMANIC+i ] = 10;
  ch->shdata->skill[ LANG_PRIMAL ] = 10;

  link->connected = CON_DECIDE_STATS; 
  nanny_stats( link, "" );
}


/*
 *   STATS
 */


void nanny_stats( link_data* link, char* argument )
{
  char_data*       ch  = link->character;
  share_data*  shdata  = ch->shdata;
  int*          bonus  = plyr_race_table[ch->shdata->race].stat_bonus;
  int          points;
  int          number;
  int             i,j;
  char              c;

  int *stat[] = { &shdata->strength, &shdata->intelligence,
    &shdata->wisdom, &shdata->dexterity, &shdata->constitution };
  char letter[] = { 'S', 'I', 'W', 'D', 'C' };
  char *name[] = { "Strength", "Intelligence", "Wisdom", "Dexterity",
    "Constitution" };

  if( !strcasecmp( "done", argument ) ) { 
    nanny_help_alignment( link, "" );
    return; 
    }

  clear_screen( ch );

  if( strlen( argument ) < 2 || ( strlen( argument ) < 3 
    && isdigit( argument[1] ) ) ) {
    do_help( ch, "login_stats" );
    send( ch, "\r\n" );
    }
  else {
    for( j = 0, points = 500; j < 5; j++ )
      points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2;

    if( isdigit( argument[1] ) ) {
      c = toupper( argument[2] );
      number = argument[1]-'0';
      }
    else {
      c = toupper( argument[1] );
      number = 1;
      }

    for( i = 0; i < 5; i++ ) 
      if( c == letter[ i ] ) 
        break;

    if( i != 5 ) {
      switch( argument[0] ) {
      case '+' :
        if( *stat[i]+number > 18+bonus[ i ] )
          send( link, 
    "\r\nYou can not raise a stat over its racial maximum.\r\n" );
        else
          *stat[i] += number;
        break;
      case '-' :
        if( *stat[i]-number < 3 )
           send( link, 
            "\r\nYou can not lower a stat below 3.\r\n" );
        else
          *stat[i] -= number;
        break;
      default:
        i = 5;
        break;
        }
      }
   
    if( i == 5 ) {
      do_help( ch, "login_stats" );
      send( ch, "\r\n" );
      }
    else {
      for( j = 0, points = 500; j < 5; j++ )
        points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2;

      if( points < 0 ) {
        send( link,
          "\r\nYou don't have enough points for that.\r\n" );
        *stat[i] -= number;
        }
      } 
    }
  
  for( j = 0, points = 500; j < 5; j++ )
    points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2;

  send( link, "Points Left: %d\r\n\r\n", points );
  send( link,
    "Ability             Character    Racial Max    Cost to inc.\r\n" );
  send( link,
    "-------             ---------    ----------    ------------\r\n" );

  for( i = 0; i < 5; i++ ) {
    send( link, "%-15s%10d%13d%15d\r\n",
      name[i], *stat[i], 18+bonus[i],*stat[i]-bonus[i]+1 );
    }

  send( link, "\r\nEnter choice: " );
}


/*
 *   ALIGNMENT
 */


bool allowed_alignment( char_data* ch, int align )
{
  return( is_set( &clss_table[ ch->pcdata->clss ].alignments, align ) 
    && is_set( &plyr_race_table[ ch->shdata->race ].alignments, align ) );  
}


void nanny_help_alignment( link_data* link, char* )
{
  char         tmp  [ TWO_LINES ];
  char_data*    ch  = link->character;
  bool       first  = TRUE;
  int            i;

  clear_screen( ch );

  do_help( ch, "login_alignment" );
  strcpy( tmp, "\r\nEnter an alignment [" );

  for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ ) {
    if( allowed_alignment( ch, i ) ) {
      if( !first ) 
        strcat( tmp, " " );
      strcat( tmp, alignment_table[i].abbrev );
      first = FALSE;
      }
    }

  strcat( tmp, "]: " );
  send( link, tmp );

  link->connected = CON_GET_NEW_ALIGNMENT;
} 


void nanny_alignment( link_data* link, char* argument )
{
  char_data*      ch  = link->player;
  int              i;
  const char*   word  = empty_string; 
  bool          help  = FALSE;

  link->connected = CON_HELP_ALIGNMENT;

  if( *argument == '?' ) {
    argument++;
    help = TRUE;
    }

  if( *argument == '\0' ) {
    wrong_choice( link );
    return;
    }
  
  for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ )
    if( !strcasecmp( argument, alignment_table[i].abbrev )
      || fmatches( argument, alignment_table[i].name, 3 ) )
      break;

  if( i == MAX_ENTRY_ALIGNMENT ) {
    wrong_choice( link );
    return;
    }   

  if( help ) {
    clear_screen( ch );
    help_link( link, alignment_table[i].name );
    press_return( link );
    return;
    }    

  if( !is_set( &clss_table[ ch->pcdata->clss ].alignments, i ) ) {
    word = clss_table[ ch->pcdata->clss ].name;
    }
  else if( !is_set( &plyr_race_table[ ch->shdata->race ].alignments, i ) ) {
    word = race_table[ ch->shdata->race ].name;
    }
  else {
    ch->shdata->alignment = i;
    clear_screen( ch );
    help_link( link, "Introduction" );
    press_return( link );
    link->connected = CON_READ_IMOTD;
    return;
    }

  send( link, "\r\nA%c %s would not choose to be %s.\r\n",
    isvowel( *word ), word, alignment_table[i].name );

  press_return( link );
}


/*
 *   INITIALIZE NEW PLAYER
 */


void new_player( player_data* ch )
{
  char               tmp  [ MAX_STRING_LENGTH ];
  int               clss  = ch->pcdata->clss;
  int                  i;

  ch->shdata->level     = 1;
  ch->exp               = 0;
  ch->pcdata->practice  = 25;

  ch->base_hit          = 20;
  ch->base_mana         = 50;
  ch->base_move         = 100;
  ch->base_age          = plyr_race_table[ ch->shdata->race ].start_age;

  update_max_hit( ch );
  update_max_mana( ch );

  ch->hit  = ch->max_hit;
  ch->mana = ch->max_mana;
  
  update_max_move( ch );

  ch->move        = ch->max_move;

  /* OPTIONS */

  set_bit( ch->pcdata->pfile->flags, PLR_PROMPT );
  set_bit( ch->pcdata->pfile->flags, PLR_GOSSIP );
  set_bit( ch->pcdata->pfile->flags, PLR_SAY_REPEAT );
  set_bit( ch->pcdata->pfile->flags, PLR_AUTO_EXIT );
  set_bit( ch->pcdata->pfile->flags, PLR_SAFE_KILL );
  set_bit( ch->pcdata->pfile->flags, PLR_PORTAL );
  set_bit( ch->pcdata->pfile->flags, PLR_IDLE );
  set_bit( ch->pcdata->pfile->flags, PLR_INFO );
  set_bit( ch->pcdata->pfile->flags, PLR_LANG_ID );
  set_bit( ch->pcdata->pfile->flags, PLR_OOC );
  
  set_level( &ch->pcdata->pfile->settings, SET_ROOM_INFO, 3 );
  set_level( &ch->pcdata->pfile->settings, SET_AUTOLOOT, 1 );

  /* IFLAGS */

  for( i = 0; i < MAX_IFLAG; i++ )
    set_level( ch->iflag, i, 3 );

  set_level( ch->iflag, IFLAG_AUCTION, 1 );
  set_level( ch->iflag, IFLAG_LOGINS, 1 );
  set_level( ch->iflag, MAX_IFLAG+NOTE_ANNOUNCEMENTS, 1 );
  set_level( ch->iflag, MAX_IFLAG+NOTE_GENERAL, 1 );

  /* MESSAGES */

  remove_bit( &ch->pcdata->message, MSG_MAX_MOVE );

  modify_pfile( ch ); 

  ch->pcdata->pfile->account = ch->link->account;

  free_string( ch->descr->singular, MEM_DESCR );
  sprintf( tmp, "%s %s",
    race_table[ ch->shdata->race ].name,
    clss_table[ clss ].name );
  ch->descr->singular = alloc_string( tmp, MEM_DESCR );

  free_string( ch->descr->long_s, MEM_DESCR );
  sprintf( tmp, "%s is standing here.", ch->descr->singular );
  tmp[0] = toupper( tmp[0] );
  ch->descr->long_s = alloc_string( tmp, MEM_DESCR );

  free_string( ch->pcdata->title, MEM_PLAYER );
  sprintf( tmp, " the %s %s", race_table[ ch->shdata->race ].name,
    clss_table[ clss ].name );
  ch->pcdata->title = alloc_string( tmp, MEM_PLAYER );

  free_string( ch->descr->keywords, MEM_DESCR );
  sprintf( tmp, "%s %s", race_table[ch->shdata->race].name,
    clss_table[clss].name );
  ch->descr->keywords = alloc_string( tmp, MEM_DESCR );

  /* SET STANDARD EQUIP/SKILLS */

  use_start_table( ch, 0 );
  use_start_table( ch, clss+1 );
  use_start_table( ch, MAX_CLSS+ch->shdata->race+1 );

  ch->To( get_temple( ch ) );
}


void use_start_table( char_data* ch, int entry )
{
  obj_clss_data*  index;
  obj_data*         obj;
  int             skill;
  int i;

  for( i = 0; i < 5; i++ ) 
    if( ( skill = starting_table[entry].skill[i] ) >= 0 )
      ch->shdata->skill[skill] = starting_table[entry].level[i];

  for( i = 0; i < 5; i++ ) 
    if( ( index = get_obj_index(
      starting_table[entry].object[2*i] ) ) != NULL ) {
      obj = create( index, starting_table[ entry ].object[ 2*i+1 ] );
      obj->To( ch );
      switch( obj->pIndexData->item_type ) {
        case ITEM_ARMOR :
        case ITEM_WEAPON : 
          needremove( obj, ch, NULL );
        }
      }
}


bool newbie_abuse( char_data* ch )
{
  if( ch->species != NULL || ch->played+current_time-ch->logon > 50 )
    return FALSE;

  send( ch, "To stop abuse you cannot drop or give anything for the\
 first 5 minutes\r\nof play.  To get rid of an item use junk.\r\n" );

  return TRUE;
}