/* /std/user/nmsh.c * from Nightmare IV * the new Nightmare shell * created by Descartes of Borg 940216 */ #include <config.h> #include "nmsh.h" #define DIRECTORY_STACK_SIZE 5 #define MAX_CMD_ALIASES 60 #define MIN_HISTORY_SIZE 10 private string __CurrentWorkingDirectory; private mapping __Nicknames, __Aliases, __Xverbs; static private int __CWDCount, __CWDBottom, __CWDTop, __CmdNumber; static private int __HistoryCount, __HistoryBottom, __HistoryTop, __HistorySize; static private string __Prompt; static private string *__Stack, *__History; void create() { __Nicknames = ([]); __Aliases = ([ "l" : "look $*", "bio" : "biography", "i" : "inventory", "n" : "go north", "s" : "go south", "e" : "go east", "w" : "go west", "ne" : "go northeast", "nw" : "go northwest", "se" : "go southeast", "sw" : "go southwest", "d" : "go down", "u" : "go up", "exa" : "look at $*", ]); __Xverbs = ([ "'" : "say $*", ":" : "emote $*" ]); } void setup() { if(this_player() != this_object()) return; reset_history(); reset_prompt(); if(!__Nicknames) __Nicknames = ([]); if(!__Aliases) __Aliases = ([]); if(!__Xverbs) __Xverbs = ([]); add_action("cmd_alias", "alias"); add_action("cmd_history", "history"); add_action("cmd_nickname", "nickname"); if(creatorp(this_object())) { __Stack = allocate(DIRECTORY_STACK_SIZE); __CWDBottom = __CWDTop = __CWDCount = 0; add_action("cmd_cd", "cd"); add_action("cmd_nmsh", "nmsh"); add_action("cmd_pushd", "pushd"); add_action("cmd_popd", "popd"); add_action("cmd_pwd", "cwd"); add_action("cmd_pwd", "pwd"); add_action("cmd_work", "work"); } } nomask static int cmd_alias(string str) { string *a, *b; string key, thing; int i; if(this_player() != this_object()) return 0; if(!str) { i = sizeof(a = keys(__Aliases)); while(i--) a[i] = sprintf("%s%s", arrange_string(a[i],15),__Aliases[a[i]]); i = sizeof(b = keys(__Xverbs)); while(i--) b[i] = sprintf("$%s%s", arrange_string(b[i],14), __Xverbs[b[i]]); this_player()->more(a+b); return 1; } if(sscanf(str, "%s %s", key, thing) != 2) { if(str[0] == '$') { str = str[1..strlen(str)-1]; if(__Xverbs[str]) { map_delete(__Xverbs, str); message("system", sprintf("Alias $%s removed.", str), this_player()); } else message("system", sprintf("No such alias $%s.", str), this_player()); return 1; } if(__Aliases[str]) { map_delete(__Aliases, str); message("system", sprintf("Alias %s removed.", str), this_player()); } else message("system", sprintf("No such alias %s.", str), this_player()); return 1; } if(sizeof(__Xverbs) + sizeof(__Aliases) >= MAX_CMD_ALIASES) { message("system", "You must remove an alias before adding another.", this_player()); return 1; } if(key == "alias") return notify_fail("You are a bonehead.\n"); if(key[0] == '$') { key = key[1..strlen(key)]; if(__Xverbs[key]) message("system", sprintf("Alias for $%s altered to (%s).", key, thing), this_player()); else message("system", sprintf("Alias $%s (%s) added.", key, thing), this_player()); __Xverbs[key] = thing; } else { if(__Aliases[key]) message("system", sprintf("Alias for %s altered to (%s).", key, thing), this_player()); else message("system", sprintf("Alias %s (%s) added.", key, thing),this_player()); __Aliases[key] = thing; } return 1; } nomask static int cmd_cd(string str) { if(this_player() != this_object()) return 0; set_cwd(str); return 1; } nomask static int cmd_history(string str) { string *cmds; int i, maxi, x; if(__CmdNumber <= __HistorySize) { for(i=0; i<__CmdNumber; i++) message("system", sprintf("%d%s",i+1, ((i+1) > 9 ? " "+__History[i] : " "+__History[i])), this_player()); return 1; } maxi = sizeof(cmds = __History[__HistoryBottom..__HistorySize-1] + __History[0..__HistoryTop]); for(i=0; i<maxi; i++) { x = __CmdNumber-__HistorySize+i+1; message("system", sprintf("%d %s", x, cmds[i]), this_player()); } return 1; } nomask static int cmd_nickname(string str) { string *cles; string key, thing; int i; if(this_player() != this_object()) return 0; if(!str) { i = sizeof(cles = keys(__Nicknames)); while(i--) cles[i] = sprintf("%s%s", arrange_string(cles[i], 15), __Nicknames[cles[i]]); this_player()->more(cles); return 1; } if(sscanf(str, "%s %s", key, thing) != 2) { if(__Nicknames[str]) { message("system", sprintf("Nickname %s removed.", str), this_player()); map_delete(__Nicknames, str); } else message("system", sprintf("No such nickname %s.", str), this_player()); } else { if(__Nicknames[key]) message("system", sprintf("Nickname %s altered to (%s).", key, thing), this_player()); else message("system", sprintf("Nickname %s (%s) added.", key, thing), this_player()); __Nicknames[key] = thing; } return 1; } nomask static int cmd_nmsh(string str) { string *lines; string tmp; int i, maxi; if(!str) return 0; if(this_player() != this_object()) return 0; if((int)this_player()->query_forced()) return 0; if(!(tmp = read_file(absolute_path(query_cwd(), str)))) return notify_fail(sprintf("nmsh: script %s not found.\n")); maxi = sizeof(lines = explode(tmp, "\n")); for(i=0; i < maxi; i++) { if(lines[i][0] == '#') continue; if(!command(lines[i])) { message("system", sprintf("nmsh: error in executing %s.", str), this_player()); return 1; } } return 1; } nomask static int cmd_pushd(string str) { if(this_player() != this_object()) return 0; if(!set_cwd(str)) return 0; pushd(str); return 1; } nomask static int cmd_popd(string str) { if(this_player() != this_object()) return 0; set_cwd(popd()); return 1; } nomask static int cmd_pwd(string str) { if(!query_cwd()) message("system", "No current directory.", this_object()); else message("system", query_cwd()+":", this_object()); return 1; } nomask static int cmd_work(string str) { string *tmp; object ob; string file; int flag; if(!str || str == "") ob = environment(this_object()); else if(str == "!") { flag = 1; ob = environment(this_object()); } else if(str[0] == '!') { flag = 1; str = str[1..strlen(str)]; } if(!ob && !(ob = present(str, this_object()))) ob = present(str, environment(this_object())); if(!ob) return notify_fail("No target object found.\n"); tmp = explode(file = base_name(ob), "/"); set_cwd("/"+implode(tmp[0..sizeof(tmp)-2], "/")); if(flag) { message("system", file+".c, "+file_size(file+".c")+" bytes:", this_object()); ed(file+".c"); } return 1; } nomask string write_prompt() { string tmp, ret; int x; if((ret = __Prompt) == DEFAULT_PROMPT) { message("prompt", ret, this_object()); return ret; } while((x = strsrch(ret, "$")) != -1) { if(x == strlen(ret) -1) break; switch(ret[x+1]) { case 'D': if(!creatorp(this_object())) break; if(sscanf(query_cwd(), user_path(query_name())+"%s", tmp)) tmp = "~"+tmp; else tmp = query_cwd(); ret = replace_string(ret, "$D", tmp); break; case 'V': case 'v': if(query_invis()) { ret = replace_string(ret, "$V", "INVIS"); ret = replace_string(ret, "$v", "invis"); } else if(hiddenp(this_object())) { ret = replace_string(ret, "$V", "HID"); ret = replace_string(ret, "$v", "hid"); } else { ret = replace_string(ret, "$V", ""); ret = replace_string(ret, "$v", ""); } break; case 'C': ret = replace_string(ret, "$C", sprintf("%d", __CmdNumber+1)); break; case 'H': ret = replace_string(ret, "$H", sprintf("%d", query_max_hp())); break; case 'h': ret = replace_string(ret, "$h", sprintf("%d", query_hp())); break; case 'G': ret = replace_string(ret, "$G", sprintf("%d", query_max_mp())); break; case 'g': ret = replace_string(ret, "$g", sprintf("%d", query_mp())); break; case 'I': ret = replace_string(ret, "$I", sprintf("%d", query_max_sp())); break; case 'i': ret = replace_string(ret, "$i", sprintf("%d", query_sp())); break; default: ret = replace_string(ret, ret[x..x+1], ""); break; } } message("prompt", ret, this_object()); return ret; } nomask string process_input(string str) { string tmp, xtra, request; if(!str || str == "") return ""; else if(query_client() && member_array(query_client(), SUPPORTED_CLIENTS) != -1) { if(sscanf(str, "<%s>%s", request, xtra)) { process_request(request, xtra ? xtra : ""); return ""; } else return str; } else if((tmp = do_history(str)) == "") return ""; if(tmp != str) message("system", tmp, this_object()); add_history_cmd(tmp); return do_alias(do_nickname(tmp)); } nomask static void process_request(string request, string xtra) { switch(request) { case "ALIAS": receive("<ALIAS>[n,go north] [s,go south] [e,go east] [w,go west] " "[nw,go northwest] [ne,go northeast] [sw,go southwest] " "[se,go southeast] [u,go up] [d,go down] [i,inventory] " "[bio,biography] [exa,look at $*] [$',say $*] " "[$:,emote $*] [l,look]\n"); break; case "NICKNAME": receive("<NICKNAME>\n"); break; case "USERS": receive("<USERS>"+implode(map_array(filter_array(users(), "request_vis", this_object()), "user_names", this_object()), ", ")+"\n"); break; case "ROOM": receive("<ROOM>"+ (string)environment(this_object())->query_short()+"\n"); break; case "PRESENT": receive("<PRESENT>"+ implode(map_array(filter_array(all_inventory(environment(this_object())), "request_vis", this_object()), "user_names", this_object()), ", ")+"\n"); break; default: receive("<error>Request not supported.\n"); break; } } static int request_vis(object ob) { return (userp(ob) && !((int)ob->query_invis(this_object()))); } static string user_names(object ob) { return (string)ob->query_cap_name(); } static private int set_cwd(string str) { int x; //tc("str: "+str); if(!str || str == "") str = user_path(query_name()); //tc("str: "+str); if(str != "/" && str[<1..] == "/") str = str[0..<2]; //tc("str: "+str); replace_string(str, "//", "/"); //tc("str: "+str); str = absolute_path(query_cwd(), str); //tc("str: "+str); if(!str || !sizeof(str)) str = "/"; //tc("str: "+str); if((x=file_size(str)) != -2) { if(x > -1) { message("system", sprintf("%s: Path is a file.", str), this_player()); return 0; } else { message("system", sprintf("%s: No such reference.", str), this_player()); return 0; } } //tc("str: "+str); __CurrentWorkingDirectory = str; message("system", sprintf("%s:", __CurrentWorkingDirectory), this_player()); return 1; } static private void pushd(string str) { if(__CWDCount++ == DIRECTORY_STACK_SIZE) { __CWDCount--; __CWDBottom = (++__CWDBottom) % DIRECTORY_STACK_SIZE; } __Stack[__CWDTop] = str; __CWDTop = (++__CWDTop) % DIRECTORY_STACK_SIZE; } static private string popd() { if(!__CWDCount) return 0; __CWDCount--; return __Stack[--__CWDTop]; } nomask static private string do_nickname(string str) { if(!__Nicknames) return str; if(str[0..7] == "nickname") return str; return implode(map_array(explode(str, " "), "replace_nickname", this_object()), " "); } nomask static private string do_alias(string str) { string *words; string tmp; int x, i; if(!sizeof(words = explode(str, " "))) return ""; if((x = strlen(words[0])) && (tmp = __Xverbs[words[0][0..0]])) { words[0] = words[0][1..x-1]; return replace_string(tmp, "$*", implode(words, " ")); } if(!(tmp = __Aliases[words[0]])) return implode(words, " "); else str = implode(words[1..sizeof(words)-1], " "); return replace_string(tmp, "$*", str); } nomask static private string do_history(string str) { string *args; string tmp, cmd, expr; int x, slen, i; if(str[0] != '!') return str; if(str == "!!" || str == "!-1") { if(__CmdNumber == 0) { message("system", "Try entering a command first.", this_player()); return ""; } else return __History[(__CmdNumber-1) % __HistorySize]; } if(sscanf(str, "%ss/%s", cmd, expr) == 2) { if((tmp = do_history(cmd)) == "") return ""; switch(sizeof(args = explode(expr, "/"))) { case 2: if((x = strsrch(tmp, args[0])) == -1) { message("system", "nmsh: History expression not found.", this_player()); return ""; } else if(!x) return sprintf("%s%s",args[1],tmp[strlen(args[0])..strlen(tmp)-1]); else return sprintf("%s%s%s", tmp[0..x-1], args[1], tmp[x+strlen(args[0])..strlen(tmp)-1]); case 3: if(args[2] != "g") { message("system", "nmsh: History syntax error.", this_player()); return ""; } else return replace_string(tmp, args[0], args[1]); default: message("system", "nmsh: History syntax error.", this_player()); return ""; } } if(sscanf(str, "!%d", x) == 1) { if(x < 1) x = 1+ __CmdNumber + x; if(x < 1 || x >= 1 + __CmdNumber) { message("system", sprintf("Event %d not found.", x), this_player()); return ""; } if(__CmdNumber - __HistorySize > x) { message("system", sprintf("Event %d is lost from the queue.", x), this_object()); return ""; } else return __History[(x-1) % __HistorySize]; } else { if(__CmdNumber <= __HistorySize) i=sizeof(args=map_array(__History[0..__CmdNumber-1],"replace_null", this_object())); else i=sizeof(args=map_array(__History[__HistoryBottom..__HistorySize-1]+ __History[0..__HistoryTop], "replace_null", this_object())); while(i--) if(!strsrch(args[i], str[1..strlen(str)-1])) return args[i]; return ""; } } nomask static string replace_null(string str) { if(!str) return ""; else return str; } nomask static private void add_history_cmd(string str) { __History[__HistoryTop = (++__CmdNumber-1) % __HistorySize] = str; if(__CmdNumber < __HistorySize) __HistoryBottom = 0; else if(!__HistoryTop) __HistoryBottom = __HistorySize - 1; else __HistoryBottom = __HistoryTop + 1; } nomask static string replace_nickname(string str) { if(str == "") return str; if(str[0] == '\\') return str[1..(strlen(str)-1)]; else if(__Nicknames[str]) return __Nicknames[str]; else return str; } void reset_history() { __CmdNumber = 0; __HistoryCount = __HistoryBottom = __HistoryTop = 0; __History = allocate(__HistorySize = query_history_size()); } void reset_prompt() { __Prompt = query_prompt(); if(!stringp(__Prompt)) __Prompt = "Prompt screwey> "; __Prompt = replace_string(__Prompt, "$M", mud_name()); __Prompt = replace_string(__Prompt, "$m", lower_case(mud_name())); __Prompt = replace_string(__Prompt, "$N", (string)this_object()->query_CapName()); __Prompt = replace_string(__Prompt, "$n", query_name()); } string query_cwd() { return __CurrentWorkingDirectory; } int query_history_size() { return MIN_HISTORY_SIZE; } string query_prompt() { return DEFAULT_PROMPT; } int query_mp() { return 1; } int query_max_mp() { return 10; } int query_hp() { return 1; } int query_max_hp() { return 10; } int query_sp() { return 1; } int query_max_sp() { return 10; } string get_path() { return query_cwd(); } varargs int query_invis(object ob) { return 0; } string query_name() { return 0; }