/
2.4.5/dgd/include/
2.4.5/dgd/std/
2.4.5/dgd/sys/
2.4.5/doc/LPC/
*** obj/player.c.orig	Sun May 29 20:23:15 1994
--- obj/player.c	Sat May  7 13:57:50 1994
***************
*** 1,3 ****
--- 1,5 ----
+ # include <config.h>
+ 
  inherit "/dgd/lib/player";
  
  #include "log.h"
***************
*** 111,116 ****
--- 113,123 ----
      }
      if (name != "logon") {
  	illegal_patch("logon2 " + name);
+ 	destruct(this_object());
+ 	return;
+     }
+     if (str == "HNAME") {
+ 	HNAME->logon();
  	destruct(this_object());
  	return;
      }
*** obj/master.c.orig	Sun May 29 20:37:00 1994
--- obj/master.c	Sat May  7 13:57:49 1994
***************
*** 338,340 ****
--- 338,345 ----
      }
      return fname;
  }
+ 
+ int valid_exec(string prog)
+ {
+     return prog == "dgd/sys/hname";
+ }
*** dgd.old/include/config.h	Tue Dec 28 21:28:48 1993
--- dgd/include/config.h	Sat May  7 13:55:47 1994
***************
*** 10,18 ****
  # define AUTO		"/dgd/lib/auto"
  # define DRIVER		"/dgd/sys/driver"
  # define GLOBAL		"/dgd/sys/global"
! # define MASTER		"/obj/master"
  # define USER		"/dgd/std/user"
  # define PLAYER		"/dgd/lib/player"
  # define EDITOR		"/dgd/std/editor"
  # define CINDENT	"/dgd/std/cindent"
  
--- 10,19 ----
  # define AUTO		"/dgd/lib/auto"
  # define DRIVER		"/dgd/sys/driver"
  # define GLOBAL		"/dgd/sys/global"
! # define HNAME		"/dgd/sys/hname"
  # define USER		"/dgd/std/user"
  # define PLAYER		"/dgd/lib/player"
+ # define MASTER		"/obj/master"
  # define EDITOR		"/dgd/std/editor"
  # define CINDENT	"/dgd/std/cindent"
  
*** dgd.old/lib/auto.c	Tue Dec 14 16:32:54 1993
--- dgd/lib/auto.c	Sun May  8 15:23:06 1994
***************
*** 3,9 ****
--- 3,13 ----
   */
  
  # include <config.h>
+ # undef status
+ # include <status.h>
+ # include <limits.h>
  
+ # include "reset.h"
  # include "privilege.h"
  # include "creator.h"
  # include "global.h"
***************
*** 17,22 ****
--- 21,27 ----
  # include "call_out.h"
  # include "simfun.h"
  
+ # include "reset.c"
  # include "privilege.c"
  # include "creator.c"
  # include "global.c"
***************
*** 55,77 ****
  {
      lock(initialize());
  
!     if (function_object("reset", this_object()) != 0) {
! 	object save_player;
! 
! 	::call_out("_F_reset", RESET_TIME * 60);
! 	save_player = this_player();
! 	this_object()->reset(0);
! 	set_this_player(save_player);
!     }
! }
! 
! /*
!  * NAME:	_F_reset()
!  * DESCRIPTION:	reset the object
!  */
! nomask void _F_reset()
! {
!     ::call_out("_F_reset", RESET_TIME * 60);
!     set_this_player(0);
!     this_object()->reset(1);
  }
--- 60,64 ----
  {
      lock(initialize());
  
!     INIT_RESET();
  }
*** dgd.old/lib/call_out.c	Mon Dec 13 23:12:32 1993
--- dgd/lib/call_out.c	Sun May 29 20:08:18 1994
***************
*** 1,4 ****
! private mixed heart_beat;	/* heart_beat key */
  
  /*
   * NAME:	call_out()
--- 1,4 ----
! private mixed *callout;		/* call_out key */
  
  /*
   * NAME:	call_out()
***************
*** 8,30 ****
  {
      ARGCHECK(func, call_out, 1);
  
!     if (func == "_F_heart_beat" || func == "_F_reset") {
! 	return;
      }
-     add_call_out(delay);
-     ::call_out(func, delay, args...);
  }
  
  /*
   * NAME:	remove_call_out()
   * DESCRIPTION:	remove a call_out
   */
  static int remove_call_out(string func)
  {
!     if (func == "_F_heart_beat" || func == "_F_reset") {
! 	return -1;
      }
!     return ::remove_call_out(func);
  }
  
  /*
--- 8,69 ----
  {
      ARGCHECK(func, call_out, 1);
  
!     if (func != "_F_reset") {
! 	lock(add_call_out(),
! 	     ::call_out("_F_call_out", delay, callout, func, this_player(),
! 			args...));
      }
  }
  
  /*
+  * NAME:	_F_call_out()
+  * DESCRIPTION:	handle a call_out
+  */
+ nomask varargs void
+ _F_call_out(mixed *key, string func, object player, mixed args...)
+ {
+     if (key == callout) {
+ 	del_call_out();
+ 	set_this_player(player);
+ 	call_other(this_object(), func, args...);
+     }
+ }
+ 
+ /*
+  * NAME:	find_call_out()
+  * DESCRIPTION:	find a call_out
+  */
+ static int find_call_out(string func)
+ {
+     mixed **clist, *c;
+     int i, sz;
+ 
+     clist = status(this_object())[O_CALLOUTS];
+     for (i = 0, sz = sizeof(clist); i < sz; i++) {
+ 	if (sizeof(c=clist[i]) > 3 && c[4] == func) {
+ 	    return c[2];
+ 	}
+     }
+     return -1;
+ }
+ 
+ /*
   * NAME:	remove_call_out()
   * DESCRIPTION:	remove a call_out
   */
  static int remove_call_out(string func)
  {
!     mixed **clist, *c;
!     int i, sz;
! 
!     clist = status(this_object())[O_CALLOUTS];
!     for (i = 0, sz = sizeof(clist); i < sz; i++) {
! 	if (sizeof(c=clist[i]) > 3 && c[4] == func) {
! 	    return lock(del_call_out(),
! 			::remove_call_out(c[0]));
! 	}
      }
!     return -1;
  }
  
  /*
***************
*** 34,53 ****
  static int set_heart_beat(int flag)
  {
      if (flag) {
! 	if (!arrayp(heart_beat)) {
! 	    heart_beat = ({ });
! 	    ::call_out("_F_heart_beat", 1 + (time() & 1), heart_beat);
! 	    add_heart_beat();
  	    return 1;
  	}
      } else {
! 	if (arrayp(heart_beat)) {
! 	    ::remove_call_out("_F_heart_beat");
! 	    del_heart_beat();
! 	    heart_beat = 0;
  	    return 1;
  	}
! 	heart_beat = 0;
      }
      return 0;
  }
--- 73,92 ----
  static int set_heart_beat(int flag)
  {
      if (flag) {
! 	if (callout[0] == 0) {
! 	    lock(add_heart_beat(),
! 		 callout[0] = ::call_out("_F_heart_beat", 1 + (time() & 1),
! 					 callout));
  	    return 1;
  	}
      } else {
! 	if (callout[0] > 0) {
! 	    lock(del_heart_beat(),
! 		 ::remove_call_out(callout[0]),
! 		 callout[0] = 0);
  	    return 1;
  	}
! 	callout[0] = 0;
      }
      return 0;
  }
***************
*** 56,65 ****
   * NAME:	_F_heart_beat()
   * DESCRIPTION:	handle heart_beat calls
   */
