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