[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Plugins
. . -> [Subject]  Nick's Learning Mapper

Nick's Learning Mapper

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Sun 02 Feb 2020 12:30 AM (UTC)

Amended on Fri 25 Jun 2021 11:10 PM (UTC) by Nick Gammon

Message

Nick’s learning mapper

by Nick Gammon (February 2020)

Updates

I have made various improvements since making this original post. Later versions have a lot more features, as described in further posts below.

To check if you have the latest version go to the Learning_Mapper plugin page on GitHub and check the version number (line 15 of the file). At present it reads:

 version="2.1"

The latest version of the mapper (1.8 onwards) shows the version when the mapper starts, like this:

[Learning_Mapper version 2.10]

The version number is also shown when you type “mapper help” (right at the top of the help information). Also at the end of the mapper help are links to the two files mentioned below.

If you don’t have the latest version please download it from here (two different files):

As mentioned below, RH-click on the “Raw” button on those pages, download the raw files, and save them in your MUSHclient / worlds / plugins directory.

Links for the actual raw files (the ones you should download) are:

RH-click on those two links to download the actual files for the mapper.

What is a mapper?

A few years ago now (2010) I released a generic mapper module which was intended to allow you to (fairly) simply map the MUD you are playing. This has since been incorporated into various MUDs by me, and other enthusiastic people.

An example from that post shows how you can get a good idea of where you are, and where and what the surrounding rooms are:

You can zoom in or out, and colour various important rooms, like shops:

The mapper can be dragged around, and resized to your convenience.

  • You can LH click on any visible room to speedwalk to that room by the shortest route.

  • Speedwalking is “throttled” so that it only moves from one room to the next once you arrive there. Even then you can add in a configurable delay, in case the MUD requires it.

  • Speedwalking auto-cancels if it detects it has ended up in an unexpected room number enroute.

  • There is a generic “room finder” built in. For example, nearby shops, trainers, portals, or match on text in the room name. Found rooms can be walked to by just clicking on the hyperlink in the list of found rooms.

  • You can RH click on a room to do other actions, like marking a room as a shop, or adding some free-format notes (eg. this room has quests)

  • If you hover over a room with the mouse a message appears (room name, exits, first sentence of description)

  • Recently trod paths are shown with a thicker line, so you can see where you have come from.


How do you add a mapper to your own MUD?

In the past this has been tricky, as the mapper needs to “know” what room you are in, what the exits are, and where they lead. I did a post in 2014 describing how you could adapt the mapper to your MUD, with a considerable amount of work adding triggers and aliases to detect rooms, exits and movements. As a lot of MUDs have different styles of output it has not been really practical to take a plugin from one MUD and use it on another.

The two major things the mapper needs to know are:

  • A unique way of identifying what room you are in (so it can tell one room from another one)
  • What exits a room has, and where they lead

Enter the “learning” mapper

After fielding yet another request to adapt the mapper to a MUD, I thought of the idea of making a generic interface, where you (the end user) don’t need to write any code, nor add any triggers or aliases, but just “teach” the mapper what the MUD output looks like.

This is done by Bayesian analysis of the incoming text, after a short training period, where you “teach” the plugin what lines represent what line types. This is very similar to how some spam filters work. Basically you mark email messages as “spam” or “not spam”. Then each word in the message is added to a list with a count of how many times it appeared in spam, and how many times it appeared in not spam. For example:

Spam words

  • winnings
  • lottery
  • inheritance
  • millions
  • guaranteed
  • revenue

Not spam

  • mirror
  • cupboard
  • children
  • visit
  • weather

Neutral

  • and
  • the
  • is
  • are
  • then

Of course, some emails may have both spam and not spam words, along with neutral ones. However if the majority of words are spam, then an overall rating is given to the email, and it is classified as spam.

References


How does this help?

If we know the line types then we can do some useful things:

  • The description of a room can be used to generate a unique identifier for that room. We do that by “hashing” up the room description to get a 25-character hex string like this: “7CDA6EAED3A94997F6DF9F364”. If the description doesn’t change then a room with that description will always have a unique hash.

  • The exits line can be used to work out which exits the room has.

  • The room name can be used to add room names to the mapper window.

  • The prompt line can be used as a trigger to display the room in the map. If we hit a prompt line, and we also had a description and exits, then we know enough to redraw the map with the current room centered.


How do you train the mapper?

First you install the mapper plugin, and put its associated Lua file into the “plugins” directory for MUSHclient. The plugins directory is located under the “worlds” directory, which will be a directory under where MUSHclient was installed.

How to install the mapper

  • Go to this link: https://github.com/nickgammon/mushclient/blob/master/lua/mapper.lua

  • RH-click on the “Raw” button and save the file mapper.lua to your <MUSHclient installation folder> -> lua directory.

    Note: This will overwrite an existing file. This updated mapper.lua file has two lines of bug fix in them.

  • Then go to this link: https://github.com/nickgammon/mushclient/blob/master/lua/serialize.lua

  • RH-click on the “Raw” button and save the file serialize.lua to your <MUSHclient installation folder> -> lua directory.

    Note: This will overwrite an existing file. This updated serialize.lua file has a bug fix re serializing the words “true” and “false”.

  • Then go to this link: https://github.com/nickgammon/plugins/blob/master/Learning_Mapper.xml

  • RH-click on the “Raw” button and save the file Learning_Mapper.xml to your <MUSHclient installation folder> -> worlds -> plugins directory.

  • Now go to this link: https://github.com/nickgammon/plugins/blob/master/Learning_Mapper.lua

  • RH-click on the “Raw” button and save the file Learning_Mapper.lua to the same directory (the plugins directory).

    You should now have those two files in your plugins directory (along with other ones that came with MUSHclient).

    The Lua file has the code for the learning mapper. The XML file has the plugin information, such as aliases, help information etc.

  • Open the world file for your MUD. This is where you will add the mapper plugin.

  • Go the MUSHclient File menu and choose Plugins:

  • Click on “Add” and then select the file Learning_Mapper.xml (not Learning_Mapper.lua) that you downloaded, and click Open. After you have done that the mapper plugin should appear in the plugins list.

  • Close the Plugins dialog.

  • You should now see the mapper window and the training window below it.


Starting training

Then log into your MUD and type look to see the room you are in. Select the room name, or part of the room name. Double-clicking on a word in the room name will do that.

Then click on the “Room name” -> “Yes” button as shown:

(If you don’t see a room name, just skip that step)


Then select all of the description lines as shown (click and drag over all the lines) and click on “Description” -> “Yes”.


Then select the exits line (or lines) as shown and click on “Exits” -> “Yes”.


Then select the prompt line as shown and click on “Prompt” -> “Yes”.


If you walk around the MUD you should see other rooms automatically recognizing the trained line types. If not, repeat the training for other rooms.


Correcting mis-recognized lines

As you walk around keep an eye on the “status window” on the right. That shows what line types the mapper has deduced. If it is wrong then train it to correct it. For example:

In this case it hasn’t recognized the room name. So, select the room name and click on “Room name” -> “Yes”.

It also thinks the line “A guard of the city stands at the ready.” is a description when it isn’t. So select that line and click on “Description” -> “No”.

Do this a few times and it should recognize both the words, and the line colours for different line types.

Watch for missing descriptions

You will probably find in the early minutes of training that description lines are not always fully recognized. This is bad because the room description will appear to change, and therefore its hashed room number will change, as learning progresses elsewhere. For example:

The middle line there was not recognized, so select the entire description and click on “Description” -> “Yes”. The more words you train the better, so it is better to train a paragraph rather than one line.

Once you retrain a line type, the map may make the current room seem to be disconnected from other rooms. You can fix this by visiting nearby rooms and going back again, to re-establish the links with the exits correctly.


Differences between MUDs

It would be nice if the mapper worked “out of the box” for every MUD. However since various MUDs present their room information in different ways you may need to change some of the mapper configuration items. This is done by typing:

mapper config <option> <value>

The current settings can be found by typing “mapper config”, for example:

All mapper configuration options
------------------------------------------------------------

    mapper config when_to_draw                             prompt
    mapper config activate_description_after_exits         No
    mapper config activate_description_after_room_name     No
    mapper config add_newline_to_prompt                    No
    mapper config blank_line_terminates_line_type          Yes
    mapper config exits_on_room_name                       No
    mapper config include_exits_in_hash                    Yes
    mapper config exits_is_single_line                     Yes
    mapper config prompt_is_single_line                    Yes
    mapper config exit_lines_start_with_direction          No
    mapper config status_background                        black
    mapper config status_border                            #1B1B1B
    mapper config status_text                              lightgreen
    mapper config uid_size                                 4
    mapper config show_info                                No
    mapper config show_warnings                            Yes
    mapper config show_room_and_exits                      No

------------------------------------------------------------
Type "mapper help" for more information about the above options.
Number of times line types trained: 31.
Type "mapper corpus info" for more information about line training.
Show mapper training window and status: Yes
Type "mapper learn" to toggle the training windows.

The options between the hyphens can be directly typed into the command window. Or, you can copy one of them, paste into the command window, and change it (for example, change “Yes” to “No”).

You could also share these options with other players, so that if you find a certain combination works best, tell them to use those options (copy and paste).

You can see from the information line above that it took 31 training clicks to train the mapper for this particular MUD.

Multiple exit lines

Some MUDs have multiple lines for exits, for example:

In this case, just select all the exits line when training them to be exits.

However if the exits line is always a single line then it is better to tell the mapper that:

mapper config exits_is_single_line YES

When to draw

Many MUDs show lines in this order:

  1. Room name
  2. Description
  3. Exits
  4. Prompt

In this case we want to draw the room when the exits arrive. So you want the option:

mapper config when_to_draw exits

(The room is actually drawn when the next non-exits line arrives after the exits line, in case there are multiple exits lines).

Some MUDs however show the exits line after the room name, like this:

  1. Room name
  2. Exits
  3. Description
  4. Prompt

In this case we want to draw after the description has (fully) arrived. So you want the option:

mapper config when_to_draw description

Force drawing on exits line

A problem with timing can occur if you get an exits line, and then a prompt which is not terminated by a newline. In that case the mapper waits for the prompt line to be terminated. If you are sure that exits are always on a single line, then you can activate this option:

mapper config exits_is_single_line Yes

Ignore bogus description lines

MUDs may have bogus description lines appear during normal playing, so it is best to tell the mapper to ignore lines that look like descriptions, until after a room name arrives:

mapper config activate_description_after_exits  Yes

It can also be helpful to disable description lines until after a room name arrives (this won’t apply if your MUD doesn’t show room names):

mapper config activate_description_after_room_name Yes

Add newline to prompt

If the last thing received was a prompt, and the prompt did not have a newline, then the mapper may not recognize the line-type change, and still show the previous room. There are various ways of fixing that:

  • Try activating world configuration -> Appearance -> Output -> “Convert IAC EOR/GA to new line”
  • If the MUD has prompts, try forcing a newline after a prompt (the suggestion above might do that)

    For example, on some MUDs you can change the prompt like this: PROMPT %hH %mM %vV>!

    In that case the “!” tells the MUD to send a new line. See your MUD documentation for details.
  • You can also try activating the automatic adding of newlines after simple prompts. Type:

    mapper config add_newline_to_prompt YES
  • If you have an MXP-enabled MUD this might not be a good idea, as MXP uses < and > symbols a lot. In that case use one of the other suggestions above.

Exits on room name line

Some MUDs may put the exits on the same line as the room name, for example:

In this case you want to activate the options:

mapper config exits_on_room_name YES
mapper config when_to_draw description

The first one tells the mapper to pull the exits from the room name, and the second to redisplay the map at the end of the description.

Include exits in hash

The mapper includes the exits in the room as part of the hashed room ID. This is to help navigate through parts of the MUD with identical descriptions. Without including the exits they will all appear to be the same room. With the exits included they become different rooms, providing the exits are different.

However some MUDs change the exits shown (for example, if you unlock a door). In that case you should not include the exits in the hash, otherwise the room will seem to be a different room every time the number of exits changes. To do this type:

mapper config include_exits_in_hash NO

What you can do with the map

As you walk around in the MUD you are both training the mapper to recognize line types, and also mapping. Keep an eye on the training information window on the right, to make sure room names are recognized, all lines of the description, and exits. If not, select them and train the appropriate type. If you are happy with the training you can close the training window (click the X) or type “mapper learn” to toggle the learning and information windows.

Sometimes it helps to go back and forwards between rooms to learn the exits which go each way (to and from the room).

You can mouse-over any room to see a pop-up box to tell you the room name, and the first sentence of the description.

You can RH-click on any room to mark it as a certain type (shop/trainer/bank), add a free-format note, or view the full description for it. You can also delete any exits that were erroneously added by the mapper.

The free-format notes are intended for you to add any useful information you might want to, for example that this room has a:

  • Healer
  • Quest-giver
  • Repairer
  • Food or water
  • Guild
  • Portal

Finding things

Type “mapper find ” to find something, eg.

mapper find shop

Three things are searched:

  • Room name
  • Description
  • Notes

Thus, you can search your own notes with this.

The links shown can be clicked on to speedwalk to that room.

Finding shops, trainers and banks

mapper shops        --> find nearby shops
mapper trainers     --> find nearby trainers
mapper banks        --> find nearby banks

Find where a room is

Each room has a “hashed” ID which is displayed in the room information when you mouse-over the room. Only some characters are displayed, you can control how many by the configuration option “uid_size”, for example:

mapper config uid_size 4

You may want to remember important location IDs, because then you can find where they are like this:

mapper where 55e

The mapper will respond (if it can):

Path to 55E is: 2n 2e 5s w

Go to a room by ID

You can also go directly to a room by typing “mapper goto ”, for example

mapper goto 55e

Find all rooms with notes

You can type “mapper notes” to display all nearby rooms which you have set a note for:

mapper notes

Exporting and importing the map and learning corpus

If you want to share your map or corpus, or use them for a different character, you can export them:

mapper export map
mapper export corpus

And then you, or someone else, can import them:

mapper import map
mapper import corpus

You cannot import a map on top of existing mapped rooms, so if you plan to import one, you must first clear out your existing one:

mapper reset map

The same applies to the corpus.

Suggestion: Use the export feature above to back up your map database, if you have explored many rooms.


Disclaimer

This mapper was designed to work with many MUDs, without needing any coding or adding of triggers and aliases. Basically, to be useable by anyone who is prepared to spend 15 minutes training its line type recognition.

Having said that, some types of MUDs are just not suitable for it. In particular MUSH games like PennMUSH tend to have free-format exits, for example:

<ET> Enter Tavern   <BN> Building nexus   <IN> The Inn   <ROPE> Climb the rope

These sorts of exits do not conform to the usual north/south/east/west paradigm, and thus the mapper will have trouble recognizing them, or indeed, drawing a map of them.

Similar remarks apply to MOO codebases.

Basically, your MUD will probably work if it conforms, at least to a large extent, to the examples above.

In particular you would want to see something like this:

That is, well-defined and separated:

  • Prompt
  • Room name
  • Description
  • Exits

As explained above, it is OK if the exits come before the description. What would throw the mapper out is if a MUD mixes up room information with exits, the people in the room, and the contents of rooms, all in one large paragraph. It would be hard then to separate out what is fixed description and what is variable (like, if someone enters or leaves a room).


Tips

  • If the mapper seems to lag behind drawing a new room, make sure that you get a complete line after the exits line.

  • You can try activating the automatic adding of newlines after simple prompts. Type “mapper config add_newline_to_prompt YES”.

  • You can also activate the option “exits_is_single_line” if your MUD always has exits on one line.

  • If the MUD supports colours, then use them. The mapper uses the colour of lines to distinguish them from each other.

  • Try activating world configuration -> Appearance -> Output -> “Convert IAC EOR/GA to new line”

  • If the MUD has prompts, try forcing a newline after a prompt (the suggestion above might do that)

    For example, on some MUDs you can change the prompt like this: PROMPT %hH %mM %vV>!

    In that case the “!” tells the MUD to send a new line. See your MUD documentation for details.

  • If room descriptions are not shown every time you enter a room (but only the first time) turn that option off in the MUD configuration (eg. “toggle brief”). Consult your MUD help files for how to do that, or ask in general chat.

  • Also try training prompt lines (they are not otherwise used, but a prompt line helps terminate a non-prompt line)

  • If the MUD shows a minimap on the left or right side of description lines, turn that option off in the MUD configuration (eg. “toggle minimap”). Consult your MUD help files for how to do that, or ask in general chat.

  • It is important that temporary things (like mobs in a room, people in a room, items on the ground, chat messages) are not considered part of the description. If they are select that line and click “Description: No”.

  • If the MUD shows everything in one colour, try activating colour output (eg. “term ansi”). There may be configuration options to colour certain types of lines (eg. “ansi roomshort light green”). This will help with recognition of line types. The exact options will vary from MUD to MUD.

  • An exit line like: “South: A Room in Mud School” will give an erroneous link to the “in” direction. You can delete unwanted exits by RH-clicking on the room and selecting “Delete an exit”.


If you have a MUD which you think should work, but doesn’t, please reply and provide a link to the MUD (IP address and port). Also show your current configuration choices:

mapper config

Also, describe in what circumstances it is not working (eg. a screenshot). This forum does not support uploading images, you can upload them to https://imgur.com/ or similar.


View the corpus

If you want to see what “learning” the mapper has been doing, type “mapper corpus”. That will show you a lengthy lot of information along these lines:

========================================================================
Description
========================================================================
  ----------------------------------------------------------------------
  Foreground colour of first style run
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                   white     4     0    0.70
                    gray    17     0    0.74
                   olive     5     0    0.71
                  silver     2     0    0.67
  ----------------------------------------------------------------------
  First word in the line
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                             2     0    0.67
               character     2     0    0.67
                  delete     1     0    0.63
                    down     1     0    0.63
                    east     1     0    0.63
               happening     1     0    0.63
                 however     1     0    0.63
              kidnapping     1     0    0.63
                     mud     2     0    0.67
                   north     1     0    0.63
                  please     1     0    0.63
                  school     1     0    0.63
                    some     1     0    0.63
             surrounding     1     0    0.63
               surrounds     1     0    0.63
                   swamp     1     0    0.63
                     the     3     0    0.69
                   theme     1     0    0.63
                    time     1     0    0.63
                towering     1     0    0.63
                      we     1     0    0.63
                    west     1     0    0.63
                    will     1     0    0.63
  ----------------------------------------------------------------------
  All words in the line
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                       a     6     0    0.71
                   adult     2     0    0.67
                advanced     1     0    0.63
                     all     2     0    0.67
                  almost     2     0    0.67
                      an     2     0    0.67
                     and     9     0    0.72
                 anytime     1     0    0.63
                     are     2     0    0.67
                    area     3     0    0.69
                      as     1     0    0.63
                     ask     1     0    0.63
                      at     1     0    0.63
                   bases     1     0    0.63
                   basic     1     0    0.63
                      be     1     0    0.63
              beginnings     1     0    0.63

You can see that description lines usually start with the colour gray. The word “and” appears a lot (as expected).


However exits look quite different:

========================================================================
Exits
========================================================================
  ----------------------------------------------------------------------
  Foreground colour of first style run
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                  silver     3     0    0.69
  ----------------------------------------------------------------------
  First word in the line
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                             3     0    0.69
  ----------------------------------------------------------------------
  All words in the line
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                    east     1     0    0.63
                   exits     3     0    0.69
                   north     2     0    0.67
                   south     1     0    0.63
               southwest     1     0    0.63
                      up     1     0    0.63
                    west     1     0    0.63

Clearly exits in this MUD are in silver colour, and consit exclusively of compass direction words. The difference between the corpus entries is how the mapper works out the line types.


In the examples above lines have been trained by clicking “Yes” rather than “No”. An example of both is:

========================================================================
Exits
========================================================================
  ----------------------------------------------------------------------
  Foreground colour of first style run
  ----------------------------------------------------------------------
                   Value   Yes    No   Score
                 -------   ---   ---   -----
                    teal     4     0    0.70
                  silver     0     8    0.28

In this case we can see that exits lines are shown in teal but not silver. If the mapper identified a silver line as an exit line then by selecting that line and clicking “Exits” -> “No” then it has learned that silver lines are not exits.


Other line types will be different again. For example:

  • A prompt line is unlikely to have “kidnapping” in it. It will be more likely to have numbers, and short words like “hp”, and “mana”.
  • Chat messages are likely to have player names in them and general conversation.
  • Lines listing room contents will be likely to have objects in them, rather than room descriptions.
  • Lines listing what mobs or players are in a room will have mob or player names, rather than room descriptions.
  • Combat lines will have action verbs like “slashed” and “hacked” rather than descriptive words.

Saving the map

The mapping database is saved in the plugin’s “state” file which is automatically saved when you save the world file. Thus you must make sure to save the current world file, in order to save the map (and the mapping corpus). Also you might want to save them separately as shown below just in case.

mapper export map
mapper export corpus

Video showing how to train the mapper


Updates

Since making the video above, I have been making various improvements in order to make the mapper work on a wider range of MUDs. The following differences will be obvious:

  • The line information (shown on the right of the output) is no longer retrospective. It was getting too complex (and too buggy) to work out how a line might have been processed. So now it remembers how each line is actually processed and shows that. So, if you teach it something (like “this line is a description”) it will no longer update the screen further up for earlier lines.

  • There are now more configuration options, at present:

    mapper config when_to_draw                             prompt
    mapper config activate_description_after_exits         No
    mapper config activate_description_after_room_name     No
    mapper config add_newline_to_prompt                    No
    mapper config blank_line_terminates_line_type          Yes
    mapper config exits_on_room_name                       No
    mapper config include_exits_in_hash                    Yes
    mapper config exits_is_single_line                     Yes
    mapper config prompt_is_single_line                    Yes
    mapper config exit_lines_start_with_direction          No
    mapper config status_background                        black
    mapper config status_border                            #1B1B1B
    mapper config status_text                              lightgreen
    mapper config uid_size                                 4
    mapper config show_info                                No
    mapper config show_warnings                            Yes
    mapper config show_room_and_exits                      No

    If things are not behaving as expected you could try activating ‘show_info’ and ‘show_room_and_exits’ for a while.

  • You can now interact with the mapper from your world file by making triggers to mark certain lines as definitely of a certain type (eg. this is definitely an exit line). This can help in some cases as the Bayesian analysis can be a bit dodgy with short lines. Details for this will be covered in a post below.

  • There are more training line types:

    • “Ignore” - ignore these lines (useful for marking a line as definitely not a different type. For example: “You are carrying:”

    • “Can’t move” - for messages that you can’t move (eg. “The door is locked” / “You are exhausted” / “You are not allowed in there”). Such lines will, if noticed, cancel any speedwalks.

  • The training line types are in a more logical order: Room name / Description / Exits


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Wed 05 Feb 2020 10:12 PM (UTC)

Amended on Fri 14 Feb 2020 12:56 AM (UTC) by Nick Gammon

Message

Fuzzy logic vs Boolean logic

Bayesian analysis (fuzzy)

My first post (above) described how we could use Bayesian analysis of incoming text to assign a probability that it is one line type or another one. Basically each line is tested against a corpus of words and other attributes (such as the line colour) and then a probability assigned to it. The highest probability for a particular line is considered the “winner”. This could be called fuzzy logic because we are working on probabilities and not certainties.

Comparing against exact criteria (boolean)

During testing however, I have discovered various MUDs where the fuzzy approach doesn’t really work that well. For example:

You are standing in the Village Square.
    This is the centre of Storybook Village.  It is a peaceful area and is
inviting to new players.  Each corner of the square has a small potted money
tree.  In the centre of the square is a wishing well--legend has it that anyone
who throws a coin into the well will be rewarded with knowledge.
    West of the square stands the library, while to the north is a tall clock
tower.  A path south leads towards a pond and an interesting, colourful cottage.
A bright yellow brick road stretches off to the east.
    It is a bright and sunny morning.
You see :
  A large wishing well sitting in the middle of the square.
  A money tree growing in a large ceramic pot (type EX TREE).
Obvious exits are :
  North : Clock Tower
  East  : Yellow Brick Road
  South : Path
  West  : Library
TerraFirmA>

This MUD has some pretty straightforward formatting:

  • Room names always start with: “You are standing in/on/at”.
  • There are weather lines like “It is a bright and sunny morning.” which change depending on the time of day, and which should not be considered part of the description.
  • Things in the room are preceded by “You see :”
  • Exits are preceded by “Obvious exits are :”
  • Exit lines themselves are just: (two spaces)(compass direction)(space):(space)
  • The prompt is a fixed word with no HP, mana or anything like that in it

The exits lines in particular are hard to detect with fuzzy logic, because (taking East as an example) the line consists of four words, three of which are likely to vary, and only one, the first, being a compass direction.

So, using fuzzy logic, the exits lines might be assigned “description” line type (false negative). And the second line here this might be considered to be an exit line (false positive):

It is a peaceful area and is inviting to new players. A bright yellow brick road stretches off to the
east.

That second line has only a compass direction on it, so it is likely to be considered an exit.

The solution? A combination of both

To work reliably with MUDs like this I extended the way the mapper works to provide a programming interface that could be called from triggers that you supply. I initially wanted to avoid this, but having two or three triggers, to make it work reliably, is a lot less work than writing a mapper plugin from scratch.

The programming interface is implemented by using CallPlugin, which lets plugins (or scripts in the main world file) call “exposed” functions in a plugin. In the case of the Learning_Mapper plugin, the plugin ID is “99c74b2685e425d3b6ed6a7d”, so the general format is:

Note that the function to be called is a quoted string: the name of the function. Since it exists in a different script space to where you are calling from you call by name, not by using an actual function there. You can then supply zero or more arguments, which can be one of nil, boolean, number or string (if called from Lua).

For more documentation on CallPlugin see: http://www.gammon.com.au/scripts/doc.php?function=CallPlugin

To take the exits line as an example, first we need to match on the exits line, which is one of the compass directions followed by one or more spaces and then a colon. A suitable regular expression would be:

^  (North|South|East|West|Up|Down)\s+:

The directions are in brackets, first so you can have alternatives, and second so that they are “captured”.

A suitable script call would be:

What this does is tell the mapper that the current line is definitely an “exits” line, and also that the exits to be considered are wildcard 1 (“%1”). This will give a proper positive for exit lines.

The second issue is that we don’t want the Bayesian analysis on other lines that look a bit like exits lines (false positives) so we tell the mapper not to try to deduce exits lines itself.

The line above turns off fuzzy logic for detecting exits. Now, only lines specifically nominated as exits (as in the earlier script line) will be considered exit lines.


The whole trigger will look like this:

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^  (North|South|East|West|Up|Down)\s+: "
   name="Exits_Line"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "exits", "%1"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "exits"))
  </send>
  </trigger>