! nomask void _F_heart_beat(mixed key)
  {
!     if (key == heart_beat && arrayp(key)) {
! 	heart_beat = 1;
  	del_heart_beat();
  	if (living(this_object())) {
  	    set_this_player(this_object());
--- 95,104 ----
   * NAME:	_F_heart_beat()
   * DESCRIPTION:	handle heart_beat calls
   */
! nomask void _F_heart_beat(mixed *key)
  {
!     if (key == callout) {
! 	key[0] = -1;
  	del_heart_beat();
  	if (living(this_object())) {
  	    set_this_player(this_object());
***************
*** 67,76 ****
  	    set_this_player(0);
  	}
  	this_object()->heart_beat();
! 	if (heart_beat == 1) {
! 	    heart_beat = key;
! 	    ::call_out("_F_heart_beat", 1 + (time() & 1), key);
! 	    add_heart_beat();
  	}
      }
  }
--- 106,114 ----
  	    set_this_player(0);
  	}
  	this_object()->heart_beat();
! 	if (key[0] < 0) {
! 	    lock(add_heart_beat(),
! 		 key[0] = ::call_out("_F_heart_beat", 1 + (time() & 1), key));
  	}
      }
  }
*** dgd.old/lib/call_out.h	Mon Dec 13 01:09:23 1993
--- dgd/lib/call_out.h	Fri Mar 18 20:37:33 1994
***************
*** 2,5 ****
  static int remove_call_out(string func);
  static int set_heart_beat(int flag);
  
! # define INIT_CALL_OUT()
--- 2,5 ----
  static int remove_call_out(string func);
  static int set_heart_beat(int flag);
  
! # define INIT_CALL_OUT()	callout = allocate(1)
*** dgd.old/lib/file.c	Tue Dec 28 21:27:18 1993
--- dgd/lib/file.c	Mon Apr 25 19:48:29 1994
***************
*** 489,495 ****
   * NAME:	editor()
   * DESCRIPTION:	handle an editor command
   */
! static void editor(string cmd)
  {
      string fname;
  
--- 489,495 ----
   * NAME:	editor()
   * DESCRIPTION:	handle an editor command
   */
! static string editor(string cmd)
  {
      string fname;
  
***************
*** 498,506 ****
  	error("Illegal call to editor()");
      }
      if (cmd == 0) {
! 	::editor();
      } else {
! 	::editor(cmd);
      }
  }
  
--- 498,506 ----
  	error("Illegal call to editor()");
      }
      if (cmd == 0) {
! 	return ::editor();
      } else {
! 	return ::editor(cmd);
      }
  }
  
*** dgd.old/lib/global.c	Thu Dec 23 21:29:05 1993
--- dgd/lib/global.c	Fri Mar 18 20:57:30 1994
***************
*** 1,15 ****
- private object global;
- 
  /*
   * NAME:	init_global()
!  * DESCRIPTION:	initialize global object handling
   */
  private void init_global()
  {
-     call_other(GLOBAL, "???");
-     global = find_object(GLOBAL);
      lock(privileged = 1,
! 	 global->add_object(),
  	 privileged = 0);
  }
  
--- 1,11 ----
  /*
   * NAME:	init_global()
!  * DESCRIPTION:	initialize the global object interface
   */
  private void init_global()
  {
      lock(privileged = 1,
! 	 GLOBAL->add_object(),
  	 privileged = 0);
  }
  
