/* * MusicMUD - Basic Verbs Module * Copyright (C) 1998-2003 Abigail Brady * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <string.h> #include <ctype.h> #include <stdlib.h> #include <unistd.h> #include "musicmud.h" #include "verbs.h" #include "util.h" #include "State.h" #include "flagnames.h" #include "misc.h" #include "util.h" #include "wordwrap.h" #include "events.h" #include "trap.h" #include "pflags.h" #include "vsprintf.h" #include "prep.h" #include "match.h" #include "msi.h" #include "levels.h" #include "move.h" #include "shared.h" #include <map> #define INDENT " " #define WIERD get_wierd() #define MODULE "verbs" static bool is_canlatch(MudObject *what) { return what->get_flag(FL_CANLATCH); } static char *exitnames[] = { "North", "East", "South", "West", "Rimwards", "Clockwise", "Hubwards", "Anticlockwise", "Fore", "Starboard", "Aft", "Port", "Up", "Down", "In", "Out", "Other"}; /* * * "size" = the actual size of this item. Subitems don't count to the mass * * "overhead" = the overhead of this item. Subitems DO count to the mass. * * * if neither, then "overhead" = 0 * */ static bool verb_exits(MudObject *player, int argc, const char**) { if (!cansee(player)) { player->printf("You can't see a thing.\n"); return true; } if (!player->owner) { player->printf("^WYou are nowhere.\n"); return true; } player->owner->ref(); MudObject *obj; int i, state=0; if (!has_light(player->owner) && !wf_wears_with_flag(player, FL_NIGHTVISION)) { player->printf("^WIt's ^Ldark^W!\n"); return true; } if (player->owner->get_flag(FL_ONFIRE) && !wf_wears_with_flag(player, FL_NIGHTVISION)) { player->printf("^RYou cannot see anything through the smoke and flames.\n"); return true; } int clas = 0; if (const char *cl=player->get("colours")) { if (cl && streq(cl, "classic")) { clas = 1; } } player->printf("%sObvious exits are...^n\n",clas?"^r":"^W"); foreach(player->owner->children, obj, i) { obj->set_flag(FL_OBSERVED, 0); } int had[17] = { 0 }; for (int j =0; j < 17; j++) { foreach(player->owner->children, obj, i) { if (obj->get_flag(FL_SECRET)) continue; MudObject *dest = obj->get_object("link"); MudObject *door = obj->get_object("door"); const char *en = obj->get("short"); if (!en && dest) { log (PFL_SEEINFO, 0, "bug", "%s has no short", obj->id); obj->set_flag(FL_OBSERVED, 1); continue; } if (dest && !obj->get_flag(FL_EXIT) && !obj->get_flag(FL_PARTEXIT)) { log (PFL_SEEINFO, 0, "bug", "%s apparently an exit but does not have an exit/partexit flag", obj->id); } if (obj != player && dest) if ((strcasecmp(en, exitnames[j])==0) || (j==16 && !obj->get_flag(FL_OBSERVED))) { if (!door || (door && !is_closed(door))) { obj->set_flag(FL_OBSERVED, 1); had[j] = 1; if (player->get_flag(FL_NSEW)) { if (streq(en, "rimwards") && !had[0]) en = "north"; if (streq(en, "anticlockwise") && !had[1]) en = "east"; if (streq(en, "hubwards") && !had[2]) en = "south"; if (streq(en, "clockwise") && !had[3]) en = "west"; } string x = ssprintf("\3Ex\4%s\3/Ex\4", en); int i = 14 - strlen(en); while (i>0) { x += " "; i--; } if (!player->get_priv(PFL_SEESTATS) || (player->owner->get_flag(FL_MAZE)) && (!can_affect(player, player->owner->get("zone")))) player->printf(INDENT"^d%s : %s%#s^}\n", x.c_str(), clas?"^{B":"^{D", room_name(dest, player->owner)); else { if (argc) player->printf(INDENT"^d%s : %s%#-30s^} : ^d%s ^d(^D%s^d)^n\n", x.c_str(), clas?"^{B":"^{D", room_name(dest, player->owner), dest->id, obj->id); else player->printf(INDENT"^d%s : %s%#-30s^} : ^d%s^n\n", x.c_str(), clas?"^{B":"^{D", room_name(dest, player->owner), dest->id); dest->ref(); } state++; } } } } foreach(player->owner->children, obj, i) { obj->set_flag(FL_OBSERVED, 0); } if (!state) { player->printf(INDENT"None...\n"); } return true; } static bool verb_lookin(MudObject *player, int argc, const char **argv) { if (argc < 2) { player->printf("Look in what?\n"); return true; } MudObject *what=0; NewWorld whatg = match(player, argc-1, argv+1, NULL, LOOK_BOTH|IGNORE_EXITS); if (whatg.getsize()>1) { player->printf("You can only look in one thing at a time.\n"); return true; } if (whatg.getsize()) { what = whatg.get_nth(0); } if (!what) { player->printf("Look in what?\n"); return true; } if (what->array_size("$fill") == 1) { describe_liquid_to(player, what); return true; } if (!is_container(what)) { player->printf("%#Y^n isn't a container.\n", what); return true; } if (is_closed(what) && !what->get_flag(FL_TRANSPARENT)) { player->printf("%#Y^n %s closed.\n", what, is_are(what)); return true; } MudObject *o; int i; bool need = true; player->spec_printf("%#Y contains : \n", what); map<string, NewWorld> m; map<string, string> plu; foreach(what->children, o, i) { if (o->get_flag(FL_EXIT)) continue; if (!o->get("name")) continue; const char *n = name(o); if (m.find(n)!=m.end()) { m[n].add(o); } else { NewWorld a; a.add(o); m[n] = a; } if (name(o, 1) && plu.find(n)==plu.end()) { plu[n] = name(o, 1, 1); } } for (map<string, NewWorld>::iterator it=m.begin();it!=m.end();it++) { string ph = it->first; const char *num = ""; if (it->second.getsize() != 1) { ph = plural_phrase(remove_articles(ph.c_str())); if (plu.find(it->first)!=plu.end()) { ph = plu.find(it->first)->second; } num = numbertostring(it->second.getsize()); } if (num[0]) { player->printf(" %s %s\n", num, ph.c_str()); } else { if (player->get_priv(PFL_SEESTATS)) { player->printf(" %s (%s)\n", ph.c_str(), it->second.get(0)->id); } else { player->printf(" %s\n", ph.c_str()); } } need = 0; } if (need) { player->cancel_printf(); player->printf("%#Y is empty.\n", what); } return true; } static bool key_fits(MudObject *key, MudObject *lock) { int i_key = key->get_int("key"); int i_lock = lock->get_int("lock"); if ((i_key > 0) && ((i_lock % i_key)==0)) return true; if (streq(lock->get("key"), key->id)) return true; if (streq(lock->id, key->get("lock"))) return true; MudObject *ta = key->get_object("treatas"); if (ta && ta != key) return key_fits(ta, lock); return false; } static void lock_unlock(MudObject *player,MudObject *what, MudObject *with, int to, const char *text, const char *text2=0) { if (with) { player->printf("You %s %Q with %Y.\n", text, what, with); if (!player->get_flag(FL_PLURAL) && text2) player->oprintf(cansee, "%#M %s %Q with %P.\n", player, text2, what, with); else player->oprintf(cansee, "%#M %s%[s/] %Q with %P.\n", player, text, what, with); } else { player->printf("You %s %Q.\n", text, what, to); if (!player->get_flag(FL_PLURAL) && text2) player->oprintf(cansee, "%#M %s %Q.\n", player, text2, what); else player->oprintf(cansee, "%#M %s%[s/] %Q.\n", player, text, what); } set_locked(what, to); MudObject *o = what->get_object("other"); if (o) { set_locked(o, to); o->oprintf(cansee, "%#Y %s %sed from the other side.\n", o, is_are(what), text); } } static bool verb_unlock(MudObject *player, int argc, const char *argv[]) { if (argc<2) { player->printf("Unlock what?\n"); return true; } MudObject *what=0; NewWorld whatg = match(player, argc-1, argv+1, NULL, LOOK_BOTH|FIND_EXITS); if (whatg.getsize()>1) { player->printf("You can only unlock one thing at a time.\n"); return true; } if (whatg.getsize()) { what = whatg.get_nth(0); } if (!what) { player->printf("Unlock what?\n", argv[1]); return true; } if ((what->get_flag(FL_EXIT)||what->get_flag(FL_PARTEXIT)) && what->get_object("door")) what = what->get_object("door"); /* ::: before_try_unlock o1==object we want to lock; return 1 to abort. before everything, including testing that it is locked */ if (dotrap(E_BEFORETRYUNLOCK, player, what)) return true; if (!is_locked(what)) { if (!is_canlatch(what)) { player->printf("%#Y %s not locked.\n", what, is_are(what)); return true; } else { player->printf("%#Y %s not latched.\n", what, is_are(what)); return true; } } if (is_canlatch(what)) { if (dotrap(E_BEFOREUNLOCK, player, what)) return true; /* ::: before_unlock o1==object to be unlocking, o2==the key (if any); return 1 to abort */ lock_unlock(player, what, 0, 0, "unlatch", "unlatches"); set_locked(what, 0); return true; } MudObject *other = what->get_object("other"); if (other && !what->get_flag(FL_CANLOCK) && other->get_flag(FL_CANLATCH)) { player->printf("%#Y %[is/are] latched from the other side.\n", what); return true; } int i; MudObject *o; foreach(player->children, o, i) { MudObject *oth=o->get_object("other"); if (key_fits(o, what) || (oth && key_fits(o, oth))) { if (dotrap(E_BEFOREUNLOCK, player, what, o)) return true; lock_unlock(player, what, o, 0, "unlock"); set_locked(what, 0); return true; } } if (!what->get_flag(FL_CANLOCK)) { player->printf("You can't unlock %Y.\n", what); return true; } player->printf("You have nothing to unlock %Y with.\n", what); return true; } static bool verb_close(MudObject *a, int b, const char **c); static bool verb_lock(MudObject *player, int argc, const char *argv[]) { if (argc<2) { player->printf("Lock what?\n"); return true; } MudObject *what=0; NewWorld whatg = match(player, argc-1, argv+1, NULL, LOOK_BOTH|FIND_EXITS); if (whatg.getsize()>1) { player->printf("You can only lock one thing at a time.\n"); return true; } if (whatg.getsize()) { what = whatg.get_nth(0); } if (!what) { player->printf("Lock what?\n", argv[1]); return true; } if ((what->get_flag(FL_EXIT)||what->get_flag(FL_PARTEXIT)) && what->get_object("door")) what = what->get_object("door"); if (!is_canlock(what) && !is_canlatch(what)) { player->printf("%#Y cannot be locked.\n", what); return true; } if (is_locked(what)) { player->printf("%#Y %s already locked.\n", what, is_are(what)); return true; } if (is_open(what)) { verb_close(player, argc, argv); if (is_open(what)) { return true; } } if (is_canlatch(what)) { if (dotrap(E_BEFORELOCK, player, what)) return true; /* ::: before_lock o1==object to be locking, o2==the key (if any); return 1 to abort */ lock_unlock(player, what, 0, 1, "latch", "latches"); return true; } int i; MudObject *o; foreach(player->children, o, i) { if (key_fits(o, what)) { if (dotrap(E_BEFORELOCK, player, what, o)) return true; lock_unlock(player, what, o, 1, "lock"); return true; } } player->printf("You have nothing to lock %M with.\n", what); return true; } static bool verb_openclose(MudObject *player, int argc, const char *argv[], const char *text, const char * past, int state, const char *already) { if (argc<2) { player->printf("%#s what?\n", text); return true; } MudObject *what=0; NewWorld whatg = match(player, argc-1, argv+1, NULL, LOOK_BOTH|FIND_EXITS); if (whatg.getsize()>1) { player->printf("You can only %s one thing at a time.\n", argv[0]); return true; } if (whatg.getsize()) { what = whatg.get_nth(0); } if (!what) { player->printf("%#s what?\n", argv[0]); return true; } if ((what->get_flag(FL_EXIT)||what->get_flag(FL_PARTEXIT)) && what->get_object("door")) what = what->get_object("door"); /* ::: before_try_open o1==object we want to lock; return 1 to abort. before everything, including testing that it is closed */ if (streq(text, "open") && dotrap(E_BEFORETRYOPEN, player, what)) return true; if (!is_canopen(what)) { player->printf("You cannot %s %Y.\n", text, what); return true; } if (is_locked(what) && streq(text, "open")) { verb_unlock(player, argc, argv); if (is_locked(what)) return true; } if (is_open(what)==state) { player->printf("%#Y %s already %s.\n", what, is_are(what), already); return true; } if (what && streq(text, "open")) { if (dotrap(E_ONOPEN, player, what)) return true; /* ::: open o1==object to open; return 1 to abort. if o1=='other' of the object really being opened, o2==the real object, and return 1 doesn't abort. */ } if (what && streq(text, "close")) { if (dotrap(E_ONCLOSE, player, what)) return true; /* ::: close o1==object to close; return 1 to abort. if o1=='other' of the object really being closed, o2==the real object, and return 1 doesn't abort. */ } MudObject *other = what->get_object("other"); if(other) { if(streq(text, "open")) { dotrap(E_ONOPEN, player, other, what); } else if(streq(text, "close")) { dotrap(E_ONCLOSE, player, other, what); } set_open(other, state); (other->owner)->aprintf("%#Q %s%[s/].\n", other, text); } set_open(what, state); player->printf("You %s %Q.\n", text, what); player->oprintf(cansee, "%#M %s%[s/] %Q.\n", player, text, what); if (what && streq(text, "open")) { if (dotrap(E_AFTEROPEN, player, what)) return true; /* ::: after_open o1==object opened */ } if (what && streq(text, "close")) { if (dotrap(E_AFTERCLOSE, player, what)) return true; /* ::: after_close o1==object closed */ } if(other) { if(streq(text, "open")) { if (dotrap(E_AFTEROPEN, player, other)) return true; } else if(streq(text, "close")) { if (dotrap(E_AFTERCLOSE, player, other)) return true; } } return true; } static bool verb_open(MudObject *a, int b, const char **c) { return verb_openclose(a, b, c, "open", "opened", 1, "open"); } static bool verb_close(MudObject *a, int b, const char **c) { return verb_openclose(a, b, c, "close", "closed", 0, "closed"); } static bool names_match(MudObject *what, const char *str) { if (names_match(what->get("name"), str)) return 1; if (names_match(what->get("short"), str)) return 1; if (names_match(what->get("short"), str)) return 1; if (names_match(what->get("altshort"), str)) return 1; return 0; } static bool verb_where(MudObject *player, int argc, const char **argv) { if (player->get_flag(FL_SLEEPING)) { player->printf("You toss and turn in your sleep.\n"); player->oprintf(cansee, "%#M tosses and turns in %s sleep.\n",player, his_or_her(player)); return true; } bool verbose = player->get_priv(PFL_SEESTATS); if (argc<2) { player->printf("Usage: where object\n"); return true; } if (strlen(argv[1])<2) { player->printf("Where is what?\n"); return true; } bool noclones = argv[1][0] == '|'; if (noclones) argv[1]++; if (!is_player(player)) return true; Divert d(player, "where"); MudObject *o; int i; int found=0; MudObject *empty = planet->get("empty"); foreach_alpha(planet, o, i) { MudObject *owner = o->owner; if (noclones && o->get_object("cloneof")) continue; if (o->get_flag(FL_ROOM)) continue; if (!owner || owner == empty || owner == mud) continue; if (o->get("link")) continue; if (!visible_to(player, o)) continue; if (!verbose && o->get_flag(FL_UNLOCATEABLE)) continue; if (!names_match(o, argv[1])) continue; if (!o->get("name")) continue; const char *ran = remove_articles(o->get("name")); MudObject *room = owner; while (!(room->get_flag(FL_ROOM) || room->get_flag(FL_SHIP)) && room->owner) { room = room->owner; } if (!room->get_flag(FL_ROOM) && !room->get_flag(FL_SHIP)) room = owner; string rsh = ran; size_t nonidspace = 35-strlen(o->id); int capornot = 0; string owh = owhere(o, room); if (!owh.length()) continue; if (colour_strlen(ran, colinfo(player))>=(nonidspace-2)) { if (o->get_flag(FL_MOBILE)) { rsh = "^P"; rsh += o->get("short")?:"???"; rsh += "^n"; capornot = 1; } else { rsh = "^o"; rsh += o->get("short")?:"???"; rsh += "^n"; } } char fmt[100]; sprintf(fmt, "%%s %%%s%is - %%-40s\n", capornot?"#":"", nonidspace); player->printf(fmt, o->id, rsh.c_str(), owh.c_str()); found = 1; } if (found == 0) player->printf("Nothing like that could be located.\n"); return true; } static bool verb_echo(MudObject *player, int argc, const char *argv[]) { if (player->get_flag(FL_SLEEPING)) { player->printf("You toss and turn in your sleep.\n"); player->oprintf(cansee, "%#M tosses and turns in %s sleep.\n",player,his_or_her(player)); return true; } string buffer = the_rest(argc, argv, 1); if (buffer.length()==0) { player->printf("Echo what?\n"); return true; } string buffer2 = sprinta(0, buffer.c_str(), player, 0, 0); MudObject *o; int i; if (is_player(player)) log(PFL_ECHO,0,"echo","in %s: '%s'" ,player->get("owner") , buffer2.c_str()); player->oprintf("%s\n", buffer2.c_str()); player->printf("You echo : '%s'\n", buffer2.c_str()); foreach(player->children, o, i) if (is_mobile(o) || is_player(o)) { o->printf("%s\n", buffer2.c_str()); } return true; } bool is_ininv(const TeleObject &what) { if (is_person(what.where)) return 1; return 0; } bool is_person(const TeleObject &what) { return is_person(what.what); } static bool verb_inject(MudObject *who, int argc, const char **argv) { if (argc<2) { who->printf("Inject what?\n"); return true; } TeleWorld prepless = multi_match(who, argc-1, argv+1, is_ininv, LOOK_BOTH|IGNORE_EXITS); TeleWorld blank; if (prepless.prep) { prepless = blank; } TeleWorld into = multi_match(who, argc-1, argv+1, is_person, LOOK_BOTH|IGNORE_EXITS, 0, 0, "into"); TeleWorld with = multi_match(who, argc-1, argv+1, NULL, LOOK_INV|IGNORE_EXITS, 0, 0, "with"); if (into.prep && with.prep && prepless.txt.length()) { who->printf("Inject what into who?\n"); return true; } if (!with.prep && !into.prep) { with = prepless; into.add(who); } else if (!with.prep) { with = prepless; } else if (!into.prep) { into = prepless; if (prepless.txt=="") { into.add(who); } } if (into.getsize()>1) { who->printf("You can only inject into one person at a time.\n"); return true; } if (with.getsize()>1) { who->printf("You can only inject with one implement at a time.\n"); return true; } if (into.getsize()==0) { who->printf("Inject who?\n"); return true; } if (with.getsize()==0) { who->printf("Inject with what?\n"); return true; } MudObject *needle = with.get(0).what; MudObject *victim = into.get(0).what; /* ::: before_inject o1==object to inject, o2==thing to inject into; return 1 to not give error */ if (dotrap(E_BEFOREINJECT, who, needle, victim)) return true; if (victim != who) { who->printf("You can't inject into %s.\n", him_or_her(victim)); return true; } /* ::: inject o1==object to inject; return 1 to not give error message */ if (dotrap(E_ONINJECT, who, needle)) return true; who->printf("You can't inject %M.\n", needle); return true; } static bool verb_hook(MudObject *player , int argc, const char **argv) { int next = 1; TeleWorld w1 = multi_match(player, argc-next, argv+next, NULL, LOOK_BOTH|IGNORE_EXITS, &next, 0, 0); TeleWorld w2; if (next < argc) { w2 = multi_match(player, argc-next, argv+next, NULL, LOOK_BOTH|IGNORE_EXITS, &next, 0, 0); } MudObject *what=0, *what2=0; if (w1.getsize()) { what = w1.get_nth(0); } if (w2.getsize()) { what2 = w2.get_nth(0); } if (streq(argv[0], "combine") && w1.getsize()==2 && w2.getsize()==0) { what2 = w1.get_nth(1); } else if (w1.getsize()>1) { if (streq(argv[0], "combine")) { player->printf("You can only combine two things at a time.\n", argv[0]); } else { player->printf("You can only %s one thing at a time.\n", argv[0]); } return true; } if (w2.getsize()>1) { player->printf("You can only %s %s one thing at a time.\n", argv[0], w2.prep); return true; } // FIXME : HARDCODED SPECIAL if (streq(argv[0], "press") || streq(argv[0], "push") && argv[1]) { if (dotrap(E_ONPRESSTEXT, player, player->owner, 0, argv[1])) /* ::: press_text o1==the room, txt==text after 'press' or 'push'; return 1 to abort */ return true; } if (what && what->get_flag(FL_PUSHTOGGLE)) { if (streq(argv[0], "press") || streq(argv[0], "push") || streq(argv[0], "move") || streq(argv[0], "heave")) { if (state(what)) { what->set(KEY_STATE, 0); } else { what->set(KEY_STATE, 1); } int nowstate = state(what); if (const char *up=what->get(ssprintf("user.push.%i", nowstate).c_str())) player->printf("%s\n", up); else if (what->get("reveal")) player->printf("You push %Y, %s %s.\n", what, nowstate?"blocking":"revealing", what->get("reveal")); else player->printf("You push %Y.\n", what); if (const char *op=what->get(ssprintf("others.push.%i", nowstate).c_str())) player->oprintf(cansee, "%s\n", op); else if (what->get("reveal")) player->oprintf(cansee, "%#M pushes %Y, %s %s.\n", player, what, nowstate?"blocking":"revealing", what->get("reveal")); else player->oprintf(cansee, "%#M pushes %P.\n", player, what); MudObject *o = what->get_object("other"); if (o && o->get("reveal")) { o->set(KEY_STATE, nowstate); o->oprintf(cansee, "%#M %[is/are] pushed from the other side, %s %s.\n", nowstate?"blocking":"revealing", o->get("reveal")); } if (MudObject *light=what->get_object("light")) { int lit = !nowstate; light->set_flag(FL_LIT, lit); light->oprintf(cansee, lit ? "%#Y %[illuminates/illuminate].\n" : "%#Y %[is/are] extinguished.\n", light); } return true; } } if (what && (streq(argv[0], "push") || streq(argv[0], "press") || streq(argv[0], "move"))) { if (dotrap(E_ONPUSH, player, what)) /* ::: push o1==object to push/press/move; return 1 to abort */ return true; if (dotrap("press", player, what)) return true; /* ::: push_mount o1==object being mounted by someone who has been pushed, o2==the person themself; return 1 to abort */ if (MudObject *m=mount(what)) { if (dotrap(E_ONPUSHMOUNT, player, m, what)) return true; } } if (streq(argv[0], "climb")) { if (what) { if (MudObject *m=mount(player)) { player->printf("You can't climb whilst you are on %Y.\n", m); return true; } if (player->get_flag(FL_FLYING)) { player->printf("You are flying and so climbing would be silly.\n"); return true; } if (player->get_flag(FL_SITTING)) { player->printf("Try standing up first.\n"); return true; } /* ::: climb o1==object to climb; return 1 to abort */ if (dotrap(E_ONCLIMB, player, what)) return true; if (what->get("climbto")) { traverse(player, what); return true; } } else { player->interpret("climbs"); return true; } } if (what && streq(argv[0], "turn")) { /* ::: turn o1==object to turn; return 1 to abort */ if (dotrap(E_ONTURN, player, what)) return true; } if (what && streq(argv[0], "combine")) { /* ::: combine o1==an object, o2==another object; called both ways; return 1 to abort */ if (what2) { if (dotrap(E_ONCOMBINE, player, what, what2)) return true; if (dotrap(E_ONCOMBINE, player, what2, what)) return true; } else { player->printf("Combine %M with what?\n", what); return 1; } } if (streq(argv[0], "tie")) { if (what && !what2) { player->printf("Tie %P to what?\n", what); return true; } if (what && what2) { /* ::: tie o1==object, o2==object to; return 1 to abort */ if (dotrap(E_ONTIE, player, what, what2)) return true; } } if (streq(argv[0], "untie")) { if (what) { /* ::: untie o1==object, o2==object from (if applicable); return 1 to abort */ if (dotrap(E_ONUNTIE, player, what, what2)) return true; } } if (what && streq(argv[0], "cut")) { if (dotrap(E_ONCUT, player, what, what2)) return true; /* ::: cut o1==target, o2==tool; return 1 to abort */ } if (what && streq(argv[0], "sign")) { if (dotrap(E_ONSIGN, player, what)) return true; /* ::: sign o1==target; return 1 to abort */ } if (what && streq(argv[0], "kick")) { if (dotrap(E_ONKICK, player, what)) return true; /* ::: kick o1==target; return 1 to abort */ if (what && what->get_flag(FL_FRAGILE)) { player->printf("You kick %P, smashing %s.\n", what, him_or_her(what)); player->oprintf(cansee, "%#M %[kicks/kick] %P, smashing %s.\n", player, what, him_or_her(what)); vanish(what); return true; } player->interpretf("kicks %s", argv[1]); return true; } if (what && streq(argv[0], "lift")) { /* ::: lift o1==target; return 1 to abort */ if (dotrap(E_ONLIFT, player, what)) return true; } if (what && streq(argv[0], "pull")) { /* ::: pull o1==target; return 1 to abort */ if (dotrap(E_ONPULL, player, what)) return true; } if (streq(argv[0], "trap")) { if (argv[1]) { dotrap(ssprintf("trap.%s", argv[1]).c_str(), player, player, 0, argv[1]); } /* ::: trap o1==target, txt==the text; return 1 to abort */ dotrap(E_ONTRAP, player, player, 0, argv[1]); return true; } if (streq(argv[0], "swing")) { if (!what) { player->printf("Swing on what?\n"); return true; } /* ::: swing o1==target; return 1 to abort */ if (dotrap(E_ONSWING, player, what, 0, 0)) return true; player->printf("You cannot swing on that.\n"); return true; } if (streq(argv[0], "clean")) { /* ::: clean o1==the room/object; return 1 to abort */ if (what) if (dotrap(E_ONCLEAN, player, what, 0, 0)) return true; if (!what || what->get_flag(FL_FLOOR)) { if (dotrap(E_ONCLEAN, player, player->owner, 0, 0)) return true; player->printf("You clean up your act.\n"); player->oprintf(cansee, "%#M cleans up %s act.\n", player, his_or_her(player)); } else { player->printf("You can't clean that.\n"); } return true; } if (streq(argv[0], "jump")) { if (MudObject *m=mount(player)) { /* ::: jump_mount o1==mount; return 1 to abort */ if (dotrap(E_ONJUMPMOUNT, player, m, 0, 0)) return true; player->printf("You can't jump when on %M.\n", m); return true; } if (player->get_flag(FL_FLYING)) { player->printf("You are flying and cannot jump.\n"); return true; } if (player->get_flag(FL_SWIMMING)) { player->printf("You are swimming and cannot jump.\n"); return true; } if (player->get_flag(FL_SITTING)) { player->printf("You are sitting and cannot jump.\n"); return true; } if (what) { if (dotrap(E_ONJUMPON, player, what)) return true; /* ::: jump_on o1==object to jump on; return 1 to abort */ } if (MudObject *o=player->get_object(KEY_SITON)) { if (dotrap(E_ONJUMPSTANDING, player, o)) /* ::: jump_standing o1==object you are standing on (not floor); return 1 to abort. */ return true; } /* ::: jump o1==room; return 1 to abort */ if (dotrap(E_ONJUMP, player, player->owner)) return true; player->printf("You jump.\n"); player->oprintf(cansee, "%#M %[jumps/jump].\n", player); return true; } if (what) { if (what2 || !w2.txt.length()) { player->printf("Nothing happens when you do that.\n"); } else { player->printf("Cannot find : ^o%s^n.\n", w2.txt.c_str()); } } else { if (argc > 1) { player->printf("Cannot find: ^o%s^n.\n", w1.txt.c_str()); } else { player->printf("What do you want to %s?\n", argv[0]); } } return true; } static const char *make_id(const char *zone, const char *abbrv) { int i = 1; static char temp[1024]; while (1) { if (abbrv) sprintf(temp, "%s_%s_%i", zone, abbrv, i); else sprintf(temp, "%s_%i", zone, i); if (planet->get(temp)==0) return temp; i++; } } static const char *expand_dir(const char *dir) { if (streq(dir, "n")) return "north"; if (streq(dir, "s")) return "south"; if (streq(dir, "e")) return "east"; if (streq(dir, "w")) return "west"; if (streq(dir, "u")) return "up"; if (streq(dir, "d")) return "down"; if (streq(dir, "a")) return "anticlockwise"; if (streq(dir, "r")) return "rimwards"; if (streq(dir, "h")) return "hubwards"; if (streq(dir, "c")) return "clockwise"; if (streq(dir, "i")) return "in"; if (streq(dir, "o")) return "out"; return dir; } void dig_exit(MudObject *player, const char *z, const char *dir) { if (!cantouch_zone(player, z)) { player->printf("Sorry, you can't modify %s zone.\n", z); return; } string id = make_id(z, 0); MudObject *r = new MudObject(id.c_str()); planet->add(*r); string start = ssprintf("%s_zone", z); set_owner(r, start.c_str()); if (r->owner==NULL) { set_owner(r, "@musicmud"); } r->set("start", r->owner->id); r->set_bflag(FL_ROOM, 1); r->set_bflag(FL_OUTDOORS, player->owner->get_flag(FL_OUTDOORS)); r->set_bflag(FL_LIT, player->owner->get_flag(FL_LIT)); r->set_bflag(FL_AIRLESS, player->owner->get_flag(FL_AIRLESS)); r->set_bflag(FL_NOGRAVITY, player->owner->get_flag(FL_NOGRAVITY)); r->set("name", "new room"); r->unreset(); id = ssprintf("%s_%s", player->owner->id, dir); MudObject *x = new MudObject(id.c_str()); planet->add(*x); set_owner(x, player->owner); x->set("link", r->id); x->set("short", dir); x->set("start", player->owner->id); id = ssprintf("%s_%s", r->id, other_dir(dir)); MudObject *x2 = new MudObject(id.c_str()); planet->add(*x2); set_owner(x2, r->id); x2->set("link", player->owner->id); x2->set("short", other_dir(dir)); x2->set("start", r->id); x->set("zone", z); r->set("zone", z); x2->set("zone", z); x->set_bflag(FL_FIXED, 1); x2->set_bflag(FL_FIXED, 1); x->set_bflag(FL_EXIT, 1); x2->set_bflag(FL_EXIT, 1); player->printf("You dig ^D%s^n to ^D%s^n.\n", dir, r->id); player->set("lastmaderoom", r->id); log(PFL_SEEINFO, 0, "make", "new room : %s", r->id); return; } static bool verb_dig(MudObject *player, int argc, const char **argv) { if (argc > 1 && player->get_priv(PFL_MAKE)) { argv[1] = expand_dir(argv[1]); const char *z = player->owner?player->owner->get("zone"):NULL; if (other_dir(argv[1]) && z && player->owner) { dig_exit(player, z, argv[1]); return true; } } /* ::: dig o1==room; return 1 to abort */ if (dotrap(E_ONDIG, player, player->owner)) return true; MudObject *where = player->owner; MudObject *buried = where->get_object("!buried"); if (buried) { player->printf("You find %P not far below the surface.\n", buried); player->oprintf(cansee, "%#M finds %P not far below the surface.\n", player, buried); set_owner(buried, where); where->unset("!buried"); return true; } MudObject *fl = floor(where); if (!fl) { player->printf("You can't dig here.\n"); return true; } if (fl->get_int("candig", 1)==0) { player->printf("You cannot dig through %Y.\n", fl); return true; } player->printf("You exert yourself needlessly, and find nothing.\n"); player->oprintf(cansee, "%#M attempts to dig for something, needlessly.\n", player); return true; } #include "verbmodule.h" #define HOOK_VERB(str, p, pfl) ADD_VERB(#str, strlen(#str), verb_hook, p, pfl) void startup() { AUTO_VERB(lookin, 5, 0, PFL_AWAKE); AUTO_VERB(exits, 3, 0, PFL_AWAKE); AUTO_VERB(lock, 3, 0, PFL_AWAKE); AUTO_VERB(unlock, 2, 0, PFL_AWAKE); ADD_ALIAS(latch, 3, lock); ADD_ALIAS(unlatch, 4, unlock); AUTO_VERB(open, 2, 0, PFL_AWAKE); AUTO_VERB(close, 4, 0, PFL_AWAKE); ADD_ALIAS(shut, 4, close); HOOK_VERB(climb, 0, PFL_AWAKE); HOOK_VERB(cut, 0, PFL_AWAKE); HOOK_VERB(heave, 0, PFL_AWAKE); HOOK_VERB(press, 0, PFL_AWAKE); HOOK_VERB(push, 0, PFL_AWAKE); //HOOK_VERB(inject, 0, PFL_AWAKE); HOOK_VERB(pull, 0, PFL_AWAKE); HOOK_VERB(tie, 0, PFL_AWAKE); HOOK_VERB(turn, 0, PFL_AWAKE); HOOK_VERB(combine, 0, PFL_AWAKE); HOOK_VERB(clean, 0, PFL_AWAKE); HOOK_VERB(untie, 0, PFL_AWAKE); HOOK_VERB(sign, 0, PFL_AWAKE); HOOK_VERB(swing, 0, PFL_AWAKE); HOOK_VERB(move, 0, PFL_AWAKE); HOOK_VERB(jump, 0, PFL_AWAKE); HOOK_VERB(kick, 0, PFL_AWAKE); HOOK_VERB(lift, 0, PFL_AWAKE); HOOK_VERB(trap, 0, PFL_AWAKE); AUTO_VERB(inject, 3, 0, PFL_AWAKE); AUTO_VERB(where, 3, 0, PFL_WHERE); AUTO_VERB(dig, 3, 0, PFL_AWAKE); AUTO_VERB(echo, 4, 0, PFL_ECHO); }