**************************************************************************************
                           巫师编程

1) 最简单的房间的撰写

最简单的房间是什么？就是里面什么都没有，机关，人物(npc)，物品，什么都没有
比如说就是一条路上的一
程序举例如下：（//表示注释）
// Room: /d/snow/eroad1.c      //程序开头注一下,说明是什么文件,在什么地方
inherit ROOM;                  //继承 ROOM 类
void create()           //  创建函数;在里面定义各种属性

        set("short", "黄土小径");      // 房间的 短描述
        set("long", @LONG              // 房间的长描述
这是一条普通的黄土小径，弯弯曲曲往东北一路盘旋上山，北边有
一间城隍庙，往西则是雪亭镇的街道。     //@LONG&LONG是一对宏,表示里面是字符串
 LONG
        );
        set("exits", ([ /* sizeof() == 3 */     // 设房间出口
  "northeast" : "/d/snow/eroad2",               // 不同的方向指令,跳转到
  "north" : "/d/snow/temple",                   // 不同的房间
  "west" : "/d/snow/sroad1",                    // 注意,不加 .c 后缀
]));
        set("outdoors", "snow");                // 是雪淳镇的室外
        setup();                                //不用管它,照抄就是
        replace_program(ROOM);

2)  房间的物品和门
最简单的房间说完了,就再复杂一点儿加上 物品定义,和物品拿枋?还有建个门吧
还是举例说明
// inn.c
#include
inherit ROOM;
string look_sign(object me);            // 函数原型定义
void create()

        set("short", "饮风客栈");
        set("long", @LONG
你现在正站在雪亭镇南边的一家小客栈里，这家客栈虽小，却是方圆
五百里内最负盛名的一家，客栈的主人据说是一位云游四海的仙人，如果
你的福缘深厚的话，也许可以在这里遇到他。除此之外，来自各地的旅人
都喜欢聚集在这里交换旅途上的见闻，你也可以在这里打听到许多有趣的
消息。靠近门口的地方有一块乌木雕成的招牌(sign)。
    西北边有一个红木门(door)，门上泛著一层白色的光晕，一种令人感
觉很有力量，又很柔和的光芒。
LONG
        );
        // This enables players to save this room as their startroom.
        set("valid_startroom", 1);        //使该房间可以成为下一次进来的地方
        set("item_desc", ([
                "sign": (: look_sign :),        // 物品(其实不是物品)描述
// 只是一个记号而已,玩家可以用 look sign 来看你的描述 , 不是实际存在的物品
//   冒号左边的是名称,右边的是描述 如 :
//  "pillar" : "石柱上刻著：剑气指天、剑心内敛、剑芒不显、剑神如电。"
// 玩家 look pillar 是,就会出来 后面跟的话
// 如果你想叫玩家look 时,去调一个函数,就后面跟一个 (: 函数名 :)
                "door": (: look_door, "northwest" :),
                // 这里调的就是look_door函数,参数是northwest
        ]) );
        set("exits", ([
                "east"          : "/d/snow/square",
                "up"            : "/d/snow/inn_2f",
                "northwest"     : "/d/wiz/entrance" ]) );
        // 下面是定义房间里的NPC, 这就是一个店小二啦
        set("objects", ([
                "/d/snow/npc/waiter" : 1 ]) );  // 后面的1, 就是一个的意思
        // 创建房间的门, 平时是关闭的
        create_door("northwest", "木门", "southeast", DOOR_CLOSED);
        setup();
        // 建一个公告板,是另一个地方定义的函数
        // To "load" the board, don't ever "clone" a bulletin board.
        call_other( "/obj/board/common_b", "???" );

// look sign时调用,根据玩家的级别返回描述
string look_sign(object me)     // me是一个对象,指向动作的主人
                                // 这里的me是参数,如果没有这个参数,
                                // 可以在函数里用
                                // object me; me = this_player();定

        if( wizardp(me) )       // wizardp(me) 是一个efun, 是mudos 定义的
                                // 判断me这个对象是否是巫师
                return "招牌写著：饮风客栈。旁边一排小字：庄思哑题。\n";
        else
                return "招牌写著：饮风客栈。\n";

3)  人物创作入门
每一个人物都需要单独的一个*.c文件,由其所在房间的源码调用.前面已经说过
一般来说,NPC放在npc各个地方的npc目录下,如 /d/snow/npc下是雪淳镇的npc
记住一点就是:NPC其实和玩家是一样的,只不过是电脑控制而已,
        玩家有的各项值它都有,而且比如说,fight的时候,它也会涨经验值的
        也会慢慢恢复. 所以它可以用command来执行命令.
举例说明:
::::::::::::::
fist_trainer.c
::::::::::::::
// trainer.c
inherit NPC;            // 继承 NPC类
void create()

        set_name("李火狮", ({ "trainer", "lee" }) );    //设NPC名字和中文名字
                               ^^^^^^^^^|^^^^^
                                        +-------就是有两个名字,哪个都可以
        set("title", "拳法教练");       // 头
        set("gender", "男性" );         // 性别
        set("age", 28);                 // 年龄
        set("str", 26);                 // str, int 都是天赋值
        set("int", 14);
        set("long",                     // 人物的长描述,当玩家look trainer时
                                        // 显示该描述
"李火狮是个孔武有力的大块头，他正在训练他的弟子们习练「柳家拳\n"
                "法」(liuh-ken)。\n" );
        set("combat_exp", 3000);        // 人物的实战经验
        set("attitude", "heroism");     // 好战态度
        set("force", 120);              // 内力值
        set("max_force", 120);          // 最大内力
        set("force_factor", 1);         // 一次发出多少点内力
        set("inquiry", ([               // 玩家ask 时的反应
                "here": "这里当然是淳风武馆，不然还是哪里？\n",
// 如上句, 玩家ask trainer about here 就会出后面的话
                "name": "在下姓李，名字就叫火狮，人称李教头的便是我。\n",
                "柳家拳法": "哦....说来惭愧，小弟这套拳法还没学得到家,
柳馆主就教我在这里传艺。\n"
        ]) );
        set_skill("unarmed", 30);       // 设置各项武功技能
        set_skill("liuh-ken", 20);
        set_skill("dodge", 30);
        map_skill("unarmed", "liuh-ken");       // enable 柳家拳法
        setup();

