Message
| Below is my first attempt at a mapper for the Twin Two Towers MUD.
It certainly isn't perfect, but it might help others get further.
Basically the problem with a mapper is to detect unique rooms, and in the case of this MUD I fairly quickly stumbled into a place where each room had the same description, namely:
You stand in a very dark tunnel. All around you shadows hide
the sides of the walls. Every once in a while you pass a torch
which gives off a small amount of light that is consumed by the
darkness. In the distance you hear the dripping of water and an
occasional hammering of stone.
Also rooms don't seem to have names per se, so in the absence of a better idea I have put in the partial room hash (better than nothing, maybe).
To use, install as per the instructions below. Then you have to "teach" it by walking around. You should start to see squares appearing with you in the middle. You are best off backtracking as you enter each room. (So if you go west from A to B, it knows A leads to B. Then go back east again, so it knows B leads back to A).
This version just stores the map in the plugin state file. It could be modified to use a SQLite3 database, which would then let you share the map between different characters.
It is based on Simple_Mapper.xml from this page:
http://www.gammon.com.au/forum/bbshowpost.php?id=10138&page=7
The only real change was to make a multi-line trigger that tries to detect room descriptions, namely starting with 4 spaces, then multiple lines, followed by "The only obvious exits are xxx" or "The only obvious exit is xxx".
|
To save and install the Two_Towers_Mapper plugin do this:
- Copy between the lines below (to the Clipboard)
- Open a text editor (such as Notepad) and paste the plugin into it
- Save to disk on your PC, preferably in your plugins directory, as Two_Towers_Mapper.xml
- Go to the MUSHclient File menu -> Plugins
- Click "Add"
- Choose the file Two_Towers_Mapper.xml (which you just saved in step 3) as a plugin
- Click "Close"
|
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="Two_Towers_Mapper"
author="Nick Gammon"
id="565a2ddd934aca9913894ad4"
language="Lua"
purpose="Mapper for LOTR Two Towers"
save_state="y"
date_written="2010-08-30"
requires="4.51"
version="1.1"
>
</plugin>
<!-- Triggers -->
<triggers>
<trigger
enabled="y"
lines_to_match="10"
match="^\s{4}(?P<roomdesc>.*\n(\S.*\n)*)\s{4}The only obvious exit(s are| is) (?P<exits>.*)\.\Z"
multi_line="y"
regexp="y"
script="process_room_description"
sequence="100"
>
</trigger>
</triggers>
<aliases>
<alias
match="^mapper find ([\w* %d/"]+)$"
enabled="y"
sequence="100"
script="map_find"
regexp="y"
>
</alias>
</aliases>
<!-- Script -->
<script>
<![CDATA[
local MAX_NAME_LENGTH = 60
local MUD_NAME = "Two Towers"
require "mapper"
require "serialize"
require "copytable"
require "commas"
default_config = {
-- assorted colours
BACKGROUND_COLOUR = { name = "Background", colour = ColourNameToRGB "lightseagreen", },
ROOM_COLOUR = { name = "Room", colour = ColourNameToRGB "cyan", },
EXIT_COLOUR = { name = "Exit", colour = ColourNameToRGB "darkgreen", },
EXIT_COLOUR_UP_DOWN = { name = "Exit up/down", colour = ColourNameToRGB "darkmagenta", },
EXIT_COLOUR_IN_OUT = { name = "Exit in/out", colour = ColourNameToRGB "#3775E8", },
OUR_ROOM_COLOUR = { name = "Our room", colour = ColourNameToRGB "black", },
UNKNOWN_ROOM_COLOUR = { name = "Unknown room", colour = ColourNameToRGB "#00CACA", },
DIFFERENT_AREA_COLOUR = { name = "Another area", colour = ColourNameToRGB "#009393", },
MAPPER_NOTE_COLOUR = { name = "Messages", colour = ColourNameToRGB "lightgreen" },
ROOM_NAME_TEXT = { name = "Room name text", colour = ColourNameToRGB "#BEF3F1", },
ROOM_NAME_FILL = { name = "Room name fill", colour = ColourNameToRGB "#105653", },
ROOM_NAME_BORDER = { name = "Room name box", colour = ColourNameToRGB "black", },
AREA_NAME_TEXT = { name = "Area name text", colour = ColourNameToRGB "#BEF3F1",},
AREA_NAME_FILL = { name = "Area name fill", colour = ColourNameToRGB "#105653", },
AREA_NAME_BORDER = { name = "Area name box", colour = ColourNameToRGB "black", },
FONT = { name = get_preferred_font {"Dina", "Lucida Console", "Fixedsys", "Courier", "Sylfaen",} ,
size = 8
} ,
-- size of map window
WINDOW = { width = 400, height = 400 },
-- how far from where we are standing to draw (rooms)
SCAN = { depth = 30 },
-- speedwalk delay
DELAY = { time = 0.3 },
-- how many seconds to show "recent visit" lines (default 3 minutes)
LAST_VISIT_TIME = { time = 60 * 3 },
}
rooms = {}
valid_direction = {
n = "n",
s = "s",
e = "e",
w = "w",
u = "u",
d = "d",
ne = "ne",
sw = "sw",
nw = "nw",
se = "se",
north = "n",
south = "s",
east = "e",
west = "w",
up = "u",
down = "d",
northeast = "ne",
northwest = "nw",
southeast = "se",
southwest = "sw",
['in'] = "in",
out = "out",
} -- end of valid_direction
-- -----------------------------------------------------------------
-- We have a room name and room exits
-- -----------------------------------------------------------------
function process_room_description (name, line, wildcards)
local exits_str = trim (wildcards.exits)
local roomdesc = trim (wildcards.roomdesc)
-- ColourNote ("white", "blue", "exits: " .. exits_str) -- debug
-- generate a "room ID" by hashing the room description and exits
uid = utils.tohex (utils.md5 (roomdesc .. exits_str))
uid = uid:sub (1, 25)
-- break up exits into individual directions
exits = {}
for exit in string.gmatch (exits_str, "%w+") do
local ex = valid_direction [exit]
if ex then
exits [ex] = "0" -- don't know where it goes yet
end -- if
end -- for
local name = string.match (roomdesc, "^(.-)[.\n]")
if #name > MAX_NAME_LENGTH then
name = name:sub (1, MAX_NAME_LENGTH - 3) .. "..."
end -- if too long
-- add to table if not known
if not rooms [uid] then
ColourNote ("cyan", "", "Mapper adding room " .. uid:sub (1, 8) .. ", name: " .. name)
rooms [uid] = { name = name, desc = roomdesc, exits = exits, area = MUD_NAME }
end -- if
-- save so we know current room later on
current_room = uid
-- call mapper to draw this rom
mapper.draw (uid)
-- try to work out where previous room's exit led
if expected_exit == "0" and from_room then
fix_up_exit ()
end -- exit was wrong
end -- Name_Or_Exits
-- -----------------------------------------------------------------
-- mapper 'get_room' callback - it wants to know about room uid
-- -----------------------------------------------------------------
function get_room (uid)
if not rooms [uid] then
return nil
end -- if
local room = copytable.deep (rooms [uid])
local texits = {}
for dir in pairs (room.exits) do
table.insert (texits, dir)
end -- for
table.sort (texits)
room.hovermessage = string.format (
"%s\tExits: %s\nRoom: %s",
room.name or "unknown",
table.concat (texits, ", "),
uid
)
if uid == current_room then
room.bordercolour = config.OUR_ROOM_COLOUR.colour
room.borderpenwidth = 2
end -- not in this area
return room
end -- get_room
-- -----------------------------------------------------------------
-- We have changed rooms - work out where the previous room led to
-- -----------------------------------------------------------------
function fix_up_exit ()
-- where we were before
local room = rooms [from_room]
-- leads to here
room.exits [last_direction_moved] = current_room
-- clear for next time
last_direction_moved = nil
from_room = nil
end -- fix_up_exit
-- -----------------------------------------------------------------
-- try to detect when we send a movement command
-- -----------------------------------------------------------------
function OnPluginSent (sText)
if valid_direction [sText] then
last_direction_moved = valid_direction [sText]
-- print ("Just moved", last_direction_moved)
if current_room and rooms [current_room] then
expected_exit = rooms [current_room].exits [last_direction_moved]
if expected_exit then
from_room = current_room
end -- if
-- print ("expected exit for this direction is to room", expected_exit)
end -- if
end -- if
end -- function
-- -----------------------------------------------------------------
-- Plugin Install
-- -----------------------------------------------------------------
function OnPluginInstall ()
config = {} -- in case not found
-- get saved configuration
assert (loadstring (GetVariable ("config") or "")) ()
-- allow for additions to config
for k, v in pairs (default_config) do
config [k] = config [k] or v
end -- for
-- and rooms
assert (loadstring (GetVariable ("rooms") or "")) ()
-- initialize mapper
mapper.init { config = config, get_room = get_room }
mapper.mapprint (string.format ("MUSHclient mapper installed, version %0.1f", mapper.VERSION))
end -- OnPluginInstall
-- -----------------------------------------------------------------
-- Plugin Save State
-- -----------------------------------------------------------------
function OnPluginSaveState ()
mapper.save_state ()
SetVariable ("config", "config = " .. serialize.save_simple (config))
SetVariable ("rooms", "rooms = " .. serialize.save_simple (rooms))
end -- OnPluginSaveState
-- -----------------------------------------------------------------
-- Plugin just connected to world
-- -----------------------------------------------------------------
function OnPluginConnect ()
from_room = nil
last_direction_moved = nil
end -- OnPluginConnect
-- -----------------------------------------------------------------
-- Find a room
-- -----------------------------------------------------------------
function map_find (name, line, wildcards)
local room_ids = {}
local count = 0
local wanted = (wildcards [1]):lower ()
-- scan all rooms looking for a simple match
for k, v in pairs (rooms) do
local desc = v.desc:lower ()
if string.find (desc, wanted, 1, true) then
room_ids [k] = true
count = count + 1
end -- if
end -- finding room
-- see if nearby
mapper.find (
function (uid)
local room = room_ids [uid]
if room then
room_ids [uid] = nil
end -- if
return room, next (room_ids) == nil
end, -- function
show_vnums, -- show vnum?
count, -- how many to expect
false -- don't auto-walk
)
end -- map_find
]]>
</script>
</muclient>
[EDIT] Amended to fix up problems with room detection. Also put room name on top of map.
Example screenshot:
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|