Help with mapper

Posted by Death on Tue 08 Jan 2019 12:33 PM — 20 posts, 66,916 views.

#0
Hey Nick,

I've done my best to adapt the mapper you made, and it works quite well.
I've found that it looks quite beautiful when you require "aardmapper.lua" instead of mapper.lua; I love the resizing, and the general look of it all.

Everything is working well with my mapper, except I can't figure out how to make the CLICK to goto (click on map) or the mapper goto * function properly. With mapper.lua it works perfectly, but with aardmapper.lua, it doesn't. I can't seem to adapt it, or figure out what exactly is going on.

I'm getting this error when clicking on a room
"Run-time error
Plugin: AlterAeonMapper (called from world: Demonclient)
Function/Sub: mapper.mouseup_room called by Plugin AlterAeonMapper
Reason: Executing plugin AlterAeonMapper sub mapper.mouseup_room
DesktopMUSHclientluaaardmapper.lua:1187: attempt to call global 'findpath' (a nil value)
stack traceback:
DesktopMUSHclientluaaardmapper.lua:1187: in function 'full_find'
DesktopMUSHclientluaaardmapper.lua:1403: in function 'find'
DesktopMUSHclientluaaardmapper.lua:1556: in function DesktopMUSHclientluaaardmapper.lua:1536>"


and this when I am doing mapper goto *
Run-time error
Plugin: AlterAeonMapper (called from world: Demonclient)
Function/Sub: map_goto called by alias
Reason: processing alias ""
DesktopMUSHclientluaaardmapper.lua:1388: attempt to get length of local 'dests' (a nil value)
stack traceback:
DesktopMUSHclientluaaardmapper.lua:1388: in function 'find'
[string "Plugin: AlterAeonMapper"]:326: in function <[string "Plugin: AlterAeonMapper"]:312>



My code is located here.

https://pastebin.com/EsrTT3PB

I've scoured the forum for quite a while. Some of that code in there is not currently necessary, and some of it is from your recent post with the inquisition mapper. I'm just trying to figure it out.

Any guidance would help.

Cheers,

MasterVivi
Amended on Fri 18 Jan 2019 06:47 AM by Nick Gammon
USA Global Moderator #1
Quote:
\Desktop\MUSHclient\lua\aardmapper.lua:1187: attempt to call global 'findpath' (a nil value)


Your call to mapper.init is insufficient for aardmapper.lua. You have to pass in a findpath implementation from your plugin.

Your init looks like this:

  mapper.init { config = config, get_room = get_room  }


But mine is more involved than that.
https://github.com/fiendish/aardwolfclientpackage/blob/d19bf291bada66c3cd9f76d3aec8b62baac3546c/MUSHclient/worlds/plugins/aard_GMCP_mapper.xml#L2952
Amended on Tue 08 Jan 2019 07:19 PM by Fiendish
Australia Forum Administrator #2
Fiendish, if findpath is required you may want to check for that in init, like I do for get_room:


   supplied_get_room = t.get_room
   assert (type (supplied_get_room) == "function", "No 'get_room' function supplied to mapper.")


That way you get alerted earlier and with a more meaningful error message.
USA Global Moderator #3
Quote:
Fiendish, if findpath is required you may want to check for that in init

Lol. I don't exactly work on aardmapper.lua with interoperability with other people and other MUDs in mind. ^_^

It's fine if someone decides to borrow and modify it, but not having that check doesn't hurt me for two reasons:

  1. I consider the ability to interpret the error message
    aardmapper.lua:1187: attempt to call global 'findpath' (a nil value)
    to be a necessary skill when modifying code for a new context. It says exactly what happened and where.

    I don't have the peculiarities of aardmapper's usage of findpath memorized, so I just went to https://github.com/fiendish/aardwolfclientpackage/search?q=findpath to see where findpath is mentioned in my repository, and it showed me https://github.com/fiendish/aardwolfclientpackage/blob/2ad6646f861cacc41f92ffc9cc0394fe1677e1aa/MUSHclient/lua/aardmapper.lua#L989
  2. Aardwolf's mapper plugin is already written and debugged.
Amended on Tue 08 Jan 2019 11:58 PM by Fiendish
#4
Hey friends,


I've solved all of my issues, and everything is working well, thanks.

I've got quite an issue I need help with if you'd be so kind to help me work it out.


Currently, in my plugin, all directions with an undefined exit = 0 in my state file, and all directions with an exit defined = the vnum they go to.

