Skip to content

BugFix: Fix original coding errors creating data in TArea::exits member#219

Merged
SlySven merged 4 commits intoMudlet:developmentfrom
SlySven:fix_areaExits
Jan 6, 2015
Merged

BugFix: Fix original coding errors creating data in TArea::exits member#219
SlySven merged 4 commits intoMudlet:developmentfrom
SlySven:fix_areaExits

Conversation

@SlySven
Copy link
Copy Markdown
Member

@SlySven SlySven commented Oct 22, 2014

The specification for this member is:

QMultiMap\<int, QPair\<int, int> > exits

and it is a record of the rooms that are on border on the TArea instance.
The outer QMultiMap key is the room id of the in_area room, and the value
pair is:

first=out_of_area room id
second=direction code

The original direction codes were defined at the start of the TArea.cpp
class file but there did not appear to be any logic to the values used:
N=12, NE=1, E=3, SE=4, S=6, SW=7, W=9, NW=10, UP=13, DOWN=14, IN=15,
OUT=16, OTHER=17. Other than a lua function getAreaExits(areaId) which was
supposed to return just a list of unique keys via a TArea::getAreaExits()
method - i.e. a list of rooms in the given area which were exits to another
area, no other use was made of this data. I propose to replace this list
of values with the better known list stored in the TRoom class header file
but as that does not currently have a value for "other" {a.k.a. Special}
exits I had added a new define: #DEFINE DIR_OTHER with the value 13.

The data IS stored in the map file but is not changed except by calls to:

* (void)TArea::ausgaengeBestimmen() called from:
    (void)TRoomDB::initAreasForOldMaps()
* (void)TArea::fast_ausgaengeBestimmen(int id) called from:
    (bool)TMap::setExit(int from, int to, int dir)
    (void)TRoom::setArea(int _areaID)
    (void)TRoom::setSpecialExit(int to, const QString & cmd)
    (void)TRoom::removeAllSpecialExitsToRoom(int _id)
    (void)dlgRoomExits::save()
* (void)TArea::removeRoom(int room) called from:
    (void)TRoom::setArea(int _areaID)
    (bool)TRoomDB::__removeRoom(int id)

The bugs are that the code in both "ausgaengeBestimmen" methods (with
and without the "fast_" prefix) used the FROM room Id as the first member
of the value pair rather than the TO (a.k.a. exit) room Id for Normal
exits and use the room ID of the TO (a.k.a. exit) room Id as the key for
Special exits (i.e. stores a room that is NOT in the relevant area as a
room IN the area that is an exit from THAT area!) Additionally, even if
the code was correct the existing flawed data would not be corrected when
the map is loaded by running TArea::ausgaengeBestimmen() again because that
is only called at the end of TRoomDB::initAreasForOldMaps() which was
called only for old pre-version 15 map file formats (and we are currently
on 16 - though I have plans in pipeline for something that would require an
increment on that). To further stir the faulty data up previous faulty
code that introduced problems when moving a room from one area to another
may also have contributed to errors with the TArea::exits data.

However:

tl;dr;

running the lua command "auditAreas()" runs TRoomDB::initAreasForOldMaps()
which will fix-up existing maps after this commit has been committed...!

This fixes "getAreaExits is broken (bug 1380822)" 8-)

Signed-off-by: Stephen Lyons slysven@virginmedia.com

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Nov 10, 2014

Any one have any objections to merging this?

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Nov 10, 2014

Sorry, I have not reviewed this yet! I would like to when I can.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Nov 11, 2014

This is so verbose....can you simply say if it's a bug fix and if it
introduces anything incompatible?

Sent from my phone.
On Nov 10, 2014 6:59 PM, "Vadim Peretokin" notifications@github.com wrote:

Sorry, I have not reviewed this yet! I would like to when I can.


Reply to this email directly or view it on GitHub
#219 (comment).

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Nov 12, 2014

