/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#ifndef lint
static char RCSid[] = "$Header: /home/mjr/hacks/umud/CMD/RCS/build.c,v 1.2 92/03/01 23:13:29 mjr Exp $";
#endif
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "mud.h"
#include "vars.h"
#include "match.h"
/*
create new objects for our mini-universe.
*/
static int build_goodname();
/* create a standard-carrying-around-type thang */
static int
buildobj(who,aswho,name,desc)
char *who;
char *aswho;
char *name;
char *desc;
{
char nuf[MAXOID];
char hm[MAXOID];
char *op;
if(!build_goodname(name,0)){
say(who,"bad name.\n",(char *)0);
return(UERR_ILLASGN);
}
if(ut_objnew(who,nuf))
return(UERR_FATAL);
eval_cmd_returnstr(nuf);
/* add the object to player's inventory */
if(ut_listadd(who,who,var_cont,nuf))
return(UERR_FATAL);
/* set owner */
op = ut_getatt(aswho,0,typ_list,var_owner,(char *)0);
if(op != (char *)0 && ut_set(who,nuf,typ_list,var_owner,op))
return(UERR_FATAL);
/* set location of the object (on the player) */
if(ut_set(who,nuf,typ_obj,var_loc,who))
return(UERR_FATAL);
/* set home of the object (on the player) */
(void)strcpy(hm,who);
ut_delocaliz(hm);
if(ut_set(who,nuf,typ_obj,var_home,hm))
return(UERR_FATAL);
/* set name if one given */
if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
return(UERR_FATAL);
/* set desc if one given */
if(desc != (char *)0 && ut_set(who,nuf,typ_str,var_desc,desc))
return(UERR_FATAL);
if(run_level() == 0)
say(who,"Created object ",nuf,".\n",(char *)0);
return(UERR_NONE);
}
/* make a new person! */
static int
buildplayer(who,aswho,name,loc,pass)
char *who;
char *aswho;
char *name;
char *loc;
char *pass;
{
char nuf[MAXOID];
char hm[MAXOID];
char *limbo;
if(!ut_flagged(aswho,var_wiz)) {
say(who,"Only a wizard can bring forth new life.\n",(char *)0);
return(UERR_PERM);
}
if(ut_objnew(who,nuf))
return(UERR_FATAL);
eval_cmd_returnstr(nuf);
/* add the object to room */
if(ut_listadd(who,loc,var_ply,nuf))
return(UERR_FATAL);
/* set owner - player owns itself ! */
if(ut_set(who,nuf,typ_list,var_owner,nuf))
return(UERR_FATAL);
/* set password */
if(pass == (char *)0) {
/* set an empty password */
if(ut_set(who,nuf,typ_str,var_pass,""))
return(UERR_FATAL);
} else {
if(ut_setpass(nuf,pass))
return(UERR_FATAL);
}
/* make it a player */
if(ut_set(who,nuf,typ_flag,var_isplay,""))
return(UERR_FATAL);
/* set location of the object (in the room) */
if(ut_set(who,nuf,typ_obj,var_loc,loc))
return(UERR_FATAL);
/* set home for the player (limbo) */
limbo = ut_getatt(system_object,0,typ_obj,var_syslimbo,(char *)0);
if(limbo == (char *)0) {
plogf("build player %s: no limbo; home is room %s\n",
nuf,loc);
say(who,"no limbo; player home is here\n",(char *)0);
limbo = loc;
}
(void)strcpy(hm,limbo);
ut_delocaliz(hm);
if(ut_set(who,nuf,typ_obj,var_home,hm))
return(UERR_FATAL);
/* set name if one given */
if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
return(UERR_FATAL);
if(run_level() == 0)
say(who,"Created player ",nuf,".\n",(char *)0);
return(UERR_NONE);
}
static int
build_canlink(who,aswho,to,from,remoteflg)
char *who;
char *aswho;
char *to;
char *from;
int remoteflg;
{
int wiz = ut_flagged(aswho,var_wiz);
/* If not to 'home', check the dest busily */
if(!strcmp(to,"home"))
return(1);
if(remoteflg && !wiz && !cache_check(to)) {
/* Try to make a remote link */
if(xact_addlink(to,from,aswho)){
say(who,"No such destination locally. Could not make ",
"remote link to ",to,".\n",(char *)0);
return(0);
}
} else {
/* is the destination link ok ? */
if(!wiz && !ut_isobjown(aswho,to) && bool_locked(aswho,to,(char *)0,var_link,1)) {
say(who,"Cannot link to ",to,".\n",(char *)0);
return(0);
}
/* is it really a room ? */
if(!wiz && !ut_flagged(to,var_isroom)) {
say(who,"You cannot link into a non-room.\n",(char *)0);
return(0);
}
}
return(1);
}
/*
check if a string is a valid thing-name. Basically, nothing can start with
and @ character.
*/
static int
build_goodname(nam,exitflag)
char *nam;
int exitflag;
{
int ok = 1;
if(nam == (char *)0)
return(0);
/* Don't let people build things that will confuse the matcher. */
if(strcmp(nam, "here") == 0 || strcmp(nam, "me") == 0)
return(0);
if(exitflag){ /* Check an exit name */
if(*nam == '#')
return(0);
while((nam = index(nam,';')) != (char *)0 && ok)
ok = (*(++nam) != '#');
return(ok);
} else { /* Check other stuff */
return(*nam != '#');
}
}
/* create an exit */
static int
buildexit(who,aswho,name,from,to)
char *who;
char *aswho;
char *name;
char *to;
char *from;
{
char nuf[MAXOID];
char *op;
if(!build_goodname(name,1)) {
say(who,"bad name.\n",(char *)0);
return(UERR_ILLASGN);
}
/* do we own this room ? */
if(ut_flagged(aswho,var_wiz) == 0 && !ut_isobjown(aswho,from)) {
say(who,"Cannot open exit. Not owner.\n",(char *)0);
return(UERR_PERM);
}
if(!strcmp("here",to))
to = ut_loc(run_actor());
if(to != (char *)0 && !build_canlink(who,aswho,to,from,1)) {
say(who,"Exit not created.\n",(char *)0);
return(UERR_PERM);
}
if(ut_objnew(who,nuf))
return(UERR_FATAL);
eval_cmd_returnstr(nuf);
/* chown it inherited from effective user-id */
op = ut_getatt(aswho,0,typ_list,var_owner,(char *)0);
if(op != (char *)0 && ut_set(who,nuf,typ_list,var_owner,op))
return(UERR_FATAL);
if(run_level() == 0)
say(who,"Opened exit ",nuf,".\n",(char *)0);
/* name it */
if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
return(UERR_FATAL);
/* link it to its destination - TODO - add checking, etc. */
if(to != (char *)0) {
if(ut_set(who,nuf,typ_obj,var_dest,to))
return(UERR_FATAL);
if(run_level() == 0)
say(who,"Linked exit to ",to,".\n",(char *)0);
}
/* set the exits location */
if(ut_set(who,nuf,typ_obj,var_loc,from))
return(UERR_FATAL);
/* add the object to room's exit list */
if(ut_listadd(who,from,var_xit,nuf))
return(UERR_FATAL);
return(UERR_NONE);
}
/* create a room */
static int
buildroom(who,aswho,name,exnam,retnam)
char *who;
char *aswho;
char *name;
char *exnam;
char *retnam;
{
char *op;
char nuf[MAXOID];
int xx;
if(!build_goodname(name,0)){
say(who,"bad room name.\n",(char *)0);
return(UERR_ILLASGN);
}
if((exnam != (char *)0 && !build_goodname(exnam,1))
|| (retnam != (char *)0 && !build_goodname(retnam,1))){
say(who,"bad exit name.\n",(char *)0);
return(UERR_ILLASGN);
}
if(ut_objnew(who,nuf))
return(UERR_FATAL);
/* chown it */
op = ut_getatt(aswho,0,typ_list,var_owner,(char *)0);
if(op != (char *)0 && ut_set(who,nuf,typ_list,var_owner,op))
return(UERR_FATAL);
/* make it a room */
if(ut_set(who,nuf,typ_flag,var_isroom,""))
return(UERR_FATAL);
/* name it */
if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
return(UERR_FATAL);
if(exnam != (char *)0 && (xx = buildexit(who,aswho,exnam,ut_loc(who),nuf)) != UERR_NONE)
return(xx);
if(retnam != (char *)0 && (xx = buildexit(who,aswho,retnam,nuf,ut_loc(who))) != UERR_NONE)
return(xx);
/* down here to return the OID of the room, not the exits */
eval_cmd_returnstr(nuf);
if(run_level() == 0)
say(who,"Dug room ",nuf,".\n",(char *)0);
return(UERR_NONE);
}
/* new destination for an existing exit */
static int
buildlink(who,aswho,name,from,to)
char *who;
char *aswho;
char *name;
char *to;
char *from;
{
char nuf[MAXOID];
if(matchexit(who,name,from,MTCH_EXACT|MTCH_NONLOC|MTCH_UNIQ,nuf))
return(UERR_NOMATCH);
/* do we own this exit ? */
if(ut_flagged(aswho,var_wiz) == 0 && !ut_isobjown(aswho,nuf)) {
say(who,"Cannot link exit. Not owner.\n",(char *)0);
return(UERR_PERM);
}
if(to != (char *)0 && !build_canlink(who,aswho,to,from,1)){
say(who,"Cannot link exit. Permission denied.\n",(char *)0);
return(UERR_PERM);
}
if(to != (char *)0) {
if(ut_set(who,nuf,typ_obj,var_dest,to))
return(UERR_FATAL);
if(run_level() == 0)
say(who,"Linked exit to ",to,".\n",(char *)0);
}
return(UERR_NONE);
}
/* figure out what the hell the goober is trying to do - modularize */
/* ARGSUSED */
cmd_build(ac,av,who,aswho)
int ac;
char *av[];
char *who;
char *aswho;
{
if(ac < 2) {
say(who,av[0]," a what?\n",(char *)0);
return(UERR_ARGCNT);
}
if(ac >= 2 && !strncmp(av[1],"object",strlen(av[1]))) {
char *name = (char *)0;
char *desc = (char *)0;
if(ac > 2) name = av[2];
if(ac > 3) desc = av[3];
return(buildobj(who,aswho,name,desc));
}
if(ac >= 2 && !strncmp(av[1],"room",strlen(av[1]))) {
char *name = (char *)0;
char *exnam = (char *)0;
char *retnam = (char *)0;
if(ac > 2) name = av[2];
if(ac > 3) exnam = av[3];
if(ac > 4) retnam = av[4];
return(buildroom(who,aswho,name,exnam,retnam));
}
if(ac >= 2 && !strncmp(av[1],"exit",strlen(av[1]))) {
char *name = (char *)0;
char *dest = (char *)0;
if(ac < 4) {
say(who,"usage: ",av[0]," exit name destination-room\n",(char *)0);
return(UERR_ARGCNT);
}
name = av[2];
dest = av[3];
return(buildexit(who,aswho,name,ut_loc(who),dest));
}
if(ac >= 2 && !strncmp(av[1],"link",strlen(av[1]))) {
char *name = (char *)0;
char *dest = (char *)0;
if(ac < 4) {
say(who,"usage: ",av[0]," link existing-exit destination-room\n",(char *)0);
return(UERR_ARGCNT);
}
name = av[2];
dest = av[3];
return(buildlink(who,aswho,name,ut_loc(who),dest));
}
if(ac >= 2 && !strncmp(av[1],"player",strlen(av[1]))) {
char *name = (char *)0;
char *pass = (char *)0;
if(ac > 2) name = av[2];
if(ac > 3) pass = av[3];
return(buildplayer(who,aswho,name,ut_loc(who),pass));
}
if(!strcmp(av[1],"help")) {
say(who,av[0]," object [name] [description]\n",(char *)0);
say(who,av[0]," room [name] [exit-to-name] [exit-back-name]\n",
(char *)0);
say(who,av[0]," exit name destination-room\n",(char *)0);
say(who,av[0]," link existing-exit destination-room\n",(char *)0);
say(who,av[0]," player name [password]\n",(char *)0);
return(UERR_NONE);
}
say(who,"I don't understand what you want to ",av[0],"\n",(char *)0);
return(UERR_ARGCNT);
}