TinTin++ Mud Client The TinTin++ message board

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
TinTin++ Mud Client

[Solution "sortof" found] Script request - suggest

 
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> General Discussion
View previous topic :: View next topic  
Author Message
Slysven



Joined: 10 Apr 2011
Posts: 365
Location: As "Jomin al'Bara" in WoTMUD or Wiltshire, UK

PostPosted: Sat Nov 10, 2012 3:58 pm    Post subject: [Solution "sortof" found] Script request - suggest Reply with quote

I need a function to trace though a given exit from a given room, probably the one I am in that will transverse an unspecified number of VOID flagged rooms until the destination is reached, returning at a minimum the destination room that I would end up in. I would welcome suggestions as to the best way to achieve this but the following points may impact on any solutions that can be conceived:

Current versions of TinTin++ require that a void room has no more than two EXITS, however it is possible that I may have situations in my map that have only ONE which can be valid if I enter the room via a one-way link. The alternatives where the map is "broken" can arise, especially during editing so situations where there are too many or not enough exits should be handled gracefully by the function stopping and returning the room vnumber for the VOID room where it has had to stop.

Although any room or exit can now be flagged as not to be used with the corresponding AVOID flag for my purposes it can be safely assumed that any VOID flagged room is not so flagged, and even if the destination room is flagged "AVOID" I still wish to know it's vnumber.

Similarly rooms, whether VOID or not should ignore any HIDE flags on the room (and also on exits for the VOID rooms).

It is possible for an exit to loop around and return to the starting room, this would not be an issue under normal situations but one should not assume that the starting room is NOT void. So the script should terminate either returning the starting room or the last room encountered before it revisits an already traversed room.

