# define A_OBJ 0 # define A_NEXT 1 # define A_VERB 2 # define A_FUNC 3 private int alive; /* living flag */ private mixed *chunks; /* array of action chunks */ private mapping actions; /* objects:actions mapping */ private string saved_action; /* action saved by add_action with 1 argument */ /* * NAME: _Q_alive() * DESCRIPTION: return the living status of this object */ nomask int _Q_alive() { return alive; } /* * NAME: _Q_actions() * DESCRIPTION: return the action chunks of this object */ nomask mixed *_Q_actions() { if (PRIVILEGED()) { return chunks; } } /* * NAME: _F_add_action() * DESCRIPTION: define an action for this object */ nomask void _F_add_action(object obj, string verb, string func, int flag) { if (PRIVILEGED()) { mixed chunk; if (flag) { chunk = ({ obj, actions[obj], verb, func }); chunks = ({ chunk }) + chunks; actions[obj] = chunk; } else if (sizeof(chunks) != 0 && mappingp(chunk=chunks[0]) && chunk[A_OBJ] == obj && chunk[verb] == 0) { chunk[verb] = func; } else { chunk = ([ A_OBJ:obj, A_NEXT:actions[obj], verb:func ]); chunks = ({ chunk }) + chunks; actions[obj] = chunk; } } } /* * NAME: _F_remove_actions() * DESCRIPTION: remove the actions defined by obj */ nomask void _F_remove_actions(object obj) { if (PRIVILEGED()) { mixed *removed, chunk; removed = ({ }); for (chunk = actions[obj]; chunk != 0; chunk = chunk[A_NEXT]) { chunk[A_OBJ] = 0; removed += ({ chunk }); } chunks -= removed; actions[obj] = 0; } } /* * NAME: _F_checkfunc() * DESCRIPTION: check if a function exists */ nomask string _F_checkfunc(string func) { if (PRIVILEGED()) { return function_object(func, this_object()); } } /* * NAME: _F_call() * DESCRIPTION: handle the calling of a function */ nomask int _F_call(string func, string args) { if (previous_object() == this_user()) { return call_other(this_object(), func, args); } } /* * NAME: remove_actions * DESCRIPTION: remove the actions defined for player by obj */ private void remove_actions(object player, object obj) { player->_F_remove_actions(obj); } /* * NAME: enable_commands() * DESCRIPTION: mark this object as living */ static void enable_commands() { alive = 1; set_this_player(this_object()); } /* * NAME: disable_commands() * DESCRIPTION: mark this object as non-living */ static void disable_commands() { if (this_player() == this_object()) { set_this_player(0); } alive = 0; } /* * NAME: living() * DESCRIPTION: determine if an object is alive */ static int living(object obj) { ARGCHECK(obj, living, 1); return obj->_Q_alive(); } /* * NAME: add_action() * DESCRIPTION: add an action for the current player */ static varargs void add_action(string func, string verb, int flag) { object player, e1, e2; ARGCHECK(func, add_action, 1); player = this_player(); if (player == 0) { return; } if (this_object() != player && (e1=environment()) != player && e1 != (e2=environment(player)) && this_object() != e2) { error("add_action from object that was not present"); } if (func == "exit") { error("Illegal to define a command to the exit() function"); } if (verb == 0) { saved_action = func; } else { lock(privileged = 1, player->_F_add_action(this_object(), verb, func, flag), privileged = 0, saved_action = 0); } } /* * NAME: add_verb() * DESCRIPTION: add a verb for the current player (most follow add_action() * with one argument) */ static void add_verb(string verb) { object player; ARGCHECK(verb, add_verb, 1); player = this_player(); if (player != 0 && saved_action != 0) { lock(privileged = 1, player->_F_add_action(this_object(), verb, saved_action, 0), privileged = 0, saved_action = 0); } } /* * NAME: command() * DESCRIPTION: force a given player to execute a command */ static varargs int command(string cmd, object obj) { mixed *list, chunk; string arg, verb, func, prog; object player, save_player; int i, sz, exec_cost; ARGCHECK(cmd, command, 1); if (this_object() == 0) { return 0; } player = (obj != 0) ? obj : this_object(); save_player = this_player(); if (player != save_player && !player->_Q_alive()) { return 0; } set_this_player(player); notify_fail("What ?\n"); lock(privileged = 1, list = player->_Q_actions(), privileged = 0); for (i = strlen(cmd); --i >= 0 && cmd[i] == ' '; ) ; if (i < 0) { return 0; } cmd = cmd[0 .. i]; switch (cmd) { case "n": cmd = "north"; break; case "s": cmd = "south"; break; case "e": cmd = "east"; break; case "w": cmd = "west"; break; case "ne": cmd = "northeast"; break; case "nw": cmd = "northwest"; break; case "se": cmd = "southeast"; break; case "sw": cmd = "southwest"; break; case "u": cmd = "up"; break; case "d": cmd = "down"; break; default: sscanf(cmd, "%s %s", cmd, arg); break; } exec_cost = 1000 + get_exec_cost(); for (i = 0, sz = sizeof(list); i < sz; i++) { if (player == 0 || this_object() == 0) { return 0; } chunk = list[i]; if (arrayp(chunk)) { verb = chunk[A_VERB]; if (strlen(verb) > strlen(cmd) || (cmd[0 .. strlen(verb) - 1] != verb && verb != "")) { continue; } func = chunk[A_FUNC]; } else { func = chunk[cmd]; if (func == 0) { continue; } } obj = chunk[A_OBJ]; if (obj == 0) { continue; } set_verb(cmd); lock(privileged = 1, prog = obj->_F_checkfunc(func), privileged = 0); if (prog != 0) { if (this_object() == this_user()) { if (obj->_F_call(func, arg)) { set_verb(0); set_this_player(save_player); return exec_cost - get_exec_cost(); } continue; } else if (function_object(func, obj) != 0) { if (call_other(obj, func, arg)) { set_verb(0); set_this_player(save_player); return exec_cost - get_exec_cost(); } continue; } } write("Error: function " + func + " not found.\n"); set_verb(0); set_this_player(save_player); return exec_cost - get_exec_cost(); } if (player != 0 && (player=interactive(player)) != 0) { player->notify_fail(); } set_verb(0); set_this_player(save_player); return 0; } /* * NAME: localcmd() * DESCRIPTION: show the current verbs defined */ static void localcmd() { string list; int i, sz; mixed chunk; list = "Local commands:\n"; for (i = 0, sz = sizeof(chunks); i < sz; i++) { chunk = chunks[i]; if (mappingp(chunk)) { mapping m; m = chunk + ([ ]); m[A_OBJ] = 0; m[A_NEXT] = 0; list += implode(map_indices(m), " ") + " "; } else { list += chunk[A_VERB] + " "; } } write(list[0 .. strlen(list) - 2] + "\n"); }