Example:
  ["70409"] = {
    desc = "70409",
    area = "",
    fillcolour = 65280,
    fillbrush = 0,
    bordercolour = 16777215,
    name = "The Southern Road.",
    exits = {
      w = "70408",
      s = "70410",
      e = "0",
      },
    },


The main recall point in the game is vnum 0, and this makes WEIRD stuff happen to the mapper.

How do you reckon I can go about setting all of those undefined exits to -1, instead of 0, so that I can go in the main recall without destroying the whole mapper and ruining all rooms because it thinks its in other rooms, or continuously is fixing exits.


I tried doing it plugin side, here is the code.

-- -----------------------------------------------------------------
-- Here on "Exits:" line ----- we have changed rooms
-- -----------------------------------------------------------------

function process_exits (exits_str)
  
  -- genereate a "room ID" by hashing the room name, description and exits

  -- break up exits into individual directions
  exits = {}
  
  for exit in string.gmatch (exits_str, "%w+") do
    local ex = valid_direction [exit]
    if ex then
      exits [ex] = "0"  -- don't know where it goes yet
    end -- if
  end -- for

  -- add to table if not known
  if not rooms [uid] then
   rooms [uid] = { name = name, desc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }
  end -- if

  -- save so we know current room later on  
  current_room = uid


  
  -- call mapper to draw this rom
  mapper.draw (uid)

  -- try to work out where previous room's exit led  
  if expected_exit == "0" and from_room then
    fix_up_exit ()
  end -- exit was wrong
    
end -- process_exits


I tried changing
 exits [ex] = "0"  -- don't know where it goes yet
to -1, but it set ALL exits to -1, and wouldn't connect to the other rooms any more; it treated the room as a different area suddenly.

Do you think there is an easy fix to this?
Do you think I should be trying to make changes to my LUA file? I'd think it would be plugin side.

I'm not a professional coder like you guys, I'm just an amateur, but your guidance truly does help.

I appreciate your help...
Amended on Fri 11 Jan 2019 12:47 AM by Death
USA Global Moderator #5
I see "0" in more than one place in the code you posted, but you say you only changed one of them. Did you try changing the other one too? Are there other places that have "0" in your code? Did you try changing those as well?
Amended on Fri 11 Jan 2019 02:52 AM by Fiendish
#6
Hey fiendish,

I initially tried it, and it didn't work, but I guess I didn't change EVERY ONE. I've done it, and it's worked.

Thanks!
USA Global Moderator #7
Always glad to help!
#8
Hey friends,

I've been building my database more and more using my state file, and it's becoming quite big, so I've adapted the materia magica plugin to work..

The map is building, and everything seems to be working, but my DATABASE file is not saving any data into it.

A database file was indeed created, but it remains empty.

The rooms draw, but when I reinstall the plugin, or close and reopen the client, it's all gone again..

What might be the problem?

My code is here

https://pastebin.com/GWJudaqT


Any help would be appreciated.... Cheers.

P.S. the database backup (manual) code in there doesn't work, I've not finished adding that in, I thought that might help with the problem, but I shouldn't try to band-aid fix the problem.
Amended on Wed 16 Jan 2019 05:30 AM by Death
USA Global Moderator #9
Do you know for sure that your save_room_to_database function is being called? If not, why not? If so, are the SQL commands in it failing?
Amended on Wed 16 Jan 2019 03:10 PM by Fiendish
Australia Forum Administrator #10
Is the database indeed empty? Use the Sqlite3.exe command-line program to dump the contents of the rooms table.

eg.


select * from rooms;


You have show_database_mods as true, so you should see debugging displays when rooms are added.
#11
The database is indeed empty, as I've used a program called "DB browser for SQLITE" and it only contains the blank tables.

I've got no messages saying any rooms have been added, only messages saying Fixed exit n from room 10103 to be to 36
(which lets me know when an exit was added to the room.)

Like I said, the rooms are drawing, but I'm getting NO debug messages for adding rooms via the database.


Any help would be appreciated; I've got no idea why this isn't working...
USA Global Moderator #12
So save_room_to_database isn't being called. Look at where it's supposed to be called and check your assumptions.

A quick look at your process_exits function (where save_room_to_database gets invoked) shows ...


if not rooms [uid] then
   rooms [uid] = { name = name, description = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }


thus ensuring that rooms[uid] is always populated.

Then you say

  current_room = uid


and

  local room = rooms [current_room]

and since uid and current_room are the same, room now always contains something because you already populated rooms[uid]

