作者laechan (小太保)
看板mud
标题Re: [闲聊] tmi-2 efun 与 simul_efun 简单说明
时间Sat Jun 28 10:26:58 2014
所有的 simul_efun 都位於 /adm/simul_efun 目录下,有些 .c 档
内只有一个 simul_efun,有些会包含好几个。
底下有说明的部份就是我判断会用到、常用的、重要的,相反的若我有
说这东西没用、很少用、用不太到、我不太熟....这类的,就代表我判
断就算不知道这些东西也没关系,有兴趣的可自行研究这样。
依据就是我在 sanc 1x 年的经验。
int adminp( mixed ob_or_str )
判断一个物件或是 id 是不是 admin,因为可接物件跟字串,所以它用
mixed 宣告,然後再用底下的判断式区隔:
if(stringp(ob_or_str)) // 如果是字串的话
.
.
else if(objectp(ob_or_str)) // 如果是物件的话
然後其读取的源头就是 /adm/obj/master.c 的 query_member_group
函数。
int wiz_lv(string str)
这个则是我仿 sanc 新增的函数,例如说 laechan 是 wiz,则
wiz_lv(
"laechan") > 0
它主要是读取玩家的 /data/std/connection 目录下的连线资料档去做
判断的,而且当该玩家在线时它直接做 adminp(str) 的判断。
string cap_words( string str )
基本上如果 str = "laechan", cap_words("laechan") = "Laechan",
如果 str = "abc def",cap_words(str) = "Abc Def"
这函数我摸 lpc 摸了十几年用都没用过。
string article(string str)
这东西主要是用在英文版的 tmi2-mudlib,比方我们要形容一只鸟时是
"a bird",要形容一颗蛋时则用"
an egg",那如何判断啥时该用 a 啥
时该用 "an"? 就是用这函数,它会判断 str 的首字字母是不是母音字
母 'a', 'e', 'i', 'o', 'u' 开头。
int atoi(string str)
简单的说它可以把字串 "123" 变成数字 123,它的做法很简单
int num;
sscanf(str,"%d",num);
那有没有 itoa?不需要,因为
int num=123;
string str;
str=""+num;
这样 str 就是 "123"。
string htoa(string map_string,int e)
这个则是我为地图系统新增的函数,它的关键段落在底下..
while(j-->0)
{
tmp=(s%2)+tmp; // 一直做 s mod 2 的动作
s=s/2;
}
map_string+=tmp;
从上面就可以想像 tmp 会一直做 "0" "1" 这两个字串的累加。
简单的说,例如底下的字串
str="7680,992,7,0,1020"
做 htoa 之後就能变成像底下这样的字串:
map_string="110101010101010010101......"
而 e 就是其长度。
这东西基本上也只有地图系统会用到。
int cant_attack(object me,object tar)
这个是我为 tmi2_v3_改 新增的 /adm/simul_efun/attack.c 里面
的函数之一,主要是做 me 与 tar 能否进入战斗状态的判断,不能
的话就传回 1(代表 cant)
当这样的判断被写成全域函数时,则不管今天玩家是下 k mob,还
是 spell 法术 mob,还是 force 法术 mob,都只需要呼叫这个函
数来判断即可,相同的,管理者要控制今天 me 能不能攻击 mob,
也是修改这个函数即可,则所有的攻击指令就会全部适用。
string damage_str(int damage,int hp)
这个日後会改成 varargs 宣告。
这东西简单的说就是,当某一目标受到 damage 的伤害时,这时跟
它剩余的 hp 对照,就会得到一个比例。
比方剩余 hp 剩 1000 时,受到 500 的伤害,这时受伤比例就是
50%,damage_str 就会依据这个比例,决定要吐出什麽受伤讯息
switch(p)
{
case 0 : return "但是没有造成任何伤害。"; break;
case 1..40 : return "形成轻微的伤害。"; break;
.
.
varargs mixed defence_attack(object me,object tar,int damage,int hit_chance)
这个也是 attack.c 的函数,me 与 tar 在战斗状态时的闪格挡
处理函数。
我在这个函数里有建立基础的盾挡、武器挡两种类型的格挡方式
,使用者可参考。简单的说就是呼叫这个函数来专门处理闪格挡
,并依据它回传的阵列来判断是否受伤。
({tar 实际受到多少伤害, "相关讯息"})
比方 ({0, "但是被$O以盾挡开了"}), ({15,"形成轻微的伤害"})
varargs int normal_attack(object me,mixed attackers,int n)
这个就是当 me 与「它的战斗对象们」处於攻击状态时,me 会透
过 continue_attack 循环呼叫的函数,直到战斗结束才停止呼叫
attackers 就是 me 的战斗对象们,n 就是内回几次。
比方三连击,传统的做法可能如下
for(i=1;i<=3;i++)
normal_attack(me,attackers);
但采用内回的做法,normal_attack 呼叫一次即可:
normal_attack(me,attackers,
3);
normal_attack 每内回一次,defence_attack 就会呼叫一次,唯
有 defence_attack 是无法内回的,因为每一次的闪格挡都是独立
的。
string base_name(mixed obj)
简单的说如果一房间 ob = /d/area/wiz.c,那 base_name(ob) 就
传回 "/d/area/wiz"。
varargs string explode_base_name(string str)
如果一 str = "/d/area/wiz",则 explode_base_name(str) 就等
於 "/d/area
*wiz",也就是最後一个 / 会被替换为 *。
这是我为 tmi2_v3_改 新增的函数,它有什麽好处呢,就是方便使
用者对 base_name 出来的结果分离出[目录]与[档名]。
str="/d/area*wiz";
int s=strsrch(str,"*");
则此时:
[目录] = str[0..s-1]
[档名] = str[s+1..strlen(s)-1]+".c"
string to_chinese(string str)
string skill_name(string str)
string chinese_number(int n)
这三个函数写在 /adm/simul_efun/chinese.c,它们则会呼叫
/adm/daemons/chinesed.c 去读取储存的中文资料。
比方 to_chinese("knight") = "骑士",能做这样转换的原因就在
於 knight 有透过 chinese 指令设定其中文是 "骑士" 的缘故
> chinese knight==骑士
chinese: knight==骑士 设定 ok.
chinese_number 很简单:
int num=123456789;
string str=chinese_number(num);
则 str = "一亿两千三百四十五万六千七百八十九"
有兴趣者可参考 /adm/daemons/chinesed.c 里面看这函数怎麽写。
varargs int cat( string path, int start, int num )
一般简易的 cat 用法就是 cat("/d/area/wiz.c") 这样就可以马上
秀出 /d/area/wiz.c 这个档案的内容。
但是它也可以加参数,start 就是「要从哪一行开始 cat」,num就
是「要看多少行」,例如
::create();
seteuid(getuid(this_object()));
set("light",1);
set("short",HIY"\t\t\t神"HIW"之"HIG"国度\n"NOR);
set("long", @LONG
这里是神居住的地方,在这里遍布着许多美丽的花园,里头
开满了漂亮的花,还有几只蝴蝶在花丛里飞舞着。中间有一条小
河流,潺潺的流水声使你忘却了心头的烦闷!另外,还有几位天
神正在坐在一旁的石头上聊着天!
::create(); 就是 /d/area/wiz.c 的第 10 行,而上面也总共秀
出 10 行的资料。
varargs string extract( string str, int from, int to )
object first_inventory( mixed ob )
object next_inventory( object ob )
object shadowp( object ob ) { return query_shadowing( ob ); }
这几个从来没用过。
void log_file( string file, string text )
这个简单的说就是,比方 file="editing",那实际上档案是写
在 LOG_DIR+file,也就是 "/log/editing"。
所以它实际上是 write_file,只是它更针对了要将 text 写在哪
个指定目录内,并且会依据原本档案的大小做特殊的处理,比方原
本的纪录档已经很大了,就将其更名为 xxx.old,然後才写入一个
新的 xxx 档。
mixed copy(mixed var)
简单的说,它可以传回一个变数 var 的 copy。
var="123" copy(var) = "123"
var=({"1","2","3"}) copy(var) = ({"1","2","3"})
var=(["1":2,"3":4]) copy(var) = (["1":2,"3":4])
它的重要用途是,比方 mapping new_var=copy(var),则 new_var
与 var 之间是独立的、不会连动的。
string creator_file(string str)
从来没用过。
string data_dir(object obj)
string data_file(object obj)
varargs string user_data_dir(object obj, string name)
varargs string user_data_file(object obj, string name)
void assure_user_save_dir(object user)
void assure_save_dir(object user)
其实这五个写成 simul_efun 是蛮浪费的,因为上面会看到它们都
有接 object obj 或 object user,代表这五个平常其实很少在其
它物件会用到的东西,是可以写在 /std/user.c 或其相关继承档
里面的。
比方 me = laechan 这个玩家,则
data_dir(me)=/data/std/user
data_file(me)=/data/std/user/laechan
user_data_dir(me)=/data/std/user/l
user_data_file(me)=/data/std/user/l/laechan
上面的结果透过 running code 就可以跑出来:
write("data_dir(me)="+data_dir(me)+"\n"+
"data_file(me)="+data_file(me)+"\n"+
"user_data_dir(me)="+user_data_dir(me)+"\n"+
"user_data_file(me)="+user_data_file(me)+"\n");
後面两个函数就没用过了但也是 user data file 相关的函数。
void domain_log_file(string file, string message)
没用过这东西,domain 在 tmi-2 里面有时是指 /d 的意思,这点
我也是之後才知道的。
string domain_master( mixed domain )
这东西主要是用来找 /d 下面的物件,其控制的 d_master.c 档,
比方可透过在 /d/area 下各个物件档,透过 domain_master.c 可
找到它们的 d_master.c 档(一般是在 /d/area/adm/ 目录下)。
而且要该 d_master.c 档存在才算数。
d_master.c 顾名思义就是用来控制 /d 下面各目录的存取权用的。
string dump_socket_status()
varargs string dump_variable(mixed arg, int indent)
这两个东西没用过,dump 可以想成「要吐出什麽讯息」的意思。
後面那个蛮简单的,它就跟 identify 是类似的东西,把 identify
函数会做的事情透过 dump_variable 秀给你看。
比方底下的 running code
obs=({"1",2,({"3",4}),(["5":6])});
write("identify(obs)="+identify(obs)+"\n"+
"dump_variable(obs)="+dump_variable(obs)+"\n");
========== 程式执行区 ==========
identify(obs)=({ "1", 2, ({ "3", 4 }), ([ "5" : 6 ]) })
dump_variable(obs)=ARRAY:
[0] == "1"
[1] == #2
[2] ==
[0] == "3"
[1] == #4
[3] ==
["5"] == #6
========== 程式执行区 ==========
总之这东西很少用。
varargs int emote (object sender, string msg_self, string msg_others,
mixed target, string msg_target, string extra)
这东西已经没用了,目前 emote 都用 /adm/daemons/channeld.c
来控制。
然後从这东西就能看得出来,就算 tmi2_v3 有撰写 emote 系统,
使用者(例如我)依旧可以无视它,自己写新的 emote 与公频系统
,关键就在於你将系统写好後,要如何使它 work,并无视旧的系
统─即便今天旧的东西被写成了 simul_efun 一样可无视。
那为什麽我写好新的公频系统後不拿掉这个旧的 emote 呢?因为
或许有 tmi2_v3_改 的使用者会想用旧的不想用新的。
varargs mixed *exclude_array(mixed *array,int from, int to)
这东西简单的说就是
obs=({1,2,3,4,5});
obs=exclude_array(obs,1,3);
write(identify(obs)+"\n");
========== 程式执行区 ==========
({ 1, 5 })
========== 程式执行区 ==========
为什麽剩 1 跟 5,因为 obs[1..3] = ({2,3,4})
所以 exclude 的意思在这里就可以想成「排除掉元素 1..3」的意
思,也就是 ({1,2,3,4,5}) 排除掉 ({2,3,4}) 就是 ({1,5})
这东西我蛮少用的,因为一般都是明确知道 obs 里面有什麽,然後
做 obs-=({其中的元素}),不过有时会用得到它。
然後同样的,这里也能仿 exclude_array 写 exclude_string,这
函数用到的机会就比较多了。
/adm/simul_efun/existence.c
这里面宣告的一些函数都是「判断OOXX是否存在」的相关函数。
int file_exists(string file) 判断档案存不存在
int directory_exists(string dirname) 判断目录存不存在
int user_exists(string user) 判断一个玩家 id 存不存在
第三个我在 sanc 蛮少用的,但是 tmi2_v3_改 有机会用到。
例如在猎人的贪婪之岛游戏里,要判断「比诺透」这个玩家还有
没有活着:
if(user_exists("比诺透"))
object find_object_or_load (string str)
这个函数非常非常的重要而且常用。
find_object_or_load 顾名思义就是先在记忆体里面找 str 这个
物件档案有没有被载入,有的话就直接传回该物件,没有的话就
load 该物件。
也就是先做 find_object,找不到就做 load_object,而 load 一
个物件的方法就写在里面:
catch( call_other( str, "???" ) );
用 catch 包住就是即便 call_other 的时候产生错误也能无视。
string format_string (string format, mixed *variables)
这东西我几乎没用过。
string substr(string ostr1,string cstr1,string cstr2)
这东西是我新增的,而它其实就等於 replace_string。
string substr(string ostr1,string cstr1,string cstr2)
{
return replace_string(ostr1,cstr1,cstr2);
}
string no_ansi_color(string str)
比方 str = "$HIR$test$NOR$",那 no_ansi_color(str)="test"
string get_ansi_color(string str)
比方 str = "$HIR$test$NOR$",那 get_ansi_color(str)="
test"
这两个函数就是做这些处理用的。
varargs string Ctime(int t,int no_color)
用底下的 running code 来测
i=time();
write("ctime(i)="+ctime(i)+"\n"+
"Ctime(i)="+Ctime(i)+"\n"+
"Ctime(i,1)="+Ctime(i,1)+"\n");
========== 程式执行区 ==========
ctime(i)=Sat Jun 28 20:45:55 2014
Ctime(i)=
6/28 20:45(六)
Ctime(i,1)=6/28 20:45(六)
========== 程式执行区 ==========
Ctime 是 sanc 的 adm 写的函数,用习惯了所以也写进 tmi2 里
面,并加了一个 no_color 的参数。
然後 Ctime 可以透过之前介绍的 local_time 来更简化,新的版
本就会以 local_time 来处理。
varargs string format_time(int tm, int verbose)
这函数很好用,比方要知道 99999 秒到底是几天几小时几分几秒
write(format_time(99999)+"\n");
========== 程式执行区 ==========
1天 3小时 46分 39秒
========== 程式执行区 ==========
比方要 show 玩家已经发呆了几分几秒、玩家从创角色到现在已经
过了多久,都可以呼叫这个函数来 show。
varargs string intl_date_stamp( int time_flag )
这函数用都没用过。
ret = sprintf( "%d-%02d-%d", year, 1 + member_array( month, MONTHS ), day );
嘛,排出来大概是 西元-月-日,然後如果有给 time_flag,就再
show 出几点几分几秒,不然就只秀出 2014-06-28 这样。
它也算好用,但是应该再给使用者可以自订什麽分隔符号的参数,
例如 intl_date_stamp(0,"/") 那就秀出 2014/06/28 这样,或是
intl_date_stamp(-1,"-") 那就秀出 28-06-2014 这样。
使用者可根据这个概念自订适合自己 mud 的时间显示相关函数。
/*
varargs void get_char (string fun, int flag)
*/
这东西已经被 tmi2_v3 abort 掉了,而其实 efun 就有了只要呼
叫 efun 的就够了。
(因为 get_char 并不需要做什麽特殊的处理,反过来说需要做特
殊处理的话应该要使用 input_to)
varargs object get_object( string str, object player )
这东西我几乎没用过,不过从函数的内容来看应该是蛮好用的,它
甚至可能还比 find_object_or_load 好用。
不过我猜使用的时机多半是在 wiz 使用指令时。
简单的说,比方今天做 get_object(str),它的搜寻顺序依序就是
1.str="me" 时就传回自己
2.str 这 id 就是身上某物的 id 时就传回该物品
3.str="here" or "env" or "environment" 时就传回 environment(me)
4.str=某线上玩家的 id 时就传回该玩家
5.str=某线上生物的 living_name 时就传回该生物
6.真的都找不到时就将 str 视为物件档案,试着载入并传回该物件
(通常只有 wiz 会用到 5,6)
这东西在 /cmds/object/_data.c 可以找到,data 指令接的 str
就有这个特质,所以使用者才可以 data me、data here、..
more 指令理论上也应该要用 get_object。
varargs mixed get_objects( string str, object player, int no_arr )
就想成是 get_object 的多次呼叫版本,然後不需呼叫多次,只
要呼叫一次 get_objects 就可。
str 要依它指定的格式以 ":" 分隔。
几乎没用过,就不介绍哩。(因为有其它替代做法不一定要呼叫它)
varargs string get_stack( int x)
getoid(object obj)
int gettype (mixed item)
string strtype (mixed item)
int comptype (mixed item, mixed other)
int hiddenp( object ob )
以上几个从来没用过,我也不是很熟,节省时间,不介绍哩。
要判断一个东西的 type 我通常都用 stringp、mapp、pointerp、
等等的函数,甚至用 identify 也可。
有兴趣的可自行研究。
varargs string identify( mixed a, string indent )
这个函数非常的好用,我也很频繁地使用它,因为它可以把任何变
数变成以字串的形式显示出来,这样就不必花时间解析变数的内容
再做格式化输出,有时考量到效率问题以 identify 把变数转成字
串输出出来即可。
有兴趣的可自行用 running code 把任何变数塞进 identify 里面
再对照输出的结果,就知道它是做什麽的。
它最大的好处我认为是可以用来凭空生出 .o 档,我的意思就是说
,.o 档的产生不一定都只能靠 save_object 这个函数,它也可以
靠 write_file + identify 来办到。
string query_idle_string( object player, int verbose )
这东西用都没用过,它其实是 query_idle + format_time 的结合
,而通常我们需要知道一个玩家发呆多久时是在 "who" 的时候,
更多时候是需要知道玩家有没有断线、已断线多久。
所以这函数用到的时机是很少的,除非使用者的 mud 有很在意玩
家发呆了多久而且会经常显示出来这样,比方
> l
[/d/area/wiz ]
神之国度
这里是神居住的地方,在这里遍布着许多美丽的花园,里头
开满了漂亮的花,还有几只蝴蝶在花丛里飞舞着。中间有一条小
河流,潺潺的流水声使你忘却了心头的烦闷!另外,还有几位天
神正在坐在一旁的石头上聊着天!
明显出口有: whitetile, quad, shadow, 和 newbie.
神之仆人(servant) [已发呆 3 分 20 秒]
int index(mixed target, mixed *array, int offset)
这东西很少用到。它可以从 array 的指定位置开始找 target 这
个元素的位置。比方说今天 array 是一个 size 超过 10000 的阵
列,那我们每次找东西都得从位置 0 开始找的话太耗效率,反之,
若大略知道我们要找的东西差不多位於 5000 起的话
index(要找的东西,该size=10000的阵列,5000)
这样就可以从 5000 找起,找到了就会传回它的位置。
这东西很少用的原因是因为通常靠 member_array 就可以解决半数
以上的搜寻问题,剩下的就靠 for 或 foreach 或 while。
string int_string (int num)
这东西只有英文版 tmi2 用的到,可以把 2 转成 "two" 这样,
其它就以此类推。
varargs string iwrap(string str, int width, int indent)
这东西用都没用过。
/adm/simul_efun/mail_package.c
处理 mud 内的 mail 用的。没用过,有兴趣可自行研究。
static int m_str2(int mp, int sp)
蛮奇怪的一个 function,我很少看到 simul_efun 这样命名。
int match_string(string pattern, string source)
这函数我蛮少用的。用 running code 来试
write(match_string("abc","abc")+"\n"+
match_string("abc","abd")+"\n");
========== 程式执行区 ==========
1 <= abc = abc
0 <= abc != abd
========== 程式执行区 ==========
实在没啥意义啦我觉得,做 if(str1==str2) 不就好了..
int member_group(string user, string group)
这东西就是用来判断一个 user id 跟一个 group id 两者是不是
match。例如 "laechan" 今天是一个 admin
write(member_group("laechan","admin")+"\n");
========== 程式执行区 ==========
1 <= 就代表 laechan 确实是 admin
========== 程式执行区 ==========
要知道有哪些 group 只要 more /adm/etc/groups 就可以知道。
void mkdirs(string path)
这东西还蛮好用的,比方今天我们要建立 /x/xx/xxx/ 目录,只要
这样做
mkdirs("/x/xx/xxx");
它会判断如果没有 /x 目录就先建 /x 目录,建好後发现没有
/x/xx 目录就建 /x/xx 目录,之後再判断又没有 /x/xx/xxx 目
录就建 /x/xx/xxx 目录 这样。
不过用到的机会很少就是了。
int destruct(object destructee)
就是用来消灭一个已载入记忆体的物件用的,BJ4。
nomask varargs void shutdown(int code)
shutdown 时会呼叫的函数。
nomask varargs object snoop(object snooper, object snoopee)
nomask object query_snoop(object who)
nomask object query_snooping(object who)
做 snoop 时呼叫的函数。
nomask int exec(object to_obj, object from_obj)
没用过。
nomask int export_uid(object ob)
export 就是汇出的意思,汇出 ob 的 uid。没用过。
nomask int set_eval_limit(int num)
没用过。
以上几个都写在 /adm/simul_efun/overrides.c,它的意思就是它
想用自己写的 simul_efun 去 override(覆盖) efun,而需覆盖的
原因就是因为它想自订一些额外处理。
nomask int set_eval_limit(int num)
{
// 这一段就是它想做的额外处理判断
if ( getuid(previous_object()) != ROOT_UID ) return 0;
// 前置处理完就呼叫 efun 做原本这函数该做的事情
efun::set_eval_limit(num);
return 1;
}
所以假设 time 函数也是 efun,你想针对 time 函数做什麽额外
处理的话就把 time 函数写在 overrides.c 里面,比方
int time()
{
int t=efun::time();
return t-3600;
}
这样每次 time() 传回来的时间都会少 3600 秒。比方以刀剑神域
里面的 ALO 世界为例,现实是白天,游戏里实际上是晚上,就可以
修改 time() 函数来达到目的。
mixed *path_file(mixed full_path)
这东西没用过,刚看了才知道这东西跟 explode_base_name 是一样
的,用 running code 跑如下
tmp="/d/area/wiz";
write(identify(path_file(tmp))+"\n");
========== 程式执行区 ==========
({ "/d/area", "wiz" })
========== 程式执行区 ==========
所以不习惯 explode_base_name 的人也可以考虑 path_file 函数
,它一样可将 path 与 file 分离出来。
这就我说的,「很多东西我在知道之前我已经先写了,而且也在一
大堆物件都用了,然後才发现这个时就已经来不及了」的意思。
/adm/simul_efun/pluralize.c
/adm/simul_efun/pronouns.c
我不太清楚这两个是干嘛的。
不过这两个应该只有英文版的 tmi-2 用得到。
varargs string resolv_path(string cur, string newvalue)
这函数在写 wiz 可用的指令时还蛮常用的,简单的说就是,比方
你目前正在 /d/area 目录,data me 就会看到如下的东西
> data me
cwd : "/d/area"
那麽,当你下 more wiz.c 时,它如何判断是 /d/area/wiz.c 呢
? 就是用 resolv_path
resolv_path(me->query("cwd"),"wiz.c");
它就会去依据你的 cwd 参数,与後面的 wiz.c 参数,来解析後
得到 wiz.c 的完整档名是 /d/area/wiz.c
如果你 more ../README,它同样会拿 cwd 来跟 ../README 做解
析,得到你要 more 的目标是 /d/README 这个档。
这就是 resolv_path 的用途。後面的参数就叫做「相对档名」,
而前面的参数就叫做「绝对参考目录」,绝对+相对 就能得出正确
的完整档名,它就像是..
你的正确位置 = resolv_path("绝对参考座标","往右移两格")
类似这样的概念。
varargs void say(string msg, mixed exclude)
这函数值得一提的地方就是後面还可以加 exclude,所以它实际上
比 tell_room 更好用。
(我也是今天才知道 say 後面可以加 exclude,然後同样的,我在
知道前已经用 tell_room(env,...,({欲排除的对象})); 写了一堆
varargs void shout(string msg, mixed exclude)
同样的悲剧,今天才知道 shout 可以接 exclude。
mixed *slice_array(mixed *arr, int from, int to)
这东西没啥意义,要取得阵列中的 a..b 就直接取就好。
slice_array(obs,3,5) 跟直接 obs[3..5] 是一样的。
(正确的做法是 slice_array 应判断 size 及边界,才有写成函数
的价值)
/adm/simul_efun/system.c
这里面定义了一些可直接回传系统参数的函数。
string version() 传回 mud 版本资讯
string arch() 传回 mudos 执行在什麽作业系统的资讯
string mud_name() 传回 mud 的名字
int mud_port() 传回 mud 开在什麽 port (如 5000)
string mudlib_name() 传回这个 mud 使用的这份 mudlib 的 name
string mudlib_version() 传回这份 mudlib 的版本
int tail(string file)
这个从来没用过。
varargs void tc(string str, string col, object dude)
这个函数真的很不好,因为它的名字太短了。
而且内容更脑x,直接无视吧。
int tell_group (mixed file, string msg)
这东西很少用,非常少,而且它用了非常没效率的 read_file。
简单的说假设有个档案叫做你的好友名单,然後你要线上传讯息给
所有好友,file 就是指那个档案,它会把档案读进来看你有几个
好友,然後就把 msg 传给那些好友这样。
void tell_object(mixed ob, mixed msg)
这东西实际上就是在做 message("tell_object", msg + "", ob);
而且 mixed ob 代表可接复数个 ob。
message 就是 efun,它会依据第一个参数是什麽,来决定要执行
什麽样的讯息呈现。
varargs void tell_room(mixed room, string msg, mixed exclude)
tell_room 跟 say 一样的意思,不同之处就是 tell_room 可以指
定要 tell 给哪个 room。悲剧的就是,绝大部份的情况就是 tell
给呼叫主体所在的 room──这时候用 say 就够了。
varargs int show(object me,object tar,string msg,int damage)
这东西是 sanc 在用的函数,我在 tmi2_v3_改 也写了一个,它好
用的地方就是可以依所给定的 me 与 tar,自动解析 $N、$O 等字
串要 substr 成什麽,然後再 tell_room 出来,比方
show(me,tar,"$N用砂锅大的拳头打向$O",100);
这意思就是 $N 会替换成 me 的名字、$O 会替换成 tar 的名字,
而最後面接伤害数值的话,在显示该讯息的同时 tar 也会受到伤
害。
可自行 more /adm/simul_efun/tell_room.c 即可知。
理论上 say.c 也可以并入 tell_room.c,这个新的版本会做。
varargs string temp_file( string base, object obj )
很少用,只有少数指令会用到。
string tilde_path(string path, string name)
从来没用过。
/adm/simul_efun/un_article.c
/adm/simul_efun/un_pluralize.c
/adm/simul_efun/unart_indefinite.c
英文版 tmi-2 在用的。
mixed *uniq_array(mixed *arr)
这东西就类似说,arr 是一个阵列,然後我们希望复制一个跟 arr
一样的阵列 new_arr,而且不与 arr 有连动关系。
new_arr = uniq_array(arr);
大概是这样。用到的机会不多。
mapping unique_mapping(mixed *arr, string func, string var)
这函数很少用,不过跟上面很类似,只是不清楚 func 是干嘛的。
string *update_file(string file)
这个我从来没用过,它的意思也不是像它字面写的 update 啥。
string user_path(string name)
varargs mixed is_user_path (string path, string name)
这东西现在几乎没用了,/student 目录我甚至打算在 tmi2_v3_改
让它无效化了。
(因为会用到这东西通常也只有 wiz 指令时)
varargs int visible( object detectee_obj, object detector_obj )
这东西没用过,大抵上它的意思就是说,一个 detector 想要"看到"
一个 detectee,要判断「能不能看到」,就是用 visible 这个函数
来判断。
不过它的判断是写死的,如果要沿用这个函数名的话,里面的判断就
改成适合自己的 mud 就可,它就类似生活在三次元空间的人,看不到
四次元(wiz 看不到 adm)的人,为何看不到? 因为 visible 回传 0。
类似四次元 三次元
if( detectee_vis > detector_rank )
return 0; // detector can't see detectee.
/adm/simul_efun/vt100.c
这里面所有的函数几乎都用不太到,因为目前的连线软体几乎都能自
行调整一些显示了,而不需要 mud 针对 vt100 介面的使用者来做什
麽特别的调整。
varargs string wrap(string str, int width)
这东西只对英文句子有用(也就是以 , ? . 为分隔的句子),一串落
落长没有分行的英文长句,透过 wrap 就可以分行为指定宽度的段落
,它透过的就是 sprintf 内建的能力:
sprintf("%-=*s\n", width, str);
但是上面的 %-=*s\n 到底是啥意思? 我只能说 -= 就是你所想像的
那个 -= (以方 obs-=({xxx}) 的 -=),当 sprintf 里面有 -= 时,
它就类似在做一个递回的东西。
随便去 cnn 找一个 cnn 的英文,复制贴上到这里就变底下
Whalers say they've been catching and eating whales in the area for centuries. This year's hunting season, which began on June 20, is the first since an international court ordered Japan to end its controversial research whaling expedition in the Antarctic, after failing to find evidence the program had legitimate scientific value.
透过 wrap 宽度指定 58 的话就变底下
Whalers say they've been catching and eating whales in the area for
centuries. This year's hunting season, which began on June 20, is the first
since an international court ordered Japan to end its controversial
research whaling expedition in the Antarctic, after failing to find
evidence the program had legitimate scientific value.
至於为啥第二行特别长? 阿灾...XD
上面只适用英文,因为如果是中文段落的话它只认 , . ? 这些,中文段落字
与字之间是没有空白的。
void write(string msg)
这函数没啥好讲的
message("write", msg + "", this_player());
总之它就是交给 message 函数处理。
「理论上」,当然也可以在 simul_efun 自定 message 函数来实现
简繁转换,这个我有空再试试,它的做法就是之前提过的:
void message(string kind,string msg,mixed tars)
{
// 对 msg 做简繁转换的判断
msg=.......;
// 然後再 call efun 的 message
return efun::message(kind,msg,tars);
}
简繁转换的函数要上网找一下,这样就不需要动 mudos,但缺点就
是 simul_efun 的执行效率毕竟不如 efun。
string writef( string str, int n, int flags )
从来没用过。
simul_efun 大概就到这罗。
laechan
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.165.161.242
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/mud/M.1403922422.A.7BD.html
※ 编辑: laechan (1.165.161.242), 06/29/2014 17:08:02