***************
*** 19,25 ****
   */
  static void set_this_player(object player)
  {
!     global->set_this_player(player);
  }
  
  /*
--- 15,21 ----
   */
  static void set_this_player(object player)
  {
!     GLOBAL->set_this_player(player);
  }
  
  /*
***************
*** 34,40 ****
  	}
  	return 0;
      }
!     return global->query_this_player();
  }
  
  /*
--- 30,36 ----
  	}
  	return 0;
      }
!     return GLOBAL->query_this_player();
  }
  
  /*
***************
*** 46,52 ****
      ARGCHECK(name, set_living_name, 1);
  
      lock(privileged = 1,
! 	 global->set_living_name(name),
  	 privileged = 0);
  }
  
--- 42,48 ----
      ARGCHECK(name, set_living_name, 1);
  
      lock(privileged = 1,
! 	 GLOBAL->set_living_name(name),
  	 privileged = 0);
  }
  
***************
*** 58,64 ****
  {
      ARGCHECK(name, find_player, 1);
  
!     return global->query_find_player(name);
  }
  
  /*
--- 54,60 ----
  {
      ARGCHECK(name, find_player, 1);
  
!     return GLOBAL->query_find_player(name);
  }
  
  /*
***************
*** 69,75 ****
  {
      ARGCHECK(name, find_living, 1);
  
!     return global->query_find_living(name);
  }
  
  /*
--- 65,71 ----
  {
      ARGCHECK(name, find_living, 1);
  
!     return GLOBAL->query_find_living(name);
  }
  
  /*
***************
*** 79,85 ****
  private void set_verb(string verb)
  {
      lock(privileged = 1,
! 	 global->set_verb(verb),
  	 privileged = 0);
  }
  
--- 75,81 ----
  private void set_verb(string verb)
  {
      lock(privileged = 1,
! 	 GLOBAL->set_verb(verb),
  	 privileged = 0);
  }
  
***************
*** 89,95 ****
   */
  static string query_verb()
  {
!     return global->query_verb();
  }
  
  /*
--- 85,91 ----
   */
  static string query_verb()
  {
!     return GLOBAL->query_verb();
  }
  
  /*
***************
*** 98,104 ****
   */
  private void show_wiz_list()
  {
!     global->show_wiz_list();
  }
  
  /*
--- 94,100 ----
   */
  private void show_wiz_list()
  {
!     GLOBAL->show_wiz_list();
  }
  
  /*
***************
*** 108,114 ****
  private void del_object()
  {
      lock(privileged = 1,
! 	 global->del_object(),
  	 privileged = 0);
  }
  
--- 104,110 ----
  private void del_object()
  {
      lock(privileged = 1,
! 	 GLOBAL->del_object(),
  	 privileged = 0);
  }
  
***************
*** 119,125 ****
  private void add_heart_beat()
  {
      lock(privileged = 1,
! 	 global->add_heart_beat(),
  	 privileged = 0);
  }
  
--- 115,121 ----
  private void add_heart_beat()
  {
      lock(privileged = 1,
! 	 GLOBAL->add_heart_beat(),
  	 privileged = 0);
  }
  
***************
*** 130,136 ****
  private void del_heart_beat()
  {
      lock(privileged = 1,
! 	 global->del_heart_beat(),
  	 privileged = 0);
  }
  
--- 126,132 ----
  private void del_heart_beat()
  {
      lock(privileged = 1,
! 	 GLOBAL->del_heart_beat(),
  	 privileged = 0);
  }
  
***************
*** 138,159 ****
   * NAME:	add_call_out()
   * DESCRIPTION:	add a call_out
   */
! private void add_call_out(int delay)
  {
!     if (this_object() != global) {
  	lock(privileged = 1,
! 	     global->add_call_out(delay),
  	     privileged = 0);
      }
  }
  
  /*
   * NAME:	lambda()
   * DESCRIPTION:	compile a function definition to a closure
   */
  private mixed relay(string func, mixed arg, closure expr)
  {
!     return call_other(global, func, arg, expr);
  }
  
  /*
--- 134,168 ----
   * NAME:	add_call_out()
   * DESCRIPTION:	add a call_out
   */
