ZebLith: Ah, good morning Magine. :)
Magine: so, did you look at ...uh, whatever it was i told you to
look at? :D
ZebLith: I think it was [SayLong] but I'm not sure. I did
right after class. lemme check ^^
Magine: 'k
ZebLith: Ah, it was [PickAv]...
Magine: ok, so what did you think?
Magine: did it make sense?
ZebLith: Hehe, somewhat. I haven't looked up all the variables
yet.
Magine: well, we can go thru it today. but any other questions
from last time?
ZebLith: no questions :)
Magine: ok, then let's go thru the [PickAv] button to start with
Magine: the first command in the button is RESETNEARBY
Magine: (you probably want to look at the code in the button to
follow along, if you aren't already doing that)
Magine: the RESETNEARBY command works with the $listnext function
Magine: the $listnext function retrieves the "next" name in the
list of nearby avs
Magine: each time you use $listnext, it moves the "next" pointer
forward one name
Magine: and RESETNEARBY moves the pointer back to the beginning
of the list
Magine: so by calling RESETNEARBY and then calling $listnext multiple
times, you can get all the names from the nearby list
Magine: you know when you get to the end of the list only by using
the count of the names in the list,
Magine: and that count is gotten from the @avspresent function
Magine: which returns the number of nearby avs
Magine: so, you can see that the pickav button first checks to
see if there are any avs nearby,
Magine: and if so, it uses a loop to copy all the names from the
nearby list into a string list named "nearby"
Magine: that's what the ENLIST command is doing there
Magine: actually, you can tell how long ago i wrote the PickAv
button, but i would do that kind of differently now.
Magine: early versions of magsbot had no FOR loop, only a WHILE
loop
Magine: i'm assuming you understand how the loops work, right?
ZebLith: yes :)
Magine: but for the benefit of any class log readers, i'll explain
briefly (tho it's probably self-evident)
Magine: that the commands within a FOR or WHILE loop are repeated
Magine: the WHILE loop repeats as long as the initial expression
is true (not 0)
Magine: and the FOR loop, which looks like this:
Magine: for i 1 10 { rem do something }
Magine: the FOR loop assigns numbers to the specified variable
(in this case i)
Magine: the first time through the loop, i will be assigned the
first specified number ( 1 in this case )
Magine: and the loop will be repeated for each consecutive number,
up to the second specified number (10 in this case)
Magine: you could also specify an increment other than 1,
Magine: like this:
Magine: for i 1 10 2 { rem do something }
Magine: in which case @i would be incremented by 2 each time instead
of 1 (the default)
Magine: and finally, you can also use a negative increment, like
Magine: for i 10 1 -1 { rem do something }
Magine: to count down instead of up.
Magine: so, getting back to the PickAv button,
Magine: instead of @i=0; while @i<@avspresent { ENLIST nearby
$listnext; @i=@i+1 }
Magine: how would i do the same thing with a for loop? (this is
a pop quiz, heheh)
ZebLith: eerg :D alright. let's see...
Magine: this should be very simple :)
ZebLith: "should" ;) Well I'm not sure what to do for the
maximum value for i...
Magine: ok, you would do
Magine: for i 0 @avspresent-1 { enlist nearby $listnext }
Magine: or, since the value of @i is not important in the loop,
Magine: for i 1 @avspresent { enlist nearby $listnext }
Magine: would do that same thing
Magine: actually there is one other improvement you could make
there
Magine: since @avspresent is a function, and it might be faster
if you didn't call the function each time thru the loop,
Magine: you could get the number and put it in a variable first,
like this:
Magine: @ct=@avspresent; for i 1 @ct { rem etc. }
Magine: make sense?
Magine: ok, to continue...
ZebLith: yes, I wasn't sure if you could do functions while setting
the range. okay :)
Magine: you can, it's just usually faster if you use a variable
instead
Magine: anyway, once you have the list of nearby av names in the
list
Magine: you can use the $pick function with that list
Magine: to let the user select one of the names.
Magine: the $pick function displays a popup window with a list
of all global variables that have the specified prefix
Magine: in other words, all global variables whose name begins
as specified.
Magine: in this case i use $listprefix[nearby]
Magine: but i could just as easily used
Magine: "$nearby:"
Magine: because all the $listprefix function does is to add the
$ at the beginning and : at the end of a string
Magine: so $listprefix takes "nearby" and changes it to "$nearby:"
Magine: therefore, the $pick function here shows a popup list of
all global variables whose names begin with "$nearby:"
Magine: and as i explained in a previous class, lists in magsbot
as just a group of global variables with a similar name
Magine: so when ENLIST was used to put an avname into the list
named "nearby"
Magine: all it did was to create global variables named
Magine: $nearby:1, $nearby:2, $nearby:3 and so forth
Magine: and of course those variables will each contain a different
av name
Magine: the whole point of the loop to put the names of nearby
avs into a list,
Magine: was just so the $pick function could be used to present
a list of those names to the user,
Magine: and get the user's selection from that list.
Magine: when the user clicks a name in the list, the $pick function
will return that name
Magine: therefore, the variable named $target that you see there,
will be assigned the name from the list that the user chooses.
Magine: make sense?
ZebLith: perfect sense :)
Magine: ok :)
Magine: after getting the user's pick, you don't want that list
hanging around and wasting memory,
Magine: so you use the FREELIST command to get rid of it.
Magine: next you check to make sure that the user really did choose
a name from the list,
Magine: because if the user just clicked "cancel" then $pick would
return a empty string and $target would just be "" (empty)
Magine: so you use the @neq function (which compares two strings
and returns true if they are not equal)
Magine: and if $target is not empty, then the REPORT command prints
the name in the chat window
Magine: now, the next section that says POPUP "There are no avatars"
etc.
Magine: is the "else" clause of the original IF @avspresent at
the beginning of the code
Magine: if that "there are avs" popup message will only appear
if there are no avs present
Magine: and $target is assigned an empty string just so the next
command, RETURN, will have something to return even if there are no avs
present
Magine: so finally, RETURN $target passes the user's choice back
to the calling routine
Magine: so when you use $ftn["[PickAv]"]
Magine: it will return that choice
Magine: everything clear?
ZebLith: yes :)
Magine: ok cool :)
Magine: well, there are scores if not hundreds of buttons, and
it would take forever to go thru them all,
Magine: so i will let you study them on your own.
Magine: but i'll try to explain a few things that are commonly
done in magsbot code.
Magine: specifically, i should tell you more about lists,
Magine: since they're used all over the place in all my magsbot
programs.
ZebLith: that'd be great, I was just about to ask if you would
:)
Magine: if you want to open a couple of web browser windows, take
a look at http://www.turtleflight.com/mbh/mh_actions.htm#assign
Magine: and also at http://www.turtleflight.com/mbh/mh_lists.htm
Magine: on those pages you can see many commands and functions
for dealing with lists
Magine: and you can read those later on, but right now i'll explain
some basic list operations.
Magine: first, creating a list :)
Magine: you can read a list in from a text file using GETLIST and
other commands,
Magine: as explained on those pages,
Magine: but more commonly you'll add to lists one item at a time
Magine: using ENLIST, ENLIST_, SETITEM or SETITEM_
Magine: the difference between the two variations of those commands
(e.g. ENLIST and ENLIST_) is that the commands that end in an underscore
_
Magine: are for numeric lists,
Magine: and the non-underscore versions are for string lists.
Magine: the difference between ENLIST and SETITEM is that ENLIST
will add an item to a list and automatically give it an item number
Magine: whereas with SETITEM you specify the number yourself
Magine: you should note that the item numbers in magsbot lists
are NOT indexes in the list
Magine: the item numbers are arbitrary
Magine: for instance, if you have a list with 3 items in it
Magine: the list may consist of global variables like $mylist:1
$mylist:2 $mylist:3
Magine: but it doesn't have to use consecutive numbers like that
Magine: it can just as easily be $mylist:12 $mylist:2478
$mylist:92
Magine: and even if the numbers are consecutive as in the first
example,
Magine: if you delete the middle one ($mylist:2) the numbers of
the other items will not change
Magine: so you would have a list with two items, but still named
$mylist:1 and $mylist:3
Magine: in some ways this is a bit awkward perhaps,
Magine: but it does have some advantages
Magine: in that you can use object numbers, avatar session numbers,
citizen numbers or any other numbers as item numbers
Magine: allowing you to look up items in a list easily
Magine: so for instance,
Magine: if you wanted a list that would allow you to find someone's
cit number quickly,
Magine: you could do
Magine: SETITEM mylist @atr[citizen_number] $atr[avatar_name]
Magine: in the AVATARADD event
Magine: which would create an item in $mylist like
Magine: $mylist:28777
Magine: with the value (for instance) of "Magine"
Magine: so later on in your program when you need to know the citizen
number (e.g. in some event where it is not normally available)
Magine: you could get it from the list using
Magine: @itemnum[mylist,Magine]
Magine: or the other way around, to find the name from the cit
number:
Magine: $litem[mylist,28777]
Magine: do you see how that works? :)
ZebLith: yes :)
Magine: to remove an item from a list, you can use FREEITEM or
FREEITEM_ (for string or numeric lists, respectively)
Magine: or you can use FREELIST or FREELIST_ to get rid of the
entire list.
Magine: now one important thing to note about freeing list items
or lists
Magine: is that it can be a tiny bit slow (comparatively)
Magine: due to some changes i made in magsbot 4.0 to speed up variable
access.
Magine: you can read about that in the tech note under the DEFER
command on http://www.turtleflight.com/mbh/mh_actions.htm#assign
Magine: but basically, it amounts to this: when you free a global
variable or a list, magsbot has to make a quick check
Magine: of the entire behavior table and all the action buttons
Magine: in order to update any references to the freed variable.
Magine: so, when you write your program, you want to try to avoid
calling FREEITEM or FREELIST too often.
Magine: and also, if you are freeing several variables or several
lists at once,
Magine: you should use the DEFER command with those FREEITEM, etc
commands within the DEFER clause,
Magine: in order to delay the update of the behavior table and
buttons until all the variables are freed,
Magine: so you don't do the update over and over for each variable.
Magine: does that make some sense? :)
ZebLith: yes, very clear. :)
Magine: ok good :)
Magine: to look at individual items in a list,
Magine: you use $listitem[$list,@i] (string lists) or @listitem[$list,@i]
(numeric lists) where $list is the listname and @i is the item number
Magine: or you can use $litem and @litem instead of $listitem and
@listitem,
Magine: the only difference being that $litem and @litem won't
cause an error if the specified item is missing
Magine: $litem will just return an empty string and @litem will
return 0, if the specified item is missing.
Magine: now, if you want to examine all the items in a list one
at a time
Magine: you can use $nextitem[$list] or @nextitem[$list]
Magine: after calling RESETLIST $list to set the pointer back to
the top of the list.
Magine: or, instead of $nextitem/@nextitem, you can use @nextnum
(string lists) or @nextnum_ (numeric lists) to get the item numbers instead
of the values,
Magine: then you could use $litem or @litem to get the values (having
gotten the item number)
Magine: i'm trying to think of an example, somewhere i use this
technique that isn't too complicated otherwise
Magine: well i'll just use an imaginary example :D
ZebLith: hehe ^^
Magine: suppose you have a string list named $mylist
Magine: and you just want to REPORT each item the the chat window
Magine: you would do this:
RESETLIST $mylist;Magine: simple enough, huh? :)
@ct=@itemcount[$mylist];
FOR i 1 @ct {
REPORT $nextitem[$mylist] }
RESETLIST $mylist;Magine: instead of getting the next value, you get the next item number
@ct=@itemcount[$mylist];
FOR i 1 @ct {
@n=@nextnum[$mylist];
FREEITEM $mylist @n };
RESETLIST $mylist;Magine: you see how that works? :)
@ct=@itemcount[$mylist];
FOR i 1 @ct {
@n=@nextnum[$mylist];
REPORT "deleting "+$litem[$mylist,@n];
FREEITEM $mylist @n };
RESETLIST $mylist;Magine: but as i said, that won't work
@ct=@itemcount[$mylist];
FOR i 1 @ct {
@n=@nextnum[$mylist];
$x=$litem[$mylist,@n];
if @eq[$left[$x,1],"a"] {
FREEITEM $mylist @n }};