背景:
阅读文章

Lpc程序和编程环境

[日期:2007-05-05] 来源:  作者: [字体: ]

第一节,编程环境


通常我们所见到的Mud大多是LpMud。LpMuds使用Unix的指令和
文件结构。如果你对Unix有所了解,那么LpMud中的一些指令和它的
文件结构与普通的Unix基本一样。如果你从未使用过Unix,那么它
Dos不同的是在文件的路径用"/",而不是Dos的"\".
一个典型的LpMud的文件是这样的:
/clone/player/player.c


"/clone/player/"是路径,player.c是文件名。
在多数的LpMud中,下面这些的基本的Unix指令是可以使用的:
pwd, cd, ls, rm, mv, cp, mkdir, rmdir, more, tail, cat, ed
如果从未使用过Unix,那么下面这张表也许是有用的。
pwd: 显示当前目录
cd: 改换你当前的工作目录,和Dos的cd一样。
ls: 列出指定目录下的所有文件,如果没有指定任何目录,那就列
出当前目录底下的文件。和Dos的dir一样。
rm: 删除一个文件 和Dos的rmdir一样
mv: 从命名一个文件 和Dos的move一样
cp: 复制一个文件 和Dos的copy一样
mkdir: 创建一个目录
rmdir: 删除一个目录
more: 按页显示一个文件在你的当前屏幕。
cat: 显示整个文件。和Dos的type一样。
tail: 现在一个文件的结尾几行。
ed: 允许你使用Mud自带的编辑器,编辑一个文件。

第二节 Lpc程序


2.1 Lpc程序。
Lpc的程序看起来和一般的C区别不断大,语法基本一样,但是
Lpc和一般的语言有着根本的不同,Lpc程序是编写一个一个的"Object"。
这有什么区别呢?一般的程序是在执行过程中,通常有一个明显的
开始和和结束。程序从一个地方开始,然后顺序执行下去,到了结
束的地方就中断了。Lpc的Object不是这样的。
所谓的不同的Mud,实际上是一些不同的Lpc的Object在一个Driver
的上的各种不同的表现。也就说,Lpc的Object是运行在一个Driver
上的。这些Object组成了LpMud的丰富多彩的世界。Driver几乎不参
与创建你所接触到的世界,它所完成的工作只是让那些Lpc的Object
活动起来。Lpc的Object可能没有明显的开始和结束的标志,它可能
永远在工作。 和一般的程序一样,Lpc“程序”也是由一个或多个
文件组成。一个Lpc的Object是按如下方式被执行的:Driver把和这
个Object相关的文件读入内存,然后解释执行。但是要记住的是,
读入内存,并不是说,它就开始按顺序执行。

2.2 Driver和Mudlib关系
在有些游戏中,整个游戏包括Driver和游戏世界都用C写好,这样
能快一些,但是游戏的扩充性很差,巫师们不可能在游戏进行中添
加任何东西。LpMud则相反。Driver理论上应该和玩家所接触的世界
几乎没有任何直接的联系。游戏世界应该是自己独立的,而且是“即
玩即加”的。这就是为什么LpMud使用Lpc作为编程语言的原因。它
允许你创建一个游戏世界,再由Driver在需要时读入解释执行。Lpc
甚至比C更简单,更容易明白,但是它可以创建一个可以让许多人在
上面游戏的世界。
在你写完一个Lpc的文件时,它存在于主机的硬盘上。在游戏进行
中,当需要整个Object时,这份文件将被调入内存,一个特殊的函
数被调用来初始化这个Object的一些变量。现在你不用关心什么是
变量,什么是函数以及游戏本身怎样来调用这个object,你只要记
住Driver从硬盘中读入一个文件,然后放在内存中,如果没有任何
错误的话。

2.3 一个Object被装人内存。
一个Object不会也不必有一个特点的地方让Driver去执行它,通
常Drvier会在Object中找一个地方去初始化它。一般都是这个函数
叫做create()。
Lpc的Object是一些变量(它的值能变化)和函数(函数通常是用来
操纵那些变量的一段程序)的组合。函数操纵变量的方式有:调用
其他函数,使用Driver内部定义的函数(efun),基本的Lpc表达式
以及流控制。
我们来看个变量的例子: wiz_level。这个变量记录你的巫师等
级,如果是0呢,通常是普普通通的玩家了。这个值如果越大就表
示你的巫师等级越高。这个也同时控制了你能不能执行一些巫师
指令。基本上来说,一个Object就是一些变量“堆”在一起的东
西。一个Object改变了,也就是某一个或者一些变量改变了。
总的来说,一个Object如果要被内存中的另一个Object调用,
Driver会去找这个Object的那堆变量放在哪里,如果这些变量没
有值,那么Driver会调用一个特定的函数create来初始化这些变
量。
但是create()不是Lpc代码开始执行的地方,只是大多数的Object
从这里开始。事实上,create()可以不存在。如果这个Object不
需要对变量初始化,那么create()可以不存在。那么这样的Object
开始执行的地方就完全的不同于一般的Object,可以从任何地方开
始。

那么究竟什么是Lpc的Object?Lpc的Object就是一堆变量的集合,
它带有一个或者更多的函数来操纵控制这些变量,函数的排列顺序
是无所谓的,随便那个排在前面对这个Object的特性没有影响。 2.3 代码风格
在上面说过函数的顺序对这个Object的特性是毫无影响的。
但是一个有着良好代码风格的程序对LpMud是很重要的。因为
LpMud通常不会也不可能是一个人完成的,如果程序没有较好
的可读性,那么别人理解你的“作品”是很困难的。而且有个
良好的程序风格能给人以优雅的感觉,因此希望大家写的Lpc
程序能有个好的风格。大家中的有些人可能以后会加入XO team
创建自己梦想中的世界,我们要求你采用如下的格式书写程序。

