Logo Search packages:      
Sourcecode: aime version File versions  Download package

specials.cpp

/**********************************************************************
 ** Specials class: This class handles the specials code
 **
 **
 ** Reviewed through:  version 0.14
 **    
 **
 ** Copyright (C) 2000 George Noel (Slate)
 **
 **   This program is free software; you can redistribute it and/or modify
 **   it under the terms of the GNU General Public License as
 **   published by the Free Software Foundation; either version 2 of the 
 **   License, or any later version. 
 **
 **   This program is distributed in the hope that it will be useful, but 
 **   WITHOUT ANY WARRANTY; without even the implied warranty of 
 **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 **   General Public License for more details. 
 ** 
 **   You should have received a copy of the GNU General Public License 
 **   along with this program (in the docs dir); if not, write to the Free
 **   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 **
 **********************************************************************/

#ifndef SPECIALS_C
#define SPECIALS_C

#include "config.h"
#include "sysdep.h"
#include "strings.h"
#include "mudtypes.h"
#include "mudobject.h"
#include "objtype.h"
#include "utils.h"
#include "specials.h"
#include "lexer.h"
#include "errlog.h"
#include "code.h"
#include "builder.h"
#include "editor.h"
#include "newfuncts.h"
#include "player.h"

/***********************************************************************
 ** ~Specials (destructor) - destroys the special
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Specials::~Specials()
{
   Code *tmp_code;
   vars *tmp_var;

   tmp_code = the_code;
   while (tmp_code != NULL)
   {
      the_code = tmp_code->get_next_code();
      delete tmp_code;
      tmp_code = the_code;
   }
   
   tmp_var = var_list;
   while (tmp_var != NULL)
   {
      var_list = tmp_var->next_var;
      delete_vars(tmp_var);
      tmp_var = var_list;
   }

}


/***********************************************************************
 ** Specials (constructor) - Creates the special 
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Specials::Specials(char *spec_name, char *the_area)
{
   if (spec_name != NULL)
      set_name(spec_name);

   if (the_area != NULL)
      set_area(the_area);

   obj_type = OBJ_TYPE_SPECIAL;
   activation = 0;
   interval = 0;
   num_times = 0;
   expired = 0;
   counter = 0;

   var_list = NULL;
   the_code = NULL;

   max_exe = avg_exe = num_exe = 0;
   min_exe = 10000;
}


/***********************************************************************
 ** set_activation_date - sets the date that this code will activate
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::set_activation_date(time_t the_time)
{ 
   activation = the_time;
}


/***********************************************************************
 ** set_interval - sets the interval between code activation
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::set_interval(time_t the_time)
{ 
   interval = the_time;
}


/***********************************************************************
 ** set_num_times - set the number of times this code runs
 **
 ** Parameters: the_num - the number of times to set it to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::set_num_times(int the_num)
{ 
   num_times = the_num;
}


/***********************************************************************
 ** set_trigger - sets the trigger that activates this special
 **
 ** Parameters: the_trigger - the trigger string
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

int Specials::set_trigger(char *the_trigger)
{
   triggername = the_trigger;
   return 1;
}

/***********************************************************************
 ** set_comments - sets the comments string for use on the builder port
 **
 ** Parameters: the_str - the comments string
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::set_comments(char *the_str)
{
   comments = the_str;
}


/***********************************************************************
 ** get_comments - gets the comments string for use on the builder port
 **
 ***********************************************************************/

char *Specials::get_comments()
{
   return comments.str_show();
}


/***********************************************************************
 ** is_expired - detects if this has expired or not
 **
 ** Parameters: Nothing
 **
 ** Returns: 1 if expired, 0 if not
 **
 ***********************************************************************/

int Specials::is_expired(void)
{
   return expired;
}