</triggers>

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


If you think it looks ugly to keep seeing the plugin ID, you can make a helper function, so that you only have to specify the plugin ID once:

The check function is there to raise an error if you misspell a function name.


In a similar vein for the above MUD, we can detect room names:

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^You are standing (in|on|at) (?&lt;location&gt;.*)$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

  local location = "%&lt;location&gt;"
  location = location:sub (1, 1):upper () .. location:sub (2)
  if location:sub (-1) == "." then
    location = location:sub (1, -2)
  end -- if ends with period
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "room_name", location))

  </send>
  </trigger>

</triggers>

The code above extracts the room name from the whole line, capitalizes the first letter, and removes the period from the end of the line.


Finally we can ignore the “You see :” line like this:

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="You see : "
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "ignore"))
  </send>
  </trigger>
</triggers>

Now when you test this, you should see “(certain)” in the status window on the right, rather than a probability percentage.


Exposed functions

  set_line_type (linetype, contents) --> set this current line to be definitely linetype with option contents
  set_line_type_contents (linetype, contents)  --> sets the content for <linetype> to be <contents>
                                                   (for example, if you get a room name on a prompt line)
  set_uid (uid)                      --> use the supplied uid (hashed) instead of hashing the room name and exits
  set_area_name (name)               --> set the name of this area (optional, use if known) - shown at the bottom of the map
  set_not_line_type (linetype)       --> set this current line to be definitely not linetype (can call for multiple line types)
  do_not_deduce_line_type (linetype) --> do not deduce (do Bayesian analysis) on this type of line - has to be set by set_line_type
  deduce_line_type (linetype)        --> deduce this line type (cancels do_not_deduce_line_type)
  get_last_line_type ()              --> get the previous line type as deduced or set by set_line_type
  get_this_line_type ()              --> get the current overridden line type (from set_line_type)
  set_config_option (name, value)    --> set a mapper configuration value of <name> to <value>
  get_config_option (name)           --> get the current configuration value of <name>
  get_corpus ()                      --> get the corpus (serialized table)
  get_stats ()                       --> get the training stats (serialized table)
  get_database ()                    --> get the mapper database (rooms table) (serialized table)
  get_config ()                      --> get the configuration options (serialized table)
  get_current_room ()                --> gets the current room's UID and room information (serialized table)
  set_room_extras (uid, extras)      --> sets extra information for the room (user-supplied)
                                          extras must be a string which serializes into a variable including a table
                                          eg. " { a = 42, b = 666, c = 'Kobold' } "

