#include "copyright.h"
/* commands which set parameters */
#include "os.h"
#include "db.h"
#include "config.h"
#include "match.h"
#include "interface.h"
#include "externs.h"
#ifdef COMPRESS
#define alloc_compressed(x) alloc_string(compress(x))
#else /* COMPRESS */
#define alloc_compressed(x) alloc_string(x)
#endif /* COMPRESS */
#define FREE_STRING(X) X = ((X) ? (free ((void *) (X)), NULL) : NULL)
static dbref match_controlled (dbref player, const char *name)
{
dbref match;
init_match (player, name, NOTYPE);
match_everything ();
match = noisy_match_result ();
if (match != NOTHING && !controls (player, match)) {
notify (player, "Permission denied.");
return NOTHING;
} else {
return match;
}
}
void do_name (dbref player, const char *name, char *newname)
{
dbref thing;
char *password;
if ((thing = match_controlled (player, name)) != NOTHING) {
/* check for bad name */
if (*newname == '\0') {
notify (player, "Give it what new name?");
return;
}
/* check for renaming a player */
if (Typeof (thing) == TYPE_PLAYER) {
/* split off password */
for (password = newname; *password && !isspace ((int)*password); password++);
/* eat whitespace */
if (*password) {
*password++ = '\0'; /* terminate name */
while (*password && isspace ((int)*password))
password++;
}
/* check for null password */
if (!*password) {
notify (player,
"You must specify a password to change a player name.");
notify (player, "E.g.: name player = newname password");
return;
} else if (strcmp (db[thing].name, "guest") == 0) {
notify (player, "You are only a guest here...no name changing.");
return;
} else if (!db[thing].password) {
/* If original has no password, set one */
db[thing].password = alloc_string (password);
} else if (strcmp (password, db[thing].password)) {
notify (player, "Incorrect password.");
return;
} else if (string_compare (newname, db[thing].name) &&
!ok_player_name (newname)) {
notify (player, "You can't give a player that name.");
return;
}
/* everything ok, notify */
writelog ("NAME CHANGE: %s(#%d) to %s\n",
db[thing].name, thing, newname);
#ifdef PLAYER_LIST
delete_player (thing);
free ((void *) db[thing].name);
db[thing].name = alloc_string (newname);
add_player (thing);
notify (player, "Name set.");
return;
#endif /* PLAYER_LIST */
} else {
if (!ok_name (newname)) {
notify (player, "That is not a reasonable name.");
return;
}
}
/* everything ok, change the name */
if (db[thing].name) {
free ((void *) db[thing].name);
}
db[thing].name = alloc_string (newname);
notify (player, "Name set.");
}
}
void do_describe (dbref player, const char *name, const char *description)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
if (db[thing].description) {
free ((void *) db[thing].description);
}
db[thing].description = alloc_compressed (description);
notify (player, "Description set.");
}
}
void do_fail (dbref player, const char *name, const char *message)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
if (db[thing].fail_message) {
free ((void *) db[thing].fail_message);
}
db[thing].fail_message = alloc_compressed (message);
notify (player, "Message set.");
}
}
void do_success (dbref player, const char *name, const char *message)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
if (db[thing].succ_message) {
free ((void *) db[thing].succ_message);
}
db[thing].succ_message = alloc_compressed (message);
notify (player, "Message set.");
}
}
void do_osuccess (dbref player, const char *name, const char *message)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
if (db[thing].osuccess) {
free ((void *) db[thing].osuccess);
}
db[thing].osuccess = alloc_compressed (message);
notify (player, "Message set.");
}
}
void do_ofail (dbref player, const char *name, const char *message)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
if (db[thing].ofail) {
free ((void *) db[thing].ofail);
}
db[thing].ofail = alloc_compressed (message);
notify (player, "Message set.");
}
}
void do_lock (dbref player, const char *name, const char *keyname)
{
dbref thing;
struct boolexp *key;
init_match (player, name, NOTYPE);
match_everything ();
switch (thing = match_result ()) {
case NOTHING:
notify (player, "I don't see what you want to lock!");
return;
case AMBIGUOUS:
notify (player, "I don't know which one you want to lock!");
return;
default:
if (!controls (player, thing)) {
notify (player, "You can't lock that!");
return;
}
break;
}
key = parse_boolexp (player, keyname);
if (key == TRUE_BOOLEXP) {
notify (player, "I don't understand that key.");
} else {
/* everything ok, do it */
free_boolexp (db[thing].key);
db[thing].key = key;
notify (player, "Locked.");
}
}
void do_unlock (dbref player, const char *name)
{
dbref thing;
if ((thing = match_controlled (player, name)) != NOTHING) {
free_boolexp (db[thing].key);
db[thing].key = TRUE_BOOLEXP;
notify (player, "Unlocked.");
}
}
void do_unlink (dbref player, const char *name)
{
dbref exit;
init_match (player, name, TYPE_EXIT);
match_exit ();
match_here ();
if (Wizard (player)) {
match_absolute ();
}
switch (exit = match_result ()) {
case NOTHING:
notify (player, "Unlink what?");
break;
case AMBIGUOUS:
notify (player, "I don't know which one you mean!");
break;
default:
if (!controls (player, exit)) {
notify (player, "Permission denied.");
} else {
switch (Typeof (exit)) {
case TYPE_EXIT:
db[exit].location = NOTHING;
notify (player, "Unlinked.");
break;
case TYPE_ROOM:
db[exit].location = NOTHING;
notify (player, "Dropto removed.");
break;
default:
notify (player, "You can't unlink that!");
break;
}
}
}
}
void do_chown (dbref player, const char *name, const char *newobj)
{
dbref thing;
dbref owner;
init_match (player, name, NOTYPE);
match_everything ();
if ((thing = noisy_match_result ()) == NOTHING) {
return;
} else if ((owner = lookup_player (newobj)) == NOTHING &&
string_compare (newobj, "me")) {
notify (player, "I couldn't find that player.");
} else if (Typeof (thing) == TYPE_PLAYER) {
notify (player, "Players always own themselves.");
} else if (!Wizard (player) &&
((string_compare (newobj, "me") &&
owner != player) || !(db[thing].flags & UNWANTED))) {
notify (player, "Permission denied.");
} else if (!Wizard (player) && !could_doit (player, thing)) {
notify (player, "That item is locked.");
} else {
if (!string_compare (newobj, "me"))
owner = player;
db[thing].owner = owner;
notify (player, "Owner changed.");
}
}
void do_set (dbref player, const char *name, const char *flag)
{
dbref thing;
const char *p;
object_flag_type f;
/* find thing */
if ((thing = match_controlled (player, name)) == NOTHING)
return;
/* move p past NOT_TOKEN if present */
for (p = flag; *p && (*p == NOT_TOKEN || isspace ((int)*p)); p++);
/* identify flag */
if (*p == '\0') {
notify (player, "You must specify a flag to set.");
return;
} else if (string_prefix ("LINK_OK", p)) {
f = LINK_OK;
} else if (string_prefix ("DARK", p)) {
f = DARK;
} else if (string_prefix ("STICKY", p)) {
f = STICKY;
} else if (string_prefix ("WIZARD", p) || string_prefix ("TINKER", p)) {
f = WIZARD;
} else if (string_prefix ("TEMPLE", p) || string_prefix ("JUNKPILE", p)) {
f = TEMPLE;
} else if (string_prefix ("HAVEN", p)) {
f = HAVEN;
} else if (string_prefix ("ABODE", p)) {
f = ABODE;
} else if (string_prefix ("UNWANTED", p)) {
f = UNWANTED;
#ifdef ROBOT_MODE
} else if (string_prefix ("ROBOT", p) || string_prefix ("BOT", p)) {
if (Typeof (thing) == TYPE_PLAYER) {
if (Wizard (player)) {
writelog ("ROBOT: success %s(%d) %s %s(%d)\n",
db[player].name, player,
*flag == NOT_TOKEN ? "reset" : "set", db[thing].name, thing);
} else {
writelog ("ROBOT: failed %s(%d) %s %s(%d)\n",
db[player].name, player,
*flag == NOT_TOKEN ? "reset" : "set", db[thing].name, thing);
notify (player,
#ifndef TINKER
"Only a Wizard can designate a player robotic.");
#else /* TINKER */
"Only a Tinker can designate a player robotic.");
#endif /* TINKER */
return;
}
}
f = ROBOT;
#endif /* ROBOT_MODE */
} else if (string_prefix ("TABULAR_WHO", p)) {
f = TABULAR_WHO;
} else if (string_prefix ("REVERSED_WHO", p)) {
f = REVERSED_WHO;
#ifdef GENDER
} else if (string_prefix ("MALE", p) || string_prefix ("FEMALE", p) ||
string_prefix ("NEUTER", p) || string_prefix ("UNASSIGNED", p)) {
if (Typeof (thing) != TYPE_PLAYER) {
notify (player, "Sorry, only players have gender.");
return;
}
if (thing != player && !Wizard (player)) {
notify (player, "You can only give yourself a sex-change.");
return;
}
db[thing].flags &= ~GENDER_MASK;
if (string_prefix ("UNASSIGNED", p) || *flag == NOT_TOKEN) {
db[thing].flags |= (GENDER_UNASSIGNED << GENDER_SHIFT);
notify (player, "Gender set to unassigned.");
} else if (string_prefix ("MALE", p)) {
db[thing].flags |= (GENDER_MALE << GENDER_SHIFT);
notify (player, "Gender set to male.");
} else if (string_prefix ("FEMALE", p)) {
db[thing].flags |= (GENDER_FEMALE << GENDER_SHIFT);
notify (player, "Gender set to female.");
} else if (string_prefix ("NEUTER", p)) {
db[thing].flags |= (GENDER_NEUTER << GENDER_SHIFT);
notify (player, "Gender set to neuter.");
}
return;
#endif /* GENDER */
#ifdef RESTRICTED_BUILDING
} else if (string_prefix ("BUILDER", p) ||) {
string_prefix ("CONSTRUCTOR", p)
f = BUILDER;
#endif /* RESTRICTED_BUILDING */
} else {
notify (player, "I don't recognize that flag.");
return;
}
/* check for restricted flag */
if (!Wizard (player)
&& (f == TEMPLE
#ifdef RESTRICTED_BUILDING
|| f == BUILDER
#endif /* RESTRICTED_BUILDING */
|| f == DARK &&
(Typeof (thing) != TYPE_ROOM && Typeof (thing) != TYPE_THING))) {
notify (player, "Permission denied.");
return;
}
#ifdef GOD_PRIV
if (!God (player) && f == DARK && Typeof (thing) == TYPE_PLAYER) {
notify (player, "Permission denied.");
return;
}
#endif /* GOD_PRIV */
if (!Wizard (player) && f == DARK && Typeof (thing) == TYPE_THING &&
db[thing].location != player) {
notify (player, "You must be holding an object to set it DARK.");
return;
}
#ifdef GOD_PRIV
if (!God (player) && (f == WIZARD)) {
#else
if (!Wizard (player) && (f == WIZARD)) {
#endif /* GOD_PRIV */
writelog ("WIZARD: failed %s(%d) %s %s(%d)\n",
db[player].name, player,
*flag == NOT_TOKEN ? "reset" : "set", db[thing].name, thing);
notify (player, "Permission denied.");
return;
}
if (f == WIZARD) {
writelog ("WIZARD: success %s(%d) %s %s(%d)\n",
db[player].name, player,
*flag == NOT_TOKEN ? "reset" : "set", db[thing].name, thing);
}
#ifdef GOD_PRIV
/* check for unGODding */
if (f == WIZARD && God (thing)) {
notify (player, "Gods can not me made mortal.");
return;
}
#else
if (f == WIZARD && thing == player) {
notify (player, "You cannot make yourself mortal!");
return;
}
#endif /* GOD_PRIV */
if (f == HAVEN && !(Typeof (thing) == TYPE_ROOM ||
Typeof (thing) == TYPE_PLAYER)) {
notify (player, "Only rooms or players can be HAVEN.");
return;
}
if (f == UNWANTED && Typeof (thing) == TYPE_PLAYER) {
notify (player, "You should always want yourself.");
return;
}
if ((f == TABULAR_WHO || f == REVERSED_WHO) &&
Typeof (thing) != TYPE_PLAYER) {
notify (player, "Player preference flags can only be set on players.");
return;
}
/* else everything is ok, do the set */
if (*flag == NOT_TOKEN) {
/* reset the flag */
db[thing].flags &= ~f;
notify (player, "Flag reset.");
} else {
/* set the flag */
db[thing].flags |= f;
notify (player, "Flag set.");
}
}
#ifdef RECYCLE
/****************************************************************
* do_recycle: Allow any player to give an item away...the item
* is @chowned to the "Recycler" player, and if it's a thing,
* it is @linked to the home of the "Recycler" as well.
****************************************************************/
void do_recycle (dbref player, const char *name)
{
dbref thing, recip, i;
char buf[BUFFER_LEN];
if (!name || !*name) {
notify (player, "You must specify an object to @recycle.");
return;
}
if ((thing = match_controlled (player, name)) == NOTHING)
return;
if (Typeof (thing) == TYPE_PLAYER) {
notify (player, "You can't @recycle players.");
return;
}
if ((recip = lookup_player (RECYCLER)) == NOTHING) {
notify (player, "There is no current Recycler.");
return;
}
/* Okay - do it */
db[thing].owner = recip;
/* If its a thing, link it to the Recyclers home */
if (Typeof (thing) == TYPE_THING) {
db[thing].exits = db[recip].exits;
moveto (thing, db[thing].exits);
}
/* Clear its strings */
FREE_STRING (db[thing].name);
FREE_STRING (db[thing].description);
FREE_STRING (db[thing].fail_message);
FREE_STRING (db[thing].ofail);
FREE_STRING (db[thing].succ_message);
FREE_STRING (db[thing].osuccess);
sprintf (buf, "junk-%d", thing);
db[thing].name = alloc_string (buf);
/* unlock it */
free_boolexp (db[thing].key);
db[thing].key = TRUE_BOOLEXP;
/* Make it worthless */
db[thing].pennies = 1;
/* Make it up for grabs */
db[thing].flags |= UNWANTED;
/* Tell player we did it */
notify (player, "Object recycled.");
}
/****************************************************************
* do_count: count things...
* players: Number of objects owned, carried
* rooms: number of exits from & to, number contents
****************************************************************/
void do_count (dbref player, const char *name)
{
dbref thing, i, exit;
char buf[BUFFER_LEN];
int owned = 0, contents = 0, from = 0, to = 0, objects = 0, rooms =
0, exits = 0;
int rowned = 0, rplayers = 0, robjects = 0, rrooms = 0, rexits = 0;
if (!name || !*name) {
notify (player, "You must specify an object to @count.");
return;
}
if ((thing = match_controlled (player, name)) == NOTHING)
return;
if (Typeof (thing) != TYPE_PLAYER && Typeof (thing) != TYPE_ROOM) {
notify (player, "You can only @count people or rooms.\n");
return;
}
if (!payfor (player, FIND_COST)) {
notify (player, "You don't have enough pennies.");
return;
}
switch (Typeof (thing)) {
case TYPE_PLAYER:
for (i = 0; i < db_top; i++) {
if (db[i].location == thing)
contents++;
if (db[i].owner == thing) {
switch (Typeof (i)) {
case TYPE_THING:
objects++;
break;
case TYPE_EXIT:
exits++;
break;
case TYPE_ROOM:
rooms++;
break;
}
owned++;
}
}
sprintf (buf,
"%s owns %d objects (%d things, %d rooms, %d exits), %d carried.",
unparse_object (player, thing), owned, objects, rooms, exits, contents);
notify (player, buf);
break;
case TYPE_ROOM:
for (i = 0; i < db_top; i++) {
if (db[i].location == thing) {
if (Typeof (i) == TYPE_EXIT) {
to++;
} else {
contents++;
}
}
}
DOLIST (exit, db[thing].exits) {
from++;
}
sprintf (buf, "%s has %d entrances, %d exits, %d objects.",
unparse_object (player, thing), to, from, contents);
notify (player, buf);
if (!Wizard (player))
break;
for (i = 0; i < db_top; i++) {
if (db[db[i].owner].location == thing) {
switch (Typeof (i)) {
case TYPE_EXIT:
rexits++;
break;
case TYPE_ROOM:
rrooms++;
break;
case TYPE_THING:
robjects++;
break;
case TYPE_PLAYER:
rplayers++;
break;
}
rowned++;
}
}
if (rplayers == 0) {
sprintf (buf, "There are no players in %s.\n",
unparse_object (player, thing));
} else {
sprintf (buf,
"The %d player%s in %s own%s %d %s: %d %s, %d %s, %d %s\n.",
rplayers, (rplayers == 1) ? "" : "s",
unparse_object (player, thing), (rplayers == 1) ? "s" : "",
rowned, "objects", robjects, "things", rrooms, "rooms",
rexits, "exits");
}
notify (player, buf);
break;
}
}
#endif /* RECYCLE */