! private void add_call_out()
  {
!     if (object_name(this_object()) != GLOBAL) {
  	lock(privileged = 1,
! 	     GLOBAL->add_call_out(),
  	     privileged = 0);
      }
  }
  
  /*
+  * NAME:	del_call_out()
+  * DESCRIPTION:	delete a call_out
+  */
+ private void del_call_out()
+ {
+     if (object_name(this_object()) != GLOBAL) {
+ 	lock(privileged = 1,
+ 	     GLOBAL->del_call_out(),
+ 	     privileged = 0);
+     }
+ }
+ 
+ /*
   * NAME:	lambda()
   * DESCRIPTION:	compile a function definition to a closure
   */
  private mixed relay(string func, mixed arg, closure expr)
  {
!     return call_other(GLOBAL, func, arg, expr);
  }
  
  /*
***************
*** 169,175 ****
  	ARGCHECK(arrayp(def) && sizeof(def) != 0, lambda, 2);
      }
  
!     return global->compile(func, def);
  }
  
  /*
--- 178,184 ----
  	ARGCHECK(arrayp(def) && sizeof(def) != 0, lambda, 2);
      }
  
!     return GLOBAL->compile(func, def);
  }
  
  /*
***************
*** 181,185 ****
      if (sizeof(args) == 0) {
  	error("Too few arguments to function apply");
      }
!     return (closurep(args[0])) ? global->eval(args, ([ ]))[1] : args[0];
  }
--- 190,194 ----
      if (sizeof(args) == 0) {
  	error("Too few arguments to function apply");
      }
!     return (closurep(args[0])) ? GLOBAL->eval(args, ([ ]))[1] : args[0];
  }
*** dgd.old/lib/global.h	Thu Dec 23 21:29:13 1993
--- dgd/lib/global.h	Fri Mar 18 20:54:55 1994
***************
*** 4,10 ****
  private void del_object();
  private void add_heart_beat();
  private void del_heart_beat();
! private void add_call_out(int delay);
  private mixed relay(string func, mixed arg, closure expr);
  
  static void set_this_player(object player);
--- 4,11 ----
  private void del_object();
  private void add_heart_beat();
  private void del_heart_beat();
! private void add_call_out();
! private void del_call_out();
  private mixed relay(string func, mixed arg, closure expr);
  
  static void set_this_player(object player);
*** dgd.old/lib/interactive.c	Tue Dec 28 21:27:22 1993
--- dgd/lib/interactive.c	Sat May  7 13:48:55 1994
***************
*** 38,44 ****
      ARGCHECK(obj, query_ip_name, 1);
  
      obj = interactive(obj);
!     return (obj == 0) ? 0 : ::query_ip_number(obj);
  }
  
  /*
--- 38,44 ----
      ARGCHECK(obj, query_ip_name, 1);
  
      obj = interactive(obj);
!     return (obj == 0) ? 0 : HNAME->request_ip_name(::query_ip_number(obj));
  }
  
  /*
***************
*** 91,97 ****
  
      player = this_player();
      if (player != 0) {
! 	if (intp(str)) {
  	    str = str + "";
  	} else if (objectp(str)) {
  	    str = object_name(str);
--- 91,97 ----
  
      player = this_player();
      if (player != 0) {
! 	if (intp(str) || floatp(str)) {
  	    str = str + "";
  	} else if (objectp(str)) {
  	    str = object_name(str);
***************
*** 131,137 ****
      }
  
      if (stringp(room)) {
! 	call_other(room, "???");
  	room = find_object(room);
      }
      ARGCHECK(objectp(room), tell_room, 1);
--- 131,137 ----
      }
  
      if (stringp(room)) {
! 	call_other(room = DRIVER->path_object(room), "???");
  	room = find_object(room);
      }
      ARGCHECK(objectp(room), tell_room, 1);
***************
*** 183,189 ****
      list = query_inventory(origin);
      obj = environment(origin);
      if (obj != 0) {
! 	list = query_inventory(obj) + list;
      }
  
      if (avoid == 0 || avoid == origin) {
--- 183,189 ----
      list = query_inventory(origin);
      obj = environment(origin);
      if (obj != 0) {
! 	list = ({ obj }) + query_inventory(obj) + list;
      }
  
      if (avoid == 0 || avoid == origin) {
***************
*** 225,231 ****
      usr = ::users();
      for (i = 0, sz = sizeof(usr); i < sz; i++) {
  	obj = usr[i];
! 	if (obj != user) {
  	    obj->catch_tell(str);
  	}
      }
--- 225,231 ----
      usr = ::users();
      for (i = 0, sz = sizeof(usr); i < sz; i++) {
  	obj = usr[i];
! 	if (obj != user && object_name(obj->query_player()) != HNAME) {
  	    obj->catch_tell(str);
  	}
      }
***************
*** 358,362 ****
      for (i = 0, sz = sizeof(usr); i < sz; i++) {
  	usr[i] = usr[i]->query_player();
      }
!     return usr;
  }
--- 358,362 ----
      for (i = 0, sz = sizeof(usr); i < sz; i++) {
  	usr[i] = usr[i]->query_player();
      }
!     return usr - ({ find_object(HNAME) });
  }
*** dgd.old/lib/inventory.c	Tue Dec 14 15:15:14 1993
--- dgd/lib/inventory.c	Sun May 29 20:08:45 1994
***************
*** 170,181 ****
      int i, sz;
  
      if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), move_object, 1);
      if (stringp(dest)) {
! 	call_other(dest, "???");
  	dest = find_object(dest);
      }
      ARGCHECK(objectp(dest), move_object, 2);
--- 170,181 ----
      int i, sz;
  
      if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), move_object, 1);
      if (stringp(dest)) {
! 	call_other(dest = DRIVER->path_object(dest), "???");
  	dest = find_object(dest);
      }
      ARGCHECK(objectp(dest), move_object, 2);
***************
*** 198,209 ****
  	}
      }
  
      lock(move(obj, env, dest));
  
      if (living(obj)) {
  	set_this_player(obj);
  	dest->init();
!     if (obj == 0 || obj->_Q_env() != dest) {
  	    set_this_player(save_player);
  	    return;
  	}
--- 198,211 ----
  	}
      }
  
+     obj->_F_reset();
+     dest->_F_reset();
      lock(move(obj, env, dest));
  
      if (living(obj)) {
  	set_this_player(obj);
  	dest->init();
! 	if (obj == 0 || obj->_Q_env() != dest) {
  	    set_this_player(save_player);
  	    return;
  	}
***************
*** 221,226 ****
--- 223,229 ----
  	}
  	if (living(obj) && invobj != 0) {
  	    set_this_player(obj);
+ 	    invobj->_F_reset();
  	    invobj->init();
  	    if (obj == 0 || obj->_Q_env() != dest) {
  		set_this_player(save_player);
***************
*** 286,292 ****
      if (obj == 0) {
  	obj == this_object();
      } else if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), first_inventory, 1);
--- 289,295 ----
      if (obj == 0) {
  	obj == this_object();
      } else if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), first_inventory, 1);
*** dgd.old/lib/mapping.c	Thu Dec 23 21:47:24 1993
--- dgd/lib/mapping.c	Mon Mar 14 23:49:33 1994
***************
*** 81,87 ****
      }
      ARGCHECK(stringp(func), filter_mapping, 2);
      if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), filter_mapping, 3);
--- 81,87 ----
      }
      ARGCHECK(stringp(func), filter_mapping, 2);
      if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), filter_mapping, 3);
***************
*** 115,121 ****
      }
      ARGCHECK(stringp(func), map_mapping, 2);
      if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), map_mapping, 3);
--- 115,121 ----
      }
      ARGCHECK(stringp(func), map_mapping, 2);
      if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), map_mapping, 3);
*** dgd.old/lib/simfun.c	Thu Dec 23 01:54:05 1993
--- dgd/lib/simfun.c	Sat May  7 16:07:14 1994
***************
*** 1,3 ****
--- 1,5 ----
+ # include <type.h>
+ 
  /*
   * NAME:	filter_objects()
   * DESCRIPTION:	the same as filter_array()
***************
*** 45,68 ****
  }
  
  /*
!  * NAME:	closurep()
!  * DESCRIPTION:	return 1 if the argument is a closure, 0 otherwise
   */
! static int closurep(mixed value)
  {
!     return (arrayp(value) && sizeof(value) != 0 && value[0] == LAMBDA);
  }
  
  /*
   * NAME:	pointerp()
   * DESCRIPTION:	return 1 if the argument is an array and not a closure
   */
  static int pointerp(mixed value)
  {
!     return (arrayp(value) && (sizeof(value) == 0 || value[0] != LAMBDA));
  }
  
  /*
   * NAME:	add_worth()
   * DESCRIPTION:	dummy function
   */
--- 47,126 ----
  }
  
  /*
!  * NAME:	intp()
!  * DESCRIPTION:	return 1 if the argument is an integer
   */
! static int intp(mixed value)
  {
!     return typeof(value) == T_INT;
  }
  
  /*
+  * NAME:	floatp()
+  * DESCRIPTION:	return 1 if the argument is a float
+  */
+ static int floatp(mixed value)
+ {
+     return typeof(value) == T_FLOAT;
+ }
+ 
+ /*
+  * NAME:	stringp()
+  * DESCRIPTION:	return 1 if the argument is a string
+  */
+ static int stringp(mixed value)
+ {
+     return typeof(value) == T_STRING;
+ }
+ 
+ /*
+  * NAME:	objectp()
+  * DESCRIPTION:	return 1 if the argument is an object
+  */
+ static int objectp(mixed value)
+ {
+     return typeof(value) == T_OBJECT;
+ }
+ 
+ /*
+  * NAME:	arrayp()
+  * DESCRIPTION:	return 1 if the argument is an array
+  */
+ static int arrayp(mixed value)
+ {
+     return typeof(value) == T_ARRAY;
+ }
+ 
+ /*
+  * NAME:	mappingp()
+  * DESCRIPTION:	return 1 if the argument is a mapping
+  */
+ static int mappingp(mixed value)
+ {
+     return typeof(value) == T_MAPPING;
+ }
+ 
+ /*
   * NAME:	pointerp()
   * DESCRIPTION:	return 1 if the argument is an array and not a closure
   */
  static int pointerp(mixed value)
  {
!     return (typeof(value) == T_ARRAY &&
! 	    (sizeof(value) == 0 || value[0] != LAMBDA));
  }
  
  /*
+  * NAME:	closurep()
+  * DESCRIPTION:	return 1 if the argument is a closure, 0 otherwise
+  */
+ static int closurep(mixed value)
+ {
+     return (typeof(value) == T_ARRAY && sizeof(value) != 0 &&
+ 	    value[0] == LAMBDA);
+ }
+ 
+ /*
   * NAME:	add_worth()
   * DESCRIPTION:	dummy function
   */