/***********************************************************************
 ** read_code - loads the special code from a file and puts it into memory
 **
 ** Parameters: the_file - the file to load the specials from
 **             the_log - where to record the errors we encounter
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Specials::read_code(FILE *the_file, ErrLog *the_log, int is_build_port)
{
   token_record  *the_token;
   Strings       holder;
   Code          *code_holder;

   if ((the_file == NULL) || (the_log == NULL))
      return -1;


   if (is_build_port)
   {
      char *temp_code;

      temp_code = read_desc_type(the_file, the_log, this);
   
      if (temp_code == NULL)
         return -1;

      set_code_str(temp_code);

      delete temp_code;

      return 1;
   }

   the_token = get_token(the_file, '\0');
   if (the_token->token_type != T_CARROT)
   {
      holder.sprintf("Invalid format for special %s", get_name());
      the_log->log_err(holder.str_show(), "read_code");
      return -1;
   }

   /* get the commands */
   the_token = get_token(the_file, '\0');
   while (the_token->token_type != T_CARROT)
   {
      Strings functname;

      if (the_token->token_type != T_IDENTIFIER)
      {
         holder.sprintf("Invalid format for special %s", get_name());
         the_log->log_err(holder.str_show(), "read_code");
         return -1;
      }

      functname = the_token->the_string;

      the_token = get_token(the_file, '\0');
      if (the_token->token_type == T_LPAREN)
      {
         code_holder = new Code(functname.str_show());
         if (!code_holder->check_valid())
         {
            holder.sprintf("Unrecognized function '%s' in special %s", 
                             functname.str_show(), get_name());
            the_log->log_err(holder.str_show(), "load_from_file");
            delete code_holder;
            return -1;
         }

         if (code_holder->load_from_file(the_file, the_log) <=0)
         {
            holder.sprintf("Error in function '%s' in special %s", 
                          functname.str_show(), get_name());
            the_log->log_err(holder.str_show(), "read_code");
            delete code_holder;
            return -1;
         }

         the_token = get_token(the_file, '\0');
         if (the_token->token_type != T_SEMICOLON)
         {
            holder.sprintf("Missing semicolon after function '%s' "
                          "for special %s", functname.str_show(), get_name());
            the_log->log_err(holder.str_show(), "read_code");
            delete code_holder;
            return -1;
         }

         add_code(code_holder);      
         the_token = get_token(the_file, '\0');
 
      }
      else if (the_token->token_type == T_EQUALS)
      {
         code_holder = new Code("assign");

         if (code_holder->load_from_file(the_file, the_log, FORMAT_EQ) <=0)
         {
            holder.sprintf("Error in function '%s' in special %s", 
                          functname.str_show(), get_name());
            the_log->log_err(holder.str_show(), "read_code");
            delete code_holder;
            return -1;
         }

         code_holder->set_var_name(functname.str_show());
         add_code(code_holder);
         the_token = get_token(the_file, '\0');
      } else if (the_token->token_type == T_COLON)
      {
         vars *new_var = NULL;
         Code *tmp_code;

         tmp_code = the_code;
         while ((tmp_code != NULL) && (tmp_code->get_next_code() != NULL))
            tmp_code = tmp_code->get_next_code();

         new_var = new_vars();
         new_var->varname = functname.str_show();
         new_var->vartype = VAR_TYPE_GOTO;

         if (the_code == NULL)
            new_var->the_ptr.goto_code = &the_code;
         else
            new_var->the_ptr.goto_code = tmp_code->get_next_ptr();

         add_var(new_var);
         the_token = get_token(the_file, '\0');
      }
      else
      {

      }

   }

   return 1;   
}

/***********************************************************************
 ** get_trigger - returns the string that triggers this special
 **
 ** Parameters: None
 **
 ** Returns: pointer to the trigger strin
 **
 ***********************************************************************/

char *Specials::get_trigger(void)
{
   return triggername.str_show();
}


/***********************************************************************
 ** run_special - runs the special code
 **
 ** Parameters: None
 **
 ** Returns: -1 if failed, 
 **           1 if good, 
 **           2 if we should delete the object
 **           3 if conditions were not met to complete the special execution
 **           4 used with abilities in attempt trigger, if the attempt 
 **             should fail
 **           5 used with abilities in attempt trigger, if the attempt 
 **             should succeed
 **             Note: 4 and 5 override all output
 **           6 indicates we should remove this special from the object
 **             it is attached to
 **
 ***********************************************************************/