and then you only store something in the database if room is nil, which it is guaranteed to not be.


The basis for debugging a function that isn't being called is finding where it's supposed to be called, looking at the conditions that determine whether it gets called or not, and then walking backwards to see where those conditions are set the wrong way.


Reading the above in reverse, you should see:


if not room then
...
save_room_to_database


if not room then save_room_to_database...


room = rooms [current_room]


if not rooms[current_room] then save_room_to_database...


  current_room = uid


if not rooms[uid] then save_room_to_database...


if not rooms [uid] then
   rooms [uid] =  .... 


aha. rooms[uid] is never empty by the time it checks later whether it's empty, thus preventing it from ever getting put into the database.
Amended on Thu 17 Jan 2019 12:26 AM by Fiendish
#13
Hey friend, I've changed to the following code...

function process_exits (exits_str)

     -- generate a "room ID" by hashing the room name, description and exits
  -- break up exits into individual directions
  exits = {}
 for exit in string.gmatch (exits_str, "%w+") do
    local ex = valid_direction [exit]
    if ex then
      exits [ex] = "-666"  -- don't know where it goes yet
    end -- if
  end -- for
  if not rooms [current_room] then
   rooms [uid] = { name = name, roomdesc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }
  end -- if
  -- save so we know current room later on  
  current_room = uid


--  ColourNote ("rosybrown", "", roomdesc)
--  ColourNote ("olive", "", uid)
  
  local room = rooms [current_room]
  
  -- not cached - see if in database
  if not room then
    -- print ("Loading room", current_room, "from database")
    room = load_room_from_database (current_room)
  end -- not in cache
   
    
  
  if not room then
    -- print ("Added room", uid)  -- debugging
    -- print ("Name", name)
    -- ColourNote ("rosybrown", "", roomdesc)
     
    db:exec ("BEGIN TRANSACTION;") 	

    save_room_to_database (current_room, name, roomdesc)
    save_exits_to_database (current_room, exits)
    
    db:exec ("COMMIT;") 

    -- get it back now
    room = load_room_from_database (current_room)

  end -- if room not there
  
  -- call mapper to draw this rom
  mapper.draw (current_room)    -- redraw room with name

  -- try to work out where previous room's exit led  
  if expected_exit == "-666" and from_room then
    fix_up_exit ()
  end -- exit was wrong
  
end -- process_exits


What I've changed from
 if not rooms [uid] then
rooms [uid] = { name = name, roomdesc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }


to
  if not rooms [current_room] then
   rooms [uid] = { name = name, roomdesc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }


Now I'm getting rooms added to the database, but I'm popping an error..

Run-time error
Plugin: Materia_Magica_Mapper (called from world: Demonclient)
Immediate execution
[string "Plugin: Materia_Magica_Mapper"]:589: bad argument #1 to 'gmatch' (string expected, got table)
stack traceback:
[C]: in function 'gmatch'
[string "Plugin: Materia_Magica_Mapper"]:589: in function 'save_exits_to_database'
[string "Plugin: Materia_Magica_Mapper"]:113: in function 'process_exits'
[string "Trigger: Exits_Line"]:1: in main chunk

every time I enter a room.

When I type look again, it's fine, and when I walk back to the previous room, it fixes exits still.
The problem seems to be only when adding the room to the database. The room itself won't draw until I type look again, and I don't get the error code after looking again.


Hrm.. Is it because current_room is something that is saved and loaded into the database like this?

    save_room_to_database (current_room, name, roomdesc)
USA Global Moderator #14
Quote:
FIXED initial problem.

Please don't remove the content of your posts after you get your answer. The forum is for everyone to learn from. Editing posts to remove their content because _you_ don't need it anymore is poor etiquette.


Quote:
but I'm popping an error..

Did you read the error message?

Quote:
in function 'save_exits_to_database'

Quote:
bad argument #1 to 'gmatch' (string expected, got table)


What more information do you need than that? It looks straightforward to me.
Amended on Thu 17 Jan 2019 10:51 PM by Fiendish
#15
Didn't quite mean to offend you, mate. Next time I won't delete my post for any reason, I didn't really understand that was a problem.

As for the error code, I know what it's saying, but don't quite understand it.

Can you give me some guidance?

Why might it be getting a table instead of a string?

I'm not a coding expert, but I am trying to learn.
USA Global Moderator #16
Quote:
Didn't quite mean to offend you, mate.

I'm not offended. I perceive that your action causes harm, and I'm letting you know.

Looking back at your code now...

