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 ¤t_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 (¤t_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