			LPC Basics
		Written by Descrates of Borg
			23 April 1993
		     Translated by Hanzo

		第三章  函数 (Functions)

	  现在，你知道物件 (objects) 是由函数所组成。物件与游戏的
	其他部份以呼叫函数 (call function) 的方式互动。你也知道变
	数 (Variables) 与其最基本的三种LPC资料型态 void, int 与 
	string。若你不完全了解这些，你需要复习第一章和第二章。

	  LPC 的函数就像数学的函数一样，需要输入值与输出计算结果。
	有些语言像 Pascal 的程序 (procedure) 和函数 (function)的构

	想 (concept)是不同的，但是在 LPC 中是没有分别的。在 Pascal
	中称为程序 (procedure)，在 LPC 中称为 type void 的函数 (a 
	function of type void)。这是指一个函数不会输出一的有用的值。
	最平常的函数像以下的例子:

	void do_nothing() { }

	这个函数没有输入值，不执行指令，也没有输出任何有效值。


	有效的函数必须包含三个部份:
	
	(1) 宣告 (the declaration)
	(2) 定义 (the definition)
	(3) 呼叫 (the call)

	函数与变数相同，都必须做宣告 (declare)。宣告可以使驱动程式知
	道几件事: (1)此函数将会传回 (return) 何种函数资料。 (2)有几
	个输入值以及它们的种类。
	更为常用的函数输入值称为"参数" (parameter) 。而从现在起，所
	有的函数输入值将被称为函数之参数。

	定义 (definition) 是一个能告诉驱动程式这个被定义的函数将如何
	处理它的输入值的代号。

	呼叫 (call) 是从别的程式输入一个代号来使用一个已定义的完整函
	数。

	以下是一个函数的例子:
	
	void write_vals();       /* 这通常是宣告 */
	int add(int x, int y);   /* 开始输入物件的代号 */

	void write_vals() {      /* 这个函数的定义 */
	    int x;               /* write_vals().  写入 x 的值 */

	    x = add(2, 2);       /* 呼叫 add(). 送出 add() 函数所
					需的输入值 */
	    write(x+"\n");       /* 传回变数 x 的值 */
	}

	int add(int x, int y) {  /* add() 的定义，需要两个整数输
					入值 */
    	    return x + y;        /* 把执行的结果传回呼叫此函数的
					函数 */
	}

	函数呼叫的顺序和代号的排列顺并不需要一致，但是函数的宣告必
	须放在此函数的定义之前而且必须放在每一个呼叫此函数的函数之
	前。

	现在你应该成功的了解一个函数的组成结构了。了解你要呼叫的函
	数的传回资料的种类是十分重要的。如果你把一个函数的传回的文
	字资料指定到一个并宣告为整数的变数，最后得到的一定是错误的
	执行结果。你曾注意到一些你以前看不懂的代号是函数吗？例如: 
	this_player(), write(), say(), this_object() 等.
	事实上，在上面提到的 write_val() 函数中，包函两个"呼叫"。
	第一个是由你自己定义的 add() 。第二的是由驱动程式定义的 
	write()。驱动程式 (driver)已经替你将 write() 宣告和定义完
	毕。你只须要呼叫它出来用即可。此类的函数称为 efuns，efuns 
	是 everywhere function 的缩写。efuns 定义在游戏驱动程式的 
	C 之中。因为如此，所以呼叫 efuns 比呼叫设计者自行创造的函
	数要快一些，而且呼叫的方式计完全相同。但在使用 efuns 之前
	必须注意两件事:
	(1)efuns 函数的传回资料的种类 (2)efuns 函数所需要的参数。
	大部份的 mud都会有以下的其中之一:
	  最常见: 在叫做 /doc/efun 的子目录中。在其中宣告和描述放
	在此目录中的 efuns。
	  此外: 一个叫 man 或 help 的指令可供使用。若你键入 man 
	write 或 help write，就可以得到在 /doc/efun 中的资料。
	你可以看到 write() 函数如下:

	void write(string|int)

	这表示一个正确的呼叫 write() 没有传回资料，而需要一个字串
	或是整数当作输入值。

	在函数中，定义的说明放置的顺序是非常重要的。例如在以上的 
	write_vals() 的函数中，若想得到正确的 write() 输出值，那个
	把 add() 传回资料指定到 x 的说明必须放在呼叫 write() 的说
	明之前。换而言之，虽然函数可以不同置于档案之中。但是在函数
	的定义中，定义的说明必须按照它们被执行的先后顺序放置。

	最后还有一点补充是有关于传回资料的。把资料传回到一个函数的
	简单方法是在欲执行的函数中加入此说明:
		return value;
	其中的 value 是指一个能够符合此函数宣告之任何型态的变数或
	常数。

	总结:
	LPC 的物件档案是由许多函数所组成。而函数是由三部份组成: (1)
	宣告 (2) 定义 (3) 呼叫。函数的定义可以用任何方式出现在物件档
	案之中除了你不能把这个函数定义在别的函数之中。函数的宣告必须
	出现在函数的定义和任何对此函数的呼叫之前。每次需要用到一个函
	数之时，可用呼叫的方式来执行那个函数。函数的定义是由一系列有
	顺序的代号 (code) 所组成，顺序如下:
	(1) 函数的送回资料型态。
	(2) 函数的名字。
	(3) 参数列。
	(4) 一个开始的符号 "{" 表示所有的指令从此符号之后开始。
	(5) 说明、表示和呼叫其他的函数。
	(6) 一个结束的符号 "}" 表示所有的指令从此符号之后结束。

	以下是一个简单而完整的函数的例子:
	void do_nothing() { }
	说明 (instruction) : 指示驱动程式要做的事。
	表示 (expression)  : 有关于数值的说明，像 "a==b"
	呼叫 (call)        : 所有的函数呼叫的顺序必须符合你所要执行
			     的顺序。

	每一个游戏的驱动程式中，都有一些预先设定好的函数称为 efuns。
	你可以在大部份的 mud 的 /doc/efun 目录中找到详细资料。有的 
	mud 站有特别的巫师 help 或 man 指令供线上查询使用。使用这些 
	efuns 必须遵守已经被定义在 efuns 中的方式。例如参数的数量和
	形态或传回资料的形态等等。

	注意:
	有的 mud 驱动程式不要求作函数的宣告。有些甚至不需要你指定函
	数的传回资料形态。但不论如何，想要省略宣告或传回资料形态的定
	义是不明智的。因为:
	(1) 方便别人(包括你自己在内)读你写的函数。
	(2) 容易找到在你的程式中，有由于资料形态不符造成的错误。
	(3) 这是公认的一种好的函数写作方式。

	另外，efuns 在各个驱动程式中的设定大致相同。另外，还有类似的
	函数群称为 simul efuns (simulated efuns)。simul efuns 就会随
	着 mudlib 的不同而不同。simul efuns 是被定义在 LPC 中的特殊物
	件称为 simul_efun.c 的档案中。每个好的 mudlib 对其 simul_funs
	都会有充份的说明文件。有的 mud 会将部份的 efuns 从驱动程式中
	搬到 mudlib 中而变成 simul_efuns。但对一个程式设计者而言并没
	有差异。我之所以特别指出这点是因为有的人在他 mud 站的 efun 
	中找不到 write() 而是在 simul_efun 之中。若一切正常，write()
	在大部份的 mud 中将是一个 simul_efun。

