作者laechan (小太保)
看板mud_sanc
标题[转载] 梦幻七域(DS)使用的区域产生器
时间Fri Mar 6 17:46:37 2009
作者 luky (天行光) 看板 Mud
标题 [其它]梦幻七域用的地图编辑器程式码大公开.
时间 Tue Jun 6 07:31:12 2000
───────────────────────────────────────
因为有许多架设mud的朋友问到map怎麽做的.
我想就公开让大家去改进好了.
//mapmaker2.c
/*
Title: 地图编辑器 v2.0
Coder: Luky 05/06/2000
MUD: ds.muds.net 7000
*/
#define HAVE_OBLIQUE_LINK 0
#define MAP_BEGIN_LINE 2
inherit ITEM;
static string *outdoors_type = ({"off","land"});
mixed *maps;
string *icons;
string *room_short;
string file_head="map";
string current_path="/";
int block=0;
int busy;
int lock=1;
int save_room_file(string yn, string file_name, string file);
int light=0;
int can_save=0;
string outdoors="off";
void create()
{
set_name("区域产生器(v2.0)", ({ "area maker", "maker" }) );
set_weight(100);
set("unit", "个" );
set("long", @MYLONG
这个工具是可以方便巫师快速建立完整的区域房间连结结构。本
产生器可将一个地图编码档案快速转换为整批房间档案。<help maker>
指令:
┌help <关键字> 相关说明
├setpath <路径> 设定工作路径
├setblock <编号> 设定障碍物编号范围
├setoutdoors <种类|off> 设定产生档案是否为户外(预设为off:室内)
├setlight <on|off> 设定产生区域是否要加light(预设为off)
├setsaveroom <on|off> 设定产生区域是否可定点储存(预设为off)
└readmap <完整档案路径> 读取地图档
├showmap 显示区域地图
├savemap <档名> 储存区域地图档案
└generate 产生区域档案
MYLONG
);
}
void init()
{
if( wizardp(environment()) ) {
seteuid(getuid(environment()));
add_action("do_setpath", "setpath");
add_action("do_setblock", "setblock");
add_action("do_setoutdoors", "setoutdoors");
add_action("do_setlight", "setlight");
add_action("do_setsaveroom", "setsaveroom");
add_action("do_readmap", "readmap");
add_action("do_showmap", "showmap");
add_action("do_generate", "generate");
add_action("do_savemap", "savemap");
add_action("do_help", "help");
}
}
int do_help(string arg)
{
if(arg=="maker")
{
write(@HELP_MAKER
区域产生器使用方法:
1.使用之前必须先编辑好一个N*N的正方形地图档, 地图范例如下:
4;30m~~0m,3m▲0m,█,镇,;36;46m╬0m,4;36m::0m,;30m□0m, ,2m林0m,6m︻0m
大海,高山,石壁,城镇,岩浆,葬屍江,石板路,草原,榕树林,拱桥
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,07,07,00,00,00,07,07,00,00,00,07,07,00,00,00
00,03,06,06,07,08,07,07,07,07,07,07,07,07,06,06,07,00,00
00,00,07,06,08,08,01,01,07,07,07,06,06,06,06,03,07,07,00
00,00,00,06,08,08,08,01,05,05,05,06,07,07,06,07,07,07,00
00,00,07,06,01,01,01,08,07,07,05,09,05,05,06,07,07,07,00
00,07,07,06,01,01,08,07,07,07,07,06,07,05,06,07,07,07,00
00,00,07,06,01,07,07,07,07,03,07,06,07,05,09,05,05,00,00
00,00,07,06,07,07,07,07,07,06,06,06,06,06,06,08,00,00,00
00,00,07,06,06,06,06,06,06,06,07,07,08,08,08,08,00,00,00
00,07,07,07,07,07,07,07,07,07,07,07,07,07,08,08,08,07,00
00,07,03,07,07,00,07,07,07,07,07,07,07,07,07,08,07,07,00
00,07,07,07,00,00,00,07,07,07,07,07,00,00,07,07,07,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
PS:
第一行为图示阵列以逗号隔开, 分别代表每个边号的图示. 为一个全形或是两个半形符号.
第二行为文字, 数量要与第一行相同, 分别代表各种类的短名称.
第三行以後为矩形数字阵列, 数字分别代表该房间的种类. (目前不支援负值)
注意: 0-3 种类为障碍物, 将不会产生房间.
2. 使用 setblock <数字> 设定你的障碍物范围([0~数字]的房间种类将不会产生).
3. 如果需要存於其他路径则使用 setpath <档案路径>
指令设定要存放房间档案的路径. (预设: 目前所在目录)
4. 再用 readmap <map完整路径档名> 指令将地图档读入.
(预设: 目前所在目录的 map.txt)
5. 如果地图档案处理无误, 此时应该会自动显示地图供预览.
(也可以用 showmap 指令来看.)
6. 确定无误则可以使用 generate 指令来自动产生房间档案.
HELP_MAKER);
return 1;
}
return 0;
}
int do_setoutdoors(string arg)
{
if(!arg) return notify_fail("室外(land): setoutdoors land 室内: setoutdoors
off。\n");
if(member_array(arg,outdoors_type)==-1) return notify_fail("没有这种室外(内)
型态。\n");
outdoors=arg;
write("设定为: "+arg+" ..OK.");
return 1;
}
int do_setlight(string arg)
{
if(!arg || (arg!="on" && arg!="off")) return notify_fail("setlight <on|off>ꄊC\n");
if(arg=="on")
{
light=1;
write("房间将自动加入 set(\"light\",1); \n");
return 1;
}
if(arg=="off")
{
light=0;
write("房间将不会产生 set(\"light\",1); \n");
return 1;
}
}
int do_setsaveroom(string arg)
{
if(!arg || (arg!="on" && arg!="off")) return notify_fail("setlight <on|off>ꄊC\n");
if(arg=="on")
{
can_save=1;
write("房间将自动加入 set(\"valid_startroom\",1); \n");
return 1;
}
if(arg=="off")
{
can_save=0;
write("房间将不会产生 set(\"valid_startroom\",1); \n");
return 1;
}
}
int process_map(string file)
{
string input,*line,*type;
int i,j;
mixed map;
if(file_size(file)>0)
{
input=read_file(file);
line=explode(input,"\n");
icons=explode(line[0],",");
if(sizeof(icons)<1) return 0;
room_short=explode(line[1],",");
map=allocate(sizeof(line)-MAP_BEGIN_LINE);
for(i=MAP_BEGIN_LINE;i<sizeof(line);i++)
{
type=explode(line[i],",");
map[i-MAP_BEGIN_LINE]=allocate(sizeof(type));
for(j=0;j<sizeof(type);j++)
{
sscanf(type[j],"%d",map[i-MAP_BEGIN_LINE][j]);
}
}
maps=map;
return 1;
} else return 0;
}
mixed query_map()
{
return maps;
}
string show_map(int raw)
{
int i,j,count=0;
string str="\n";
if(sizeof(maps)<1) return "目前没有地图被载入。\n";
for(i=0;i<sizeof(maps);i++)
{
for(j=0;j<sizeof(maps[i]);j++)
{
str=sprintf("%s<%d>",str,maps[i][j]);
if(maps[i][j]>block) count++;
}
str+="\n";
}
for(i=0;i<sizeof(icons);i++)
{
str=replace_string(str,sprintf("<%d>",i),icons[i]);
}
if(!raw) str+=sprintf("\n 将产生 %d 个房间档案。\n",count);
else str+="\n";
return str;
}
private int generate_room_file(int x, int y)
{
int i,type,tmp_h;
string file_name,file,*exit_key,*exit_file;
mapping exit=([]);
type=maps[y][x];
if(type<=block || type>=sizeof(icons)) return 0;
//为求简洁, 取消斜向连结
//Scan north
if(y>=1) {
tmp_h=maps[y-1][x];
if(tmp_h>block && tmp_h<sizeof(icons)) {
exit["north"]=file_head+sprintf("_%d_%d",y-1,x);
}
}
//Scan east
if(x<sizeof(maps[y])-1) {
tmp_h=maps[y][x+1];
if(tmp_h>block && tmp_h<sizeof(icons)) {
exit["east"]=file_head+sprintf("_%d_%d",y,x+1);
}
}
//Scan south
if( y<sizeof(maps)-1) {
tmp_h=maps[y+1][x];
if(tmp_h>block && tmp_h<sizeof(icons)) {
exit["south"]=file_head+sprintf("_%d_%d",y+1,x);
}
}
//Scan west
if(x>=1) {
tmp_h=maps[y][x-1];
if(tmp_h>block && tmp_h<sizeof(icons)) {
exit["west"]=file_head+sprintf("_%d_%d",y,x-1);
}
}
//generate file
file_name=current_path+file_head+sprintf("_%d_%d.c",y,x);
file=@FILE_1
inherit ROOM;
void create()
{
FILE_1;
file+=sprintf("\tset(\"short\", \"%s\");\n",room_short[type]);
file+=@FILE_LONG
set("long", @LONG
LONG
);
set("exits",([
FILE_LONG;
exit_key=keys(exit);
for(i=0;i<sizeof(exit_key);i++) {
file=sprintf("%s\t\"%s\" : __DIR__\"%s\",\n",file,exit_key[i],exit[exit_
key[i]]);
}
file+="\t]));\n";
//
//其他房间设定
//
// if(type==23)
// {
// file+=@TREES
// set("outdoors","land");
//
//TREES;
// }
// else
// {
if(outdoors!="off") file+="\tset(\"outdoors\",\""+outdoors+"\");\n";
if(light ) file+="\tset(\"light\",1);\n";
if(can_save) file+="\tset(\"valid_startroom\",1);\n";
// }
file+=@FILE_2
setup();
set("map_long",1); //show map as long
replace_program(ROOM); //加其他函式xxx()时请拿掉此行
}
FILE_2
;
if( file_size(file_name)!=-1 ) {
write("档案 " + file_name + " 已存在﹐要删除旧档吗﹖[y/n]");
input_to("save_room_file", file_name, file);
return 1;
}
return save_room_file("y", file_name, file);
}
int save_room_file(string yn, string file_name, string file)
{
if( strlen(yn)<1 || yn[0]!='y' ) return 1;
if( file_size(file_name)!=-1 ) rm(file_name);
write("建立 " + file_name + "...");
if( write_file(file_name, file,1) ) {
write("OK!\n");
return 1;
} else
{
write("失败!!\n");
return notify_fail("你没有写入这个档案(" + file_name + ")的权利。\n");
}
}
int do_setpath(string arg)
{
string dir;
if(!arg)
{
if(dir = this_player()->query("cwd"))
{
current_path=dir;
write("你将放置档案目录设定为[ "+current_path+" ]\n");
return 1;
} else return notify_fail("无法自动取得目录。\n");
}
else
{
if( strsrch(arg, "...") >= 0 ) return notify_fail("没有这个目录。\n");
//Add by Luky
dir = resolve_path(this_player()->query("cwd"), arg);
if(file_size(dir)!=-2) return notify_fail("没有这个目录。\n");
if(dir[strlen(dir)-1]!='/') dir += "/";
current_path=dir;
write("你将放置档案目录设定为[ "+current_path+" ]\n");
return 1;
}
}
int do_setblock(string arg)
{
int temp;
if(!arg) write("目前地图设定为种类编号[ "+block+" ]以下的为障碍物。\n");
else
{
if(sscanf(arg,"%d",temp)!=1) return notify_fail("设定区域的障碍物种类范댊 setblock [数字]。\n");
if(temp<0) return notify_fail("设定区域的障碍物种类范围: setblock [数字]
<需大於0>。\n");
block=temp;
write("你将编号"+block+"以下的房间种类设定为障碍物。\n");
}
return 1;
}
int do_readmap(string arg)
{
string file;
if(!arg)
{
current_path=this_player()->query("cwd");
file=resolve_path(this_player()->query("cwd"),"map.txt");
if(process_map(file))
{
write("地图档载入完成!!\n");
this_player()->start_more(show_map(0));
return 1;
}
else
{
return notify_fail("地图档"+file+"载入失败。\n");
}
}
else
{
file=resolve_path(this_player()->query("cwd"), arg);
if(process_map(file))
{
write("地图档载入完成!!\n");
this_player()->start_more(show_map(0));
return 1;
}
else
{
return notify_fail("地图档"+file+"载入失败。\n");
}
}
}
int do_showmap(string arg)
{
this_player()->start_more(show_map(0));
return 1;
}
void delay_generate(int y)
{
int x;
for(x=0;x<sizeof(maps[y]);x++)
{
generate_room_file(x,y);
}
return;
}
void generate_done()
{
busy=0;
write("档案建立完成!!\n");
return;
}
int do_generate(string arg)
{
int x,y,time=0;
if(current_path=="/") current_path=this_player()->query("cwd");
if(!current_path) return notify_fail("请先设定目录(setpath)。\n");
if(block<10 && lock)
{
lock=0;
return notify_fail("紧告: 你目前的障碍物设定为:"+block+", 若有错误请用 s
etblock 重设。\n[再次使用generate则会强迫执行。]\n");
}
lock=1;
if(busy) return notify_fail("正在产生档案中, 请稍待。\n");
busy = 1;
for(y=0;y<sizeof(maps);y++)
{
call_out("delay_generate",time,y);
time+=3;
//for(x=0;x<sizeof(maps[y]);x++)
//{
// generate_room_file(x,y);
//}
}
call_out("generate_done",time);
write("准备开始建立档案...这可能会花一段时间, 请稍待。\n");
return 1;
}
int do_savemap(string arg)
{
string output;
if(sizeof(maps)<1) return notify_fail("目前没有地图被载入。\n");
if(!arg) arg = "area";
arg = current_path+arg;
output=show_map(1);
if( file_size(arg)!=-1 ) {
write("档案 " + arg + " 已存在﹐要覆盖\旧档﹖[y/n]");
input_to("save_room_file", arg, output);
return 1;
}
return save_room_file("y", arg, output);
}
int query_autoload() { return 1; }
void owner_is_killed() { destruct(this_object()); }
//档案结束
至於要怎麽做到像梦幻七域的现代区域这样的显示方式
只要利用档案的档名取得座标. 由路径取得对应的地图
然後配合上 showmap 的技巧, 我想应该不难想到.
如果有任何缺点和需要改进的地方也请告知.
注: 虽然我给大家参考, 但是并不代表你可以随意取用.
若要实际使用请支会我一声, 非营利性质的只要不更动标头档便可使用
--
※ Origin: 巴哈姆特<bahamut.org> ◆ From: 203.79.179.116
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 218.170.228.153