Consider the follow case which it is vital that this situation is detected so that the script does not get stuck in a loop.
Code:

        [ ]    * --- *
         |     |     |
         |           |
        [#]--------- *
         |
         |
        [ ]

In practice I quickly checked with a copy of WinTin++ 2.00.6 that the program would not permit one to move east from the shown starting point...! A scripted function should be robust enough to survive such a contrived booby trap. In passing I found it IS possible to crash TinTin++ if one manually makes a void room loop by say making the exit east from the current room one-way (using #MAP UNLINK {w} from that void room)! Crying

I will try and post a solution that I can come up with in the next few days but I would welcome other people's suggestions... Coffee


Last edited by Slysven on Fri Nov 23, 2012 6:29 pm; edited 4 times in total
Back to top
View user's profile Send private message
Slysven



Joined: 10 Apr 2011
Posts: 365
Location: As "Jomin al'Bara" in WoTMUD or Wiltshire, UK

PostPosted: Sat Nov 10, 2012 9:49 pm    Post subject: [SOLUTION FOUND] Script requirement - suggestions sought Reply with quote

Use the Source, Luke.... Well I found the solution staring me in the face, the exact thing I required is also in the mapper.c source code file, where it is called tunnel_void()! It uses recursion so to implement it in TinTin++ script one has to get around the fact that all variables are global, I've managed that by making each instance of what would be a "local" variable unique with the value of the next room to be considered (all those [%2]s) which should work unless a room is revisited - but if the same room is being revisited then there is a loop situation which will already be causing worse problems...!
Code:
#FUNCTION {tunnelvoid}
{
   #nop Arguments are: 1: from room, 2: this room, 3: iterations - MUST BE 0 when invoked, 4: initial direction;
   #nop echo {tunnelvoid called, iteration:%3, from room:%1, this room:%2, direction:%4};
   #map get {roomflags} {tv_flags[%2]} {%2};
   #if {(${tv_flags[%2]} & 8) == 0}
   {
      #if {%3==0}
      {
         #unvariable {tv_%*}
      };
      #return %2
   };
   #map get {roomexits} {tv_exits[%2]} {%2};
   #math {tv_iterations[%2]} (%3)+1;
   #list {tv_exits_list_keys[%2]} {CREATE} {$tv_exits[%2][]};
   #variable {tv_exits_list_index[%2]} &{tv_exits_list_keys[%2][]};
   #if {&{tv_exits[%2][]} != 2}
   {
      #while {${tv_exits_list_index[%2]}}
      {
         #if {"${tv_exits_list_keys[%2][${tv_exits_list_index[%2]}]}"=="%4"}
         {
            #variable {result} @tunnelvoid{{%2}{${tv_exits[%2][%4]}}{${tv_iterations[%2]}}{%4}};
            #if {%3==0}
            {
               #unvariable {tv_%*}
            };
            #return ${result}
         };
         #math {tv_exits_list_index[%2]} ${tv_exits_list_index[%2]}-1
      };
      #if {%3==0}
      {
         #unvariable {tv_%*}
      };
      #return %2
   };
   #if {${tv_exits[%2][${tv_exits_list_keys[%2][1]}]} != %1}
   {
      #variable result @tunnelvoid{{%2}{${tv_exits[%2][${tv_exits_list_keys[%2][1]}]}}{${tv_iterations[%2]}}{${tv_exits_list_keys[%2][1]}}};
      #if {%3==0}
      {
         #unvariable {tv_%*}
      };
      #return ${result}
   };
   #else
   {
      #variable result @tunnelvoid{{%2}{${tv_exits[%2][${tv_exits_list_keys[%2][2]}]}}{${tv_iterations[%2]}}{${tv_exits_list_keys[%2][2]}}};
      #if {%3==0}
      {
         #unvariable {tv_%*}
      };
      #return ${result}
   }
}

To use this function it needs to be invoked with three required and one optional argument:
  1. The starting room vnumber.
  2. The vnumber of the first room in the direction to be traced.
  3. The value zero (0), this is required internally to track the number of recursions, so that when completed the first instance of the function can clean-up the variables that each of its children created, it may be cleaner for each instance to clean up after itself, but I think this will be faster!
  4. The direction to go to get from the first room to the next, this seems to be optional for the base, invoking instance but I think the child instances that it spawns need it. In practice it seems OK to call the function with this argument an empty {}.
The value returned is the required vnumber of the room at the other end of a chain of void rooms. Note that the function uses variables with names of the form "tv_..." so beware if you already something of that form (I did and only just spotted it before I clobbered it!) If you want to see it recursing itself remove the second "nop" from between the "#" and the "echo" at the top of the function, this will report the arguments supplied to each instance of the function as it is spawned. Coffee
Back to top
View user's profile Send private message
Slysven



Joined: 10 Apr 2011
Posts: 365
Location: As "Jomin al'Bara" in WoTMUD or Wiltshire, UK

PostPosted: Sun Nov 11, 2012 1:32 pm    Post subject: Reply with quote

Arrgh! Stack overflow...? Sad
The above works, but only for short void paths - but if there is more than somewhere between 10 to 20 (and I have some VERY long interconnection void paths) then it crashes, and inspection of the DEBUG STACK display alongside some diagnostic #ECHOs shows that I've exceeded the space available (I have a very large script system in place!)

OK, this function needs to be converted to an iterative (loops inside itself) rather than recursive (calls itself) one - which can be done I understand, but how? Use your Head
Back to top
View user's profile Send private message
Scandum
Site Admin


Joined: 03 Dec 2004
Posts: 3770

PostPosted: Thu Nov 15, 2012 6:57 pm    Post subject: Reply with quote

Wouldn't it be easier to store the current vnum, use #map move, record the destination vnum, and #map goto to get back to the original vnum?
Back to top
View user's profile Send private message Send e-mail
Slysven



Joined: 10 Apr 2011
Posts: 365
Location: As "Jomin al'Bara" in WoTMUD or Wiltshire, UK

PostPosted: Sat Nov 17, 2012 12:21 am    Post subject: Reply with quote

Doesn't the #MAP MOVE trigger the #EVENT {MAP ENTER ROOM} event? The reason I ask that is that the tracing out the exits is something I do to update my information display - which is called as part of a #EVENT {MAP ENTER ROOM} event so you can see things will get nastily circular if I'm not careful! Nope

For what it is worth I have added code to give me a #MAP TUNNEL {<direction>} [{<variable>}] command that invokes the tunnel_void() function - which seems to be a solution - obviously the 'C' function stack that gets used for each recursion is considerably smaller that the equivalent data structure that a TinTin++ script #FUNCTION would use (and may not even be coming from the same memory stack/heap!) Seems to work quite nicely, but I suppose my original query was trying to convert a recursive script into an iterative one. Coffee
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    The TinTin++ message board Forum Index -> General Discussion All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads Get TinTin++ Mud Client at SourceForge.net. Fast, secure and Free Open Source software downloads
TinTin++ Homepage

Powered by phpBB © 2001, 2002 phpBB Group