void setup_new_commands (object_t * dest, object_t * item) { object_t *next_ob, *ob; /* * Setup the new commands. The order is very important, as commands in * the room should override commands defined by the room. Beware that * init() in the room may have moved 'item' ! * * The call of init() should really be done by the object itself (except in * the -o mode). It might be too slow, though :-( */ if (item->flags & O_ENABLE_COMMANDS) { save_command_giver(item); (void) apply(APPLY_INIT, dest, 0, ORIGIN_DRIVER); restore_command_giver(); if (item->super != dest) return; } /* * Run init of the item once for every present user, and for the * environment (which can be a user). */ for (ob = dest->contains; ob; ob = next_ob) { next_ob = ob->next_inv; if (ob == item) continue; if (ob->flags & O_DESTRUCTED) error("An object was destructed at call of " APPLY_INIT "()\n"); if (ob->flags & O_ENABLE_COMMANDS) { save_command_giver(ob); (void) apply(APPLY_INIT, item, 0, ORIGIN_DRIVER); restore_command_giver(); if (dest != item->super) return; } if (item->flags & O_DESTRUCTED) /* marion */ error("The object to be moved was destructed at call of " APPLY_INIT "()\n"); if (ob->flags & O_DESTRUCTED) /* Alaron */ error("An object was destructed at call of " APPLY_INIT "()\n"); if (item->flags & O_ENABLE_COMMANDS) { save_command_giver(item); (void) apply(APPLY_INIT, ob, 0, ORIGIN_DRIVER); restore_command_giver(); if (dest != item->super) return; } } if (dest->flags & O_DESTRUCTED) /* marion */ error("The destination to move to was destructed at call of " APPLY_INIT "()\n"); if (item->flags & O_DESTRUCTED) /* Alaron */ error("The object to be moved was destructed at call of " APPLY_INIT "()\n"); if (dest->flags & O_ENABLE_COMMANDS) { save_command_giver(dest); (void) apply(APPLY_INIT, item, 0, ORIGIN_DRIVER); restore_command_giver(); } }
static void notify_no_command (void) { union string_or_func p; svalue_t *v; if (!command_giver || !command_giver->interactive) return; p = command_giver->interactive->default_err_message; if (command_giver->interactive->iflags & NOTIFY_FAIL_FUNC) { save_command_giver(command_giver); v = call_function_pointer(p.f, 0); restore_command_giver(); free_funp(p.f); if (command_giver && command_giver->interactive) { if (v && v->type == T_STRING) { tell_object(command_giver, v->u.string, SVALUE_STRLEN(v)); } command_giver->interactive->iflags &= ~NOTIFY_FAIL_FUNC; command_giver->interactive->default_err_message.s = 0; } } else { if (p.s) { tell_object(command_giver, p.s, strlen(p.s)); free_string(p.s); command_giver->interactive->default_err_message.s = 0; } else { tell_object(command_giver, default_fail_message, strlen(default_fail_message)); } } }
/* * Take a user command and parse it. * The command can also come from a NPC. * Beware that 'str' can be modified and extended ! */ int parse_command (char * str, object_t * ob) { int res; /* disallow users to issue commands containing ansi escape codes */ #if defined(NO_ANSI) && !defined(STRIP_BEFORE_PROCESS_INPUT) char *c; for (c = str; *c; c++) { if (*c == 27) { *c = ' '; /* replace ESC with ' ' */ } } #endif save_command_giver(ob); res = user_parser(str); restore_command_giver(); return res; }
static int user_parser (char * buff) { char verb_buff[MAX_VERB_BUFF]; sentence_t *s; char *p; int length; char *user_verb = 0; int where; int save_illegal_sentence_action; debug(d_flag, ("cmd [/%s]: %s\n", command_giver->obname, buff)); /* strip trailing spaces. */ for (p = buff + strlen(buff) - 1; p >= buff; p--) { if (*p != ' ') break; *p = '\0'; } if (buff[0] == '\0') return 0; length = p - buff + 1; p = strchr(buff, ' '); if (p == 0) { user_verb = findstring(buff); } else { *p = '\0'; user_verb = findstring(buff); *p = ' '; length = p - buff; } if (!user_verb) { /* either an xverb or a verb without a specific add_action */ user_verb = buff; } /* * copy user_verb into a static character buffer to be pointed to by * last_verb. */ strncpy(verb_buff, user_verb, MAX_VERB_BUFF - 1); if (p) { int pos; pos = p - buff; if (pos < MAX_VERB_BUFF) { verb_buff[pos] = '\0'; } } save_illegal_sentence_action = illegal_sentence_action; illegal_sentence_action = 0; for (s = command_giver->sent; s; s = s->next) { svalue_t *ret; object_t *command_object; if (s->flags & (V_NOSPACE | V_SHORT)) { if (strncmp(buff, s->verb, strlen(s->verb)) != 0) continue; } else { /* note: if was add_action(blah, "") then accept it */ if (s->verb[0] && (user_verb != s->verb)) continue; } /* * Now we have found a special sentence ! */ if (!(s->flags & V_FUNCTION)) debug(d_flag, ("Local command %s on /%s", s->function.s, s->ob->obname)); if (s->flags & V_NOSPACE) { int l1 = strlen(s->verb); int l2 = strlen(verb_buff); if (l1 < l2) last_verb = verb_buff + l1; else last_verb = ""; } else { if (!s->verb[0] || (s->flags & V_SHORT)) last_verb = verb_buff; else last_verb = s->verb; } /* * If the function is static and not defined by current object, then * it will fail. If this is called directly from user input, then * the origin is the driver and it will be allowed. */ where = (current_object ? ORIGIN_EFUN : ORIGIN_DRIVER); /* * Remember the object, to update moves. */ command_object = s->ob; save_command_giver(command_giver); if (s->flags & V_NOSPACE) { copy_and_push_string(&buff[strlen(s->verb)]); } else if (buff[length] == ' ') { copy_and_push_string(&buff[length + 1]); } else { push_undefined(); } if (s->flags & V_FUNCTION) { ret = call_function_pointer(s->function.f, 1); } else { if (s->function.s[0] == APPLY___INIT_SPECIAL_CHAR) error("Illegal function name.\n"); ret = apply(s->function.s, s->ob, 1, where); } /* s may be dangling at this point */ restore_command_giver(); last_verb = 0; /* was this the right verb? */ if (ret == 0) { /* is it still around? Otherwise, ignore this ... it moved somewhere or dested itself */ if (s == command_giver->sent) { char buf[256]; if (s->flags & V_FUNCTION) { sprintf(buf, "Verb '%s' bound to uncallable function pointer.\n", s->verb); error(buf); } else { sprintf(buf, "Function for verb '%s' not found.\n", s->verb); error(buf); } } } if (ret && (ret->type != T_NUMBER || ret->u.number != 0)) { #ifdef PACKAGE_MUDLIB_STATS if (command_giver && command_giver->interactive #ifndef NO_WIZARDS && !(command_giver->flags & O_IS_WIZARD) #endif ) add_moves(&command_object->stats, 1); #endif if (!illegal_sentence_action) illegal_sentence_action = save_illegal_sentence_action; return 1; } if (illegal_sentence_action) { switch (illegal_sentence_action) { case 1: error("Illegal to call remove_action() [caller was /%s] from a verb returning zero.\n", illegal_sentence_ob->obname); case 2: error("Illegal to move or destruct an object (/%s) defining actions from a verb function which returns zero.\n", illegal_sentence_ob->obname); } } } notify_no_command(); illegal_sentence_action = save_illegal_sentence_action; return 0; }
void call_heart_beat() { object_t *ob; heart_beat_t *curr_hb; error_context_t econ; current_interactive = 0; if ((num_hb_to_do = num_hb_objs)) { num_hb_calls++; heart_beat_index = 0; save_context(&econ); while (1) { ob = (curr_hb = &heart_beats[heart_beat_index])->ob; DEBUG_CHECK(!(ob->flags & O_HEART_BEAT), "Heartbeat not set in object on heartbeat list!"); /* is it time to do a heart beat ? */ curr_hb->heart_beat_ticks--; if (ob->prog->heart_beat != 0) { if (curr_hb->heart_beat_ticks < 1) { object_t *new_command_giver; curr_hb->heart_beat_ticks = curr_hb->time_to_heart_beat; current_heart_beat = ob; new_command_giver = ob; #ifndef NO_SHADOWS while (new_command_giver->shadowing) new_command_giver = new_command_giver->shadowing; #endif #ifndef NO_ADD_ACTION if (!(new_command_giver->flags & O_ENABLE_COMMANDS)) new_command_giver = 0; #endif #ifdef PACKAGE_MUDLIB_STATS add_heart_beats(&ob->stats, 1); #endif set_eval(max_cost); if (SETJMP(econ.context)) { restore_context(&econ); } else { save_command_giver(new_command_giver); call_direct(ob, ob->prog->heart_beat - 1, ORIGIN_DRIVER, 0); pop_stack(); /* pop the return value */ restore_command_giver(); } current_object = 0; } } if (++heart_beat_index == num_hb_to_do) break; } pop_context(&econ); if (heart_beat_index < num_hb_to_do) perc_hb_probes = 100 * (float) heart_beat_index / num_hb_to_do; else perc_hb_probes = 100.0; heart_beat_index = num_hb_to_do = 0; } current_prog = 0; current_heart_beat = 0; look_for_objects_to_swap(); #ifdef PACKAGE_MUDLIB_STATS mudlib_stats_decay(); #endif } /* call_heart_beat() */
static void call_heart_beat() { object_t *ob; heart_beat_t *curr_hb; error_context_t econ; #ifdef WIN32 static long Win32Thread = -1; #endif heart_beat_flag = 0; #ifdef SIGALRM signal(SIGALRM, sigalrm_handler); #endif #ifdef HAS_UALARM ualarm(HEARTBEAT_INTERVAL, 0); #else # ifdef WIN32 if (Win32Thread == -1) Win32Thread = _beginthread( /* This shouldn't be necessary b/c alarm_loop is already declared as this. Microsoft lossage? -Beek */ (void (__cdecl *)(void *)) alarm_loop, 256, 0); # else alarm(SYSV_HEARTBEAT_INTERVAL); /* defined in config.h */ # endif #endif current_interactive = 0; if ((num_hb_to_do = num_hb_objs)) { num_hb_calls++; heart_beat_index = 0; save_context(&econ); while (!heart_beat_flag) { ob = (curr_hb = &heart_beats[heart_beat_index])->ob; DEBUG_CHECK(!(ob->flags & O_HEART_BEAT), "Heartbeat not set in object on heartbeat list!"); DEBUG_CHECK(ob->flags & O_SWAPPED, "Heartbeat in swapped object.\n"); /* is it time to do a heart beat ? */ curr_hb->heart_beat_ticks--; if (ob->prog->heart_beat != 0) { if (curr_hb->heart_beat_ticks < 1) { object_t *new_command_giver; curr_hb->heart_beat_ticks = curr_hb->time_to_heart_beat; current_heart_beat = ob; new_command_giver = ob; #ifndef NO_SHADOWS while (new_command_giver->shadowing) new_command_giver = new_command_giver->shadowing; #endif #ifndef NO_ADD_ACTION if (!(new_command_giver->flags & O_ENABLE_COMMANDS)) new_command_giver = 0; #endif #ifdef PACKAGE_MUDLIB_STATS add_heart_beats(&ob->stats, 1); #endif eval_cost = max_cost; if (SETJMP(econ.context)) { restore_context(&econ); } else { save_command_giver(new_command_giver); call_direct(ob, ob->prog->heart_beat - 1, ORIGIN_DRIVER, 0); pop_stack(); /* pop the return value */ restore_command_giver(); } current_object = 0; } } if (++heart_beat_index == num_hb_to_do) break; } pop_context(&econ); if (heart_beat_index < num_hb_to_do) perc_hb_probes = 100 * (float) heart_beat_index / num_hb_to_do; else perc_hb_probes = 100.0; heart_beat_index = num_hb_to_do = 0; } current_prog = 0; current_heart_beat = 0; look_for_objects_to_swap(); call_out(); #ifdef PACKAGE_MUDLIB_STATS mudlib_stats_decay(); #endif } /* call_heart_beat() */