Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Thu Feb 04, 2016 3:03 am   

#Function help
 
So I decided to convert a couple of specialized aliases to #FUNCTIONs, just to make the odds of accidentally calling them even more remote.

Generally, this works great, but one particular alias resists my attempts, and as a function throws an AV, the xml code for the two are identical, minus the facts that one is an alias and the other is a function, and that their ID numbers differ. The alias looks like this:
Code:

<alias name="EndofScan" id="11">
  <value><![CDATA[#if (@ScanSettings.%char) {
    #execute {//%char/Scan/ScanSettings.%char=0}
   #if ("suspicious" =~ @ScanSettings.String) {
      #switch (@TargetList.a) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         rob %item(TargetList.a,2)~.
      } (@TargetList.b) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #execute %item(@TargetList.b,1)
         rob %item(@TargetList.b,2)~.
      } (@TargetList.c) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 2 {%item(@TargetList.c,1)}
         rob %item(@TargetList.c,2)~.
      } (@TargetList.d) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 3 {%item(@TargetList.d,1)}
         rob %item(@TargetList.d,2)~.
      } (@TargetList.e) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 4 {%item(@TargetList.e,1)}
         rob %item(@TargetList.e,2)~.
      } {
         #if (@Rob.Auto AND @Rob.Attempted) {
            #stop
            Rob.Attempted=0
            nextarea
         } {
            #if (@Rob.Auto AND !@Rob.Attempted) {
               #ok
            }
         }
      }
   } {
      #if (@ScanSettings.A1 OR @ScanSettings.A2) {
         #if (@TargetList) {
            #mark
            #t+ StepCheck
         }
      }
      #switch (@TargetList.a) {
         look
            #execute {//%char/Scan/ScanSettings.StepNumber=0}
         #delkey @TargetList h
      } (@TargetList.b) {
         #execute %item(@TargetList.b,1)
         #repeat 2 {#delnitem @TargetList.b 1}
            #execute {//%char/Scan/ScanSettings.StepNumber=0}
      } (@TargetList.c) {
         #loop 2 {%item(@TargetList.c,1)}
         #repeat 2 {#delnitem @TargetList.c 1}
            #execute {//%char/Scan/ScanSettings.StepNumber=1}
      } (@TargetList.d) {
         #loop 3 {%item(@TargetList.d,1)}
         #repeat 2 {#delnitem @TargetList.d 1}
            #execute {//%char/Scan/ScanSettings.StepNumber=2}
      } (@TargetList.e) {
         #loop 4 {%item(@TargetList.e,1)}
         #repeat 2 {#delnitem @TargetList.e 1}
            #execute {//%char/Scan/ScanSettings.StepNumber=3}
      }
   }
}
#t- ScanEnd
#t- StringCheck]]></value>
</alias>


