
	***** Lpc, the stuff that dreams are made of *****

A great man once said "I am not a great man, I stand on the shoulders of
giants." Another man said that in the computer business we stand on
eachothers feet. I'd like to think that is not so and therefor I share some
of my experiences here.

Hacking
  There is a hack for every problem, and you can quote me on that. However
  there is a right and a wrong way to solve a problem. When the problem is
  caused by the mudlib, the right way is of course to change the mudlib,
  this may seem hopeless, but don't dispair, the archwizards are there to
  make the changes for you. Arches often equals lazy though, so you better
  have ample motivation for your change.

Security
  Remember that anyone can call any functions that you haven't declared as
  static. Also remember that static functions can't be called by any other
  objects, not even your own or call_out:s. ALso remember that arrays are
  shared, that means that if you return an array from a function its contents
  can be modifyed from another object. Lpmud is never more safe than it's
  most unsafe object.

Wizards beware
  Making good armours and weapons is probably the best way of ensuring that
  players will visit your area, but beware, too good stuff will invariably
  cause some sort of inflation in weapons and armours. You'll become
  inpopular among the older and higher wizards. Your chanses of advancing
  beyond wizardhood may reduce. If you still want to make a bunch of really
  good weapons then make sure that they are _very_ hard to get and that your
  area is inpeckable, variated and full of surprises. That way noone can
  complain and you can motivate your good weapons.

Administrators beware
  Some of your wizards _will_ ignore the warning above, so what the heck,
  giv'em hell for it. There is of course another way to stop an evil trend:
  Example, someone dreams up an 'autobow' command, and suddenly everybody
  goes around bowing to everybody. As an administrator you can either
  perish by this evil, useless and extremly utter command or you can make
  your own generalized 'auto' command and put it in the playerobject. Now
  all the novelty with autobow is lost and with any luck, the trend will die
  all by itself. If not, well, nobody is perfect.

Things not to do

  Don't do this, or you'll become very, very inpopular:

      o throw(0);
	It crashes most lpmuds.

      o destruct(this_object()); or destruct(this_player()); in init()
	It crashes some lpmuds.

      o explode() with a user-typed second argument can crash the mud.

      o Never do errors in auto_loading objects.
	Players can loose their commands.

      o Errors in exit() will stop people from leaving and that's not a
	pretty sight.

      o Don't trust find_call_out(), it can return -1 even if there are
	pending call_outs.

      o Never make super-monsters, you have no idea how usual it is that they
	escape and kill players.

      o Avoid putting \ at the end of strings in objects that use
	save_object(). It won't be able to restore that string on many muds.

      o In native mode, if an objects euid is zero it is not possible to
	call_out to other objects if you don't make absolutely sure that the
	other object is loaded first. It gives the error 'Illigal to load
	object with euid zero'.

      o Never trust the players not to do something, sooner or later they will
	anyway.

      o Be careful with call_outs if they multiply they stop the mud.

      o Be careful with inherit, if you inherit an object that inherit your
	object the mud stops in an eternal loop.

      o Don't use the efuns ed() & shout() without a this_player()

      o On some muds it's possible to catch() too long evaluation and then
	continue as nothing has happened. This can of course cause an eternal
	loop.

      o In native mode it is possible to initialize variables like this:
	int a=12;
	or
	int b=destruct(this_object());
	Don't use the latter example, it crashes most muds.

      o Watch out for too deep recursions, it can actually crash the driver.

      o The preprocessor isn't bugfree either, division by zero or modulo by
	zero in #if will crash most drivers.

      o Don't make it possible to enter your workroom from the game, it's easy
	to forget superweapons etc. in the workroom.

      o Everybody loves to make wiztools, but think first, maybe your
	particular wiztool is already made.

      o explode() is not the inverse of implode(), rememeber that.

      o Never remember players by their playerobject, always use
	ob->query_real_name() and find_player() to remember the player as
	the playerobject may change.

      o Watch out with inherit, if your object inherit two objects which in
        their turn inherit the same object. You will have two sets of some
        variables.

      o Remember that lpmud is singel-threaded, that mean that if you succseed
	in keeping the cpu for yourself the mud will stop.

      o Watch out when using say() and call_out(), call_out saves this_player
	in all modern lpmuds, therefor say() will appear where this_player is
	even he/she has wandered across the whole game during the delay.

  There are lots of other things you shouldn't do, but with any common sense
  you won't make _every_ mistake in the book :) If you don't belive me, go
  ahead, make a fool out of yourself.

