
 message() 讯息处理函式
------------------------

message() 是 MudOS  中, 新设计的外部函式 (efun).  此函式的用途是使讯息
传递更简易, 并提供讯息处理程式沟通的标准.

以下是 message 的使用说明:
=====================================================================
语法:

void message( mixed class, string message, mixed targets, mixed exclude);

无传回值 message( 混合 class, 字串 message, 混合 targets, 混合 exclude );

message() 呼叫任何接收讯息之物件里面的 
receive_message( 混合 class, 字串 message ) 函式 (target  名单就是接收
讯息的物件).  而 exclude  中列出不予接收讯息的物件. 基本上, 这样会送讯
息给目标物件.

message 就是要传达的讯息字串.

class 是讯息的种类 (给讯息处理程式或其他程式分类用) 一些例子像是: 
combat (战斗) 、 shout (呐喊)、  emergency (危急) 等等.

target  是接收讯息的物件名单. 可以是一个物件档案名称的字串, 也可以是一
个物件指标 (pointer), 亦可以是多个物件的档案名称或指标的阵列 (array).

exclude 是不可收到讯息的物件名单. 可以是一个物件指标或是多个物件指标的
阵列.
======================================================================

message() 函式最重要的地方应该是 class  参数. 如果能正确使用它, 您可以
作出一个简单的耳罩以过滤讯息, 或是让讯息处理程式加以处理. class 定义了
message 字串讯息的分类为何. 一开始简单的分类应包括 shout (呐喊)、 say
 (谈话)、 write (显示)、 tell_object (给物件的讯息)  (tell_object 由
模拟外部函式 (simul_efun) 中的 tell_object()  函式产生, 代替传统的外部
函式).

谈到这里, 您大概想要马上作出一个简单的耳罩功能 (过滤呐喊的功能).  在您
的使用者 (玩家) 物件中, 您要有 receive_message()  函式. 以下是一个最简
单的作法 (随您 mudlib 不同, 应作出一些修正以符合实际情况) :

void receive_message (string msg, mixed class)
{
	receive(msg);
}

这样只是收到 message()  送来的所有的讯息, 并原封不动显示给使用者. 但是
, 您可以想到一个简单的耳罩:

// 先初始化 muffle 阵列的值, 以预防 muffle 没有东西时, 让 member_array()
   产生阵列指向错误的讯息.

string *muffle = ({});

// 呼叫 muffle_class() 可以随时加上耳罩的种类.

int muffle_class ( string arg )
{
	muffle += ({ arg });
}

// receive_message() 是 message() 呼叫的讯息处理函式.
   在此检查 muffle 阵列中是否有跟 class 相同的种类, 没有就放行.

void receive_message ( string msg, string class )
{
	if ( member_array( class, muffle ) == -1 )
		receive(msg);
}

您现在可以看到, 如果特定种类的讯息被消音 (假设是“呐喊”),  则呐喊的讯
息永远不会显示出来, 其他种类的讯息则正常显示.

可是, 在传统的 mud  观念中, 并非所有使用 shout()  的讯息都是呐喊. 譬如
说, mud 系统管理者想对所有的使用者宣布 mud  将于五分钟后关闭. 如此一来
, 可能会用 echo 指令. 而 echo 指令又使用 shout(). 如此导致使用呐喊耳罩
的使用者听不见重要的讯息. 这种情形表示讯息还需要再分类. 所以, 我们干脆
把这种讯息归类为新的 broadcast (广播) 分类. 而这种分类就用于每一个人都
该听到的重要讯息. 甚至应限制使用者使用广播耳罩.

让我们看看另一个例子. 如果您对于塞满你荧幕的表情叙述 (emotes) 感到厌烦
的话, 该怎么办 ?  要是有个表情讯息的耳罩该有多好 ?  很显然, 我们需要把
这些讯息归类为 emote (表情).  现在您也许会想到: “喂....我可不想在每次
写这种表情指令的时候, 还要用那个超级复杂的 message()  函式。像 write()
和 say()  就很简单, 我宁愿用这些。”好吧, 我也同意您的话. 要对付这个问
题, 我将一般会用到的讯息种类写成个别的模拟外部函式 (simul_efun) . 我新
写了一个名为 emote()  的模拟外部函式, 让这些指令写起来要方便多了. 而
emote() 函式使用 message()  传达 emote  种类的讯息. 我不把程式给您, 以
下是基本的概念:

varargs int emote (object emoter, string self_message, string
	other_message, mixed emotee, string target_message, string modifier);