Some strange things are happening to formatting there but that's essentially what it looks like. I've noticed there ARE a few commands and functions out there that won't work properly if they aren't formatted correctly (#switch is such an offender), so I went ahead and reformatted it all, with no change.

The first large #SWITCH isn't processed in this case, because @ScanSettings.String != "suspicious." As far as I can tell, the script gets down to the "#mark" and "#t+ StepCheck" before the second #SWITCH. Then, in the second #SWITCH, it skips "look", and does "#execute {//%char/Scan/ScanSettings.StepNumber=0}" and stops.

I thought this might be due to the old "lines must begin with commands" bug, but prefacing all such lines with #send doesn't fix the problem.
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Thu Feb 04, 2016 7:52 am   
 
You have a few things that can be corrected.
#DELKEY and #DELNITEM take the variable name as their first parameter, your lines like "#delkey @TargetList h" should be '#delkey TargetList "h" '.
Near the begining you have "rob %item(TargetList.a,2)~." you need an @ in there, just a typo.
In the line "#if ("suspicious" =~ @ScanSettings.String) {" the tilde after the equals appears to be incorrect. If you meant to use pattern matching as mentioned here then I think you have the order reversed.

It is generally good to avoid #EXECUTE. I would suggest rewriting lines such as '#execute {//%char/Scan/ScanSettings.StepNumber=1}' to '#ADDKEY {//%char/Scan/ScanSettings} "StepNumber" "1" '. Lines such as "#execute %item(@TargetList.b,1)" should be thought about whether they might more properly use #SEND
Also the whole //%char/Scan/ScanSettings seems completely pointless when you reference the variable directly as @ScanSettings.key. There are only 2 times such naming should be needed. First is when you have multiple variables all of the same name and you must be sure you access the correct one. Second is when you want to precisely control the creation of the variable to be in a specific package and class, and that might be better done using the #MODULE command. Given that I think there is not a multiple variables issue just use '#ADDKEY ScanSettings "StepNumber" "1" ' for my above suggestion.

As a personal habit I always use some extra parenthesis on conditionals. I have just had to spend too many hours searching for a bug that turned out to be me not remembering the order of operations for logic. As a result of that habit "#if (@ScanSettings.A1 OR @ScanSettings.A2) {" becomes "#if ((@ScanSettings.A1) OR (@ScanSettings.A2)) {". I think it is a good programming habit, because once it becomes automatic it doesn't cost anytime on the typing side but can save hours of debugging.

Without more extensive knowledge of what is going on in the rest of the script to populate the variables I cant suggest too many things.
I might suggest a bit of a change in the TargetList variable. It looks like you are using the key as little more than a counter. It might be simpler to make the whole thing a single list. The code for the entire first #SWITCH would then be replaced with something like
Code:
$count=%item(@TargetList,1)
$rob=%item(@TargetList,2)
$command=%item(@TargetList,3)
#WHILE ($count) {
 #SEND {$command}
 #ADD $count -1
}
#SEND {%concat("rob ",$rob,".")}
I am going to guess that the lines like "#repeat 2 {#delnitem @TargetList.b 1}" could be replaced with "#DELKEY TargetList b" and If am right about that and if you made a change like above then the new replacement would be 'TargetList="" '.

Simplification is your best friend when programming.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Thu Feb 04, 2016 11:04 am   
 
The extra @ in the delkey/delnitem lines is a good catch. Don't know how I've gotten away with doing that for so long, but it's fixed :)

As to the explicit paths: I was told in the past that using #addkey with an explicit path, or #var with an explicit path, was not actually supported, and that while it might appear to work sometimes, it probably screws things up.

In fact, the syntax as you show it always sees the path as a comment, because normally a path containing a variable--predefined or otherwise--is not recognized as a path. The way I got around that in the past was to do something like "#addkey %expand(//%char/Class/Variable, 1) key value". This worked 98% of the time, but when things started to break down, that'd be first to go. If you know of another method that works, please let me know; I tried to avoid #execute there and just couldn't find anything that worked as well.

I explicitly path because this package is global, and might be accessed by 3 sessions more or less simultaneously, each of which has a copy of the variable in question. I had a lot of issues with cross-contamination. I added pathing wherever cross-contamination was happening to ensure that variables went to the right Session, and left it out in places that never had that issue. It seems as though, once created in the right place, the correct variable will be accessed; thus I've generally pathed variables to define them, but not to reference them.


The TargetList variable actually takes the output of the Scan mud command and creates a list of everything matching whatever I've set my target string to, recording the direction it's in, the number of steps away, and the position of the target in the room's stack. Number of steps away is denoted by the key: a (right here), b (one step away), c (two steps away), etc.

