Magine: so, everyone read the log from last time?
ZebLith: yep!
Magine: just waiting a few minutes for anne to get here
ZebLith: Okay, I'm finishing off a letter anyways. :)
DLP Anne: hi
Magine: hey :)
DLP Anne: :)
ZebLith: Hi Anne. :)
Magine: brb then we'll start
DLP Anne: k
Magine: ok back
Magine: so, any questions from last time?
DLP Anne: wb nope
ZebLith: Welcome back, and no questions. :)
Magine: ok...well, to begin with today i wanted to talk about how
the bot receives events from the world server
DLP Anne: k
Magine: just so you can have an idea of what the bot is doing internally
Magine: any aw sdk bot will receive messages from the world server
only when it calls an sdk function called aw_wait
Magine: so any bot program needs to call aw_wait repeatedly as
it runs
Magine: and when the program calls aw_wait, it will be "blocked"
until aw_wait is done
["blocked" = program
will lock up]
Magine: so the program doesn't want to call aw_wait for too long
a time.
Magine: when the program calls aw_wait, it specifies how long [it
should fetch messages].
Magine: during the call to aw_wait,
Magine: the aw_wait function will itself call functions within
the bot program, that are called "handlers"
Magine: when the bot program starts, it calls some other sdk functions
that tell the sdk what functions in the bot program should be used to handle
each event type
Magine: and that's how aw_wait knows what handler functions to
call for each event
DLP Anne: ummm ok lol
ZebLith: Oooh, okay. (Making sense. ^^)
Magine: take a look now in magsbot, to menu Options/Handlers...
Magine: everyone have that dialog up?
ZebLith: yep
DLP Anne: yeppers
Magine: all of those checkboxes represent a handler within magsbot
that responds to messages (events) from the world server
Magine: and each handler within magsbot will send the event message
to the behavior table for processing
Magine: you'll notice on the handlers dialog there, that some handlers
are for "callbacks"
DLP Anne: the highlighted ones
Magine: yes
DLP Anne: i can read yerppers lol
Magine: a callback is a message that is sent in response
to some function call within the bot program
DLP Anne: sorry im in a funny mood this morning lol
Magine: np, me too :D
Magine: always :D
Magine: callback....for instance, when you create an object in
aw,
Magine: you get a "Callback" event, ObjectResult, that tells you
the result of the attempt to create the object
ZebLith: oh!
Magine: now the reason for the handlers dialog in magsbot,
Magine: is just so you can turn off handlers that you are sure
you're not going to need
Magine: for a particular situation
Magine: so cut down on the number of messages the bot has to process
DLP Anne: oh ok
Magine: although in most cases you probably won't bother doing
that....
Magine: i just wanted you to see the list of handlers to give you
an idea of what the bot is doing :)
DLP Anne: nope i dont touch little check boxes lol they are there
for a reason lol
Magine: :D
ZebLith: it's appreciated, for I will be unchecking several of
them... >:D
Magine: i put all of the handlers that magsbot uses on that dialog,
DLP Anne: k
Magine: even though some of them, like login,
Magine: you would probably never uncheck.
ZebLith: yeah, lol
DLP Anne: still its good to know
Magine: yeah
Magine: so, getting back to magsbot specifically (as opposed to
aw bots in general)
Magine: (hm, wondering how technical i should get, don't want to
confuse things with superfluous information...)
Magine: well anyhow, basically, as magsbot runs, it alternates
between calling aw_wait for short periods,
Magine: and processing the event messages that it receives.
Magine: you all have the monitor bar open? ctrl-M
Magine: hello? :D
DLP Anne: i keep it open
ZebLith: lol yes, so do i :)
Magine: ok....well the blue light shows when magsbot is receiving
messages,
DLP Anne: sorry Magine lol its hard to be in 2 places at once
Magine: and the yellow light shows when it's processing messages
DLP Anne: k
Magine: the Events bar there shows how many messages have been
received but not processed yet.
Magine: as you recall from when we were doing surveys.
DLP Anne: right
ZebLith: heh right :D
Magine: the point of all this, is that you can adjust the amount
of time spent receiving messages & processing, respectively
Magine: by using the "synchtimer" command
DLP Anne: k
Magine: just to give you an idea, press f5 and type "synchtimer
1000 50" and click ok
Magine: that's not really a great setting, but just to show you
how it works
DLP Anne: hmmm ack new keyboard have to figure out how to get
f5 to work
Magine: you can see that now the blue light stays on for quite
a long time each cycle
Magine: your new computer has function keys in a strange place?
DLP Anne: this stupid one has them showing on the side
DLP Anne: not on toip
Magine: sounds ancient :D
ZebLith: ooh, wow
DLP Anne: lol no new
Magine: that's how keyboards used to be on AT's
DLP Anne: they are running across the top but on the side of the
keys
Magine: oh i see, the labels are on the sides of the keys
Magine: well, not to get sidetracked.... :D
DLP Anne: go on lol i will figure that out later
Magine: anyway, as you might notice in magsbot with the timing
set to 1000 50,
Magine: while the blue light is on, the program can't respond
Magine: so you want to find a balance,
Magine: between receiving messages quickly enough to prevent lag,
Magine: while not staying in wait state (receiving messages, blue
light on) long enough to make the program unresponsive
Magine: now press F5 and type synchtimer 50 500
Magine: that's a more reasonable timing...
Magine: in any case, you won't have to adjust the timing very often,
if ever,
Magine: but i wanted to show you that to give you an idea of how
the message processing works
DLP Anne: got it working
Magine: everyone with me? :) anyone falling asleep? :D
DLP Anne: nope right here :)
ZebLith: *zzz* Huh? ;) Nope, right here. :)
Magine: ok..... :D
Magine: i should have explained, the two numbers in the synchtimer
command:
Magine: the first number is the wait time (how long to receive
messages) and the second number is the processing time, both in milliseconds
Magine: so....during the wait phase, magsbot gets messages from
the world server, and the handlers send those messages to the behavior
table
DLP Anne: ok
Magine: now each message has some data associated with it
Magine: take a look at http://www.activeworlds.com/sdk/
Magine: in particular, scroll down the lefthand frame to the "Events"
section
Magine: that shows you all the events that the sdk can send to
bots
DLP Anne: cool
Magine: (magsbot [generally] uses the same event names without
the AW_ part of the name, btw)
Magine: click on AW_EVENT_CHAT
Magine: you can see there that there are several "attributes" associated
with the event
DLP Anne: yeah]
Magine: in this case they are AVATAR_NAME, CHAT_MESSAGE, CHAT_SESSION,
CHAT_TYPE
Magine: in magsbot, when an event message is received,
Magine: all the attributes that are associated with that event,
Magine: are send to the behavior table along with the event type
ID.
Magine: well, actually,
Magine: events are not sent *directly* to the behavior table,
Magine: because at the rate they are received, they would interrupt
and interfere with each other
Magine: since processing a message can easily take longer than
the time it takes to receive another message
Magine: so, in magsbot, the events are put into a queue
DLP Anne: i see
Magine: to be processed in the order they were received
Magine: and during the processing phase, a few events are taken
from the queue and processed through the behavior table
DLP Anne: so one best not type faster than the bot can process
lol
Magine: heheh well there is no problem there, because of the queue
DLP Anne: lol
Magine: unless the bot starts receiving so many events that it
can't ever catch up
Magine: in which case you would consider changing the synch timing
as we were talking about earlier.
Magine: for instance,
Magine: the default timing in magsbot used to be 1 ms wait, 500
ms processing
Magine: but when running the bot in awrpg,
Magine: i discovered that there was a lot of lag in the response
with that timing
Magine: because the events were coming in too slowly
Magine: but when i changed the timing to 50ms wait, 500 ms processing,
Magine: it picked up nicely :)
DLP Anne: cool
ZebLith: ah great!
Magine: anyway, one more point i wanted to make here was,
Magine: that because of the queueing,
Magine: all of the attributes associated with a particular event,
Magine: must be placed in the queue [by magsbot] with the event
ID,
Magine: so when the behavior table processes the event,
Magine: it will be able to see the attributes *as they were at
the time the event occurred*
DLP Anne: makes sence
Magine: everyone see what i mean?
DLP Anne: yes
Magine: ok....
ZebLith: yeah :)
Magine: so, to see what an attribute is within the [context of
the]behavior table,
Magine: you use the @atr or $atr functions in magsbot
Magine: @atr for a numerical attribute, $atr for a string attribute
Magine: for instance, in the case of the AW_EVENT_CHAT event,
Magine: you could find the name of the speaker by using $atr[AVATAR_NAME]
Magine: or their session number, using @atr[CHAT_SESSION]
Magine: btw, the session number is a unique ID number that gets
assigned to every avatar that the bot can see
DLP Anne: ahh ok so that is what those numbers are
Magine: right
Magine: you can use the session number instead of the name for
several different functions
Magine: in fact, in the sdk you need to use the session number
rather than the name for most things,
Magine: but magsbot can look up the session number automatically
for most functions.
Magine: for instance in magsbot you can use the command
Magine: WHISPER Magine "Hello there!"
Magine: or
Magine: WHISPER_ 1394 "Hello there!"
Magine: (1394 being my session number at the moment)
DLP Anne: k
Magine: that session number will change each time the bot sees
someone, btw...it's not like citizen ID that is constant)
DLP Anne: right
Magine: ok...so to summarize, in magsbot, when an event occurs,
the attrbutes are send to the queue with the event ID, then during processing
those attributes are available in the behavior table
Magine: if you use the @atr or $atr functions in magsbot to check
the value of some attribute that is NOT valid for that particular event,
Magine: then you just get the value directly from the SDK (not
the stored value from the queue), which in most cases won't be useful
DLP Anne: oh ok this will take some getting ued to
DLP Anne: used
ZebLith: yeah heh
Magine: i know :) maybe i'm being too technical here....
Magine: or giving you more info that you need at the moment
Magine: but at least you have an idea of how events are processed,
hm? :)
DLP Anne: yup :)
ZebLith: yeah! :D
Magine: ok, let's open the behavior table (alt-B) and double-click
on the event column
Magine: then click on the Insert Event button
Magine: that shows you a list of all the magsbot events
Magine: a few of them have slightly different names from the SDK
web page
Magine: like AW_EVENT_CHAT is called "HEAR" in magsbot
Magine: also, magsbot has a few extra events of its own, that [aren't
generated by] the world server
Magine: for instance the STARTUP event, that occurs when the magsbot
program is started
DLP Anne: ahh hok i see
Magine: or the CLOCKTICK event [that is generated by a custom timer
in magsbot]
Magine: any questions so far?
ZebLith: None here. :)
DLP Anne: nope
Magine: ok...
Magine: well, next i'd like to take a look at the behavior table
and go thru how magsbot does some of the standard behaviors,
Magine: so you can see some examples of how to do some more complicated
things.
DLP Anne: ok
ZebLith: okay :D
Magine: but first i'm going to go off on a short tangent to explain
macros and functions a bit better :)
DLP Anne: lol ok
Magine: so what you see in the table will make more sense
ZebLith: heh okies :D
Magine: so, you probably all have a basic idea of what functions
are, right?
DLP Anne: yes
Magine: a function is like a magic box, you put something into
it and get something back out, nevermind where it came from :D
Magine: like the @len function for example
Magine: you put a string into it, and it give you a number, the
length of the string, back :D
Magine: and btw here's a chance for me to show you the magsbot
pocket calculator :D
Magine: press F3
Magine: you can type any magsbot expression in there and get the
result back
Magine: for instance, you can type @len["some string of mine"]
in there
Magine: and get back the result = 19 (in the log window)
Magine: anyway, to continue....
DLP Anne: haha I got result=17
Magine: you must have entered a different string than i did :)
DLP Anne: yeah lol ["how do I do this?"] lol
Magine: there ya go :D
Magine: you can use that window to experiment with functions too,
to get a better understanding of how they work
ZebLith: ah great :)
DLP Anne: k
Magine: now, besides built-in functions like @len and a few hundred
others
Magine: magsbot also has "macros"
Magine: i originally called these "user-defined functions" but
macros is really more accurate
Magine: in general [programming] terms, a macro is like an abbreviation
of a longer something, that gets expanded in action
DLP Anne: k
Magine: in magsbot, macros are defined in the userdefs.udf file.
Magine: go to the "." tab of the magsbot action panel, and click
"EditUserDefs"
Magine: that's your userdefs.udf file, containing all the macros
defined for magsbot.
DLP Anne: oh cool it opens it
DLP Anne: lol
Magine: :)
Magine: there are tons of standard macros that i've put in there,
starting where it says "Standard Macros" :D
Magine: and you can of course add your own
Magine: some macros are very very simple, like
Magine: $midiobject="midispk.rwx"
Magine: and some are pretty complicated, like the $title macro
you can see there
Magine: (that's not in the standard section but it is in the userdefs.udf
that is in the mbot.zip)
Magine: anyway, you don't need to understand all that code yet,
DLP Anne: ok
Magine: as long as you get the idea that a macro is something that
gets substituted for something else
Magine: so if you put $midiobject in your code in the behavior
table or a button,
Magine: it will get translated to "midispk.rwx"
DLP Anne: ahhh ok
Magine: another example is
Magine: way down in the file is a line that has:
Magine: $avname=$atr[AVATAR_NAME]
Magine: so you can use simply $avname instead of having to type
the longer $atr[AVATAR_NAME]
Magine: you could define your own macro like that for any attribute
you expect to use often
DLP Anne: i see it so that code is basically letting you shorten
it
Magine: right
DLP Anne: kk
Magine: yet another example,
DLP Anne: lol i use eject alot LOL how can it be shortened
Magine: well, eject is a command, not a function
DLP Anne: oh yeah :) lol
Magine: so you can't make a macro out of it
DLP Anne: ahhh ok
Magine: however there is a way you can do that [i.e. abbreviate
a sequence of commands into one]....by using the custom buttons. but i
don't want to get ahead of myself here :)
DLP Anne: ok
Magine: yet another example of a very frequently used macro is
the @eq macro
Magine: you use @eq to compare strings, it returns "true" (1) if
the strings match
Magine: like
Magine: @eq[$avname,Magine]
Magine: well, @eq is actually a macro for
Magine: (@icmp[~1,~2]=0)
Magine: @icmp is a built-in function that also compares strings
DLP Anne: blank stare lol
Magine: @icmp is a built-in function that compares strings alphabetically
DLP Anne: ok
Magine: it returns 0 if the strings match,
Magine: a negative number if the first string comes before the
second string, alphabetically
Magine: or a positive number if the second string comes before
the first, alphabetically
Magine: try it, using F3
Magine: type something like
Magine: @icmp["first string","second string"]
Magine: that will give you -1 because "first string" comes before
"second string" alphabetically
DLP Anne: i got result=1
ZebLith: ditto :)
Magine: what strings did you enter?
ZebLith: @icmp["Mankey","Magine"]
DLP Anne: @icmp["this is neat","how is this done?"]
Magine: if you got a 1, it's because the second string comes first,
alphabetically
DLP Anne: ahah
ZebLith: right. perfect :D
DLP Anne: mag comes before man
Magine: always :P
DLP Anne: gotcha
Magine: lol
ZebLith: lol
DLP Anne: that sounded funny lol
Magine: there is also a @cmp function that does that same thing,
but it's case-sensitve
Magine: you all know what that means, right?
ZebLith: anywho ^^ yeah. so, it returns the same kind of
results, -1 0 1?
Magine: yes
DLP Anne: k
Magine: so, the macro @eq is derived from the built-in @icmp function
Magine: somewhere in the userdefs.udf file is this line:
Magine: @eq[$,$]=(@icmp[~1,~2]=0)
Magine: what that means is,
Magine: "when you see @eq with two strings as parameters, then
substitute this expression using @icmp with the parameters inserted where
the ~1 and ~2 are".
Magine: the $,$ tells magsbot that the @eq requires two string
parameters (or "arguments" in programmerese)
Magine: and the ~1 and ~2 in the translation shows where the arguments
get plugged in.
DLP Anne: k
Magine: let's take a short break
DLP Anne: ok thank you :)
DLP Anne: brb
Magine: but does that makes sense so far?
ZebLith: yeah. :) I'm curious though...
ZebLith: okay, so if I put in @eq["Right","Wrong"] and @icmp["Right","Wrong"]
I should get the same result in theory?
Magine: no...[because] if you look carefully, the macro isn't just
@eq[$,$]=@icmp[~1,~2]
Magine: it's @eq[$,$]=(@icmp[~1,~2]=0)
Magine: you would get the same thing as @eq["Right","Wrong"] if
you put
Magine: (@icmp["Right","Wrong"]=0)
ZebLith: oh, right!
ZebLith: forgot that wonderful =0
Magine: yep
DLP Anne: back thanks magine :)
Magine: np anne :)
ZebLith: okay, that makes sense. welcome back anne!
DLP Anne: ty Zeb :)
Magine: what the =0 does, zeb, is to compare the result of the
@icmp with 0
Magine: if @icmp returns 0 (meaning that the strings match) then
@icmp=0 will be true and the @eq macro will return 1
Magine: you see how that works?
ZebLith: yes :D
Magine: anne?
DLP Anne: yes
DLP Anne: im with you
Magine: ok
DLP Anne: so far anyway
Magine: ok, well time is almost up, so i won't try to get into
the behavior table examples this time (unless everyone wants to stay longer,
but i will need a break myself if so)
Magine: but in the time left, we could try to define our own macro
to show you how it works
DLP Anne: I cant stay longer son wants attention lol
Magine: ok
Magine: so let's just take the remaining 10 minutes or so to try
a macro definition :)
DLP Anne: i get to go outside and play with supersoaker water guns
lol
[Magine: kind of cold for that, isn't it? :D]
DLP Anne: okies
Magine: hmm, let me see...
Magine: ok, this will be pretty useless, but it will give you an
idea anyway :D
DLP Anne: ok
ZebLith: lol okies :)
Magine: assuming you all still have userdefs.udf open in notepad?
DLP Anne: yup
ZebLith: yes
Magine: ok, pick a line in there and put...let me see.......
Magine: @foo[$,$]=$cat[~2,~1]
[<<< this is a goof! read on...]
DLP Anne: you mean under macros?
Magine: anywhere in the userdefs file, on a line by itself
(but better to put it in the custom section above the "Standard Macros"
line)
Magine: that is, it will work anywhere, but better to leave the
standard section alone
Magine: just for the sake of orderliness :D
DLP Anne: ok done
Magine: then save file (File/Save, but you dont need to close the
file)
Magine: and then in magsbot, press Ctrl-F11 or menu File/Open Macros
Magine: everyone done that?
ZebLith: yes :)
Magine: before we test it,
DLP Anne: yup
Magine: i'll explain that the $cat function, which is a built-in
function,
Magine: just sticks two strings together into one
Magine: like $cat["one","two"] would return "onetwo"
Magine: so knowing that, what do you think our new macro will do?
ZebLith: it will combine the two strings we enter into a single
line.
Magine: (hm, well actually guess what...i goofed!)
DLP Anne: lol
ZebLith: oops ^^
Magine: because that should have been $foo not @foo
Magine: @foo would be for a function that returns a number, not
a string
Magine: what version of magsbot are you all running?
DLP Anne: the latest
ZebLith: 4.0 as requested to be used
DLP Anne: same
Magine: ok, well then i won't have you try the bogus function to
see what happens :D
Magine: if you were using 4.1 b8 then it would just give you an
error message in the log window
DLP Anne: lol i changed it already
ZebLith: lol *watches older mags version explode*
Magine: but 4.0 i think would cause [an exception with a] pop-up
error message
DLP Anne: no i got one in the window
Magine: ok
DLP Anne: acess violation
Magine: yeah
Magine: well let's change it in the userdefs to $foo= etc.
Magine: and save it again
DLP Anne: already done
Magine: and Ctrl-F11 load it again
DLP Anne: i hit control f11 and a window comes up to load the userdefs?
Magine: anne, yes
DLP Anne: kk when i try to load I get an error or am i not supposed
to
Magine: uhh, hmm, no not supposed to [get an error when loading]
Magine: what is the error?
DLP Anne: i never closed it once I saved it the first itme
Magine: doesn't matter if you close it as long as you save it
Magine: what error message?
DLP Anne: acess violation at address 004729B4
Magine: anne, if you're sure you typed the macro right anne, then
just restart magsbot
DLP Anne: ok
Magine: sometimes if there is an error in a macro when it loads,
it will mess things up
Magine: because if there's an error it will stop loading, and if
there are macros missing then many things in the standard behavior table
will crash
DLP Anne: LOL it wont let me x out
Magine: ah right
Magine: well here is what you can do with that situation :D
Magine: (maybe i need to change this, but magsbot won't quit if
it has an error while trying to quit)
Magine: you can force it to quit by making it ignore errors while
quitting
Magine: press F5 and type
Magine: trap { quit }
Magine: and click Ok
Magine: the trap command turns off error messages
DLP Anne: kk
Magine: did that do it?
DLP Anne: yup and she is back
Magine: ok, so any other guesses as to what [our new macro] will
do?
Magine: this is a trick question, look carefully :)
ZebLith: Oh! I have another guess of what it will do... concerning
order. ;)
Magine: zeb, i think you have it :)
ZebLith: second string first, first last. correct?
Magine: (to ZebLith) yes
Magine: ok, so with out $foo macro, as zeblith has figured out,
Magine: it will combine the two strings, but in reverse order
DLP Anne: ahhh ok
Magine: because in the macro the order of the arguments is ~2,~1
ZebLith: Can you add more, like change the code to $foo[$,$,$,$]=$cat[~1,~3,~2,~4]?
Magine: zeb, yes indeed :) up to 12 arguments are possible
Magine: and arguments can also be numeric if you want
Magine: so you could have
Magine: @foo[@,@,@]=~1+~2*~3
Magine: for example.
ZebLith: ah! I see. okies :)
Magine: and you can mix them of course, numeric and string
Magine: the only thing is, the result has to match the macro type
DLP Anne: this is all programming right
Magine: yep :)
DLP Anne: ahhh ok
DLP Anne: i will leave the programming to you lol but its good
to know
Magine: lol
Magine: well putting stuff in the behavior table is programming
too :)
DLP Anne: k
Magine: and creating your own buttons is also
DLP Anne: i will learn may take longer than zeb lol
but i will try
Magine: just play with it, a little at a time, you'll get it :)
ZebLith: You'll do great Anne. :)
DLP Anne: ty :)
Magine: so next time we will take a look at some of the behavior
table code and i will explain why it does what it does :)
DLP Anne: ok
Magine: ok folks, see you all next time i hope :)
DLP Anne: will be there :)
DLP Anne: here too
Magine: any last questions?
ZebLith: lol :) I'll remember to set my alarm again. ;)
Magine: zeb, ok good :)
DLP Anne: magine so is mine LOL
ZebLith: nuuuu! :D okies, well no questions here. but
next time probably. ;)
Magine: 'k
DLP Anne: same here no questions :)
Magine: bye bye then, see ya's next time :)
ZebLith: Bye Magine! :)
DLP Anne: byeeeeee to you both :)