mud/
mud/2.4.5/dgd/include/
mud/2.4.5/dgd/std/
mud/2.4.5/dgd/sys/
mud/2.4.5/doc/
mud/2.4.5/doc/examples/
mud/2.4.5/log/
mud/2.4.5/obj/Go/
mud/2.4.5/players/
mud/2.4.5/players/lars/
mud/2.4.5/room/death/
mud/2.4.5/room/maze1/
mud/2.4.5/room/post_dir/
mud/2.4.5/room/sub/
# include <config.h>
# undef status
# include <status.h>
# include "/dgd/lib/privilege.h"

object *usr;		/* user array just before a swapout */

/*
 * NAME:	load()
 * DESCRIPTION:	load a castle
 */
private void load(string castle)
{
    rlimits (MAXDEPTH; MAXTICKS) {
	call_other(castle, "???");
	return;
    }
}

/*
 * NAME:	initialize()
 * DESCRIPTION:	called once at game startup
 */
static void initialize()
{
    string *castles, castle, err;
    object *precomp;
    int i, sz, t;

    precomp = status()[ST_PRECOMPILED];
    for (i = 0, sz = sizeof(precomp); i < sz; i++) {
	send_message("Precompiled: " + object_name(precomp[i]) + "\n");
    }
    send_message("\nLoading init file room/init_file\n");
    castles = explode(read_file("/room/init_file"), "\n");
    for (i = 0, sz = sizeof(castles); i < sz; i++) {
	castle = castles[i];
	if (strlen(castle) != 0 && castle[0] != '#') {
	    send_message("Preloading: " + castle);
	    t = time();
	    if (castle[strlen(castle) - 2 ..] == ".c") {
		castle = castle[0 .. strlen(castle) - 3];
	    }
	    err = catch(load(castle));
	    if (err == 0) {
		send_message(" " + (time() - t) + ".0\n");
	    } else {
		send_message(err + "\n");
	    }
	}
    }
    send_message("Setting up ipc.\n");
}

/*
 * NAME:	set_users()
 * DESCRIPTION:	keep a copy of the users array
 */
void set_users()
{
    if (PRIVILEGED()) {
	usr = users();
    }
}

/*
 * NAME:	restored()
 * DESCRIPTION:	re-initialize the system after a restore
 */
static void restored()
{
    object *precomp;
    int i, sz;

    precomp = status()[ST_PRECOMPILED];
    for (i = 0, sz = sizeof(precomp); i < sz; i++) {
	send_message("Precompiled: " + object_name(precomp[i]) + "\n");
    }
    if (usr != 0) {
	for (i = 0, sz = sizeof(usr); i < sz; i++) {
	    catch(usr[i]->force_close());
	}
    }
    usr = 0;
    send_message("\nState restored.\nSetting up ipc.\n");
}

/*
 * NAME:	path_read()
 * DESCRIPTION:	handle an editor read path
 */
string path_read(string path)
{
    if (path != "" && path[0] != '/') {
	path = "/" + this_user()->query_player()->query_path() + "/" + path;
    }
    return this_user()->query_player()->valid_read(path);
}

/*
 * NAME:	path_write()
 * DESCRIPTION:	handle an editor write path
 */
string path_write(string path)
{
    if (path != "" && path[0] != '/') {
	path = "/" + this_user()->query_player()->query_path() + "/" + path;
    }
    return this_user()->query_player()->valid_write(path);
}

/*
 * NAME:	path_object()
 * DESCRIPTION:	translate an object path
 */
string path_object(string path)
{
    int i;

    if (sscanf(path, "../%*s") != 0 || sscanf(path, "%*s/../%*s") != 0) {
	error("Illegal path");
    }
    if ((i=strlen(path)) >= 2 && path[i - 2 ..] == ".c") {
	return path[0 .. i - 3];
    }
    return path;
}

/*
 * NAME:	call_object()
 * DESCRIPTION:	get the object to call with call_other
 */
static object call_object(string file)
{
    object obj;

    file = path_object(file);
    obj = find_object(file);
    if (obj == 0) {
	obj = compile_object(file);
    }
    return obj;
}

/*
 * NAME:	inherit_program()
 * DESCRIPTION:	get an object to inherit
 */
static object inherit_program(string file, string path)
{
    return call_object(path);
}

/*
 * NAME:	path_include()
 * DESCRIPTION:	translate an include path
 */
string path_include(string file, string path)
{
    if (path[0] != '/') {
	return file + "/../" + path;
    }
    return path;
}

/*
 * NAME:	remove_program()
 * DESCRIPTION:	the last reference to a program is removed
 */
static void remove_program(string name)
{
}