The value of each key is a string list that shows direction|stack number|direction|stack number..., so TargetList.b might have a value of "w|2|e|6|n|1|s|4|u|3|d|2" for example. Thus, each target is referred to by two items in the string list. So, when I head to the first thing on the list, I delete those two items. Then, if, for instance, I see an ongoing fight when I arrive in that room, I automatically go back to the starting position and then head to the next target on the list (for courtesy's sake).

It seems needlessly complicated, perhaps, but it allows me to always move to the closest target, rather than the first one to appear on the scan list, and it allows me to do some useful things with determining whether or not I should fight in the room, and allows me to interact with a mob using its position in the room's stack rather than keyword, which can be useful in a number of situations.


Anyway, apart from where I explained my reasoning otherwise, I made the changes you recommended, and in testing for non-suspicious (I had the =~ where I wanted it, but decided to go ahead and make it more specific) targets it worked fine for the 10 minutes or so I tested. I switched to a thief, and attempted to use the rob functionality, and things went haywire again. If the target was in the room with me, it worked, but if I had to move, it would just send "rob 2." (regardless of the actual position in the room stack of the target) and not send the direction commands, while also generating an AV.

The code as it stands now looks like this:
Code:

#if (@ScanSettings.%char) {
   #execute {//%char/Scan/ScanSettings.%char=0}
   #if (@ScanSettings.String="(suspicious)") {
      #switch (@TargetList.a) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #send {rob %item(@TargetList.a,2)~.}
      } (@TargetList.b) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #send {%item(@TargetList.b,1)}
         #send {rob %item(@TargetList.b,2)~.}
      } (@TargetList.c) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 2 {%item(@TargetList.c,1)}
         #send {rob %item(@TargetList.c,2)~.}
      } (@TargetList.d) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 3 {%item(@TargetList.d,1)}
         #send {rob %item(@TargetList.d,2)~.}
      } (@TargetList.e) {
         #if (@Rob.Auto) {
            Rob.Attempted=1
            Rob.Exits=0
         }
         #loop 4 {%item(@TargetList.e,1)}
         #send {rob %item(@TargetList.e,2)~.}
      } {
         #if ((@Rob.Auto) AND (@Rob.Attempted)) {
            #stop
            Rob.Attempted=0
            nextarea
         } {
            #if ((@Rob.Auto) AND (!@Rob.Attempted)) {
               #ok
            }
         }
      }
   } {
      #if ((@ScanSettings.A1) OR (@ScanSettings.A2)) {
         #if (@TargetList) {
            #mark
            #t+ StepCheck
         }
      }
      #switch (@TargetList.a) {
         #send look
         #execute {//%char/Scan/ScanSettings.StepNumber=0}
         #delkey TargetList a
      } (@TargetList.b) {
         #send %item(@TargetList.b,1)
         #repeat 2 {#delnitem TargetList.b 1}
         #execute {//%char/Scan/ScanSettings.StepNumber=0}
      } (@TargetList.c) {
         #loop 2 {%item(@TargetList.c,1)}
         #repeat 2 {#delnitem TargetList.c 1}
         #execute {//%char/Scan/ScanSettings.StepNumber=1}
      } (@TargetList.d) {
         #loop 3 {%item(@TargetList.d,1)}
         #repeat 2 {#delnitem TargetList.d 1}
         #execute {//%char/Scan/ScanSettings.StepNumber=2}
      } (@TargetList.e) {
         #loop 4 {%item(@TargetList.e,1)}
         #repeat 2 {#delnitem TargetList.e 1}
         #execute {//%char/Scan/ScanSettings.StepNumber=3}
      }
   }
}
#t- ScanEnd
#t- StringCheck


As before, this code works perfectly as an alias, just not as a function.
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Thu Feb 04, 2016 3:26 pm   
 
Quote:
It seems as though, once created in the right place, the correct variable will be accessed
Yes this is exactly what I said is the way it works. Try doing this in the command line while not actively running the scripts:
#ALL {#THREAD %char {#SHOW {Beginning %char test};#LOOP 10000 {#ADDKEY ScanSettings {IAm} {%char};#IF (@ScanSettings.IAm!=%char) {#SHOW {Error on try %i};#BREAK};#DELKEY ScanSettings {IAm}};#SHOW {Ended %char test}}}
That code should be enough of a stress test to demonstrate that there is no problem because you have the variables already in existence in each characters' personal package.