***************
*** 90,101 ****
      object from, from_env, dest_env;
  
      if (!objectp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), transfer, 1);
      if (!objectp(dest)) {
! 	call_other(dest, "???");
  	dest = find_object(dest);
      }
      ARGCHECK(objectp(dest), transfer, 2);
--- 148,159 ----
      object from, from_env, dest_env;
  
      if (!objectp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), transfer, 1);
      if (!objectp(dest)) {
! 	call_other(dest = DRIVER->path_object(dest), "???");
  	dest = find_object(dest);
      }
      ARGCHECK(objectp(dest), transfer, 2);
***************
*** 192,199 ****
--- 250,262 ----
   */
  nomask void _F_destruct()
  {
+     int i;
+ 
      if (PRIVILEGED()) {
  	set_heart_beat(0);
+ 	for (i = sizeof(status(this_object())[O_CALLOUTS]); i > 0; --i) {
+ 	    del_call_out();
+ 	}
  	del_object();
  	::destruct_object(this_object());
      }
***************
*** 316,334 ****
  }
  
  /*
!  * NAME:	swapout()
!  * DESCRIPTION:	swap out all objects
   */
! static varargs void swapout(int flag)
  {
!     if (flag) {
! 	lock(privileged = 1,
! 	     DRIVER->set_users(),
! 	     ::swapout(1),
! 	     privileged = 0);
!     } else {
! 	::swapout();
!     }
  }
  
  /*
--- 379,393 ----
  }
  
  /*
!  * NAME:	dump_state()
!  * DESCRIPTION:	dump state
   */
! static void dump_state()
  {
!     lock(privileged = 1,
! 	 DRIVER->set_users(),
! 	 ::dump_state(),
! 	 privileged = 0);
  }
  
  /*
***************
*** 348,354 ****
   */
  static string version()
  {
!     return __VERSION__;
  }
  
  /*
--- 407,413 ----
   */
  static string version()
  {
!     return status()[ST_VERSION];
  }
  
  /*
*** dgd.old/lib/simfun.h	Tue Dec 21 01:38:37 1993
--- dgd/lib/simfun.h	Mon Mar 14 23:22:32 1994
***************
*** 2,9 ****
  filter_objects(mixed *arr, string func, object obj, mixed arg);
  static varargs string file_name(object obj);
  static varargs string function_exists(string func, object obj);
! static int closurep(mixed value);
  static int pointerp(mixed value);
  static varargs void add_worth(int worth, object obj);
  static varargs void wizlist(string name);
  static int transfer(mixed obstr, mixed tostr);
--- 2,15 ----
  filter_objects(mixed *arr, string func, object obj, mixed arg);
  static varargs string file_name(object obj);
  static varargs string function_exists(string func, object obj);
! static int intp(mixed value);
! static int floatp(mixed value);
! static int stringp(mixed value);
! static int objectp(mixed value);
! static int arrayp(mixed value);
! static int mappingp(mixed value);
  static int pointerp(mixed value);
+ static int closurep(mixed value);
  static varargs void add_worth(int worth, object obj);
  static varargs void wizlist(string name);
  static int transfer(mixed obstr, mixed tostr);
*** dgd.old/lib/tool.c	Mon Dec 27 18:59:43 1993
--- dgd/lib/tool.c	Fri Mar 25 22:42:37 1994
***************
*** 149,155 ****
      }
      ARGCHECK(stringp(func), filter_array, 2);
      if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), filter_array, 3);
--- 149,155 ----
      }
      ARGCHECK(stringp(func), filter_array, 2);
      if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), filter_array, 3);
***************
*** 179,185 ****
      }
      ARGCHECK(stringp(func), map_array, 2);
      if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), map_array, 3);
--- 179,185 ----
      }
      ARGCHECK(stringp(func), map_array, 2);
      if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), map_array, 3);
***************
*** 228,286 ****
   * NAME:	sort_array()
   * DESCRIPTION:	sort an array
   */
