SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 1
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)



    1        	/*** Include these files for Bub's VMS list_files () ***/
    2        	#include <descrip.h>
  435        	#include <rmsdef.h>
 1041        	
 1042        	#include <types.h>
 1051        	#include <stat.h>
 1100        	#include "dir.h"
 1173        	#include <setjmp.h>
 1192        	#include <string.h>
 1238        	#include <errno.h>
 1337        	#include <stdio.h>
 1567        	#include "lint.h"
 1688        	#include "config.h"
 1977        	/* What is this? (bub) */
 1978        	/*#include "stdio.h"*/
 1979        	#include "lnode.h"
 2120        	#include "y-tab.h"
 2302        	#include "interpret.h"
 2371        	#include "object.h"
 2447        	#include "sent.h"
 2461        	#include "wiz_list.h"
 2486        	
 2487        	/*** Who forgot this? (bub) ***/
 2488        	#include <perror.h>
 2501        	
 2502        	extern int errno, current_time;
 2503        	
 2504        	char *inherit_file;
 2505        	
 2506        	extern char *xalloc (), *string_copy (), *dump_trace (), *check_file_name (),
 2507        	*xalloc ();
 2508        	
 2509        	extern struct value *catch_value;
 2510        	char *last_verb;
 2511        	
 2512        	extern int special_parse PROT ((char *)), yyparse (),
 2513        	 set_call PROT ((struct object *, struct sentence *, int)),
 2514        	 parse_command PROT ((char *, struct object *, int)),
 2515        	 legal_path PROT ((char *)), print_call_out_usage ();
 2516        	
 2517        	char *read_file PROT ((char *, int));
 2518        	void pre_compile PROT ((char *)),
 2519        	 remove_interactive PROT ((struct object *)),
 2520        	 add_light PROT ((struct object *, int)),
 2521        	 do_write PROT ((struct value *)), add_action PROT ((char *, char *, int)),
 2522        	 add_verb PROT ((char *, int)),
 2523        	 print_local_commands (), ipc_remove (),
 2524        	 show_info_about PROT ((char *, char *, struct interactive *)),
 2525        	 ed_start PROT ((char *)), say PROT ((struct value *, struct object *)),
 2526        	 set_snoop PROT ((struct object *, struct object *)),
 2527        	 tell_room PROT ((struct object *, struct value *)),
 2528        	 print_lnode_status PROT ((int)),
 2529        	 remove_all_players (), start_new_file (),
 2530        	 move_or_destruct PROT ((struct object *, struct object *)),
 2531        	 startshutdowngame (),

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 2
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2532        	 load_ob_from_swap PROT ((struct object *)), dump_malloc_data (),
 2533        	 dump_all_objects (),
 2534        	 debug_message_value ();
 2535        	
 2536        	struct value *contents (), *search_array ();
 2537        	
 2538        	extern struct value *allocate_array ();
 2539        	
 2540        	extern int d_flag;
 2541        	
 2542        	struct object *obj_list, *obj_list_destruct;
 2543        	
 2544        	extern struct object *get_interactive_object PROT ((int));
 2545        	extern int current_line;
 2546        	
 2547        	struct object *current_object;	/* The object interpreting a function. */
 2548        	struct object *command_giver;	/* Where the current command came from. */
 2549        	
 2550        	int num_parse_error;		/* Number of errors in the parser. */
 2551        	
 2552        	void shutdowngame ();
 2553        	
 2554        	
 2555        	extern FILE *vpopen_grep ();
 2556        	
 2557        	#define GREP "/bin/grep"
 2558        	
 2559        	void
 2560        	grep_file (options, regexp, path)
 2561        	     char *path, *options, *regexp;
 2562        	{
 2563    1   	  char buff[500];
 2564    1   	  char buff2[100];
 2565    1   	  FILE *f;
 2566    1   	  int i;
 2567    1   	
 2568    1   	  if (!path)
 2569    1   	    error ("File name required to grep()\n");
 2570    1   	  path = check_file_name (path, 0);
 2571    1   	  if (path == 0)
 2572    1   	    return;
 2573    1   	  if (strchr (options, ' ') || strchr (options, 'f'))
 2574    1   	    error ("Bad argument 1 to grep()\n");
 2575    1   	  if (regexp[0] == 0)
 2576    1   	    error ("Bad argument 2 to grep()\n");
 2577    1   	  strcpy (buff2, "-");
 2578    1   	  strncat (buff2, options, (sizeof buff2) - 2);
 2579    1   	  if (options[0] == 0)
 2580    1   	    f = vpopen_grep (GREP, regexp, path, 0, "r");
 2581    1   	  else
 2582    1   	    f = vpopen_grep (GREP, buff2, regexp, path, "r");
 2583    1   	  if (f == 0)
 2584    1   	    return;
 2585    1   	  for (i = 0; i < MAX_LINES; i++)
 2586    1   	    {
 2587    2   	      if (fgets (buff, sizeof (buff), f) == 0)
 2588    2   		break;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 3
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2589    2   	      add_message ("%s", buff);
 2590    2   	    }
 2591    1   	  if (i == MAX_LINES)
 2592    1   	    add_message ("*****TRUNCATED*****\n");
 2593    1   	  vpclose (f);
 2594    1   	}
 2595        	
 2596        	struct svalue *
 2597        	find_value (p)
 2598        	     struct lnode_variable *p;
 2599        	{
 2600    1   	  if (p->number >= current_object->num_variables)
 2601    1   	    {
 2602    2   	      dump_trace ();
 2603    2   	      fatal ("Illegal variable access %d(%d). See trace above.\n",
 2604    2   		     p->number, current_object->num_variables);
 2605    2   	    }
 2606    1   	  return &current_object->variables[p->number];
 2607    1   	}
 2608        	
 2609        	struct lnode_var_def *
 2610        	find_status (str, must_find)
 2611        	     char *str;
 2612        	     int must_find;
 2613        	{
 2614    1   	  struct lnode_var_def *p;
 2615    1   	
 2616    1   	  for (p = current_object->status; p; p = p->next)
 2617    1   	    {
 2618    2   	      if (strcmp (p->name, str) == 0)
 2619    2   		return p;
 2620    2   	    }
 2621    1   	  if (!must_find)
 2622    1   	    return 0;
 2623    1   	  error ("--Status %s not found in prog for %s\n", str,
 2624    1   		 current_object->name);
 2625    1   	  return 0;
 2626    1   	}
 2627        	
 2628        	/*
 2629        	 * Save the name of the current .i file, so we are able to remove it
 2630        	 * if it contains illegal include files.
 2631        	 */
 2632        	char *current_i_file;
 2633        	
 2634        	void
 2635        	remove_i_file ()
 2636        	{
 2637    1   	  unlink (current_i_file);
 2638    1   	}
 2639        	
 2640        	/*
 2641        	 * Load an object definition from file. If the object wants to inherit
 2642        	 * from an object that is not loaded, discard all, load the inherited object,
 2643        	 * and reload again.
 2644        	 *
 2645        	 * Save the command_giver, because reset() in the new object might change

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 4
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2646        	 * it.
 2647        	 */
 2648        	struct object *
 2649        	load_object (lname)
 2650        	     char *lname;
 2651        	{
 2652    1   	  FILE *f;
 2653    1   	  extern int total_lines;
 2654    1   	
 2655    1   	  struct object *ob, *save_command_giver = command_giver;
 2656    1   	  extern struct lnode *prog, *heart_beat;
 2657    1   	  extern char *current_file;
 2658    1   	  extern int variable_count, static_variable_flag;
 2659    1   	  extern struct object *inherit_ob;
 2660    1   	  struct stat i_st, c_st;
 2661    1   	  int i, name_length;
 2662    1   	  char real_name[200], name[200];
 2663    1   	
 2664    1   	  /* Remove leading '/' if any. */
 2665    1   	  while (lname[0] == '/')
 2666    1   	    lname++;
 2667    1   	  /*
 2668    1   	   * We must clear inherit_ob, to be sure it is initialized to 0.
 2669    1   	   * It can still be pointing to something, where an error aborted
 2670    1   	   * execution.
 2671    1   	   */
 2672    1   	  inherit_ob = 0;
 2673    1   	  /* Truncate possible .c in the object name. */
 2674    1   	  strncpy (name, lname, sizeof (name) - 1);
 2675    1   	  name_length = strlen (name);
 2676    1   	  if (name_length > sizeof name - 4)
 2677    1   	    name_length = sizeof name - 4;
 2678    1   	  name[name_length] = '\0';
 2679    1   	  if (name[name_length - 2] == '.' && name[name_length - 1] == 'c')
 2680    1   	    {
 2681    2   	      name[name_length - 2] = '\0';
 2682    2   	      name_length -= 2;
 2683    2   	    }
 2684    1   	  /*
 2685    1   	   * First check that the c-file exists.
 2686    1   	   */
 2687    1   	  (void) strcpy (real_name, name);
 2688    1   	  (void) strcat (real_name, ".c");
 2689    1   	  if (stat (real_name, &c_st) == -1)
 2690    1   	    {
 2691    2   	      fprintf (stderr, "Could not load descr for %s\n", real_name);
 2692    2   	      error ("Failed to load file.\n");
 2693    2   	      return 0;
 2694    2   	    }
 2695    1   	  /*
 2696    1   	   * Check if it's a legal name.
 2697    1   	   */
 2698    1   	  if (!legal_path (real_name))
 2699    1   	    {
 2700    2   	      fprintf (stderr, "Illegal pathname: %s\n", real_name);
 2701    2   	      error ("Illegal path name.\n");
 2702    2   	      return 0;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 5
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2703    2   	    }
 2704    1   	  /*
 2705    1   	   * Now check if the i-file is newer or nonexisting.
 2706    1   	   */
 2707    1   	  real_name[name_length + 1] = 'i';
 2708    1   	  if (stat (real_name, &i_st) == -1 || i_st.st_mtime < c_st.st_mtime)
 2709    1   	    {
 2710    2   	      real_name[name_length + 1] = 'c';
 2711    2   	      pre_compile (name);
 2712    2   	      real_name[name_length + 1] = 'i';
 2713    2   	    }
 2714    1   	  if (stat (real_name, &i_st) == -1 || i_st.st_mtime < c_st.st_mtime)
 2715    1   	    {
 2716    2   	      if (command_giver)
 2717    2   		add_message ("Failed to compile the new file.\n");
 2718    2   	    }
 2719    1   	  current_i_file = real_name;
 2720    1   	  f = fopen (real_name, "r");
 2721    1   	  if (f == 0)
 2722    1   	    {
 2723    2   	      perror (real_name);
 2724    2   	      error ("Could not read the file.\n");
 2725    2   	    }
 2726    1   	  start_new_file (f);
 2727    1   	  current_file = string_copy (real_name);	/* This one is freed below */
 2728    1   	  current_line = 0;
 2729    1   	  prog = heart_beat = 0;
 2730    1   	  prog_status = 0;
 2731    1   	  variable_count = 0;
 2732    1   	  num_parse_error = 0;
 2733    1   	  static_variable_flag = 0;
 2734    1   	  (void) yyparse ();
 2735    1   	  update_compile_av (total_lines);
 2736    1   	  total_lines = 0;
 2737    1   	  (void) fclose (f);
 2738    1   	#ifdef REMOVE_I_FILES
 2739   X    	  unlink (current_i_file);
 2740    1   	#else
 2741    1   	  /*
 2742    1   	   * Remove the i-file if there was an error. This
 2743    1   	   * is necessary, to protect against security problems.
 2744    1   	   */
 2745    1   	  if (num_parse_error)
 2746    1   	    unlink (current_i_file);
 2747    1   	#endif
 2748    1   	  free (current_file);
 2749    1   	  current_file = 0;
 2750    1   	  current_i_file = 0;
 2751    1   	  if (inherit_file == 0 && (num_parse_error > 0 || prog == 0))
 2752    1   	    {
 2753    2   	      if (inherit_file)
 2754    2   		{
 2755    3   		  inherit_file = 0;
 2756    3   		  free (inherit_file);
 2757    3   		}
 2758    2   	      if (prog)
 2759    2   		{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 6
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2760    3   		  /*
 2761    3   	           * Set the reference count to one.
 2762    3   	           * We don't want to confuse free_prog().
 2763    3   	           */
 2764    3   		  add_prog_ref ((struct lnode_def *) prog);
 2765    3   		  if (!free_prog ((struct lnode_def *) prog, 0, 0))
 2766    3   		    fatal ("Failed to release prog area.\n");
 2767    3   		}
 2768    2   	      if (num_parse_error == 0 && prog == 0)
 2769    2   		error ("No program in object !\n");
 2770    2   	      error ("Error in loading object\n");
 2771    2   	    }
 2772    1   	  if (inherit_file)
 2773    1   	    {
 2774    2   	      char *tmp = inherit_file;
 2775    2   	      if (prog)
 2776    2   		{
 2777    3   		  /*
 2778    3   	           * Set the reference count to one.
 2779    3   	           * We don't want to confuse free_prog().
 2780    3   	           */
 2781    3   		  add_prog_ref ((struct lnode_def *) prog);
 2782    3   		  if (!free_prog ((struct lnode_def *) prog, 0, 0))
 2783    3   		    fatal ("Failed to release prog area.\n");
 2784    3   		  prog = 0;
 2785    3   		}
 2786    2   	      if (strcmp (inherit_file, name) == 0)
 2787    2   		{
 2788    3   		  free (inherit_file);
 2789    3   		  inherit_file = 0;
 2790    3   		  error ("Illegal to inherit self.\n");
 2791    3   		}
 2792    2   	      inherit_file = 0;
 2793    2   	      load_object (tmp);
 2794    2   	      free (tmp);
 2795    2   	      ob = load_object (name);
 2796    2   	      return ob;
 2797    2   	    }
 2798    1   	  ob = get_empty_object (variable_count);
 2799    1   	  if (inherit_ob)
 2800    1   	    {
 2801    2   	      if (strcmp (inherit_ob->name, name) == 0)
 2802    2   		{
 2803    3   		  free ((char *) ob);
 2804    3   		  inherit_ob = 0;
 2805    3   		  error ("Illegal to inherit self.\n");
 2806    3   		}
 2807    2   	      ob->inherit = inherit_ob;
 2808    2   	      inherit_ob->inherited = 1;
 2809    2   	      add_ref (inherit_ob, "load_object inherit");
 2810    2   	      if (ob->heart_beat == 0)
 2811    2   		ob->heart_beat = inherit_ob->heart_beat;
 2812    2   	      inherit_ob = 0;
 2813    2   	    }
 2814    1   	  ob->name = string_copy (name);
 2815    1   	  ob->name_length = strlen (name);
 2816    1   	  /* Is this object wizard defined ? */

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 7
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2817    1   	  {
 2818    2   	    char wiz_name[100];
 2819    2   	    if (sscanf (real_name, "players/%s", wiz_name) == 1)
 2820    2   	      {
 2821    3   		char *np;
 2822    3   		np = strchr (wiz_name, '/');
 2823    3   		if (np)
 2824    3   		  *np = '\0';
 2825    3   		ob->wl = add_name (wiz_name);
 2826    3   	      }
 2827    2   	    else
 2828    2   	      {
 2829    3   		ob->wl = 0;
 2830    3   	      }
 2831    2   	  }
 2832    1   	#if 0
 2833   X    	  /* No longer here. It is done in get_empty_object() */
 2834   X    	  /* Allocate space for local variables. */
 2835   X    	  if (variable_count > 0)
 2836   X    	    ob->variables =
 2837   X    	      (struct svalue *) xalloc (variable_count * sizeof (struct svalue));
 2838   X    	  ob->num_variables = variable_count;
 2839   X    	  /* Initialize variables... */
 2840   X    	  for (i = 0; i < variable_count; i++)
 2841   X    	    {
 2842   X    	      ob->variables[i].u.number = 0;
 2843   X    	      ob->variables[i].type = T_NUMBER;
 2844   X    	    }
 2845    1   	#endif
 2846    1   	  ob->status = prog_status;
 2847    1   	  if (prog)
 2848    1   	    {
 2849    2   	      ob->prog = (struct lnode_def *) prog;
 2850    2   	      add_prog_ref ((struct lnode_def *) prog);
 2851    2   	    }
 2852    1   	  else
 2853    1   	    {
 2854    2   	      ob->prog = 0;
 2855    2   	    }
 2856    1   	  ob->next_all = obj_list;
 2857    1   	  obj_list = ob;
 2858    1   	  if (heart_beat)
 2859    1   	    ob->heart_beat = heart_beat;
 2860    1   	  enter_object_hash (ob);	/* add name to fast object lookup table */
 2861    1   	  ob->reset = 1;
 2862    1   	  ob->last_reset = current_time;
 2863    1   	  (void) apply ("reset", ob, 0);
 2864    1   	  command_giver = save_command_giver;
 2865    1   	  if (d_flag)
 2866    1   	    debug_message ("--%s loaded\n", ob->name);
 2867    1   	#if NUM_RESET_TO_SWAP > 0
 2868    1   	  swap (ob);
 2869    1   	#endif
 2870    1   	  return ob;
 2871    1   	}
 2872        	
 2873        	struct object *previous_ob;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 8
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2874        	extern struct lnode_2 *next_arg_list_to_use;
 2875        	
 2876        	/*
 2877        	 * Call function in another object. The object can be given both as a string
 2878        	 * and a pointer.
 2879        	 *
 2880        	 * Save the caller object in previous_ob, so some functions can
 2881        	 * see who called them.
 2882        	 *
 2883        	 * If find_object() is called, the object might be non-existing, and
 2884        	 * thus loaded. If the object is loaded, "reset" will be called in the object.
 2885        	 * next_arg_list_to_use must be hidden, so that the reset() won't
 2886        	 * get these arguments.
 2887        	 */
 2888        	struct value *
 2889        	call_other (obj, name, arg)
 2890        	     struct value *obj;
 2891        	     char *name;
 2892        	     struct value *arg;
 2893        	{
 2894    1   	  struct object *ob, *save_command_giver = command_giver;
 2895    1   	  struct value *ret;
 2896    1   	
 2897    1   	  if (obj->type == T_OBJECT)
 2898    1   	    {
 2899    2   	      ob = obj->u.ob;
 2900    2   	    }
 2901    1   	  else
 2902    1   	    {
 2903    2   	      struct lnode_2 *save_args = next_arg_list_to_use;
 2904    2   	      next_arg_list_to_use = 0;
 2905    2   	      ob = find_object (obj->u.string);
 2906    2   	      next_arg_list_to_use = save_args;
 2907    2   	    }
 2908    1   	  if (ob == 0)
 2909    1   	    error ("Could not find object %s\n", obj);
 2910    1   	  /*
 2911    1   	   * Test if this really is an existing object.
 2912    1   	   */
 2913    1   	  if (ob->reset == 0)
 2914    1   	    {
 2915    2   	      next_arg_list_to_use = 0;
 2916    2   	      return &const0;
 2917    2   	    }
 2918    1   	  if (ob->last_reset < (current_time - RESET_TIME * 60))
 2919    1   	    {
 2920    2   	      struct lnode_2 *save_args = next_arg_list_to_use;
 2921    2   	      next_arg_list_to_use = 0;
 2922    2   	      ob->last_reset = current_time;
 2923    2   	      (void) apply ("reset", ob, &const1);
 2924    2   	      next_arg_list_to_use = save_args;
 2925    2   	      command_giver = save_command_giver;
 2926    2   	      if (ob->destructed)
 2927    2   		{
 2928    3   		  next_arg_list_to_use = 0;
 2929    3   		  return &const0;
 2930    3   		}

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 9
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2931    2   	    }
 2932    1   	  ret = apply (name, ob, arg);
 2933    1   	  command_giver = save_command_giver;
 2934    1   	  if (ret == 0)
 2935    1   	    return &const0;
 2936    1   	  return ret;
 2937    1   	}
 2938        	
 2939        	struct value *
 2940        	this_player ()
 2941        	{
 2942    1   	  struct value *p;
 2943    1   	
 2944    1   	  if (command_giver == 0 || command_giver->destructed)
 2945    1   	    return &const0;
 2946    1   	  p = alloc_value ();
 2947    1   	  p->type = T_OBJECT;
 2948    1   	  p->u.ob = command_giver;
 2949    1   	  add_ref (command_giver, "this_player()");
 2950    1   	  return p;
 2951    1   	}
 2952        	
 2953        	struct value *
 2954        	caller ()
 2955        	{
 2956    1   	  struct value *p;
 2957    1   	  extern struct object *frame_ob;
 2958    1   	
 2959    1   	  if (frame_ob == 0 || (frame_ob->destructed))
 2960    1   	    return &const0;
 2961    1   	  p = alloc_value ();
 2962    1   	  p->type = T_OBJECT;
 2963    1   	  p->u.ob = frame_ob;
 2964    1   	  add_ref (frame_ob, "caller()");
 2965    1   	  return p;
 2966    1   	}
 2967        	
 2968        	struct value *
 2969        	this_object ()
 2970        	{
 2971    1   	  struct value *p;
 2972    1   	
 2973    1   	  if (current_object->destructed)
 2974    1   	    return &const0;
 2975    1   	  p = alloc_value ();
 2976    1   	  p->type = T_OBJECT;
 2977    1   	  p->u.ob = current_object;
 2978    1   	  add_ref (current_object, "this_object()");
 2979    1   	  return p;
 2980    1   	}
 2981        	
 2982        	struct value *
 2983        	call_local_function (name, arg)
 2984        	     char *name;
 2985        	     struct value *arg;
 2986        	{
 2987    1   	  struct value *ret;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 10
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 2988    1   	
 2989    1   	  ret = apply (name, current_object, arg);
 2990    1   	  if (ret == 0)
 2991    1   	    error ("Local function %s not found.\n", name);
 2992    1   	  return ret;
 2993    1   	}
 2994        	
 2995        	char *
 2996        	make_new_name (str)
 2997        	     char *str;
 2998        	{
 2999    1   	  static int i;
 3000    1   	  char *p = xalloc (strlen (str) + 10);
 3001    1   	
 3002    1   	  (void) sprintf (p, "%s#%d", str, i);
 3003    1   	  i++;
 3004    1   	  return p;
 3005    1   	}
 3006        	
 3007        	/*
 3008        	 *
 3009        	 * Save the command_giver, because reset() in the new object might change
 3010        	 * it.
 3011        	 */
 3012        	struct value *
 3013        	clone_object (str1)
 3014        	     char *str1;
 3015        	{
 3016    1   	  struct object *ob, *new_ob;
 3017    1   	  struct value *ret;
 3018    1   	  int i;
 3019    1   	  struct object *save_command_giver = command_giver;
 3020    1   	
 3021    1   	  ob = find_object (str1);
 3022    1   	  if (!ob)
 3023    1   	    {
 3024    2   	      if (strcmp (str1, "obj/sing") == 0)
 3025    2   		fatal ("No singularity.\n");
 3026    2   	      ret = clone_object ("obj/sing");
 3027    2   	      if (!ret)
 3028    2   		fatal ("No singularity.\n");
 3029    2   	      return ret;
 3030    2   	    }
 3031    1   	  if (ob->super || ob->cloned)
 3032    1   	    error ("Cloning a used object !\n");
 3033    1   	  if (ob->enable_heart_beat)
 3034    1   	    (void) set_heart_beat (ob, 0);
 3035    1   	  ob->reset = 0;
 3036    1   	  new_ob = get_empty_object (ob->num_variables);
 3037    1   	  new_ob->name = make_new_name (ob->name);
 3038    1   	  new_ob->name_length = strlen (new_ob->name);
 3039    1   	  new_ob->cloned = 1;
 3040    1   	  new_ob->last_reset = current_time;
 3041    1   	  new_ob->prog = ob->prog;
 3042    1   	  new_ob->inherit = ob->inherit;
 3043    1   	  if (new_ob->inherit)
 3044    1   	    add_ref (new_ob->inherit, 0);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 11
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3045    1   	  if (new_ob->prog)
 3046    1   	    add_prog_ref ((struct lnode_def *) (new_ob->prog));
 3047    1   	  if (current_object && current_object->wl && !ob->wl)
 3048    1   	    new_ob->wl = current_object->wl;
 3049    1   	  else
 3050    1   	    new_ob->wl = ob->wl;	/* Possibly a null pointer */
 3051    1   	  new_ob->status = ob->status;
 3052    1   	  new_ob->heart_beat = ob->heart_beat;
 3053    1   	  new_ob->next_all = obj_list;
 3054    1   	  new_ob->block = ob->block;
 3055    1   	  new_ob->swap_size = ob->swap_size;	/* Used only for statistics. */
 3056    1   	  obj_list = new_ob;
 3057    1   	  enter_object_hash (new_ob);	/* add name to fast object lookup table */
 3058    1   	#if 0				/* This was done in get_empty_object() */
 3059   X    	  new_ob->num_variables = ob->num_variables;
 3060   X    	  /* Allocate space for local variables. */
 3061   X    	  if (ob->num_variables > 0)
 3062   X    	    new_ob->variables =
 3063   X    	      (struct svalue *) xalloc (ob->num_variables *
 3064   X    					sizeof (struct svalue));
 3065   X    	  /* Initialize variables... */
 3066   X    	  for (i = 0; i < ob->num_variables; i++)
 3067   X    	    {
 3068   X    	      new_ob->variables[i].u.number = 0;
 3069   X    	      new_ob->variables[i].type = T_NUMBER;
 3070   X    	    }
 3071    1   	#endif
 3072    1   	  new_ob->reset = 1;
 3073    1   	  (void) apply ("reset", new_ob, 0);
 3074    1   	  command_giver = save_command_giver;
 3075    1   	  if (d_flag)
 3076    1   	    debug_message ("--%s cloned to %s\n", ob->name, new_ob->name);
 3077    1   	  if (new_ob->destructed)
 3078    1   	    return &const0;
 3079    1   	  ret = alloc_value ();
 3080    1   	  ret->type = T_OBJECT;
 3081    1   	  ret->u.ob = new_ob;
 3082    1   	  add_ref (new_ob, "clone_object");
 3083    1   	  return ret;
 3084    1   	}
 3085        	
 3086        	struct value *
 3087        	environment (arg)
 3088        	     struct value *arg;
 3089        	{
 3090    1   	  struct value *ret;
 3091    1   	  struct object *ob = current_object;
 3092    1   	
 3093    1   	  if (arg && arg->type == T_OBJECT)
 3094    1   	    ob = arg->u.ob;
 3095    1   	  else if (arg && arg->type == T_STRING)
 3096    1   	    ob = find_object2 (arg->u.string);
 3097    1   	  else
 3098    1   	    ob = current_object;
 3099    1   	  if (ob == 0 || ob->super == 0)
 3100    1   	    return &const0;
 3101    1   	  if (ob->destructed)

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 12
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3102    1   	    error ("environment() off destructed object.\n");
 3103    1   	  ret = alloc_value ();
 3104    1   	  ret->type = T_OBJECT;
 3105    1   	  ret->u.ob = ob->super;
 3106    1   	  add_ref (ret->u.ob, "environment");
 3107    1   	  return ret;
 3108    1   	}
 3109        	
 3110        	/*
 3111        	 * Execute a command for an object. Copy the command into a
 3112        	 * new buffer, because 'parse_command()' can modify the command.
 3113        	 * If the object is not current object, static functions will not
 3114        	 * be executed. This will prevent forcing players to do illegal things.
 3115        	 */
 3116        	int
 3117        	command_for_object (str, ob)
 3118        	     char *str;
 3119        	     struct object *ob;
 3120        	{
 3121    1   	  char buff[1000];
 3122    1   	
 3123    1   	  if (strlen (str) > sizeof (buff) - 1)
 3124    1   	    error ("Too long command.\n");
 3125    1   	#ifdef LOG_FORCE
 3126   X    	  if (ob && command_giver != ob && ob->interactive)
 3127   X    	    {
 3128   X    	      struct value *force, *forced;
 3129   X    	      FILE *f;
 3130   X    	
 3131   X    	      force = apply ("query_real_name", command_giver, 0);
 3132   X    	      forced = apply ("query_real_name", ob, 0);
 3133   X    	      f = fopen ("log/FORCE", "a");
 3134   X    	      if (f && force && forced)
 3135   X    		{
 3136   X    		  if (force->type == T_STRING && forced->type == T_STRING)
 3137   X    		    fprintf (f, "%s %s: %s\n", force->u.string, forced->u.string,
 3138   X    			     str);
 3139   X    		}
 3140   X    	      if (f)
 3141   X    		fclose (f);
 3142   X    	    }
 3143    1   	#endif
 3144    1   	  if (ob == 0)
 3145    1   	    ob = current_object;
 3146    1   	  strncpy (buff, str, sizeof buff);
 3147    1   	  return parse_command (buff, ob, (ob != current_object));
 3148    1   	}
 3149        	
 3150        	/*
 3151        	 * To find if an object is present, we have to look in two inventory
 3152        	 * lists. The first list is the inventory of the current object.
 3153        	 * The second list is all things that have the same ->super as
 3154        	 * current_object.
 3155        	 * Also test the environment.
 3156        	 * If the second argument 'ob' is non zero, only search in the
 3157        	 * inventory of 'ob'. The argument 'ob' will be mandatory, later.
 3158        	 */

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 13
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3159        	
 3160        	static struct value *object_present2 ();
 3161        	
 3162        	struct value *
 3163        	object_present (v, ob)
 3164        	     struct value *v;
 3165        	     struct object *ob;
 3166        	{
 3167    1   	  struct value *ret;
 3168    1   	  int specific = 0;
 3169    1   	
 3170    1   	  if (ob == 0)
 3171    1   	    ob = current_object;
 3172    1   	  else
 3173    1   	    specific = 1;
 3174    1   	  if (v->type == T_OBJECT)
 3175    1   	    {
 3176    2   	      if (specific)
 3177    2   		{
 3178    3   		  if (v->u.ob->super == ob)
 3179    3   		    return v;
 3180    3   		  else
 3181    3   		    return &const0;
 3182    3   		}
 3183    2   	      if (v->u.ob->super == ob ||
 3184    2   		  (v->u.ob->super == ob->super && ob->super != 0))
 3185    2   		return v;
 3186    2   	      return &const0;
 3187    2   	    }
 3188    1   	  ret = object_present2 (v, ob->contains);
 3189    1   	  if (ret)
 3190    1   	    return ret;
 3191    1   	  if (specific)
 3192    1   	    return &const0;
 3193    1   	  if (ob->super)
 3194    1   	    {
 3195    2   	      ret = apply ("id", ob->super, v);
 3196    2   	      if (ob->super->destructed)
 3197    2   		return &const0;
 3198    2   	      if (ret && !(ret->type == T_NUMBER && ret->u.number == 0))
 3199    2   		{
 3200    3   		  ret = alloc_value ();
 3201    3   		  ret->type = T_OBJECT;
 3202    3   		  ret->u.ob = ob->super;
 3203    3   		  add_ref (ret->u.ob, "present()");
 3204    3   		  return ret;
 3205    3   		}
 3206    2   	      return object_present2 (v, ob->super->contains);
 3207    2   	    }
 3208    1   	  return &const0;
 3209    1   	}
 3210        	
 3211        	static struct value *
 3212        	object_present2 (v, ob)
 3213        	     struct value *v;
 3214        	     struct object *ob;
 3215        	{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 14
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3216    1   	  struct value *ret;
 3217    1   	  char *p;
 3218    1   	  int count = 0, length;
 3219    1   	  struct value item;
 3220    1   	
 3221    1   	  item.type = T_STRING;
 3222    1   	  item.u.string = string_copy (v->u.string);
 3223    1   	  length = strlen (item.u.string);
 3224    1   	  p = item.u.string + length - 1;
 3225    1   	  if (*p >= '0' && *p <= '9')
 3226    1   	    {
 3227    2   	      while (p > item.u.string && *p >= '0' && *p <= '9')
 3228    2   		p--;
 3229    2   	      if (p > item.u.string && *p == ' ')
 3230    2   		{
 3231    3   		  count = atoi (p + 1) - 1;
 3232    3   		  *p = '\0';
 3233    3   		  length = p - item.u.string;	/* This is never used again ! */
 3234    3   		}
 3235    2   	    }
 3236    1   	  for (; ob; ob = ob->next_inv)
 3237    1   	    {
 3238    2   	      ret = apply ("id", ob, &item);
 3239    2   	      if (ob->destructed)
 3240    2   		{
 3241    3   		  free (item.u.string);
 3242    3   		  return 0;
 3243    3   		}
 3244    2   	      if (ret == 0 || (ret->type == T_NUMBER && ret->u.number == 0))
 3245    2   		continue;
 3246    2   	      if (count-- > 0)
 3247    2   		continue;
 3248    2   	      ret = alloc_value ();
 3249    2   	      ret->type = T_OBJECT;
 3250    2   	      ret->u.ob = ob;
 3251    2   	      add_ref (ret->u.ob, "object_present2");
 3252    2   	      free (item.u.string);
 3253    2   	      return ret;
 3254    2   	    }
 3255    1   	  free (item.u.string);
 3256    1   	  return 0;
 3257    1   	}
 3258        	
 3259        	/*
 3260        	 * Remove an object. It is first moved into the destruct list, and
 3261        	 * not really destructed until later. (destruct2()).
 3262        	 *
 3263        	 * If the object is inherited, it must not be destructed. So we just rename
 3264        	 * it to something new. Thus will all pointers to this object continue to
 3265        	 * work, and new objects that needs this object will load a new copy.
 3266        	 */
 3267        	void
 3268        	destruct_object (v)
 3269        	     struct value *v;
 3270        	{
 3271    1   	  struct object *ob, *super;
 3272    1   	  struct object **pp;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 15
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3273    1   	  int removed;
 3274    1   	  struct value *weight, neg_weight;
 3275    1   	  extern struct object *current_reset;
 3276    1   	
 3277    1   	  if (v->type == T_OBJECT)
 3278    1   	    ob = v->u.ob;
 3279    1   	  else
 3280    1   	    {
 3281    2   	      ob = find_object2 (v->u.string);
 3282    2   	      if (ob == 0)
 3283    2   		error ("destruct_object: Could not find %s\n", v->u.string);
 3284    2   	    }
 3285    1   	  if (ob->destructed)
 3286    1   	    error ("Destruct destructed object.\n");
 3287    1   	  if (d_flag)
 3288    1   	    debug_message ("Destruct object %s (ref %d)\n", ob->name, ob->ref);
 3289    1   	  /*
 3290    1   	   * Inherited objects will never be removed.
 3291    1   	   */
 3292    1   	  if (ob->inherited)
 3293    1   	    {
 3294    2   	      char *p;
 3295    2   	      remove_object_hash (ob);
 3296    2   	      p = ob->name;
 3297    2   	      ob->name = make_new_name (p);
 3298    2   	      free (p);
 3299    2   	      ob->name_length = strlen (ob->name);
 3300    2   	      enter_object_hash (ob);
 3301    2   	      return;
 3302    2   	    }
 3303    1   	  if (ob == current_reset)
 3304    1   	    {
 3305    2   	      /*
 3306    2   	       * current_reset must be set to 0, not the next object in the list,
 3307    2   	       * as this next object migh be destructed from a recursive call of
 3308    2   	       * us from destruct_object()_ from above !
 3309    2   	       */
 3310    2   	      current_reset = 0;
 3311    2   	    }
 3312    1   	  super = ob->super;
 3313    1   	  if (super == 0)
 3314    1   	    {
 3315    2   	      super = find_object ("room/void");	/* Take any existing void. */
 3316    2   	    }
 3317    1   	  else
 3318    1   	    {
 3319    2   	      /* Call exit in current room, if player or npc */
 3320    2   	      if (ob->enable_commands)
 3321    2   		{
 3322    3   		  struct value v;
 3323    3   		  v.type = T_OBJECT;
 3324    3   		  v.u.ob = ob;
 3325    3   		  apply ("exit", super, &v);
 3326    3   		}
 3327    2   	      weight = apply ("query_weight", ob, 0);
 3328    2   	      if (weight && weight->type == T_NUMBER)
 3329    2   		{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 16
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3330    3   		  neg_weight.type = T_NUMBER;
 3331    3   		  neg_weight.u.number = -weight->u.number;
 3332    3   		  (void) apply ("add_weight", super, &neg_weight);
 3333    3   		}
 3334    2   	    }
 3335    1   	  if (super == 0)
 3336    1   	    fatal ("Could not find the void.\n");
 3337    1   	
 3338    1   	  set_heart_beat (ob, 0);
 3339    1   	
 3340    1   	  while (ob->contains)
 3341    1   	    move_or_destruct (ob->contains, super);
 3342    1   	  set_heart_beat (ob, 0);
 3343    1   	  /*
 3344    1   	   * Remove us out of this current room (if any).
 3345    1   	   * Remove all sentences defined by this object from all objects here.
 3346    1   	   */
 3347    1   	  if (ob->super)
 3348    1   	    {
 3349    2   	      if (ob->super->enable_commands)
 3350    2   		remove_sent (ob, ob->super);
 3351    2   	      add_light (ob->super, -ob->total_light);
 3352    2   	      for (pp = &ob->super->contains; *pp;)
 3353    2   		{
 3354    3   		  if ((*pp)->enable_commands)
 3355    3   		    remove_sent (ob, *pp);
 3356    3   		  if (*pp != ob)
 3357    3   		    pp = &(*pp)->next_inv;
 3358    3   		  else
 3359    3   		    *pp = (*pp)->next_inv;
 3360    3   		}
 3361    2   	    }
 3362    1   	  if (ob->ed_buffer)
 3363    1   	    {
 3364    2   	      extern void save_buffer (), deallocate_buffer ();
 3365    2   	      save_buffer (ob);
 3366    2   	      deallocate_buffer (ob);
 3367    2   	    }
 3368    1   	  if (ob->inherit)
 3369    1   	    {
 3370    2   	      struct object *tmp = ob->inherit;
 3371    2   	      ob->inherit = 0;
 3372    2   	      free_object (tmp, "inherit");
 3373    2   	    }
 3374    1   	  /*
 3375    1   	   * Now remove us out of the list of all objects.
 3376    1   	   * This must be done last, because an error in the above code would
 3377    1   	   * halt execution.
 3378    1   	   */
 3379    1   	  removed = 0;
 3380    1   	  for (pp = &obj_list; *pp; pp = &(*pp)->next_all)
 3381    1   	    {
 3382    2   	      if (*pp != ob)
 3383    2   		continue;
 3384    2   	      *pp = (*pp)->next_all;
 3385    2   	      removed = 1;
 3386    2   	      remove_object_hash (ob);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 17
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3387    2   	      break;
 3388    2   	    }
 3389    1   	  if (!removed)
 3390    1   	    fatal ("Failed to delete object.\n");
 3391    1   	  if (ob->living_name)
 3392    1   	    remove_living_name (ob);
 3393    1   	  ob->super = 0;
 3394    1   	  ob->next_inv = 0;
 3395    1   	  ob->heart_beat = 0;
 3396    1   	  ob->contains = 0;
 3397    1   	  ob->enable_commands = 0;
 3398    1   	  ob->next_all = obj_list_destruct;
 3399    1   	  obj_list_destruct = ob;
 3400    1   	  ob->destructed = 1;
 3401    1   	}
 3402        	
 3403        	/*
 3404        	 * This one is called when no program is execuiting.
 3405        	 * The super pointer is still maintained.
 3406        	 */
 3407        	void
 3408        	destruct2 (ob)
 3409        	     struct object *ob;
 3410        	{
 3411    1   	  if (ob->interactive)
 3412    1   	    remove_interactive (ob);
 3413    1   	  /*
 3414    1   	   * We must deallocate variables here, not in 'free_object()'.
 3415    1   	   * That is because one of the local variables may point to this object,
 3416    1   	   * and deallocation of this pointer will also decrease the reference
 3417    1   	   * count of this object. Otherwise, an object with a variable pointing
 3418    1   	   * to itself, would never be freed.
 3419    1   	   * Just in case the program in this object would continue to
 3420    1   	   * execute, change string and object variables into the number 0.
 3421    1   	   */
 3422    1   	  if (ob->num_variables > 0)
 3423    1   	    {
 3424    2   	      /*
 3425    2   	       * Deallocate variables in this object.
 3426    2   	       * The space of the variables are not deallocated until
 3427    2   	       * the object structure is freed in free_object().
 3428    2   	       */
 3429    2   	      int i;
 3430    2   	      for (i = 0; i < ob->num_variables; i++)
 3431    2   		{
 3432    3   		  free_svalue (&ob->variables[i]);
 3433    3   		  ob->variables[i].type = T_NUMBER;
 3434    3   		  ob->variables[i].u.number = 0;
 3435    3   		}
 3436    2   	    }
 3437    1   	  free_object (ob, "destruct_object");
 3438    1   	}
 3439        	
 3440        	struct value *
 3441        	create_wizard (owner)
 3442        	     char *owner;
 3443        	{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 18
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3444    1   	  struct stat st;
 3445    1   	  char name[200], cmd[200];
 3446    1   	  FILE *f;
 3447    1   	  struct value *ret;
 3448    1   	  struct object *owner_obj;
 3449    1   	
 3450    1   	  if (strncmp (current_object->name, "obj/", 4) != 0 &&
 3451    1   	      strncmp (current_object->name, "room/", 5) != 0)
 3452    1   	    {
 3453    2   	      error ("Illegal use of create_wizard()\n");
 3454    2   	    }
 3455    1   	  if (strchr (owner, '.') || strchr (owner, '/'))
 3456    1   	    error ("Bad name to create_wizard: %s\n", owner);
 3457    1   	  owner_obj = find_living_object (owner, 1);
 3458    1   	  if (owner_obj == 0)
 3459    1   	    {
 3460    2   	      fprintf (stderr,
 3461    2   		       "create_wizard: Could not find living object %s.\n", owner);
 3462    2   	      return 0;
 3463    2   	    }
 3464    1   	  if (owner_obj->super == 0 || owner_obj->super->cloned)
 3465    1   	    {
 3466    2   	      struct value v;
 3467    2   	      v.type = T_STRING;
 3468    2   	      v.u.string =
 3469    2   		"There is a crash, the room collapses and the castle disappears.\n";
 3470    2   	      say (&v, 0);
 3471    2   	      return 0;
 3472    2   	    }
 3473    1   	  if (stat (PLAYER_DIR, &st) == -1)
 3474    1   	    if (mkdir (PLAYER_DIR, 0777) == -1)
 3475    1   	      error ("Could not mkdir %s\n", PLAYER_DIR);
 3476    1   	  (void) sprintf (name, "%s/%s", PLAYER_DIR, owner);
 3477    1   	  if (stat (name, &st) == 0)
 3478    1   	    error ("Player %s already has a castle!\n", owner);
 3479    1   	  if (mkdir (name, 0777) == -1)
 3480    1   	    {
 3481    2   	      perror (name);
 3482    2   	      error ("Could not mkdir %s\n", name);
 3483    2   	    }
 3484    1   	  (void) sprintf (name, "%s/%s/%s", PLAYER_DIR, owner, "castle.c");
 3485    1   	  f = fopen (name, "w");
 3486    1   	  if (f == NULL)
 3487    1   	    error ("Could not create a castle file %s!\n", name);
 3488    1   	  (void) fprintf (f, "#define NAME \"%s\"\n", owner);
 3489    1   	  (void) fprintf (f, "#define DEST \"%s\"\n", owner_obj->super->name);
 3490    1   	  (void) fclose (f);
 3491    1   	  (void) sprintf (cmd, "cat %s >> %s", DEFAULT_CASTLE, name);
 3492    1   	  (void) system (cmd);
 3493    1   	  f = fopen (INIT_FILE, "a");
 3494    1   	  if (f == NULL)
 3495    1   	    error ("Could not add the new castle to the %s\n", INIT_FILE);
 3496    1   	  (void) fprintf (f, "%s\n", name);
 3497    1   	  (void) fclose (f);
 3498    1   	  ret = alloc_value ();
 3499    1   	  ret->type = T_STRING;
 3500    1   	  ret->u.string = string_copy (name);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 19
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3501    1   	  return ret;
 3502    1   	}
 3503        	
 3504        	/*
 3505        	 * A message from an object will reach
 3506        	 * all objects in the inventory,
 3507        	 * all objects in the same environment and
 3508        	 * the surrounding object.
 3509        	 * Non interactive objects gets no messages.
 3510        	 *
 3511        	 * There are two cases to take care of. If this routine is called from
 3512        	 * a player (indirectly), then the message goes to all in his
 3513        	 * environment. Otherwise, the message goes to all in the current_object's
 3514        	 * environment (as the case when called from a heart_beat()).
 3515        	 *
 3516        	 * If there is a second argument 'avoid_ob', then do not send the message
 3517        	 * to that object.
 3518        	 */
 3519        	
 3520        	void
 3521        	say (v, avoid_ob)
 3522        	     struct value *v;
 3523        	     struct object *avoid_ob;
 3524        	{
 3525    1   	  struct object *ob, *save_command_giver = command_giver;
 3526    1   	  struct object *origin;
 3527    1   	  char buff[256];
 3528    1   	
 3529    1   	  if (current_object->enable_commands)
 3530    1   	    command_giver = current_object;
 3531    1   	  if (command_giver)
 3532    1   	    origin = command_giver;
 3533    1   	  else
 3534    1   	    origin = current_object;
 3535    1   	  switch (v->type)
 3536    1   	    {
 3537    2   	      case T_STRING :
 3538    2   		strncpy (buff, v->u.string, sizeof buff);
 3539    2   	      break;
 3540    2   	      case T_OBJECT :
 3541    2   		strncpy (buff, v->u.ob->name, sizeof buff);
 3542    2   	      break;
 3543    2   	      case T_NUMBER :
 3544    2   		sprintf (buff, "%d", v->u.number);
 3545    2   	      break;
 3546    2   	      default :
 3547    2   		error ("Invalid argument %d to say()\n", v->type);
 3548    2   	    }
 3549    1   	  for (ob = origin->contains; ob; ob = ob->next_inv)
 3550    1   	    {
 3551    2   	      struct object *save_again;
 3552    2   	      if (ob->interactive == 0)
 3553    2   		{
 3554    3   		  if (ob->enable_commands && ob != command_giver && ob != avoid_ob)
 3555    3   		    tell_npc (ob, buff);
 3556    3   		  if (ob->destructed)
 3557    3   		    break;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 20
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3558    3   		  continue;
 3559    3   		}
 3560    2   	      if (ob == save_command_giver || ob == avoid_ob)
 3561    2   		continue;
 3562    2   	      save_again = command_giver;
 3563    2   	      command_giver = ob;
 3564    2   	      add_message ("%s", buff);
 3565    2   	      command_giver = save_again;
 3566    2   	    }
 3567    1   	  if (origin->super)
 3568    1   	    {
 3569    2   	      if (origin->super->interactive && origin != command_giver &&
 3570    2   		  origin->super != avoid_ob)
 3571    2   		{
 3572    3   		  command_giver = origin->super;
 3573    3   		  add_message ("%s", buff);
 3574    3   		}
 3575    2   	      else if (origin->super->interactive == 0 &&
 3576    2   		       origin->super != avoid_ob &&
 3577    2   		       origin->super->enable_commands && ob != command_giver)
 3578    2   		{
 3579    3   		  tell_npc (origin->super, buff);
 3580    3   		}
 3581    2   	      for (ob = origin->super->contains; ob; ob = ob->next_inv)
 3582    2   		{
 3583    3   		  struct object *save_again;
 3584    3   		  if (ob == avoid_ob)
 3585    3   		    continue;
 3586    3   		  if (ob->interactive == 0)
 3587    3   		    {
 3588    4   		      if (ob->enable_commands && ob != command_giver)
 3589    4   			tell_npc (ob, buff);
 3590    4   		      if (ob->interactive)
 3591    4   			break;
 3592    4   		      continue;
 3593    4   		    }
 3594    3   		  if (ob == command_giver)
 3595    3   		    continue;
 3596    3   		  save_again = command_giver;
 3597    3   		  command_giver = ob;
 3598    3   		  add_message ("%s", buff);
 3599    3   		  command_giver = save_again;
 3600    3   		}
 3601    2   	    }
 3602    1   	  command_giver = save_command_giver;
 3603    1   	}
 3604        	
 3605        	/*
 3606        	 * Send a message to all objects inside an object.
 3607        	 * Non interactive objects gets no messages.
 3608        	 * Compare with say().
 3609        	 */
 3610        	
 3611        	void
 3612        	tell_room (room, v)
 3613        	     struct object *room;
 3614        	     struct value *v;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 21
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3615        	{
 3616    1   	  struct object *ob, *save_command_giver = command_giver;
 3617    1   	  char buff[256];
 3618    1   	
 3619    1   	  switch (v->type)
 3620    1   	    {
 3621    2   	      case T_STRING :
 3622    2   		strncpy (buff, v->u.string, sizeof buff);
 3623    2   	      break;
 3624    2   	      case T_OBJECT :
 3625    2   		strncpy (buff, v->u.ob->name, sizeof buff);
 3626    2   	      break;
 3627    2   	      case T_NUMBER :
 3628    2   		sprintf (buff, "%d", v->u.number);
 3629    2   	      break;
 3630    2   	      default :
 3631    2   		error ("Invalid argument %d to tell_room()\n", v->type);
 3632    2   	    }
 3633    1   	  for (ob = room->contains; ob; ob = ob->next_inv)
 3634    1   	    {
 3635    2   	      if (ob->interactive == 0)
 3636    2   		{
 3637    3   		  if (ob->enable_commands)
 3638    3   		    tell_npc (ob, buff);
 3639    3   		  if (ob->destructed)
 3640    3   		    break;
 3641    3   		  continue;
 3642    3   		}
 3643    2   	      command_giver = ob;
 3644    2   	      add_message ("%s", buff);
 3645    2   	    }
 3646    1   	  command_giver = save_command_giver;
 3647    1   	}
 3648        	
 3649        	void
 3650        	shout_string (str)
 3651        	     char *str;
 3652        	{
 3653    1   	  struct object *ob, *save_command_giver = command_giver;
 3654    1   	  extern int num_player;
 3655    1   	  FILE *f = 0;
 3656    1   	  char *p;
 3657    1   	  struct value *v, *muffled;
 3658    1   	  int emergency = 0, i;
 3659    1   	
 3660    1   	  if (str[0] == '!')
 3661    1   	    {
 3662    2   	      emergency = 1;
 3663    2   	      str++;
 3664    2   	    }
 3665    1   	  for (p = str; *p; p++)
 3666    1   	    {
 3667    2   	      if ((*p < ' ' || *p > '~') && *p != '\n')
 3668    2   		*p = ' ';
 3669    2   	    }
 3670    1   	  p = 0;
 3671    1   	#ifdef LOG_SHOUT

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 22
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3672   X    	  if (command_giver)
 3673   X    	    {
 3674   X    	      v = apply ("query_real_name", command_giver, 0);
 3675   X    	      if (v && v->type == T_STRING)
 3676   X    		p = v->u.string;
 3677   X    	    }
 3678   X    	  else if (current_object && current_object->wl)
 3679   X    	    p = current_object->wl->name;
 3680   X    	  if (p)
 3681   X    	    f = fopen ("log/SHOUTS", "a");
 3682   X    	  if (f)
 3683   X    	    {
 3684   X    	      fprintf (f, "%s: %s\n", p, str);
 3685   X    	      fclose (f);
 3686   X    	    }
 3687    1   	#endif
 3688    1   	  /* for (ob = obj_list; ob; ob = ob->next_all) { */
 3689    1   	  for (i = 0; i < num_player; i++)
 3690    1   	    {
 3691    2   	      ob = get_interactive_object (i);
 3692    2   	      if (ob->interactive == 0 || ob == save_command_giver)
 3693    2   		continue;
 3694    2   	      muffled = apply ("query_muffled", ob, (struct value *) 0);
 3695    2   	      if (!emergency && muffled->type == T_NUMBER && muffled->u.number)
 3696    2   		continue;
 3697    2   	      command_giver = ob;
 3698    2   	      add_message ("%s", str);
 3699    2   	    }
 3700    1   	  command_giver = save_command_giver;
 3701    1   	}
 3702        	
 3703        	struct value *
 3704        	first_inventory (arg)
 3705        	     struct value *arg;
 3706        	{
 3707    1   	  struct object *ob;
 3708    1   	  struct value *ret;
 3709    1   	
 3710    1   	  if (arg->type == T_STRING)
 3711    1   	    ob = find_object (arg->u.string);
 3712    1   	  else
 3713    1   	    ob = arg->u.ob;
 3714    1   	  if (ob == 0)
 3715    1   	    error ("No object to first_inventory()");
 3716    1   	  if (ob->contains == 0)
 3717    1   	    return 0;
 3718    1   	  ret = alloc_value ();
 3719    1   	  ret->type = T_OBJECT;
 3720    1   	  ret->u.ob = ob->contains;
 3721    1   	  add_ref (ret->u.ob, "first_inventory");
 3722    1   	  return ret;
 3723    1   	}
 3724        	
 3725        	struct value *
 3726        	next_inventory (arg)
 3727        	     struct value *arg;
 3728        	{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 23
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3729    1   	  struct object *ob;
 3730    1   	  struct value *ret;
 3731    1   	
 3732    1   	  if (arg->type == T_STRING)
 3733    1   	    ob = find_object (arg->u.string);
 3734    1   	  else
 3735    1   	    ob = arg->u.ob;
 3736    1   	  if (ob == 0)
 3737    1   	    error ("No object to next_inventory()");
 3738    1   	  if (ob->next_inv == 0)
 3739    1   	    return 0;
 3740    1   	  ret = alloc_value ();
 3741    1   	  ret->type = T_OBJECT;
 3742    1   	  ret->u.ob = ob->next_inv;
 3743    1   	  add_ref (ret->u.ob, "next_inventory");
 3744    1   	  return ret;
 3745    1   	}
 3746        	
 3747        	/*
 3748        	 * This will enable an object to use commands normally only
 3749        	 * accessible by interactive players.
 3750        	 * Also check if the player is a wizard. Wizards must not affect the
 3751        	 * value of the wizlist ranking.
 3752        	 */
 3753        	
 3754        	void
 3755        	enable_commands (num)
 3756        	     int num;
 3757        	{
 3758    1   	  current_object->enable_commands = num;
 3759    1   	  command_giver = current_object;
 3760    1   	}
 3761        	
 3762        	/*
 3763        	 * Set up a function in this object to be called with the next
 3764        	 * user input string.
 3765        	 */
 3766        	struct value *
 3767        	input_to (fun, flag)
 3768        	     char *fun;
 3769        	     int flag;
 3770        	{
 3771    1   	  struct sentence *s = alloc_sentence ();
 3772    1   	
 3773    1   	  if (set_call (command_giver, s, flag))
 3774    1   	    {
 3775    2   	      s->function = make_shared_string (fun);
 3776    2   	      s->ob = current_object;
 3777    2   	      add_ref (current_object, "input_to");
 3778    2   	      return &const1;
 3779    2   	    }
 3780    1   	  free_sentence (s);
 3781    1   	  return &const0;
 3782    1   	}
 3783        	
 3784        	
 3785        	int

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 24
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3786        	pstrcmp (p1, p2)
 3787        	     char **p1, **p2;
 3788        	{
 3789    1   	  return strcmp (*p1 + 2 * sizeof (int), *p2 + 2 * sizeof (int));
 3790    1   	}
 3791        	
 3792        	/*
 3793        	* List files in a directory. The standard 'ls' could be used, but
 3794        	* it takes too much time.
 3795        	* Prepared for flag decoding.
 3796        	*
 3797        	* Look at the the last component of the path name. If it is a regular
 3798        	* expression, select only matching files.
 3799        	*
 3800        	* '.' and '..' are only listed if they match the regexp.
 3801        	*
 3802        	*/
 3803        	/*  * But of course, none of this works in VMS..... (bub)
 3804        	    * The problem is with the READDIR, OPENDIR, and CLOSEDIR ()
 3805        	#define MAXLSCOLUMNS 6
 3806        	void
 3807        	list_files (path, flags)
 3808        	     char *path, *flags;
 3809        	{
 3810        	  DIR *dirp;
 3811        	  struct direct *de;
 3812        	  struct stat st;
 3813        	  char regexp[80], *p, path2[150];
 3814        	  int do_match = 0;
 3815        	  char *name[MAXLSCOLUMNS * MAX_LINES];
 3816        	  char *nbuf;
 3817        	  int colwidth[MAXLSCOLUMNS];
 3818        	  char *fname;
 3819        	  int num, i, j, k, ncols, npercol, max, total, size;
 3820        	
 3821        	  if (!path)
 3822        	    path = ".";
 3823        	  path = check_file_name (path, 0);
 3824        	  if (path == 0)
 3825        	    return;
 3826        	  strncpy (path2, path, sizeof path2);
 3827        	  path2[sizeof path2 - 1] = '\0';
 3828        	  p = path2 + strlen (path2) - 2;
 3829        	  if (p >= path2 && p[0] == '/' && p[1] == '.')
 3830        	    p[0] = '\0';
 3831        	  if (stat (path2, &st) == -1)
 3832        	    {
 3833        	      * Either the directory does not exist, or it is a regexp
 3834        	       * file name. Strip of the last component.
 3835        	       *
 3836        	      p = strrchr (path2, '/');
 3837        	      if (p == 0 || p[1] == '\0')
 3838        		return;
 3839        	      strncpy (regexp, p + 1, sizeof regexp);
 3840        	      regexp[sizeof regexp - 1] = '\0';
 3841        	      *p = '\0';
 3842        	      do_match = 1;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 25
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3843        	    }
 3844        	  dirp = opendir (path2);
 3845        	  if (dirp == 0)
 3846        	    {
 3847        	      add_message ("No such directory '%s'\n", path2);
 3848        	      return;
 3849        	    }
 3850        	  num = 0;
 3851        	  total = 0;
 3852        	  if (path[0])
 3853        	    strcat (path2, "/");
 3854        	  i = strlen (path2);
 3855        	  fname = &path2[i];
 3856        	  i = sizeof (path2) - i - 1;
 3857        	  nbuf = (char *) xalloc ((34 + 2 * sizeof (int)) * MAXLSCOLUMNS * MAX_LINES);
 3858        	
 3859        	  for (j = 0; j < MAXLSCOLUMNS * MAX_LINES; j++)
 3860        	    name[j] = nbuf + (j * (34 + 2 * sizeof (int)));
 3861        	
 3862        	  for (de = readdir (dirp); (de && num < (MAXLSCOLUMNS * MAX_LINES)); de = readdir (dirp))
 3863        	    {
 3864        	      if (!do_match && (strcmp (de->d_name, ".") == 0 ||
 3865        				strcmp (de->d_name, "..") == 0))
 3866        		continue;
 3867        	      if (do_match && !match_string (regexp, de->d_name))
 3868        		continue;
 3869        	      strncpy (fname, de->d_name, i);
 3870        	      j = 0;
 3871        	      if (stat (path2, &st) != -1)
 3872        		{
 3873        		  size = (int) st.st_size / 1024 + ((int) st.st_size % 1024 > 0);
 3874        		  total += size;
 3875        		  if (S_IFDIR & st.st_mode)
 3876        		    j = 1;
 3877        		}
 3878        	      else
 3879        		size = 0;
 3880        	      strncpy (name[num] + 2 * sizeof (int), de->d_name, 32);
 3881        	      (name[num] + 2 * sizeof (int))[32] = 0;
 3882        	      ((int *) name[num])[0] = de->d_namlen + j;
 3883        	      ((int *) name[num])[1] = size;
 3884        	      if (j)
 3885        		strcat (name[num] + 2 * sizeof (int), "/");
 3886        	      num++;
 3887        	    }
 3888        	  closedir (dirp);
 3889        	
 3890        	  if (num == 0)
 3891        	    {
 3892        	      add_message (do_match ? "No matching files.\n" : "No files.\n");
 3893        	      return;
 3894        	    }
 3895        	
 3896        	  * Sort the names. *
 3897        	  qsort ((char *) name, num, sizeof (char *), pstrcmp);
 3898        	
 3899        	  ncols = num / (num / MAXLSCOLUMNS + (num % MAXLSCOLUMNS > 0)) + ((num % (num / MAXLSCOLUMNS + (num % MAXLSCOLUMNS > 

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 26
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

0))) > 0);
 3900        	  while (1)
 3901        	    {
 3902        	      npercol = num / ncols + (num % ncols > 0);
 3903        	      for (j = 0; j < ncols; j++)
 3904        		{
 3905        		  max = 0;
 3906        		  for (i = j * npercol; i < (j + 1) * npercol && i < num; i++)
 3907        		    {
 3908        		      if (((int *) name[i])[0] > max)
 3909        			max = ((int *) name[i])[0];
 3910        		    }
 3911        		  colwidth[j] = max + 6;
 3912        		}
 3913        	      for (i = 0, max = 0; i < ncols; i++)
 3914        		max += colwidth[i];
 3915        	      if (max < 79)
 3916        		break;
 3917        	      ncols--;
 3918        	      if (ncols < 1)
 3919        		{
 3920        		  ncols = 1;
 3921        		  npercol = num;
 3922        		  break;
 3923        		}
 3924        	    }
 3925        	
 3926        	  for (i = 1; i < ncols; i++)
 3927        	    colwidth[i] += colwidth[i - 1];
 3928        	
 3929        	  add_message ("Total %d\n", total);
 3930        	
 3931        	  max = 0;
 3932        	  i = 0;
 3933        	  j = 0;
 3934        	  strcpy (path2,
 3935        		  "                                                                                ");
 3936        	  while (max < num)
 3937        	    {
 3938        	      k = (i * npercol) + j;
 3939        	      if (i >= ncols)
 3940        		{
 3941        		  j++;
 3942        		  i = 0;
 3943        		  add_message ("%s\n", path2);
 3944        		  strcpy (path2,
 3945        			  "                                                                                ");
 3946        		  continue;
 3947        		}
 3948        	      if (k < num)
 3949        		{
 3950        		  if (((int *) name[k])[1] > 9999)
 3951        		    sprintf (&path2[(i > 0 ? colwidth[i - 1] : 0)],
 3952        			     "BIG! %s ", name[k] + 2 * sizeof (int));
 3953        		  else
 3954        		    sprintf (&path2[(i > 0 ? colwidth[i - 1] : 0)],
 3955        			     "%4d %s ",

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 27
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 3956        			     ((int *) name[k])[1],
 3957        			     name[k] + 2 * sizeof (int));
 3958        		  if ((i + 1) * npercol + j < num)
 3959        		    path2[(i > 0 ? colwidth[i - 1] : 0) +
 3960        			  6 + ((int *) name[k])[0]] = ' ';
 3961        		  max++;
 3962        		}
 3963        	      i++;
 3964        	    }
 3965        	  add_message ("%s\n", path2);
 3966        	  if (num == MAXLSCOLUMNS * MAX_LINES)
 3967        	    add_message ("***Too many files, listing truncated***\n");
 3968        	  free (nbuf);
 3969        	}
 3970        	*/
 3971        	
 3972        	/*** Insert Bub's list_files () ***/
 3973        	/*** I just ignore the flags..... ***/
 3974        	void list_files (char * path, char * flags)
 3975        	{
 3976    1   	  /* Declare storage for the input file name, and the output file name */
 3977    1   	  /* The VAX will want these in stupid descriptor form, hence the strange */
 3978    1   	  /* declarations. */
 3979    1   	  static $DESCRIPTOR (filespec, 
 3980    1   	         "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
 3981    1   	  static $DESCRIPTOR (new_files, 
 3982    1   	         "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
 3983    1   	  /* The context for the find_file call, so I can get multiple files using */
 3984    1   	  /* wild card stuff. */
 3985    1   	  unsigned long context = 0;
 3986    1   	  /* The returned value from the call. */
 3987    1   	  long status;
 3988    1   	  /* number of files found */
 3989    1   	  int file_count = 0;
 3990    1   	  /* So we can re-initialize the length of the new_files descriptor */
 3991    1   	  int old_length;
 3992    1   	  /* string to help process the path. */
 3993    1   	  char temp_path [81];
 3994    1   	  /* Variable to keep track of tabs */
 3995    1   	  int three_counter;
 3996    1   	  /* Your basic dummy variables. */
 3997    1   	  int i, j, counter;
 3998    1   	
 3999    1   	
 4000    1   	    if (!path)
 4001    1   	        path = ".";
 4002    1   	    path = check_file_name(path, 0);
 4003    1   	    if (path == 0)
 4004    1   	        return;
 4005    1   	
 4006    1   	/*
 4007    1   	 add_message ("\n");
 4008    1   	 add_message (path);
 4009    1   	 add_message ("\n");
 4010    1   	*/
 4011    1   	
 4012    1   	/*** Convert a /dir1/dir2 type path to a [mudlib.dir1.dir2]*.* type path ***/

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 28
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4013    1   	 strcpy (temp_path, "[MUDLIB.");
 4014    1   	 strcat (temp_path, path);
 4015    1   	
 4016    1   	 counter = 0;
 4017    1   	 while ((counter < 80) && (temp_path [counter] != 0))
 4018    1   	   {
 4019    2   	     if (temp_path [counter] == '/')
 4020    2   	       temp_path [counter] = '.';
 4021    2   	     counter ++;
 4022    2   	   }
 4023    1   	
 4024    1   	 counter --;
 4025    1   	 /*** Get rid of the extra dots... ***/
 4026    1   	 while ((temp_path [counter] == '.') && (counter > 0))
 4027    1   	   {
 4028    2   	    temp_path [counter] = 0;
 4029    2   	    counter --;
 4030    2   	   }
 4031    1   	
 4032    1   	 strcat (temp_path, "]*.*");
 4033    1   	
 4034    1   	 if (!temp_path)
 4035    1   	   strcpy (filespec.dsc$a_pointer, "*.*");
 4036    1   	 else 
 4037    1   	   strcpy (filespec.dsc$a_pointer, temp_path);
 4038    1   	
 4039    1   	  filespec.dsc$w_length = strlen (filespec.dsc$a_pointer);
 4040    1   	
 4041    1   	 three_counter = 0;
 4042    1   	
 4043    1   	 old_length = new_files . dsc$w_length;
 4044    1   	
 4045    1   	/*
 4046    1   	 add_message ("\n");
 4047    1   	 add_message (filespec . dsc$a_pointer);
 4048    1   	 add_message ("\n");
 4049    1   	*/
 4050    1   	
 4051    1   	/*** The top of the loop. ***/
 4052    1   	 again:
 4053    1   	
 4054    1   	  new_files . dsc$w_length = old_length;
 4055    1   	
 4056    1   	  /* Go get me a file that matches that filespec */
 4057    1   	  status = lib$find_file (&filespec, &new_files, &context, 0, 0, 0, 0);
 4058    1   	
 4059    1   	  if (status & 1)
 4060    1   	    {
 4061    2   	    /* Remove the disk, and directory from the name */
 4062    2   	    /* by searching for a ']' */
 4063    2   	    /* Eg.  $disk:[harris.io]filename.c;45 */
 4064    2   	    /*     will turn into filename.c;45 */
 4065    2   	
 4066    2   	     i = 0;  /* i will hold the start of the filename */
 4067    2   	     while ((new_files . dsc$a_pointer [ i ] != ']') &&
 4068    2   	            (i < old_length))
 4069    2   	           i++;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 29
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4070    2   	     i ++;  /* So we don't include the ']' */
 4071    2   	
 4072    2   	     /* These names will have some spaces at the end of them. */
 4073    2   	     /* Also they will end with a semi-colon and a version number. */
 4074    2   	     /* Remove the semi-color and the version number. */
 4075    2   	     j = 0;  /* j will hold the end of the filename */
 4076    2   	     while ((new_files . dsc$a_pointer [ j ] != ';') &&
 4077    2   	            (j < old_length))
 4078    2   	           j ++;
 4079    2   	
 4080    2   	     new_files . dsc$a_pointer [j] = 0;
 4081    2   	     new_files . dsc$w_length = j - i;
 4082    2   	
 4083    2   	     three_counter += strlen (& (new_files . dsc$a_pointer [i]));
 4084    2   	
 4085    2   	     add_message (& (new_files . dsc$a_pointer [i]));
 4086    2   	
 4087    2   	     /*** Here I need to print some tabs. ***/
 4088    2   	     if (three_counter < 8)
 4089    2   	       {
 4090    3   	        add_message ("\t\t\t");
 4091    3   	        three_counter = 24;
 4092    3   	       }
 4093    2   	     else if (three_counter < 16)
 4094    2   	       {
 4095    3   	        add_message ("\t\t");
 4096    3   	        three_counter = 24;
 4097    3   	       }
 4098    2   	     else if (three_counter < 24)
 4099    2   	       {
 4100    3   	       add_message ("\t");
 4101    3   	        three_counter = 24;
 4102    3   	       }
 4103    2   	     else if (three_counter < 32)
 4104    2   	       {
 4105    3   	       add_message ("\t\t\t");
 4106    3   	        three_counter = 48;
 4107    3   	       }
 4108    2   	     else if (three_counter < 40)
 4109    2   	       {
 4110    3   	       add_message ("\t\t");
 4111    3   	        three_counter = 48;
 4112    3   	       }
 4113    2   	     else if (three_counter < 48)
 4114    2   	       {
 4115    3   	       add_message ("\t");
 4116    3   	        three_counter = 48;
 4117    3   	       }
 4118    2   	     else
 4119    2   	       {
 4120    3   	        add_message ("\n");
 4121    3   	        three_counter = 0;
 4122    3   	       }
 4123    2   	
 4124    2   	     file_count ++;
 4125    2   	
 4126    2   	     goto again;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 30
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4127    2   	   }
 4128    1   	  else if (status == RMS$_FNF)
 4129    1   	    add_message ("File not found!\n");
 4130    1   	  else if (status == RMS$_DNF)
 4131    1   	    add_message ("Directory not found!\n");
 4132    1   	  else if (status == RMS$_NMF)
 4133    1   	    ;  /* Do nothing.  We go to the end of the list. */
 4134    1   	  else if (status == RMS$_SYN)
 4135    1   	    add_message ("File syntax error.  (Don't confuse me!)\n");
 4136    1   	  else if (status == RMS$_FND)
 4137    1   	    add_message ("File messed up in a big way, call a god.\n");
 4138    1   	  else
 4139    1   	     if (! (status & 1))
 4140    1   	       {
 4141    2   	        printf ("list_files () error status code = %X\n", status);
 4142    2   	        add_message ("Wierd error code on list_files (), have a god check the log.\n");
 4143    2   	        /*** This crashes the game on all those wierd errors ***/
 4144    2   	        /*** I don't catch. ***/
 4145    2   	/*        lib$signal (status);*/
 4146    2   	       }
 4147    1   	
 4148    1   	  if (status == RMS$_NMF)
 4149    1   	    {
 4150    2   	     if (three_counter != 0)
 4151    2   	       add_message ("\n");
 4152    2   	     if (file_count == 1)
 4153    2   	       add_message ("One file found.\n");
 4154    2   	     else
 4155    2   	       add_message ("%d files found.\n", file_count);
 4156    2   	    }
 4157    1   	
 4158    1   	 /*** Free up file_find context memory. ***/
 4159    1   	 lib$find_file_end (&context);
 4160    1   	}
 4161        	
 4162        	
 4163        	void
 4164        	copy_file (src, dst)
 4165        	     char *src, *dst;
 4166        	{
 4167    1   	  FILE *src_f, *dst_f;
 4168    1   	  int c;
 4169    1   	
 4170    1   	  src = check_file_name (src, 0);
 4171    1   	  dst = check_file_name (dst, 1);
 4172    1   	  if (src == 0 || dst == 0)
 4173    1   	    return;
 4174    1   	  src_f = fopen (src, "r");
 4175    1   	  if (src_f == 0)
 4176    1   	    return;
 4177    1   	  dst_f = fopen (dst, "w");
 4178    1   	  if (dst_f == 0)
 4179    1   	    {
 4180    2   	      fclose (src_f);
 4181    2   	      return;
 4182    2   	    }
 4183    1   	  while ((c = fgetc (src_f)) != EOF)

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 31
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4184    1   	    fputc (c, dst_f);
 4185    1   	  fclose (src_f);
 4186    1   	  fclose (dst_f);
 4187    1   	}
 4188        	
 4189        	void
 4190        	rename_file (src, dst)
 4191        	     char *src, *dst;
 4192        	{
 4193    1   	  extern int sys_nerr;
 4194    1   	  extern char *sys_errlist[];
 4195    1   	
 4196    1   	  src = check_file_name (src, 0);
 4197    1   	  dst = check_file_name (dst, 1);
 4198    1   	  if (src == 0 || dst == 0)
 4199    1   	    return;
 4200    1   	  if (rename (src, dst) == -1)
 4201    1   	    add_message ("rename: %s\n",
 4202    1   			 errno < sys_nerr ? sys_errlist[errno] : "unknown error");
 4203    1   	}
 4204        	int
 4205        	tail (path)
 4206        	     char *path;
 4207        	{
 4208    1   	  char buff[1000];
 4209    1   	  FILE *f;
 4210    1   	  struct stat st;
 4211    1   	  int offset;
 4212    1   	
 4213    1   	  path = check_file_name (path, 0);
 4214    1   	  if (path == 0)
 4215    1   	    return 0;
 4216    1   	  f = fopen (path, "r");
 4217    1   	  if (f == 0)
 4218    1   	    return 0;
 4219    1   	  if (fstat (fileno (f), &st) == -1)
 4220    1   	    fatal ("Could not stat an open file.\n");
 4221    1   	  offset = st.st_size - 54 * 20;
 4222    1   	  if (offset < 0)
 4223    1   	    offset = 0;
 4224    1   	  if (fseek (f, offset, 0) == -1)
 4225    1   	    fatal ("Could not seek.\n");
 4226    1   	  /* Throw away the first incomplete line. */
 4227    1   	  if (offset > 0)
 4228    1   	    (void) fgets (buff, sizeof buff, f);
 4229    1   	  while (fgets (buff, sizeof buff, f))
 4230    1   	    {
 4231    2   	      add_message ("%s", buff);
 4232    2   	    }
 4233    1   	  fclose (f);
 4234    1   	  return 1;
 4235    1   	}
 4236        	
 4237        	void
 4238        	remove_file (path)
 4239        	     char *path;
 4240        	{

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 32
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4241    1   	  path = check_file_name (path, 1);
 4242    1   	  if (path == 0)
 4243    1   	    return;
 4244    1   	  if (unlink (path) == -1)
 4245    1   	    add_message ("No such file: %s\n", path);
 4246    1   	  return;
 4247    1   	}
 4248        	
 4249        	void
 4250        	people ()
 4251        	{
 4252    1   	  struct object *ob;
 4253    1   	  struct value *player;
 4254    1   	
 4255    1   	  for (ob = obj_list; ob; ob = ob->next_all)
 4256    1   	    {
 4257    2   	      if (!ob->interactive)
 4258    2   		continue;
 4259    2   	      player = apply ("query_name", ob, 0);
 4260    2   	      if (player == 0 || player->type != T_STRING)
 4261    2   		continue;
 4262    2   	      if (!ob->super)
 4263    2   		continue;
 4264    2   	      show_info_about (player->u.string, ob->super->name, ob->interactive);
 4265    2   	    }
 4266    1   	}
 4267        	
 4268        	void
 4269        	log_file (file, str)
 4270        	     char *file, *str;
 4271        	{
 4272    1   	  FILE *f;
 4273    1   	  char file_name[100];
 4274    1   	
 4275    1   	  if (strchr (file, '/') || file[0] == '.' || strlen (file) > 30)
 4276    1   	    error ("Illegal file name to log_file(%s)\n", file);
 4277    1   	  sprintf (file_name, "log/%s", file);
 4278    1   	  f = fopen (file_name, "a");
 4279    1   	  if (f == 0)
 4280    1   	    return;
 4281    1   	  fwrite (str, strlen (str), 1, f);
 4282    1   	  fclose (f);
 4283    1   	}
 4284        	
 4285        	/*VARARGS1*/
 4286        	struct value *
 4287        	call_indirect (fun, arg, arg2, arg3)
 4288        	     int fun;
 4289        	     int arg, arg2, arg3;
 4290        	{
 4291    1   	  struct value *ret;
 4292    1   	  struct object *o1, *o2;
 4293    1   	
 4294    1   	  switch (fun)
 4295    1   	    {
 4296    2   	      case F_FIND_OBJECT :
 4297    2   		o1 = find_object2 ((char *) arg);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 33
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4298    2   	      if (!o1)
 4299    2   		return &const0;
 4300    2   	      ret = alloc_value ();
 4301    2   	      ret->type = T_OBJECT;
 4302    2   	      ret->u.ob = o1;
 4303    2   	      add_ref (o1, "F_FIND_OBJECT");
 4304    2   	      return ret;
 4305    2   	      case F_CONTENTS :
 4306    2   		return contents ((struct value *) arg);
 4307    2   	      case F_IN_EDITOR :
 4308    2   		if (((struct object *) arg)->destructed)
 4309    2   		return &const0;
 4310    2   	      if (((struct object *) arg)->interactive &&
 4311    2   		  ((struct object *) arg)->ed_buffer)
 4312    2   		return &const1;
 4313    2   	      return &const0;
 4314    2   	      case F_SEARCHA :
 4315    2   		return search_array ((struct vector *) arg, (struct value *) arg2, arg3);
 4316    2   	      case F_SNOOP :
 4317    2   		if (arg && ((struct object *) arg)->destructed)
 4318    2   		error ("snoop() on destructed object.\n");
 4319    2   	      if (!current_object->interactive)
 4320    2   		error ("snoop() from non-interactive object!\n");
 4321    2   	      set_snoop (current_object, (struct object *) arg);
 4322    2   	      return 0;
 4323    2   	      case F_SET_HEART_BEAT :
 4324    2   		if (set_heart_beat (current_object, arg))
 4325    2   		return &const1;
 4326    2   	      else
 4327    2   		return &const0;
 4328    2   	      case F_READ_FILE :
 4329    2   	      {
 4330    3   		char *str = read_file ((char *) arg, arg2);
 4331    3   		if (str)
 4332    3   		  return make_string (str);
 4333    3   		return &const0;
 4334    3   	      }
 4335    2   	      case F_LOG_FILE :
 4336    2   		log_file ((char *) arg, (char *) arg2);
 4337    2   	      return 0;
 4338    2   	      case F_SHUTDOWN :
 4339    2   		startshutdowngame ();
 4340    2   	      return 0;
 4341    2   	      case F_LIVING :
 4342    2   		if (((struct object *) arg)->destructed)
 4343    2   		return &const0;
 4344    2   	      ret = alloc_value ();
 4345    2   	      ret->type = T_NUMBER;
 4346    2   	      ret->u.number = ((struct object *) arg)->enable_commands;
 4347    2   	      return ret;
 4348    2   	      case F_ED :
 4349    2   		if (arg && !legal_path ((char *) arg))
 4350    2   		{
 4351    3   		  add_message ("Illegal path\n");
 4352    3   		  return 0;
 4353    3   		}
 4354    2   	      ed_start ((char *) arg);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 34
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4355    2   	      return 0;
 4356    2   	      case F_TELL_OBJECT :
 4357    2   		if (((struct object *) arg)->destructed)
 4358    2   		error ("Tell_object to destructed object./\n");
 4359    2   	      tell_object ((struct object *) arg, (char *) arg2);
 4360    2   	      return 0;
 4361    2   	      case F_RM :
 4362    2   		remove_file ((char *) arg);
 4363    2   	      return 0;
 4364    2   	      case F_LS :
 4365    2   		list_files ((char *) arg, (char *) 0);
 4366    2   	      return 0;
 4367    2   	      case F_CAT :
 4368    2   		return make_number (print_file ((char *) arg, arg2, arg3));
 4369    2   	      case F_CP :
 4370    2   		copy_file ((char *) arg, (char *) arg2);
 4371    2   	      return &const0;
 4372    2   	      case F_RENAME :
 4373    2   		rename_file ((char *) arg, (char *) arg2);
 4374    2   	      return &const0;
 4375    2   	      case F_INPUT_TO :
 4376    2   		if (current_object->destructed)
 4377    2   		error ("input_to() on destructed object.\n");
 4378    2   	      return input_to ((char *) arg, arg2);
 4379    2   	      break;
 4380    2   	      case F_ENABLE_COMMANDS :
 4381    2   		enable_commands (1);
 4382    2   	      return 0;
 4383    2   	      case F_INTERACTIVE :
 4384    2   		if (((struct object *) arg)->destructed)
 4385    2   		return &const0;
 4386    2   	      if (((struct object *) arg)->interactive)
 4387    2   		return &const1;
 4388    2   	      return &const0;
 4389    2   	      case F_FIRST_INVENTORY :
 4390    2   		return first_inventory ((struct value *) arg);
 4391    2   	      case F_NEXT_INVENTORY :
 4392    2   		return next_inventory ((struct value *) arg);
 4393    2   	      case F_SHOUT :
 4394    2   		shout_string ((char *) arg);
 4395    2   	      return 0;
 4396    2   	      case F_SAY :
 4397    2   		say ((struct value *) arg, (struct object *) arg2);
 4398    2   	      return 0;
 4399    2   	      case F_TELL_ROOM :
 4400    2   		if (((struct object *) arg)->destructed)
 4401    2   		error ("tell_room to destructed object.\n");
 4402    2   	      tell_room ((struct object *) arg, (struct value *) arg2);
 4403    2   	      return 0;
 4404    2   	      case F_CREATE_WIZARD :
 4405    2   		return create_wizard ((char *) arg);
 4406    2   	      case F_DESTRUCT :
 4407    2   		destruct_object ((struct value *) arg);
 4408    2   	      return 0;
 4409    2   	      case F_SET_LIGHT :
 4410    2   		add_light (current_object, arg);
 4411    2   	      ret = alloc_value ();

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 35
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4412    2   	      ret->type = T_NUMBER;
 4413    2   	      o1 = current_object;
 4414    2   	      while (o1->super)
 4415    2   		o1 = o1->super;
 4416    2   	      ret->u.number = o1->total_light;
 4417    2   	      return ret;
 4418    2   	      case F_COMMAND :
 4419    2   		if (command_for_object ((char *) arg, (struct object *) arg2))
 4420    2   		return &const1;
 4421    2   	      else
 4422    2   		return &const0;
 4423    2   	      case F_PRESENT :
 4424    2   		if (arg2 && ((struct object *) arg2)->destructed)
 4425    2   		error ("present() on destructed object.\n");
 4426    2   	      return object_present ((struct value *) arg, (struct object *) arg2);
 4427    2   	      case F_ENVIRONMENT :
 4428    2   		return environment ((struct value *) arg);
 4429    2   	      case F_SAVE_OBJECT :
 4430    2   		save_object (current_object, (char *) arg);
 4431    2   	      return 0;
 4432    2   	      case F_RESTORE_OBJECT :
 4433    2   		ret = alloc_value ();
 4434    2   	      ret->type = T_NUMBER;
 4435    2   	      ret->u.number = restore_object (current_object, (char *) arg);
 4436    2   	      return ret;
 4437    2   	      case F_CLONE_OBJECT :
 4438    2   		return clone_object ((char *) arg);
 4439    2   	      case F_FUNCTION :
 4440    2   		return call_local_function ((char *) arg, (struct value *) arg2);
 4441    2   	      case F_CALL_OTHER :
 4442    2   		return call_other ((struct value *) arg, (char *) arg2,
 4443    2   				   (struct value *) arg3);
 4444    2   	      case F_WRITE :
 4445    2   		do_write ((struct value *) arg);
 4446    2   	      break;
 4447    2   	      case F_MOVE_OBJECT :
 4448    2   		if (((struct value *) arg)->type == T_OBJECT)
 4449    2   		o1 = ((struct value *) arg)->u.ob;
 4450    2   	      else
 4451    2   		{
 4452    3   		  o1 = find_object (((struct value *) arg)->u.string);
 4453    3   		  if (o1 == 0)
 4454    3   		    error ("Object %s not found.\n", ((struct value *) arg)->u.string);
 4455    3   		}
 4456    2   	      if (((struct value *) arg2)->type == T_OBJECT)
 4457    2   		o2 = ((struct value *) arg2)->u.ob;
 4458    2   	      else
 4459    2   		{
 4460    3   		  o2 = find_object (((struct value *) arg2)->u.string);
 4461    3   		  if (o2 == 0)
 4462    3   		    error ("Object %s not found.\n", ((struct value *) arg2)->u.string);
 4463    3   		}
 4464    2   	      if (((struct object *) o1)->destructed)
 4465    2   		error ("move_object() of destructed object.\n");
 4466    2   	      if (((struct object *) o2)->destructed)
 4467    2   		error ("move_object() to destructed object.\n");
 4468    2   	      move_object (o1, o2);

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 36
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4469    2   	      break;
 4470    2   	      case F_ADD_VERB :
 4471    2   		add_verb ((char *) arg, 0);
 4472    2   	      break;
 4473    2   	      case F_ADD_XVERB :
 4474    2   		add_verb ((char *) arg, 1);
 4475    2   	      break;
 4476    2   	      case F_GREP :
 4477    2   		grep_file ((char *) arg, (char *) arg2, (char *) arg3);
 4478    2   	      return &const0;
 4479    2   	      case F_THIS_PLAYER :
 4480    2   		return this_player ();
 4481    2   	      case F_CALLER :
 4482    2   		return caller ();
 4483    2   	      case F_THIS_OBJECT :
 4484    2   		return this_object ();
 4485    2   	      default :
 4486    2   		fatal ("Unimplemented hard linked function %d\n", fun);
 4487    2   	      abort ();
 4488    2   	    }
 4489    1   	  return 0;
 4490    1   	}
 4491        	
 4492        	void
 4493        	do_write (arg)
 4494        	     struct value *arg;
 4495        	{
 4496    1   	  if (arg == 0)
 4497    1   	    add_message ("<NULL>");
 4498    1   	  else if (arg->type == T_STRING)
 4499    1   	    {
 4500    2   	      if (strlen (arg->u.string) > 9500)	/* Not pretty */
 4501    2   		error ("Too long string.\n");
 4502    2   	      add_message ("%s", arg->u.string);
 4503    2   	    }
 4504    1   	  else if (arg->type == T_OBJECT)
 4505    1   	    add_message ("OBJ(%s)", arg->u.ob->name);
 4506    1   	  else if (arg->type == T_NUMBER)
 4507    1   	    add_message ("%d", arg->u.number);
 4508    1   	  else
 4509    1   	    add_message ("<UNKNOWN>");
 4510    1   	}
 4511        	
 4512        	/* Find an object. If not loaded, load it ! */
 4513        	
 4514        	struct object *
 4515        	find_object (str)
 4516        	     char *str;
 4517        	{
 4518    1   	  struct object *ob;
 4519    1   	
 4520    1   	  /* Remove leading '/' if any. */
 4521    1   	  while (str[0] == '/')
 4522    1   	    str++;
 4523    1   	  ob = find_object2 (str);
 4524    1   	  if (ob)
 4525    1   	    return ob;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 37
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4526    1   	  ob = load_object (str);
 4527    1   	  if (ob->destructed)		/* *sigh* */
 4528    1   	    return 0;
 4529    1   	  if (ob->swapped)
 4530    1   	    load_ob_from_swap (ob);
 4531    1   	  return ob;
 4532    1   	}
 4533        	
 4534        	/* Look for a loaded object. */
 4535        	struct object *
 4536        	find_object2 (str)
 4537        	     char *str;
 4538        	{
 4539    1   	  register struct object *ob;
 4540    1   	  register int length;
 4541    1   	  char *name;
 4542    1   	
 4543    1   	  /* Remove leading '/' if any. */
 4544    1   	  while (str[0] == '/')
 4545    1   	    str++;
 4546    1   	  /* Truncate possible .c in the object name. */
 4547    1   	  length = strlen (str);
 4548    1   	  name = string_copy (str);
 4549    1   	  if (name[length - 2] == '.' && name[length - 1] == 'c')
 4550    1   	    {
 4551    2   	      name[length - 2] = '\0';
 4552    2   	      length -= 2;
 4553    2   	    }
 4554    1   	  if (ob = lookup_object_hash (name))
 4555    1   	    {
 4556    2   	      free (name);
 4557    2   	      if (ob->swapped)
 4558    2   		load_ob_from_swap (ob);
 4559    2   	      return ob;
 4560    2   	    }
 4561    1   	  free (name);
 4562    1   	  return 0;
 4563    1   	}
 4564        	
 4565        	void
 4566        	apply_command (com)
 4567        	     char *com;
 4568        	{
 4569    1   	  struct value *ret;
 4570    1   	
 4571    1   	  if (command_giver == 0)
 4572    1   	    error ("command_giver == 0 !\n");
 4573    1   	  ret = apply (com, command_giver->super, 0);
 4574    1   	  if (ret != 0)
 4575    1   	    {
 4576    2   	      add_message ("Result:");
 4577    2   	      if (ret->type == T_STRING)
 4578    2   		add_message ("%s\n", ret->u.string);
 4579    2   	      if (ret->type == T_NUMBER)
 4580    2   		add_message ("%d\n", ret->u.number);
 4581    2   	    }
 4582    1   	  else

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 38
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4583    1   	    {
 4584    2   	      add_message ("Error apply_command: function %s not found.\n", com);
 4585    2   	    }
 4586    1   	}
 4587        	
 4588        	#if 0
 4589   X    	/* This is merged into move_object() */
 4590   X    	void
 4591   X    	set_current_room (ob, dest)
 4592   X    	     struct object *ob, *dest;
 4593   X    	{
 4594   X    	  struct object **pp, *p;
 4595   X    	  struct object *save_command_giver = command_giver;
 4596   X    	
 4597   X    	  if (dest == 0)
 4598   X    	    dest = find_object ("room/void.c");	/* Get any existing void. */
 4599   X    	  if (dest == 0)
 4600   X    	    fatal ("Not even a void !\n");
 4601   X    	  command_giver = ob;
 4602   X    	  if (ob->super)
 4603   X    	    {
 4604   X    	      struct value v;
 4605   X    	
 4606   X    	      v.type = T_OBJECT;
 4607   X    	      v.u.ob = ob;		/* No need to increment ref count */
 4608   X    	      (void) apply ("exit", ob->super, &v);
 4609   X    	      add_light (ob->super, -ob->total_light);
 4610   X    	      remove_sent (ob->super, ob);
 4611   X    	      /*
 4612   X    	       * Now we link the ob out of its list.
 4613   X    	       * Remove sentences tied to objects that stays in this room.
 4614   X    	       */
 4615   X    	      for (pp = &ob->super->contains; *pp;)
 4616   X    		{
 4617   X    		  if (*pp == ob)
 4618   X    		    *pp = (*pp)->next_inv;
 4619   X    		  else
 4620   X    		    {
 4621   X    		      remove_sent (*pp, ob);
 4622   X    		      pp = &(*pp)->next_inv;
 4623   X    		    }
 4624   X    		}
 4625   X    	    }
 4626   X    	  ob->next_inv = dest->contains;
 4627   X    	  dest->contains = ob;
 4628   X    	  add_light (dest, ob->total_light);
 4629   X    	  ob->super = dest;
 4630   X    	  if (d_flag)
 4631   X    	    debug_message ("--Current room: %s\n", dest->name);
 4632   X    	  (void) apply ("init", dest, 0);
 4633   X    	  for (p = dest->contains; p; p = p->next_inv)
 4634   X    	    {
 4635   X    	      if (p == ob)
 4636   X    		continue;
 4637   X    	      (void) apply ("init", p, 0);
 4638   X    	    }
 4639   X    	  command_giver = save_command_giver;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 39
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4640   X    	}
 4641   X    	
 4642        	#endif
 4643        	
 4644        	/*
 4645        	 * Transfer an object.
 4646        	 * The object has to be taken from one inventory list and added to another.
 4647        	 * The main work is to update all command definitions, depending on what is
 4648        	 * living or not. Note that all objects in the same inventory are affected.
 4649        	 */
 4650        	void
 4651        	move_object (item, dest)
 4652        	     struct object *item, *dest;
 4653        	{
 4654    1   	  struct object **pp, *ob;
 4655    1   	  struct object *save_cmd = command_giver;
 4656    1   	
 4657    1   	  /* Recursive moves are not allowed. */
 4658    1   	  for (ob = dest; ob; ob = ob->super)
 4659    1   	    if (ob == item)
 4660    1   	      return;
 4661    1   	  if (item->last_reset < (current_time - RESET_TIME * 60))
 4662    1   	    {
 4663    2   	      item->last_reset = current_time;
 4664    2   	      (void) apply ("reset", item, &const1);
 4665    2   	      if (item->destructed)
 4666    2   		return;
 4667    2   	    }
 4668    1   	  if (dest->last_reset < (current_time - RESET_TIME * 60))
 4669    1   	    {
 4670    2   	      dest->last_reset = current_time;
 4671    2   	      (void) apply ("reset", dest, &const1);
 4672    2   	      if (dest->destructed)
 4673    2   		return;
 4674    2   	    }
 4675    1   	  if (item->super)
 4676    1   	    {
 4677    2   	      int okey = 0;
 4678    2   	
 4679    2   	      if (item->enable_commands)
 4680    2   		{
 4681    3   		  struct value v;
 4682    3   	
 4683    3   		  v.type = T_OBJECT;
 4684    3   		  v.u.ob = item;	/* No need to increment ref count */
 4685    3   		  command_giver = item;
 4686    3   		  (void) apply ("exit", item->super, &v);
 4687    3   		  remove_sent (item->super, item);
 4688    3   		}
 4689    2   	      if (item->super->enable_commands)
 4690    2   		remove_sent (item, item->super);
 4691    2   	      add_light (item->super, -item->total_light);
 4692    2   	      for (pp = &item->super->contains; *pp;)
 4693    2   		{
 4694    3   		  if (*pp != item)
 4695    3   		    {
 4696    4   		      if ((*pp)->enable_commands)

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 40
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4697    4   			remove_sent (item, *pp);
 4698    4   		      if (item->enable_commands)
 4699    4   			remove_sent (*pp, item);
 4700    4   		      pp = &(*pp)->next_inv;
 4701    4   		      continue;
 4702    4   		    }
 4703    3   		  *pp = item->next_inv;
 4704    3   		  okey = 1;
 4705    3   		}
 4706    2   	      if (!okey)
 4707    2   		fatal ("Failed to find object %s in super list of %s.\n",
 4708    2   		       item->name, item->super->name);
 4709    2   	    }
 4710    1   	  item->next_inv = dest->contains;
 4711    1   	  dest->contains = item;
 4712    1   	  item->super = dest;
 4713    1   	  /*
 4714    1   	   * Setup the new commands. The order is very important, as commands
 4715    1   	   * in the room should override commands defined by the room.
 4716    1   	   */
 4717    1   	  if (item->enable_commands)
 4718    1   	    {
 4719    2   	      command_giver = item;
 4720    2   	      (void) apply ("init", dest, 0);
 4721    2   	      if (dest->destructed)
 4722    2   		return;
 4723    2   	    }
 4724    1   	  /*
 4725    1   	   * Run init of the item once for every present player, and
 4726    1   	   * for the environment (which can be a player).
 4727    1   	   */
 4728    1   	  for (ob = dest->contains; ob; ob = ob->next_inv)
 4729    1   	    {
 4730    2   	      if (ob == item)
 4731    2   		continue;
 4732    2   	      if (ob->enable_commands)
 4733    2   		{
 4734    3   		  command_giver = ob;
 4735    3   		  (void) apply ("init", item, 0);
 4736    3   		}
 4737    2   	      if (item->enable_commands)
 4738    2   		{
 4739    3   		  command_giver = item;
 4740    3   		  (void) apply ("init", ob, 0);
 4741    3   		}
 4742    2   	    }
 4743    1   	  if (dest->enable_commands)
 4744    1   	    {
 4745    2   	      command_giver = dest;
 4746    2   	      (void) apply ("init", item, 0);
 4747    2   	    }
 4748    1   	  command_giver = save_cmd;
 4749    1   	  add_light (dest, item->total_light);
 4750    1   	  if (d_flag)
 4751    1   	    debug_message ("--move_object: %s to %s\n", item->name, dest->name);
 4752    1   	}
 4753        	

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 41
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4754        	/*
 4755        	 * Every object as a count of number of light sources it contains.
 4756        	 * Update this.
 4757        	 */
 4758        	
 4759        	void
 4760        	add_light (p, n)
 4761        	     struct object *p;
 4762        	     int n;
 4763        	{
 4764    1   	  if (n == 0)
 4765    1   	    return;
 4766    1   	  p->total_light += n;
 4767    1   	  if (p->super)
 4768    1   	    add_light (p->super, n);
 4769    1   	}
 4770        	
 4771        	struct sentence *sent_free = 0;
 4772        	int tot_alloc_sentence;
 4773        	
 4774        	struct sentence *
 4775        	alloc_sentence ()
 4776        	{
 4777    1   	  struct sentence *p;
 4778    1   	
 4779    1   	  if (sent_free == 0)
 4780    1   	    {
 4781    2   	      p = (struct sentence *) xalloc (sizeof *p);
 4782    2   	      tot_alloc_sentence++;
 4783    2   	    }
 4784    1   	  else
 4785    1   	    {
 4786    2   	      p = sent_free;
 4787    2   	      sent_free = sent_free->next;
 4788    2   	    }
 4789    1   	  p->verb = 0;
 4790    1   	  p->function = 0;
 4791    1   	  p->next = 0;
 4792    1   	  p->no_space = 0;
 4793    1   	  p->short_verb = 0;
 4794    1   	  return p;
 4795    1   	}
 4796        	
 4797        	#ifdef free
 4798   X    	void
 4799   X    	free_all_sent ()
 4800   X    	{
 4801   X    	  struct sentence *p;
 4802   X    	  for (; sent_free; sent_free = p)
 4803   X    	    {
 4804   X    	      p = sent_free->next;
 4805   X    	      free (sent_free);
 4806   X    	    }
 4807   X    	}
 4808   X    	
 4809        	#endif
 4810        	

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 42
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4811        	void
 4812        	free_sentence (p)
 4813        	     struct sentence *p;
 4814        	{
 4815    1   	  if (p->function)
 4816    1   	    free_string (p->function);
 4817    1   	  p->function = 0;
 4818    1   	  if (p->verb)
 4819    1   	    free_string (p->verb);
 4820    1   	  p->verb = 0;
 4821    1   	  p->next = sent_free;
 4822    1   	  sent_free = p;
 4823    1   	}
 4824        	
 4825        	/*
 4826        	 * Find the sentence for a command from the player.
 4827        	 * Return success status.
 4828        	 */
 4829        	int
 4830        	player_parser (buff)
 4831        	     char *buff;
 4832        	{
 4833    1   	  struct sentence *s;
 4834    1   	  char *p;
 4835    1   	  int length;
 4836    1   	  struct object *save_current_object = current_object;
 4837    1   	  char verb_copy[20];
 4838    1   	
 4839    1   	  if (d_flag)
 4840    1   	    debug_message ("cmd [%s]: %s\n", command_giver->name, buff);
 4841    1   	  /* strip trailing spaces. */
 4842    1   	  for (p = buff + strlen (buff) - 1; p > buff; p--)
 4843    1   	    {
 4844    2   	      if (*p != ' ')
 4845    2   		break;
 4846    2   	      *p = '\0';
 4847    2   	    }
 4848    1   	  if (buff[0] == '\0')
 4849    1   	    return 0;
 4850    1   	  if (special_parse (buff))
 4851    1   	    return 1;
 4852    1   	  p = strchr (buff, ' ');
 4853    1   	  if (p == 0)
 4854    1   	    length = strlen (buff);
 4855    1   	  else
 4856    1   	    length = p - buff;
 4857    1   	  clear_notify ();
 4858    1   	  for (s = command_giver->sent;
 4859    1   	       s && command_giver && !command_giver->destructed;
 4860    1   	       s = (s ? s->next : 0))
 4861    1   	    {
 4862    2   	      struct value *ret;
 4863    2   	      struct value arg;
 4864    2   	      int len;
 4865    2   	
 4866    2   	      if (s->verb == 0)
 4867    2   		continue;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 43
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4868    2   	      len = strlen (s->verb);
 4869    2   	      if (s->no_space)
 4870    2   		{
 4871    3   		  if (strncmp (buff, s->verb, len) != 0)
 4872    3   		    continue;
 4873    3   		}
 4874    2   	      else if (s->short_verb)
 4875    2   		{
 4876    3   		  if (strncmp (s->verb, buff, len) != 0)
 4877    3   		    continue;
 4878    3   		}
 4879    2   	      else
 4880    2   		{
 4881    3   		  if (strlen (s->verb) != length)
 4882    3   		    continue;
 4883    3   		  if (strncmp (buff, s->verb, length) != 0)
 4884    3   		    continue;
 4885    3   		}
 4886    2   	      /*
 4887    2   	       * Now we have found a special sentence !
 4888    2   	       */
 4889    2   	      if (d_flag)
 4890    2   		debug_message ("Local command %s on %s\n", s->function, s->ob->name);
 4891    2   	      if (length > sizeof verb_copy)
 4892    2   		len = sizeof verb_copy - 1;
 4893    2   	      else
 4894    2   		len = length;
 4895    2   	      strncpy (verb_copy, buff, len);
 4896    2   	      verb_copy[len] = '\0';
 4897    2   	      last_verb = verb_copy;
 4898    2   	      /*
 4899    2   	       * If the function is static and not defined by current object,
 4900    2   	       * then it will fail. If this is called directly from player input,
 4901    2   	       * then we set current_object so that static functions are allowed.
 4902    2   	       */
 4903    2   	      if (current_object == 0)
 4904    2   		current_object = s->ob;
 4905    2   	      if (s->no_space)
 4906    2   		{
 4907    3   		  arg.type = T_STRING;
 4908    3   		  arg.u.string = &buff[strlen (s->verb)];
 4909    3   		  ret = apply (s->function, s->ob, &arg);
 4910    3   		}
 4911    2   	      else if (buff[length] == ' ')
 4912    2   		{
 4913    3   		  arg.type = T_STRING;
 4914    3   		  arg.u.string = &buff[length + 1];
 4915    3   		  ret = apply (s->function, s->ob, &arg);
 4916    3   		}
 4917    2   	      else
 4918    2   		{
 4919    3   		  ret = apply (s->function, s->ob, 0);
 4920    3   		}
 4921    2   	      if (current_object->destructed)
 4922    2   		s = command_giver->sent;/* Restart :-( */
 4923    2   	      last_verb = 0;
 4924    2   	      current_object = save_current_object;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 44
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4925    2   	      /* If we get fail from the call, it was wrong second argument. */
 4926    2   	      if (ret && ret->type == T_NUMBER && ret->u.number == 0)
 4927    2   		continue;
 4928    2   	#if 0
 4929   X    	      if (s && s->ob && s->ob->wl && command_giver->interactive &&
 4930   X    		  !command_giver->is_wizard)
 4931   X    		s->ob->wl->score++;
 4932    2   	#endif
 4933    2   	      if (ret == 0)
 4934    2   		add_message ("Error: function %s not found.\n", s->function);
 4935    2   	      break;
 4936    2   	    }
 4937    1   	  if (s == 0)
 4938    1   	    {
 4939    2   	      notify_no_command ();
 4940    2   	      return 0;
 4941    2   	    }
 4942    1   	  return 1;
 4943    1   	}
 4944        	
 4945        	
 4946        	/*
 4947        	 * Associate a command with function in this object.
 4948        	 * The optional second argument is the command name. If the command name
 4949        	 * is not given here, it should be given with add_verb().
 4950        	 *
 4951        	 * The optinal third argument is a flag that will state that the verb should
 4952        	 * only match against leading characters.
 4953        	 *
 4954        	 * The object must be near the command giver, so that we ensure that the
 4955        	 * sentence is removed when the command giver leaves.
 4956        	 */
 4957        	void
 4958        	add_action (str, cmd, flag)
 4959        	     char *str, *cmd;
 4960        	     int flag;
 4961        	{
 4962    1   	  struct sentence *p;
 4963    1   	
 4964    1   	  if (command_giver == 0)
 4965    1   	    return;
 4966    1   	  if (current_object != command_giver &&
 4967    1   	      current_object->super != command_giver &&
 4968    1   	      current_object->super != command_giver->super &&
 4969    1   	      current_object != command_giver->super)
 4970    1   	    error ("add_action from object that was not present.\n");
 4971    1   	  if (d_flag)
 4972    1   	    debug_message ("--Add action %s\n", str);
 4973    1   	  if (strcmp (str, "exit") == 0)
 4974    1   	    error ("Illegal to define a command to the exit() function.\n");
 4975    1   	  p = alloc_sentence ();
 4976    1   	  p->function = make_shared_string (str);
 4977    1   	  p->ob = current_object;
 4978    1   	  p->next = command_giver->sent;
 4979    1   	  p->short_verb = flag;
 4980    1   	  p->no_space = 0;
 4981    1   	  if (cmd)

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 45
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 4982    1   	    p->verb = make_shared_string (cmd);
 4983    1   	  else
 4984    1   	    p->verb = 0;
 4985    1   	  command_giver->sent = p;
 4986    1   	}
 4987        	
 4988        	void
 4989        	add_verb (str, no_space)
 4990        	     char *str;
 4991        	     int no_space;
 4992        	{
 4993    1   	  if (command_giver == 0)
 4994    1   	    return;
 4995    1   	  if (command_giver->sent == 0)
 4996    1   	    error ("No add_action().\n");
 4997    1   	  if (command_giver->sent->verb != 0)
 4998    1   	    error ("Tried to set verb again.\n");
 4999    1   	  command_giver->sent->verb = make_shared_string (str);
 5000    1   	  command_giver->sent->no_space = no_space;
 5001    1   	  command_giver->sent->short_verb = 0;
 5002    1   	  if (d_flag)
 5003    1   	    debug_message ("--Adding verb %s to action %s\n", str,
 5004    1   			   command_giver->sent->function);
 5005    1   	}
 5006        	
 5007        	void
 5008        	remove_sent (ob, player)
 5009        	     struct object *ob, *player;
 5010        	{
 5011    1   	  struct sentence **s;
 5012    1   	
 5013    1   	  for (s = &player->sent; *s;)
 5014    1   	    {
 5015    2   	      struct sentence *tmp;
 5016    2   	      if ((*s)->ob == ob)
 5017    2   		{
 5018    3   		  if (d_flag)
 5019    3   		    debug_message ("--Unlinking sentence %s\n", (*s)->function);
 5020    3   		  tmp = *s;
 5021    3   		  *s = tmp->next;
 5022    3   		  free_sentence (tmp);
 5023    3   		}
 5024    2   	      else
 5025    2   		s = &((*s)->next);
 5026    2   	    }
 5027    1   	}
 5028        	
 5029        	#if 0
 5030   X    	/* This function has been replaced by using users(). */
 5031   X    	void
 5032   X    	display_all_players ()
 5033   X    	{
 5034   X    	  struct object *ob;
 5035   X    	  struct value *ret;
 5036   X    	
 5037   X    	  for (ob = obj_list; ob; ob = ob->next_all)
 5038   X    	    {

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 46
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5039   X    	      if (ob->interactive == 0)
 5040   X    		continue;
 5041   X    	      ret = apply ("short", ob, 0);
 5042   X    	      if (ret && ret->type == T_STRING)
 5043   X    		add_message ("%s.\n", ret->u.string);
 5044   X    	    }
 5045   X    	}
 5046   X    	
 5047        	#endif
 5048        	
 5049        	char debug_parse_buff[50];	/* Used for debugging */
 5050        	
 5051        	int
 5052        	special_parse (buff)
 5053        	     char *buff;
 5054        	{
 5055    1   	/*
 5056    1   	    if (strcmp(buff, "who") == 0) {
 5057    1   		display_all_players();
 5058    1   		return 1;
 5059    1   	    }
 5060    1   	*/
 5061    1   	  strncpy (debug_parse_buff, buff, sizeof debug_parse_buff);
 5062    1   	  if (strcmp (buff, "malloc") == 0)
 5063    1   	    {
 5064    2   	#if defined(MALLOC_malloc) || defined(MALLOC_smalloc)
 5065   X    	      dump_malloc_data ();
 5066    2   	#endif
 5067    2   	#ifdef MALLOC_gmalloc
 5068   X    	      add_message ("Using Gnu malloc.\n");
 5069    2   	#endif
 5070    2   	      return 1;
 5071    2   	    }
 5072    1   	  if (strcmp (buff, "dumpallobj") == 0)
 5073    1   	    {
 5074    2   	      dumpstat ();
 5075    2   	      return 1;
 5076    2   	    }
 5077    1   	#if defined(MALLOC_malloc) || defined(MALLOC_smalloc)
 5078   X    	  if (strcmp (buff, "debugmalloc") == 0)
 5079   X    	    {
 5080   X    	      extern int debugmalloc;
 5081   X    	      debugmalloc = !debugmalloc;
 5082   X    	      if (debugmalloc)
 5083   X    		add_message ("On.\n");
 5084   X    	      else
 5085   X    		add_message ("Off.\n");
 5086   X    	      return 1;
 5087   X    	    }
 5088    1   	#endif
 5089    1   	  if (strcmp (buff, "status") == 0)
 5090    1   	    {
 5091    2   	      extern int tot_alloc_sentence, tot_alloc_value, tot_alloc_object,
 5092    2   	       num_swapped, total_bytes_swapped, tot_string_space;
 5093    2   	      extern int total_num_prog_blocks, total_prog_block_size;
 5094    2   	      add_message ("Sentences:   %5d %6d\n", tot_alloc_sentence,
 5095    2   			   tot_alloc_sentence * sizeof (struct sentence));

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 47
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5096    2   	      add_message ("Objects:     %5d %6d (%d swapped, %d Kbyte)\n",
 5097    2   			   tot_alloc_object,
 5098    2   			   tot_alloc_object * sizeof (struct object), num_swapped,
 5099    2   			   total_bytes_swapped / 1024);
 5100    2   	      add_message ("Prog blocks: %5d %6d\n", total_num_prog_blocks,
 5101    2   			   total_prog_block_size);
 5102    2   	      add_message ("Values:      %5d %6d\n\n", tot_alloc_value,
 5103    2   			   tot_alloc_value * sizeof (struct value));
 5104    2   	      status_lnodes_matched ();
 5105    2   	      stat_living_objects ();
 5106    2   	      print_lnode_status (tot_alloc_sentence * sizeof (struct sentence) +
 5107    2   				  tot_alloc_object * sizeof (struct object) +
 5108    2   				  tot_alloc_value * sizeof (struct value) +
 5109    2   				  total_prog_block_size +
 5110    2   				  show_otable_status () +
 5111    2   				  heart_beat_status () +
 5112    2   				  add_string_status () +
 5113    2   				  print_call_out_usage ());
 5114    2   	      return 1;
 5115    2   	    }
 5116    1   	  return 0;
 5117    1   	}
 5118        	
 5119        	void
 5120        	print_local_commands ()
 5121        	{
 5122    1   	  struct sentence *s;
 5123    1   	
 5124    1   	  add_message ("Current local commands:\n");
 5125    1   	  for (s = command_giver->sent; s; s = s->next)
 5126    1   	    add_message ("%s ", s->verb);
 5127    1   	  add_message ("\n");
 5128    1   	}
 5129        	
 5130        	/*
 5131        	 * Error() has been "fixed" so that users can catch and throw them.
 5132        	 * To catch them nicely, we really have to provide decent error information.
 5133        	 * Hence, all errors that are to be caught
 5134        	 * (error_recovery_context_exists == 2) construct a string containing
 5135        	 * the error message, which is returned as the
 5136        	 * thrown value.  Users can throw their own error values however they choose.
 5137        	 */
 5138        	
 5139        	/*
 5140        	 * This is here because throw constructs its own return value; we dont
 5141        	 * want to replace it with the system's error string.
 5142        	 */
 5143        	
 5144        	void
 5145        	throw_error ()
 5146        	{
 5147    1   	  extern int error_recovery_context_exists;
 5148    1   	  extern jmp_buf error_recovery_context;
 5149    1   	  if (error_recovery_context_exists > 1)
 5150    1   	    {
 5151    2   	      longjmp (error_recovery_context, 1);
 5152    2   	      fatal ("Throw_error failed!");

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 48
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5153    2   	    }
 5154    1   	  error ("Throw with no catch.\n");
 5155    1   	}
 5156        	
 5157        	static char emsg_buf[2000];
 5158        	
 5159        	/*VARARGS1*/
 5160        	void
 5161        	fatal (fmt, a, b, c, d, e, f, g, h)
 5162        	     char *fmt;
 5163        	     int a, b, c, d, e, f, g, h;
 5164        	{
 5165    1   	  static int in_fatal = 0;
 5166    1   	  /* Prevent double fatal. */
 5167    1   	  if (in_fatal)
 5168    1   	    abort ();
 5169    1   	  in_fatal = 1;
 5170    1   	  (void) fprintf (stderr, fmt, a, b, c, d, e, f, g, h);
 5171    1   	  fflush (stderr);
 5172    1   	  if (current_object)
 5173    1   	    (void) fprintf (stderr, "Current object was %s\n",
 5174    1   			    current_object->name);
 5175    1   	  debug_message (fmt, a, b, c, d, e, f, g, h);
 5176    1   	  if (current_object)
 5177    1   	    debug_message ("Current object was %s\n", current_object->name);
 5178    1   	  debug_message ("Dump of variables:\n");
 5179    1   	#ifdef TRACE
 5180   X    	  (void) dump_trace ();
 5181    1   	#endif
 5182    1   	  abort ();
 5183    1   	}
 5184        	
 5185        	int num_error = 0;
 5186        	/*VARARGS1*/
 5187        	void
 5188        	error (fmt, a, b, c, d, e, f, g, h)
 5189        	     char *fmt;
 5190        	     int a, b, c, d, e, f, g, h;
 5191        	{
 5192    1   	  char *object_name;
 5193    1   	  extern int error_recovery_context_exists;
 5194    1   	  extern jmp_buf error_recovery_context;
 5195    1   	  extern struct object *current_heart_beat;
 5196    1   	#ifdef TRACE
 5197   X    	  extern int trace_depth;
 5198    1   	#endif
 5199    1   	
 5200    1   	  sprintf (emsg_buf + 1, fmt, a, b, c, d, e, f, g, h);
 5201    1   	  emsg_buf[0] = '*';
 5202    1   	  if (error_recovery_context_exists > 1)
 5203    1   	    {				/* user catches this error */
 5204    2   	      catch_value = make_string (emsg_buf);
 5205    2   	      longjmp (error_recovery_context, 1);
 5206    2   	      fatal ("Catch() longjump failed");
 5207    2   	    }
 5208    1   	
 5209    1   	  num_error++;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 49
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5210    1   	  if (num_error > 1)
 5211    1   	    fatal ("Too many simultaneous errors.\n");
 5212    1   	  debug_message ("%s", emsg_buf + 1 /*fmt, a, b, c, d, e, f, g, h*/ );
 5213    1   	  if (current_object)
 5214    1   	    {
 5215    2   	      debug_message ("Current object was %s, line %d\n",
 5216    2   			     current_object->name, current_line);
 5217    2   	      save_error (emsg_buf + 1, current_object->name, current_line);
 5218    2   	    }
 5219    1   	#ifdef TRACE
 5220   X    	  object_name = dump_trace ();
 5221   X    	  fflush (stdout);
 5222   X    	  if (object_name)
 5223   X    	    {
 5224   X    	      struct object *ob;
 5225   X    	      ob = find_object2 (object_name);
 5226   X    	      if (!ob)
 5227   X    		{
 5228   X    		  if (command_giver)
 5229   X    		    add_message ("error when executing program in destroyed object %s\n",
 5230   X    				 object_name);
 5231   X    		  debug_message ("error when executing program in destroyed object %s\n",
 5232   X    				 object_name);
 5233   X    		}
 5234   X    	    }
 5235   X    	  trace_depth = 0;
 5236    1   	#endif
 5237    1   	  if (command_giver)
 5238    1   	    {
 5239    2   	      add_message ("%s", emsg_buf + 1 /*fmt, a, b, c, d, e, f, g, h*/ );
 5240    2   	      if (current_object)
 5241    2   		add_message ("Current object was %s, line %d\n",
 5242    2   			     current_object->name, current_line);
 5243    2   	#if 0
 5244   X    	      if (!command_giver->destructed)
 5245   X    		{
 5246   X    		  dest = find_object ("room/void.c");	/* Get any existing void. */
 5247   X    		  if (dest == 0)
 5248   X    		    fatal ("Could not find the void room.\n");
 5249   X    		  move_object (command_giver, dest);
 5250   X    		}
 5251    2   	#endif
 5252    2   	    }
 5253    1   	  if (current_heart_beat)
 5254    1   	    {
 5255    2   	      set_heart_beat (current_heart_beat, 0);
 5256    2   	      debug_message ("Heart beat in %s turned off.\n",
 5257    2   			     current_heart_beat->name);
 5258    2   	      if (current_heart_beat->interactive)
 5259    2   		{
 5260    3   		  struct object *save_cmd = command_giver;
 5261    3   		  command_giver = current_heart_beat;
 5262    3   		  add_message ("Game driver tells you: You have no heart beat !\n");
 5263    3   		  command_giver = save_cmd;
 5264    3   		}
 5265    2   	      current_heart_beat = 0;
 5266    2   	    }

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 50
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5267    1   	#if 0
 5268   X    	  debug_message ("Dump of variables:\n");
 5269   X    	  if (current_object)
 5270   X    	    {
 5271   X    	      struct lnode_var_def *p;
 5272   X    	      for (p = current_object->status; p; p = p->next)
 5273   X    		{
 5274   X    		  debug_message ("%20s: ", p->name);
 5275   X    		  debug_message_value (&current_object->variables[p->num_var]);
 5276   X    		  debug_message ("\n");
 5277   X    		}
 5278   X    	    }
 5279    1   	#endif
 5280    1   	  num_error--;
 5281    1   	  if (error_recovery_context_exists)
 5282    1   	    longjmp (error_recovery_context, 1);
 5283    1   	  abort ();
 5284    1   	}
 5285        	
 5286        	#ifdef TRACE
 5287   X    	char *
 5288   X    	get_current_object_name ()
 5289   X    	{
 5290   X    	  if (current_object == 0)
 5291   X    	    return "NONE";
 5292   X    	  return current_object->name;
 5293   X    	}
 5294   X    	
 5295   X    	char *
 5296   X    	get_command_giver_name ()
 5297   X    	{
 5298   X    	  if (command_giver == 0)
 5299   X    	    return "NONE";
 5300   X    	  return command_giver->name;
 5301   X    	}
 5302   X    	
 5303        	#endif
 5304        	
 5305        	void
 5306        	pre_compile (str)
 5307        	     char *str;
 5308        	{
 5309    1   	  char *c_name, *i_name, buff[1000];
 5310    1   	  FILE *f;
 5311    1   	
 5312    1   	  if (!legal_path (str))
 5313    1   	    error ("Illegal attempt to access %s\n", str);
 5314    1   	  i_name = xalloc (strlen (str) + 3);
 5315    1   	  (void) strcpy (i_name, str);
 5316    1   	  (void) strcat (i_name, ".i");
 5317    1   	  c_name = (char *) xalloc (strlen (str) + 3);
 5318    1   	  (void) strcpy (c_name, str);
 5319    1   	  (void) strcat (c_name, ".c");
 5320    1   	  sprintf (buff, "%s %s %s", PRE_COMPILE, c_name, i_name);
 5321    1   	  f = (FILE *) vpopen (buff, "r");
 5322    1   	  if (f == 0)
 5323    1   	    {

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 51
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5324    2   	      error ("Unable to invoke precompiler!\n");
 5325    2   	      alarm (0);
 5326    2   	    }
 5327    1   	  while (1)
 5328    1   	    {
 5329    2   	      if (fgets (buff, sizeof buff, f) == 0)
 5330    2   		break;
 5331    2   	      add_message ("%s", buff);
 5332    2   	    }
 5333    1   	  vpclose (f);
 5334    1   	  free (c_name);
 5335    1   	  free (i_name);
 5336    1   	}
 5337        	
 5338        	/*** It seems the VAX doesn't like a #ifdef 0  (bub) ***/
 5339        	#ifdef ZERO0ZERO
 5340   X    	void
 5341   X    	pre_compile (str)
 5342   X    	     char *str;
 5343   X    	{
 5344   X    	  char *i_name;
 5345   X    	  int pid;
 5346   X    	  int fd, fd2;
 5347   X    	  unsigned int save_alarm;
 5348   X    	
 5349   X    	  i_name = xalloc (strlen (str) + 3);
 5350   X    	  (void) strcpy (i_name, str);
 5351   X    	  (void) strcat (i_name, ".i");
 5352   X    	  /*
 5353   X    	   * We don't want the child process to have an alarm signal.
 5354   X    	   * The alarm might as well be removed here, instead of in the child
 5355   X    	   * after vfork(), because some Unix (read: apollo) will remove the alarm
 5356   X    	   * for the parent also when done in vfork before exec().
 5357   X    	   */
 5358   X    	  save_alarm = alarm (0);
 5359   X    	/*** in case alarm rounds down and returns a zero. ***/
 5360   X    	  if (save_alarm == 0)
 5361   X    	    save_alarm = 1;
 5362   X    	#ifdef USE_VFORK
 5363   X    	  pid = vfork ();
 5364   X    	#else
 5365   X    	  pid = fork ();
 5366   X    	#endif
 5367   X    	  if (pid)
 5368   X    	    {
 5369   X    	      /* This is the parent. Wait for the childe to complete. */
 5370   X    	      int result;
 5371   X    	
 5372   X    	      /* Enable the alarm again. */
 5373   X    	      (void) alarm (save_alarm);
 5374   X    	      while (1)
 5375   X    		{
 5376   X    		  if (wait (&result) != -1)
 5377   X    		    break;
 5378   X    		  if (errno == EINTR)
 5379   X    		    continue;
 5380   X    		  perror ("wait");

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 52
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5381   X    		  abort ();
 5382   X    		}
 5383   X    	#ifdef USE_VFORK
 5384   X    	      /*
 5385   X    	       * When using vfork(), i_name can have been changed by the child
 5386   X    	       * into name.c. Change this back.
 5387   X    	       */
 5388   X    	      i_name[strlen (i_name) - 1] = 'i';
 5389   X    	#endif
 5390   X    	      /*
 5391   X    	       * Remove the i-file here, because the file might contain include
 5392   X    	       * of files from ../../../ etc. The i-file will also be removed
 5393   X    	       * if there is a compilation error.
 5394   X    	       */
 5395   X    	      if (result != 0)
 5396   X    		unlink (i_name);
 5397   X    	      free (i_name);
 5398   X    	      if (result == 0)
 5399   X    		return;
 5400   X    	      error ("Precompiler returned signal %d, return code %d\n",
 5401   X    		     result & 0xf, result >> 8);
 5402   X    	    }
 5403   X    	  fd = creat (i_name, 0666);
 5404   X    	  if (fd == -1)
 5405   X    	    {
 5406   X    	      perror (i_name);
 5407   X    	      /*
 5408   X    	       * Do not call exit() now, which would close all files for parent.
 5409   X    	       */
 5410   X    	      _exit (1);
 5411   X    	    }
 5412   X    	  if ((fd2 = dup2 (fd, 1)) != 1)
 5413   X    	    {
 5414   X    	      extern int errno;
 5415   X    	      fprintf (stderr, "FATAL: failed to dup2. fd2 = %d, errno = %d, fd = %d\n",
 5416   X    		       fd2, errno, fd);
 5417   X    	      _exit (1);
 5418   X    	    }
 5419   X    	  close (fd);
 5420   X    	  (void) strcpy (i_name, str);
 5421   X    	  (void) strcat (i_name, ".c");
 5422   X    	  if (PRE_COMPILE (i_name) == -1)
 5423   X    	    {
 5424   X    	      perror ("precompile");
 5425   X    	      _exit (99);
 5426   X    	    }
 5427   X    	  _exit (0);
 5428   X    	}
 5429   X    	
 5430        	#endif
 5431        	
 5432        	/*
 5433        	 * Check that it is an legal path. No '..' are allowed.
 5434        	 */
 5435        	int
 5436        	legal_path (path)
 5437        	     char *path;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 53
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5438        	{
 5439    1   	  char *p;
 5440    1   	
 5441    1   	  if (path == NULL || strchr (path, ' '))
 5442    1   	    return 0;
 5443    1   	  if (path[0] == '/')
 5444    1   	    return 0;
 5445    1   	  for (p = strchr (path, '.'); p; p = strchr (p + 1, '.'))
 5446    1   	    {
 5447    2   	      if (p[1] == '.')
 5448    2   		return 0;
 5449    2   	    }
 5450    1   	  return 1;
 5451    1   	}
 5452        	
 5453        	void
 5454        	smart_log (error_file, line, what)
 5455        	     char *error_file, *what;
 5456        	     int line;
 5457        	{
 5458    1   	  char buff2[100], buff[100], *p;
 5459    1   	  int n;
 5460    1   	
 5461    1   	  if (error_file == 0)
 5462    1   	    return;
 5463    1   	  n = sscanf (error_file, "players/%s", buff2);
 5464    1   	  if (n != 1)
 5465    1   	    return;
 5466    1   	  p = strchr (buff2, '/');
 5467    1   	  if (p)
 5468    1   	    *p = '\0';
 5469    1   	  sprintf (buff, "%s line %d:%s\n", error_file, line, what);
 5470    1   	  log_file (buff2, buff);
 5471    1   	}
 5472        	
 5473        	/*
 5474        	 * Check that a file name is valid for read or write.
 5475        	 * Also change the name as if the current directory was at the players
 5476        	 * own directory.
 5477        	 * This is done by functions in the player object.
 5478        	 */
 5479        	char debug_check_file[50];
 5480        	
 5481        	char *
 5482        	check_file_name (file, writeflg)
 5483        	     char *file;
 5484        	     int writeflg;
 5485        	{
 5486    1   	  struct value v, *ret;
 5487    1   	
 5488    1   	  if (!command_giver)
 5489    1   	    return 0;
 5490    1   	  v.type = T_STRING;
 5491    1   	  v.u.string = file;
 5492    1   	  /*
 5493    1   	   * We don't have to free the string in ret. This is done
 5494    1   	   * by the garbage collection.

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 54
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5495    1   	   */
 5496    1   	  if (writeflg)
 5497    1   	    ret = apply ("valid_write", command_giver, &v);
 5498    1   	  else
 5499    1   	    ret = apply ("valid_read", command_giver, &v);
 5500    1   	  if (command_giver->destructed)
 5501    1   	    return 0;
 5502    1   	  if (ret->type != T_STRING)
 5503    1   	    {
 5504    2   	      add_message ("Bad file name.\n");
 5505    2   	      return 0;
 5506    2   	    }
 5507    1   	  strncpy (debug_check_file, ret->u.string, sizeof debug_check_file);
 5508    1   	  if (!legal_path (ret->u.string))
 5509    1   	    {
 5510    2   	      add_message ("Illegal path\n");
 5511    2   	      return 0;
 5512    2   	    }
 5513    1   	  return ret->u.string;
 5514    1   	}
 5515        	
 5516        	/*
 5517        	 * This one is called from HUP.
 5518        	 */
 5519        	int game_is_being_shut_down;
 5520        	
 5521        	void
 5522        	startshutdowngame ()
 5523        	{
 5524    1   	  game_is_being_shut_down = 1;
 5525    1   	}
 5526        	
 5527        	/*
 5528        	 * This one is called from the command "shutdown".
 5529        	 * We don't call it directly from HUP, because it is dangerous when being
 5530        	 * in an interrupt.
 5531        	 */
 5532        	void
 5533        	shutdowngame ()
 5534        	{
 5535    1   	  shout_string ("Game driver shouts: LPmud shutting down immediately.\n");
 5536    1   	  save_wiz_file ();
 5537    1   	  ipc_remove ();
 5538    1   	  remove_all_players ();
 5539    1   	#ifdef free
 5540   X    	  remove_all_objects ();
 5541   X    	  free_all_sent ();
 5542   X    	  remove_wiz_list ();
 5543   X    	  dump_malloc_data ();
 5544   X    	  find_alloced_data ();
 5545    1   	#endif
 5546    1   	  exit (0);
 5547    1   	}
 5548        	
 5549        	/*
 5550        	 * Transfer an object from an object to an object.
 5551        	 * Call add_weight(), drop(), get(), prevent_insert(), add_weight(),

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 55
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5552        	 * and can_put_and_get() where needed.
 5553        	 * Return 0 on success, and special code on failure:
 5554        	 *
 5555        	 * 1: To heavy for destination.
 5556        	 * 2: Can't be dropped.
 5557        	 * 3: Can't take it out of it's container.
 5558        	 * 4: The object can't be inserted into bags etc.
 5559        	 * 5: The destination doesn't allow insertions of objects.
 5560        	 * 6: The object can't be picked up.
 5561        	 */
 5562        	int
 5563        	transfer_object (ob, to)
 5564        	     struct object *ob, *to;
 5565        	{
 5566    1   	  struct value *weight, neg_weight, *ret;
 5567    1   	  struct object *from = ob->super;
 5568    1   	
 5569    1   	  /*
 5570    1   	   * Get the weight of the object
 5571    1   	   */
 5572    1   	  weight = apply ("query_weight", ob, 0);
 5573    1   	  if (weight && weight->type != T_NUMBER)
 5574    1   	    error ("Bad type the weight of object in transfer()\n");
 5575    1   	  if (ob->destructed)
 5576    1   	    return 3;
 5577    1   	  /*
 5578    1   	   * If the original place of the object is a living object,
 5579    1   	   * then we must call drop() to check that the object can be dropped.
 5580    1   	   */
 5581    1   	  if (from && from->enable_commands)
 5582    1   	    {
 5583    2   	      ret = apply ("drop", ob, 0);
 5584    2   	      if (ret && (ret->type != T_NUMBER || ret->u.number != 0))
 5585    2   		return 2;
 5586    2   	      /* This shold not happen, but we can't trust LPC hackers. :-) */
 5587    2   	      if (ob->destructed)
 5588    2   		return 2;
 5589    2   	    }
 5590    1   	  /*
 5591    1   	   * If 'from' is not a room and not a player, check that we may
 5592    1   	   * remove things out of it.
 5593    1   	   */
 5594    1   	  if (from && from->super && !from->enable_commands)
 5595    1   	    {
 5596    2   	      ret = apply ("can_put_and_get", from, 0);
 5597    2   	      if (!ret || (ret->type != T_NUMBER && ret->u.number != 1) ||
 5598    2   		  from->destructed)
 5599    2   		return 3;
 5600    2   	    }
 5601    1   	  /*
 5602    1   	   * If the destination is not a room, and not a player,
 5603    1   	   * Then we must test 'prevent_insert', and 'can_put_and_get'.
 5604    1   	   */
 5605    1   	  if (to->super && to->enable_commands == 0)
 5606    1   	    {
 5607    2   	      ret = apply ("prevent_insert", ob, 0);
 5608    2   	      if (ret && (ret->type != T_NUMBER || ret->u.number != 0))

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 56
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5609    2   		return 4;
 5610    2   	      ret = apply ("can_put_and_get", to, 0);
 5611    2   	      if (!ret || (ret->type != T_NUMBER && ret->type != 0) ||
 5612    2   		  to->destructed || ob->destructed)
 5613    2   		return 5;
 5614    2   	    }
 5615    1   	  /*
 5616    1   	   * If the destination is a player, check that he can pick it up.
 5617    1   	   */
 5618    1   	  if (to->enable_commands)
 5619    1   	    {
 5620    2   	      ret = apply ("get", ob, 0);
 5621    2   	      if (!ret || (ret->type == T_NUMBER && ret->u.number == 0) ||
 5622    2   		  ob->destructed)
 5623    2   		return 6;
 5624    2   	    }
 5625    1   	  /*
 5626    1   	   * If it is not a room, correct the total weight in the destination.
 5627    1   	   */
 5628    1   	  if (to->super && weight)
 5629    1   	    {
 5630    2   	      /*
 5631    2   	       * Check if the destination can carry that much.
 5632    2   	       */
 5633    2   	      ret = apply ("add_weight", to, weight);
 5634    2   	      if (ret && ret->type == T_NUMBER && ret->u.number == 0)
 5635    2   		return 1;
 5636    2   	      if (to->destructed)
 5637    2   		return 1;
 5638    2   	    }
 5639    1   	  /*
 5640    1   	   * If it is not a room, correct the weight in the 'from' object.
 5641    1   	   */
 5642    1   	  if (from && from->super && weight)
 5643    1   	    {
 5644    2   	      neg_weight.type = T_NUMBER;
 5645    2   	      neg_weight.u.number = -weight->u.number;
 5646    2   	      (void) apply ("add_weight", from, &neg_weight);
 5647    2   	    }
 5648    1   	  move_object (ob, to);
 5649    1   	  return 0;
 5650    1   	}
 5651        	
 5652        	/*
 5653        	 * Move or destruct one object.
 5654        	 */
 5655        	void
 5656        	move_or_destruct (what, to)
 5657        	     struct object *what, *to;
 5658        	{
 5659    1   	  int res;
 5660    1   	  struct value v;
 5661    1   	
 5662    1   	  res = transfer_object (what, to);
 5663    1   	  if (res == 0 || what->destructed)
 5664    1   	    return;
 5665    1   	  if (res == 1 || res == 4 || res == 5)

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 57
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5666    1   	    {
 5667    2   	      move_or_destruct (what, to->super);
 5668    2   	      return;
 5669    2   	    }
 5670    1   	  /*
 5671    1   	   * No need to add the reference count of 'what', as this
 5672    1   	   * local 'v' is not deallocated by 'free_all_value()'
 5673    1   	   */
 5674    1   	  v.type = T_OBJECT;
 5675    1   	  v.u.ob = what;
 5676    1   	  destruct_object (&v);
 5677    1   	}
 5678        	
 5679        	/*
 5680        	 * Call this one when there is only little memory left. It will start
 5681        	 * Armageddon.
 5682        	 */
 5683        	void
 5684        	slow_shut_down (minutes)
 5685        	     int minutes;
 5686        	{
 5687    1   	  struct object *ob;
 5688    1   	  struct value v;
 5689    1   	
 5690    1   	  /*
 5691    1   	   * Swap out objects, and free some memory.
 5692    1   	   */
 5693    1   	#if 0
 5694   X    	#if NUM_RESET_TO_SWAP > 0
 5695   X    	  for (ob = obj_list; ob; ob = ob->next_all)
 5696   X    	    {
 5697   X    	      if (!ob->swapped)
 5698   X    		swap (ob);
 5699   X    	    }
 5700   X    	#endif
 5701    1   	#endif
 5702    1   	  ob = find_object ("obj/shut");
 5703    1   	  if (!ob)
 5704    1   	    {
 5705    2   	      struct object *save_current = current_object, *save_command = command_giver;
 5706    2   	      command_giver = 0;
 5707    2   	      current_object = 0;
 5708    2   	      shout_string ("Game driver shouts: Out of memory.\n");
 5709    2   	      command_giver = save_command;
 5710    2   	      current_object = save_current;
 5711    2   	      startshutdowngame ();
 5712    2   	      return;
 5713    2   	    }
 5714    1   	  shout_string ("Game driver shouts: The memory is getting low !\n");
 5715    1   	  v.type = T_NUMBER;
 5716    1   	  v.u.number = minutes;
 5717    1   	  (void) apply ("shut", ob, &v);
 5718    1   	}
 5719        	
 5720        	int
 5721        	match_string (match, str)
 5722        	     char *match, *str;

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 58
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5723        	{
 5724    1   	  int i;
 5725    1   	
 5726    1   	  again :
 5727    1   	    if (*str == '\0' && *match == '\0')
 5728    1   	    return 1;
 5729    1   	  switch (*match)
 5730    1   	    {
 5731    2   	      case '?' :
 5732    2   		if (*str == '\0')
 5733    2   		return 0;
 5734    2   	      str++;
 5735    2   	      match++;
 5736    2   	      goto again;
 5737    2   	      case '*' :
 5738    2   		match++;
 5739    2   	      if (*match == '\0')
 5740    2   		return 1;
 5741    2   	      for (i = 0; str[i] != '\0'; i++)
 5742    2   		if (match_string (match, str + i))
 5743    2   		  return 1;
 5744    2   	      return 0;
 5745    2   	      case '\0' :
 5746    2   		return 0;
 5747    2   	      case '\\' :
 5748    2   		match++;
 5749    2   	      if (*match == '\0')
 5750    2   		return 0;
 5751    2   	      /* Fall through ! */
 5752    2   	      default :
 5753    2   		if (*match == *str)
 5754    2   		{
 5755    3   		  match++;
 5756    3   		  str++;
 5757    3   		  goto again;
 5758    3   		}
 5759    2   	      return 0;
 5760    2   	    }
 5761    1   	}
 5762        	
 5763        	char *
 5764        	read_file (file, line)
 5765        	     char *file;
 5766        	     int line;
 5767        	{
 5768    1   	  FILE *f;
 5769    1   	  static char buff[1024];
 5770    1   	  int i;
 5771    1   	
 5772    1   	  if (line <= 0)
 5773    1   	    return 0;
 5774    1   	  if (!(file = check_file_name (file, 0)))
 5775    1   	    return 0;
 5776    1   	  if (!(f = fopen (file, "r")))
 5777    1   	    return 0;
 5778    1   	  for (i = 1; i < line; i++)
 5779    1   	    {

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 59
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5780    2   	      if (!(fgets (buff, sizeof (buff), f)))
 5781    2   		{
 5782    3   		  fclose (f);
 5783    3   		  return 0;
 5784    3   		}
 5785    2   	    }
 5786    1   	  if (!(fgets (buff, sizeof (buff), f)))
 5787    1   	    {
 5788    2   	      fclose (f);
 5789    2   	      return 0;
 5790    2   	    }
 5791    1   	  fclose (f);
 5792    1   	  return buff;
 5793    1   	}
 5794        	
 5795        	struct value *
 5796        	search_array (a, target, index)
 5797        	     struct vector *a;
 5798        	     struct value *target;
 5799        	     int index;
 5800        	{
 5801    1   	  struct value *ret;
 5802    1   	  struct value orig_targ;
 5803    1   	  int i;
 5804    1   	
 5805    1   	  if (!a)
 5806    1   	    error ("Bad array pointer in searcha().\n");
 5807    1   	  if (target->type != T_STRING && target->type != T_OBJECT
 5808    1   	      && target->type != T_NUMBER && target->type != T_POINTER)
 5809    1   	    error ("Bad argument 2 to searcha().\n");
 5810    1   	  if (index + 1 > a->size || index < 0 || index > MAX_ARRAY_SIZE)
 5811    1   	    error ("Illegal index to searcha().\n");
 5812    1   	
 5813    1   	  orig_targ = *target;
 5814    1   	  if (target->type == T_OBJECT && target->u.ob->destructed)
 5815    1   	    {
 5816    2   	      target->type = T_NUMBER;
 5817    2   	      target->u.number = 0;
 5818    2   	    }
 5819    1   	  ret = alloc_value ();
 5820    1   	  ret->type = T_NUMBER;
 5821    1   	  ret->u.number = -1;
 5822    1   	  for (i = index; i < a->size; i++)
 5823    1   	    {
 5824    2   	
 5825    2   	      if (a->item[i].type != target->type &&
 5826    2   		  !(a->item[i].type == T_OBJECT && a->item[i].u.ob->destructed &&
 5827    2   		    target->type == T_NUMBER))
 5828    2   		continue;
 5829    2   	      switch (target->type)
 5830    2   		{
 5831    3   		  case T_OBJECT :
 5832    3   		    if (a->item[i].u.ob == target->u.ob &&
 5833    3   			!a->item[i].u.ob->destructed)
 5834    3   		    ret->u.number = i;
 5835    3   		  break;
 5836    3   		  case T_STRING :

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 60
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5837    3   		    if (strcmp (a->item[i].u.string, target->u.string) == 0)
 5838    3   		    ret->u.number = i;
 5839    3   		  break;
 5840    3   		  case T_POINTER :
 5841    3   		    if (a->item[i].u.vec == target->u.vec)
 5842    3   		    ret->u.number = i;
 5843    3   		  break;
 5844    3   		  case T_NUMBER :
 5845    3   		    if (a->item[i].u.number == target->u.number)
 5846    3   		    ret->u.number = i;
 5847    3   		  else if (a->item[i].type == T_OBJECT &&
 5848    3   			   a->item[i].u.ob->destructed &&
 5849    3   			   target->u.number == 0)
 5850    3   		    ret->u.number = i;
 5851    3   		  break;
 5852    3   		  default :
 5853    3   		    break;
 5854    3   		}
 5855    2   	      if (ret->u.number != -1)
 5856    2   		break;
 5857    2   	    }
 5858    1   	  *target = orig_targ;
 5859    1   	  return ret;
 5860    1   	}
 5861        	
 5862        	struct value *
 5863        	contents (arg)
 5864        	     struct value *arg;
 5865        	{
 5866    1   	  struct object *ob;
 5867    1   	  struct value *ret;
 5868    1   	  int count;
 5869    1   	  if (arg->type == T_STRING)
 5870    1   	    ob = find_object (arg->u.string);
 5871    1   	  else
 5872    1   	    ob = arg->u.ob;
 5873    1   	  if (ob == 0)
 5874    1   	    error ("No object to contents()");
 5875    1   	  if (ob->contains == 0)
 5876    1   	    return &const0;
 5877    1   	  for (ob = ob->contains, count = 0; ob; ob = ob->next_inv, count++) ;
 5878    1   	  ret = allocate_array (count);
 5879    1   	  for (ob = arg->u.ob->contains, count = 0; ob; ob = ob->next_inv, count++)
 5880    1   	    {
 5881    2   	      ret->u.vec->item[count].type = T_OBJECT;
 5882    2   	      ret->u.vec->item[count].u.ob = ob;
 5883    2   	      add_ref (ob, "contents");
 5884    2   	    }
 5885    1   	  return ret;
 5886    1   	}
 5887        	
 5888        	int
 5889        	print_file (path, start, len)
 5890        	     char *path;
 5891        	     int start, len;
 5892        	{
 5893    1   	  char buff[1000];

SIMULATE                                                        18-APR-1991 10:34:57    VAX C      V3.1-051                 Page 61
V1.0                                                             1-APR-1991 10:23:23    LPMUD_DIR:[000000]SIMULATE.C;16 (1)

 5894    1   	  FILE *f;
 5895    1   	  int i, num_read = 0;;
 5896    1   	
 5897    1   	  if (len < 0)
 5898    1   	    return -1;
 5899    1   	  path = check_file_name (path, 0);
 5900    1   	  if (path == 0)
 5901    1   	    return -1;
 5902    1   	  f = fopen (path, "r");
 5903    1   	  if (f == 0)
 5904    1   	    return -1;
 5905    1   	  if (start < 0)
 5906    1   	    {
 5907    2   	      int lines = 0;
 5908    2   	
 5909    2   	      while (fgets (buff, sizeof buff, f) != 0)
 5910    2   		lines++;
 5911    2   	      rewind (f);
 5912    2   	      start = lines - len + 1;
 5913    2   	    }
 5914    1   	  for (i = 1; i < start; i++)
 5915    1   	    {
 5916    2   	      if (fgets (buff, sizeof buff, f) == 0)
 5917    2   		break;
 5918    2   	    }
 5919    1   	  if (!len || len > MAX_LINES)
 5920    1   	    len = MAX_LINES;
 5921    1   	  for (i = 0; i < len; i++)
 5922    1   	    {
 5923    2   	      if (fgets (buff, sizeof buff, f) == 0)
 5924    2   		break;
 5925    2   	      num_read++;
 5926    2   	      add_message ("%s", buff);
 5927    2   	    }
 5928    1   	  if (i == MAX_LINES)
 5929    1   	    add_message ("*****TRUNCATED*****\n");
 5930    1   	  fclose (f);
 5931    1   	  return num_read;
 5932    1   	}

 
 
Command Line
------------
 
CC SIMULATE/LIST