Tips & trix

  o Mappings are sorted, for all types but integers this is uninportant, as
    they are sorted in a strange order. However, integers are sorted in
    numerical order and it's much faster than sort_array()

  o add_action() has a flag that makes it possible to catch all commands
    beginning with a certain string. add_action("com","",1) is a special
    case thogh, it catches _all_ commands typed by a player. Nifty, but
    dangerous, beware.

  o input_to() is another way of catching all the input from a player, but
    if the command is prepended with a ! it will still be interpreted like
    a normal command.

  o implode(explode("  alpha beta "," ")," ")=="alpha beta" Remember and use.

  o Don't get carried away and make zillions of rooms without anything
    interesting in them, mortals invariably find this boring.

  o Try not to copy code, use inherit instead, that is much more
    memory-efficient.

  o Avoid too much calling between objects, it makes the code unreadable and slow.
    If you want to split the code into lots of files, use inherit.

  o Don't take any responsibily youself, always let some higher wizard check
    your obejects so he can take part of the blame.

  o enable_commands() changes this_player() to this_object() use with care.

  o if simul_efun has defined an efun in a way you don't like, you can use
    efun::function() instead.


Questions and answers about lpc.

  Q: How do I make a weapon that hits harder against some types of monsters.
  A: Here is an example of an weapon that has the upper hand on orcs.

	int weapon_hit(object attacked)
	{
	  if(attacked->query_race()=="orc")
	  {
	    write("Ziing!\n");
	    return 10;  /* This number is added to the damage */
	  }else{
	    return ;
	  }
	}

  Q: Can I use ANSI codes to make objects look green?
  A: Yes, you can, No are not allowed to do it. Some muds will even filter out
     your escape sequences.

  Q: How do I know if an object is in the same room as my object?
  A: if(environment()==environment(the_object)))

  Q: How do I let another wizard read my files?
  A: The only way that works on all muds is the directory /open. Everybody
     can read and write there.

  Q: How do I know the filenames to the rooms when I use goto?
  A: You don't, you have to go there and check it out first.

  Q: How do I change a character within a string?
  A: You don't, you have to build a new string like this:
	string char;
	int pos;
	new_string=old_string[0..pos-1]+char+old_string[pos+1,10000];
     Note that char is a string, not an int or char or anything like that.

  Q: How do I transform an ascii value to a character in a string?
  A: In standard lpc there is no way of doing this but to have an array with
     all the strings in and index it on the number, but some lpmuds have an
     efun sprintf, and then you can do like this:
	str=sprintf("%c",value);
     See the efun chapter for further details.

  Q: How do I make my monsters wander around without letting them leave my area?
  A: The easiest way is to put a function in your monsters that identifies them,
     let's say query_is_profezzorns_monster() and let this function return 1,
     then you put the following code in all your rooms that leads out:

	int no_way() { return 1; }

	void init()
	{
	  ::init()
	  if(this_player()->query_is_profezzorns_monster())
	  {
	    /* Do this for every direction that leads out. */
	    add_action("no_way","south");
	  }
	}
     Some mudlibs has blocking function in their standarobjects and those
     functions are probably better, however, this solution should work
     almost everywhere.

  Q: Why doesn't the driver tell _me_ about the error, it just winds up in
     lpmud.log?
  A: Somewhere on the way to the error this_player() was changed to a monster,
     the most usual case is when enable_commands() is executed in the creation
     of a monster.

  Q: Are there any real manual or tutorial about lpc?
  A: If you don't count this document, then the answer is no.

  Q: Can I redefine an efun and still use the real efun?
  A: Yes, here is an example of how explode _should_ work:

	string my_extract(string a,int b,int c)
	{
	  if(b<=c && b>-1 && c<strlen(a)) return efun::extract(a,b,c);
	  return "";
	}

	string *explode(string a,string b)
	{
	  string *c;
	  if(a==b) return ({"",""}); 
	  if(strlen(b) && my_extract(a,0,strlen(b)-1)==b)
	    return ({ "" })+explode(my_extract(a,strlen(b),strlen(a)-1),b);
	  if(c=efun::explode(a+b,b)) return c;
	  return ({});
	}

     Note that efun::explode() is used to call the efun explode.

  Q: Is there a way of doing this or that?
  A: Read the efun chapter before you ask.

  Q: Why doesn't my object appear when I clone it? I can't find any errors
     anywhere!
  A: If are programming under a native mud you probably forgot to define
     move(), put this line in your program:
	void move(object o) { move_object(this_object(),o); }

  Q: Why isn't my question listed?
  A: It's not asked often enough or I just forgot, ask me about it.


						/Profezzorn