int Specials::run_special(Individual *the_user, in_params *the_params, 
                                                   special_env *environment)
{
   int results = 0;
   long timespan;


#if defined( AIME_WIN32 )
   FILETIME time_start, time_end;

   GetSystemTimeAsFileTime( &time_start );

#else
   struct timeval time_start, time_end;

   gettimeofday(&time_start, NULL);
#endif


   environment->stack_pointer = the_code;
   while (environment->stack_pointer != NULL)
   {

      (environment->stack_pointer)->
         execute_command(this, the_user, the_params, &results, environment);

      if (results != 2)
         environment->stack_pointer = 
                              (environment->stack_pointer)->get_next_code();

      /* if we are to delete this object now */
      if (results >= 3)
      {
         delete_var_list(environment);
         return results - 1;
      }
   }


#if defined( AIME_WIN32 )
   GetSystemTimeAsFileTime( &time_end );

   if( time_start.dwHighDateTime != time_end.dwHighDateTime )
   {
      timespan = ( long )( ( time_end.dwHighDateTime
                             - time_start.dwHighDateTime )
                           * 4294.967296 );
   }
   else
   {
      timespan = 0;
   }

   timespan += ( time_end.dwLowDateTime
                - time_start.dwLowDateTime ) / 1000000;

#else
        gettimeofday(&time_start, NULL);

     if (time_start.tv_sec != time_end.tv_sec)
     {
        timespan = ((1000000 - time_start.tv_usec) + 
                   ((time_end.tv_sec - (time_start.tv_sec+1)) * 1000000) +
                   (time_end.tv_usec));
     }
     else
        timespan = time_end.tv_usec - time_start.tv_usec;
#endif


   num_exe++;
   if (timespan > max_exe)
      max_exe = timespan;

   if (timespan < min_exe)
      min_exe = timespan;

   avg_exe = ((avg_exe*(num_exe-1)) + timespan) / num_exe;

   delete_var_list(environment);
   return 1;
}


/***********************************************************************
 ** add_code - adds code to the stack
 **
 ** Parameters: new_code - the code object to add
 **
 ** Returns: -1 if failed, 1 if successful
 **
 ***********************************************************************/

int Specials::add_code(Code *new_code)
{
   Code *tmp_list;

   if (new_code == NULL)
      return -1;

   if (the_code == NULL)
   {
      the_code = new_code;
      return 1;
   }   

   tmp_list = the_code;
   while (tmp_list->get_next_code() != NULL)
   {
      tmp_list = tmp_list->get_next_code();
   }
   return tmp_list->set_next_code(new_code);
}


/***********************************************************************
 ** add_var - adds a variable to the variable list
 **
 ** Parameters: new_var - the new variable to add
 **
 ** Returns: -1 if failed, 1 if successful
 **
 ***********************************************************************/

int Specials::add_var(vars *new_var)
{
   vars *tmp_list;

   if (new_var == NULL)
      return -1;

   new_var->next_var = NULL;
   if (var_list == NULL)
   {
      var_list = new_var;
      return 1;
   }   

   tmp_list = var_list;
   while (tmp_list->next_var != NULL)
   {
      tmp_list = tmp_list->next_var;
   }

   tmp_list->next_var = new_var;
   return 1;
}


/***********************************************************************
 ** get_var - gets a var based on a string
 **
 ** Parameters: the_var_name - the name of the variable we are looking for
 **
 ** Returns: Pointer to the var if found, NULL if not found
 **
 ***********************************************************************/

vars *Specials::get_var(char *the_var_name)
{
   vars *tmp_var;

   if (the_var_name == NULL)
      return NULL;

   tmp_var = var_list;
   while (tmp_var != NULL)
   {
      if (!STRCASECMP(the_var_name, tmp_var->varname.str_show()))
         return tmp_var;
      tmp_var = tmp_var->next_var;
   }
   return NULL;
}


/***********************************************************************
 ** set_stack_pointer - sets the stack pointer to the indicated code
 **
 ** Parameters: the_code - the code we are setting the stack to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

/* void Specials::set_stack_pointer(Code *the_code)
{
   stack_pointer = the_code;
} */