emoter - 作出表情的物件.
self_message - 作出表情的物件本身收到的讯息.
other_message -  整个房间其他人收到的讯息.
emotee - 传达表情讯息的对象 (例如 kick huthar)
target_message - 对象收到的讯息.
string modifier - 任何加在讯息尾端的修饰词. (像是副词: smile happily,
		  cheerfully  等等) - 这只有很复杂的表情指令用得到 (
		  如果您想让一个表情指令能有多个修饰词的话).
		   (译按: 这是英文的文法, 与中文文法不同)

在此, 有些人可能会想到: “好....你可以作出功能强大的多用途耳罩，厉害。
不过这玩意儿看来没啥用处。”说得好, 目前您只能利用耳罩过滤一些讯息而已.
有的人有办法写出聪明的讯息处理程式, 才是下面介绍的 message() 真正好处. 
以下是实际的作法:

基本上, 要把送给使用者的讯息按照内容分类. 所以假设您有一个 combat 分类
、一个  stat (叙述) 分类、一个 room_description  (房间描述) 分类、一个
help (求助资料) 分类. 在开始之前, 我们来写一个新的 receive_message().

int has_smart_client;

void receive_message (string msg, string class)
{
	if (member_array(class,muffle) == -1) {
		if (has_smart_client) 
			receive (class + " : " + msg);
		else
			receive (msg);
	}
}


好. 我们来看看这些在作什么. 如果一个使用者物件定义了 has_smart_client > 0,
则所有的讯息前面都会加上分类名称. 所以, 如果您想写一个聪明的讯息处理程
式分析所有的讯息, 您可以把房间叙述放在一个视窗里, 谈话放在另一个视窗,
战斗讯息摆在另一个视窗, 以此类推. 您甚至可以摆一个状态列, 用来显示目前
身处的房间名称 (因为您进入房间时, 收到一个 room_name (房间名称) 分类的
讯息) . 您可以利用 heart_beat() 函式, 在状态列中显示目前的体力. 这些分
类的讯息都可以用这种方式显示给终端的使用者.

您甚至可以使用此方法写出一个简单的图形介面的用户端程式. BSX 图形 mud  
与用户端程式可以用 MudOS  的 message()  函式在内部工作. 您也可以传输一
张小的点阵图案 (bitmap) 代替 BSX 的多边形线条绘图 (polygon-based line 
drawing). message() 的用途极广.

但是以上所谈的事情之中, 至少有个大问题在里面. 既然每个人都要自己撰写程
式处理这些讯息, 也没有人写出这么好的用户端程式 (client) 以发挥这些讯息
分类的长处. 一旦讯息处理程式写出来了, 您的 mudlib 又凭什么保证能与此程
式配合 ?  好吧, 这就是这份说明文件的重点所在. 我希望能概略介绍一个简单
的讯息协定让大家接受, 如果用户端程式哪一天真的写出来了, 只要您的 mudlib
符合以下的协定即可.

讯息协定:

所有送给聪明用户端程式的讯息格式如下:

"class:msg_length:msg"

msg_len 是 msg  字串的长度. 加上这个可以让用户端程式知道讯息到底传送完
毕了没.

使用底下的分类清单, 使用户端程式分析并使用这些分类的讯息.

say			使用 say  指令
shout			使用 shout  指令
tell			使用 tell 指令
emote			表情指令
broadcast		对每一个人广播的讯息
combat			普通的战斗讯息
combat_self		使用者自己产生的战斗讯息
combat_other		别人产生的战斗讯息
combat_*		其他特定的战斗讯息
room_description	房间或地点的长叙述
room_name		房间的简短名称
inventory		您身上带着的东西
item_description	物品的叙述
status			普通的状态讯息
status_hp		目前的体力
status_sp		目前的法力
status_sobriety		目前的酒醉状况
status_*		其他的状态
score			普通的总评讯息
score_exp		经验值
score_money		金钱或其他货币的数量
developer		对所有巫师或发展程式者广播
class_fighter		给全体战士的讯息
class_mage		给全体法师的讯息
class_thief		给全体贼的讯息
class_priest		给全体主教的讯息
class_*			给其他职业全体的讯息
race_human		给全体人类的讯息
race_elf		给全体精灵的讯息
race_dwarf		给全体矮人的讯息
race_*			给其他种族全体的讯息

*** 其他内部的选项 ***
bitmap			普通的点阵图
bitmap_*		特定的点阵图
drawing			普通的绘图
drawing_*		特定型态的绘图

翻译:	Spock @ FF	97.Aug.8.
