/* buildcmds.c */
#include "copyright.h"
#include "config.h"
#include <stdio.h>
#ifdef STRING_H
#include <string.h>
#else
#include <strings.h>
#endif /* STRING_H */
#include <ctype.h>
#if defined(ALLOCA_H) && !defined(NO_ALLOCA)
#include <alloca.h>
#endif
#include "teeny.h"
#include "case.h"
#include "strlist.h"
/*
* Building/Creating commands
*/
/* Buffer from cmds.c */
extern char cmdwork[];
voidfunc do_create(player, argone)
int player;
char *argone;
{
int obj, next, home, here;
#ifdef RESTRICT_BUILDING
if (!isbuilder(player) && !iswiz(player)) {
notify_player(player, "That command is for authorized builders only.\r\n");
return;
}
#endif /* RESTRICT_BUILDING */
if (check_quota(player)) {
notify_player(player, "Sorry, you're over your limit.\r\n");
return;
}
if (!argone || !*argone) {
notify_player(player, "You need to specify a name.\r\n");
return;
}
if (!ok_name(argone)) {
notify_player(player, "That's a silly name for an object!\r\n");
return;
}
/* Go to it */
obj = create_obj(TYP_THING);
if (set_str_elt(obj, NAME, argone) == -1)
goto createbomb;
if (set_int_elt(obj, OWNER, player) == -1)
goto createbomb;
if (set_int_elt(obj, LOC, player) == -1)
goto createbomb;
if (get_int_elt(player, LOC, &here) == -1)
goto createbomb;
if (controls(player, here) || isabode(here)) {
home = here;
} else {
if (get_int_elt(player, HOME, &home) == -1)
goto createbomb;
}
if (set_int_elt(obj, HOME, home) == -1)
goto createbomb;
if (get_int_elt(player, CONTENTS, &next) == -1)
goto createbomb;
if (set_int_elt(player, CONTENTS, obj) == -1)
goto createbomb;
if (set_int_elt(obj, NEXT, next) == -1)
goto createbomb;
stamp(obj);
/* Tell the player */
sprintf(cmdwork, "Object %s created with number #%d.\r\n", argone, obj);
notify_player(player, cmdwork);
return;
createbomb:
notify_bad(player);
return;
}
voidfunc do_dig(player, arg, argtwo)
int player;
char *arg;
char *argtwo;
{
int room, parent;
#ifdef RESTRICT_BUILDING
if (!isbuilder(player) && !iswiz(player)) {
notify_player(player, "That command is for authorized builders only.\r\n");
return;
}
#endif /* RESTRICT_BUILDING */
if (check_quota(player)) {
notify_player(player, "Sorry, you're over your limit.\r\n");
return;
}
if (!arg || !*arg) {
notify_player(player, "You need to specify a name.\r\n");
return;
}
if (!ok_name(arg)) {
notify_player(player, "That's a silly name for a room!\r\n");
return;
}
if (!argtwo || !*argtwo) {
parent = ROOT_PARENT;
} else {
if (!strcasecmp(argtwo, "root"))
parent = ROOT_PARENT;
else {
if (argtwo[0] != '#' || !argtwo[1] || !isdigit(argtwo[1])) {
notify_player(player, "You must specify the parent by number.\r\n");
return;
}
parent = atoi(argtwo + 1);
if (!exists_object(parent)) {
notify_player(player, "That parent does not exist.\r\n");
return;
}
if (!isroom(parent)) {
notify_player(player, "Illegal parent.\r\n");
return;
}
if (!controls(player, parent) && parent != ROOT_PARENT &&
!isabode(parent)) {
notify_player(player, "Permission denied.\r\n");
return;
}
if (get_int_elt(parent, LOC, &room) == -1)
goto digbomb;
if (!legal_parent_check(parent, room)) {
notify_player(player, "Illegal parent.\r\n");
return;
}
}
}
room = create_obj(TYP_ROOM);
if (set_int_elt(room, OWNER, player) == -1)
goto digbomb;
if (set_str_elt(room, NAME, arg) == -1)
goto digbomb;
if (set_int_elt(room, LOC, parent) == -1)
goto digbomb;
list_add(room, parent, ROOMS_LIST);
stamp(room);
/* Tell the player */
sprintf(cmdwork, "Room %s created with number #%d.\r\n", arg, room);
notify_player(player, cmdwork);
return;
digbomb:
notify_bad(player);
return;
}
void do_set_string(player, argone, argtwo, code)
int player;
char *argone;
char *argtwo;
int code;
{
int obj, flags;
StringList *strs;
/* Find the thing to set the string ON */
if (!argone || !*argone) {
for (strs = Strings; strs->code && strs->code != code; strs++);
if (!strs->code) { /* shouldn't ever happen.. */
notify_player(player, "Set what on what?\r\n");
return;
}
(void) sprintf(cmdwork, "Set the %c%s string on what?\r\n",
DOWNCASE((strs->name)[0]), (strs->name) + 1);
notify_player(player, cmdwork);
return;
}
if ((obj = resolve_object(player, argone, 0)) == -1) {
if ((obj = resolve_exit(player, argone)) == -1) {
notify_player(player, "I don't see that here.\r\n");
return;
}
}
if (obj == -2) {
notify_player(player, "I don't know which one you mean.\r\n");
return;
}
if (!controls(player, obj)) {
notify_player(player, "You can't do that!\r\n");
return;
}
if (!isplayer(obj))
stamp(obj);
/* We *might* be setting a player name. Gotta be careful */
if (code == NAME) {
if (argtwo == NULL || *argtwo == 0) {
notify_player(player, "You must specify a name.\r\n");
return;
}
/* Check out the name */
if (get_int_elt(obj, FLAGS, &flags) == -1) {
warning("do_set_string", "cannot get flags");
goto namebomb;
}
if ((flags & TYPE_MASK) == TYP_EXIT)
if (!ok_exit_name(argtwo)) {
notify_player(player, "Bad exit name.\r\n");
return;
} else if (!ok_name(argtwo)) {
notify_player(player, "Bad name.\r\n");
return;
}
if ((flags & TYPE_MASK) == TYP_PLAYER) {
char *name, *pword, *givenpwd;
/* skip to pwd in given name */
if (parse_name_pwd(argtwo, &name, &givenpwd) == -1) {
notify_player(player, "Wrong password.\r\n");
return;
}
if (!ok_player_name(name)) {
notify_player(player, "You can't give a player that name.\r\n");
return;
}
if (get_str_elt(obj, PASSWORD, &pword) == -1) {
goto namebomb;
}
if (!pword || !*pword) {
notify_player(player, "You can't change your name.\r\n");
return;
}
if (!givenpwd || !*givenpwd) {
notify_player(player, "Wrong password.\r\n");
return;
}
if (strcmp(crypt(givenpwd, CRYPT_KEY), pword) != 0) {
notify_player(player, "Wrong password.\r\n");
return;
}
argtwo = name;
}
}
if (set_str_elt(obj, code, argtwo) == -1)
goto namebomb;
switch (code) {
case NAME:
notify_player(player, "Name set.\r\n");
break;
case DESC:
case IDESC:
notify_player(player, "Description set.\r\n");
break;
default:
notify_player(player, "Message set.\r\n");
}
return;
namebomb:
notify_bad(player);
return;
}
voidfunc do_open(player, argone, argtwo)
int player;
char *argone;
char *argtwo;
{
int here, exit, list, dest, flags;
int source;
char *p;
#ifdef RESTRICT_BUILDING
if (!isbuilder(player) && !iswiz(player)) {
notify_player(player, "That command is for authorized builders only.\r\n");
return;
}
#endif /* RESTRICT_BUILDING */
if (check_quota(player)) {
notify_player(player, "Sorry, you're over your limit.\r\n");
return;
}
if (!argone || !*argone) {
notify_player(player, "You must specify a name.\r\n");
return;
}
if (!ok_exit_name(argone) && !isgod(player)) {
notify_player(player, "That's a silly name for an exit!\r\n");
return;
}
/* parse for a source object */
for (p = argone; *p && *p != '/'; p++);
if (*p == '/') { /* found one */
*p++ = 0; /* terminate argone */
if (*p) {
if ((source = resolve_object(player, p, iswiz(player))) == -1) {
notify_player(player, "I can't find that source.\r\n");
return;
}
if (source == -2) {
notify_player(player, "I can't tell which source you mean.\r\n");
return;
}
if (!exists_object(source) || !controls(player, source) || isexit(source)) {
notify_player(player, "You can't open an exit on that!\r\n");
return;
}
} else {
notify_player(player, "You need to specify a source.\r\n");
return;
}
} else {
if (get_int_elt(player, LOC, &source) == -1)
goto openbomb;
#ifndef BUILDING_OK
if (!controls(player, source)) {
#else
if (!controls(player, source) && !isbuildok(source)) {
#endif
notify_player(player, "You can't open an exit here!\r\n");
return;
}
}
exit = create_obj(TYP_EXIT);
if (set_str_elt(exit, NAME, argone) == -1)
goto openbomb;
if (set_int_elt(exit, OWNER, player) == -1)
goto openbomb;
if (set_int_elt(exit, LOC, source) == -1)
goto openbomb;
if (get_int_elt(source, EXITS, &list) == -1)
goto openbomb;
if (set_int_elt(exit, NEXT, list) == -1)
goto openbomb;
if (set_int_elt(source, EXITS, exit) == -1)
goto openbomb;
stamp(exit);
/* Tell the player about this exit */
sprintf(cmdwork, "Exit %s opened with number #%d.\r\n", argone, exit);
notify_player(player, cmdwork);
if (get_int_elt(player, LOC, &here) == -1)
goto openbomb;
if (argtwo != NULL) { /* Try to link this */
if (strcasecmp(argtwo, "home") == 0) {
dest = -3;
} else {
if ((dest = resolve_object(player, argtwo, iswiz(player))) == -1) {
notify_player(player, "I can't find that destination.\r\n");
return;
}
if (dest == -2) {
notify_player(player, "I can't tell which destination you mean.\r\n");
return;
}
}
notify_player(player, "Trying to link...\r\n");
/* Can we link there? */
if (dest != -3 && !exists_object(dest)) {
notify_player(player, "Bad destination.\r\n");
return;
}
if (dest != -3 && get_int_elt(dest, FLAGS, &flags) == -1) {
notify_player(player, "Can't find destination.\r\n");
return;
}
if (dest != -3 && (TYPE_MASK & flags) == TYP_EXIT) {
notify_player(player, "You can't link an exit to that!\r\n");
return;
}
if (!controls(player, dest) && !(flags & LINK_OK)) {
notify_player(player, "Can't link to destination.\r\n");
return;
}
/* OK. We can link there. */
if (set_int_elt(exit, DESTINATION, dest) == -1)
goto openbomb;
notify_player(player, "Linked.\r\n");
}
return;
openbomb:
notify_bad(player);
return;
}
voidfunc do_link(player, argone, argtwo)
int player;
char *argone;
char *argtwo;
{
int dest, flags, thing, here;
int code, foo, exowner;
char *msg;
if (!argone || !*argone || !argtwo || !*argtwo) {
notify_player(player, "Link what to where?\r\n");
return;
}
if (get_int_elt(player, LOC, &here) == -1)
goto linkbomb;
/* Find the destination, thing to link to */
if (!strcasecmp(argtwo, "home"))
dest = -3;
else {
if ((dest = resolve_object(player, argtwo, iswiz(player))) == -1) {
notify_player(player, "I can't find that destination.\r\n");
return;
}
if (dest == -2) {
notify_player(player, "I can't tell which destination you mean.\r\n");
return;
}
}
/* Can we link there? */
if (dest != -3 && !exists_object(dest)) {
notify_player(player, "Bad destination.\r\n");
return;
}
if (dest != -3 && get_int_elt(dest, FLAGS, &flags) == -1) {
notify_player(player, "Can't find destination.\r\n");
return;
}
if (dest != -3 && (flags & TYPE_MASK) == TYP_EXIT) {
notify_player(player, "You can't link anything to that!\r\n");
return;
}
/* OK. Try to get the thing to link */
if ((thing = resolve_exit(player, argone)) == -1) {
if ((thing = resolve_object(player, argone, 0)) == -1) {
notify_player(player, "I don't see that here.\r\n");
return;
}
}
if (thing == -2) {
notify_player(player, "I can't tell which one you want to link.\r\n");
return;
}
if (get_int_elt(thing, FLAGS, &flags) == -1)
goto linkbomb;
switch (flags & TYPE_MASK) {
case TYP_PLAYER:
case TYP_THING:
if (!controls(player, dest) && !isabode(dest)) {
notify_player(player, "You can't link that there!\r\n");
return;
}
break;
case TYP_ROOM:
case TYP_EXIT:
if (!controls(player, dest) && !islinkok(dest)) {
notify_player(player, "You can't link that there!\r\n");
return;
}
}
/* What sort of thing is it? */
switch (flags & TYPE_MASK) {
case TYP_PLAYER:
case TYP_THING:
if (dest == -3) {
notify_player(player, "Paradox in link of object.\r\n");
return;
}
msg = "Home set.\r\n";
code = HOME;
break;
case TYP_ROOM:
msg = "Dropto set.\r\n";
code = DROPTO;
break;
case TYP_EXIT:
msg = "Linked.\r\n";
code = DESTINATION;
/* Check that the exit is unlinked */
if (get_int_elt(thing, DESTINATION, &foo) == -1)
goto linkbomb;
if (foo != -1) {
notify_player(player, "That exit is linked.\r\n");
return;
} else {
if (get_int_elt(thing, OWNER, &exowner) == -1)
goto linkbomb;
if (exowner != player) {
#ifdef RESTRICT_BUILDING
if (!isbuilder(player) && !iswiz(player)) {
notify_player(player, "Only authorized builders may do that.\r\n");
return;
}
#endif /* RESTRICT_BUILDING */
if (check_quota(player)) {
notify_player(player, "Sorry, you're over your limit.\r\n");
return;
}
}
}
if (set_int_elt(thing, OWNER, player) == -1)
goto linkbomb;
notify_player(player, "Trying to link...\r\n");
break;
default:
notify_player(player, "I don't understand that.\r\n");
warning("do_link", "bad type field detected");
return;
}
if (!controls(player, thing)) {
notify_player(player, "You don't own that!\r\n");
return;
}
/* Link it up. */
if (set_int_elt(thing, code, dest) == -1)
goto linkbomb;
notify_player(player, msg);
return;
linkbomb:
notify_bad(player);
return;
}
voidfunc do_unlink(player, arg)
int player;
char *arg;
{
int obj, flags, code;
char *msg;
if (!arg || !*arg) {
notify_player(player, "Unlink what?\r\n");
return;
}
if ((obj = resolve_exit(player, arg)) == -1) {
if ((obj = resolve_object(player, arg, 0)) == -1) {
notify_player(player, "I can't find that.\r\n");
return;
}
}
if (obj == -2) {
notify_player(player, "I can't tell which one you want to unlink.\r\n");
return;
}
if (!controls(player, obj)) {
notify_player(player, "You can't unlink that!\r\n");
return;
}
/* Unlink it. */
if (get_int_elt(obj, FLAGS, &flags) == -1)
goto unlinkbomb;
switch (flags & TYPE_MASK) {
case TYP_PLAYER:
case TYP_THING:
notify_player(player, "Can't unset an object's home!\r\n");
return;
case TYP_EXIT:
code = DESTINATION;
msg = "Exit unlinked.\r\n";
break;
case TYP_ROOM:
code = DROPTO;
msg = "Dropto unset.\r\n";
break;
default:
notify_player(player, "I don't understand that.\r\n");
return;
}
if (set_int_elt(obj, code, -1) == -1)
goto unlinkbomb;
notify_player(player, msg);
return;
unlinkbomb:
notify_bad(player);
return;
}
/*
* the next two routines provide @edit service. yay. the code be based on
* code found deep within TinyMUSH, with me own argument parser.
*/
static int parse_attrib(player, s, thing, atr)
int player;
char *s;
int *thing;
int *atr;
{
char buff[1024];
StringList *strs;
strcpy(buff, s);
/* get name up to / */
for (s = buff; *s && (*s != '/'); s++);
if (!*s)
return (0);
*s++ = 0;
if ((*thing = resolve_anything(player, buff, iswiz(player))) == -1)
return (0);
if (*thing == -2)
return (-2);
if (!exists_object(*thing) || !controls(player, *thing))
return (0);
/* rest is attrib name */
for (strs = Strings; strs->code; strs++) {
if (stringprefix(s, strs->name)) {
*atr = strs->code;
break;
}
}
if (!strs->code)
return (0);
if (((*atr == NAME) && isplayer(*thing)) || *atr == SITE || *atr == PASSWORD)
return (-1);
return (1);
}
voidfunc do_copy(player, first, second)
int player;
char *first, *second;
{
int ret, source, dest, satr, datr;
char *p, *buf = NULL, *msg;
if (!first || !*first || !second || !*second) {
notify_player(player, "Copy what to what?\r\n");
return;
}
if ((ret = parse_attrib(player, first, &source, &satr)) == 0) {
notify_player(player, "No match.\r\n");
return;
}
if (ret == -2) {
notify_player(player, "I can't tell which source object you mean.\r\n");
return;
}
if (ret != 1) {
notify_player(player, "Permission denied.\r\n");
return;
}
if ((ret = parse_attrib(player, second, &dest, &datr)) == 0) {
notify_player(player, "No match.\r\n");
return;
}
if (ret == -2) {
notify_player(player, "I can't tell which destination object you mean.\r\n");
return;
}
if (ret != 1) {
notify_player(player, "Permission denied.\r\n");
return;
}
if (get_str_elt(source, satr, &p) == -1) {
notify_bad(player);
return;
}
if (!p || !*p) {
notify_player(player, "Nothing to do.\r\n");
return;
}
#ifdef NO_ALLOCA
buf = (char *) ty_malloc(strlen(p) + 1, "do_copy");
#else
buf = (char *) alloca(strlen(p) + 1);
#endif
(void) strcpy(buf, p);
if (set_str_elt(dest, datr, buf) == -1) {
notify_bad(player);
#ifdef NO_ALLOCA
ty_free(buf);
#endif
return;
}
#ifdef NO_ALLOCA
ty_free(buf);
#endif
stamp(dest);
switch (datr) {
case NAME:
msg = "Name set.\r\n";
break;
case DESC:
case IDESC:
msg = "Description set.\r\n";
break;
default:
msg = "Message set.\r\n";
}
notify_player(player, msg);
}
voidfunc do_edit(player, it, args)
int player;
char *it;
char *args;
{
int thing;
int atr, d, len;
char *r, *s, *val;
char dest[1024], arg1[BUFFSIZ], arg2[BUFFSIZ];
if (!it || !*it) {
notify_player(player, "Edit what?\r\n");
return;
}
d = parse_attrib(player, it, &thing, &atr);
if (d == 0) {
notify_player(player, "No match.\r\n");
return;
} else if (d == -2) {
notify_player(player, "I can't tell which one you want to edit.\r\n");
return;
} else if (d != 1) {
notify_player(player,
"Permission denied. You can't change that attribute on that object.\r\n");
return;
}
/* parse arguments */
if (!args || !*args) {
notify_player(player, "Nothing to do.\r\n");
return;
}
d = 0;
/* make arg1 */
/* eat this pointer game, xibo ;-) */
while (d < (BUFFSIZ - 32) && args[0] != 0) {
if (args[0] != ',' && args[0] != '\\') {
arg1[d] = *args++;
d++;
} else {
if (args[0] == '\\' && args[1] != ',') {
arg1[d] = *args++;
d++;
} else {
if (args[0] == '\\' && args[1] == ',') {
arg1[d] = args[1];
args += 2;
d++;
} else {
arg1[d] = 0;
d++;
args++;
break;
}
}
}
}
arg1[d] = 0;
/* make arg2 */
d = 0;
while (d < (BUFFSIZ - 32) && args[d] != 0) {
arg2[d] = args[d];
d++;
}
arg2[d] = 0;
if (arg1[0] == 0) {
notify_player(player, "Nothing to do.\r\n");
return;
}
val = arg1;
r = (arg2[0]) ? arg2 : (char *) "";
/* replace all occurances of val with r */
if (get_str_elt(thing, atr, &s) == -1) {
warning("do_edit", "bad object ref");
notify_bad(player);
return;
}
if (!s || !*s) {
notify_player(player, "Nothing to do.\r\n");
return;
}
len = strlen(val);
for (d = 0; (d < 1000) && *s;)
if (strncmp(val, s, len) == 0) {
if ((d + strlen(r)) < 1000) {
strcpy(dest + d, r);
d += strlen(r);
s += len;
} else
dest[d++] = *s++;
} else
dest[d++] = *s++;
dest[d++] = 0;
dest[BUFFSIZ - 1] = '\0';
if (set_str_elt(thing, atr, dest) == -1) {
warning("do_edit", "failed to store revised string");
notify_bad(player);
return;
}
switch (atr) {
case DESC:
case IDESC:
notify_player(player, "Description set.\r\n");
break;
case NAME:
notify_player(player, "Name set.\r\n");
break;
default:
notify_player(player, "Message set.\r\n");
}
if (!isplayer(thing)) {
stamp(thing);
}
}