Okay, here's the update, and it's quite a step forwards! I'm open to any advice on optimising it and since I'm a lua newbie if there's a better way to achieve the same thing, let me know.
First up, here's my map script file
mudlet = mudlet or {}; mudlet.mapper_script = true
exitmap = {
n = 1,
north = 1,
ne = 2,
northeast = 2,
nw = 3,
northwest = 3,
e = 4,
east = 4,
w = 5,
west = 5,
s = 6,
south = 6,
se = 7,
southeast = 7,
sw = 8,
southwest = 8,
u = 9,
up = 9,
d = 10,
down = 10,
["in"] = 11,
out = 12,
[1] = "north",
[2] = "northeast",
[3] = "northwest",
[4] = "east",
[5] = "west",
[6] = "south",
[7] = "southeast",
[8] = "southwest",
[9] = "up",
[10] = "down",
[11] = "in",
[12] = "out",
}
function showExits(roomID)
local tmp = getRoomExits(roomID)
local size = table.size(tmp)
echo(getRoomName(roomID).." leads ")
for k, v in pairs(tmp) do
if size>2 then
echo(k.."("..getRoomName(v).."), ")
elseif size==2 then
echo(k.."("..getRoomName(v)..") and ")
else
echo(k.."("..getRoomName(v)..")\n")
end
size = size-1
end
end
function showStubs(roomID)
local tmp = getExitStubs(roomID)
local size = table.size(tmp)
echo(getRoomName(roomID).." leads ")
for k, v in pairs(tmp) do
if size>2 then
echo(exitmap[v]..", ")
elseif size==2 then
echo(exitmap[v].." and ")
else
echo(exitmap[v].."\n")
end
size = size-1
end
end
currentRoom = 0
currentArea = 0
lastCommand = ""
registerAnonymousEventHandler("sysDataSendRequest", "parseCommands")
function parseCommands(_,command)
lastCommand=command
end
function newCoords(id,dir)
local x,y,z = getRoomCoordinates(id)
if type(dir)~="number" then dir=exitmap[dir] end
if dir==1 or dir==2 or dir==3 then y=y+1
elseif dir==6 or dir==7 or dir==8 then y=y-1 end
if dir==2 or dir==4 or dir==7 then x=x+1
elseif dir==3 or dir==5 or dir==8 then x=x-1 end
return x,y,z
end
function isRoomNear(id,area,dir)
local x,y,z=newCoords(id,dir)
local otherroom = select(2, next(getRoomsByPosition(area,x,y,z)))
if not otherroom then return 0
else return otherroom end
end
function reverseStub(dir)
if dir==1 then return 6
elseif dir==2 then return 8
elseif dir==3 then return 7
elseif dir==4 then return 5
elseif dir==5 then return 4
elseif dir==6 then return 1
elseif dir==7 then return 3
elseif dir==8 then return 2
elseif dir==9 then return 10
elseif dir==10 then return 9
elseif dir==11 then return 12
elseif dir==12 then return 11
end
end
I wrote a few functions to make life easier for myself (working out relative coords and reversing directions etc).
Then the mapper functionality itself is all contained in a single trigger. I know I'm going to need to add more triggers later for things like party following and "you can't go there" style actions. I'll also have to tackle special exits (which I have an issue with already). The trigger pattern matches on the room description and exits when entering a room, example "
The White Stallion Inn(
e, u and s)", there is the potential for an extra " [n and s]" style exit on the end, which are water exits (swimming or boating only) but for now I'm ignoring those entirely!
Trigger Line 1 (regexp): ^(.*)\((.*)[\)|\) \[.*\]]$
Trigger Line 2 (color trigger): Light White/Blue (I couldn't set the bg color on the example above, it's white on blue)
Script:
room=multimatches[1][2]
exits = {}
index = 1
for value in string.gmatch(multimatches[1][3],"%w+") do
if value~="and" then
exits[index] = value
index = index + 1
end
end
if currentRoom==0 then -- If lost
-- Compare room name to DB, if it's a unique name, you're found
local tmp = searchRoom(multimatches[1][2])
if (table.size(tmp)==1) then
for k,v in pairs(tmp) do
if (v==multimatches[1][2]) then
currentRoom = k
currentArea = getRoomArea(k)
centerview(currentRoom)
end
end
end
else -- Not lost
local tmp = getRoomExits(currentRoom)
if tmp[lastCommand]~=null then --if exit exists
if multimatches[1][2]==getRoomName(tmp[lastCommand]) then -- and room name matches
currentRoom=tmp[lastCommand]
centerview(currentRoom) --update location
else -- exit exists but room name doesn't
currentRoom=0
end
else -- exit doesn't exist
tmp2 = getExitStubs(currentRoom) -- check stubs, maybe make a new room
if table.contains(tmp2,exitmap[lastCommand]) then -- exit stub exists in that direction PROBLEM
nextroom=isRoomNear(currentRoom,currentArea,lastCommand)
if nextroom~=0 then
-- does IT have the appropriate exit stub?
tmpStub=getExitStubs(nextRoom)
if tmpStub[reverseStub(exitmap[lastCommand])]~=null then
connectExitStub(currentRoom,exitmap[lastCommand])-- connect them
currentRoom=nextroom
centerview(currentRoom)
else
echo("Failed connect, room but no reverse stub")
currentRoom=0
end
else
-- make the room
local newRoom = createRoomID()
addRoom(newRoom)
setRoomArea(newRoom,currentArea)
setRoomName(newRoom,multimatches[1][2])
local x,y,z=newCoords(currentRoom,lastCommand)
setRoomCoordinates(newRoom,x,y,z)
echo("Making new room: "..newRoom.." at "..x.."/"..y.."/"..z)
-- add Exit stubs
for i = 1, #exits do setExitStub(newRoom,exitmap[exits[i]],true) end --problem with non-standard exits here!
-- connect to current room
connectExitStub(currentRoom,exitmap[lastCommand])
-- update location
currentRoom=newRoom
centerview(currentRoom)
end
else
currentRoom=0 -- give in, you're lost
end
end
end
if currentRoom==0 then
echo("lost")
else
echo(currentRoom)
end(0,0,0)
I need to add some more comments so I can follow the logic in a week's time but it flows 'fairly' well. The current issue comes up when I enter a room with a special exit (e.g. "enter"), in which case it throws an error to the error console and fails to connect the exit stubs. I suspect the best way to handle that will be to use an if statement
if exit[i]==n or exit[i]=s or etc then setExitStub(stuff)
else specialExitStuff() end
I just thought that I'd made enough progress that it was worth coming back here to check I'm not heading for disaster. I've managed to map "most" of a town just by walking around, and towns are tricky with lots of overlapping rooms (make room, move room, carry on mostly). I do need to tackle to issue of moving to a new area, though I "think" the current code should cover it well enough, it tracks and updates the currentArea variable.
Anyway, taking a break means I actually get time to play the game too
Look forwards to any feedback and as always, it's much appreciated!