Line types

For functions that require a line type, line types are a string being one of the following words:

room_name

This line is a room name, and it will be placed at the top of the mapper window for the current room.

description

This line (or lines) are the room description.

exits

This line (or lines) are the room exits.

prompt

This line is a prompt. Not used as such, except that you might want to trigger drawing the room when a prompt arrives.

ignore

This line is to be ignored. Not used as such, but useful for indicating that this line is not some other line type. For example “The sun rises in the east.” can be marked as “ignore” so it isn’t considered part of a description.

cannot_move

This line indicates that you can’t move. For example “The door is locked”, “You don’t have permission”, “You can’t swim”. This is used to cancel speedwalking.


In detail:


set_line_type

Sets the line type of the current line to be “linetype”:

eg.

The contents are optional. If omitted, then the entire line is taken as the line to be used. However if a subset of the line is the useful part then you can supply that.

set_line_type_contents

Sets the contents of a certain type of line to be the supplied contents.

This is intended for situations where one line (eg. a room name) contains other information (eg. possible exits). Or, as in one MUD I saw, you can put the room name into the prompt.

An example of that is:

<triggers>

<!-- Prompt -->

  <trigger
   enabled="y"
   match="^&lt;\d+/\d+hp \d+/\d+m \d+/\d+mv \d+tnl \[(.*)\] &gt;"
   name="Prompt_line"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "prompt"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "prompt"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type_contents", "room_name", [====[%1]====]))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "room_name"))
  </send>
  </trigger>
</triggers>