2.3.1 头文件
在一个文件的开头是一段说明。采用如下格式:

/* /u/trill/obj/test.c
* from XO Object Library
* 测试用的Object
* created by trill 19970808
* version @(#) test.c 2.1@(#)
* last modified by trill 19971008
* 测试tell_wizard这个simul_efun
*/
第一行是这个文件的绝对路径,就是全路径。
第二行是它所在的Mudlib
第三行是它的功能的简单的描述,可以超过一行。
第四行是这个文件的作者和创建时间。
第五行是它的版本号,可能做了多次修改,甚至可能会重写,
这个数字2.1标志了它大概做过多少次改动。
第六行是最后一次修改的人和时间。
第七行是最后一些修改什么东西。

对于一个Object我们要求必须有这样一段说明,特别是前面
的五行必须存在,如果做了改动那么最后两行也要加上。
这样一般的一个Object,我们从这段说明就能了解到一些很重
要的信息。

下面是include一些文件和继承(inherit)一些Object。

#include
#include "include/test.h"

inherit NPC;

先系统的文件,后自己定义的一些头文件。特别要求的是必须
有个和这个Object同名的".h"文件,比如"test.h"放在这个
Object所在的目录的下一级目录"include"底下,就是说在
include部分的最后一行是#include "include/test.h"。
在test.h定义所有在test.c用到的函数的原形,以及定义一些
宏和常量。
这样做的好处是:
第一不用出现一个函数在引用时没有说明,
第二如果想知道这个Object有什么函数,直接看这个文件就可以
了,不必去看那个test.c,可能test.c非常长。
第三如果建立一个help系统,用来查询每个Object存在的函数,
那么这样直接去读test.h就可以,否则是一件很麻烦的事。

关于inherit我们在继承部分再说。

2.3.2 变量说明

在变量说明部分,大家最好在每个变量后面加一个简单的说明。

2.3.3 函数

一个Object的函数的顺序和名字对这个Object的表现是毫无影
响的。但是为了让这个Object有良好的可读性,我们要求一个Object
的函数按如下方式排列和命名:
首先是变量的接口部分,这些函数统一用Set+变量名来改变该
变量的值,用Get+变量来返回变量的值。比如

static int level;

void SetLevl(int i)
{
level = i;
}

int GetLevel()
{
return level;
}
其次是一些操纵和控制变量的一些函数。比如

void AddLevel(int i)
{
一个Object的函数的顺序和名字对这个Object的表现是毫无影
响的。但是为了让这个Object有良好的可读性,我们要求一个Object
的函数按如下方式排列和命名:
首先是变量的接口部分,这些函数统一用Set+变量名来改变该
变量的值,用Get+变量来返回变量的值。比如

static int level;

void SetLevl(int i)
{
level = i;
}

int GetLevel()
{
return level;
}
其次是一些操纵和控制变量的一些函数。比如

void AddLevel(int i)
{
level += i;
}

这两类函数要求每个单词的第一字母大写。

再是一些Object所能做的事件(event),比如战斗,结婚等等。比如

void eventQuit()
{
...
}

这些函数要求事件的每个单词的第一字母大写,比如eventFight,
eventMarry等等。

再下面的是由Driver调用的一些函数,比如create(), heart_beat,
setup()。

最后是一些这个Object自己私有的函数,完成一些特别的功能。这些
函数通常让要求每个单词的小写,中间用下划线(_)隔开。

要注意的是每个函数之间用一个空行隔开。

这些是对一个文件的整体要求,如果你有兴趣将来在XO team写程序,
最好从现在开始就养成这样的编程习惯。如果你是别的Mud里面的巫师,
我想一个Mud里面最好也有一个统一的整齐的风格。
也许你会问,这样要求有必要吗?这样太麻烦,程序写了自己能明
白就可以了。这是不对的,LpMud是大家合作的项目,如果你做的程序
别人没法看懂,不知道写的东西里面有些什么,能调用什么函数,那
么实际上你写的东西是失败的,没人会去用它,它可能永远“死”在
硬盘上。而且函数统一的命名法能尽快找到你所需要的函数,同时也
能提高整个程序的可读性。
对于代码风格XO还有一些别的要求,我们将在以后的文章中介绍,
如果你加入了XO team,代码风格将是第一篇要读的文章。

小结:
关于Lpc程序和编程环境,就介绍到这里。看完这一章,我想大家
要记住的是LpMud是采用Lpc做为编程语言,Unix文件结构作为文件组
织形式。Lpc是编写Object的一种语言,它的程序没有特殊的开始和
结束的标志。如果Object被使用到,那么它被调入内存,如果这个
Object有一个叫create()的函数,首先被执行,来初始化一些变量。
Lpc的Object是一堆变量的集合,同时带有一些能操纵改变这些变量
的函数。Lpc的代码风格,我想一个Mud最好有一个统一的风格,特别
的XO有自己的特别的要求。

题外话:
当了好久的巫师,也用Lpc写了一些东西。我一直在试着理解Lpc,
因为以我看如果一个巫师没有真正理解Lpc,他就不可能真正理解
LpMud。理解Lpc并不仅仅意味着会使用它,许多巫师能使用它但是
并不真正理解它。我希望在这个Lpc的介绍文章,能给大家一个Lpc
的整体的印象,真正把握和理解Lpc,能创造自己心中梦想的世界


尊重作者 转载请注明出处52mud.com

收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容       Lpc 
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论