If such an arrangement is something you need to ensure when sharing your package over the package library you might use the onload event to create the variables in the correct place. For example:
Code:
#EVENT onload {
 #IF (!@MyPackage_DidFirstTimeLoad) {
  #MODULE %window
  #CLASS MyPackageSettings
  #VAR MyPackage_abc {} ""
  #VAR MyPackage_DidFirstTimeLoad {1}
  #CLASS 0
  #MODULE 0
 }
}

Another way to handle it is to assure that the variable is created using the specific destination at the first point a user can activate the script, this might be better than the onload method. If you have multiple initiation points then you should instead make a test. This is quite easy when you have a specific class name to look in:
Code:
$findvar=%session.GetVar(varName, className)
#IF (!$findvar) {do var making stuff}
Additional documentation for the %session predefined variable can be found at http://www.zuggsoft.com/zmud/comserve.htm There were some minor changes from zMud, but an updated document was never made.

Now that I have a better idea what you are doing I can tell you the shortcuts.
First do the proof above so you can comfortably switch to #ADDKEY and #DELKEY. Although you might be able to skip this because you do not use any full path with the TargetList variable.
Second change your TargetList keys from 'a', 'b', 'c', 'd', and 'e' to '0', '1', '2', '3', '4'. The dot notation can be used with lists and I think doing @var.1 will return the first list entry and not the value of key "1". This would break dot notation as you currently use it, which is why you need #ADDKEY.
Now with the change we use the shortcut that record variables are also lists. Use "$targets=%item(@TargetList, 1)" to get a value like "3=w|2|e|6", you will have to make sure that the auto sort option is set for the TargetsList variable. You should also confirm that you did not get a value with some parenthesis in it.
Then we again use the item trick and one of the few times that #EXECUTE makes sense along with a little string magic, '#EXECUTE {%concat(%pref("iMoveChar"),%replace(%item($targets,1),"=",""))} ' This assembles a string like ".3w" and you get the idea.
For later reference you need to hold onto the key, use %dbkeys and another local variable
Next is a hop with %dbvalues "$targets=%dbvalues($targets)" followed by 2 #DELNITEM.
Then you have to look at whether anything is left in the local variable. and choose either #DELKEY to get rid of the finished group or #ADDKEY to update the information with the removed entries.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Wed Feb 10, 2016 5:12 am   
 
Well, I decided to go through and do a complete rewrite. I'd originally planned to use 0-4 as keys, but at the time didn't know that I should do "#if (%db(Var,Key))" in that instance instead of "#if (@Var.Key)." Writing an equipment database script taught me a lot about DB manipulation and local variables though, and it's nice to be able to use %min as I originally planned to find the nearest target instead of a #switch.

I think maybe you misunderstood my issues with cross-contamination. I was having it happen at almost every instance of defining a variable, even one that already existed. The right variables were always referenced, but when not pathed, duplicates would occasionally be created in other sessions. I'm certain that corruption of some sort caused that problem, but it seemed to be a very common sort of corruption. I have a "recast" script that simply uses %char as the key of a variable so that even if there's a problem like that, the correct key will be referenced. Until I started using the #execute syntax, I would on rare occasions find variables in one session with the name of another session as a key in addition to its own. However, I'm going to go ahead and remove pathing except for where the package is initialized--I'll create and explicitly path all the necessary variables there. If I have problems in the future I'll just assume corruption and work on that instead of finding ways around it.

It's amazing looking back at some of my scripts and realizing how many redundant checks and explicit paths and unique identifiers I added because I was attempting to circumvent problems caused by corruption. I don't have that much trouble anymore, I try to keep backups of every package available so that I can quickly rename some .pkg files and fix whatever issue I'm having.