The above code, triggered by a prompt does this:

  • Tells the mapper this is a prompt line (set_line_type)
  • Tells the mapper to not try to deduce prompt lines in general (do_not_deduce_line_type)
  • Copies the room name (from the prompt - wildcard #1 - and sends it as the contents of the room name (set_line_type_contents)
  • Tells the mapper to not try to deduce room names (as we are telling it the room name here) (do_not_deduce_line_type)

The actual prompt line in this case looks like:

<50/100hp 20/50m 5/100mv 800tnl [The Village Square] >

set_not_line_type

Sets the current line to be not a certain line type. Can be called multiple times for different line types. Could be used for things like weather lines, to indicate that they are not description lines.

For example:

set_area_name

Sets the area (zone) name to be the supplied string. Some MUDs use areas, and you might be able to find their name (eg. from a prompt, or from the room name). This will be shown on the bottom of the map. With no area name specified the MUD name is shown.

For example:

set_uid

If you happen to know a unique identifier for the MUD (eg. a vnum or room number) then you can use this to tell the mapper to use this rather than hashing up the description. If you can get the MUD name reliably (eg. from a prompt) then you could supply that, or that combined with the exits.

For example:

do_not_deduce_line_type

Tells the mapper to not attempt to deduce (do fuzzy logic) certain line types. In general, if you are telling the mapper explicitly that a certain line is a certain type you would also tell it to not deduce that type.

For example:

deduce_line_type

Undoes the effect of do_not_deduce_line_type for a certain line type, in case you want to deduce that type of line again.

get_last_line_type

Gets the previously deduced line type. So, when you get an exits line, you might want to see if the previous line type was a description.

get_this_line_type

Gets this line’s type, as set by set_line_type, if any.

set_config_option

Sets a mapper configuration option. This has the same effect as “mapper config <name> <value>”.

get_config_option

Gets the value of a mapper configuration option.

eg.

Note that CallPlugin will return two values:

  • 0 indicating that CallPlugin worked
  • 4 (or some number) being the value of uid_size

get_corpus

Get the entire corpus as a serialized table.

eg.

get_stats

Get the training stats (how many times each line type was trained) as a serialized table.

eg.

get_database

Get the entire mapping database (rooms and exits) as a serialized table.

eg.

get_config

Get the mapper configuration options as a serialized table.

eg.

get_current_room

Get the current room’s UID and serialized room information. If there is no current room (eg. if you are not logged on, or have not done a LOOK to find where you are, returns nil).

  uid, room = get_current_room ()

eg.

Output:

E178D8D93F8DA7BA05C58446D

room = {
  name = "Intersection of Vertic Avenue and Market Street",
  exits = {
    e = "1D4EC0146F9C05151318A104E",
    w = "5D5D955202A5DA152884FA53C",
    s = "FF9048CDE31EE314995B7657C",
    n = "0FF844933F47B48DC3D4E490D",
    },
  area = "Darkhaven",
  desc = "You stand at the intersection of Vertic Avenue and Market Street.  The\
intersection bustles with activity as citizens go about their business.\
To the east and west runs Market Street, lined with the exotic shops of\
Darkhaven, while Vertic Avenue lies to the north and south.",
  }

set_room_extras

Sets user-supplied extra information for the nominated room by UID. The extra information can be anything you wish, logically a table would be supplied with many entries, such as mobs found in this room, what shops sell, and so on).

  result = set_room_extras (uid, extras)

The UID must exist in the database or nil will be returned. Extras must be a string which can be serialized (read as Lua code). Typically you would supply a table as in the example below, so it can be serialized by the mapper and stored in the database.

The example illustrates how you can turn an actual Lua table into a string (with serialize.save_simple) and then use loadstring to convert the string returned by get_current_room back into a table.

eg.

  -- find the current room's UID
  status, uid, room = CallPlugin ("99c74b2685e425d3b6ed6a7d", "get_current_room")
  check (status)  -- check function call succeeded

  if not uid then
    print "No current room"
    return
  end -- if

  -- example extras

  local extras = {
                 a = 42,
                 b = 666,
                 c = "But does it get goat's blood out?"
                 }

  require "serialize"

  -- set extras for this room (serialize the table into a string)
  status, result = CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_room_extras", uid, serialize.save_simple (extras))
  check (status)  -- check function call succeeded
  if not result then
    print ("Unable to set room extras")
    return
  end -- if

  -- get the room details back
  local status, uid, room = CallPlugin ("99c74b2685e425d3b6ed6a7d", "get_current_room")
  check (status)  -- check function call succeeded

  -- turn serialized room data into a table
  local env = {}
  setfenv (assert (loadstring (room)), env) ()
  local room = env.room

  -- show extras
  require "tprint"
  tprint (room.extras)

Output:

"a"=42
"c"="But does it get goat's blood out?"
"b"=666

Suggestions

  1. If the mapper is not recognizing a line type (eg. a room name) see if there is something unique about that line that could be identified in a script. For example, it might always be shown in a certain colour.

  2. If there is a line that you can easily identify (eg. “Obvious exits: north, south, east, west”) then you can use that to identify nearby lines. If the exits line is directly preceded by a room name, you can work backwards through the output buffer (skipping any input or note lines) and find the preceding output line. That, therefore, is your room name. There is an example of doing that in the Frandum MUD, shown below.

  3. Similarly, you can tell the mapper to start deducing descriptions now, if you know they follow exits. (Or deduce descriptions if you know they follow room names). The function deduce_line_type can be used to activate description deduction.

  4. If you know descriptions lines do not follow a certain obvious line (eg. “There is a bag here.”) then you can tell the mapper to stop deducing descriptions. The function do_not_deduce_line_type can be used to deactivate description deduction.

  5. If certain line types are in a distinctive colour (eg. red) then you can make a trigger that matches everything (“*“) but only if it is that colour (that is an option when you make triggers) and then set the line type to”ignore" for that line.

  6. If information can be pulled out of other lines (eg. a room name from a prompt line, or exits from a room name) then you can use the function set_line_type_contents to tell the mapper what the contents of that line type is.

  7. Receiving a prompt line could be used to trigger disabling line type recognition for certain types (for example, you might never get an exits line directly after a prompt, but always after a description). Thus disabling recognition of such line types can help avoid false positives.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,513 posts)  [Biography] bio   Global Moderator
Date Reply #2 on Wed 05 Feb 2020 10:50 PM (UTC)

Amended on Wed 05 Feb 2020 11:24 PM (UTC) by Fiendish

Message
Quote:
The exits lines in particular are hard to detect with fuzzy logic, because (taking East as an example) the line consists of four words, three of which are likely to vary, and only one, the first, being a compass direction.

I wonder if that's largely because the layout of the text isn't being considered at all and because there are no labels for section boundary indicators.

Right now you're telling it to ignore the "Obvious exits are" line, but if "Obvious exits are" could be labeled as an exits section boundary indicator, and if the analysis of each line looked also at the label probabilities of its neighboring lines for support, I bet it would work better.

Another example: One of your images shows an unlabeled line right between two high probability description lines. That line should be automatically predicted to be a description line with reasonably high probability just by that fact alone even before looking at the content.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Wed 05 Feb 2020 11:11 PM (UTC)

Amended on Wed 05 Feb 2020 11:15 PM (UTC) by Nick Gammon

Message

Right now you’re telling it to ignore the “Obvious exits are” line, but if “Obvious exits are” could be labeled as an exits section boundary indicator, and if the analysis of each line looked also at the label probabilities of its neighboring lines for support, I bet it would work better.

See below for my “neighbouring” comment. However I agree that the “Obvious exits are” line could be treated in a trigger to cancel description recognition until another prompt arrives.

Another example: One of your images shows an unlabeled line right between two high probability description lines. That line should be automatically expected to be a description line with reasonably high probability just by that fact alone even before looking at the content.

The problem is I am trying to deduce in a “streaming” way, so I don’t know with the sequence A B C, when B arrives I don’t know what line type C is, except later. So you would have to go back and alter your opinion of B after the fact.

And you also have the issue that if you conclude B is (say) an exit, then that could alter how you perceive C, which makes it harder for C to be used to influence what you think B is.


The scripting interface with its ability to turn on and off deduction of line types could certainly be used to more efficiently process incoming text based on what has come before.

I did that with The Prophecy mapper because after an exits line arrived, I set a flag to not allow following lines to be descriptions, until we get a prompt. This could certainly be done in multiple ways.

Another way of doing it would be to do this after getting “You see”:

So now any lines after that won’t be considered descriptions.

And then after a prompt start deducing again:


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,513 posts)  [Biography] bio   Global Moderator
Date Reply #4 on Thu 06 Feb 2020 12:16 AM (UTC)

Amended on Thu 06 Feb 2020 07:20 PM (UTC) by Fiendish

Message
Quote:
And you also have the issue that if you conclude B is (say) an exit, then that could alter how you perceive C, which makes it harder for C to be used to influence what you think B is.


I think the way you do it is by storing more than one set of values for each line. One based on word analysis and one based on influence. You analyze all of your words for each line as it arrives. Then you propagate belief from each line to neighboring lines. Then at the end you combine them just for the final determination (but you actually still keep them separately stored).

Consider lines A, B, and C with word analysis values A_w, B_w, and C_w.

The influence on A is some fraction 1/m of B_w plus (for simplicity) the same fraction of the influence on B from C.

That is,

A_i = (1/m)B_w + (1/(m*m))C_w

and

B_i = (1/m)A_w + (1/m)C_w

and

C_i = (1/m)B_w + (1/(m*m))A_w

We can see from the repeated division by m, that if we keep looking farther away for influence the amount of influence drops until it becomes _basically_ zero.

So then

A_result = A_w + A_i
B_result = B_w + B_i
C_result = C_w + C_i

_If_ you wanted to take it further and transmit all of the _i values back out to neighboring lines, you can see that A_i will receive an additional component of (1/m)B_i + (1/(m*m))C_i, which I think is equal to

1/(m*m)A_w + 1/(m*m)C_w + 1/(m*m*m)B_w + 1/(m*m*m*m)A_w

I think it becomes obvious from there that even only a very small number of steps of that converges to zero, so you can stop iterating very quickly and even ignore some of the terms. And in reality using the same fraction of influence from more remote neighbors is probably overweighting them. Probably they should be considered even less, maybe exponentially less the farther away they get.


So maybe you can say that e.g. A_result = A_w + (1/m)B_w + 1/(m*m)A_w + 1/(m*m)C_w and call it square without needing to loop multiple times.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Fiendish   USA  (2,513 posts)  [Biography] bio   Global Moderator
Date Reply #5 on Thu 06 Feb 2020 12:54 AM (UTC)
Message
I think the initial A_i, B_i, C_i in the above should all be divided by 2? But anyway the point is the same.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Thu 06 Feb 2020 06:29 AM (UTC)
Message

Thanks for your comments. First, even unmodified and without external triggers, the mapper seems to work quite well for some MUDs.