Yes - it fixes the specific bug - but theoretically anyone relying on the data involved (which I don't think there can be) should run auditAreas() to fix it up on existing maps. I apologise if I seem to go on a bit in commit comments but that does seem to be the place to leave anything that a change-log or other reviewing process might need.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Nov 12, 2014

I have to agree, this information is useful to know.

On Wed, Nov 12, 2014 at 10:24 AM, Stephen Lyons notifications@github.com
wrote:

Yes - it fixes the specific bug - but theoretically anyone relying on the
data involved (which I don't think there can be) should run
auditAreas() to fix it up on existing maps. I apologise if I seem to go on
a bit in commit comments but that does seem to be the place to leave
anything that a change-log or other reviewing process might need.


Reply to this email directly or view it on GitHub
#219 (comment).

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Nov 14, 2014

It is still weird is best I can describe it. At first I loaded the map (get it here) and only got this result for area 44:

{ 12477 }

Which is a valid area exit room, but there are more than that.

Then I did a pathfind, and the result changed to:

{ 7091, 11400, 11841, 11911, 11912, 11913, 11915, 11916, 11919, 11933, 12057, 12185, 12294, 12383, 12468, 12483, 12510, 13713, 14551, 14829, 15510, 15610, 15810, 24012 }

Which includes non-area exits like 11841.

The actual list is:

{ [12483] = "In a chamber of skulls", [11122] = "Pestilent Way", [11112] = "Nefarious Way", [24012] = "Before the Mhaldor Cathedral", [11400] = "The gates of Mhaldor", [11133] = "Abomination Road", [7091] = "Approaching the temple", [10659] = "Central courtyard" }

Which is generated by this Lua-side function:

function mmp.getAreaBorders(areaid)
    if mmp.debug then
        mmp.getAreaBordersTimer = mmp.getAreaBordersTimer or createStopWatch()
        startStopWatch(mmp.getAreaBordersTimer)
    end

    local roomlist, endresult = getAreaRooms(areaid), {}
    -- sometimes getAreaRooms can give us no result :(
    if not roomlist then mmp.echo("Sorry, seems we can't go there - getAreaRooms("..areaid..") didn't give us any results (Mudlet problem - redownloading the map might help fix it)") return end

    local getRoomExits, getRoomName, getSpecialExitsSwap, contains, pairs = getRoomExits, getRoomName, getSpecialExitsSwap, table.contains, pairs

    -- make a key-value list of room IDs
    local reverselist = {}
    for i = 0, #roomlist do reverselist[roomlist[i]] = true end

    -- obtain a room list for each of the room IDs we got
    --for _, id in pairs(roomlist) do
    for i = 0, #roomlist do
      local id = roomlist[i]
      local exits = getRoomExits(id)
      for _, to in pairs(exits) do
        if not reverselist[to] then
          endresult[id] = getRoomName(id)
        end
      end
      local specialexits = getSpecialExitsSwap(id)
      for _, to in pairs(specialexits) do
        if not reverselist[to] then
          endresult[id] = getRoomName(id)
        end
      end
    end

    if mmp.debug then
        mmp.echo("mmp.getAreaBordersTimer() on areaid "..areaid.." took "..stopStopWatch(mmp.getAreaBordersTimer).."s to run. Returned "..table.size(endresult).." results.")
    end

    return endresult
end

Also what does TRoom::auditExits() WARNING: roomID:11051076 REMOVING invalid (general) exit: <exit> exactly mean... ?

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Nov 17, 2014

This doesn't fix getAreaExits() but does fix auditAreas(), so +1.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 15, 2014

Since this is a broken function, let's make the output better. A table with exit rooms as keys and the room they go to as value?

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 15, 2014

Well since I've got a better idea about Lua tables now (thanks to that gitter hint) I'll tack something on, but I think directions will be the keys. Of course it can be the case that one exit room has multiple exits in different directions to either the same or different rooms.

Though since Mudlet doesn't have separate "name" and "command" items for Special Exits c.f. TinTin++ where an exit has something you type to use it - which for "normal" exits is just something like "e" or "ne" but could also be say what we have as a "special" exit "jump out" which is separate from the "command" that is sent to the MUD server - the key could become a long lua script...

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 15, 2014

One room can go to several different areas though, which complicates it. Just an indexed list of the room id's or a key-value list with the room id and room name will be enough.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 15, 2014

For possible future work on chunked path-finding, a key-value pair of from->to is better. I implemented as such, though this pull is needed for it to work as well, along with a map version increase.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 15, 2014

Can you add a version increase @SlySven and rename the functions something English? With the version 17 re-running the code to populate the exits. Then we can merge in #225 which needs this to operate.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 15, 2014

From a room to a room? But a room can have several exits leading to other
areas.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 16, 2014

Is there anything else that we want to bring in with a map file format increment?

  • I've got some "file magic" I want to include {so that *nix systems at least can examine the file with the file(1) command and use some magic(5) to report some data about the file: the fact that it IS a mudlet map file and number of rooms, number of area and the UTC datetime it was written.} The use of the generic ".dat" extension just compounds the lack of metadata about such files available to things that are NOT the Mudlet application. 😜
  • We can lose the useless (TArea *)->z{min|max}Ebenen members.
  • With an overhaul to (TArea *)->koordinatenSystem() to use and retain its data, and convert the QMap<int, QMap<int, QMultiMap<int, int> > > structure where from the outside to in the keys are the x, y and z coordinates to a QMap<int, QMap<int, QMap<int, QSet > > > with the key order reversed I believe we can improve on the 2D and particularly the 3D mapper paint code - as well as establishing very quickly room spatial collision. Ah, that isn't tied to the file format, we could regenerate it on loading.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 16, 2014

Nothing else, since this commit needs to go into 3.0 and 3.0 is frozen for new features - we're just trying to fix all the new issues introduced and get it released.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 16, 2014

@SlySven Just a version # increase to 17 and rerun initAreasForOldMaps if version < 17 (look at the code in TMap::init)

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 17, 2014

Yeah, that initAreasForOldMaps() (run by TMap::init() for map file formats less than 15 IIRC) runs the same bit of code needed as the lua auditAreas() does - the downside of incrementing the map file version being that shared/crowd sourced maps then become unusable to anyone not using the beta at this point in time. Whereas implementing the code in this PR so far and advising users to use "lua auditAreas()" once on existing maps (and subsequently each time they use their map on the Mudlet application built on this or later code if it has been touched by an earlier Mudlet application instance) may be less disruptive at this point in the release process.

I'd prefer to combine the auto map data fixup with the next other change that forces a map version increment unless you really,really want it done with such an increment now Chris ❓

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 17, 2014

I have no idea how the crowd sourced maps work. How are they updated? If someone does the lua auditAreas(), then uploads that map, it would be the same problem, correct?

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 17, 2014

If you increment the version number, you increment the Mudlet version dependency. This means that if the person doing the mapping upgrades to a new Mudlet, nobody else on the old Mudlet can use the map. So ideally, this happens fewest times possible because it's a pita for everyone involved because of the abscence of forward compatibility.

Just run the map fix thing automatically, no need to actually change the map format until the 'magic numbers' come in, yeah? Which we can bundle with something else since very, very few people are actually going to be making use of that feature.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 18, 2014

Sounds good @vadi2 . If they are adding a new feature, they can do the run. Here's another idea then as well -- how about a mudlet version/map version fetcher for lua so scripts can run any migration code that is needed. To make it easier we can even bundle it in LuaGlobal (or whatever) so there aren't 15 different migration scripts.

@SlySven Do you want to change the mapping to:
QMap<from_id, QPair<QString(exit), to_id> >

or you can merge this and I'll change that code with getAreaExits fix.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 18, 2014

Do you mean QMap > or something else, you keep mentioning it and it seems something is getting cut off.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 18, 2014

The issue is forward compatibility, old Mudlet can't load the a binary map from a newer Mudlet - not sure Lua scripts can do much here.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 18, 2014

yeah, it's the markup.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 18, 2014

Well we can't change the exits variable without a version increase, since the new map will be storing the information differently and importing the old map will throw an error.

We can address this by a new variable, or a version increase. I don't like having cruft hanging around, but for backwards compatibility I suppose a new variable is the only way.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 18, 2014

To clear up any potential confusion -

Any newer Mudlet can load any older map version (and then it saves it in the current map format)
No older Mudlet can load a newer map version

So the practical effect is that we can change the map version format, just not very often, because upgrading Mudlet isn't that seamless (as say the self-updating Chrome). As soon as the person doing the map upgrades (after holding out appropriately long and missing out on the new features) upgrades, everyone else on the older versions has to.

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 18, 2014

I'm going to merge this in then because I like what's been done for the exit mapping and the actual code is cleaner. But I'm going to make new versions of mudlet empty the exits table since it's useless overhead (but still there/saved for compatibility) with a warning in the code of why there's a dead variable hanging around. We can revisit it at a later Mudlet. A good lesson in how wise it is to put data structures that are wrong/may change in the map file.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 18, 2014

Didn't @SlySven mention this has an issue of only allowing 1 special exit between two rooms?

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Dec 18, 2014

It does. If @SlySven doesn't mind, I'll pull this locally and submit a new PR with the faulty exits being removed and a new exit mapping being created.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 22, 2014

@Chris7 This latest commit should sort things out - it provides an additional TArea Class method to massage the area exit data to the wanted QMap<(int)fromRomId, QPair<(QString)direction, (int)toRoomId> > and uses it when TLuaInterpreter::getAreaExits() is called with a second optional boolean argument set to true. I think this will render #225 redundant. 😄

I anticipate that this will/can be revisited when/if we restructure the TRoom::other member to use the exit direction as the key instead of the toRoomId.

It also renames those areaExits finding methods to something in English!

src/TMap.cpp Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this show up in the errors view or the main view?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the main console (as part of the map loading), using the same system as the one that report the Lua modules loaded directly from C++ code and not via LuaGlobal.lua - partly because if the profile is being auto-loaded the messages could be lost otherwise and the user will want to fix the problems ones (and might want to know about the one-time conversion that is taking place for the non-problem one...)
Just noted that I've messed up the qApp->tr() should be qApp->translate() - it'll compile as is but the arguments will be wrong as they are used here - just going to amend last commit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the common user wants to know about this internal map file data stuff. At most it should go into the errors view where the technical one would look.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 22, 2014

How do you think I should best present the directions in the detailed output for that lua function? 😕

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 22, 2014

Same way as http://wiki.mudlet.org/w/Manual:Mapper_Functions#getRoomExits does, without the translation stuff as it has.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 22, 2014

Can I make the defensive point that just because a string is marked as being a candidate for translation that it does not have to be translated, we are perfectly at liberty to leave the "translated" version to be the same as the source when Qt Linguist is used - or indeed the person doing it could produce two translations to ship: one with the lua API using the US English form and one completely rendered in their mother tongue - it may be that we recommend the former but a section of users might wish to go all the way (possibly at their own effort) with the latter. This, I would imagine, could be a selling point for some countries (somehow I keep thinking of France for some reason, of course they'd be wanting the cardinal compass points to be n,e,s,o !)

For the moment I see that we'd get what you describe if I took the hyphens out of the diagonals...

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 22, 2014

I don't think APIs in other languages are an idea that took off. Microsoft has translated APIs with Excel formula names I know, and as far as I can see that just makes coding harder for everyone involved.

The other issue is adding this stuff doesn't guarantee that's what we'll end up with once we decide to take it seriously. So why have half of the stuff translatable in various different forms only for us to decide on something and have to go through and fix everything? Makes more sense to put it off until we're ready to tackle it, form a strategy and apply it.

…ember

The specification for this member is:
    QMultiMap<int, QPair<int, int> > exits
and it is a record of the rooms that are on border on the TArea instance.
The outer QMultiMap key is the room id of the in_area room, and the value
pair is: first=out_of_area room id
         second=direction code
The original direction codes were defined at the start of the TArea.cpp
class file but there did not appear to be any logic to the values used:
N=12, NE=1, E=3, SE=4, S=6, SW=7, W=9, NW=10, UP=13, DOWN=14, IN=15,
OUT=16, OTHER=17.  Other than a lua function getAreaExits(areaId) which was
supposed to return just a list of unique keys via a TArea::getAreaExits()
method - i.e. a list of rooms in the given area which were exits to another
area, no other use was made of this data.  I propose to replace this list
of values with the better known list stored in the TRoom class header file
but as that does not currently have a value for "other" {a.k.a. Special}
exits I had added a new define: #DEFINE DIR_OTHER with the value 13.

The data IS stored in the map file but is not changed except by calls to:
* (void)TArea::ausgaengeBestimmen() called from:
    (void)TRoomDB::initAreasForOldMaps()
* (void)TArea::fast_ausgaengeBestimmen(int id) called from:
    (bool)TMap::setExit(int from, int to, int dir)
    (void)TRoom::setArea(int _areaID)
    (void)TRoom::setSpecialExit(int to, const QString & cmd)
    (void)TRoom::removeAllSpecialExitsToRoom(int _id)
    (void)dlgRoomExits::save()
* (void)TArea::removeRoom(int room) called from:
    (void)TRoom::setArea(int _areaID)
    (bool)TRoomDB::__removeRoom(int id)

The bugs are that the code in both "ausgaengeBestimmen" methods (with
and without the "fast_" prefix) used the FROM room Id as the first member
of the value pair rather than the TO (a.k.a. exit) room Id for Normal
exits and use the room ID of the TO (a.k.a. exit) room Id as the key for
Special exits (i.e. stores a room that is NOT in the relevant area as a
room IN the area that is an exit from THAT area!)  Additionally, even if
the code was correct the existing flawed data would not be corrected when
the map is loaded by running TArea::ausgaengeBestimmen() again because that
is only called at the end of TRoomDB::initAreasForOldMaps() which was
called only for old pre-version 15 map file formats (and we are currently
on 16 - though I have plans in pipeline for something that would require an
increment on that).  To further stir the faulty data up previous faulty
code that introduced problems when moving a room from one area to another
may also have contributed to errors with the TArea::exits data.

However:

tl;dr;

running the lua command "auditAreas()" runs TRoomDB::initAreasForOldMaps()
which will fix-up existing maps after this commit has been committed...!

This fixes ["getAreaExits is broken (bug 1380822)"](http://bugs.launchpad.net/mudlet/+bug/1380822) 8-)

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 23, 2014

Humm, this has become a series of four commits but it would make things clearer if I squashed the last three together IMO. As I understand it that would make the git history cleaner when it gets merged but can be confusing if anyone looks through this PR. @vadi2 Are you OK with the state now before I squash the last two commits into the second one?

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Dec 23, 2014

Yep, go ahead!

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Dec 23, 2014

OK - should be just the two commits ready for someone to merge now. 👍 {Also kills off need for #225 I believe!}

@SlySven SlySven mentioned this pull request Dec 23, 2014
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of the message and the 1/0?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional (ignorable) translated response message - and a numeric return code so international script writers don't have to parse each and every language it gets changed into to know the outcome. Returning just a nil if there is no data does not distinguish between bad input values (note the message and -1 result for that) and no output for valid input (0); neither of these throws a Lua error as the invalid input (wrong type) does; which is what I thought we wanted - only throw errors for "code design" errors not for run-time issues...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the convention with lua we have @vadi2 ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only return the table and that's it - no need for the message because this is for scripting, not the UI. If the input value is bad, then you return nil + the error message (and that is the only time you return a message). We follow the same convention as Lua's standard stuff does.

The message bit isn't really followed though so most functions return nil, which is a problem in case of multiple error messages.

In the case of this function:

  • bad input value would be nil + error message
  • no output for valid input would be an empty table
  • output would just be the table, no status codes or success messages

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, let me reiterate how I see this so I have it clear:

  • If the user's script supplies incorrect types of arguments that cannot be coerced(?) into the wanted one, throw a lua_error() which aborts things and passes a message back to the user about the first argument that is not right - that message should begin with the name of the function that encountered the problem, without "()" but followed by a ':'. This message IMHO ought to be translated via a Qt tr().toUtf8().constData() wrapper when we go multi-lingual as it will help to inform the user in their own language what the problem is. Not furnishing enough mandatory arguments should now be caught by the current standard type checking tests {with lua_pushstring( L, tr(": bad argument #N (..., got %1).arg( luaL_typename, N).toUtf8().constData() ) } type messages as the automatically generated nil values that the missed out arguments get will trip the type checks.
  • If the user's script supplies the correct type of arguments, but one or more values is outside of the acceptable range of values the first return value is a nil and a second value, a message about the problem value should be returned. Like the message in the previous case, in my option, that message should, in the future, be subject to translation into the user's language of choice as it is intended to inform them of the problem rather than be parsed for meaning by other scripts.
  • If the user's script supplies the correct type of arguments, and all values are inside of the acceptable range of values but there is no data to return for that particular set of values then an empty table "{}" or string "" should be returned. We should avoid returning nil in this situation...
  • For the normal case the expected data should be returned, without further strings attached 😜 - I'm not entirely convinced of this, unless it is essential that the additional message provision for wrong value arguments must be nil when things are 🆗, as a script writer I'd welcome positive outcome messages when debugging stuff unless they get in the way by decreasing the Signal-to-Noise ratio of debugging message.

In the case where a function does produce a multi-value return in the event of a bad argument value should all of those values get set to nil then the extra error message gets tagged on? I was going to quote my getMudletVersion() when supplied with a single (literal) string of "table" as an argument - which produces a multi-value return but that would be a bad example because it only does a multi-value return if the (incorrectly chosen) string "table" is supplied so this situation does not apply.

Discuss ❓
If I can get a good grip on this I would consider writing it up for the wiki / sticky it in the development forum 😁

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • yes, no further strings attached - it makes the functions simpler to work with and hasn't been necessary. I also don't know of an API that would so verbosely describe what it gives you.
  • I don't know what value are you referring to.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what value are you referring to.

I was thinking of a (hypothetical) case where the normal output was, say, a 3 value multi-return rather than a table, e.g. perhaps an alternative room coordinate function that might be used thus:

lua x,y,z = getRoomCoordinates( 123 ) echo( "The room is at ("..x..","..y..","..z..")\n" )

If room 123 did not exist, following the nil return plus extra message suggestion should the return be:

nil, nil, nil, "getRoomCoordinates: Warning - bad argument #1 value (Room number 123 does not-exist)."

This is only a contrived example to explain my query. 😉

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nil and the message then. It's not possible for a room coordinate to be nil, so when checking for success you'd just be checking the first return value.

This should go up on the wiki as the Lua API design philosophy for developers.

…rrect

Rename:
(void)TArea::fast_ausgaengeBestimmen(int)
                                     ==> TArea::determineAreaExitsOfRoom
(void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits
(const)(QList<int>)TArea::getAreaExits() const
                                     ==> TArea::getAreaExitRoomIds()

Add new method to return area exit data in new, wanted format:
(const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const

In preparation to revising internal storage representation of area exit
data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member
from public to private area of class.  To permit save and load the
following have had to be made friends of the TArea class:
(bool)TMap::serialize( QDataStream & ) and  (bool)TMap::restore( QString )

Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on
current and all previous map file format versions, will not be needed on
future version as the code to manage the areaExits data is now functional.
Previous code would have done this only for versions prior to 14 files
(current is 16) or if the lua function auditAreas() was manually run.  In
passing also modified code that "fixed-up" "old style" map labels so that
it is no longer run on current version files and pushes any messages that
that creates into the main profile console instead of using standard C++
cout calls which we deprecate now.

All code blocks that have been touched by this series of commits have been
re-formatted to current styles.

Update copyrights on all files touched that have not already been marked as
having been edited by myself.

Revised TLuaInterpreter::getAreaExits(...) to take a second optional
Boolean that if present and true cause it to return data about the area
exit directions and the destination rooms, if false or omitted, returns
only the rooms in the area that have exits out of it, reproducing the
previous implementation.  In either case the result is a table if there
are area exits (or a nil for an isolate area without exits); two additional
values are returned an informative, translatable, text message and an
integer status code that reflects the same information.

When moving a series of rooms to a different area via the 2D mapper's GUI
the recalculations for the area extremes {by TArea::calcSpan()} and the
out of area exits {by TArea::determineAreaExits()} can now be deferred
until the last room has been moved by passing a third true (boolean)
argument to TMap::setRoomArea(...) which defaults to false for other single
room at a time usages.  Though that method keeps a local copy of the areas
that have been modified and thus need updating, should the last room NOT
be processed (null TRooo pointer for room Id) a publicly accessible
"mIsDirty" flag is also used so that recovery code can identify and clean
up those affected areas otherwise.  It is possible that this flag may be
useful in other situations, such as when moving or adding multiple rooms
WITHIN an area.

*** This commit has been rebased so it's history might not be the same as
someone else's copy of it ***

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Jan 5, 2015

Been tweaking again, to get the lua returns inline with the suggestions given for error/fault/no output cases. Bottom line:

  • User supplies wrong type of argument: lua_error is thrown, returning a string diagnostic message.
  • User supplies right type of arguments, but values are faulty: e.g. negative RoomID: nil (primary) return value plus (secondary) string diagnostic message.
  • User supplies right values but no output: empty table or string or signal number returned.
  • User supplies right values but function has no intrinsic output: return boolean true to indicate success.

If there are no objections I'd like to get this one into development branch.

Note: I've raise the point on Gitter that we are ambiguous about duplication of area names - some parts demand unique area names others permit them without hesitation. I have another Pull Request ready to put out that addresses this consistently (prohibits duplicates, fixes existing maps by applying numeric suffixes to duplicates, and applying a generic name to unnamed areas {with a suffix if more than one} - it advises user with what is happening and why and offers them the information of the specific area names before and after that are being affected) and it will only hit the user once per map file. I've thought about this a little and I feel that allowing two areas to have an identical name does not make sense from a semantic point of view and whilst it might surprise a user who falls foul of this issue if they are referring to areas by name as some of the Lua functions permit they are gonna have bigger problems than existing names changing in a comprehensible manner.

Unfortunately the fix I have for this does merge conflict slightly with this one so as to save having two versions here I won't raise a PR until this one has had a final 👍 or 👎 .

The two candidates are is: against current development branch or post application of this one post application of this one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Bad' needs to be lowercase.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Jan 5, 2015

Looks good to me otherwise.

…andard

Due to unawareness of standards I have deviated from them in producing
multiple return values upon success as well as failure.  Whilst I feel that
a second return value being a translatable status string and a third being
an integer encoding of the same might have some merit, particularly in a
fully internationalised and localised version of Mudlet in the future; no
decision has been made over precisely how I18n and L10n will be handled so
using them is a little premature and only confuses things for the moment.

The current methodology is:
* For bad argument TYPE situations: to throw a lua_error and provide a
error message using a fairly uniform construction, I provide these via
Qt's translation system to permit that part of the Lua API to be
translated with the C++ parts of the application's framework.

* For bad argument VALUE situations best practice is for a lua function to
provide a primary nil return value but to also provide a secondary value as
a string message describing the (first) argument value error.  A lua error
is NOT thrown but unless the user catches the error message by providing a
second variable to contain the second return value they may not find out
what is wrong.  Again I choose to provide a translatable message for this.

* For good arguments case that are satisfactory but produce no data, an
empty table, an empty string or a signal number value is an appropriate
primary return value. For example for either type of table that the lua
getAreaExits((int) areaId, <(bool) provide Full data> ) function now
returns, an empty table will be returned for an area which is isolated and
has no exits.  A secondary return value is NOT expected in this situation
as far as I can tell, though I believe one could be useful...

* For good arguments values for functions that provide data then the data
is returned as the primary and only return value.

* For good arguments values for functions that do not return data then
success should be indicated by a single true Boolean return value.

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
SlySven added a commit that referenced this pull request Jan 6, 2015
BugFix: Fix original coding errors creating data in TArea::exits member
@SlySven SlySven merged commit 9d08e4a into Mudlet:development Jan 6, 2015
@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Jan 6, 2015

This needs to be merged into release_30 because it fixes getAreaExits(), a function introduced in 3.0 but was broken.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Jan 6, 2015

OK, so I should make a local branch of release30 and check that I can merge the same series of commits in on my system then put up a PR against that branch, yes?

@Chris7
Copy link
Copy Markdown
Member

Chris7 commented Jan 6, 2015

Yeah

Sent from my phone
On Jan 6, 2015 10:59 AM, "Stephen Lyons" notifications@github.com wrote:

OK, so I should make a local branch of release30 and check that I can
merge the same series of commits in on my system then put up a PR against
that branch, yes?


Reply to this email directly or view it on GitHub
#219 (comment).

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Jan 8, 2015

@Chris7 Done, awaiting merge by a suitably authorised person 😉

@vadi2 vadi2 removed the 3 - Done label Jan 20, 2015
@SlySven SlySven deleted the fix_areaExits branch June 24, 2015 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants