随机迷宫以及地图是很多Mud引入的新任务类型。
比如下面就是一个典型的迷宫地图
┌─┬─┬─┬─┬─┬─┬─┬─┐
│★│ │ │
├ ┼─┼ ┼─┼ ┼─┼─┼ ┤
│ │ │ │ │ │
├ ┼ ┼─┼ ┼ ┼─┼─┼ ┤
│ │ │ │ │
├ ┼─┼ ┼─┼ ┼─┼ ┼ ┤
│ │ │ │ │
├─┼ ┼ ┼─┼─┼─┼ ┼ ┤
│ │ │ │ │ │ │ │
├ ┼ ┼ ┼ ┼ ┼ ┼ ┼─┤
│ │ │ │ │ │ │
├ ┼ ┼─┼─┼─┼ ┼ ┼ ┤
│ │ │ │
├─┼─┼ ┼─┼ ┼─┼ ┼ ┤
│ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┘
这种地图本质就是在服务器创建了一系列的虚拟房间,并建立了房间中之间的联系,最后将这些方向和关系再打印成文字图案。
那么,处理方式也比较直接。
先将文字图标准化,化成比较简单的单字节图,然后再遍历建立临时房间和出口信息就可以。
参考HellMapManager.Dll的范例代码
local hmmlib=require('hmm')
local hmm=hmmlib.new()
hmm.DllEncoding=0 --0 for utf-8, 1 for gbk
local json=require('json')
local file=assert(io.open("hongchen.hmm","r"))
local data=file:read("*a")
file:close();
hmm:call("import",data)
local extrooms={}
local extpaths={}
local function buildMyRoom(entry,roomid,roomname)
local myroom1=hmmlib.Room.new()
myroom1.Key="myroom-entry"
myroom1.Name=roomname.."大厅"
local myroomexit1=hmmlib.Exit.new()
myroomexit1.Command="open gate;n"
myroomexit1.To="myroom-home"
local myroomexit2=hmmlib.Exit.new()
myroomexit2.Command="out"
myroomexit2.To=entry
myroom1.Exits={myroomexit1,myroomexit2}
local myroom2=hmmlib.Room.new()
myroom2.Key="myroom-home"
myroom2.Name=roomname.."卧室"
local myroomexit3=hmmlib.Exit.new()
myroomexit3.Command="open gate;s"
myroomexit3.To="myroom-entry"
myroom2.Exits={myroomexit3}
table.insert(extrooms, myroom1)
table.insert(extrooms, myroom2)
local entrypath=hmmlib.Path.new()
entrypath.From=entry
entrypath.Command="go "..roomid
entrypath.To="myroom-entry"
table.insert(extpaths, entrypath)
end
buildMyRoom("2440","myhouse","大别野")
local mazemaptxt=[[
┌─┬─┬─┬─┬─┬─┬─┬─┐
│ │ │
├─┼ ┼─┼─┼─┼─┼ ┼ ┤
│ │ │ │ │ │
├ ┼ ┼─┼ ┼ ┼─┼ ┼ ┤
│ ♚ │ │ │ │ │
├─┼ ┼ ┼ ┼ ┼─┼ ┼ ┤
│ │ │ │ │
├─┼ ┼─┼ ┼─┼─┼ ┼─┤
│ │ │ │ │ │
├ ┼ ┼─┼─┼ ┼ ┼─┼ ┤
│ │ │ │ │ │
├ ┼ ┼─┼─┼ ┼ ┼ ┼ ┤
│ │ │ │ │ │
├ ┼ ┼─┼ ┼ ┼ ┼ ┼─┤
│ │ │ │ │ ★│
└─┴─┴─┴─┴─┴─┴─┴─┘
]]
--♚为当前位置,★为出口
local Maze={}
Maze.__index=Maze
Maze.new=function()
local self=setmetatable({},Maze)
self.RoomPrefix="maze-"
self.RoomKeys={}
self.Rooms={}
self.Paths={}
self.EntryRoom=""
self.ExitRooms={}
return self
end
function Maze:buildRoomKey(x,y)
return self.RoomPrefix..tostring(x).."-"..tostring(y)
end
function Maze:buildExit(room,tokey,command)
local exit1=hmmlib.Exit.new()
exit1.Command=command
exit1.To=tokey
table.insert(room.Exits, exit1)
end
function Maze:readmap(maptxt)
local maplines={}
for line in string.gmatch(maptxt, "[^\r\n]+") do
if #line>0 then
--因为utf8不定长,进行处理
line = string.gsub(line," "," ")
line = string.gsub(line,"│","+")
line = string.gsub(line,"─","+")
line = string.gsub(line,"├","+")
line = string.gsub(line,"┤","+")
line = string.gsub(line,"┴","+")
line = string.gsub(line,"┬","+")
line = string.gsub(line,"└","+")
line = string.gsub(line,"┘","+")
line = string.gsub(line,"┌","+")
line = string.gsub(line,"┐","+")
line = string.gsub(line,"┼","+")
line = string.gsub(line,"♚","I")
line = string.gsub(line,"★","O")
table.insert(maplines, line)
end
end
local roomwidth=(#maplines[1]-1)/2
local roomheight=(#maplines-1)/2
local currentY=1
--按行处理
while currentY<=roomheight do
local currentX=1
--处理每个房间
while currentX<=roomwidth do
local roomkey=self:buildRoomKey(currentX-1, currentY-1)
table.insert(self.RoomKeys, roomkey)
local room=hmmlib.Room.new()
room.Key=roomkey
if maplines[currentY*2]:sub(currentX*2, currentX*2)=="I" then
self.EntryRoom=roomkey
end
if maplines[currentY*2]:sub(currentX*2, currentX*2)=="O" then
table.insert(self.ExitRooms, roomkey)
end
if maplines[currentY*2]:sub(currentX*2+1, currentX*2+1)==" " then
self:buildExit(room,self:buildRoomKey(currentX,currentY-1),"e")
end
if maplines[currentY*2]:sub(currentX*2-1, currentX*2-1)==" " then
self:buildExit(room,self:buildRoomKey(currentX-2,currentY-1),"w")
end
if maplines[currentY*2+1]:sub(currentX*2, currentX*2)==" " then
self:buildExit(room,self:buildRoomKey(currentX-1,currentY),"s")
end
if maplines[currentY*2-1]:sub(currentX*2, currentX*2)==" " then
self:buildExit(room,self:buildRoomKey(currentX-1,currentY-2),"n")
end
table.insert(self.Rooms, room)
currentX=currentX+1
end
currentY=currentY+1
end
end
function Maze:applyTo(environment)
for _, room in ipairs(self.Rooms) do
table.insert(environment.Rooms, room)
end
for _, path in ipairs(self.Paths) do
table.insert(environment.Paths, path)
end
end
local mymaze=Maze.new()
mymaze:readmap(mazemaptxt)
local query=hmmlib.QueryPathAny.new()
query.From={"2522"}
query.Target={"myroom-home"}
query.Environment=hmmlib.Environment.new()
query.Environment.Rooms=extrooms
query.Environment.Paths=extpaths
local result=json.decode(hmm:call("querypathany", json.encode(query)))
if (result==nil) then
print("No home path found")
else
print("Home path found:")
print(json.encode(result))
end
-- 遍历迷宫后离开
local queryall=hmmlib.QueryPath.new()
queryall.Start=mymaze.EntryRoom
queryall.Target=mymaze.RoomKeys
queryall.Environment=hmmlib.Environment.new()
mymaze:applyTo(queryall.Environment)
result=json.decode(hmm:call("querypathall", json.encode(queryall)))
if (result==nil) then
print("No full maze path found")
else
print("Full maze path found:")
print(json.encode(result))
end
--遍历完成,离开路径
query=hmmlib.QueryPathAny.new()
query.From={result["To"]}
query.Target=mymaze.ExitRooms
query.Environment=hmmlib.Environment.new()
mymaze:applyTo(query.Environment)
result=json.decode(hmm:call("querypathany", json.encode(query)))
if (result==nil) then
print("No maze path found")
else
print("Maze path found:")
print(json.encode(result))
end
在处理动态地图时,核心还是不要想的太复杂,直接找出Room的对应元素,以及相应的Exit,然后根据需要遍历或者导航即可。