The objective is, of course, to make it work for a wide range of MUDs, and after more testing there are still challenges ahead. For example, one MUD I tested today adds a “?” to exit directions that you haven’t been to yet, thus making the exits line keep changing, which changes the hash. I have added an option to deal with that, however it is interesting the variety out there.

After reading your suggestions about a more holistic approach, it occurs to me that, as an option, you could hive off the decision making to the calling plugin.

For example, tell the mapper when to draw a new room “never”. Then have a callback that tells the mapper “draw a room now, and here are the room name, description, and exits”. This would let the calling plugin do an analysis of incoming text and build up a bigger picture.

You might wait for an easily-recognized and unambiguous line (perhaps a prompt, or an exits line) and then the extra plugin could work backwards through the output buffer, perhaps scanning back to the previous prompt. Then it could analyse the lines between the two prompts and see if it thought it could piece together a room name, description and exits.

Perhaps there could be an additional exported function that exposes the Bayesian analysis, which the plugin could apply to each line. It could also look at line colours, sequences, and so on.

Part of this could be your suggestion that description lines, in a certain sequence, are always description lines (for example, between a room name and an exits line).

This new plugin would have one simple job: Determine when you change rooms, and what the new room’s name, description and exits are.

The existing plugin would handle all the other stuff about finding shops, adding notes, showing help, and all the other fiddly stuff that is tedious to get right, but won’t really change from one MUD to another.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #7 on Thu 06 Feb 2020 06:32 AM (UTC)
Message

Then you propagate belief from each line to neighboring lines.

I was toying with the idea of weights, so as you suggest, if a line is a description, then that could increase the weighting of the analysis of the next line (so we increase our belief it is a description, but decrease our belief it is a room name, for example).


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Sat 08 Feb 2020 03:20 AM (UTC)

Amended on Mon 10 Feb 2020 04:46 AM (UTC) by Nick Gammon

Message

Testing on various code bases

I have tested the mapper on various MUDs, in order to confirm whether or not it works, and also to tweak the way it works. Various MUDs have had challenging differences to the way they present their output.

I chose a MUD at random from each code base type (as listed on MUD Connector), preferring one with a higher ranking on MUD Connector, as that was more likely to have an active player base. I skipped a few code bases that only had one or two MUDs listed (or none).

If your MUD code base is not listed, or if its output differs substantially from the one I tested, use the ideas shown below to adapt the mapper to it. With luck, it will work without any customising, however see the suggestions in the post above to get some ideas for what to do if you need to do some work to make it function reliably.

You could browse through these triggers and find ideas for you own MUD, to help make the mapper more reliable.

Any configuration options not specified can be assumed to be the default.

This should be taken as a guide, as individual MUD developers may have changed colour schemes, layouts, and so on, and thus not conform exactly to what I tested. Also, your own configuration options on the MUD may change the way output is displayed (for example, “brief” mode might suppress rooms descriptions which will throw out the mapper).

Also see my post about adapting the mapper for Alter Aeon.


AFKMud (Armageddon)

(DikuMUD derivative)

Configuration

mapper config when_to_draw                             description
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     Yes
mapper config add_newline_to_prompt                    Yes
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       Yes
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config exit_lines_start_with_direction          No

Aber (TerraFirmA)

(Terra Adventure Engine Ver 6.2.0 )

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     Yes
mapper config add_newline_to_prompt                    Yes
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config exit_lines_start_with_direction          Yes

Notes

To help the mapper learn the exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<!-- Exits lines -->

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^  (North|South|East|West|Up|Down)\s+\: "
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "exits"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "exits"))
  </send>
  </trigger>

<!-- Room name -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^You are standing (in|on|at) (?&lt;location&gt;.*)$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

  -- extract out room nane from the line
  local location = "%&lt;location&gt;"
  -- capitalize the name
  location = location:sub (1, 1):upper () .. location:sub (2)
  -- get rid of any trailing period
  if location:sub (-1) == "." then
    location = location:sub (1, -2)
  end -- if ends with period
  -- tell the mapper it is a room name with our extracted name
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "room_name", location))

</send>
  </trigger>

<!-- Prompt -->

<!-- Modify this trigger if you are using a different prompt -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="TerraFirmA&gt;"
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "prompt"))
  </send>
  </trigger>

<!-- Things in the room -->

  <trigger
   keep_evaluating="y"
   match="You see : "
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "ignore"))
  </send>
  </trigger>
</triggers>

Ack!mud (MaDDness)

In-game configuration

config
[ Keyword  ] Option
[-nosummon ] You may be summoned.
[-novisit  ] You may be 'visited'.
[+COLOR    ] You recieve 'ANSI' color.
[+AUTOEXIT ] You automatically see exits.
[-autoloot ] You don't automatically loot corpses.
[-autogold ] You don't automatically take money from corpses.
[-autosac  ] You don't automatically sacrifice corpses.
[-autoass   ] You don't automatically assist your group members.
[+BLANK    ] You have a blank line before your prompt.
[-brief    ] You see long descriptions.
[+COMBINE  ] You see object lists in combined format.
[+PROMPT   ] You have a prompt.
[+TELNETGA ] You receive a telnet GA sequence.
[+FULLANSI ] Your client supports FULL ANSI.
[-display  ] Your are not viewing the ASCII display map.
[-justify  ] Your are not viewing rooms space justified.
Terminal set to:  25 Rows, 80 Columns.

I think the ones I changed were:

config +color
config +autoexit
config +blank
config +telnetga
congig +prompt
config +fullansi
config -display

Now in MUSHclient activate world configuration -> Appearance -> Output -> “Convert IAC EOR/GA to new line”. That makes prompt lines have a newline.

Configuration

mapper config when_to_draw                             description
mapper config activate_description_after_exits         Yes
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          Yes
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config exit_lines_start_with_direction          No

Circlemud (4 Dimensions)

Configuration

mapper config when_to_draw                             description
mapper config activate_description_after_exits         Yes
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          Yes
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config exit_lines_start_with_direction          No

CoffeeMud (Coffee MUD)

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     Yes
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          Yes
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config exit_lines_start_with_direction          Yes

Notes

To help the mapper learn the exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.

If you are using a different prompt change the prompt trigger (below) to match it.


<!-- Prompt -->

<triggers>
  <trigger
   enabled="y"
   match="&lt;*Hp *m *mv&gt;*"
   send_to="12"
   sequence="100"
   name="Prompt_line"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "prompt"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "prompt"))
</send>
  </trigger>

<!-- Exits lines -->

  <trigger
   enabled="y"
   match="^(North|South|East|West|Up|Down)\s*: "
   regexp="y"
   send_to="12"
   sequence="100"
   name="Exits_line"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "exits", "%1"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "exits"))
  </send>
  </trigger>
</triggers>


DUM (Frandum)

Prompt

Set your prompt to be more noticeable, and have a newline, similar to this:

config prompt <%h/%Hhp %s/%Ssp>\n

Configuration

mapper config when_to_draw                             description
mapper config activate_description_after_exits         Yes
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               Yes

Notes

To help the mapper learn the exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<!-- All lines - look for cyan on black -->

<triggers>
  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="*"
   match_back_colour="y"
   match_text_colour="y"
   name="Contents_in_cyan"
   send_to="12"
   sequence="100"
   text_colour="14"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "ignore"))  -- ignore all lines in cyan on black
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "description"))  -- no descriptions follow these lines
</send>
  </trigger>

<!-- Exits -->

  <trigger
   enabled="y"
   match="Obvious exits:  *"
   name="Exits_line"
   send_to="12"
   sequence="100"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "exits", "%1"))  -- it's an exits line
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "exits"))  -- so don't deduce them
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "deduce_line_type", "description"))   -- descriptions follow exits

  -- backtrack and pick up the room name (the line before the exits)
  local last_line = GetLinesInBufferCount ()

  -- go back 10 lines looking for an output line
  for line = last_line - 1, last_line - 10, -1 do
    if GetLineInfo (line, 4) or GetLineInfo (line, 5) then
       -- note or input line, ignore it
    else

      -- the room name is the previous line to the description
      check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type_contents", "room_name", GetLineInfo (line, 1) ))
      break

    end -- output line

  end -- for

  </send>
  </trigger>

<!-- There is xxx here (white on black) -->


  <trigger
   back_colour="8"
   enabled="y"
   match="There is * here."
   match_back_colour="y"
   match_text_colour="y"
   name="Room_contents_line"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "ignore"))  -- ignore this line
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "description"))  -- no descriptions follow these lines
</send>
  </trigger>
</triggers>

Dawn (The Gathering)

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     Yes
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               Yes

Notes

To help the mapper learn the exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<!-- Room name  -->

<triggers>
  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="* [*]*"
   match_back_colour="y"
   match_inverse="y"
   match_italic="y"
   name="Room_name"
   send_to="12"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "room_name", "%1")     -- this is a room name
  callmap ("do_not_deduce_line_type", "room_name") -- so don't try to deduce them
  callmap ("deduce_line_type", "description")      -- start deducing descriptions
  callmap ("set_area_name", WorldName () .. ": %2")-- the area name is wildcard #2

  </send>
  </trigger>

<!-- Exits -->

  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="[Exits: *]"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Exits_Line"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "exits")                 -- this is an exit
  callmap ("do_not_deduce_line_type", "exits")       -- so don't deduce exits
  callmap ("do_not_deduce_line_type", "description") -- and no descriptions follow exits

  </send>
  </trigger>
</triggers>

Training

Don’t bother training exit lines and room names, as the triggers will override that. Train descriptions, prompts, and “do not move” lines.


Dikumud (Arctic)

This one was a bit challenging because I couldn’t find a way of showing the exits automatically, except they were on the prompt line. So, a bit of scripting was needed to pull them from the prompt, put spaces between them, and process them as exits.

In MUSHclient activate world configuration -> Appearance -> Output -> “Convert IAC EOR/GA to new line”. That makes prompt lines have a newline.

Configuration

mapper config when_to_draw                             prompt
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     Yes
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               Yes
mapper config status_background                        black
mapper config status_border                            #1B1B1B
mapper config status_text                              lightgreen
mapper config uid_size                                 4
mapper config show_info                                No
mapper config show_warnings                            Yes
mapper config show_room_and_exits                      No

Notes

To help the mapper learn the exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<!-- Ignore lines in red  -->

<triggers>
  <trigger
   back_colour="8"
   bold="y"
   enabled="y"
   match="*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Ignore_Line"
   send_to="12"
   sequence="100"
   text_colour="9"
  >
  <send>
     check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "ignore"))
  </send>
  </trigger>