/***********************************************************************
 ** set_code_str - sets the code string for builder port storage of code
 **
 ** Parameters: the_string - the string to set the code to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Specials::set_code_str(char *the_string)
{
   if (the_string == NULL)
      return -1;

   code_string = the_string;
   return 1;
}

/***********************************************************************
 ** get_code_str - gets the builder code string
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the string, or NULL if failed
 **
 ***********************************************************************/

char *Specials::get_code_str()
{
   return code_string.str_show();
}


/***********************************************************************
 ** edit_code_str - like get_long_input for the code string
 **
 ** Parameters: the_builder - the builder who is editing the code string
 **
 ** Returns: the start_editor output 
 **          -1 if failed
 **
 ***********************************************************************/
   
int Specials::edit_code_str(Builder *the_builder)
{ 
   Editor *input_editor;

   input_editor = new Editor(code_string.str_show());
   return input_editor->start_editor((MudObject *) the_builder, 
                                                           &code_string);
}


/***********************************************************************
 ** edit_comments - like get_long_input for the comments string
 **
 ** Parameters: the_builder - the builder who is editing the comments
 **
 ** Returns: the start_editor output 
 **          -1 if failed
 **
 ***********************************************************************/
   
int Specials::edit_comments(Builder *the_builder)
{ 
   Editor *input_editor;

   input_editor = new Editor(comments.str_show());
   return input_editor->start_editor((MudObject *) the_builder, 
                                                           &comments);
}


/***********************************************************************
 ** get_activation - gets the activation time
 **
 ** Parameters: Nothing
 **
 ** Returns: the activation time
 **
 ***********************************************************************/

time_t Specials::get_activation()
{
   return activation;
}


/***********************************************************************
 ** get_interval - gets the interval between specials activation
 **
 ** Parameters: Nothing
 **
 ** Returns: the activation time
 **
 ***********************************************************************/

time_t Specials::get_interval()
{
   return interval;
}


/***********************************************************************
 ** get_activation - gets the activation time
 **
 ** Parameters: Nothing
 **
 ** Returns: the activation time
 **
 ***********************************************************************/

int Specials::get_num_times()
{
   return num_times;
}


/***********************************************************************
 ** read_code_type - reads in a code listing
 **
 ** Parameters: read_file - the file to read in from
 **             error_log - the error log to write any errors to
 **             the_obj - the object that we are getting from
 **
 ** Returns: a pointer to the created string
 **
 ***********************************************************************/

char *Specials::read_code_type(FILE *read_file)
{
   token_record *the_token;
   token_record *temp_tok;
   int size = 0;
   char *temp_code;
   Strings holder;
   int first = 1;

   
   /* get the location description and get its size, how many characters */
   the_token = get_token(read_file, '#');
   temp_tok = the_token;
   while (temp_tok != NULL)
   {
      size = size + strlen(temp_tok->the_string) + 1;
      temp_tok = temp_tok->more;  
   }


   /* create the code array given the size we need to store, efficient
      use of memory by dynamically allocating it based on size. We use this
      instead of the method provided by strings since this is more efficient
      to do one malloc instead of a malloc and destroy for each additional
      line in the code. */
   temp_code = new char[size + 2];
   BZERO(temp_code, size + 2);

   /* load the code strings into the array */
   temp_tok = the_token;
   while (temp_tok != NULL)
   {
      /* remove the preceeding newline */
      if (!first)
      {
         strcat(temp_code, temp_tok->the_string);
         strcat(temp_code, "\n");
      }
      else
      {
         char *tmp_str;

         tmp_str = temp_tok->the_string;
         while ((*tmp_str) && (*tmp_str == ' '))
          tmp_str++;

         if ((*tmp_str) && (*tmp_str != '\n') && 
             (*tmp_str != '\r') && (*tmp_str != '\0'))
       {
            strcat(temp_code, temp_tok->the_string);
            strcat(temp_code, "\n");
         }
         first = 0;
      }
      temp_tok = temp_tok->more;
   }

   return temp_code;
}