A couple questions:
1. Is the "begin all lines with commands" directive still applicable? From your suggestions I assume yes.
2. Why does using #execute make sense in an instance where you can easily use some other method, but not make sense where there's no reliable alternative?


Anyway, I finally got a little time to myself and rewrote the function. To test it, I left the rest of the package alone (because I know it works) except for the #switch that changes my keys from numbers to letters, which I commented out. I then called the new function instead of the old alias and tested, and again, for some reason, an AV was generated.

Because I don't believe in coincidences, I created a new alias, pasted the function into that, and called that instead of the new function, and it worked fine. I really don't understand why this is happening. There must be some sort of bug with #Functions? Every other one I've tried has worked flawlessly, it's just this one step in this one package that doesn't translate. I can't really use the script debugger or trigger debug messages to figure it out, because it just doesn't function as a function.

New code:
Code:
#t- ScanEnd                                              //as a function, this line is processed before the AV pops up
#t- StringCheck                                                //as a function, AV stops this line from processing
$Settings=@ScanSettings
#if ($Settings.%char) {
   $Settings.%char=0                                         //Don't make me repeat myself.
   $List=@TargetList
   $Distance=%min(%dbkeys($List))                            //I check these more than once, may
   $Direction=%item(%db($List,$Distance),1)                  //as well abbreviate for clarity and brevity
   $Rob_Target=%item(%db($List,$Distance),2)                 //Target acquired.
   #if ((!$List) && (@Rob.Auto)) {                                //!$List functions for rob variant only
      #if (@Rob.Attempted) {
         #stop                                                  //I got it! Aww I lost it. I give up.
         Rob.Attempted=0
         nextarea                                             //TODO: make this a function so I can "start lines with commands" other than #execute
      } {
         #ok
      }
   } {
      #if (($Settings.A1) OR ($Settings.A2)) {
         #t+ StepCheck
      }
      $Settings.LastPath=(%subchar(%concat($Distance,$Direction),"01h",""))  //.0n .1n and .2n all send "n" twice. Weird. "h" = "Here"

      $Settings.StepNumber=(%replace(($Distance-1),"-1","0"))                //Steps before target room can't be less than zero. This is not a time machine.

      #repeat %replace($Distance,"0","1") {#send %replace($Direction,"h","look")}  //I'll fix this later so the first item in $List."0" is "look" instead of "h".

      #if (($Settings.String="(suspicious)") && (@Rob.Auto)) {
         #addkey Rob {Attempted=1|Exits=0}
      }
      #if ($Settings.String="(suspicious)") {
         #send {rob $Rob_Target~.}                                               //I'm here. Now GIMME.
      }
      #if (%item(%db($List,$Distance),3)) {                //here's how I know if I should bother with #delnitem or just go to #delkey
         #repeat 2 {#Delnitem TargetList.$Distance 1}     //Tests show delnitem only works with non-local variables.
      } {
         #Delkey TargetList $Distance //Since delnitem is already non-local, same here to skip the "Target_List=$List" step entirely.
      }
   }
   ScanSettings=$Settings
}
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Wed Feb 10, 2016 5:57 am   
 
For the AV I can only guess the problem is coming from the mapper commands, #STOP or #OK. Just keep the thing as an alias, there is nothing wrong with an alias being called.

