/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /usr/users/mjr/hacks/umud/CMD/RCS/build.c,v 1.6 91/09/19 12:55:31 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(1);
	}

	/* get an object-ID for it and make it non-local */
	if(ut_objnew(who,nuf,0))
		return(1);

	/* add the object to player's inventory */
	if(ut_listadd(who,who,var_cont,nuf))
		return(1);

	/* 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(1);

	/* set location of the object (on the player) */
	if(ut_set(who,nuf,typ_obj,var_loc,who))
		return(1);

	/* 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(1);

	/* set name if one given */
	if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
		return(1);

	/* set desc if one given */
	if(desc != (char *)0 && ut_set(who,nuf,typ_str,var_desc,desc))
		return(1);

	if(run_level() == 0)
		say(who,"Created object ",nuf,".\n",(char *)0);
	return(0);
}




/* 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(1);
	}

	/* get an object-ID for it and make it non-local */
	if(ut_objnew(who,nuf,0))
		return(1);

	/* add the object to room */
	if(ut_listadd(who,loc,var_ply,nuf))
		return(1);

	/* set owner - player owns itself ! */
	if(ut_set(who,nuf,typ_list,var_owner,nuf))
		return(1);

	/* set password */
	if(pass == (char *)0) {
		/* set an empty password */
		if(ut_set(who,nuf,typ_str,var_pass,""))
			return(1);
	} else {
		if(ut_setpass(nuf,pass))
			return(1);
	}

	/* make it a player */
	if(ut_set(who,nuf,typ_flag,var_isplay,""))
		return(1);

	/* set location of the object (in the room) */
	if(ut_set(who,nuf,typ_obj,var_loc,loc))
		return(1);

	/* 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(1);

	/* set name if one given */
	if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
		return(1);

	if(run_level() == 0)
		say(who,"Created player ",nuf,".\n",(char *)0);
	return(0);
}




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];
	int	wiz;
	char	*op;

	if(!build_goodname(name,1)){
		say(who,"bad name.\n",(char *)0);
		return(1);
	}
	/* do we own this room ? */
	if((wiz = ut_flagged(aswho,var_wiz)) == 0 && !ut_isobjown(aswho,from)) {
		say(who,"Cannot open exit. Not owner.\n",(char *)0);
		return(1);
	}

	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(1);
	}

	if(ut_objnew(who,nuf,1))
		return(1);

	/* 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(1);

	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(1);

	/* link it to its destination - TODO - add checking, etc. */
	if(to != (char *)0) {
		if(ut_set(who,nuf,typ_obj,var_dest,to))
			return(1);

		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(1);

	/* add the object to room's exit list */
	if(ut_listadd(who,from,var_xit,nuf))
		return(1);
	return(0);
}




/* 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];

	if(!build_goodname(name,0)){
		say(who,"bad room name.\n",(char *)0);
		return(1);
	}
	if((exnam != (char *)0 && !build_goodname(exnam,1))
			|| (retnam != (char *)0 && !build_goodname(retnam,1))){
		say(who,"bad exit name.\n",(char *)0);
		return(1);
	}

	if(ut_objnew(who,nuf,1))
		return(1);

	/* 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(1);

	/* make it a room */
	if(ut_set(who,nuf,typ_flag,var_isroom,""))
		return(1);

	/* name it */
	if(name != (char *)0 && ut_set(who,nuf,typ_str,var_nam,name))
		return(1);

	if(exnam != (char *)0 && buildexit(who,aswho,exnam,ut_loc(who),nuf))
			return(1);

	if(retnam != (char *)0 && buildexit(who,aswho,retnam,nuf,ut_loc(who)))
			return(1);

	if(run_level() == 0)
		say(who,"Dug room ",nuf,".\n",(char *)0);
	return(0);
}




/* 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];
	int	wiz;

	if(matchexit(who,name,from,MTCH_EXACT|MTCH_NONLOC|MTCH_UNIQ,nuf))
		return (1);

	/* do we own this exit ? */
	if((wiz = ut_flagged(aswho,var_wiz)) == 0 && !ut_isobjown(aswho,nuf)) {
		say(who,"Cannot link exit. Not owner.\n",(char *)0);
		return(1);
	}

	if(to != (char *)0 && !build_canlink(who,aswho,to,from,1)){
		say(who,"Cannot link exit. Permission denied.\n",(char *)0);
		return(1);
	}

	if(to != (char *)0) {
		if(ut_set(who,nuf,typ_obj,var_dest,to))
			return(1);

		if(run_level() == 0)
			say(who,"Linked exit to ",to,".\n",(char *)0);
	}
	return(0);
}




/* 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(1);
	}

	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(1);
		}
		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(1);
		}
		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(0);
	}

	say(who,"I don't understand what you want to ",av[0],"\n",(char *)0);
	return(1);
}