/***********************************************************************
 ** write_object - writes the special to a file
 **
 ** Parameters: the_file - the file to write to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::write_object(FILE *the_file, int build_format)
{
   fprintf(the_file, "\nspecial %s\n", get_name());
   if (build_format)
      fprintf(the_file, "%d\n", is_modified());
   fprintf(the_file, "%s\n", get_trigger());
   fprintf(the_file, "%lu\n", get_activation());
   fprintf(the_file, "%lu\n", get_interval());
   fprintf(the_file, "%d\n", get_num_times());
   fprintf(the_file, "%ld\n", get_counter());
   fprintf(the_file, "^\n%s^\n", (get_code_str() == NULL) ? "" : 
                                                          get_code_str());
   fprintf(the_file, "^\n%s^\n", (get_comments() == NULL) ? "" : 
                                                          get_comments());
}



/***********************************************************************
 ** describe - displays a special to the user
 **
 ** Parameters: the_builder - the builder to send all this to
 **             spec_num - the special sequence in the list
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::describe(Builder *the_builder)
{
   Strings holder;

   the_builder->send_bldr("&+W\nName: \t\t\t%s&*\n", get_name());
   the_builder->send_bldr("&+MTrigger: &+G\t\t%s\n", get_trigger());
   the_builder->send_bldr("&+GActivation: \t\t&*%lu\n", get_activation());
   the_builder->send_bldr("&+GInterval: \t\t&*%lu\n", get_interval());
   the_builder->send_bldr("&+GNum Times: \t\t&*%d\n", get_num_times());
   the_builder->send_bldr("&+GCounter: \t\t&*%d\n", get_counter());

   the_builder->send_bldr("&+GComments: &*\n%s\n", 
                    (comments.str_show() == NULL) ? "" : comments.str_show());

   holder = get_code_str();
   the_builder->send_bldr("&+GCode: &*\n%s\n", 
                    (holder.str_show() == NULL) ? "" : holder.str_show());
   return;
}


/***********************************************************************
 ** describe - displays a special to the user
 **
 ** Parameters: the_builder - the builder to send all this to
 **             spec_num - the special sequence in the list
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::describe(Player *the_player)
{
   the_player->send_plr("&+W\nName: \t\t\t%s&*\n", get_name());
   the_player->send_plr("&+MTrigger: &+G\t\t%s\n", get_trigger());
   the_player->send_plr("&+GActivation: \t\t&*%lu\n", get_activation());
   the_player->send_plr("&+GInterval: \t\t&*%lu\n", get_interval());
   the_player->send_plr("&+GNum Times: \t\t&*%d\n", get_num_times());
   the_player->send_plr("&+GCounter: \t\t&*%d\n", get_counter());

   the_player->send_plr(
        "&+GComments: &+gComments only viewable on builder port&*\n");
   the_player->send_plr(
        "&+GCode: &+gCode only viewable on builder port&*\n");
   the_player->send_plr("&+YSize: \t\t\t&+W%d&*\n", get_mem_size());
   return;
}


/***********************************************************************
 ** copy_special - copies special info from copy_from to this special
 **
 ** Parameters: copy_obj - the special we are copying from
 **
 ** Returns: 1 if successful, -1 if failed
 **
 ***********************************************************************/

int Specials::copy_object(Entity *copy_obj)
{
   Specials *copy_from;

   if (copy_obj->get_type() != OBJ_TYPE_SPECIAL)
      return 0;

   copy_from = (Specials *) copy_obj;

   set_trigger(copy_from->get_trigger());
   set_activation_date(copy_from->get_num_times());
   set_interval(copy_from->get_num_times());
   set_num_times(copy_from->get_num_times());
   set_counter(copy_from->get_counter());
   set_comments(copy_from->get_comments());

   if (copy_from->get_code_str() != NULL)
      set_code_str(copy_from->get_code_str());
   else
   {
      the_code = copy_from->copy_code();
      var_list = copy_from->copy_var_list();
   }
   return 1;
}


/***********************************************************************
 ** copy_code - copies the code list
 **
 ** Parameters: None
 **
 ** Returns: A pointer to the new list if successful, NULL if not
 **
 ***********************************************************************/

