发信人: jytjytjyt() 
整理人: zhangsf(2000-01-03 18:35:55), 站内信件
 | 
 
 
// /adm/daemons/vrm_server.c
 
 /************************************************
  * vrm_server.c                                 *
  * 虚拟的随机迷宫创造器 (Virtual Random Maze)   *
  *                                              *
  * by Find.                                     *
  *              网络游戏 天下 MUD.              *
  ************************************************/
 
 /******************************************************
  * 迷宫是一个游戏里经常要用到的东西,以前的迷宫都需要 *
  * 巫师一个房间一个房间地手工绘制,费时费力,而且一旦 *
  * 被玩家找出正确的线路,迷宫格局被泄漏,迷宫就不称其 *
  * 为迷宫了,所以巫师们都绞尽脑汁把迷宫设计的尽量复杂,*
  * 但再复杂的迷宫早晚也会被找到正确的路线,而且过于复 *
  * 杂难走的迷宫也使玩家感觉过于繁琐,降低乐趣。因此产 *
  * 生此想法。                                         *
  * 随机迷宫的产生算法尽量简单,迷宫的储存尽量节省记忆 *
  * 体,迷宫房间采用虚拟物件,处理灵活,迷宫房间只有在 *
  * 玩家走到时才会装进内存,而且迷宫房间也象普通的ROOM *
  * 一样当一段时间没有被参考到可以销毁节省记忆体,当整 *
  * 个迷宫一段时间没有被参考到可以被完全摧毁,下次再需 *
  * 要的时候会重新建立,又会产生一个新的迷宫。区域巫师 *
  * 写作随机迷宫只需规定一些预设的参数如迷宫的单边长、 *
  * 房间描述、出入口描述,几十个乃至几千个房间、路线时 *
  * 时不同的随机迷宫就建立好了,大大提高了区域写作效率 *
  * 和游戏的可玩性。                                   *
  * 此物件目前适合于随机的迷宫,即:迷宫内房间的描述基 *
  * 本相同,比如一片树林、一片坟地等,如要此物件创作完 *
  * 整的随机区域即有一定的情节、一定格局的区域,则需要 *
  * 根据自己的情况规定出迷宫内房间描述的一些规则,使相 *
  * 邻房间的描述变化合理,房间内物件与描述协调。如果愿 *
  * 意巫师可以只制作迷宫间的连接部分,而用几个迷宫组合 *
  * 成一个完全随机的区域,哈,那以后做巫师可轻松多了。 *
  * 目前本游戏使用的迷宫一般为单边长10至40,到底能做多 *
  * 大的迷宫我也不知道,下面对此有一个说明,要根据自己 *
  * 的服务器性能来讲,不过我想最普通的机器制作一个面积 *
  * 为100x100的迷宫应该也是一件轻松的事情。            *
  * 由于采用 virtual object,牵涉到一点安全问题,需要根*
  * 据自己的系统考量调整。                             *
  ******************************************************/
 
 #pragma optimize
 
 #define N		8
 #define S		4
 #define W		2
 #define E		1
 #define ALL		15
 
 /****************************************************
  * 迷宫的单边长最大值目前暂定为 100,由于随机迷宫的
  * 创造和操作比较耗费资源单边长 100 的迷宫'面积'就是
  * 100x100 等于 10000 个房间的一个迷宫,一般恐怕是用
  * 不到。一般的实时迷宫(实时迷宫是指在游戏运行过程
  * 中随时被 destruct 随着需要又会随时被创建的迷宫)的
  * 单边长以 10 到 50 之间为宜。如需创造巨型迷宫如有几
  * 万乃至十几万个房间的迷宫,应将创建工作放置于游戏启
  * 动时做,游戏启动的一段时间(比如20秒)禁止玩家登入。
  * 游戏通过定期重新启动来更新此迷宫。
  * 不知谁会用到这么大的迷宫。。。。。。
  ****************************************************/
 #define MAX_LONG	100
 
 // 只要能与其他房间相连的房间就肯定有一个入口.
 // 而可能的出口有三个.
 // define 这项规定房间最多只能有两个出口.
 // 也就是对于有三个出口的房间会随机关闭一个.
 // 不会使玩家由于看到四个方向都有出口很烦
 // 降低游戏乐趣。
 #define TWO_VALID_LEAVES
 
 inherit F_CLEAN_UP;
 
 class coordinate{ int x; int y; }
 class coordinate *newpath = ({}),/*待处理队列*/
 	enter,/* 入口坐标 */
 	leave;/* 出口坐标 */
 
 private string *valid_dirs = ({ "south","north","west","east" });
 private mapping reverse_dir = ([
 "north" : "south",
 "south" : "north",
 "west"  : "east",
 "east"  : "west",
 ]);
 
 // 全迷宫出口阵列.
 private mixed *all;
 
 /***************** 迷宫的一些预设特性:*****************/
 private int l;				// 迷宫的单边长
 private string *inherit_rooms = ({});	// 迷宫允许继承的档案名称
 private string entry_dir;		// 迷宫入口方向
 private string link_entry_dir;		// 迷宫入口与区域的连接方向
 private string link_entry_room;		// 迷宫入口所连接区域档案的文件名
 private string link_exit_dir;		// 迷宫出口与区域的连接方向
 private string link_exit_room;		// 迷宫出口所连接区域档案的文件名
 private string entry_short;		// 迷宫入口的短描述
 private string entry_desc;		// 迷宫入口的长描述
 private string exit_short;		// 迷宫出口的短描述
 private string exit_desc;		// 迷宫出口的长描述
 private string *maze_room_desc	= ({});	// 迷宫房间的长描述
 private string maze_room_short;		// 迷宫房间的短描述
 private int is_outdoors = 0;		// 迷宫房间是否为户外
 private string *maze_npcs = ({});	// 迷宫中的怪物
 /******************* ---- END ---- *********************/
 
 // 建立标记.
 private int maze_built = 0;
 
 // 重置全域变量.
 private void refresh_vars();
 
 // 建立迷宫
 private void create_maze();
 
 // 选择随机出口.
 private int random_out(int x,int y,int n);
 
 // 处理连接.
 private void link_to_north(int x,int y);
 private void link_to_south(int x,int y);
 private void link_to_west(int x,int y);
 private void link_to_east(int x,int y);
 
 // 绘制已建成迷宫的地图.
 private void paint_vrm_map();
 
 private string mroom_fname(int x,int y)
 { return sprintf("%s/%d/%d",base_name(this_object()),x,y);}
 
 
 private void refresh_vars() // 重置全域变量.
 {
 	newpath = ({});
 	all = 0;
 }
 
 // 对一些必设参数的合法性检查
 private int check_vars()
 {
 	int i,n;
 
 	if( (l < 5) || l > MAX_LONG )
 		return 0;
 
 	inherit_rooms -=({0});
 	if( !n = sizeof(inherit_rooms) )
 		return 0;
 
 	for(i=0;i<n;i++)
 		if(!stringp(inherit_rooms[i]) || (inherit_rooms[i] == ""))
 			return 0;
 
 	if(!stringp(entry_dir) || (member_array(entry_dir,valid_dirs) == -1)  )
 		return 0;
 /*
 	if(!stringp(link_entry_dir) || (member_array(link_entry_dir,valid_dir s) == -1) )
 		return 0;
 
 	if(!stringp(link_exit_dir) || (member_array(link_exit_dir,valid_dirs)  == -1) )
 		return 0;
 */
 	if(!stringp(link_entry_room) || (link_entry_room == ""))
 		return 0;
 
 	if(!stringp(link_exit_room) || (link_exit_room == ""))
 		return 0;
 
 	if(!stringp(entry_short) || (entry_short == ""))
 		return 0;
 
 	if(!stringp(exit_short) || (exit_short == ""))
 		return 0;
 
 	if(!stringp(entry_desc) || (entry_desc == ""))
 		return 0;
 
 	if(!stringp(exit_desc) || (exit_desc == ""))
 		return 0;
 
 	maze_room_desc -=({0});
 	if( !n = sizeof(maze_room_desc) )
 		return 0;
 
 	for(i=0;i<n;i++)
 		if(!stringp(maze_room_desc[i]) || (maze_room_desc[i] == ""))
 			return 0;
 
 	if(!stringp(maze_room_short) || (maze_room_short == ""))
 		return 0;
 
 	return 1;
 }
 
 private int random_out(int x,int y,int n) // 选择随机出口函数.
 {
 	int *outs = ({}), retn = 0;
 	class coordinate temp;
 
 	// The west room is (x-1,y)
 	if( n&W
 	&& ((x-1) >= 0)
 	&& !all[x-1][y] )
 	{
 		temp = new(class coordinate);
 		temp->x = x-1;
 		temp->y = y;
 
 		// 西面的房间不在待处理列表 newpath 中.
 		//if( member_array(temp,newpath) == -1 )
 			outs += ({ W });
 	}
 
 	// The east room is (x+1,y)
 	if( n&E
 	&& ((x+1) < l)
 	&& !all[x+1][y] )
 	{
 		temp = new(class coordinate);
 		temp->x = x+1;
 		temp->y = y;
 
 		// 东面的房间不在待处理列表 newpath 中.
 		//if( member_array(temp,newpath) == -1 )
 			outs += ({ E });
 	}
 
 	// The south room is (x,y-1)
 	if( n&S
 	&& ((y-1) >= 0)
 	&& !all[x][y-1] )
 	{
 		temp = new(class coordinate);
 		temp->x = x;
 		temp->y = y-1;
 
 		// 南面的房间不在待处理列表 newpath 中.
 		//if( member_array(temp,newpath) == -1 )
 			outs += ({ S });
 	}
 
 	// The north room is (x,y+1)
 	if( n&N
 	&& ((y+1) < l)
 	&& !all[x][y+1] )
 	{
 		temp = new(class coordinate);
 		temp->x = x;
 		temp->y = y+1;
 
 		// 北面的房间不在待处理列表 newpath 中.
 		//if( member_array(temp,newpath) == -1 )
 			outs += ({ N });
 	}
 
 #ifdef TWO_VALID_LEAVES
 	// 如果有三个出口,随机关闭一个.
 	if(sizeof(outs) >= 3)
 		outs -= ({ outs[random(sizeof(outs))] });
 #endif
 
 	for(int i=0;i<sizeof(outs);i++)
 		retn |= outs[i];
 
 	return retn;
 }
 
 private void create_maze()
 {
 	int i;
 	class coordinate *valid_leaves=({}),temp;
 
 	refresh_vars(); // 重置全域变量.
 	if( !check_vars() )   // 对一些预设变量进行检查。
 		return;
 
 	// 1.确定迷宫单边长.
 	all = allocate(l);
 	for(i=0;i<l;i++)
 		all[i] = allocate(l);	// 建立数组.
 
 	enter = new(class coordinate);
 
 	switch (entry_dir)
 	{
 		case "south":
 			// enter 入口坐标.
 			enter->x = to_int(l/2); // 取中迷宫比较平衡。
 			enter->y = 0;
 			all[enter->x][enter->y] |= S;
 			break;
 		case "north":
 			enter->x = to_int(l/2);
 			enter->y = l-1;
 			all[enter->x][enter->y] |= N;
 			break;
 		case "west":
 			enter->y = to_int(l/2);
 			enter->x = 0;
 			all[enter->x][enter->y] |= W;
 			break;
 		case "east":
 			enter->y = to_int(l/2);
 			enter->x = l-1;
 			all[enter->x][enter->y] |= E;
 			break;
 	}
 
 	// 存入待处理队列.
 	newpath += ({ enter });
 
 	// 进入主循环.
 	do
 	{
 		int x,y,out,numb;
 
 		// 进行一些监测与初始化.
 		if( !(numb=sizeof(newpath)) )
 			continue;
 		numb = random(numb);
 		reset_eval_cost();
 		x = newpath[numb]->x;
 		y = newpath[numb]->y;
 
 		// 如果有三个可能的出口随机关闭一个出口:
 		out = ALL^(all[x][y]);
 		out = random_out(x,y,out);
 
 		if(!out) // 没有可能的出口了.
 		{
 			newpath -= ({ newpath[numb] });
 			continue;
 		}
 
 		// 处理连接.
 		if(out&W) link_to_west(x,y);
 		if(out&E) link_to_east(x,y);
 		if(out&N) link_to_north(x,y);
 		if(out&S) link_to_south(x,y);
 
 		// 当前房间处理完毕.
 		newpath -= ({ newpath[numb] });
 	}
 	while (sizeof(newpath));
 
 	switch (entry_dir)
 	{
 		case "west":
 			for(i=0;i<l;i++)
 				if(all[l-1][i])
 				{
 					temp = new(class coordinate);
 					temp->x = l-1;
 					temp->y = i;
 					valid_leaves += ({temp});
 				}
 			break;
 		case "east":
 			for(i=0;i<l;i++)
 				if(all[0][i])
 				{
 					temp = new(class coordinate);
 					temp->x = 0;
 					temp->y = i;
 					valid_leaves += ({temp});
 				}
 			break;
 		case "south":
 			for(i=0;i<l;i++)
 				if(all[i][l-1])
 				{
 					temp = new(class coordinate);
 					temp->x = i;
 					temp->y = l-1;
 					valid_leaves += ({temp});
 				}
 			break;
 		case "north":
 			for(i=0;i<l;i++)
 				if(all[i][0])
 				{
 					temp = new(class coordinate);
 					temp->x = i;
 					temp->y = 0;
 					valid_leaves += ({temp});
 				}
 			break;
 	}
 
 	if( !(i=sizeof(valid_leaves)) ) // 没有出口 须重新建立
 	{
 		call_other(this_object(),"create_maze");
 		return;
 	}
 
 	if(i == 1)
 		leave = valid_leaves[0];
 	else
 		leave = valid_leaves[random(i)]; // 随机选一个.
 
 	switch (entry_dir)
 	{
 		case "south":
 			all[leave->x][leave->y] |= N;
 			break;
 		case "north":
 			all[leave->x][leave->y] |= S;
 			break;
 		case "west":
 			all[leave->x][leave->y] |= E;
 			break;
 		case "east":
 			all[leave->x][leave->y] |= W;
 			break;
 	}
 
 	// 迷宫创建完毕。
 	maze_built = 1;
 
 	// 绘制完成的迷宫地图。
 	// 地图文件为同目录下同名的'.map' 文件,
 	// 绘制地图也许可利于区域巫师的工作。
 	// 如需要可开放物件对于本目录的'写'。
 	//paint_vrm_map();
 }
 
 private void link_to_west(int x,int y)	// The west room is (x-1,y)
 {
 	class coordinate temp;
 	// can't link. 当前房间已经是最西面的房间了.
 	if( (x-1) < 0 )
 		return;
 
 	temp = new(class coordinate);
 	temp->x = x-1;
 	temp->y = y;
 
 	// 西面的房间已经于 path 中,或者 已在待处理列表 newpath 中.
 	if(all[temp->x][temp->y] /*|| member_array(temp,newpath)*/)
 		return;
 
 	all[x][y] |= W;
 	all[temp->x][temp->y] |= E;
 	newpath += ({temp});
 }
 
 private void link_to_east(int x,int y)	// The east room is (x+1,y)
 {
 	class coordinate temp;
 	// can't link. 当前房间已经是最东面的房间了.
 	if( (x+1) >= l )
 		return;
 
 	temp = new(class coordinate);
 	temp->x = x+1;
 	temp->y = y;
 
 	// 东面的房间已经于 path 中,或者 已在待处理列表 newpath 中.
 	if(all[temp->x][temp->y] /*|| member_array(temp,newpath)*/)
 		return;
 
 	all[x][y] |= E;
 	all[temp->x][temp->y] |= W;
 	newpath += ({temp});
 }
 
 private void link_to_south(int x,int y)	// The south room is (x,y-1)
 {
 	class coordinate temp;
 	// can't link. 当前房间已经是最南端的房间了.
 	if( (y-1) <0 )
 		return;
 
 	temp = new(class coordinate);
 	temp->x = x;
 	temp->y = y-1;
 
 	// 南端的房间已经于 path 中,或者 已在待处理列表 newpath 中.
 	if(all[temp->x][temp->y] /*|| member_array(temp,newpath)*/)
 		return;
 
 	all[x][y] |= S;
 	all[temp->x][temp->y] |= N;
 	newpath += ({temp});
 }
 
 private void link_to_north(int x,int y)	// The north room is (x,y+1)
 {
 	class coordinate temp;
 	// can't link. 当前房间已经是最北端的房间了.
 	if( (y+1) >= l )
 		return;
 
 	temp = new(class coordinate);
 	temp->x = x;
 	temp->y = y+1;
 
 	// 北端的房间已经于 path 中,或者 已在待处理列表 newpath 中.
 	if(all[temp->x][temp->y] /*|| member_array(temp,newpath)*/)
 		return;
 
 	all[x][y] |= N;
 	all[temp->x][temp->y] |= S;
 	newpath += ({temp});
 }
 
 // 绘制已建成迷宫的地图.
 private void paint_vrm_map()
 {
 	string hor = "─" ,ver = "│  ",room = "◎",sroom = "●";
 	int x,y;
 	string output = "",map_file;
 
 	for(y=(l-1);y>=0;y--)
 	{
 		reset_eval_cost();
 
 		output += sprintf("y=%-3d: ",y);
 		for(x=0;x<l;x++)
 		{
 			output += sprintf("%s",
 				(( (x==enter->x) && (y==enter->y))
 				|| ( (x==leave->x) && (y==leave->y) ))?
 				sroom:room);
 
 			if( (all[x][y])&E ) // have east
 				output += hor;
 			else
 				output += "  ";
 		}
 
 		output += "\n";
 		output += "       ";
 		for(x=0;x<l;x++)
 		{
 			if( (all[x][y])&S ) // have south
 				output += ver;
 			else
 			output += "    ";
 		}
 		output += "\n";
 	}
 
 	map_file = sprintf( "%s.map",base_name(this_object()) );
 	write_file(map_file,output,1);
 }
 
 nomask int clean_up()
 {
 	string fname;
 	int x,y;
 	object *maze_objs = ({}),link_room;
 
 	if(!maze_built)
 	{
 		destruct(this_object());
 		return 0;
 	}
 
 	fname = base_name(this_object());
 
 	if( objectp(link_room = find_object(sprintf("%s/entry",fname))) )
 	{
 		link_room->clean_up();
 		if( objectp(link_room) )
 			return 1;
 	}
 
 	if( objectp(link_room = find_object(sprintf("%s/exit",fname))) )
 	{
 		link_room->clean_up();
 		if( objectp(link_room) )
 			return 1;
 	}
 
 	for(x=0;x<l;x++)
 		for(y=0;y<l;y++)
 			if(objectp(find_object(sprintf("%s/%d/%d",fname,x,y))))
 				maze_objs += ({find_object(sprintf("%s/%d/%d",fname,x,y))});
 
 	maze_objs->clean_up();
 	maze_objs -= ({0});
 
 	if(sizeof(maze_objs))
 		return 1;
 	else
 	{
 		destruct(this_object());
 		return 0;
 	}
 }
 
 // 巫师可以 update 区域迷宫主物件强制更新迷宫,
 // 但此时迷宫中的玩家就要去 VOID 了。
 void remove(string euid)
 {
 	string fname = base_name(this_object());
 	object m_room;
 	int x,y;
 
 	for(x=0;x<l;x++)
 		for(y=0;y<l;y++)
 			if(objectp(m_room = find_object(sprintf("%s/%d/%d",fname,x,y))))
 				destruct(m_room);
 	if(find_object(sprintf("%s/entry",fname)))
 		destruct(sprintf("%s/entry",fname));
 	if(find_object(sprintf("%s/exit",fname)))
 		destruct(sprintf("%s/exit",fname));
 }
 
 /**** 以下是预设迷宫参数的接口函数 ****/
 // 迷宫的单边长
 void set_maze_long(int mlong)
 {
 	if(!intp(mlong))
 		return;
 
 	// 最小为 5,再小了没什么意义。
 	if( (mlong < 5) || mlong > MAX_LONG )
 		return;
 
 	l = mlong;
 }
 
 // 迷宫房间所继承的物件的档案名称。
 void set_inherit_room( mixed rooms )
 {
 	if(stringp(rooms))
 	{
 		// 此档案是否存在
 		if(file_size(sprintf("%s.c",rooms)) > 0)
 			inherit_rooms = ({ rooms });
 		return;
 	}
 
 	else if(arrayp(rooms))
 	{
 		foreach(string f in rooms)
 		{
 			if(!stringp(f) || f == "")
 				return;
 			if(file_size(sprintf("%s.c",f)) <= 0)
 				return;
 		}
 		inherit_rooms = rooms;
 		return;
 	}
 
 	return;
 }
 
 // 入口方向(出口在对面)
 void set_entry_dir(string dir)
 {
 	if(!stringp(dir))
 		return;
 
 	// 入口方向的合法性检查.
 	if(member_array(dir,valid_dirs) == -1)
 		return;
 
 	entry_dir = dir;
 }
 
 //入口与区域的连接方向
 void set_link_entry_dir(string dir)
 {
 	if(!stringp(dir) || dir == "")
 		return;
 
 	link_entry_dir = dir;
 }
 
 // 迷宫入口所连接区域档案的文件名
 void set_link_entry_room(string lroom)
 {
 	if(!stringp(lroom) || lroom == "")
 		return;
 
 	if(file_size(sprintf("%s.c",lroom)) <= 0)
 		return;
 
 	link_entry_room = lroom;
 }
 
 //出口与区域的连接方向
 void set_link_exit_dir(string dir)
 {
 	if(!stringp(dir) || dir == "")
 		return;
 
 	link_exit_dir = dir;
 }
 
 // 迷宫出口所连接区域档案的文件名
 void set_link_exit_room(string lroom)
 {
 	if(!stringp(lroom) || lroom == "")
 		return;
 
 	if(file_size(sprintf("%s.c",lroom)) <= 0)
 		return;
 
 	link_exit_room = lroom;
 }
 
 // 迷宫入口的短描述
 void set_entry_short(string desc)
 {
 	if(!stringp(desc) || desc == "")
 		return;
 
 	entry_short = desc;
 }
 
 // 迷宫入口的长描述
 void set_entry_desc(string desc)
 {
 	if(!stringp(desc) || desc == "")
 		return;
 
 	entry_desc = desc;
 }
 
 // 迷宫出口的短描述
 void set_exit_short(string desc)
 {
 	if(!stringp(desc) || desc == "")
 		return;
 
 	exit_short = desc;
 }
 
 // 迷宫出口的长描述
 void set_exit_desc(string desc)
 {
 	if(!stringp(desc) || desc == "")
 		return;
 
 	exit_desc = desc;
 }
 
 //迷宫房间的短描述
 void set_maze_room_short(string desc)
 {
 	if(!stringp(desc) || desc == "")
 		return;
 
 	maze_room_short = desc;
 }
 
 //迷宫房间的描述,如果有多条描述,制造每个房
 //间的时候会从中随机选择一个。
 void set_maze_room_desc(mixed desces)
 {
 	if(stringp(desces))
 	{
 		maze_room_desc = ({ desces });
 		return;
 	}
 
 	if(arrayp(desces))
 	{
 		foreach(string desc in desces)
 			if(!stringp(desc))
 				return;
 		maze_room_desc = desces;
 		return;
 	}
 }
 
 // 迷宫房间是否为户外房间
 void set_outdoors(int outd)
 {
 	if(!intp(outd))
 		return;
 
 	if(outd)
 		is_outdoors = 1;
 }
 
 // 迷宫中的怪物
 void set_maze_npcs(mixed npc)
 {
 	if(stringp(npc))
 	{
 		// 此档案是否存在
 		if(file_size(sprintf("%s.c",npc)) > 0)
 			maze_npcs = ({ npc });
 		return;
 	}
 
 	else if(arrayp(npc))
 	{
 		foreach(string f in npc)
 		{
 			if(!stringp(f) || f == "")
 				return;
 			if(file_size(sprintf("%s.c",f)) <= 0)
 				return;
 		}
 		maze_npcs = npc;
 		return;
 	}
 
 	return;
 
 }
 
 /**** 以上是预设迷宫参数的接口函数 ****/
 
 // 创造迷宫房间,由 VIRTUAL_D 调用。
 nomask object query_maze_room(string str)
 {
 	int random_rate = 20;	// 房间内放置 npc 的可能性
 	int idx,x,y,exits;
 	object ob;
 	string f;
 
 	if( previous_object() && (geteuid(previous_object()) != ROOT_UID) )
 		return 0;
 
 	if(!stringp(str) || str == "")
 		return 0;
 
 	if(!maze_built)	// 迷宫未建立
 		create_maze();
 	if(!maze_built)
 		return 0;
 
 	if(str == "entry")	// 迷宫入口房间
 	{
 		f = inherit_rooms[random(sizeof(inherit_rooms))];
 
 		ob = new(f);
 		if(!ob)
 			return 0;
 		ob->set("virtual_room",1);
 		ob->set("short",entry_short);
 		ob->set("long",entry_desc);
 		if(is_outdoors)
 			ob->set("outdoors",1);
 		ob->set(sprintf("exits/%s",link_entry_dir),link_entry_room);
 		ob->set(sprintf("exits/%s",reverse_dir[entry_dir]),mroom_fname(enter ->x,enter->y));
 		if( sizeof(maze_npcs) && (random(100) <= random_rate) )
 		{
 			ob->set("objects",([
 	maze_npcs[random(sizeof(maze_npcs))] : 1,
 ]));
 			ob->setup();
 		}
 		return ob;
 	}
 
 	if(str == "exit")	// 迷宫出口房间
 	{
 		f = inherit_rooms[random(sizeof(inherit_rooms))];
 
 		ob = new(f);
 		if(!ob)
 			return 0;
 
 		ob->set("virtual_room",1);
 		ob->set("short",exit_short);
 		ob->set("long",exit_desc);
 		if(is_outdoors)
 			ob->set("outdoors",1);
 		ob->set(sprintf("exits/%s",link_exit_dir),link_exit_room);
 		ob->set(sprintf("exits/%s",entry_dir),
 			mroom_fname(leave->x,leave->y));
 		if( sizeof(maze_npcs) && (random(100) <= random_rate) )
 		{
 			ob->set("objects",([
 	maze_npcs[random(sizeof(maze_npcs))] : 1,
 ]));
 			ob->setup();
 		}
 		return ob;
 	}
 
 	idx = member_array('/', str);
 	if( idx == -1 )
 		return 0;
 
 	if(!sscanf(str[0..idx-1],"%d",x))
 		return 0;
 	if(!sscanf(str[idx+1..],"%d",y))
 		return 0;
 
 	if( !exits = all[x][y] )
 		return 0;
 
 	f = inherit_rooms[random(sizeof(inherit_rooms))];
 	ob = new(f);
 	if(!ob)
 		return 0;
 
 	ob->set("virtual_room",1);
 	ob->set("short",maze_room_short);
 	ob->set("long",maze_room_desc[random(sizeof(maze_room_desc))]);
 	if(is_outdoors)
 		ob->set("outdoors",1);
 
 	if(exits&W)
 		ob->set("exits/west",mroom_fname(x-1,y));
 	if(exits&E)
 		ob->set("exits/east",mroom_fname(x+1,y));
 	if(exits&N)
 		ob->set("exits/north",mroom_fname(x,y+1));
 	if(exits&S)
 		ob->set("exits/south",mroom_fname(x,y-1));
 
 	if( (x == enter->x) && (y == enter->y) )
 		ob->set(sprintf("exits/%s",entry_dir),
 			sprintf("%s/entry",base_name(this_object())));
 	if( (x == leave->x) && (y == leave->y) )
 		ob->set(sprintf("exits/%s",reverse_dir[entry_dir]),
 			sprintf("%s/exit",base_name(this_object())));
 
 	if( sizeof(maze_npcs) && (random(100) <= random_rate) )
 	{
 		ob->set("objects",([
 	maze_npcs[random(sizeof(maze_npcs))] : 1,
 ]));
 		ob->setup();
 	}
 
 	return ob;
 }
 
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.74.177.246]
  | 
 
 
 |