Generic Mapping Script

All and any discussion and development of the Mudlet Mapper.
Post Reply
User avatar
SlySven
Posts: 1023
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Generic Mapping Script

Post by SlySven »

Note that you may have issues capturing/matching text that contains characters not in the range of plain ASCII - we do not (yet) properly support anything other than what Qt calls Latin1 characters - thought full support for Utf8 encoded Unicode characters is a target we are tentative putting forward for Mudlet 4.0...!

lunloon
Posts: 9
Joined: Mon Feb 06, 2017 4:55 am

Re: Generic Mapping Script

Post by lunloon »

Is there a tutorial available for making this generic script workable on any MUD?

I'm trying to use the script but I have no idea why it is not working:

1. Start mapping does not show any confirmation
2. It does say Stop Mapping when i do it.
3. It doesn't save
4. It says load but there's nothing to load cos 3.

I also do not understand the purpose of the must do's shown in the script comments, such as to make a notice when there is a OnMoveFail etc.

I can only do simple and relatively basic triggers, aliases, but I have no idea how to use and do scripts.

Jor'Mox
Posts: 1146
Joined: Wed Apr 03, 2013 2:19 am

Re: Generic Mapping Script

Post by Jor'Mox »

The short answer is that no, there is no tutorial, aside from what you see in the comments at the top of the script. Generally, getting a mapper working with the kind of reliability most people would want is a big job, and is typically more than can be handled by someone who is more or less new to coding and Mudlet. That said, I can still try to help out.

First, in order to get the map working initially, you need to give an area name when you use the "start mapping" command, otherwise it won't know what to do with the rooms it sees. After the first time, you shouldn't need to do that, as any other time you want to add a new area, you just need to have already started mapping, stand in the room you want the new area to start in, and use the "set area" alias. As a result of it not having started mapping in the first place, the "stop mapping" command didn't do anything, since there was nothing to stop. Same goes for saving and loading.

The purpose of the various events in the "must do" list, as you put it, is to ensure that the script correctly matches up room information with the direction you moved in. It stores valid exit commands in a list, and matches them up with room names and such each time it sees one. So, without something to let it know that a move attempt failed (via the onMoveFail event being raised), if you tried to go west and then south, but you weren't able to go west, then when you went south, it would think that the room you went into was to the west, rather than the south. This only generally matters when you are creating a map, but unless you are very careful when making a map, it can be a real pain.

The onNewRoom and onPrompt events are 100% needed in order to make the mapper function at all, as those are the things that tell it to do something with the room information that you have (theoretically) captured up to that point. So, when you create the triggers needed to make this script do something, there are four pieces of information you need to get. First, you need to get a room name (this can be from the prompt in some games, or via other methods, depending on what your game allows), and the name needs to be stored map.prompt.room. Second, you need to get the exits of the room you are in (this can also come from the prompt, depending), and the exits need to be stored as a string in map.prompt.exits. Third you need some indication that you have actually seen a room (this is only really separate from the first two if you are getting everything from your prompt). In many cases, the major indicator I recommend using is the line after a room description saying what exits there are, as this only shows when you walk into a room, or look around to see the room you are currently standing in again. And fourth, you need to know when a prompt occurs, as the mapper waits to actually collect the room information until the onPrompt event is raised following an onNewRoom event being raised.

The onVisionFail and onRandomMove events are more for convenience, and are intended to help keep track of where you are in certain circumstances. As such, feel free to add them in if and when it starts to matter to you. Moving around while blind, or through areas where visibility is obscured, is what onVisionFail is for, as it tells the script not to expect all of the room info, and basically just trust the movement commands it has. onRandomMove lets the script know that you have been moved to an adjacent room, but you don't know what direction you were moved in, so it will start trying to make an intelligent guess based on what it sees (easy when the candidate rooms all have distinct room names and/or exits, but harder in monotonous areas).

Looking at all of this though, I notice that I haven't allowed for the possibility of forced movement in a known direction, so that is something I will be adding in shortly.

User avatar
SlySven
Posts: 1023
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Generic Mapping Script

Post by SlySven »

Actually that was quite an informative listing! I haven't really checked in this area myself but does the onRandomMove assume that you have only been moved in an uncertain direction to a neighbouring room or to anywhere? Some MUDs allow the equivalent of "teleportation" to a random (or user directed - it only gets random if you try to go too far! ;) ) room and whilst it is not something that you'd want to engage in whilst mapping it might be something that a malevolent wizard/immortal/other player could hit you with should they have it in for you!

Jor'Mox
Posts: 1146
Joined: Wed Apr 03, 2013 2:19 am

Re: Generic Mapping Script

Post by Jor'Mox »

onRandomMove assumes that the movement is the equivalent of walking to an adjacent room. That said, the script has mechanisms in place to locate you if the room you appear in doesn't match expectations, regardless of what else is going on. Specifically, whenever you aren't mapping, it is always checking the room name and exits to make sure that reality matches expectations, including verifying that the room you came from is connected in the correct direction with the room you just walked into. If things don't match up, it finds the first room that matches the circumstances, and places you there on the map. This also takes into account doors that have been added to the map, allowing them to be either open or closed (assuming that a closed door can potentially not be captured as a valid exit).

So, basically, onRandomMove just tells it to search the rooms adjacent to the room you were in, to find the one that is the best match for where you ended up.

User avatar
SlySven
Posts: 1023
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Generic Mapping Script

Post by SlySven »

