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"


const char *action_trigger[ MAX_ATN_TRIGGER ] = { "none", "entering room",
  "random", "leaving room", "random_always", "sacrifice", "time", "attack",
  "open_door", "searching", "close_door", "lock_door", "unlock_door",
  "knock_door" };

const char *action_value[ MAX_ATN_TRIGGER ] = { "unused", "unused",
  "chance", "unused", "unused", "minutes past midnight", "unused",
  "unused", "difficulty", "unused", "unused", "unused", "unused" };


#define AFLAG_LOOP_FOLLOWER   0
#define AFLAG_MOUNTED         1
#define AFLAG_RESTING         2
#define AFLAG_SLEEPING        3
#define AFLAG_FIGHTING        4


const char* action_flags [ MAX_ATN_TRIGGER ][ 10 ] =
{
  { "loop_follower", "mounted", "resting", "sleeping", "fighting", "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "" },
  { "" },
  { "" },
  { "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "north", "east", "south", "west", "up", "down", "" },
  { "north", "east", "south", "west", "up", "down", "" },
};


const char** action_msgs [ MAX_ATN_TRIGGER ] =
{
  NULL,
  NULL,
  NULL,
  leaving_msg,
  NULL,
  NULL,
  NULL,
  NULL,
  open_msg,
  NULL,
  close_msg,
  unlock_door_msg,
  lock_door_msg,
  knock_door_msg,
};


/*
 *   DISPLAY ROUTINE
 */


void action_data :: display( char_data* ch )
{
  action_data*  action;
  int                i  = 1;

  if( room == NULL ) {
    send( ch, "%-10s %-10s %s\n\r", "??", "Acode", "Null Room??" );
    return;
    }

  for( action = room->action; action != this; action = action->next, i++ );
  send( ch, "Room %-10d Acode %-8d %s\n\r", room->vnum, i, room->name );

  return;
}     


const char* Keywords( action_data* action )
{
  const char*   list  [ 10 ];
  int              i;
  int              j  = 0;

  for( i = 0; *action_flags[action->trigger][i] != '\0'; i++ ) 
    if( is_set( &action->flags, i ) ) 
      list[j++] = action_flags[action->trigger][i];

  return word_list( list, j, FALSE );
}


/*
 *   DISK ROUTINES
 */


void read( FILE* fp, action_data*& list, room_data* room )
{
  action_data* action;

  action = new action_data;

  action->command = fread_string( fp, MEM_ACTION );
  action->target  = fread_string( fp, MEM_ACTION );
  action->code    = fread_string( fp, MEM_ACTION );

  read_extra( fp, action->data );

  action->trigger = fread_number( fp );
  action->value   = fread_number( fp );
  action->flags   = fread_number( fp );
  action->room    = room;

  append( list, action ); 

  return;  
}


void write( FILE* fp, action_data* action )
{
  fprintf( fp, "A\n" );
  fprintf( fp, "%s~\n", action->command );
  fprintf( fp, "%s~\n", action->target );
  fprintf( fp, "%s~\n", action->code );

  write_extras( fp, action->data );
  fprintf( fp, "!\n" );
 
  fprintf( fp, "%d %d %d\n", action->trigger, action->value, action->flags );
}



/*
 *   EXECUTION ROUTINES
 */


bool check_actions( char_data* ch, char* command, char* argument )
{
  action_data*  action;
  char_data*       rch;
  room_data*      room;
  int                i;

  if( ( room = Room( ch->array->where ) ) == NULL )
    return FALSE;

  for( action = room->action; action != NULL; action = action->next ) 
    if( member( command, action->command, TRUE )
      && member( argument, action->target ) ) 
      break;
          
  if( action == NULL )
    return FALSE;

  if( !check_action_flags( ch, action->flags ) )
    return TRUE;

/*
  if( is_set( &action->flags, AFLAG_LOOP_FOLLOWER ) ) 
    list = follower_list( ch );
*/
 
  disrupt_spell( ch );

  var_ch   = ch;
  var_room = room;
  var_arg  = argument;

  if( !execute( action ) ) 
    return TRUE; 

  /*
  if( list != NULL ) {
    for( i = 0; i < list->length; i++ ) {
      rch = (char_data*) list->pntr[i];
      if( rch->array == room
        && check_action_flags( rch, action->flags, FALSE ) ) {
        var_ch   = rch;
        var_room = room;  
        execute( action );
        }
      }
    delete list;
    }
  */

  return FALSE;
}


bool check_action_flags( char_data *ch, int flags, bool msg )
{
  #define types 4

  int bit[types] = { AFLAG_MOUNTED, AFLAG_FIGHTING, AFLAG_RESTING,
    AFLAG_SLEEPING };

  bool check[types] = {
    ch->mount != NULL,
    ch->fighting != NULL,
    ch->position == POS_RESTING || ch->position == POS_MEDITATING,
    ch->position <= POS_SLEEPING,
    };

  char *word[types] = { "mounted", "fighting", "sitting", "not awake" };

  for( int i = 0; i < types; i++ )
    if( check[i] && !is_set( &flags, bit[i] ) ) {
      if( msg ) 
        send( ch, "You are unable to do that while %s.\n\r", word[i] );
      return FALSE;
      }

  #undef types

  return TRUE;
}


/*
 *   RANDOM ACODES
 */


void action_update( )
{
  area_data*       area;
  room_data*       room;
  action_data*   action;
  
  for( area = area_list; area != NULL; area = area->next ) 
    for( room = area->room_first; room != NULL; room = room->next ) 
      for( action = room->action; action != NULL; action = action->next )
        if( action->trigger == TRIGGER_TIME && action->value
          == weather.minute+60*weather.hour )
          execute( action );

  return;
} 
 

/*
 *   EDITING ROUTINES
 */


void do_aedit( char_data *ch, char *argument )
{
  char              arg  [ MAX_INPUT_LENGTH ];
  char              tmp  [ TWO_LINES ];
  action_data*   action;
  room_data*       room;
  wizard_data*   wizard;
  int                 i;

  if( ( room = Room( ch->array->where ) ) == NULL ) {
    send( ch, "You aren't in a room.\n\r" );
    return;
    }

  wizard = (wizard_data*) ch;

  if( *argument == '\0' ) {
    if( ( action = room->action ) == NULL ) {
      send( ch, "This room has no actions.\n\r" );
      return;
      }
    for( i = 0, action = room->action; action != NULL;
      action = action->next ) {
      if( *action->command != '\0' )
        sprintf( tmp, "[%2d] %-20s %s - %s\n\r", ++i, "Command",
          action->command, action->target );
      else {
        sprintf( tmp, "[%2d] %-20s %s\n\r", ++i,
          action_trigger[action->trigger], Keywords( action ) );
        tmp[5] = toupper( tmp[5] );
        }
      send( ch, tmp );
      }
    return;
    }

  argument = one_argument( argument, arg );

  if( is_number( arg ) ) {
    i = atoi( arg );
    for( action = room->action; action != NULL && i != 1;
      action = action->next, i-- );
    if( action == NULL ) {
      send( ch, "No action by that number.\n\r" );
      return;
      }
    wizard->action_edit = action;
    wizard->adata_edit  = NULL;
    send( ch, "You now edit that action.\n\r" );
    return;
    }

  if( !can_edit( ch, room ) )
    return;

  room->area->modified = TRUE;

  if( !strcasecmp( arg, "new" ) ) {
    action               = new action_data;
    action->command      = alloc_string( argument, MEM_ACTION );
    wizard->action_edit  = action;
    wizard->adata_edit   = NULL;
    append( room->action, action );
    send( ch, "Action added.\n\r" );
    return;
    }

  if( !strcasecmp( arg, "delete" ) ) {
    if( ( action = wizard->action_edit ) == NULL ) {
      send( ch, "You aren't editing any action.\n\r" );
      return;
      }
    remove( room->action, action );  
    extract( wizard, offset( &wizard->action_edit, wizard ), "action" );
    delete action;
    send( ch, "Action deleted.\n\r" );
    return;
    }

  send( ch, "Illegal syntax.\n\r" );
  return;
}


void do_aflag( char_data* ch, char* argument )
{
  action_data*     action;
  const char*    response;
  wizard_data*     wizard;
  int                 max;

  wizard = (wizard_data*) ch;

  if( ( action = wizard->action_edit ) == NULL ) {
    send( ch, "You aren't editing any action.\n\r" );
    return;
    }

  for( max = 0; *action_flags[action->trigger][max] != '\0'; max++ );

  if( max == 0 ) {
    send( ch, "That type of trigger has no action flags.\n\r" );
    return;
    }

  if( *argument == '\0' ) {
    display_flags( "Action", &action_flags[action->trigger][0],
      &action_flags[action->trigger][1], &action->flags, max, ch );
    return;
    }

  if( set_flags( &action_flags[action->trigger][0],
    &action_flags[action->trigger][1], &action->flags,
    max, NULL, ch, argument, FALSE, TRUE ) == NULL ) 
    return;

  room_data* room = (room_data*) ch->array->where;
  room->area->modified = TRUE;
}


void do_astat( char_data* ch, char* )
{
  char              buf  [ 3*MAX_STRING_LENGTH ];
  action_data*   action;
  wizard_data*   wizard;

  wizard = (wizard_data*) ch;

  if( ( action = wizard->action_edit ) == NULL ) {
    send( ch, "You aren't editing any action.\n\r" );
    return;
    }

  page( ch, "%10s : %s\n\r", "Trigger", action_trigger[ action->trigger ] );
  page( ch, "%10s : %d\n\r", "Value", action->value );
  page( ch, "%10s : %s\n\r", "Command", action->command );
  page( ch, "%10s : %s\n\r\n\r", "Target", action->target );

  sprintf( buf, "[Code]\n\r%s\n\r", action->code );
  page( ch, buf );

  show_extras( ch, action->data );

  return;
}


void do_aset( char_data* ch, char* argument )
{
  action_data*   action;
  wizard_data*   wizard;
  room_data*       room  = (room_data*) ch->array->where;

  wizard = (wizard_data*) ch;

  if( ( action = wizard->action_edit ) == NULL ) {
    send( ch, "You aren't editing any action.\n\r" );
    return;
    }

  if( *argument == '\0' ) {
    do_astat( ch, argument );
    return;
    }

  if( !can_edit( ch, room ) )
    return;

  room->area->modified = TRUE;

#define att  action_trigger

  class type_field type_list[] = {
    { "trigger",  MAX_ATN_TRIGGER,  &att[0],  &att[1],  &action->trigger },
    { "",         0,                NULL,     NULL,     NULL             }
    };

#undef att

  if( process( type_list, ch, "action", argument ) )
    return;

  class string_field string_list[] = {
    { "target",    MEM_ACTION,  &action->target,   NULL },
    { "command",   MEM_ACTION,  &action->command,  NULL },
    { "",          0,           NULL,              NULL },   
    };

  if( process( string_list, ch, "action", argument ) )
    return;

  if( matches( argument, "value" ) ) {
    action->value = atoi( argument );
    send( ch, "Value on action set to %d.\n\r", action->value );
    return;
    }

  send( ch, "Syntax: aset <field> <value>\n\r" );
  return;
}


void do_acode( char_data* ch, char* argument )
{
  action_data*   action;
  wizard_data*   wizard;
  room_data*       room  = (room_data*) ch->array->where;

  wizard = (wizard_data*) ch;

  if( ( action = wizard->action_edit ) == NULL ) {
    send( ch, "You aren't editing any action.\n\r" );
    return;
    }

  if( argument[0] != '\0' && !can_edit( ch, room ) )
    return;

  room->area->modified = TRUE;
  action->code = edit_string( ch, argument, action->code, MEM_ACTION );

  var_ch =  ch;
  compile( action );
}


void do_adata( char_data* ch, char *argument )
{
  action_data*  action;
  wizard_data*  wizard;
  room_data*      room  = (room_data*) ch->array->where;

  wizard = (wizard_data*) ch;

  if( ( action = wizard->action_edit ) == NULL ) {
    send( ch, "You aren't editing any action.\n\r" );
    return;
    }

  if( wizard->adata_edit != NULL ) {
    if( !strcasecmp( argument, "exit" ) || !strcmp( argument, ".." ) ) {
      wizard->adata_edit = NULL;
      send( ch, "Adata now operates on the data list.\n\r" );
      return;
      }      
    wizard->adata_edit->text = edit_string( ch, 
      argument, wizard->adata_edit->text, MEM_EXTRA );
    }
  else {
    if( *argument == '\0' )
      show_defaults( ch, action->trigger, action_msgs );

    edit_extra( action->data, wizard, offset( &wizard->adata_edit, wizard ),
      argument, "adata" );
    room->area->modified = TRUE;
    }

  var_ch = ch;
  compile( action );
}