Quote:
A couple questions:
1. Is the "begin all lines with commands" directive still applicable? From your suggestions I assume yes.
As far as I know that was never a requirement, just a best practice. Consider your line "#repeat %replace($Distance,"0","1") {%replace($Direction,"h","look")}", when that runs it is producing a line to be executed "%replace($Direction,"h","look")" which certainly does not start with a command. The result is that whatever is produced is sent to the mud which is what you want in this case.
Quote:
2. Why does using #execute make sense in an instance where you can easily use some other method, but not make sense where there's no reliable alternative?
In general using #EXECUTE is a bad idea. The command exists to activate as script some string that was generated by the script. It is tends to be a bad idea because you can usually write it in a faster way. The specific spot I suggested using #EXEC was with a string created like ".3n". Last time I checked the movement character only works when done from the command line, and since it works within #EXEC that should tell you something about how #EXEC processes. The portions of your script that used it that I was most critical of have reliable alternatives to how you were using it. The simplest being start the script with "#CLASS {%char}" and end the script with "#CLASS 0". Those command change where the variable will be made, and the search order to find which variable to use. If you want to know all the details search the forums for the words "context" and "scope" and you should be able to find the old discussions that detail the exact behavior.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4578
Location: Pensacola, FL, USA

PostPosted: Wed Feb 10, 2016 7:13 am   
 
You should be able to pass the .3n to the #SLOW command if you want to avoid the #EXEC.
_________________
Discord: Shalimar#3679
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Thu Feb 11, 2016 9:33 am   
 
Hey, the "#CLASS {%char}" is a method I never thought of. Anyway, I'm going to try to stick assuming modules will path variables correctly on their own now.

If nothing else, failure to do so indicates a corruption issue I should take care of.

Any reason why "%pref("iMoveChar")" wold always return "46" for me?

And thank you for looking things over so thoroughly!

I apologize for my walls of text--I tend to rewrite everything half a dozen times in attempt to make my posts shorter.
Then I either give up on shortening, or give up on asking all the questions I want to ask or making all the points I want to make.

So I'm trying, anyway...?

As for #slow, I am not a fan of the way it works. #step doesn't execute the next step, it executes the last one sent before the walk was aborted, unless you use #pause, in which case you now have two commands you need to send for every step you take, and an annoying echo in every single room that you can't gag. Timeouts are annoying, and you can't turn them off without the slow walk just randomly sending the next direction; using an arbitrarily long timeout works, but whenever I have to reimport characters I have to change them again (setting as default rarely works properly for me--and leads to having to manually change settings on any child windows I create when it does).

I have a script that uses #slow, but I've long contemplated passing expanded slow walks into stringlists instead and using %pop.
I'd have done so already if I could figure out how to %pathexpand by name rather than value. You can't even enter "#PATH" without arguments and snag it from the list of every speedwalk you have, because that's treated like a #say or #echo and can't be processed.

Well there I go again, generating a wall of text. I deleted a couple paragraphs though, if that makes everyone feel better.
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4578
Location: Pensacola, FL, USA

PostPosted: Thu Feb 11, 2016 1:27 pm   
 
Sounds to me like the map is not properly confirming that you moved into the room.
An #OK trigger would fix that.
_________________
Discord: Shalimar#3679
Reply with quote
Vijilante
SubAdmin


Joined: 18 Nov 2001
Posts: 5182

PostPosted: Thu Feb 11, 2016 4:06 pm   
 
To answer one question the %pref("iMoveChar") returning 46...I had no idea it would return the ASCII value for the character. One more step and it is solved: %char(%pref("iMoveChar")) or since I am looking at the help the even shorter version that I forgot about: %char(".")

You seem to be echoing all the reasons that I tend to completely override the mapper. You can override just the walking with a little less. The trick to doing it is to set the mapper for slow walking and then detect when the mapper thinks it is going to be walking a few rooms. Use an input trigger to detect that direction was sent and then check %destroom to see if the direction is a single step or part of a longer walk. When it is part of a longer walk then you want to record the path to a variable and use #STOP and "#NODIR 1" to kill the mapper's walking routines then #QUEUE the first direction. When the direction matches to just a single step you don't have to do anything special. You trigger on a line that indicates completed movement, I prefer using a substate of the input trigger, and send the next direction in your path.

The hard part in that is you need both %roomlink and %roomportal for the checks and %roomlink likes the h,j,k,l directions and will fail with ne, nw, se, and sw so you have to detect those and convert. You have to detect the longer commands, which means your input trigger has to be aware of them, which means you have to know about them when you enter the room, which means pulling them from the list %roomexit.

My preferred strategy is to remove a direction from the path variable when the step has been confirmed. I do that tactic because mobs could attack between issuing the direction command on my computer and completing the movement on the mud in such a way that movement would be blocked. I found it more comfortable to forget a single user input when a problem occurs instead of automatically resending that direction. Script inputs would create a path record and push it to the underlying system even for a single step, which leads to automatic resending. Since I also have years of keying experience on a number pad and when there is a map in front of me can blast 10 moves in before the mud has responded to the first one, my script also records all that in a queue. I seem to recall that there is no clear way to distinguish between keyboard inputs and other sources, so the correct thing was to replace all the numberpad macros with script aware versions.

It is a lot of stuff to build, but when you can double-click on a room in the map and have it do things like search for a hidden exit 10 times and reverse course to pull a hidden lever then walk back through the secret door; or call the elevator, wait for it, step in it, push the right floor button, wait to arrive, step out, and continue walking...then it is all worth the effort.
_________________
The only good questions are the ones we have never answered before.
Search the Forums
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4578
Location: Pensacola, FL, USA

PostPosted: Thu Feb 11, 2016 4:18 pm   
 
I have never had to override the mapper... it does take more wrangling than most aspects of CMUD though.
I tend to keep track of which direction i came from by running it through %reversedir. Which you can also use to reference which move you missed in the event of not completing the movement in Vij's example.

#ONINPUT {^(%w)$} {#IF (%reversedir( %1)) {lastDir=%reversedir( %1, 1)}}
_________________
Discord: Shalimar#3679
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Fri Feb 12, 2016 6:08 am   
 
I don't actually use maps at all.

I tried when I first started using CMUD, but no matter what settings I changed, whenever I tried to log my main character, my maps would have to load, and the waiting irritated me. So instead, I use speedwalks and ignore most of the other map functions. Many of them probably do something useful without actually having a map, but the help files are all map-centric and don't really tell me what I want to know. I can see how the feature can be incredibly powerful, but the ten seconds or whatever it was that it took to start a session was not worth it to me.

I've built a couple of maps since then, by creating a special map-enabled session so that I could just load another session most of the time, and load that one if I wanted maps. I always ended up losing them to corruption though, and I just don't want to put that much effort into something so ephemeral anymore.

Anyway, for what I'm doing, a stringlist of directions makes more sense anyway. I don't have mud-based constraints on the speed at which I move--no stumbling and falling down if I try to spam directions too quickly--I just use slow walk to send a direction, then do some things in that room, and then, when done with those things, send the next direction. Using #OK immediately sends the next direction, so I can't confirm my move was successful with #OK until I'm done with whatever I had going on in that room, so timeouts become an issue. #PAUSE is the only realistic alternative, and the echo is too much for me.

So I wrote a quick and dirty script just now to convert paths to stringlists. at least that way I know everything will behave in the way I expect.
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4578
Location: Pensacola, FL, USA

PostPosted: Fri Feb 12, 2016 2:19 pm   
 
I don't know about you, but i tend to have CMUD open for days at a time.
10 seconds off the front of that is hardly noticeable.
Usually it is the package file that gets corrupted, not the map.

That aside, you totally can #GAG the information messages CMUD prints to screen.
_________________
Discord: Shalimar#3679
Reply with quote
Llohr
Apprentice


Joined: 17 May 2005
Posts: 108

PostPosted: Sun Feb 14, 2016 8:29 am   
 
Well my face is red. I tried to create a trigger that fired on the #Pause echo, and no amount of lazy matching would make anything fire. Trying it now works just fine... must have had one of those "dataset is not in edit mode" moments.

So does this mean I can gag and execute triggers on the output of "#PATH"?! Oh, nope.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion All times are GMT
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

© 2009 Zugg Software. Hosted by Wolfpaw.net