精華區beta mud_sanc 關於我們 聯絡資訊
基礎 LPC 作者: Descartes of Borg 第一版: 23 april 1993 第二版: 25 may 1993 第八章: 物件資料型態 8.1 回顧 你現在應該能從你自己的物件中呼叫函式. 你也應該清楚, 至少在一開始物件載 入記憶體的時候, 你物件中的 create() (或 reset() ) 函式會被呼叫, 而你的 reset() 函式會一直被重複呼叫, 讓你可以寫些程式碼來更新你的房間狀況. 注 意一下, 你的物件中不一定要有這兩個函式. driver 會先檢查你的物件中有沒 有這些函式. 如果沒有, 也不會怎麼樣. 你也已經認識 void (無傳回值), int (整數), string (字串) 這三種資料型態. 8.2 物件是一種資料型態 在這一章裡面, 你將會認識一種更複雜的資料型態──物件. 一個物件變數指向 一個已經載入 driver 記憶體的真正物件. 宣告物件變數的方法跟宣告其他資料 型態的變數一樣: object ob; 不過它不同的地方在於你不能在它身上用 +、- 、+=、-=、* 、/ (把一隻怪物 除以另一隻怪物到底有啥意義 ? ). 而且, 像是 say() 和 write() 外部函式 只要字串或整數, 你就不能 write() 或 say() 它們 (再次聲明, 說一隻怪物 是啥意思 ? ). 但是你可以將它們用於其他 LPC 重要的外部函式上. 8.3 外部函式: this_object() 這個外部函式傳回一個物件, 是正在執行 this_object() 的物件. 換句話說, 在一個檔案裡, this_object() 就是你的檔案物件複製出去的拷貝或是繼承這個 檔案的其他檔案. 當你正在撰寫一個會被別的檔案繼承的檔案, this_object() 就很有用. 假設你正在寫你自己的 living.c , user.c 和 monster.c 會繼承 它, 但是 living.c 不可能會獨自使用, 它只用來被這兩個物件繼承. 你想要把 設定玩家等級的 set_level() 函式記錄下來, (但是你不想記怪物的). 你可能會這樣做: void set_level(int x) { if(this_object()->is_player()) log_file("levels", "foo\n"); level = x; } 既然 living.c 或 living.c 繼承的檔案都沒有定義 is_player(), 我們就假設 if(is_player()) 會導致一個錯誤, 因為 driver 在你的檔案裡、你繼承的 檔案中都找不到 is_player() 函式. 因為你的檔案是被別的檔案繼承之故, this_object() 讓你能使用最後成品中可能擁有 (或沒有) 的函式而不會出現錯 誤. 8.4 呼叫其他物件中的函式 這當然是向你介紹物件資料型態最重要的特色. 它讓我們能使用其他物件中的函 式. 前面的範例裡, 你已經能找出一個玩家的等級、減少他們身上的錢、他們有 多少可承受傷害點數. 有兩種方法可以呼叫其他物件中的函式: 物件->函式(參數) call_other(物件, "函式", 參數); 範例: this_player()->add_money("silver", -5); call_other(this_player(), "add_money", "silver", -5); 某些情形下 (很概略的說法) , 遊戲只是由玩家命令觸發的一連串函式呼叫. 當 一個玩家開始一串函式呼叫時, 這個玩家就是 this_player() 外部函式所傳回 的物件. 所以, 因為 this_player() 可以由觸發事件的人決定, 你要小心你用 this_player() 呼叫函式的地方在哪裡. 你通常會把它擺在最後一個重要的區域 函式── init() 裡 (我們已經提過 create() 和 reset() ). 8.5 區域函式: init() 任何時候, 一個活著的東西碰到一個物件 (進入一個新的房間, 或其他物件進入 同一個房間) , 就會呼叫此物件新遇到所有物件裡面的 init() 函式. 在此, 你 可以加上一些玩家可以使用的命令. 以下是一朵花的 init() 函式範例. void init() { ::init(); add_action("smell_flower", "smell"); } 上面呼叫 smell_flower() 函式. 所以你應該有個 smell_flower() 函式長得像 這樣: 1 int smell_flower(string str); /* 玩家動作的函式是整數型態 */ 2 3 int smell_flower(string str) { 4 if(str != "flower") return 0; /* 玩家聞的不是這朵花 */ 5 write("你聞了這朵花.\n"); 6 say((string)this_player()->query_cap_name()+"聞了聞花.\n"); 7 this_player()->add_hp(random(5)); 8 return 1; 9 } 第一行, 我們宣告函式. 第三行, 開始 smell_flower(). str 是跟在玩家命令之後的任何東西 (不包括 第一個空白字元). 第四行, 檢查玩家輸入的是否為 "smell flower". 如果玩家輸入的是 "smell cheese", 則 str 就是 "cheese". 如果聞的不是花, 就傳回 0, 讓 driver 知道不該呼叫這個函式. 如果玩家身上有塊乳酪, 乳酪也有個 smell 指令的話, driver 之後會呼叫乳酪的函式. driver 會持續呼叫同 樣是 smell 的命令, 直到有一個傳回 1 為止. 如果它們都傳回 0, 則玩 家就看到「什麼 ?」 第五行, 呼叫 write() 外部函式. write() 把傳入給它的字串印出來給 this_player() . 所以, 只要輸入 "smell flower" 的玩家都會看到「你聞 了這朵花.」 第六行, 呼叫 say() 外部函式. say() 印出聞花動作的字串, 我們需要呼叫 this_player() 的 query_cap_name() 函式. 這樣子碰上隱形的玩家會印出 「某個人」 (或像是隱形的東西), 而且會把第一個字元轉為大寫 (capitalize). 第七行, 我們呼叫 this_player() 物件中的 add_hp() 函式, 因為我們想在聞 了花之後對玩家作一點治療 (註: 別把這些程式碼寫在你的 mud 裡, 管理 mud 平衡的人會斃了你). 第八行, 我們把遊戲的控制交回給 driver, 傳回 1 讓 driver 知道它呼叫的 函式正確. 8.6 在你的房間加上物件 現在, 使用物件資料型態, 你可以把怪物加進房間裡面: void create() { ::create(); set_property("light", 3); set("short", "Krasna 廣場"); set("long", "歡迎來到 Praxis 鎮的中央廣場.\n"); set_exits( ({ "d/standard/hall" }), ({ "east" }) ); } void reset() { object ob; ::reset(); if(present("guard")) return; /* 如果已經有一位警衛, */ ob = new("/std/monster"); /* 就別再增加一位 */ ob->set_name("guard"); ob->set("id", ({ "guard", "town guard" }) ); ob->set("short", "鎮警衛"); ob->set("long", "它看守著 Praxis.\n"); ob->set_gender("male"); ob->set_race("human"); ob->set_level(10); ob->set_alignment(200); ob->set_humanoid(); ob->set_hp(150); ob->set_wielding_limbs( ({ "right hand", "left hand" }) ); ob->move(this_object()); } 現在, 大多數的 mud 在此都大不相同. 前面提過, 有的 mud 把這些東西寫在 一個獨立設定的怪物物件裡. 原始模式的 mud 最後要呼叫怪物物件中的 move() 來把它搬進房間 (this_object() ) 裡. 在精簡模式的 mud 裡, 你呼叫需要兩 個參數的 move_object() 外部函式, 這兩個參數是: 要搬動的物件和要放東西 進去的物件. 8.7 本章總結 行文至此, 你現在應該有相當的知識來撰寫一些很棒的東西. 當然, 我一直強調 你真的需要去閱讀如何在你 mud 寫程式的說明文件, 它們會詳細說明在什麼種 類的物件裡擁有哪些函式可以呼叫. 無論你對 mudlib 的知識有多少, 你已經有 足夠的知識了解如何給玩家一些額外的事情做, 像是聞聞花、貼東西之類的事. 現在你應該能忙於撰寫程式. 但是此刻, 事情看起來變得枯燥沉悶, 這表示你該 進入下一階段、更深入的時間到了. 現在讓你自己撰寫一個小區域. 儘量使用你 mud room.c 裡頭所有的特殊函式 (找找別人覺得用都用不到的冷僻文件) . 加 上一堆簡潔的動作. 創造一些含有魔力的武器, 其魔力會漸漸消失. 以上這些你 現在應該都能寫得出來. 一旦這些東西對你來說都變成例行公事, 就是你開始學 習中階課程的時候. 注意, 只有很少人能真正進入中階課程. 如果你全部都做完 , 我告訴你, 你在 mud 中能做到的領域只在少數. 這不僅是因為其他許多領域 很困難, 也因為有一些已經超越此領域的人充滿了傲慢, 而且極少傳播這些知識. 秘訣在於: 強迫你自己, 並想一些你覺得不可能做到的事. 如果你問某個人怎麼 做 X, 而他們跟你說那個不可能做到, 就自己想辦法利用實驗把它寫出來. 譯者: Spock of Final Frontier 98.Feb.2.