# 炎黄群侠传 MUD - Technical Documentation ## Introduction 炎黄群侠传 (Yanhuang Heroes MUD) is a Chinese text-based multi-user dungeon (MUD) game built on the FluffOS v2019+ driver and mudcore framework v1.6+. The project implements a martial arts themed wuxia world using the LPC (Lars Pensjö C) programming language, inspired by traditional Chinese swordsmanship novels. The codebase supports multiple connection protocols including UTF-8 telnet (port 6666), GBK telnet (port 5566), and WebSocket (port 8888) for browser-based clients. This MUD features a comprehensive game system including room navigation, NPC interactions, combat mechanics, skill progression, equipment management, quest systems, and social features. The architecture leverages daemon processes for centralized service management, inheritable object types for code reuse, and a flexible room-based world structure. The game integrates modern features like MySQL database support, AI client connections, HTTP services, and network communication protocols while maintaining compatibility with classic MUD gameplay conventions. ## Core APIs and Functions ### Room System - Creating Game World Areas Rooms are the fundamental building blocks of the MUD world, defining locations players can navigate. ```lpc // /d/baituo/bridge.c inherit ROOM; void create() { set("short", "小桥"); set("long", @LONG 这是一座小竹桥,白驼山上的冰雪融化形成一条清澈的小 溪,从桥下缓缓流过。不时有顽皮的小鱼跃出水面,在阳光下 划出一条银白色的弧线。 LONG); set("outdoors", "baituo"); set("exits", ([ "north" : __DIR__"guangchang", "east" : __DIR__"xijie", ])); set("objects",([ __DIR__"npc/cungu" : 1, ])); setup(); replace_program(ROOM); } ``` ### NPC Creation - Non-Player Characters NPCs provide interaction, combat, and quest functionality throughout the game world. ```lpc // /clone/npc/killer.c #include inherit NPC; void create() { set_name("杀手", ({ "killer", "sha shou" }) ); set("gender", "男性" ); set("age", 20 + random(20)); set("long", "这是一个身材高大的江湖人,两臂粗壮,膀阔" "腰圆,看起来似乎不怀好意。\n" ); set("str", 25); set("con", 25); set("dex", 25); set("int", 25); set("combat_exp", 150000); set("attitude", "heroism"); set("chat_chance_combat", 15); set("chat_msg_combat", ({ "杀手骂道:你奶奶的,敢和我斗?不知道死字怎么写是么?\n", "杀手喝道:快把宝物交出来,我饶了你这条小命!\n", "杀手呵呵大笑:你遇到了老子我,那算是倒霉了!\n" }) ); set_skill("blade", 80); set_skill("dodge", 80); set_skill("unarmed", 80); set_skill("parry", 80); set_skill("wuhu-duanmendao", 80); set_skill("feiyan-zoubi", 80); map_skill("blade", "wuhu-duanmendao"); map_skill("parry", "wuhu-duanmendao"); set_temp("apply/damage", 25); set_temp("apply/attack", 50); set_temp("apply/defense", 50); setup(); carry_object("/clone/weapon/gangdao")->wield(); carry_object("/clone/cloth/cloth")->wear(); call_out("do_flee", 60); } void do_flee() { if (! living(this_object()) || is_fighting()) call_out("do_flee", 60); if (environment()) message_vision("$N东张西望的看了一会儿,拔腿溜走了。\n", this_object()); destruct(this_object()); } void unconcious() { message_vision(HIR "$N" HIR "嚎道:"好么!这个江湖上到底还" "是有比我狠的!"\n" NOR, this_object()); ::unconcious(); } ``` ### Master NPC with Teaching Abilities NPCs can be configured as masters who teach skills to players who meet requirements. ```lpc // /kungfu/class/duan/ba.c #include #include "duan.h" inherit NPC; inherit F_MASTER; void create() { set_name("巴天石", ({ "ba tianshi", "ba", "tianshi" })); set("title", "大理国护国三公" ); set("nickname", HIW "司空" NOR); set("long", @LONG 他是大理国三公之一。一个又瘦又黑的汉子,但他 的擅长轻功。 LONG); set("gender", "男性"); set("age", 46); set("class", "officer"); set("attitude", "friendly"); set("shen_type", 1); set("str", 30); set("int", 20); set("con", 25); set("dex", 25); set("max_qi", 3000); set("max_jing", 1800); set("neili", 3200); set("max_neili", 3200); set("jiali", 150); set("combat_exp", 1500000); set("score", 10000); set_skill("force", 180); set_skill("duanshi-xinfa", 180); set_skill("dodge", 220); set_skill("tiannan-bu", 220); set_skill("cuff", 160); set_skill("jinyu-quan", 160); set_skill("strike", 160); set_skill("wuluo-zhang", 160); set_skill("sword", 160); set_skill("duanjia-jian", 160); set_skill("parry", 160); set_skill("literate", 140); set_skill("martial-cognize", 160); map_skill("force", "duanshi-xinfa"); map_skill("dodge", "tiannan-bu"); map_skill("cuff", "jinyu-quan"); map_skill("strike", "wuluo-zhang"); map_skill("parry", "duanjia-jian"); map_skill("sword", "duanjia-jian"); prepare_skill("cuff", "jinyu-quan"); prepare_skill("strike", "wuluo-zhang"); create_family("段氏皇族", 15, "司空"); set("chat_chance_combat", 120); set("chat_msg_combat", ({ (: perform_action, "cuff.man" :), (: perform_action, "strike.bian" :), (: perform_action, "sword.jing" :), (: perform_action, "sword.lian" :), (: exert_function, "recover" :), (: exert_function, "powerup" :), })); setup(); carry_object("/d/dali/npc/obj/junfu")->wear(); carry_object("/clone/weapon/changjian")->wield(); add_money("silver", 10); } void attempt_apprentice(object ob) { if (! permit_recruit(ob)) return; command("smile"); command("say 世子殿下何需如此,只要有事吩咐在下一声便是。"); return; } ``` ### Weapon System - Creating Equippable Items Weapons provide combat bonuses and can be wielded by players and NPCs. ```lpc // /clone/weapon/bian.c #include inherit WHIP; void create() { set_name("羊鞭", ({ "bian", "yangbian","whip" })); set_weight(300); if (clonep()) set_default_object(__FILE__); else { set("unit", "柄"); set("long", "这是一柄普通的羊鞭,做工粗糙。\n"); set("value", 30); set("material", "leather"); set("wield_msg", "$N「唰」的一声从腰后抽出一柄$n握在手中。\n"); set("unwield_msg", "$N将手中的$n别回腰后。\n"); } init_whip(5); setup(); } ``` ### Armor System - Clothing and Protection Armor items provide defense bonuses when worn by characters. ```lpc // /clone/cloth/baipao.c #include #include inherit CLOTH; void create() { set_name(HIW "白袍" NOR, ({"bai pao", "pao"}) ); set_weight(2000); if( clonep() ) set_default_object(__FILE__); else { set("unit", "件"); set("long", "这是件轻纱制成的白色长袍。\n"); set("material", "silk"); set("armor_prop/armor", 8); set("value",100); } setup(); } ``` ### Beast/Monster Creation - Combat Encounters Beasts are simplified NPCs used for hunting and combat encounters. ```lpc // /clone/beast/caihuashe.c #include inherit SNAKE; void create() { set_name(HIC "菜花蛇" NOR, ({"caihua she", "caihua", "she"})); set("long", HIC "这是一只青幽幽的菜花蛇,头部呈椭圆形。\n" NOR); set("age", 1); set("str", 15); set("dex", 16); set("max_qi", 200); set("max_jing", 200); set("combat_exp", 1000); set("power", 8); set("item1", "/clone/quarry/item/sherou"); set("item2", "/clone/herb/shedan"); set_temp("apply/dodge", 80); set_temp("apply/defense", 80); set_temp("apply/unarmed_damage", 50); setup(); } ``` ### Socket Communication - Network Programming TCP/UDP socket support for external service integration and network features. ```lpc // /inherit/Socket.c #include #include #define STATE_CLOSED 0 #define STATE_CONNECTING 1 #define STATE_CONNECTED 2 #define STATE_LISTENING 3 nosave mapping Connections = ([]); nosave mapping DNSCache = ([]); nosave int Debug; // Function declarations protected void real_connect(int fd); protected void cleanup_connection(int fd); protected void on_receive(int fd, mixed data); protected void on_close(int fd); protected void on_connect(int fd); protected void on_resolve(string host, string addr, int key); void set_debug(int flag) { Debug = flag; } protected void debug(string msg) { if (Debug) { debug_message("[Socket] " + msg); } } protected void cleanup_connection(int fd) { if (Connections[fd]) { socket_close(fd); map_delete(Connections, fd); debug("Connection " + fd + " cleaned up"); } } // Override in subclass protected void on_receive(int fd, mixed data) { debug("Received from " + fd + ": " + data); } protected void on_close(int fd) { debug("Connection " + fd + " closed"); cleanup_connection(fd); } protected void on_connect(int fd) { debug("Connection " + fd + " established"); if (Connections[fd]) { Connections[fd]["state"] = STATE_CONNECTED; } } protected void real_connect(int fd) { mapping conn = Connections[fd]; string addr; int port, type, result; if (!conn) return; addr = conn["addr"]; port = conn["port"]; type = conn["type"]; if (type == STREAM) { result = socket_connect(fd, addr + " " + port, "receive_data", "connected"); } else { result = socket_connect(fd, addr + " " + port, "receive_data", 0); } if (result != EESUCCESS) { debug("Connect failed: " + socket_error(result)); cleanup_connection(fd); } } public int tcp_connect(string host, int port) { int fd = socket_create(STREAM, "receive_callback", "close_callback"); if (fd < 0) { debug("Failed to create TCP socket"); return -1; } Connections[fd] = ([ "type": STREAM, "host": host, "port": port, "state": STATE_CONNECTING, "protocol": "TCP" ]); if (DNSCache[host]) { Connections[fd]["addr"] = DNSCache[host]; real_connect(fd); } else { resolve(host, "on_resolve"); } debug("TCP connection " + fd + " created for " + host + ":" + port); return fd; } public int udp_connect(string host, int port) { int fd = socket_create(DATAGRAM, "receive_callback", "close_callback"); if (fd < 0) { debug("Failed to create UDP socket"); return -1; } Connections[fd] = ([ "type": DATAGRAM, "host": host, "port": port, "state": STATE_CONNECTING, "protocol": "UDP" ]); if (DNSCache[host]) { Connections[fd]["addr"] = DNSCache[host]; real_connect(fd); } else { resolve(host, "on_resolve"); } debug("UDP connection " + fd + " created for " + host + ":" + port); return fd; } public void send_data(int fd, mixed data) { int result; mapping conn = Connections[fd]; if (!conn) { debug("Cannot send data: invalid connection " + fd); return; } result = socket_write(fd, data); if (result != EESUCCESS) { debug("Send failed on " + fd + ": " + socket_error(result)); } } public void disconnect(int fd) { cleanup_connection(fd); } ``` ### MySQL Database Integration Database connectivity for persistent data storage and external service integration. ```lpc // /adm/daemons/mysqld.c inherit CORE_DB; varargs mixed update(object ob, string host, string db, string user) { #ifdef __PACKAGE_DB__ if (objectp(ob) && ob->query("id") && ob->query("password")) { if (stringp(host) && stringp(db) && stringp(user)) { DB::setConnection(([ "host":host, "database":db, "user":user, ])); } return DB::table("users")->where("username", ob->query("id"))->update(([ "password":ob->query("password"), "phone":ob->query("phone"), ])); } #else cecho("注意:数据库功能被禁用。"); return 0; #endif } varargs int register(object ob, string host, string db, string user) { #ifdef __PACKAGE_DB__ if (objectp(ob) && ob->query("id") && ob->query("password")) { mixed res; if (stringp(host) && stringp(db) && stringp(user)) { DB::setConnection(([ "host":host, "database":db, "user":user, ])); } if (DB::table("users")->where("username", ob->query("id"))->count()) { return 0; } res = DB::table("users")->insert(([ "username":ob->query("id"), "name":ob->query("surname")||"" + ob->query("purename"), "email":ob->query("id") + "@mud.ren", "phone":ob->query("phone"), "password":ob->query("password"), "activated_at":log_time(), "created_at":log_time(), ])); if (stringp(res)) { cecho(res); return 0; } else { cecho("提示:系统已自动在bbs.mud.ren注册账号,你可以使用游戏账号和密码登录社区。"); return 1; } } #else cecho("注意:数据库功能被禁用,无法注册论坛账号。"); return 0; #endif } ``` ### Global Definitions and Daemon Paths Essential constants and paths for game system integration. ```lpc // /include/globals.h (excerpt) #ifndef GLOBALS_H #define GLOBALS_H #ifndef __SENSIBLE_MODIFIERS__ #define protected static #define nosave static #endif // Game time configuration #define GAME_TIME(t) (t - 971000000) #define DATE_SCALE 60 // Important directories #define BACKUP_DIR "/backup/" #define COMMAND_DIR "/cmds/" #define CONFIG_DIR "/adm/etc/" #define DATA_DIR "/data/" #define HELP_DIR "/help/" #define LOG_DIR "/log/" #define QUEST_DIR "/adm/daemons/quest/" // Key daemons #define COMBAT_D "/adm/daemons/combatd" #define MYSQL_D "/adm/daemons/mysqld" #define LOGIN_D "/adm/daemons/logind" #define CHANNEL_D "/adm/daemons/channeld" #define QUEST_D "/adm/daemons/questd" #define SECURITY_D "/adm/daemons/securityd" // Standard object types #define ROOM "/inherit/room" #define NPC "/inherit/char/npc" #define ITEM "/inherit/item/item" #define WEAPON "/inherit/item/weapon" #define ARMOR "/inherit/item/armor" #define CLOTH "/inherit/item/cloth" #define SNAKE "/inherit/beast/snake" #endif ``` ### Combat System Constants Core combat mechanics definitions for attack and defense calculations. ```lpc // /include/combat.h #ifndef __COMBAT__ #define __COMBAT__ #define TYPE_REGULAR 0 #define TYPE_RIPOSTE 1 #define TYPE_QUICK 2 #define RESULT_DODGE -1 #define RESULT_PARRY -2 // Skill power calculation types #define SKILL_USAGE_ATTACK 1 #define SKILL_USAGE_DEFENSE 2 // Attack modes #define UNARMED_ATTACK 0 #define WEAPON_ATTACK 1 #define REMOTE_ATTACK 2 #endif ``` ### Admin Command Template Framework for creating privileged administrative commands. ```lpc // /cmds/test/test.c #include #include "test.h" inherit F_CLEAN_UP; void create() { seteuid(getuid()); } int main(object me, string arg) { // Security check if (!SECURITY_D->valid_grant(me, "(admin)")) return 0; write("\n"); /** * Test code here * Example usage in game: eval load_object("/cmds/test/test")->main(this_player(), "") */ return 1; } int help() { return 1; } ``` ### Game Configuration Driver configuration for server settings and runtime parameters. ```ini # config.ini (excerpt) name : 炎黃群俠傳 # Network ports external_port_1 : telnet 5566 external_port_2 : telnet 6666 external_port_3 : websocket 8888 # Paths mudlib directory : . websocket http dir : www log directory : /log include directories : /include:/mudcore/include # Core files master file : /adm/single/master simulated efun file : /adm/single/simul_efun global include file : # Error messages default fail message : [35m指令错误,请输入 help 查看游戏帮助。[0m default error message : [31m你发现事情不大对了,但是又说不上来。[0m # Runtime limits maximum array size : 30000 living hash table size : 2048 # Protocol support enable gmcp : 1 enable mssp : 1 enable msp : 1 ``` ## Use Cases and Integration The 炎黄群侠传 MUD serves as a comprehensive platform for creating immersive Chinese martial arts text adventures. Primary use cases include building expansive wuxia-themed worlds with interconnected rooms, designing complex NPC interactions with dialogue trees and quest chains, implementing robust combat systems with skill progression and equipment management, and creating social gameplay through channels and player interactions. The architecture supports both traditional MUD gameplay through telnet clients and modern web-based access via WebSocket connections. Integration patterns follow a daemon-based service architecture where centralized daemons (COMBAT_D, MYSQL_D, QUEST_D, etc.) provide shared functionality across the game world. Objects inherit from standard templates (ROOM, NPC, WEAPON, ARMOR) to ensure consistent behavior. The system uses LPC's unique features including mappings for key-value storage, function pointers for callbacks, and the inherit mechanism for code reuse. Developers can extend functionality by creating new inherit files in `/inherit/`, adding daemons to `/adm/daemons/`, implementing commands in `/cmds/`, and designing world content in `/d/` and `/clone/` directories. The modular design allows independent feature development while maintaining compatibility through the global include files and daemon interfaces. Database integration enables persistent storage and external service connectivity, making the MUD suitable for long-term player progression and community building.