! static varargs mixed *sort_array(mixed *arr, mixed func, mixed obj)
  {
!     mixed elt, val;
!     int n, i, j, size;
  
!     ARGCHECK(arr, sort_array, 1);
      if (closurep(func) && obj == 0) {
! 	return relay("lambda_sort_array", arr, func);
      }
      ARGCHECK(stringp(func), sort_array, 2);
      if (obj == 0) {
  	obj = this_object();
      } else if (stringp(obj)) {
! 	call_other(obj, "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), sort_array, 3);
  
!     arr = arr[..];
!     for (n = 1, size = sizeof(arr); n < size; n <<= 1) ;
! 
!     for (n >>= 1; n > 0; --n) {
! 	elt = arr[n - 1];
! 	for (i = n, j = n << 1; j <= size; i = j, j <<= 1) {
! 	    val = arr[j - 1];
! 	    if (j < size && call_other(obj, func, arr[j], val)) {
! 		val = arr[j++];
! 	    }
! 	    if (call_other(obj, func, elt, val)) {
! 		break;
! 	    }
! 	    arr[i - 1] = val;
! 	}
! 	arr[i - 1] = elt;
      }
  
!     for (n = size - 1; n > 0; --n) {
! 	elt = arr[n];
! 	arr[n] = arr[0];
! 	for (i = 1, j = 2; j <= n; i = j, j <<= 1) {
! 	    val = arr[j - 1];
! 	    if (j < n && call_other(obj, func, arr[j], val)) {
! 		val = arr[j++];
! 	    }
! 	    if (call_other(obj, func, elt, val)) {
! 		break;
! 	    }
! 	    arr[i - 1] = val;
! 	}
! 	arr[i - 1] = elt;
      }
! 
!     return arr;
  }
  
  /*
--- 228,296 ----
   * NAME:	sort_array()
   * DESCRIPTION:	sort an array
   */
! static varargs mixed *sort_array(mixed *source, mixed func, mixed obj)
  {
!     int step, halfstep, size;
!     int i, j, i1, i2, end1, end2;
!     mixed *dest, *temp;
  
!     ARGCHECK(source, sort_array, 1);
      if (closurep(func) && obj == 0) {
! 	return relay("lambda_sort_array", source, func);
      }
      ARGCHECK(stringp(func), sort_array, 2);
      if (obj == 0) {
  	obj = this_object();
      } else if (stringp(obj)) {
! 	call_other(obj = DRIVER->path_object(obj), "???");
  	obj = find_object(obj);
      }
      ARGCHECK(objectp(obj), sort_array, 3);
  
!     size = sizeof(source);
!     if (size < 2) {
!         return source[..];
      }
+     dest = allocate(size);
+     step = 2;
+     halfstep = 1;
  
!     while (halfstep < size) {
!         for (i = j = 0; i < size; i += step) {
!             i1 = i;
!             i2 = i + halfstep;
!             end1 = i2;
!             if (end1 > size) {
!                 end1 = size;
!             }
!             end2 = i + step;
!             if (end2 > size) {
!                 end2 = size;
!             }
!             while (i1 < end1 && i2 < end2) {
!                 if (call_other(obj, func, source[i1], source[i2]) > 0) {
!                     dest[j++] = source[i2++];
!                 } else {
!                     dest[j++] = source[i1++];
!                 }
!             }
!             if (i1 == end1) {
!                 while (i2 < end2) {
!                     dest[j++] = source[i2++];
!                 }
!             } else {
!                 while (i1 < end1) {
!                     dest[j++] = source[i1++];
!                 }
!             }
!         }
!         halfstep = step;
!         step += step;
!         temp = source;
!         source = dest;
!         dest = temp;
      }
!     return source;
  }
  
  /*
*** dgd.old/std/editor.c	Wed Dec 15 20:51:04 1993
--- dgd/std/editor.c	Mon Apr 25 19:09:08 1994
***************
*** 1,24 ****
! object user;
  
  /*
!  * NAME:	edit()
!  * DESCRIPTION:	handle an editor command
   */
  varargs void edit(string cmd)
  {
      if (user == 0 && previous_object() == this_user()->query_player()) {
! 	user = this_user();
! 	editor(cmd);
      } else if (previous_object() == user) {
! 	editor(cmd);
      }
  }
  
  /*
!  * NAME:	receive_message()
!  * DESCRIPTION:	receive a message from the editor
   */
! void receive_message(string str)
  {
!     user->catch_tell(str);
  }
--- 1,41 ----
! object user;		/* user for this editor */
  
  /*
!  * NAME:        edit()
!  * DESCRIPTION: handle an editor command
   */
  varargs void edit(string cmd)
  {
      if (user == 0 && previous_object() == this_user()->query_player()) {
!         user = this_user();
!         cmd = editor(cmd);
      } else if (previous_object() == user) {
!         cmd = editor(cmd);
      }
+     if (cmd != 0) {
+ 	user->catch_tell(cmd);
+     }
  }
  
  /*
!  * NAME:        rescue_file()
!  * DESCRIPTION: attempt to rescue the currently edited file
   */
! void rescue_file()
  {
!     string file, *path;
! 
!     if (previous_object() != user) {
!         return;
!     }
! 
!     if (query_editor(this_object()) == "input") {
! 	editor(".");
!     }
!     if (sscanf(editor("f"), "\"%s\" [Modified] %*s", file) == 2) {
!         set_this_player(user->query_player());
!         path = explode(file, "/");
!         editor("w! " + "/players/" + user->query_player()->query_real_name() +
!                "/.dead_ed_files/" + path[sizeof(path) - 1]);
!     }
  }
*** dgd.old/std/user.c	Tue Jan  4 01:07:01 1994
--- dgd/std/user.c	Sat May  7 13:49:57 1994
***************
*** 44,49 ****
--- 44,50 ----
      timestamp = time();
      echo = 1;
      set_this_player(player);
+     HNAME->request_ip_name(query_ip_number(player));
      player->_F_call("logon");
  }
  
***************
*** 95,104 ****
  }
  
  /*
!  * NAME:	ralign()
!  * DESCRIPTION:	return a number as a string, aligned to the right
   */
! private string ralign(int num)
  {
      string str;
  
--- 96,105 ----
  }
  
  /*
!  * NAME:        ralign()
!  * DESCRIPTION: return a number as a string, aligned to the right
   */