<!-- Cyan lines without quotes in them often are room names  -->

  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Room_Name"
   send_to="12"
   sequence="100"
   text_colour="14"
  >
  <send>

  if not string.match ("%1", "'") then
     check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "room_name"))
  end -- if line doesn't have a quote in it

</send>
  </trigger>

<!-- Prompt line - extract the exits  -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="* Exits:*&gt; "
   name="Exits_Line"
   send_to="12"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "prompt")                 -- this is a prompt
  callmap ("do_not_deduce_line_type", "prompt")       -- so don't deduce prompts

  -- set the exits to be the exit letters with a space between them
  callmap ("set_line_type_contents", "exits", string.gsub ("%2", "%a", "%%1 "))

</send>
  </trigger>
</triggers>



Envy (Kallindor)

(Diku based)

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               No

Notes

To help the mapper learn the room names and exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.

<triggers>

<!-- Room names -->

  <trigger
   back_colour="8"
   bold="y"
   enabled="y"
   keep_evaluating="y"
   match="*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Room_name_line"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "room_name")            -- this is a room name (bold white on black)
  callmap ("do_not_deduce_line_type", "room_name")  -- so don't try to deduce them
  callmap ("deduce_line_type", "description")       -- descriptions follow room names
  </send>
  </trigger>

<!-- Exits -->

  <trigger
   back_colour="8"
   bold="y"
   enabled="y"
   keep_evaluating="y"
   match="[Exits: *]"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Exits_Line"
   send_to="12"
   sequence="100"
   text_colour="14"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "exits", "%1")            -- this is an exits line (bold cyan on black)
  callmap ("do_not_deduce_line_type", "exits")        -- so don't try to deduce them
  callmap ("do_not_deduce_line_type", "description")  -- no descriptions until a room name
  </send>
  </trigger>
</triggers>

GodWars (Dark Skies)

The GodWars MUDs were rather challenging because they didn’t always have room descriptions, and without room descriptions you cannot hash up the description to get a room ID.

In the case of Dark Skies, you could put the room name in the prompt, so I hashed up the room name and exits, in the hope that it would give a unique hash most of the time.

Configure the MUD

Put exits and room name into your prompt, and then activate the custom prompt.

prompt <%h/%Hhp %m/%Mm %v/%vmv [%E] [%r]>%l
prompt on
config -map
config +telnetga

In MUSHclient activate world configuration -> Appearance -> Output -> “Convert IAC EOR/GA to new line”. That makes prompt lines have a newline.

Configuration

mapper config when_to_draw                             prompt
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    Yes
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               No

Notes

To help the mapper learn the room names and exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.

<triggers>

<!-- Prompt line -->

  <trigger
   back_colour="8"
   enabled="y"
   match="&lt;* [*] [*]&gt;*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Prompt_Line"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>
  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "prompt")                 -- this is a prompt line
  callmap ("do_not_deduce_line_type", "prompt")       -- so don't try to deduce them
  callmap ("do_not_deduce_line_type", "description")  -- no descriptions after prompts
  callmap ("set_uid", "%2/%3")  -- Exits and room name hashed will be the UID
  callmap ("set_line_type_contents", "room_name", "%3")   -- set the room name
  -- set the exits to be the exit letters with a space between them
  callmap ("set_line_type_contents", "exits", string.gsub ("%2", "%a", "%%1 "))
  </send>
  </trigger>

<!-- Exits line -->

  <trigger
   back_colour="8"
   bold="y"
   enabled="y"
   keep_evaluating="y"
   match="[Exits: *]"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   send_to="12"
   sequence="100"
   text_colour="9"
  >
  <send>
  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "exits", "%1")     -- this is an exits line (bold cyan on black)
  callmap ("do_not_deduce_line_type", "exits") -- so don't try to deduce them
  callmap ("deduce_line_type", "description")  -- descriptions after exits
</send>
  </trigger>
</triggers>

LP (3Scapes)

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    Yes
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               No

Notes

To help the mapper learn the room names and exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.

<triggers>

<!-- Description lines seem to be yellow on black -->

  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Description"
   send_to="12"
   sequence="100"
   text_colour="11"
  >
  <send>
  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  if description_ok then
    callmap ("set_line_type", "description")
  end -- if
  </send>
  </trigger>

<!-- Room names have a minimap on the right and exits in brackets
     The regexp allows for the minimap symbols, you may be able to change this
     if you can turn the minimap off.
-->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^(.*?) \([a-zA-Z,]+\)\s+[NSEW]? \-[-UD]\-\*\-[-UD]\-*"
   name="Room_name"
   send_to="12"
   sequence="100"
   regexp="y"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "room_name" , "%1")     -- this is a room name
  callmap ("do_not_deduce_line_type", "room_name")  -- so don't try to deduce them
  callmap ("deduce_line_type", "description")       -- descriptions after room names
  description_ok = true

  </send>
  </trigger>

<!-- Prompt (simple prompt of "> "). Need to set this so it isn't thought of as "can't move" -->

  <trigger
   back_colour="8"
   enabled="y"
   match="&gt; "
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Prompt_Line"
   regexp="y"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>
  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "prompt")                     -- this is a prompt
  callmap ("do_not_deduce_line_type", "prompt")           -- so don't deduce prompts
</send>
  </trigger>

<!-- Exits line -->

  <trigger
   back_colour="8"
   bold="y"
   enabled="y"
   keep_evaluating="y"
   match="^    There (is|are) [a-z]+ obvious exits?: (?&lt;exits&gt;.*)"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Exits_Line"
   regexp="y"
   send_to="12"
   sequence="100"
   text_colour="11"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "exits", "%&lt;exits&gt;")     -- this is an exits line
  callmap ("do_not_deduce_line_type", "exits") -- so don't try to deduce them
  callmap ("do_not_deduce_line_type", "description")  -- no descriptions after exits
  description_ok = false
  </send>
  </trigger>

<!-- A line with 60 spaces is part of the minimap, so it isn't a description or "cannot move" line -->

  <trigger
   enabled="y"
   match="^ {60,}"
   name="Map_line"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_not_line_type", "description")  -- this isn't a description
  callmap ("set_not_line_type", "cannot_move")  -- nor a "cannot move" line

</send>
  </trigger>
</triggers>

MOO (Sindome)

Server configuration

@ansi 256

As expected, this didn’t map very well. The exits lines were fairly free-format and easily confused with description lines.

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               No

Notes

To help the mapper learn the room names and exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<triggers>

<!-- Room name: red on black -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="*"
   name="Room_name"
   send_to="14"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  if  TriggerStyleRuns [1].textcolour == ColourNameToRGB ('red') and
      TriggerStyleRuns [1].backcolour == ColourNameToRGB ('black') then
    callmap ("set_line_type", "room_name")     -- this is a room name
    callmap ("do_not_deduce_line_type", "room_name")  -- so don't try to deduce them
    callmap ("deduce_line_type", "description")       -- descriptions after room names
  end -- if correct colour

  </send>
  </trigger>

<!-- Ignore lines telling you where you moved to -->

  <trigger
   back_colour="8"
   enabled="y"
   match="^You (head|make your way) (.*?)$"
   match_back_colour="y"
   match_text_colour="y"
   name="Movement_line"
   regexp="y"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "ignore")
</send>
  </trigger>
</triggers>



MUCK (Winter’s Oasis)

As expected, MUCK/MUSH/MUX games similar to this are not suitable for the mapper. They use non-compass directions like:

Obvious Exits: (T) Tutorial, (IM) IC Museum, (ML) MUCK Learning Lab,
               (O) OOC Nexus

A mapper which, by its nature, is designed to take you north/south/east/west is not going to map such locations at all efficiently.

This is not a criticism of the MUCK, it is just a fact of life. MUCK/MUSH/MUX games tend to be more like sandbox worlds, where you can build things, and the output can vary wildly depending on player input.


MUSH (M*U*S*H)

PennMUSH seemed a bit more hopeful than Winter’s Oasis (above) as it actually had compass directions listed as room exits. However I was stymied a bit because there was no prompt as such, and without a prompt line there is nothing to trigger drawing the room, since you don’t know how many exits there are until you get a non-exits line, and you don’t get that if things are quiet.

There was talk in the help files about turning on IAC EOR/GA (GOAHEAD) but I couldn’t see how to do that for my character.


MUX (Maelstrom Earth)

As expected, MUCK/MUSH/MUX games similar to this are not suitable for the mapper. They use non-compass directions like:

 Meeting Rooms <MR>       Free Code Room <FCR>     Quiet Room <QR>
 IC Nexus <IC>            Chargen <CG>             RP Suites <RP>

A mapper which, by its nature, is designed to take you north/south/east/west is not going to map such locations at all efficiently.

This is not a criticism of the MUX, it is just a fact of life. MUCK/MUSH/MUX games tend to be more like sandbox worlds, where you can build things, and the output can vary wildly depending on player input.


Merc (Avatar MUD)

(Diku based)

Configuration

mapper config when_to_draw                             description
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No
mapper config sort_exits                               No

Notes

To help the mapper learn the room names and exits lines the following triggers should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.

<triggers>

<!-- Cyan on black lines are not descriptions but rather things in the room -->

  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="*"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   send_to="12"
   sequence="100"
   text_colour="14"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_not_line_type", "description")  -- this isn't a description

</send>
  </trigger>

<!-- Prompt lines -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="&lt;*&gt;"
   name="Prompt_Line"
   send_to="12"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "prompt")
  callmap ("do_not_deduce_line_type", "prompt")
  callmap ("do_not_deduce_line_type", "description")

</send>
  </trigger>

<!-- Exits lines -->


  <trigger
   back_colour="8"
   enabled="y"
   keep_evaluating="y"
   match="[Exits: *]"
   match_back_colour="y"
   match_bold="y"
   match_inverse="y"
   match_italic="y"
   match_text_colour="y"
   name="Exits_Line"
   send_to="12"
   sequence="100"
   text_colour="15"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "exits", "%1")
  callmap ("do_not_deduce_line_type", "exits")
  callmap ("do_not_deduce_line_type", "room_name")
  callmap ("deduce_line_type", "description")

  -- backtrack and pick up the room name (the line before the exits)
  local last_line = GetLinesInBufferCount ()

  -- go back 10 lines looking for an output line
  for line = last_line - 1, last_line - 10, -1 do
    if GetLineInfo (line, 4) or GetLineInfo (line, 5) then
       -- note or input line, ignore it
    else

      -- the room name is the previous line to the description
      callmap ("set_line_type_contents", "room_name", GetLineInfo (line, 1) )
      break

    end -- output line

  end -- for

</send>
  </trigger>