Code *Specials::copy_code()
{
   Code *new_list = NULL;
   Code *new_code;
   Code *next_code;
   Code *last_added = NULL;

   next_code = the_code;
   while (next_code != NULL)
   {
      new_code = new Code(next_code->get_funct_ptr());
      new_code->copy_code(next_code);
      if (last_added == NULL)
      {
         new_list = new_code;
         last_added = new_code;
      }
      else
      {
         last_added->set_next_code(new_code);
         last_added = new_code;
      }
      next_code = next_code->get_next_code();
   }
   return new_list;
}


/***********************************************************************
 ** copy_var_list - copies the var list, passing it back
 **
 ** Parameters: None
 **
 ** Returns: A pointer to the new list if successful, NULL if not
 **
 ***********************************************************************/

vars *Specials::copy_var_list()
{
   vars *new_list = NULL;
   vars *new_var;
   vars *next_var;
   vars *last_added = NULL;

   next_var = var_list;
   while (next_var != NULL)
   {
      new_var = new_vars();
      new_var->next_var = NULL;
      new_var->varname = next_var->varname.str_show();
      new_var->vartype = next_var->vartype;

      switch(next_var->vartype)
      {
         case VAR_TYPE_STRING:
         case VAR_TYPE_OBJNAME:
         case VAR_TYPE_VAR:
            new_var->the_ptr.a_string = 
                     new Strings(next_var->the_ptr.a_string->str_show());
            break;
         case VAR_TYPE_INT:
            new_var->the_ptr.an_int = new long;
            *(new_var->the_ptr.an_int) = *(next_var->the_ptr.an_int);
            break;

         case VAR_TYPE_CODE:
            new_var->the_ptr.a_code = 
                new Code(next_var->the_ptr.a_code->get_funct_ptr());
            new_var->the_ptr.a_code->copy_code(next_var->the_ptr.a_code);
            break;

         case VAR_TYPE_GOTO:
            new_var->the_ptr.goto_code = next_var->the_ptr.goto_code;
            break;

         default: return NULL;
      }
      if (last_added == NULL)
      {
         new_list = new_var;
         last_added = new_var;
      }
      else
      {
         last_added->next_var = new_var;
         last_added = new_var;
      }

      next_var = next_var->next_var;
   }
   return new_list;
}


/***********************************************************************
 ** set_counter - sets the counter to a certain value
 **
 ** Parameters: the_val - the value to set it to
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Specials::set_counter(long the_val)
{
   counter = the_val;
}


/***********************************************************************
 ** get_counter - gets the current counter value
 **
 ** Parameters: None
 **
 ** Returns: the counter value
 **
 ***********************************************************************/

long Specials::get_counter()
{
   return counter;
}


/***********************************************************************
 ** set_attrib_trigger - for set attribute command, sets the trigger attribute
 **
 ** Parameters: the_parsed - the parsed list from the user
 **             the_builder - the builder doing this command
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Specials::set_attrib_trigger(Parse *the_parsed, Builder *the_builder)
{
   if (the_parsed->get_speech() == NULL)
   {
      the_builder->send_bldr("You need to specify a trigger to set to.\n");
      return -1;
   }
   set_trigger(the_parsed->get_speech());
   the_builder->send_bldr("Trigger on special %s set to: %s\n", get_name(), 
                                                        get_trigger());
   set_modified(1);
   return 1;
}


/***********************************************************************
 ** set_attrib - sets a specified attribute to a specified value
 **
 ** Parameters: the_builder - the builder who is changing this attribute
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/
   
int Specials::set_attrib(Builder *the_builder, Parse *the_parsed){

   if (the_parsed->get_target1() == NULL)
   {   the_builder->
           send_bldr("You can set the following attributes on a special.\n"
       "   code, counter");
       return -1;
   }
   if (!STRNCASECMP(the_parsed->get_target1(), "code",
                    strlen(the_parsed->get_target1())))
   {
      return set_special(the_builder);
   }
   if (!STRNCASECMP(the_parsed->get_target1(), "counter",
                    strlen(the_parsed->get_target1())))
   {
      return set_special_counter(the_builder, the_parsed);
   }
   if (!STRNCASECMP(the_parsed->get_target1(), "trigger",
                    strlen(the_parsed->get_target1())))
   {
      return set_attrib_trigger(the_parsed, the_builder);
   }
   if (!STRNCASECMP(the_parsed->get_target1(), "comments",
                    strlen(the_parsed->get_target1())))
   {
      return set_attrib_comments(the_builder);
   }

   the_builder->send_bldr("The attribute '%s' is not a specials attribute.\n",
                                           the_parsed->get_target1());
   return -1;
}


/***********************************************************************
 ** set_specials - sets attributes in the specials
 **
 ** Parameters: the_text - the text that is the trigger
 **
 ** Returns: 1 if success, -1 if failure
 **
 ***********************************************************************/

int Specials::set_special(Builder *the_builder)
{
   if (edit_code_str(the_builder) < 0)
   {
      the_builder->send_bldr("Error reading in input, failed!\n");
      return -1;
   }  
   set_modified(1);

   return 1;
}



/***********************************************************************
 ** set_attrib_comments - sets attributes in the specials
 **
 ** Parameters: the_builder - the builder who is setting the comments
 **
 ** Returns: 1 if success, -1 if failure
 **
 ***********************************************************************/

int Specials::set_attrib_comments(Builder *the_builder)
{
   if (edit_comments(the_builder) < 0)
   {
      the_builder->send_bldr("Error reading in input, failed!\n");
      return -1;
   }  
   set_modified(1);

   return 1;
}


/***********************************************************************
 ** set_special_counter - sets counter attributes in the specials
 **
 ** Parameters: the_text - the text that is the trigger
 **
 ** Returns: 1 if success, -1 if failure
 **
 ***********************************************************************/

int Specials::set_special_counter(Builder *the_builder, Parse *the_parsed)
{
   Strings        tmp_str;
   Strings        tmp_word;
   long           value;

   tmp_str = the_parsed->get_speech();

   tmp_word.assign_word(tmp_str.str_show(),1);
 
   if (tmp_word.str_show() == NULL)
   {
      the_builder->send_bldr("Usage: set counter <value>\n");
      return -1;
   }

   if (isdigit(*(tmp_word.str_show())))
   {  
      value = atol(tmp_word.str_show());
   }
   else
   {  the_builder->send_bldr("Usage: set counter <value>\n");
      return -1;
   }
   
   set_counter(value);
   the_builder->send_bldr("Counter value for special '&+c%s&*' "
                           "set to &+W%d&*\n", get_name(), get_counter());
   
   set_modified(1);

   return 1;
}


/***********************************************************************
 ** read_specials_attrib - reads in specials attributes from the file
 **
 ** Parameters: read_file - the file to read in from
 **             error_log - the error log to write any errors to
 **             build_format - do we read this in as a builder save?
 **             is_build_port - are we reading for the builder port?
 **
 ** Returns:  1 for successful read
 **          -1 for errors in the read
 **
 ***********************************************************************/