/*
 * NAME:	recompile()
 * DESCRIPTION:	(not) used to recompile objects
 */
static void recompile(object obj)
{
}

/*
 * NAME:	telnet_connect()
 * DESCRIPTION:	return a player object
 */
static object telnet_connect()
{
    object user, player;

    GLOBAL->set_this_player(0);
    user = find_object(USER);
    if (user == 0) {
	user = compile_object(USER);
    }
    user = clone_object(user);
    player = MASTER->connect();
    user->set_player(player);
    player->_F_user(user);

    return user;
}

/*
 * NAME:	binary_connect()
 * DESCRIPTION:	return another player object (just to test)
 */
static object binary_connect()
{
    object user, player;

    GLOBAL->set_this_player(0);
    user = find_object(USER);
    if (user == 0) {
	user = compile_object(USER);
    }
    user = clone_object(user);
    player = MASTER->connect();
    user->set_player(player);
    player->_F_user(user);

    return user;
}

/*
 * NAME:	runtime_error()
 * DESCRIPTION:	log a runtime error
 */
static void runtime_error(string error, int caught)
{
    mixed **trace;
    string progname, objname, function, str;
    int i, sz, line, len;
    object player;

    if (caught) {
	return;
    }
    send_message(error + "\n");
    trace = call_trace();
    if ((sz=sizeof(trace) - 1) != 0) {
	for (i = 0; i < sz; i++) {
	    progname = trace[i][1];
	    function = trace[i][2];

	    if (progname == AUTO && strlen(function) > 3) {
		switch (function[0 .. 2]) {
		case "bad":
		    progname = trace[i - 1][1];
		    function = trace[i - 1][2];
		case "_F_":
		case "_Q_":
		    continue;

		default:
		    break;
		}
	    }

	    objname  = trace[i][0];
	    line     = trace[i][3];

	    if (line == 0) {
		str = "    ";
	    } else {
		str = "    " + line;
		str = str[strlen(str) - 4 ..];
	    }
	    str += " " + function + " ";
	    len = strlen(function);
	    if (len < 17) {
		str += "                 "[len ..];
	    }
	    str += progname;
	    if (progname != objname) {
		len = strlen(progname);
		if (len < strlen(objname) && progname == objname[.. len - 1]) {
		    str += " (" + objname[len ..] + ")";
		} else {
		    str += " (" + objname + ")";
		}
	    }
	    send_message(str + "\n");
	}

	player = GLOBAL->query_this_player();
	if (player != 0 && function_object("valid_player", player) == PLAYER &&
	    player->_Q_user() != 0) {
	    if (player->query_level() < 21) {
		player->catch_tell("Your significant mind notices the fabric " +
				   "of space.\n");
	    } else {
		player->catch_tell(error + "\nObject: " + objname +
				   ", program: " + progname + ", line " +
				   line + "\n");
	    }
	}
    }
}

/*
 * NAME:	compile_error()
 * DESCRIPTION:	deal with a compilation error
 */
void compile_error(string file, int line, string err)
{
    string wizard;

    err = file + ", " + line + ": " + err + "\n";
    send_message(err);
    if (sscanf(file, "/players/%s/", wizard) != 0) {
	write_file("/log/" + wizard, err);
    } else {
	write_file("/log/log", err);
    }
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	deal with a kill signal
 */
static void interrupt()
{
    send_message("Shutdown by interrupt.\n");
    shutdown();
}

int shutting_down;

/*
 * NAME:	start_shut_down()
 * DESCRIPTION:	start shutting down the game
 */
void start_shut_down()
{
    if (PRIVILEGED() && shutting_down == 0) {
	shutting_down = call_out("do_shutdown", 1);
    }
}

/*
 * NAME:	do_shutdown()
 * DESCRIPTION:	actually shut down the game
 */
static void do_shutdown()
{
    object *u, player;
    int i;

    u = users();
    for (i = 0; i < sizeof(u); i++) {
	u[i]->catch_tell("Deegeedee shouts: Mud shutting down immediately.\n");
    }

    for (i = 0; i < sizeof(u); i++) {
	player = u[i]->query_player();
	GLOBAL->set_this_player(player);
	catch(player->quit());
    }
    send_message("Shutdown.\n");
    shutdown();
}

/*
 * NAME:	compile_rlimits()
 * DESCRIPTION:	determine at compile time if usage of rlimits is unrestricted
 */
static int compile_rlimits(string objname)
{
    return objname == USER;
}

/*
 * NAME:	runtime_rlimits()
 * DESCRIPTION:	restrict rlimits at runtime
 */
static int runtime_rlimits(object obj, int depth, int ticks)
{
    return 0;	/* No. */
}