Right you are - I've been playing around with building hashes (16-bit) from the room description and then looking up the rooms with matching hashes against the incoming room description as well as the room name. It IS showing promise but I'm finding side effects on the profile save file - the XML storage for, currently around 8K rooms, is bloating it (the overhead to store all the tables of room numbers that match each hash value is rather inefficient) and it also makes the Variable tab in the editor really slow to draw/refresh (a couple of seconds in some cases) - mind you I am using debug compiled code (gcc -g -O0) so that is going to be slower anyhow... It does seem fast enough to work in real time but the code is a bit Frankensteinien as I do not fully have a grip on the Generic Mapping Script (as modified for WoTMUD).

What is nice though is that I ought to be able to share a room name and a 4-hex-digit hash code with others and their client has a fair chance of finding that location even if they do not have the same map (or even the same client - I did a patch for TinTin++ a couple of years back with exactly the same algorithm) as I am using on Mudlet.

Jor'Mox
Posts: 1146
Joined: Wed Apr 03, 2013 2:19 am

Re: Generic Mapping Script

Post by Jor'Mox »

Originally, I was storing room descriptions as room user data, but then I came across rooms that had multiple room descriptions depending on circumstances (day/night, for example), and some people in the game I play use brief mode, which doesn't show room descriptions at all when you walk into a room (it does if you look at it though), so I ended up just junking the idea entirely.

I'm curious what changes you have made, aside from making the relevant triggers and such to gather the data for the script. I'm always looking for ways I can make things better.

User avatar
SlySven
Posts: 1023
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Generic Mapping Script

Post by SlySven »

Well the map I have got hold off does have the description stored in it, but I needed to clean leading and trailing new lines off of it to match my previous work then I fed the description into:
Code: [show] | [select all] lua
function wotmudmapper:hashDescription( descriptionText, report )
	local hash = nil
	local pos = 1

	for index = 1, #descriptionText do
-- LF is 10 decimal, CR is 13 decimal
		if hash == nil then
			-- reset from sentinal value
			hash = 0
		end

		if descriptionText:byte(index) == 10 then
			-- Replace '\n' by actual '\' & 'n' and process those, this is to emulate
			-- exact behaviour of my TinTin++ code - so they produce the same hash
			hash = ( hash + ( pos * 92 ) ) % 65536 -- 92 is '\'
			pos = pos + 1
			hash = ( hash + ( pos * 110 ) ) % 65536 -- 110 is 'n'
		else
			local ccode = descriptionText:byte(index)
			local char = descriptionText:sub(pos,index)
			hash = ( hash + ( pos * ccode ) ) % 65536
		end
		pos = pos + 1
	end

	if report then
		if hash == nil then
			cecho("Description:\n\"<green>"..descriptionText.."<reset>\"\n")
			cecho("Hash is: [<red:white>INVALID<reset>]\n")
		else
			cecho("Description:\n\"<green>"..descriptionText.."<reset>\"\n")
			cecho("Hash is: [<cyan:white>"..string.format("0x%04X",hash).."<reset>]\n")
		end
	end
	return hash
end
I then use non-nil hashes as a numeric key for a table where each value is a lua "list" of matching room numbers which means that, given the incoming room description, I only have to check the descriptions of the rooms with the same hash to find which rooms it could be (typically only one or two unless a description is repeated - which it is for a few location in WoTMUD). It also makes sense to build indexes of room name (key) to matching room numbers (values) because the searchRoomName("string") function is a (slow) linear search and I think a lua table is significantly faster.

I think this technique could be made to work for multiple room descriptions - you just need to capture/store all the variants for each room - and you would then have multiple description hashes for each room but it would still be valid to use a hash worked out from the incoming description to work out which room(s) you could be in - it just increases the chance of having hash collisions and that managing the data gets a bit more complex!

On the other hand it is no use if players use brief mode...

Jor'Mox
Posts: 1146
Joined: Wed Apr 03, 2013 2:19 am

Re: Generic Mapping Script

Post by Jor'Mox »

When mapping a relatively open area, with a lot of rooms with identical room names and exits (say, a large forest area), how do you distinguish between a new room with a different description, and an existing room with an alternate description? Granted, I could obviously insert additional descriptions manually, but since I don't have room numbers to work with in my game, I don't see how I could programmatically determine that a room was in fact an old room with a new description, as opposed to a new room entirely. Either I would have to err one way or the other, which seems like it would make things way more complicated than they need to be.

That said, I could easily add something in, as an option, allowing users to select if they wanted to store room descriptions (or hashes of descriptions) and use them for identification purposes. But, I am concerned that this would create an additional level of complexity in terms of getting the script to an operational state, given the number of times I have been asked for specific details about how to get things working. And, as you point out, there is the potential for slowing things down excessively if too much data gets stored for the sake of making the script slightly more capable of recognizing your location when it gets lost.

And, the problem with brief mode came up when I was sharing a map, because it obviously wouldn't matter if you were making your own map, regardless of what was done for descriptions. So, in a way, adding in descriptions to the map makes it either less portable, or more bulky for no benefit. Not to say I don't like what you have done here, I guess I have just talked myself into, and then back out of implementing some version of it in the script.

User avatar
SlySven
Posts: 1023
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Generic Mapping Script

Post by SlySven »

It is a matter of horses for courses I suppose - it is, I think, useful for WoTMUD which doesn't do the sort of thing that will cause this not to work so well - especially since that MUD steadfastly refuses to adopt new-fangled techniques such as GMCP and other out-of-band data channels which can tell you where you are as a matter of course...

Post Reply