int Specials::read_specials_attrib(FILE *read_file, ErrLog *error_log, 
                                       int build_format, int is_build_port)
{
   token_record *the_token;
   Strings      holder;
   char         *tmp_str;
   char         *temp_desc;

   /* if this is in builder format, then read in the modified attrib */
   if (build_format)
   {
      the_token = get_token(read_file, '\0');
     
      if (the_token->token_type != T_NUMERICAL)
      {
         holder.sprintf("Invalid format in special %s@%s", get_name(),
                                                              get_area());
         error_log->log_err(holder.str_show(), "read_specials_attrib");
         return -1;
      }
  
      set_modified(atoi(the_token->the_string));
   }

   /* get the trigger of this special */
   the_token = get_token(read_file, '\0');
   set_trigger(the_token->the_string);   

   /* get activation time */
   the_token = get_token(read_file, '\0');
   if (the_token->token_type != T_NUMERICAL)
   {
      holder.sprintf("Invalid format for special %s@%s", 
                                                    get_name(), get_area());
      error_log->log_err(holder.str_show(), "read_specials_attrib");
      return -1;
   }

   set_activation_date(strtoul(the_token->the_string, &tmp_str, 0));
   
   /* get interval between activations */
   the_token = get_token(read_file, '\0');
   if (the_token->token_type != T_NUMERICAL)
   {
      holder.sprintf("Invalid format for special %s@%s", 
                                                get_name(), get_area());
      error_log->log_err(holder.str_show(), "read_specials_attrib");
      return -1;
   }

   set_interval(strtoul(the_token->the_string, &tmp_str, 0));

   /* get num of times this should activate */
   the_token = get_token(read_file, '\0');
   if (the_token->token_type != T_NUMERICAL)
   {
      holder.sprintf("Invalid format for special %s@%s", 
                                                     get_name(), get_area());
      error_log->log_err(holder.str_show(), "read_specials_attrib");
      return -1;
   }

   set_num_times(atoi(the_token->the_string));


   /* get the counter value */
   the_token = get_token(read_file, '\0');
   if (the_token->token_type != T_NUMERICAL)
   {
      holder.sprintf("Invalid format for special %s@%s",
                                                get_name(), get_area());
      error_log->log_err(holder.str_show(), "read_specials_attrib");
      return -1;
   }

   set_counter(atol(the_token->the_string));

   if (read_code(read_file, error_log, is_build_port) <= 0)
   {
      holder.sprintf("Invalid format for special %s@%s",
                                                get_name(), get_area());
      error_log->log_err(holder.str_show(), "read_specials_attrib");
      return -1;
   }

   /* get the descriptions */
   temp_desc = read_desc_type(read_file, error_log, this);
   
   if (temp_desc == NULL)
      return -1;
   set_comments(temp_desc);
   delete temp_desc;

   return 1;
}


/***********************************************************************
 ** get_mem_size - gets how much memory this special is taking up
 **
 ** Returns: mem size in bytes
 **
 ***********************************************************************/

int Specials::get_mem_size()
{
   int size = 0;

   size = sizeof(this);
   size += get_mem_size_dynamic();
   return size;
}

/***********************************************************************
 ** get_mem_size_dynamic - gets how much memory is taken up by pointers
 **                        pointing to other objects, not including the
 **                        sizeof(this)
 **
 ** Returns: mem size in bytes
 **
 ***********************************************************************/

int Specials::get_mem_size_dynamic()
{
   int  size = 0;
   Code *tmp_code;  
   vars *tmp_var;

   size += triggername.get_mem_size_dynamic();

   tmp_code = the_code;
   while (tmp_code != NULL)
   {
      size += tmp_code->get_mem_size();
      tmp_code = tmp_code->get_next_code();
   }
   
   tmp_var = var_list;
   while (tmp_var != NULL)
   {
      size += sizeof(tmp_var);
      size += tmp_var->varname.get_mem_size_dynamic();

      switch (tmp_var->vartype)
      {
         case VAR_TYPE_STRING:
         case VAR_TYPE_OBJNAME:
         case VAR_TYPE_VAR:
            size += tmp_var->the_ptr.a_string->get_mem_size_dynamic();
            break;

         case VAR_TYPE_CODE:
            size += tmp_var->the_ptr.a_code->get_mem_size();
            break;

         case VAR_TYPE_INT:
            size += sizeof((*tmp_var->the_ptr.an_int));
            break;
         default:
            break;
      }
      tmp_var = tmp_var->next_var;
   }
   size += code_string.get_mem_size_dynamic();
   
   return size;
}


/***********************************************************************
 ** disp_time_stats - displays the special's time stats in line format
 **                   to the player
 **
 ** Params: the_player - the player we should send the message to
 **
 ***********************************************************************/

void Specials::disp_time_stats(Player *the_player)
{
   char tmp_line[100];
   Strings holder;
   long min_time = 0;
   holder = get_name();
   if (holder.str_len() > 14)
      holder.truncate(14);

   if (min_exe == 10000)
      min_time = 0;
   else
      min_time = min_exe;

   sprintf(tmp_line, "%-15s  %7ld %7ld %7ld %7ld\n", 
           holder.str_show(), num_exe, min_time, max_exe, avg_exe);

   the_player->send_plr("%s", tmp_line);
}

#endif















Generated by  Doxygen 1.6.0   Back to index