/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#ifndef lint
static char RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/vars.c,v 1.11 92/03/01 23:14:11 mjr Exp $";
#endif
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include <ctype.h>
#include "mud.h"
#include "vars.h"
#include "sbuf.h"
#include "match.h"
/* WARNING - globals will robinson, globals! */
char typ_str[] = "str";
char typ_int[] = "int";
char typ_cmd[] = "cmd";
char typ_list[] = "lst";
char typ_bool[] = "boo";
char typ_obj[] = "obj";
char typ_flag[] = "flg";
char typ_u[] = "U";
char var_loc[] = "loc";
char var_cont[] = "con";
char var_xit[] = "xit";
char var_dest[] = "dst";
char var_dropto[] = "drpto";
char var_lock[] = "lok";
char var_jump[] = "jmp";
char var_link[] = "lnk";
char var_ply[] = "ply";
char var_owner[] = "own";
char var_nam[] = "nam";
char var_desc[] = "desc";
char var_text[] = "txt";
char var_pass[] = "pass";
char var_using[] = "use";
char var_wiz[] = "_wz";
char var_fail[] = "fail";
char var_ofail[] = "ofail";
char var_succ[] = "succ";
char var_osucc[] = "osucc";
char var_drop[] = "drop";
char var_odrop[] = "odrop";
char var_isplay[] = "_pl";
char var_isdark[] = "dark";
char var_isroom[] = "_rm";
char var_islocal[] = "lcl";
char var_newsart[] = "newsarticle";
char var_subive[] = "subv";
char var_Subve[] = "Subv";
char var_objive[] = "objv";
char var_Objve[] = "Objv";
char var_posive[] = "posv";
char var_Posve[] = "Posv";
char var_home[] = "home";
char var_linkmsg[] = "linkmsg";
char var_wearing[] = "_wear";
#ifdef COMBAT
char var_strength[] = "_stren";
char var_Strength[] = "_Stren";
char var_endurance[] = "_endur";
char var_Endurance[] = "_Endur";
char var_willpower[] = "_willp";
char var_Willpower[] = "_Willp";
char var_agility[] = "_dextr";
char var_Agility[] = "_Dextr";
char var_magic[] = "_magic";
char var_Magic[] = "_Magic";
char var_action[] = "_actup";
char var_Action[] = "_Actup";
char var_power[] = "_power";
char var_counters[] = "counter";
char var_lastupd[] = "_lupd";
char var_lasthit[] = "_lhit";
char var_lastatt[] = "_latt";
char var_isdead[] = "_dead";
char var_weapon[] = "_weapon";
/* flags */
char var_isweapon[] = "_isweap";
char var_isarmor[] = "_isarm";
#endif
/* system object related stuff. */
char system_object[] = "sysobj";
char var_objcnt[] = "_objcnt";
char var_syslimbo[] = "_syslimbo";
char var_wizs[] = "_wizards";
char var_bsequence[] = "_backupseq";
/* variable type table */
TypTab ttab[] = {
typ_str,
typ_int,
typ_cmd,
typ_list,
typ_bool,
typ_obj,
typ_flag,
typ_u,
0
};
/*
variable permissions and other whatnots table. these should be
roughly in order of preference, since "set" chooses based on first
match
*/
VarTab vtab[] = {
var_desc, "description", typ_str, VAR_LOC_PUBLIC,
"description",
var_text, "text", typ_str, VAR_LOC_PUBLIC,
"text inscription",
var_fail, "failure", typ_str, VAR_MTYP,
"failure message/command",
var_ofail, "ofailure", typ_str, VAR_MTYP,
"other player failure message/command",
var_succ, "success", typ_str, VAR_MTYP,
"success message/command",
var_osucc, "osuccess", typ_str, VAR_MTYP,
"other player success message/command",
var_drop, "drop", typ_str, VAR_MTYP,
"drop message/command",
var_odrop, "odrop", typ_str, VAR_MTYP,
"other player drop message/command",
var_subive, "subjective", typ_str, VAR_LOC_PUBLIC,
"subjective pronoun",
var_Subve, "Subjective", typ_str, VAR_LOC_PUBLIC,
"subjective pronoun (capitalized)",
var_objive, "objective", typ_str, VAR_LOC_PUBLIC,
"objective pronoun",
var_Objve, "Objective", typ_str, VAR_LOC_PUBLIC,
"objective pronoun (capitalized)",
var_posive, "possessive", typ_str, VAR_LOC_PUBLIC,
"possessive pronoun",
var_Posve, "Possessive", typ_str, VAR_LOC_PUBLIC,
"possessive pronoun (capitalized)",
#ifdef PLAYER_NAMECHANGING
var_nam, "name", typ_str, VAR_PUBLIC,
"name",
#else
var_nam, "name", typ_str, VAR_PRIVPLY|VAR_PUBLIC,
"name",
#endif
var_pass, "password", typ_str, VAR_PRIV,
"object's password",
var_owner, "owners", typ_list, 0,
"object owner list",
var_ply, "players", typ_list, VAR_LOC_PUBLIC|VAR_PRIV,
"room player list",
var_cont, "contents", typ_list, VAR_LOC_PUBLIC|VAR_PRIV,
"contents list",
var_xit, "exits", typ_list, VAR_PRIV,
"room exit list",
var_wizs, "wizardlist", typ_list, VAR_PRIV,
"valid wizards",
var_loc, "location", typ_obj, VAR_PRIV,
"location of an object",
var_dest, "destination", typ_obj, VAR_PRIV,
"exit destination",
var_dropto, "dropto", typ_obj, 0,
"dropto destination",
var_using, "holding", typ_obj, VAR_PRIV,
"object being held by player",
var_using, "using", typ_obj, VAR_PRIV,
"object being used by player",
var_home, "home", typ_obj, 0,
"object's home location",
var_jump, "jump", typ_bool, VAR_MTYP,
"object access lock",
var_lock, "lock", typ_bool, VAR_MTYP,
"object access lock",
var_link, "linkok", typ_bool, 0,
"link permissions",
var_isdark, "isdark", typ_flag, 0,
"object is dark",
var_islocal, "local", typ_flag, 0,
"object is local",
var_wiz, "wizard", typ_flag, VAR_PRIV,
"object is a wizard",
var_isplay, "isplayer", typ_flag, VAR_PRIV,
"object is a player",
var_isroom, "isroom", typ_flag, VAR_PRIV,
"object is a room",
var_newsart, "newsarticle", typ_int, 0,
"last read news article",
var_linkmsg, "linkmessage", typ_str, VAR_PRIV,
"portal player moved through",
var_wearing, "wearing", typ_list, VAR_PRIV,
"player garments",
#ifdef COMBAT
var_strength, "strength", typ_int, VAR_PRIV,
"player current strength",
var_Strength, "Strength", typ_int, VAR_PRIV,
"player maximum strength",
var_endurance, "endurance", typ_int, VAR_PRIV,
"player current endurance",
var_Endurance, "Endurance", typ_int, VAR_PRIV,
"player maximum endurance",
var_willpower, "willpower", typ_int, VAR_PRIV,
"player current willpower",
var_Willpower, "Willpower", typ_int, VAR_PRIV,
"player maximum willpower",
var_agility, "agility", typ_int, VAR_PRIV,
"player current agility",
var_Agility, "Agility", typ_int, VAR_PRIV,
"player maximum agility",
var_magic, "magic", typ_int, VAR_PRIV,
"player current magic level",
var_Magic, "Magic", typ_int, VAR_PRIV,
"player maximum magic level",
var_action, "action", typ_int, VAR_PRIV,
"player current action points",
var_Action, "Action", typ_int, VAR_PRIV,
"player maximum action points",
var_counters, "counters", typ_list, 0,
"player counterattack list",
var_power, "power", typ_int, VAR_PRIV,
"player current power level",
var_lastupd, "lastupd", typ_str, VAR_PRIV,
"player last combat stats update time",
var_lasthit, "lasthit", typ_obj, VAR_PRIV,
"player last attacker that hit",
var_lastatt, "lastatt", typ_obj, VAR_PRIV,
"player last attacker",
var_isdead, "isdead", typ_flag, VAR_PRIV,
"player killed by something",
var_weapon, "weapon", typ_obj, VAR_PRIV,
"player weapon in use",
var_isweapon, "isweapon", typ_flag, VAR_PRIV,
"object is weapon flag",
var_isarmor, "isarmor", typ_flag, VAR_PRIV,
"object is armor flag",
#endif
0, 0, 0, 0,
0
};
/* return nonzero if the variable is public */
int
var_ispublic(vn,who,aswho,what)
char *vn;
char *who;
char *aswho;
char *what;
{
VarTab *vp = vtab;
if(*vn == LOC_PUB_COOKIE) {
return(!strcmp(ut_loc(who),ut_loc(what)) ||
!strcmp(who,ut_loc(what)) ||
!strcmp(ut_loc(who),what));
}
while(vp->vnam != (char *)0) {
if(!strcmp(vp->vnam,vn)) {
if(vp->flg & VAR_PUBLIC)
return(1);
if(vp->flg & VAR_LOC_PUBLIC) {
if(ut_flagged(what,var_isdark))
return(0);
return(!strcmp(ut_loc(who),ut_loc(what)) ||
!strcmp(who,ut_loc(what)) ||
!strcmp(ut_loc(who),what));
}
}
vp++;
}
return(0);
}
static int
set_help(who)
char *who;
{
VarTab *vp = vtab;
TypTab *tp = ttab;
char line[60];
/* TODO - prettier format ? */
say(who,"\nData types known to this MUD:\n",(char *)0);
while(tp->tnam != (char *)0) {
say(who,tp->tnam," ",(char *)0);
tp++;
}
say(who,"\n\n",(char *)0);
say(who,"Attributes known to this MUD:\n",(char *)0);
say(who,"-long name- -(type : shortname)- -description-\n",(char *)0);
while(vp->vnam != (char *)0) {
sprintf(line,"%-13.13s(%-5.5s:%11.11s) %23.23s",
vp->vlong,
vp->deftyp,
vp->vnam,
vp->desc);
say(who,line,(char *)0);
if(vp->flg & VAR_PUBLIC)
say(who," (public)",(char *)0);
if(vp->flg & VAR_PRIV)
say(who," (wiz-only)",(char *)0);
if(vp->flg & VAR_MTYP)
say(who," (multi-type)",(char *)0);
if(vp->flg & VAR_PRIVPLY)
say(who," (wiz-only on players)",(char *)0);
say(who,"\n",(char *)0);
vp++;
}
say(who,"\n",(char *)0);
return(UERR_NONE);
}
VarTab *
var_tabfind(nam)
char *nam;
{
VarTab *vp = vtab;
while(vp->vnam != (char *)0) {
if(!strcmp(vp->vnam,nam) || !strcmp(vp->vlong,nam))
return(vp);
vp++;
}
return((VarTab *)0);
}
/* resolve a possible long-form name to short form */
char *
var_namatch(nam)
char *nam;
{
VarTab *vp;
if((vp = var_tabfind(nam)) == (VarTab *)0)
return((char *)0);
return(vp->vnam);
}
/* ARGSUSED */
cmd_set(argc,argv,who,aswho)
int argc;
char *argv[];
char *who;
char *aswho;
{
char ob[MAXOID];
char *typp;
char *atpp;
char *vapp;
if(argc == 2 && !strcmp(argv[1],"help"))
return(set_help(who));
if(argc < 3 || argc > 5) {
say(who,"usage: set thing [type] attribute value\n",(char *)0);
say(who,"or \"set help\" for help using \"set\"\n",(char *)0);
return(UERR_ARGCNT);
}
if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob))
return(UERR_NOMATCH);
typp = (char *)0;
atpp = argv[2];
vapp = argv[3];
/* type spec given ? */
if(argc > 4) {
typp = argv[2];
atpp = argv[3];
vapp = argv[4];
}
return(var_set_internal(who,aswho,ob,typp,atpp,vapp,1));
}
/*
internal set routine -
very gross!! but all this gook has to fit someplace
called also from U-interpreter code.
*/
var_set_internal(who,aswho,ob,typp,atpp,vapp,vbose)
char *who;
char *aswho;
char *ob;
char *typp;
char *atpp;
char *vapp;
int vbose;
{
VarTab *vp;
int izlist = 0;
int wiz;
/* can we find a match in the variable table? */
if((vp = var_tabfind(atpp)) != (VarTab *)0) {
if(typp == (char *)0)
typp = vp->deftyp;
atpp = vp->vnam;
}
/* if it's not one of the known attributes, we need its type */
if(typp == (char *)0) {
if(vbose)
say(who,"\"",atpp,"\" type unknown. Provide its type.\n",(char *)0);
return(UERR_ILLASGN);
}
if (strlen(typp) == 0 || strlen(atpp) == 0 ||
index(typp, '=') != (char *) 0 || index(atpp, '=') != (char *)0) {
if(vbose)
say(who, "Attributes and types must be non-blank and contain no = characters.\n", (char *)0);
return(UERR_ILLASGN);
}
/* is this a priv'd attribute? */
wiz = ut_flagged(aswho,var_wiz);
/* stamp out type clash - usually - only wizards may typeclash */
if(vp != (VarTab *)0 && !wiz && !(vp->flg & VAR_MTYP) &&
strcmp(typp,vp->deftyp)) {
if(vbose)
say(who,vp->vlong," is only a ",vp->deftyp,
". You cannot set it to be a ",typp,".\n",(char *)0);
return(UERR_ILLASGN);
}
/* priv'd attribute */
if(vp != (VarTab *)0 && (vp->flg & VAR_PRIV) && !wiz) {
if(vbose)
say(who,"You must be a wizard to set ",vp->vlong,".\n",(char *)0);
return(UERR_PERM);
}
/* check for wiz-only on player */
if(vp != (VarTab *)0 && (vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) {
if(vbose)
say(who,"You must be a wizard to set ",vp->vlong," for a player.\n",(char *)0);
return(UERR_PERM);
}
/* next: do we own the thang?? */
if(!wiz && !ut_isobjown(aswho,ob)) {
if(vbose)
say(who,"You don't own ",ut_name(ob),".\n",(char *)0);
return(UERR_PERM);
}
/* if the type is a flag, trap it here */
if(!strcmp(typp,typ_flag)) {
/* Special case for DARK */
if(!wiz && !strcmp(atpp,var_isdark) && !ut_flagged(ob,var_isroom)){
if(vbose)
say(who,"You can't set a non-room dark!\n",(char *)0);
return(UERR_ILLASGN);
}
if(ut_set(who,ob,typp,atpp,""))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Set flag ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
/* at this point, we need another arg at least */
if(vapp == (char *)0) {
if(vbose)
say(who,"Set ",typp," ",atpp," to what?\n",(char *)0);
return(UERR_ARGCNT);
}
/* do not allow strings starting with '#' */
if(!wiz && !strcmp(typp,typ_str) && vapp[0] == '#') {
if(vbose)
say(who,"You cannot start a string with '#'.\n",(char *)0);
return(UERR_ILLASGN);
}
/* do re-writing and syntax checks on booleans */
if(!strcmp(typp,typ_bool)) {
Sbuf suf;
sbuf_initstatic(&suf);
if(bool_rewrite(who,vapp,&suf)) {
if(vbose)
say(who,"Bad Boolean expression.\n",(char *)0);
sbuf_freestatic(&suf);
return(UERR_SYNTAX);
}
vapp = sbuf_buf(&suf);
if(bool_syntax(who,vapp)) {
sbuf_freestatic(&suf);
return(UERR_SYNTAX);
}
if(ut_set(who,ob,typp,atpp,vapp)) {
sbuf_freestatic(&suf);
return(UERR_FATAL);
}
if(vbose && run_level() == 0)
say(who,"Set ",atpp,".\n",(char *)0);
sbuf_freestatic(&suf);
return(UERR_NONE);
}
/* special case for lists and objects being set to NULL */
izlist = !strcmp(typp,typ_list);
if((izlist || !strcmp(typp,typ_obj)) && vapp[0] == '\0') {
if(ut_unset(who,ob,atpp))
return(UERR_FATAL);
if(vbose)
say(who,"Nulled out ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
/* special case for lists +thing and -thing */
if(izlist && (vapp[0] == '+' || vapp[0] == '-')) {
char *thang;
if(!strcmp("me",&vapp[1]))
thang = aswho;
else if(!strcmp("here",&vapp[1]))
thang = ut_loc(who);
else
thang = &vapp[1];
if(vapp[0] == '-') {
if(ut_listdel(who,ob,atpp,thang))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Dropped ",thang," from ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
/* Must be adding it. Special case owners list. Xtra chex.*/
if(!strcmp(atpp,var_owner) &&
(!ut_isgoodid(thang) || !cache_check(thang))){
if(vbose && run_level() == 0)
say(who,"Cannot add ",thang," to owners list.\n",(char *)0);
return(UERR_BADOID);
}
/* add away */
if(ut_listadd(who,ob,atpp,thang))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Added ",thang," to ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
if(!wiz && izlist && vbose && run_level() == 0){
say(who, "Use + or - to manipulate lists, please.\n",(char *)0);
return(UERR_ILLASGN);
}
/* special case for droptos */
if(!strcmp(atpp,var_dropto)){
/* We setting this on a room? */
if(!wiz && !ut_flagged(ob,var_isroom)){
if(vbose)
say(who,"Can't set a dropto on a non-room.\n",(char *)0);
return(UERR_ILLASGN);
}
/* Can we link to that? */
if(!wiz && strcmp(vapp,"home") && !ut_flagged(vapp,var_isroom)) {
if(vbose)
say(who,"Can't set a dropto to a non-room.\n",(char *)0);
return(UERR_ILLASGN);
}
if(!wiz && strcmp(vapp,"home") && !ut_isobjown(aswho,vapp)
&& bool_locked(aswho,vapp,ut_loc(aswho),var_link,1)) {
if(vbose)
say(who,"You can't link a dropto to ",vapp,".\n",(char *)0);
return(UERR_ILLASGN);
}
}
/* special case for homes */
if(!strcmp(atpp,var_home)){
char hm[MAXOID];
if(matchlocal(who,vapp,ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,hm)){
if(vbose)
say(who,"I can't find ",vapp,".\n",(char *)0);
return(UERR_NOMATCH);
}
/* Can we set the home to it? */
if(!wiz &&!ut_isobjown(aswho,hm) && bool_locked(aswho,hm,ut_loc(aswho),var_link,1)) {
if(vbose)
say(who,"You can't set home to ",vapp,".\n",(char *)0);
return(UERR_PERM);
}
if(!wiz && ut_flagged(ob,var_isplay)) {
if(!ut_flagged(hm,var_isroom)) {
if(vbose)
say(who,vapp," isn't a room!\n",(char *)0);
return(UERR_ILLASGN);
}
} else if (!wiz) {
if(!ut_flagged(hm,var_isroom) && !ut_flagged(hm,var_isplay)) {
if(vbose)
say(who,"You can't set home to ",vapp,".\n",(char *)0);
return(UERR_ILLASGN);
}
}
if(index(hm,'@') == (char *)0){
/* Flesh the object ID out fully */
/* Be anal retentive about it */
if(strlen(hm) + strlen(mud_getname()) + 1 > MAXOID){
if(vbose)
say(who,"You can't set home to ",vapp,".\n",(char *)0);
return(UERR_ILLASGN);
}
strcat(hm,"@");
strcat(hm,mud_getname());
}
if(ut_set(who,ob,typp,atpp,hm))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Set ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
#ifdef PLAYER_NAMECHANGING
/* log name changes - why not ? */
if(!wiz && !strcmp(atpp,var_nam) && ut_flagged(ob,var_isplay)) {
if(index(vapp,'\'')||index(vapp,'\"')||index(vapp,';')) {
if(vbose)
say(who,"Illegal character in name.\n",(char *)0);
return(UERR_ILLASGN);
}
plogf("%s changed %s name to %s\n",who,ob,vapp);
}
#endif
if(ut_set(who,ob,typp,atpp,vapp))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Set ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
/* ARGSUSED */
cmd_unset(argc,argv,who,aswho)
int argc;
char *argv[];
char *who;
char *aswho;
{
char ob[MAXOID];
if(matchlocal(who,argv[1],ut_loc(who),MTCH_UNIQ|MTCH_NONLOC|MTCH_MEOK,ob))
return(UERR_NOMATCH);
return(var_unset_internal(who,aswho,ob,argv[2],1));
}
var_unset_internal(who,aswho,ob,atpp,vbose)
char *who;
char *aswho;
char *ob;
char *atpp;
int vbose;
{
int wiz;
VarTab *vp = vtab;
while(vp->vnam != (char *)0) {
if(!strcmp(vp->vnam,atpp))
break;
if(!strcmp(vp->vlong,atpp)) {
atpp = vp->vnam;
break;
}
vp++;
}
wiz = ut_flagged(aswho,var_wiz);
if(vp->vnam != (char *)0 && (vp->flg & VAR_PRIV) && !wiz) {
if(vbose)
say(who,"You must be a wizard to unset ",vp->vlong,".\n",(char *)0);
return(UERR_PERM);
}
if((vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged(ob,var_isplay)) {
if(vbose)
say(who,"You must be a wizard to unset ",vp->vlong," for a player.\n",(char *)0);
return(UERR_PERM);
}
if(!wiz && !ut_isobjown(aswho,ob)) {
if(vbose)
say(who,"You don't own ",ut_name(ob),".\n",(char *)0);
return(UERR_PERM);
}
if(ut_unset(who,ob,atpp))
return(UERR_FATAL);
if(vbose && run_level() == 0)
say(who,"Unset ",atpp,"\n",(char *)0);
return(UERR_NONE);
}
/* check if this is a known attribute and possibly */
/* get the long name (to use as a title) */
void
fndvnam(vt,buf,siz)
char *vt; /* the attribute */
char *buf; /* long name? */
int siz;
{
VarTab *vp;
/* can we find a match in the variable table? */
for(vp = vtab; vp->vnam != (char *)0; ++vp) {
if(!strcmp(vp->vnam,vt)) {
if(buf != (char *)0)
strncpy(buf,vp->vlong,siz - 2);
return;
}
}
if(buf != (char *)0)
strncpy(buf,vt,siz - 2); /* gotta tell'em something... */
buf[siz - 1] = '\0';
}
fndtyp(vt)
char *vt;
{
TypTab *tp;
for(tp = ttab; tp->tnam != (char *)0; tp++)
if(!strcmp(vt,tp->tnam))
return(1);
return(0);
}