</triggers>

Mordor (Mordor)

I didn’t have much luck with Mordor, because they seemed to have an outdoor map without room descriptions.

Possibly with more knowledge of how to configure the MUD it could be got to work. I had reasonable success mapping the town.

Example rooms I was able to map:

C3BC  Needful Things (Wedding)
EE84  North End of the Galleria (Wedding)
556C  Nosin's Finest Weapons (Trading Village)
0E58  Nuryan's Tailor Shop (Trading Village)
FF8B  Rings and Things (Wedding)
0C27  Room of Healing (Trading Village)
5653  South End of the Galleria (Wedding)
2A6E  Sweet Delights and Indulgences (Trading Village)
F4DC  The Communal Storage Area (Trading Village)
CC92  the market square.
2C9E  The Reception Hall (Wedding)
BED0  The Tower Exit (MORDOR School)
603D  The Village Fountain (Trading Village)
0F73  The Village General Goods (Trading Village)
EFBF  The Village Inn and Tavern (Trading Village)
EAF3  Town Meeting Hall (Trading Village)
9426  Truly Scrumptious (Wedding)

Rom (Prophecy)

(Heavily modified ROM)

Configuration

mapper config when_to_draw                             prompt
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          Yes
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     Yes
mapper config prompt_is_single_line                    Yes
mapper config exit_lines_start_with_direction          No

Prompt

Set your prompt to show the room name in square brackets, like this:

prompt <%h/%Hhp %m/%Mm %v/%Vmv %Xtnl [%r] >%c%c

You can add colours, but the trigger expects the prompt to look like that. If you want a different prompt, amend the trigger (below). The important things are:

  • That the trigger actually fires (temporarily set it to recolour the line to check that)
  • That the room name is captured as wildcard #1

Triggers

To help the mapper learn the room name the following trigger should be added to your world file.

See http://www.gammon.com.au/pasting for how to copy from below and paste into your world file.


<!-- All lines - suppress lines that are not descriptions -->

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="*"
   name="All_lines"
   send_to="12"
   sequence="1"
  >
  <send>

  -- after exits we don't have descriptions
  if have_exits then
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_not_line_type", "description"))
  end -- if

  </send>
  </trigger>

<!-- Exits -->

  <trigger
   enabled="y"
   keep_evaluating="y"
   match="[Exits: *]"
   name="Exits_line"
   send_to="12"
   sequence="100"
  >
  <send>

  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "set_line_type", "exits", "%1"))
  check (CallPlugin ("99c74b2685e425d3b6ed6a7d", "do_not_deduce_line_type", "exits"))
  have_exits = true

  </send>
  </trigger>

<!-- Prompt -->

  <trigger
   enabled="y"
   match="^&lt;\d+/\d+hp \d+/\d+m \d+/\d+mv \d+tnl \[(.*)\] &gt;"
   name="Prompt_line"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

  function callmap (...)
    check (CallPlugin ("99c74b2685e425d3b6ed6a7d", unpack ({ ... }) ))
  end -- callmap

  callmap ("set_line_type", "prompt")                     -- this is a prompt
  callmap ("do_not_deduce_line_type", "prompt")           -- so don't deduce prompts
  callmap ("set_line_type_contents", "room_name", "%1")   -- it also has the room name on it
  callmap ("do_not_deduce_line_type", "room_name")        -- so don't deduce room names
  have_exits = false

  </send>
  </trigger>
</triggers>

Training

Don’t bother training exit lines and prompts, as the triggers will override that. Train descriptions, and “do not move” lines.


Rot

(Not tested yet)


SWR

(Not tested yet)


SMAUG

(Not tested yet, however see Stock SmaugFUSS below)


Stock SmaugFUSS

Configuration

mapper config when_to_draw                             exits
mapper config activate_description_after_exits         No
mapper config activate_description_after_room_name     No
mapper config add_newline_to_prompt                    No
mapper config blank_line_terminates_line_type          No
mapper config exits_on_room_name                       No
mapper config include_exits_in_hash                    Yes
mapper config exits_is_single_line                     No
mapper config exit_lines_start_with_direction          No

TBA

(Not tested yet)


VME

(Not tested yet)


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Sat 08 Feb 2020 05:29 AM (UTC)

Amended on Fri 21 Feb 2020 06:08 AM (UTC) by Nick Gammon

Message

Mapper database management tools

Version 1.6+ of the mapper has extensive tools for querying the map database, which therefore lets you tidy up loose ends, or find rooms you might have lost.


These commands work all the time, and are not dependent on whether you are logged on, or where you are in the MUD. They simply look at the entire database.

The term uid refers to the unique identifier that identifies each room.


From the internal help (mapper help):

mapper list         --> list rooms meeting certain criteria as follows:
    mapper list     --> all rooms (can be lengthy, naturally)
    mapper list uid ...           --> one or more UIDs
                                      (if one, shows detailed info)
    mapper list name <name>       --> rooms whose names partially match <name>
    mapper list desc <description>--> rooms whose descriptions partially match
                                      <description>
    mapper list notes             --> rooms with any notes at all
    mapper list note <note>       --> rooms whose notes partially match <note>
    mapper list area <area>       --> rooms whose area partially matches <area>
    mapper list orphans           --> rooms which have no rooms leading to them
    mapper list dest <uid>        --> rooms which have an exit to <uid>
    mapper list connect <uid>     --> rooms which are connected to <uid>
    mapper list shop              --> rooms with shops
    mapper list trainer           --> rooms with trainers
    mapper list bank              --> rooms with a bank
    mapper list colour name fore <colour>  --> rooms whose name has
                                               foreground colour <colour>
    mapper list colour name back <colour>  --> rooms whose name has
                                               background colour <colour>
    mapper list colour desc fore <colour>  --> rooms whose description has
                                               foreground colour <colour>
    mapper list colour desc back <colour>  --> rooms whose description has
                                               background colour <colour>
    mapper list colour exits fore <colour> --> rooms whose exits has
                                               foreground colour <colour>
    mapper list colour exits back <colour> --> rooms whose exits has
                                               background colour <colour>
mapper delete <uid>   --> deletes this room from the database
mapper analyse        --> analyse the database and report on line type
                          colours etc.

mapper list

Lists the entire mapper database, like this:

...
6A75  Inside the Western Gate
1CB4  Intersection of Horizon Road and Falcon Road
CA9A  Intersection of Horizon Road and Hawk Street
ED2E  Intersection of Market Street and Falcon Road
D24E  Intersection of Market Street and Hawk Street
6445  Intersection of Vertic Avenue and Justice Road
BFB7  Intersection of Vertic Avenue and Law Avenue
69BF  Intersection of Vertic Avenue and Market Street
0033  Justice Road
83C7  Justice Road
...

The rooms are sorted into alphabetic order by room name, and the room UID on the left is a hyperlink. If you click one you see details about that room:

------------------------------------------------------------------------------
Room:  CA9A -> Intersection of Horizon Road and Hawk Street.
------------------------------------------------------------------------------
You stand at the intersection of Horizon Road and Hawk Street.  To the
east you can see the massive east gate of Darkhaven, while Hawk Street
lies to the north and south, and Horizon Road runs west.
------------------------------------------------------------------------------
Exits: E -> (Not explored) S -> 9490 (Hawk Street) W -> 2937 (Horizon Road) N -> (Not explored)
------------------------------------------------------------------------------

mapper list <uid>

Shows one room identified by its UID.

eg.

mapper list e6fd
------------------------------------------------------------------------------
Room:  E6FD -> Wall Road.
------------------------------------------------------------------------------
Wall Road
  You are walking next to the western city wall.  The road continues further
south and the city gate is just north of here.
------------------------------------------------------------------------------
Exits: S -> 48DC (Wall Road) N -> DDF5 (Inside the West Gate of  Sendar )

mapper list uid [uid …]

Lists one or more UIDs, giving a hyperlink to that room, and its name. If only one UID is given then list that room in detail like the example above.

mapper list 886d f314 bb6c

BB6C  On a Trail Rounding Darkhaven
F314  On the river bank in the deep, dark forest
886D  Thieves Alley
3 matches.

mapper list name <name>

Lists all rooms whose name partially matches <name> specified in the command. Not case-sensitive.

mapper list name gate

Rooms whose name match "gate"
6A75  Inside the Western Gate
BC71  On a Trail East of the Southern Gate
924F  On a Trail North of the Eastern Gate
ADB9  On a Trail South of the East Gate
0FBE  On a Trail South of the Western Gate
C9EB  On a Trail West of the Southern Gate
71A6  Outside the Eastern Gate
DF05  Outside the Southern Gate
55CE  Outside the Western Gate
092A  Outside the Western Gate
10 matches.

mapper list desc <description>

Lists all rooms whose description partially matches <desc> specified in the command. Not case-sensitive.

mapper list desc market street

Rooms whose description matches "market street"
8CDF  Quills and Parchments
C4D1  The Alchemist's
1AA1  The Butcher's Shop
0975  The Dairy Tent
3D57  The Darkhaven Bakery
973B  The Shining Emerald
3809  Weaponry Shop
7 matches.

mapper list notes

Lists all rooms with some user-supplied note attached to them.

mapper list notes

Rooms with notes
AE5D  Darkhaven Square
1D6F  Market Street
2 matches.

mapper list note <note>

Lists all rooms whose note (if any) partially matches <note> specified in the command. Not case-sensitive.

mapper list note merchant

Rooms whose notes match "merchant"
1D6F  Market Street
1 match.

mapper list area <area>

Lists all rooms whose area partially matches <area> specified in the command. Not case-sensitive.


mapper list orphans

Lists all rooms which are orphans. An orphan is a room which no other room has an exit to.

mapper list orphans

Orphaned rooms
7A38  7A38
84AD  84AD
9A76  9A76
74B7  A dead end path on the river bank in the deep, dark forest
AE5D  Darkhaven Square
24CC  Press [ENTER]
6 matches.

These rooms are probably artifacts of failed mapping while you were teaching it line types. For example “Press [ENTER]” looks like a bad room. You can click on the hyperlink to check, and if you think it is a genuine orphan, delete it, eg.

mapper delete 24CC

mapper list dest <uid>

Shows all rooms which lead to UID. This is the opposite of viewing a room and seeing what its exits are. This shows you what rooms lead to the room you are interested in.

mapper list dest 8ce5

Rooms which have an exit to 8ce5:
C974  Entrance to Cleric's Guild
E4FD  Entrance to the Grunting Boar Inn
251C  Market Square
EF7B  The Temple of UL
4 matches.

mapper list connect <uid>