!  string ralign(int num)
  {
      string str;
  
***************
*** 107,128 ****
  }
  
  /*
!  * NAME:	show_status()
!  * DESCRIPTION:	show resource usage information
   */
  private void show_status()
  {
!     int *stat;
  
      stat = status();
      catch_tell(
! 	"Swap device:        " + ralign(stat[ST_SWAPSIZE]) + " sectors,\n" +
! 	"                    " + ralign(stat[ST_SWAPUSED]) + " used.\n" +
! 	"Objects swapped out:" + ralign(stat[ST_SWAPRATE]) + " per minute.\n" +
! 	"Memory allocated:   " + ralign(stat[ST_MEMSIZE]) + " bytes,\n" +
! 	"                    " + ralign(stat[ST_MEMUSED]) + " used.\n" +
! 	"Objects:            " + ralign(stat[ST_NOBJECTS]) + "\n" +
! 	"Call_outs:          " + ralign(stat[ST_NCALLOUTS]) + "\n");
  }
  
  /*
--- 108,131 ----
  }
  
  /*
!  * NAME:        show_status()
!  * DESCRIPTION: show resource usage information
   */
  private void show_status()
  {
!     mixed *stat;
  
      stat = status();
      catch_tell(
! "Swap device:        " + ralign(stat[ST_SWAPSIZE]) + " sectors,\n" +
! "                    " + ralign(stat[ST_SWAPUSED]) + " used.\n" +
! "Objects swapped out:" + ralign(stat[ST_SWAPRATE1]) + " per minute.\n" +
! "Memory allocated:   " + ralign(stat[ST_SMEMSIZE] + stat[ST_DMEMSIZE]) +
! 		     " bytes,\n" +
! "                    " + ralign(stat[ST_SMEMUSED] + stat[ST_DMEMUSED]) +
! 		     " used.\n" +
! "Objects:            " + ralign(stat[ST_NOBJECTS]) + "\n" +
! "Call_outs:          " + ralign(stat[ST_NCOSHORT] + stat[ST_NCOLONG]) + "\n");
  }
  
  /*
*** dgd.old/sys/driver.c	Sat Dec 18 22:38:26 1993
--- dgd/sys/driver.c	Mon May 16 00:32:35 1994
***************
*** 9,15 ****
   */
  static void initialize()
  {
!     string *castles, castle;
      int i, sz, t;
  
      send_message("\nLoading init file room/init_file\n");
--- 9,15 ----
   */
  static void initialize()
  {
!     string *castles, castle, err;
      int i, sz, t;
  
      send_message("\nLoading init file room/init_file\n");
***************
*** 22,34 ****
  	    if (castle[strlen(castle) - 2 ..] == ".c") {
  		castle = castle[0 .. strlen(castle) - 3];
  	    }
! 	    if (catch(call_other(castle, "???")) == 0) {
  		send_message(" " + (time() - t) + ".0\n");
  	    }
  	}
      }
      send_message("Setting up ipc.\n");
!     call_out("swapswap", 900);
  }
  
  /*
--- 22,37 ----
  	    if (castle[strlen(castle) - 2 ..] == ".c") {
  		castle = castle[0 .. strlen(castle) - 3];
  	    }
! 	    err = catch(call_other(castle, "???"));
! 	    if (err == 0) {
  		send_message(" " + (time() - t) + ".0\n");
+ 	    } else {
+ 		send_message(err + "\n");
  	    }
  	}
      }
      send_message("Setting up ipc.\n");
!     call_out("swapswap", 1800);
  }
  
  /*
***************
*** 37,43 ****
   */
  static void swapswap()
  {
!     call_out("swapswap", 900);
      usr = 0;
      swapout();
  }
--- 40,46 ----
   */
  static void swapswap()
  {
!     call_out("swapswap", 1800);
      usr = 0;
      swapout();
  }
***************
*** 74,80 ****
   * NAME:	path_ed_read()
   * DESCRIPTION:	handle an editor read path
   */
