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 each others feet. I'd like to think that is not so and there for 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 despair, 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 modified from another object. LPMud is never more safe than it's most unsafe object.

Wizards beware

Making good armors 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 armors. You'll become unpopular among the older and higher wizards. Your chances 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 impeccable, varied and full of surprises. That way nobody 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 unpopular:
bulletthrow(0); It crashes most LPMuds.
bulletdestruct(this_object()); or destruct(this_player()); in init() It crashes some LPMuds.
bulletexplode() with a user-typed second argument can crash the mud.
bulletNever do errors in auto_loading objects. Players can loose their commands.
bulletErrors in exit() will stop people from leaving and that's not a pretty sight.
bulletDon't trust find_call_out(), it can return -1 even if there are pending call_outs.
bulletNever make super-monsters, you have no idea how usual it is that they escape and kill players.
bulletAvoid putting \ at the end of strings in objects that use save_object(). It won't be able to restore that string on many muds.
bulletIn 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 'Illegal to load object with euid zero'.
bulletNever trust the players not to do something, sooner or later they will anyway.
bulletBe careful with call_outs if they multiply they stop the mud.
bulletBe careful with inherit, if you inherit an object that inherit your object the mud stops in an eternal loop.
bulletDon't use the efuns ed() & shout() without a this_player()
bulletOn 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.
bulletIn 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.
bulletWatch out for too deep recursions, it can actually crash the driver.
bulletThe preprocessor isn't bug free either, division by zero or modulo by zero in #if will crash most drivers.
bulletDon't make it possible to enter your workroom from the game, it's easy to forget superweapons etc. in the workroom.
bulletEverybody loves to make wiztools, but think first, maybe your particular wiztool is already made.
bulletexplode() is not the inverse of implode(), rememeber that.
bulletNever remember players by their playerobject, always use ob->query_real_name() and find_player() to remember the player as the playerobject may change.
bulletWatch 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.
bulletRemember that LPMud is single-threaded, that mean that if you succeed in keeping the CPU for yourself the mud will stop.
bulletWatch 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.
bulletIt is simpler to have one file per object, but it is much more memory-efficient to clone standardobjects from rooms and configure them.
bulletBusy wait. That is, don't do a loop to make a delay by counting to one zillion, the mud will stop while you do that. Use call_out() instead.
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 & Tricks

Questions and answers about LPC.

Note that it would be impossible to give answers that would apply to every mud in the world, but I think these applies to most. 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 you 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 LPMud's have an efun sprintf, and then you can do like this: str=sprintf("%s",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 standard objects 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 extract(string a,int b,int c)
	{
	  if(c>=b) if(b>-1) if(strlen(a)>c) return efun::extract(a,b,c);
	  return "";
	}

	string *explode(string a,string b)
	{
	  string *c;
	  if(a==b) return ({"",""}); 
	  if(strlen(b)) if(my_extract(a,0,strlen(b)-1)==b)
	    return ({ "" })+explode(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 you 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.

Q: How do I recognize a roomobject?

A: You don't, on most MUDS the only definition of a room is that it is accessible by players.

Q: How do I recognize a player?

A: Use interactive(ob), not query_ip_number().

Q: How do I recognize a monster?

A: Call query_npc(), many people use living(), but other objects than monsters can be living.

 

Profezzorn (hubbe@lysator.liu.se)