Lists all rooms which are eventually connected to UID. For example, in an area of the game there might be 100 rooms which are connected to each other, but another 1000 elsewhere. If you choose one in the group of 100 then all those (in that group) will be listed. Note that the connection only has to be outward, not inward. Thus an orphaned room might connect to a lot of other rooms (outwards).


mapper list shop

Lists all shops (that is, rooms flagged as a shop by RH-clicking on the room in the map, and checking the “Shop” menu item).

mapper list shop

Rooms with shops
A4B3  Maitland's Armoury
81E7  Melancholy's Maps
3E20  Taiesin's Furniture Shop
A1DA  The Bakery
163A  The Bakery
772E  The General Store
E9C6  The Grunting Boar
6B27  The Magic Shop
843F  The Magic Shop
B836  The Pet Shop
10 matches.

mapper list trainer

Lists all trainers (that is, rooms flagged as a trainer by RH-clicking on the room in the map, and checking the “Trainer” menu item).


mapper list bank

Lists all banks (that is, rooms flagged as a bank by RH-clicking on the room in the map, and checking the “Bank” menu item).


mapper list colour name|desc|exits fore|back <colour>

These six combinations list rooms which have a foreground or background of the name/description/exits line of the nominated colour.

This is intended to find outlier rooms which may have been incorrectly mapped.


mapper analyze

This is intended to analyze every room and work out things that could be useful for making triggers to help with line type detection. For example:

------------------------------------------------------------------------------
Minimum room name length    6 (Armory)
Maximum room name length   63 (forest's ancient trees and vanishing quickly into the darkness.)
Average room name length   26

Room name styles:
Foreground           Background           Styles                         Count
----------           ----------           ------                         -----
white                black                bold                              57
lime                 black                bold                               1
yellow               black                bold                               2

Description styles:
Foreground           Background           Styles                         Count
----------           ----------           ------                         -----
white                black                bold                               2
lime                 black                bold                               1
yellow               black                bold                              61

Exits styles:
Foreground           Background           Styles                         Count
----------           ----------           ------                         -----
white                black                bold                              61
------------------------------------------------------------------------------

From the list above we see that room names are almost always white on black.

Now we can use the colour matching described earlier to see if any of those outliers are in fact wrongly mapped:

mapper list colour name fore lime

Rooms who have a name foreground style of lime:
24CC  Press [ENTER]
1 match.

Indeed, that was the room mentioned earlier that appears to have a wrong room name. So once again we have grounds for deleting that room:

mapper delete 24CC

Similarly for the yellow on black names:

mapper list colour name fore yellow

Rooms who have a name foreground style of yellow:
2E24  forest's ancient trees and vanishing quickly into the darkness.
D420  through the forest to the southeast.
2 matches.

Again they look wrong, so we can probably delete them:

mapper delete 2E24
mapper delete D420

mapper delete <uid>

This is used to delete a room. This is intended for rooms you find when analyzing the database, and realize that they were incorrectly mapped and probably better removed.

You can always re-insert rooms by going to a neighbouring room, exploring into where the room used to be, and then taking all its exits, and going back into it, to re-connect all adjoining rooms.


mapper peek <uid>

This redraws the map, as if you were standing in room UID. This lets you effectively change your view to be as if you were elsewhere. You might do this just to check how the database looks in a particular spot, or maybe to help a newbie find their way.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Sat 08 Feb 2020 08:16 PM (UTC)

Amended on Mon 10 Feb 2020 06:17 AM (UTC) by Nick Gammon

Message

Do your own database analysis

Since the mapper database is available to you, you can write your own tools to analyze it. Here is one example, which you can run from inside MUSHclient (use the Immediate scripting window — Ctrl+I — with Lua as the scripting engine).

Output

Counting rooms:

269 rooms found

Finding match on room name:

61B9CE5AE45097C967044B2D4 Wall Road
D80510F8BBFDAB6D29CAEBD59 Wall Road
E7D9DE9B1468C872202373DA0 Wall Road
011C088113C1A20F432B17CC8 Wall Road

Finding match on description:

291AE5D64E37D41E4B7155DF3
You are walking along wall road, just north of the west gate of  Sendar .
The road continues along the western wall to the north, towards an intersection
with a busy Clan street.

Finding north exits:

Room 8CE529A5CA9CA8809D3751BBF has an exit n to EF7B08176004874874031FD91
Room 9A14DF682ECAEBFF1F4D1DB50 has an exit n to 3D0462278682EF56018855EF6
Room 028EEEDED7B12E244C4F7D6A8 has an exit n to 467B80B8BA2BD29B03578987D
Room EA3DC14CD814CA7948FC36C75 has an exit n to 028EEEDED7B12E244C4F7D6A8

Offline analysis

You can also analyze the database by using the file exported by:

mapper export map

In that case you can use stand-alone Lua (or Lua within MUSHclient if you prefer) to open that file, and process it in the same way as above.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,966 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Sat 08 Feb 2020 08:42 PM (UTC)

Amended on Mon 10 Feb 2020 05:12 AM (UTC) by Nick Gammon

Message

Convert another mapper database to work with the MUSHclient one

The format used by the mapper is very easy to create from scratch. It is basically a serialized Lua table, as shown in the example below.

  • There is one top-level table, the “rooms” table with one entry for every room in the MUD. The key is the unique identifier (UID) which is a 25-character hash of the room description (optionally) concatenated with the exits. If you were coming from an external database where you didn’t know the exact format of the exits string you would probably want to turn off the mapper option “include_exits_in_hash” like this:

    mapper config include_exits_in_hash                    No

    With that option turned off you can now generate a UID that will agree with what the mapper would have generated, for example:

    desc = "You are standing within the expanse of the famous Darkhaven Square.  A\
    stone statue of occupies the square's center, surrounded by gardens of\
    shrubbery which enhance the air of serenity and peace here in the center\
    of the city.  The main road lead away in the cardinal directions, while\
    to the northeast and northwest are forested paths.  The spires of a\
    cathedral can be seen rising to the northwest."
    
    print (utils.tohex (utils.md5 (desc)):sub (1, 25))

    Output:

    8FDA67BCDB3112D05CF8F57DC

    If you are using your own MD5 function you can use the above code to test that you get the same results as shown.

    Alternatively see below for how to use the exits, providing you sort them and activate the option “sort_exits”.

  • The table entries for each room are:

    • exits — this is a table keyed by the (short) exit direction, and with the value being the UID of the room the exit leads to, or the string “0” if we know there is an exit in that direction, but have not yet found what room that is to. The “short” direction is the compass directions in one or two letters (ie. “n” rather than “north”). See the code below for an example of converting long directions to short directions.

    • area — this is the name of the area the room is in, which the mapper defaults to the MUD name.

    • desc — this is the description of the room.

    • notes — these are the notes for the room (optional)

    • extras — extra data supplied by a call to set_room_extras (described above) (optional)

    • Bank — this is true if this room is a bank, otherwise omitted or false

    • Trainer — this is true if this room is a trainer, otherwise omitted or false

    • Shop — this is true if this room is a shop, otherwise omitted or false

In the database produced by the mapper will also be styles for the colour of the first style run in the line, for analysis purposes, however this is entirely optional and can be omitted.


Example of the rooms table

rooms = {
  ["8FDA67BCDB3112D05CF8F57DC"] = {
    exits = {
      ne = "0",
      s = "C34CB5B5F9935358CC99A0DCB",
      nw = "0",
      e = "8CDA23D75D358D0702F4F54A2",
      u = "0",
      w = "70BDD9C6BE29142B2076FEE75",
      n = "DF2433DCC8E10EBE61FEEEFD3",
      },
    area = "Darkhaven",
    notes = "Main city square",
    Bank = true,
    Trainer = true,
    Shop = true,
    desc = "You are standing within the expanse of the famous Darkhaven Square.  A\
stone statue of occupies the square's center, surrounded by gardens of\
shrubbery which enhance the air of serenity and peace here in the center\
of the city.  The main road lead away in the cardinal directions, while\
to the northeast and northwest are forested paths.  The spires of a\
cathedral can be seen rising to the northwest.",
    },

  DF2433DCC8E10EBE61FEEEFD3 = {
    name = "Vertic Avenue",
    exits = {
      s = "8FDA67BCDB3112D05CF8F57DC",
      n = "0",
      },
    area = "Darkhaven",
    desc = "Here the roadway passes by a circular platform, atop which stands a man of\
ultimately stern countenance.  A wall surrounding the cathedral rises to\
the west, and a small forested area lines the eastern roadway.  Vertic\
Avenue ranges to the north and south.",
    },

  C34CB5B5F9935358CC99A0DCB = {
    name = "Vertic Avenue",
    exits = {
      s = "0",
      n = "8FDA67BCDB3112D05CF8F57DC",
      },
    area = "Darkhaven",
    desc = "You are travelling upon the southern portion of Vertic Avenue.  The tents\
of the Darkhaven markets rise high into the air to the east and west.  The\
cobblestone road stretches to the north and south, where you can see a\
bustling intersection.",
    },
    
...


  }  -- end of rooms table

Given this information you could easily take some other mapper database and output a file which looks like the above, and then import it using:

mapper import map

Including exits

If you are keen to include the exits in the hash (which will help in places where lots of rooms have the same description) then you can use the “sorted exits” option, which means you don’t need to know exactly how the exits looked on the MUD output. To do this have these options set for the mapper:

mapper config include_exits_in_hash                    Yes
mapper config sort_exits                               Yes

Now you must sort the exits into alphabetic order, in lowercase, and put a space between them, like in the code below:

desc = "You are standing within the expanse of the famous Darkhaven Square.  A\
stone statue of occupies the square's center, surrounded by gardens of\
shrubbery which enhance the air of serenity and peace here in the center\
of the city.  The main road lead away in the cardinal directions, while\
to the northeast and northwest are forested paths.  The spires of a\
cathedral can be seen rising to the northwest."

-- this table converts long direction names to short names (eg, "north" to "n")

local 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
  

local exits_str = "Exits: north east south west up northeast northwest."

local t_exits = { }
for exit in string.gmatch (exits_str, "%w+") do
  local ex = valid_direction [exit]
  if ex then
    table.insert (t_exits, ex)
  end -- if
end -- for
table.sort (t_exits)
exits_str = table.concat (t_exits, " ")

print (exits_str)
print (utils.tohex (utils.md5 (desc .. exits_str)):sub (1, 25))

Output:

e n ne nw s u w
44A08329EB9768A90A471F023

That will be consistent with what the mapper would have done.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


30,575 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]