int recognize_apprentice(object ob)     // 接受玩家拜师时的反应

        if( (string)ob->query("family/family_name")=="封山剑派" ) return 1;
                        ^^^^^^^^^^^^|^^^^^^^^^^^^
                                    +---------------查询玩家的派别
        command("say 对不起，这位" + RANK_D->query_respect(ob) +
                                     ^^^^^^^^^^^|^^^^^^^^^^^^
                                                +---对象ob, 就是玩家,的头衔
"，您不是我们武馆的弟子。");
        return notify_fail( "李火狮不愿意教你拳法。\n");
               ^^^^^|^^^^^
                    +-------这是一个很有用的函数,就是给出错误信息

int accept_fight(object me)     // 接受玩家fight时调用

        if( (string)me->query("family/family_name")=="封山剑派" ) {
                command("say 进招吧。");
                return 1;
        }
        command("say 馆主吩咐过，不许和来这里的客人过招。");
        return 0;

4) 几个零散的问题
*******************************************
1. NPC怎么有货物？
*******************************************
        如店小二，在create()函数里定义
        set("vendor_goods", ([
                "匕首": "/obj/example/dagger",
                "酒": "/obj/example/wineskin",
                "包子": "/obj/example/dumpling",
                "鸡腿": "/obj/example/chicken_leg",
        ]) );
        增加一个list功能
        在init()里定义
void init()             // 当一个玩家进入同一环境时,调用

        object ob;
        ::init();
        if( interactive(ob = this_player()) && !is_fighting() ) {
            ^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^     ^^^^^^|^^^^^^^
                          +---判断玩家是否存在       +---相互是否处于战斗状态
               remove_call_out("greeting");
                call_out("greeting", 1, ob);
        }
        add_action("do_vendor_list", "list");   //增加一个list的动作,
                       // list时自动调do_vendor_list,是系统函数

*************************************************
2. 进门时,自动问好
*************************************************
init()中函数设置如上
另外写一个greeting函数
void greeting(object ob)

        if( !ob || environment(ob) != environment() ) return;
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^判断是否是同一个房间
       switch( random(3) ) {  // 随机问好
                case  0:
                        say( "店小二笑咪咪地说道：这位" +
                                RANK_D->query_respect(ob)
                                + "，进来喝杯茶，歇歇腿吧。\n");
                        break;
                case 1:
                        say( "店小二用脖子上的毛巾抹了抹手，说道：这位" +
                                RANK_D->query_respect(ob)
                                + "，请进请进。\n");
                        break;
                case 2:
                        say( "店小二说道：这位" + RANK_D->query_respect(ob)
                                +"，进来喝几盅小店的红酒吧，这几天\
                                才从窖子里开封的哟。\n");
                        break;
        }

********************************************
3. 平时随机动作和战斗中动作
********************************************
在create()函数里
        set("chat_chance", 25);         // 随机动作概率 25%
        set("chat_msg", ({
                "僵尸护法说道：我们茅山派实力最强！谁敢欺负我们？\n"
                "僵尸护法对你说道：小心我把你变成僵尸! \n",
                "僵尸护法对你念了一会咒，你不禁毛骨悚然起来...\n",
                (:random_move :)        // 随机移动
        }) );
        set("chat_chance_combat", 70);  // 战斗中随机动作概率
        set("chat_msg_combat", ({
                (: command("你敢惹我，追到天涯海角我都要杀了你！") :),
                (: cast_spell, "drainerbolt" :),
                (: cast_spell, "netherbolt" :),         //使用各种法术
                (: cast_spell, "feeblebolt" :),
                (: cast_spell, "invocation" :),
        }) );
********************************************
4. 根据玩家询问的信息作相应的动作
********************************************
杨掌柜为例:
在create()函数里:
        set("inquiry", ([
                "治伤": (: heal_me :),
                "疗伤": (: heal_me :),
                "开药": (: heal_me :),
        ]) );
再定义一个heal_me函数
string heal_me(object me)

        int ratio;
        ratio = (int)me->query("eff_kee") * 100 / (int)me->query("max_kee");
        if( ratio >= 100 )
                return "这位" + RANK_D->query_respect(me) +
                "，您看起来气色很好啊，不像有受伤的样子。";
        if( ratio >= 95 )
                return
        "哦....我看看....只是些皮肉小伤，您买包金创药回去敷敷就没事了。";

作相应的动作
*****************************************
5. 人物身上的物品和钱
*****************************************
在create()函数里
__DIR__是一个宏,表示当前目录,提高程序可移植性
        carry_object(__DIR__"obj/magic_book");  // 一般的物品
        carry_object(__DIR__"obj/spells_book");
        carry_object(__DIR__"obj/thin_sword")->wield(); // 武器可以装备
        carry_object(__DIR__"obj/pink_cloth")->wear();  // 衣服等可以穿上
        carry_object(__DIR__"obj/shoe")->wear();
        add_money("gold", 3);           // 钱用add_money函数

**************************************************************************************
