#include "copyright.h"
/* Wizard-only commands */
#include "os.h"
#include "db.h"
#include "config.h"
#include "interface.h"
#include "match.h"
#include "externs.h"
void do_teleport (dbref player, const char *arg1, const char *arg2)
{
dbref victim;
dbref destination;
const char *to;
#ifdef RESTRICTED_TELEPORT
if (!Wizard (player)) {
#ifndef TINKER
notify (player, "Only a Wizard may teleport at will.");
#else /* TINKER */
notify (player, "Only a Tinker may teleport at will.");
#endif /* TINKER */
return;
}
#endif /* RESTRICTED_TELEPORT */
/* get victim, destination */
if (*arg2 == '\0') {
victim = player;
to = arg1;
} else {
init_match (player, arg1, NOTYPE);
match_neighbor ();
match_possession ();
match_me ();
match_absolute ();
match_player ();
if ((victim = noisy_match_result ()) == NOTHING) {
return;
}
to = arg2;
}
/* get destination */
init_match (player, to, TYPE_PLAYER);
match_here ();
match_absolute ();
if (Wizard (player)) {
match_neighbor ();
match_me ();
match_player ();
}
switch (destination = match_result ()) {
case NOTHING:
notify (player, "Send it where?");
break;
case AMBIGUOUS:
notify (player, "I don't know which destination you mean!");
break;
default:
/* check victim, destination types, teleport if ok */
if (Typeof (destination) == TYPE_EXIT
|| Typeof (destination) == TYPE_THING
|| Typeof (victim) == TYPE_EXIT
|| Typeof (victim) == TYPE_ROOM
|| (Typeof (victim) == TYPE_PLAYER
&& Typeof (destination) != TYPE_ROOM)) {
notify (player, "Bad destination.");
#ifndef RESTRICTED_TELEPORT
} else if (!Wizard (player)
&& !(Typeof (victim) == TYPE_THING
&& Typeof (destination) == TYPE_ROOM && (controls (player, victim)
|| (Typeof (db[victim].location) == TYPE_ROOM
&& controls (player, db[victim].location)))
&& (can_link_to (player, TYPE_PLAYER, destination)))) {
notify (player, "Permission denied.");
#endif /* RESTRICTED_TELEPORT */
} else if (Typeof (victim) == TYPE_PLAYER) {
notify (victim, "You feel a wrenching sensation...");
enter_room (victim, destination);
notify (player, "Teleported.");
} else {
/* check for non-sticky dropto */
if (Typeof (destination) == TYPE_ROOM
&& db[destination].location != NOTHING
&& !(db[destination].flags & STICKY)) {
/* destination has immediate dropto */
destination = db[destination].location;
}
/* do the move */
moveto (victim, destination);
notify (player, "Teleported.");
}
}
}
void do_mass_teleport (dbref player, const char *arg1)
{
dbref victim;
dbref destination;
char buf[BUFFER_LEN];
int moved = 0;
if (!God (player)) {
#ifndef TINKER
notify (player, "Only God can do a mass teleport.");
#else /* TINKER */
notify (player, "Only the Master Tinker can do a mass teleport.");
#endif /* TINKER */
return;
}
/* get destination */
init_match (player, arg1, TYPE_ROOM);
match_here ();
match_absolute ();
if ((destination = match_result ()) == NOTHING) {
notify (player, "Please specify a destination to send everyone to.");
return;
}
switch (Typeof (destination)) {
case NOTHING:
notify (player, "Send them where?");
break;
case TYPE_ROOM:
for (victim = 0; victim < db_top; victim++) {
if (victim != player && Typeof (victim) == TYPE_PLAYER) {
notify (victim,
"You and everyone around you feels a wrenching sensation...");
moveto (victim, destination);
look_room (victim, destination);
moved++;
}
}
sprintf (buf, "Teleported %d players to %s.",
moved, unparse_object (player, destination));
notify (player, "Teleported.");
break;
default:
notify (player, "Mass teleports are legal to rooms only.");
}
}
void do_force (dbref player, const char *what, char *command)
{
dbref victim;
if (!Wizard (player)) {
writelog ("FORCE: failed, priv, player %s(%d), who '%s', what '%s'\n",
db[player].name, player, what, command);
#ifndef TINKER
notify (player, "Only Wizards may use this command.");
#else /* TINKER */
notify (player, "Only Tinkers may use this command.");
#endif /* TINKER */
return;
}
/* get victim */
if ((victim = lookup_player (what)) == NOTHING) {
writelog ("FORCE: failed, victim, player %s(%d), who '%s', what '%s'\n",
db[player].name, player, what, command);
notify (player, "That player does not exist.");
return;
}
#ifdef GOD_PRIV
if (God (victim)) {
#ifndef TINKER
writelog ("FORCE: failed, wizard, player %s(%d), who '%s', what '%s'\n",
#else /* TINKER */
writelog ("FORCE: failed, tinker, player %s(%d), who '%s', what '%s'\n",
#endif /* TINKER */
db[player].name, player, what, command);
#ifndef TINKER
notify (player, "You can't force God.");
#else /* TINKER */
notify (player, "You can't force the Master Tinker.");
#endif /* TINKER */
return;
}
#endif /* GOD_PRIV */
/* force victim to do command */
writelog ("FORCE: success, player %s(%d), who '%s', what '%s'\n",
db[player].name, player, what, command);
process_command (victim, command);
}
void do_stats (dbref player, const char *name)
{
dbref rooms;
dbref exits;
dbref things;
dbref players;
dbref total;
dbref i;
dbref owner;
char buf[BUFFER_LEN];
if (!Wizard (player)) {
sprintf (buf, "The universe contains %d objects.", db_top);
notify (player, buf);
} else {
owner = lookup_player (name);
total = rooms = exits = things = players = 0;
for (i = 0; i < db_top; i++) {
if (owner == NOTHING || owner == db[i].owner) {
total++;
switch (Typeof (i)) {
case TYPE_ROOM:
rooms++;
break;
case TYPE_EXIT:
exits++;
break;
case TYPE_THING:
things++;
break;
case TYPE_PLAYER:
players++;
break;
default:
abort ();
break;
}
}
}
sprintf (buf,
"%d objects = %d rooms, %d exits, %d things, %d players.",
total, rooms, exits, things, players);
notify (player, buf);
#ifdef TEST_MALLOC
sprintf (buf, "Malloc count = %d.", malloc_count);
notify (player, buf);
#endif /* TEST_MALLOC */
}
}
void do_bobble (dbref player, const char *name, const char *rname)
{
dbref victim, recip, i;
char buf[BUFFER_LEN];
int newflags = 0;
if (!Wizard (player)) {
#ifndef TINKER
writelog ("TOAD: failed, priv %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Only a Wizard can turn a person into a toad.");
#else /* TINKER */
writelog ("BOBBLE: failed, priv %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Only a Tinker can bobble a person.");
#endif /* TINKER */
return;
}
if (!name || !*name) {
#ifndef TINKER
writelog ("TOAD: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("BOBBLE: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "You must specify a victim.");
return;
}
init_match (player, name, TYPE_PLAYER);
match_neighbor ();
match_absolute ();
match_player ();
if ((victim = noisy_match_result ()) == NOTHING) {
#ifndef TINKER
writelog ("TOAD: failed, victim %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("BOBBLE: failed, victim %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "Please specify another victim.");
return;
}
#ifdef RECYCLE
/* Default the recipient to RECYCLER */
if (!rname || !*rname || string_compare (rname, RECYCLER) == 0) {
recip = lookup_player (RECYCLER);
newflags = UNWANTED; /* Can be gotten by other players */
} else {
recip = lookup_player (rname);
}
#else
recip = lookup_player (rname);
#endif
if (recip == NOTHING || recip == victim) {
#ifndef TINKER
writelog ("TOAD: failed, recip %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("BOBBLE: failed, recip %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player,
"Please specify another player to own the victim's effects.");
return;
}
if (Typeof (victim) != TYPE_PLAYER) {
#ifndef TINKER
writelog ("TOAD: failed, type %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can only turn players into toads!");
#else /* TINKER */
writelog ("BOBBLE: failed, type %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can only bobble players!");
#endif /* TINKER */
} else if (Wizard (victim)) {
#ifndef TINKER
writelog ("TOAD: failed, wizard %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can't turn a Wizard into a toad.");
#else /* TINKER */
writelog ("BOBBLE: failed, tinker %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can't bobble a Tinker.");
#endif /* TINKER */
} else if (db[victim].contents != NOTHING) {
#ifndef TINKER
writelog ("TOAD: failed, contents %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("BOBBLE: failed, contents %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "What about what they are carrying?");
} else {
#ifndef TINKER
writelog ("TOAD: success %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("BOBBLE: success %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
/* we are ok */
/* do it */
if (db[victim].password) {
free ((void *) db[victim].password);
db[victim].password = 0;
}
db[victim].flags = TYPE_THING;
/* Give the sphere and all old belongings to recipient */
db[victim].owner = recip;
for (i = 0; i < db_top; i++) {
if (db[i].owner == victim) {
db[i].owner = recip;
db[i].flags |= newflags;
}
}
db[victim].pennies = 1; /* dont let him keep his immense wealth */
/* notify people */
#ifndef TINKER
sprintf (buf, "You have been turned into a toad by %s.", db[player].name);
#else /* TINKER */
sprintf (buf, "You have been encased in a stasis sphere by %s.",
db[player].name);
#endif /* TINKER */
notify (victim, buf);
#ifndef TINKER
sprintf (buf, "You turned %s into a toad!", db[victim].name);
#else /* TINKER */
sprintf (buf, "You bobbled %s!", db[victim].name);
#endif /* TINKER */
notify (player, buf);
/* reset name */
#ifdef PLAYER_LIST
delete_player (victim);
#endif /* PLAYER_LIST */
#ifndef TINKER
sprintf (buf, "a slimy toad named %s", db[victim].name);
#else /* TINKER */
sprintf (buf, "a silvery sphere containing %s", db[victim].name);
#endif /* TINKER */
free ((void *) db[victim].name);
db[victim].name = alloc_string (buf);
}
}
void do_unbobble (dbref player, const char *name, const char *newname)
{
dbref victim;
char buf[BUFFER_LEN];
if (!Wizard (player)) {
#ifndef TINKER
writelog ("UNTOAD: failed, priv %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Only a Wizard can turn a toad into a person.");
#else /* TINKER */
writelog ("UNBOBBLE: failed, priv %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Only a Tinker can unbobble a person.");
#endif /* TINKER */
return;
}
if (!name || !*name) {
#ifndef TINKER
writelog ("UNTOAD: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("UNBOBBLE: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "You must specify a thing.");
return;
}
if (!newname || !*newname) {
#ifndef TINKER
writelog ("UNTOAD: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You must specify a new name: @untoad <thing> = <name>");
#else /* TINKER */
writelog ("UNBOBBLE: failed, syntax %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player,
"You must specify a new name: @unbobble <thing> = <name>");
#endif /* TINKER */
return;
}
init_match (player, name, TYPE_THING);
match_neighbor ();
match_absolute ();
match_player ();
if ((victim = noisy_match_result ()) == NOTHING) {
#ifndef TINKER
writelog ("UNTOAD: failed, victim %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("UNBOBBLE: failed, victim %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "Please specify another thing.");
return;
}
if (Typeof (victim) != TYPE_THING) {
#ifndef TINKER
writelog ("UNTOAD: failed, type %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can only turn players into toads!");
#else /* TINKER */
writelog ("UNBOBBLE: failed, type %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "You can only bobble players!");
#endif /* TINKER */
} else if (!ok_player_name (newname)) {
#ifndef TINKER
writelog ("UNTOAD: failed, name %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("UNBOBBLE: failed, name %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
notify (player, "You can't give a player that name!");
} else {
#ifndef TINKER
writelog ("UNTOAD: success %s(%d) who '%s'\n",
db[player].name, player, name);
#else /* TINKER */
writelog ("UNBOBBLE: success %s(%d) who '%s'\n",
db[player].name, player, name);
#endif /* TINKER */
/* we are ok */
/* do it */
db[victim].flags = TYPE_PLAYER;
db[victim].owner = victim;
db[victim].pennies = KILL_BONUS;
/* reset name */
free ((void *) db[victim].name);
db[victim].name = alloc_string (newname);
#ifndef TINKER
sprintf (buf, "You turned the toad back into %s!", db[victim].name);
#else /* TINKER */
sprintf (buf, "You unbobbled %s!", db[victim].name);
#endif /* TINKER */
notify (player, buf);
sprintf (buf, "Use @newpassword to give %s a password", db[victim].name);
notify (player, buf);
#ifdef PLAYER_LIST
add_player (victim);
#endif /* PLAYER_LIST */
}
}
void do_newpassword (dbref player, const char *name, const char *password)
{
dbref victim;
char buf[BUFFER_LEN];
if (!Wizard (player)) {
writelog ("PASSWORD: failed, priv %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Your delusions of grandeur have been duly noted.");
return;
} else if ((victim = lookup_player (name)) == NOTHING) {
writelog ("PASSWORD: failed, victim %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "No such player.");
} else if (*password != '\0' && !ok_password (password)) {
/* Wiz can set null passwords, but not bad passwords */
writelog ("PASSWORD: failed, password %s(%d) who '%s'\n",
db[player].name, player, name);
notify (player, "Bad password");
#ifdef GOD_PRIV
} else if (God (victim) && !God (player)) {
#ifndef TINKER
writelog ("PASSWORD: failed, wizard %s(%d) who '%s'\n",
#else /* TINKER */
writelog ("PASSWORD: failed, tinker %s(%d) who '%s'\n",
#endif /* TINKER */
db[player].name, player, name);
notify (player, "You cannot change that player's password.");
#endif /* GOD_PRIV */
} else {
writelog ("PASSWORD: success %s(%d) who '%s'\n",
db[player].name, player, name);
/* it's ok, do it */
if (db[victim].password)
free ((void *) db[victim].password);
db[victim].password = alloc_string (password);
notify (player, "Password changed.");
sprintf (buf, "Your password has been changed by %s.", db[player].name);
notify (victim, buf);
}
}
void do_boot (dbref player, const char *name)
{
dbref victim;
char buf[BUFFER_LEN];
if (!Wizard (player)) {
writelog ("BOOT: failed, priv player %s(%d), who '%s'\n",
db[player].name, player, name);
#ifndef TINKER
notify (player, "Only a Wizard can boot another player off!");
#else /* TINKER */
notify (player, "Only a Tinker can boot another player off!");
#endif /* TINKER */
return;
}
init_match (player, name, TYPE_PLAYER);
match_neighbor ();
match_absolute ();
match_player ();
if ((victim = noisy_match_result ()) == NOTHING)
return;
#ifdef GOD_PRIV
if (God (victim)) {
#ifndef TINKER
writelog ("BOOT: failed, wizard, player %s(%d), who '%s'\n",
#else /* TINKER */
writelog ("BOOT: failed, tinker, player %s(%d), who '%s'\n",
#endif /* TINKER */
db[player].name, player, name);
notify (player, "You can't boot that player!");
return;
}
#endif /* GOD_PRIV */
if (Typeof (victim) != TYPE_PLAYER) {
writelog ("BOOT: failed, victim, player %s(%d), who '%s'\n",
db[player].name, player, name);
notify (player, "You can only boot off other players!");
} else {
writelog ("BOOT: success, player %s(%d), who '%s'\n",
db[player].name, player, name);
/* we are ok */
/* do it */
/* notify people */
sprintf (buf, "You have been booted off the game by %s.",
db[player].name);
notify (victim, buf);
sprintf (buf, "You booted %s off!", db[victim].name);
notify (player, buf);
boot_off (victim);
/* reset name */
}
}
# define MINUTES (60)
# define HOURS (3600)
# define DAYS (24 * HOURS)
# define WEEKS (7 * DAYS)
# define MONTHS (30 * DAYS)
# define YEARS (365 * DAYS)
long atosec (const char *str)
{
long num;
const char *s;
if (!str || !*str) return (0L);
num = atol (str);
for (s=str; *s && isspace ((int)*s) || isdigit ((int)*s); s++) ;
switch (*s) {
case '\0':
case 's':
case 'S': return (num); break;
case 'm':
case 'M':
if (s[1] == 'i' || s[1] == 'I') {
return (num * MINUTES); break;
} else {
return (num * MONTHS); break;
}
case 'h':
case 'H': return (num * HOURS); break;
case 'd':
case 'D': return (num * DAYS); break;
case 'w':
case 'W': return (num * WEEKS); break;
case 'y':
case 'Y': return (num * YEARS); break;
default: return (num);
}
}
void do_date(dbref player, const char *start, const char *thstr)
{
dbref rooms=0, arooms=0;
dbref exits=0, aexits=0;
dbref things=0, athings=0;
dbref players=0, aplayers=0;
dbref total=0, atotal=0;
dbref i;
dbref owner;
long now, start_tm, thresh;
char buf[BUFFER_LEN];
now = time (0);
if(!Wizard(player)) {
sprintf(buf, "%24.24s", ctime (&now));
notify(player, buf);
return;
}
start_tm = (start && *start) ? now - atosec (start) : now - MONTHS;
thresh = (thstr && *thstr) ? atoi (thstr) : 0;
for (i=0; i<db_top; i++) {
if (db[i].lastused >= start_tm && db[i].usecnt > thresh) {
switch (Typeof(i)) {
case TYPE_ROOM: rooms++; arooms++; break;
case TYPE_THING: things++; athings++; break;
case TYPE_EXIT: exits++; aexits++; break;
case TYPE_PLAYER: players++; aplayers++; break;
}
total++; atotal++;
} else {
switch (Typeof(i)) {
case TYPE_ROOM: rooms++; break;
case TYPE_THING: things++; break;
case TYPE_EXIT: exits++; break;
case TYPE_PLAYER: players++; break;
}
total++;
}
}
if (thresh == 0) {
sprintf (buf, "Objects used since %20.20s:", ctime (&start_tm)+4);
} else {
sprintf (buf, "Objects used more than %ld time%s since %20.20s:",
thresh, (thresh == 1) ? "" : "s", ctime (&start_tm)+4);
}
notify (player, buf);
sprintf (buf, "Totals: %8d of %8d", atotal, total);
notify (player, buf);
sprintf (buf, "Rooms: %8d of %8d", arooms, rooms);
notify (player, buf);
sprintf (buf, "Exits: %8d of %8d", aexits, exits);
notify (player, buf);
sprintf (buf, "Things: %8d of %8d", athings, things);
notify (player, buf);
sprintf (buf, "Players: %8d of %8d", aplayers, players);
notify (player, buf);
writelog ("DATE %s(%d) %s\n", db[player].name, player, start);
}
void do_top(dbref player, const char *numstr, const char *typestr)
{
dbref *top = NULL;
long num=10, type=NOTHING;
dbref i, j, k;
char buf[BUFFER_LEN];
if(!Wizard(player)) {
notify(player, "@Top is a restricted command.");
return;
}
if (numstr && *numstr) num = atol (numstr);
if (num < 1 || num > db_top) {
sprintf (buf, "You must specify an integer from %d to %d for @top",
1, db_top);
notify (player, buf);
return;
}
if (typestr && *typestr) {
switch (*typestr) {
case 'p':
case 'P': type = TYPE_PLAYER; break;
case 'e':
case 'E': type = TYPE_EXIT; break;
case 'r':
case 'R': type = TYPE_ROOM; break;
case 't':
case 'T': type = TYPE_THING; break;
}
}
top = (dbref *) malloc (num * sizeof (dbref));
for (j=0; j<num; j++) top[j] = NOTHING;
/* For each item in the database */
for (i=0; i<db_top; i++) {
if (db[i].usecnt == 0) continue;
if (type != NOTHING && Typeof(i) != type) continue;
/* Loop through the top table, sorted by usecnt */
for (j = num; j > 0; j--) {
if (top[j-1] == NOTHING) continue;
if (db[i].usecnt <= db[top[j-1]].usecnt) break;
}
/* Roll down the less used items, and insert i */
if (j < num) {
for (k = num-1; k > j; k--) top[k] = top[k-1];
top[j] = i;
}
}
/* Now print the items */
switch (type) {
case NOTHING: sprintf (buf, "The top %ld items:", num);
break;
case TYPE_PLAYER: sprintf (buf, "The top %ld most active players:", num);
break;
case TYPE_ROOM: sprintf (buf, "The top %ld most active rooms:", num);
break;
case TYPE_EXIT: sprintf (buf, "The top %ld most used exits:", num);
break;
case TYPE_THING: sprintf (buf, "The top %ld most used things:", num);
break;
}
notify (player, buf);
for (j=0; j<num && top[j] != NOTHING; j++) {
sprintf (buf, "%10ld %s", db[top[j]].usecnt,
unparse_object (player, top[j]));
notify (player, buf);
}
writelog ("TOP %s(%d) %s %s\n", db[player].name, player,
numstr ? numstr : "", typestr ? typestr : "");
}