Quote:
Why might it be getting a table instead of a string?


The answer to "why" in programming is always "because programs do exactly what you tell them to, no more and no less". You keep focusing on what you yourself are doing when you interact with the code, but you're not looking at what the code is doing. Understanding the user story can certainly be useful, but relying exclusively on it will almost always let you down.

So let's walk backward through the code starting from the error.

Why is gmatch getting a table instead of a string for its first argument?

The first argument to the call to gmatch is 'exits'. So why is exits a table there? It's a table because a table is being passed into save_exits_to_database. So why is a table being passed into save_exits_to_database?

Now, because I'd rather teach you to fish than to set you on fire, it's your turn.

Look at the code you just pasted into the forum and start at your call to save_exits_to_database, where we know that exits is a table, and start going backwards line by line until you find where you define what exits is. What do you find?
Amended on Fri 18 Jan 2019 01:30 AM by Fiendish
Australia Forum Administrator #17
Master Vivi said:

Didn't quite mean to offend you, mate. Next time I won't delete my post for any reason, I didn't really understand that was a problem.


I've reverted your first post back to what it was. The problem is that replies don't make any sense when the original post is deleted or completely changed. Also it is frustrating for people who (in the future) have a similar problem, and find only "found the problem, fixed it" without any explanation about what the fix is.

We are not offended, I'm just pointing out the problems with doing what you did. You aren't the first. :)

A forum like this can be very useful as a knowledge-base - people may search and find a problem, then find the solution, and not have to take the trouble, and time, of posting their own questions. So, win win!
#18
I can't figure it out...

I see two tables in
function process_exits (exits_str)
     -- generate a "room ID" by hashing the room name, description and exits
  -- break up exits into individual directions
exits = {}
 for exit in string.gmatch (exits_str, "%w+") do
    local ex = valid_direction [exit]
    if ex then
      exits [ex] = "-666"  -- don't know where it goes yet
end -- if
  end -- for
  if not rooms [uid] then
rooms [uid] = {name = name, roomdesc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff}
  end -- if
  -- save so we know current room later on  
  current_room = uid


--  ColourNote ("rosybrown", "", roomdesc)
--  ColourNote ("olive", "", uid)
    
local room = rooms [current_room]
  
  -- not cached - see if in database
  if not room then
    -- print ("Loading room", current_room, "from database")
    room = load_room_from_database (current_room)
  end -- not in cache
   
    
  
  if not room then
    -- print ("Added room", uid)  -- debugging
    -- print ("Name", name)
    -- ColourNote ("rosybrown", "", roomdesc)
     
    db:exec ("BEGIN TRANSACTION;") 	

    save_room_to_database (current_room, name, roomdesc)
    save_exits_to_database (current_room, exits)
    
    db:exec ("COMMIT;") 

    -- get it back now
    room = load_room_from_database (current_room)

  end -- if room not there
  
  -- call mapper to draw this rom
  mapper.draw (uid)    -- redraw room with name

  -- try to work out where previous room's exit led  
  if expected_exit == "-666" and from_room then
    fix_up_exit ()
  end -- exit was wrong
  
end -- process_exits


But my code breaks when I change either of those.

With the if not rooms [uid] then rooms [uid]
in place, the mapper draws fine, but won't save to database.
When I change that part, I get that gmatch string error. I've tried replacing those lines in like 1000 different ways, and even tried taking that whole line out of a table, but to no avail.

When I see getting table, I expect it to be exits = {}
or the {...exits=exits...} jam.
No clue how to fix it.
Amended on Fri 18 Jan 2019 07:05 AM by Death
USA Global Moderator #19
Quote:
But my code breaks when I change either of those.

It sounds like your code has inconsistent expectations. It expects a table in one place and a string in another place. But you keep giving the same thing to both and so it fails for obvious reasons.

Quote:
I've tried replacing those lines in like 1000 different ways, and even tried taking that whole line out of a table, but to no avail.

You're flailing, and no programmer ever accomplished anything by flailing. Take a step back from making changes and instead write down with pencil and paper what the code is actually doing and compare that with what you want it to be doing.

Start by putting print(exits_str) at the top of your process_exits function to make sure that exits_str is actually a string and so that you know what it looks like.
Then use that knowledge of what it looks like and go line by line and track the progression of the variables that you're using and producing and compare that with what each function call expects.

If it worked before you made changes, then your changes have violated an expectation. Before you can make changes to any code, you need to know exactly, line by line, what it's doing first. Otherwise your changes will break something, as you've discovered.