! string path_ed_read(object obj, string path)
  {
      if (path != "" && path[0] != '/') {
  	path = "/" + this_user()->query_player()->query_path() + "/" + path;
--- 77,83 ----
   * NAME:	path_ed_read()
   * DESCRIPTION:	handle an editor read path
   */
! string path_ed_read(string path)
  {
      if (path != "" && path[0] != '/') {
  	path = "/" + this_user()->query_player()->query_path() + "/" + path;
***************
*** 86,92 ****
   * NAME:	path_ed_write()
   * DESCRIPTION:	handle an editor write path
   */
! string path_ed_write(object obj, string path)
  {
      if (path != "" && path[0] != '/') {
  	path = "/" + this_user()->query_player()->query_path() + "/" + path;
--- 89,95 ----
   * NAME:	path_ed_write()
   * DESCRIPTION:	handle an editor write path
   */
! string path_ed_write(string path)
  {
      if (path != "" && path[0] != '/') {
  	path = "/" + this_user()->query_player()->query_path() + "/" + path;
***************
*** 98,104 ****
   * NAME:	path_object()
   * DESCRIPTION:	translate an object path
   */
! string path_object(object obj, string path)
  {
      int i;
  
--- 101,107 ----
   * NAME:	path_object()
   * DESCRIPTION:	translate an object path
   */
! string path_object(string path)
  {
      int i;
  
***************
*** 117,123 ****
   */
  string path_inherit(string file, string path)
  {
!     return path_object(0, path);
  }
  
  /*
--- 120,126 ----
   */
  string path_inherit(string file, string path)
  {
!     return path_object(path);
  }
  
  /*
***************
*** 150,159 ****
  }
  
  /*
!  * NAME:	connect()
   * DESCRIPTION:	return a player object
   */
! static object connect()
  {
      object user, player;
  
--- 153,162 ----
  }
  
  /*
!  * NAME:	telnet_connect()
   * DESCRIPTION:	return a player object
   */
! static object telnet_connect()
  {
      object user, player;
  
***************
*** 167,172 ****
--- 170,192 ----
  }
  
  /*
+  * NAME:	binary_connect()
+  * DESCRIPTION:	return another player object (just to test)
+  */
+ static object binary_connect()
+ {
+     object user, player;
+ 
+     GLOBAL->set_this_player(0);
+     user = clone_object(USER);
+     player = MASTER->connect();
+     user->set_player(player);
+     player->_F_user(user);
+ 
+     return user;
+ }
+ 
+ /*
   * NAME:	log_error()
   * DESCRIPTION:	log a runtime error
   */
***************
*** 215,221 ****
  	    if (len < 17) {
  		str += "                 "[len ..];
  	    }
! 	    str += " " + progname;
  	    if (progname != objname) {
  		len = strlen(progname);
  		if (len < strlen(objname) && progname == objname[.. len - 1]) {
--- 235,241 ----
  	    if (len < 17) {
  		str += "                 "[len ..];
  	    }
! 	    str += progname;
  	    if (progname != objname) {
  		len = strlen(progname);
  		if (len < strlen(objname) && progname == objname[.. len - 1]) {
***************
*** 257,262 ****
--- 277,284 ----
      return "/log/log";
  }
  
+ int shutting_down;
+ 
  /*
   * NAME:	start_shut_down()
   * DESCRIPTION:	start shutting down the game
***************
*** 263,271 ****
   */
  void start_shut_down()
  {
!     if (PRIVILEGED()) {
! 	remove_call_out("do_shutdown");
! 	call_out("do_shutdown", 1);
      }
  }
  
--- 285,292 ----
   */
  void start_shut_down()
  {
!     if (PRIVILEGED() && shutting_down == 0) {
! 	shutting_down = call_out("do_shutdown", 1);
      }
  }
  
***************
*** 275,281 ****
   */
  static void do_shutdown()
  {
!     object *u;
      int i;
  
      u = users();
--- 296,302 ----
   */
  static void do_shutdown()
  {
!     object *u, player;
      int i;
  
      u = users();
***************
*** 284,291 ****
      }
  
      for (i = 0; i < sizeof(u); i++) {
! 	GLOBAL->set_this_player(u[i]);
! 	catch(u[i]->quit());
      }
      send_message("Shutdown.\n");
      shutdown();
--- 305,313 ----
      }
  
      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();
*** dgd.old/sys/global.c	Mon Dec 27 19:08:44 1993
--- dgd/sys/global.c	Sat May  7 16:27:34 1994
***************
*** 492,498 ****
  	    MINMAX(0, 1),	/* STATUS */
  	    MINMAX(1, 1),	/* STRINGP */
  	    MINMAX(1, 1),	/* STRLEN */
! 	    MINMAX(0, 1),	/* SWAPOUT */
  	    MINMAX(1, 1),	/* TAIL */
  	    MINMAX(2, 2),	/* TELL_OBJECT */
  	    MINMAX(2, 3),	/* TELL_ROOM */
--- 492,498 ----
  	    MINMAX(0, 1),	/* STATUS */
  	    MINMAX(1, 1),	/* STRINGP */
  	    MINMAX(1, 1),	/* STRLEN */
! 	    MINMAX(0, 0),	/* SWAPOUT */
  	    MINMAX(1, 1),	/* TAIL */
  	    MINMAX(2, 2),	/* TELL_OBJECT */
  	    MINMAX(2, 3),	/* TELL_ROOM */
***************
*** 646,669 ****
   * NAME:	add_call_out()
   * DESCRIPTION:	add a call_out
   */
! void add_call_out(int delay)
  {
      if (PRIVILEGED()) {
! 	string creator;
! 
! 	call_outs[creator = creator(previous_object())]++;
! 	call_out("fix_player", delay, creator, command_giver);
      }
  }
  
  /*
!  * NAME:	fix_player()
!  * DESCRIPTION:	set this_player() in preparation of the next call_out
   */
! static void fix_player(string creator, object player)
  {
!     call_outs[creator]--;
!     command_giver = player;
  }
  
  /*
--- 646,667 ----
   * NAME:	add_call_out()
   * DESCRIPTION:	add a call_out
   */
! void add_call_out()
  {
      if (PRIVILEGED()) {
! 	call_outs[creator(previous_object())]++;
      }
  }
  
  /*
!  * NAME:	del_call_out()
!  * DESCRIPTION:	remove a call_out
   */
! void del_call_out()
  {
!     if (PRIVILEGED()) {
! 	call_outs[creator(previous_object())]--;
!     }
  }
  
  /*
***************
*** 1259,1265 ****
  				break;
      case C_STRLEN:		vars[1] = strlen(args[0]);
  				break;
!     case C_SWAPOUT:		swapout(args...);
  				break;
      case C_TAIL:		vars[1] = tail(args[0]);
  				break;
--- 1257,1263 ----
  				break;
      case C_STRLEN:		vars[1] = strlen(args[0]);
  				break;
!     case C_SWAPOUT:		swapout();
  				break;
      case C_TAIL:		vars[1] = tail(args[0]);
  				break;
***************
*** 1449,1494 ****
   * NAME:	sort_array()
   * DESCRIPTION:	sort an array
   */
! varargs mixed *lambda_sort_array(mixed *arr, closure func)
  {
!     mixed elt, val;
!     int n, i, j, size;
  
!     arr = arr[..];
!     for (n = 1, size = sizeof(arr); n < size; n <<= 1) ;
! 
!     for (n >>= 1; n > 0; --n) {
! 	elt = arr[n - 1];
! 	for (i = n, j = n << 1; j <= size; i = j, j <<= 1) {
! 	    val = arr[j - 1];
! 	    if (j < size && eval(({ func, arr[j], val }), ([ ]))[1]) {
! 		val = arr[j++];
! 	    }
! 	    if (eval(({ func, elt, val }), ([ ]))[1]) {
! 		break;
! 	    }
! 	    arr[i - 1] = val;
! 	}
! 	arr[i - 1] = elt;
      }
  
!     for (n = size - 1; n > 0; --n) {
! 	elt = arr[n];
! 	arr[n] = arr[0];
! 	for (i = 1, j = 2; j <= n; i = j, j <<= 1) {
! 	    val = arr[j - 1];
! 	    if (j < n && eval(({ func, arr[j], val }), ([ ]))[1]) {
! 		val = arr[j++];
! 	    }
! 	    if (eval(({ func, elt, val }), ([ ]))[1]) {
! 		break;
! 	    }
! 	    arr[i - 1] = val;
! 	}
! 	arr[i - 1] = elt;
      }
! 
!     return arr;
  }
  
  /*
--- 1447,1502 ----
   * NAME:	sort_array()
   * DESCRIPTION:	sort an array
   */
! varargs mixed *lambda_sort_array(mixed *source, closure func)
  {
!     int step, halfstep, size;
!     int i, j, i1, i2, end1, end2;
!     mixed *dest, *temp;
  
!     size = sizeof(source);
!     if (size < 2) {
!         return source[..];
      }
+     dest = allocate(size);
+     step = 2;
+     halfstep = 1;
  
!     while (halfstep < size) {
!         for (i = j = 0; i < size; i += step) {
!             i1 = i;
!             i2 = i + halfstep;
!             end1 = i2;
!             if (end1 > size) {
!                 end1 = size;
!             }
!             end2 = i + step;
!             if (end2 > size) {
!                 end2 = size;
!             }
!             while (i1 < end1 && i2 < end2) {
! 		if (eval(({ func, source[i1], source[i2] }), ([ ]))[1] > 0) {
!                     dest[j++] = source[i2++];
!                 } else {
!                     dest[j++] = source[i1++];
!                 }
!             }
!             if (i1 == end1) {
!                 while (i2 < end2) {
!                     dest[j++] = source[i2++];
!                 }
!             } else {
!                 while (i1 < end1) {
!                     dest[j++] = source[i1++];
!                 }
!             }
!         }
!         halfstep = step;
!         step += step;
!         temp = source;
!         source = dest;
!         dest = temp;
      }
!     return source;
  }
  
  /*