※ 引述《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