※ 引述《tenyfish (何时才有发言权?)》之铭言:
: 单纯回应L大
: 因为我虽然不是完全不懂LPMUD,但是不同版本的MUDLIB,
: 很多的资料夹分类,指令和sim efun用法还是有些不同,
: 像我讲的exit写法也是因为我当时写的东西都是用DS范本改写出来的
: DS感觉上为了让新人也能上手,很多物件的写法十分直觉。
: 例 set("exits/west",QR"002");
: 我可能会写set_exit("west","d/area/newbie/002");
: 我不是说我看不懂你的,只是我己经习惯用比较脑残的方式来写。
: 当然上面这种,看多了就适应了,倒不是什么大问题啦。
: 指令部份,TMI2是用More,我之前都在用about,
: 刚开会有一种武功全费的感觉,连recall DS里面都没在用。
: 所以其实我觉得你可以就你自己的方式来做注记说明文件,
: 等到很多人反应某项的使用再依使用者需求来增加。
: (如果你不介意大家都跑来问你的话)
本来打很长,后来决定简单讲。
我可以很直接的说,要把 tmi2_v3 改成 ds-like 对我来说一点也不困难
,抄袭是最简单的。因为 ds 也是 lpmud,就像如花跟林志玲都是人类,
理论上如花绝对可以整成林志玲。
但以 set_exit("west","d/area/newbie/002"); 与 set("exits/north")
来说,你真的觉得它们长怎样是很重要的事?
我比较在乎的是你有实际看过并理解 ds 的 set_exit 函数的内容吗?为
避免我们的交谈又没有交集,我刚刚下载了 ds mudlib,它的 domains 目
录就是 /d 目录,/domains/cave/room 下有个房间是这样写的
// /domains/cave/room/freezer.c
#include <lib.h> <= 你知道我光是要找这个 .h 档在哪里就找了多久吗
#include ROOMS_H <= 这跟 area.c 里的 area.h 是一样的意思
inherit LIB_ROOM; <= 然后见鬼的是在 lib.h 里还找不到 LIB_ROOM 这个定义
然后再逐层搜索才发现本体是 /lib/std/room.c
void create()
{
room::create();
SetNoClean(1);
SetProperties(([ "login" : ROOM_START ]));
SetShort( "The freezer");
SetLong( "The local freezer. Go down to leave.");
SetObviousExits("down");
SetExits( ([ "down" : ROOM_START ]) );
call_out("clean_room", MAX_NET_DEAD_TIME);
SetNoModify(1);
}
上面标亮绿色的全都是函数,我们就以 SetExits 这函数为例,
其本体是 /lib/exits.c
(我觉得很机车的一点是,LIB_ROOM 它是定义为 /lib/std/room.c
,但是 LIB_EXITS 它却定义为 /lib/exits.c,整人啊!)
// /lib/exits.c
mapping SetExits(mapping mp)
{
mixed room_or_arr, dir;
Exits = ([]);
foreach(dir, room_or_arr in mp)
{
if( arrayp(dir) )
{
string real_dir;
foreach(real_dir in dir)
{
if( arrayp(room_or_arr) )
AddExit(real_dir, room_or_arr...);
else
AddExit(real_dir, room_or_arr);
}
}
else
{
if( stringp(room_or_arr) )
AddExit(dir, room_or_arr);
else if( arrayp(room_or_arr) )
AddExit(dir, room_or_arr...);
}
}
return Exits;
}
(这跟我最近为货币系统的改动所做的事有何差别? 果然大家想法
都差不多)
结果它设出口的做法“又是呼叫函数 AddExit”,没关系再往下追
varargs mapping AddExit(string dir, string dest, function pre, function post)
{
if(!stringp(dir))
error("Bad argument 1 to AddExit().\n");
if(!stringp(dest))
error("Bad argument 2 to AddExit().\n");
dest = ResolveObjectName(dest);
Exits[dir] = ([ "room" : dest ]);
if( functionp(pre) )
Exits[dir]["pre"] = pre;
if( functionp(post) )
Exits[dir]["post"] = post;
return Exits[dir]; <= 我觉得这行是多余的,宣告改为 void 就够了
}
(本来还要继续 trace ResolveObjectName 的..算了先到这)
好了谜底解开了:最后用的是设定 mapping 资料的型式。
而且我能理解为什么它要这样子写。
而且我马上能在 tmi2_v3_改 照抄。(而且不用边看边抄)
而且它也给了我新的启发。(这对我来说是常有的事了)
但是我根本不想采用这种做法。(它的缺点显而易见)
你有这样子 trace 过吗?
看过 ds 后我真的觉得 tmi2_v3_改 对新手超级不亲和,要像 ds 这
样把底层的东西写到超级复杂,复杂到牺牲运作效能也无所谓,使用
者才会觉得表层的东西非常简单易用。
像我就是考虑到太多效能的问题才绑手绑脚。
但我还是宁愿以效能为主要考量。
ds tmi2_v3
============================================================
mapping Exits mapping data["exits"]
Exits[dir] data["exits"][dir]
Exits[dir]["room"] data["exits"][dir]
Exits[dir]["pre"] data["pre_exit_func"][dir]
============================================================
传统物品 虚拟物品
============================================================
mapping data mapping vobj_data[标头][编号]
data["short"] vobj_data[标头][编号]["name"]
data["value"] vobj_data[标头][编号]["value"]
============================================================
你能理解上面的东西,我们的交谈才会有交集,不然只是浪费时间,
你也只会越来越觉得 tmi2_v3_改 不好用、甚至就不想用了。
(pre_exit_func 的使用在 tmi2_v3 的 /cmds/std/_go.c 有,我是从
ds 的 "pre" 去推测它指的就是 pre_exit_func)
Laechan