Magsbot Class, Session 8
Saturday May 3, 2003 2pm VRT

Addendum 5/5/03:  Previously I stated below that the bugs mentioned in this class session are fixed in version 4.1 b20.  Well, you fix one bug and wouldn't you know it, you create another. :/  So, version 4.1 b25 is now the latest, most-fixed version. :D

The scheduled topic for this session was databases, but first we spent a lot of time finishing up material from the previous class, involving the action queue...

Magine: hi :)
ZebLith: hello magine :)
Magine: i need to take a few moments, i just had a beverage spill here :D
ZebLith: oops! >_< okies, no problem.  ^^
Magine: back
ZebLith: welcome back :)
Magine: never set drinks by the computer, heheh
Magine: well, we left off last time where i was explaining about deleting items from a list, within a loop
Magine: so let me finish that before we start on the official topic of today's session
Magine: the example [to delete items that begin with "a" from a list] i gave was this:

RESETLIST $mylist;
@ct=@itemcount[$mylist];
FOR i 1 @ct {
 @n=@nextnum[$mylist];
 $x=$litem[$mylist,@n];
 if @eq[$left[$x,1],"a"] {
  FREEITEM $mylist @n }};
Magine: but, as i said, that would not work right because the list would be changing as you went thru the loop
Magine: the number of items would change, and the pointer to the "nextnum" would change
Magine: so what you want to do is,
Magine: as you do the loop, don't actually delete items, but determine what items to delete and not actually delete them until the loop is done.
Magine: a convenient way to do this is to use the ENQUEUE command
Magine: we've already talked before about the Event queue,
Magine: that causes messages received by the bot to be processed in the order they occur
Magine: but there is also an Action queue that you can put items into yourself, in a program
Magine: so that the actions can be executed in order, and if desired, in parallel with other actions.
Magine: the basic form of the command is:
Magine: enqueue { rem put any code here };
Magine: what that does is
Magine: to add whatever code is specified, into the action queue.
Magine: now by itself that doesn't mean much,
Magine: because the items in the action queue would be executed immediately [the same as non-enqueue'd commands]
Magine: but, you can turn action queue processing on or off with the QSTATE command.
Magine: QSTATE 0 to turn it off, QSTATE 1 to turn it on
Magine: so, in our example loop, we could do this:
QSTATE 0;
RESETLIST $mylist;
@ct=@itemcount[$mylist];
FOR i 1 @ct {
 @n=@nextnum[$mylist];
 $x=$litem[$mylist,@n];
 IF @eq[$left[$x,1],"a"] {
  ENQUEUE { FREEITEM $mylist @n }}};
QSTATE 1;
Magine: so what happens here is this,
Magine: the QSTATE 0 turns off Action queue processing, so that items added to the Action queue will just sit there
Magine: and each time thru the loop we add a new item to the action queue,
Magine: that item being FREEITEM $mylist @n.
Magine: then after the loop has finished, the QSTATE 1 turns action queue processing back on again,
Magine: and all the FREEITEM commands we put into the queue,
Magine: will execute one at a time.
Magine: note that the value of @n, which is a local variable, is also stored in the action queue.
Magine: in fact, all local variables are stored in each queue item
Magine: which of course is necessary because otherwise those variables wouldn't be available when the queue items are executed.
Magine: all that make sense so far? :)
ZebLith: *nods* :)
Magine: ok, good :)
Magine: well now i have to confess that i just lied :D
Magine: there isn't really an action queue :D
Magine: there are actually any number of action queues
ZebLith: :O hehe ^^
Magine: that progress bar for Action queue at the bottom of the magsbot window actually shows [the total pending actions in] all of the action queues.
Magine: each time you use ENQUEUE as shown above, a new queue may be created
Magine: unless you specify otherwise.
Magine: you can specify the queue number by adding it to the enqueue command, like
Magine: ENQUEUE 1 { report "in the queue!" }
Magine: each queue has a non-zero ID number
ZebLith: including negatives?  or just natural numbers?
Magine: no negatives; however you can use -1 for a special purpose
Magine: which i will explain in a moment
ZebLith: ah, okay. :)
Magine: if you use ENQUEUE without specifying a number, it will create a new queue and number it automatically,
Magine: the first time you call ENQUEUE within a particular context (button or behavior table row).
Magine: however within a context, i.e. within the code for a particular action button, or within a particular behavior table row,
Magine: all ENQUEUE commands will put items into the same queue if you don't specify a queue ID
Magine: because normally, unless you specify a queue ID, magsbot assumes you would want all the enqueue'd commands to run sequentially, in order
Magine: so they all need to go into the same queue.
Magine: however, the whole point of having different queues is,
Magine: that different queues run in parallel, at the same time
Magine: and that's the other main use of ENQUEUE:
Magine: if you want the bot to be doing several things at once, you can put the commands into separate queues.
Magine: now, let's create a pair of action buttons to show what i mean
Magine: in the first button, put this:
QSTATE 0;
FOR i 1 10 {
 ENQUEUE {
  SAY $fmt["Counting %s",@i] }};
QSTATE 1;
[Mags]: Counting 1
[Mags]: Counting 2
[Mags]: Counting 3
[Mags]: Counting 4
[Mags]: Counting 5
[Mags]: Counting 6
[Mags]: Counting 7
[Mags]: Counting 8
[Mags]: Counting 9
[Mags]: Counting 10

Magine: ok, now add a second enqueue command in there
Magine: so it should read:

QSTATE 0;
FOR i 1 10 {
 ENQUEUE {
  SAY $fmt["Counting up %s",@i] } };
FOR i 10 1 -1 {
 ENQUEUE {
  SAY $fmt["Counting down %s",@i] } };
QSTATE 1
Oops!  A bug in Magsbot (now fixed in version 4.1 b25) caused some incorrect results with the examples during class. Rather than cause confusion by presenting those bugs as they happened and then trying to explain why, I've cheated a bit and changed the log to show what the bot should have done, and what the newer, repaired version will do. The green text below is the "revised" version of the chat log, that show the correct result.

[Mags]: Counting up 1
[Mags]: Counting up 2
[Mags]: Counting up 3
[Mags]: Counting up 4
[Mags]: Counting up 5
[Mags]: Counting up 6
[Mags]: Counting up 7
[Mags]: Counting up 8
[Mags]: Counting up 9
[Mags]: Counting up 10
[Mags]: Counting down 10
[Mags]: Counting down 9
[Mags]: Counting down 8
[Mags]: Counting down 7
[Mags]: Counting down 6
[Mags]: Counting down 5
[Mags]: Counting down 4
[Mags]: Counting down 3
[Mags]: Counting down 2
[Mags]: Counting down 1

In this case, the SAY commands still executed sequentially, in the same order they were enqueue'd, because they all were placed in the same queue.

If, however, the code was changed to this:

QSTATE 0;
FOR i 1 10 {
 ENQUEUE {
  SAY $fmt["Counting up %s",@i] } };
@q=@queue+1;
FOR i 10 1 -1 {
 ENQUEUE @q {
  SAY $fmt["Counting down %s",@i] } };
QSTATE 1
...then the result would be as follows, because each loop would place the SAY commands in a different queue, causing the commands to be executed simultaneously:

[Mags]: Counting up 1
[Mags]: Counting down 10
[Mags]: Counting up 2
[Mags]: Counting down 9
[Mags]: Counting up 3
[Mags]: Counting down 8
[Mags]: Counting up 4
[Mags]: Counting down 7
[Mags]: Counting up 5
[Mags]: Counting down 6
[Mags]: Counting up 6
[Mags]: Counting down 5
[Mags]: Counting up 7
[Mags]: Counting down 4
[Mags]: Counting up 8
[Mags]: Counting down 3
[Mags]: Counting up 9
[Mags]: Counting down 2
[Mags]: Counting up 10
[Mags]: Counting down 1

Magine: but you see what happened?
Magine: even though you added items [in the order] 1,2,3...9,10,10,9,8,...1
Magine: the bot executed the items at the same time
Magine: because two different queues were created
Magine: the first queue got  SAY 1..10 and the second queue got SAY 10..1
Magine: but both queues executed "at once"

Magine: so let me explain a few details about queue numbers
Magine: first of all, the number you specify will only be used if a queue with that id already exists,
Magine: but if a queue with that number doesn't already exist,
Magine: then the number you specify will be ignored and queue ID will be automatically generated instead
Magine: also, if you give -1 for a queue ID
Magine: like ENQUEUE -1 { rem do something }
Magine: then a new queue will always be created.
Magine: and finally, you can find what the queue ID really is, using the @queue function,
Magine: OUTSIDE OF the enqueue command.
Magine: the @queue function tells you the queue ID of the most recently created queue.
Magine: like:

enqueue { rem do something };
report $fmt["queue number=%s",@queue];
Magine: let's add that to our example
Magine: put:
        report $fmt["queue number=%s",@queue];
Magine: after each for loop
Magine: like this:
QSTATE 0;
FOR i 1 10  {
ENQUEUE {
 SAY $fmt["Counting up %s",@i] } };
REPORT $fmt["queue=%s",@queue];
@q=@queue+1;
FOR i 10 1 -1 {
 ENQUEUE @q {
 SAY $fmt["Counting down %s",@i] } };
REPORT $fmt["queue=%s",@queue];
QSTATE 1
As you can see below, the first loop puts all its commands into queue 0, and the second loop puts all its commands into queue 1.

[Mags]: queue=0
[Mags]: queue=1
[Mags]: Counting up 1
[Mags]: Counting down 10
[Mags]: Counting up 2
[Mags]: Counting down 9
[Mags]: Counting up 3
[Mags]: Counting down 8
[Mags]: Counting up 4
[Mags]: Counting down 7
[Mags]: Counting up 5
[Mags]: Counting down 6
[Mags]: Counting up 6
[Mags]: Counting down 5
[Mags]: Counting up 7
[Mags]: Counting down 4
[Mags]: Counting up 8
[Mags]: Counting down 3
[Mags]: Counting up 9
[Mags]: Counting down 2
[Mags]: Counting up 10
[Mags]: Counting down 1

But what if you made these changes?

QSTATE 0;
FOR i 1 10  {
ENQUEUE -1 {
 SAY $fmt["Counting up %s",@i] } };
REPORT $fmt["queue=%s",@queue];
FOR i 10 1 -1 {
 ENQUEUE -1 {
 SAY $fmt["Counting down %s",@i] } };
REPORT $fmt["queue=%s",@queue];
QSTATE 1
If you did, the result would be this:

queue=9
queue=19
[Mags]: Counting up 1
[Mags]: Counting up 2
[Mags]: Counting up 3
[Mags]: Counting up 4
[Mags]: Counting up 5
[Mags]: Counting up 6
[Mags]: Counting up 7
[Mags]: Counting up 8
[Mags]: Counting up 9
[Mags]: Counting up 10
[Mags]: Counting down 10
[Mags]: Counting down 9
[Mags]: Counting down 8
[Mags]: Counting down 7
[Mags]: Counting down 6
[Mags]: Counting down 5
[Mags]: Counting down 4
[Mags]: Counting down 3
[Mags]: Counting down 2
[Mags]: Counting down 1

Note the queue numbers 9 and 19...what is that all about? :D  Well, the -1 forces a brand new queue to be created for each ENQUEUE command, therefore the first loop creates queues 0 to 9, so the first REPORT gives you the number of the last queue created by the first loop, which is 9; then the second loop creates queues 10 to 19, so the second REPORT gives you the number of the last queue created by the second loop, which is 19.

Magine: what happened with the -1 in there was,
ZebLith: yeah, I saw that. :)
Magine: that *every* enqueue command created a new queue
Magine: so that i ended up with 20 separate queues!
ZebLith: ooooh O_O
Magine: which all executed "at once"!
Magine: the first loop put
Magine: say 1 in queue 0
Magine: say 2 in queue 1
Magine: say 3 in queue 2
Magine: and so on
Magine: and the second loop continued,
Magine: putting
Magine: say 10 in queue 11
Magine: say 9 in queue 12
Magine: say 8 in queue 13 etc
Magine: so that when queue processing was turned on again
Magine: all 20 queues went at once!
Magine: but since the bot can, of course, only say one thing at a time,
Magine: it came out appearing sequential
Magine: queue 0 executed ("say 1"), queue 1 executed ("say 2")...etc
Magine: all the way to
Magine: queue 18 executed ("say 19") ... queue 19 executed ("say 20")

Magine: which points out another issue
Magine: about how queues are executed in parallel.
Magine: of course the program can't really do two different things at once,
Magine: (even your computer can't...even when it seems to, it's really just rapidly switching between tasks, doing one program instruction at a time.)
Magine: but in the same way that your computer appears to be doing several things at once by "timesharing"
Magine: (that is, doing one thing from each program at a time)
Magine: magsbot can appear to be doing several things at once by taking one item from each action queue at a time.
Magine: so if you have, for instance, 2 queues going
Magine: magsbot will execute one item from the first queue, then one item from the second queue, then back to the first, etc. until they are both empty
Magine: does that make sense?
ZebLith: yes, perfect sense.  anything else?

(At this point I explained some things about the bug that resulted in improper results, but I've left that out of the log.)

One thing about queues I forgot to mention in class and will add here, is that although items added to a queue are normally broken up into individual actions so they can be executed one at a time and allow alternating between executing items in other queues, any Magsbot commands that have clauses in { braces } are executed as if they were a single command, even if they contain many commands within them. In other words, a command like IF, FOR, WHILE etc. will execute non-stop, and items from other queues will not be executed until everything in the { } clause is finished. Thus if you want many commands to execute simultaneously, you should put the enqueue command within the loop, not the other way around. If you did this (moving the ENQUEUEs outside of the FOR loops):

QSTATE 0;
ENQUEUE {
 FOR i 1 10  {
  SAY $fmt["Counting up %s",@i] } };
REPORT $fmt["queue=%s",@queue];
@q=@queue+1;
ENQUEUE @q {
 FOR i 10 1 -1 {
  SAY $fmt["Counting down %s",@i] } };
REPORT $fmt["queue=%s",@queue];
QSTATE 1
...it would have no practical value because you would only be putting one item in each queue. The entire contents of each FOR loop would be treated as a single item. Two queues would be created, but each one would only have one item, so the effect would be no different than one queue with two items, executing sequentially. That is, the second FOR loop in the second queue, wouldn't execute until the first FOR loop in the first queue was completely finished, so the ENQUEUE-ing would have no effect.
 
And darned if I didn't discover a different bug when I tested the code above! This time the problem was with the FOR loop: when put inside an ENQUEUE command, the increment of the FOR loop (that's the optional forth argument, where you specify how much to add to the counter variable each loop, like FOR i 1 10 2 to count by twos), which is assumed to be 1 if it's omitted, was being treated as 0, so the loop would continue indefinitely...or until the user pressed F12 to break out of it.  This bug is also fixed in version 4.1 b25.



Finally we get onto the scheduled topic of databases...

Magine: well, we only have a half hour left for the topic that was originally scheduled for today, databases, so maybe i should put that off til next time and add another class :D
Magine: is everything clear concerning queues?
ZebLith: yeah, queues are clear.  but, if you don't mind adding another hour to class, I really would like to learn about databases today.  Unless you have something else to do of course.
Magine: ok, i guess we can do that
Magine: so...databases...
Magine: i'm not really an expert on database stuff in itself,
Magine: but as far as how magsbot implements database use,
Magine: it connects to databases using an ADO (active database objects) component
Magine: so you can use any kind of database that ADO supports.
Magine: you can find some information about ADO connection settings for different kinds of databases at http://www.able-consulting.com/ADO_Conn.htm
ZebLith: okay, loading it up.
Magine: once you find the right connection setting for the kind of database you want to use,
Magine: you would use the @dbopen function in magsbot to create a handle to that database.
Magine: like
Magine: @@mydatabase=@dbopen[$Provider,$Connection,$Table]
Magine: that would create a global variable @mydatabase that you would then use with the other magsbot database functions and commands.
Magine: or, if you want to see the data in the magsbot database window,
Magine: you would use the DBPROVIDER, DBCONNECT and DBTABLE commands
Magine: that is, the DBPROVIDER and DBCONNECT commands specify the database to use in the magsbot database window,
Magine: while the database handle created with the @dbopen function,
Magine: is used to manipulate the database within a magsbot program.
Magine: for example,
Magine: suppose you want to use a MS Access database on your computer...
Magine: looking on the ADO page there, you can see that for an "OLE DB Provider for Microsoft Jet"
Magine: (MS Jet = the driver for Access)
Magine: on the web page it says

oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
           "Data Source=c:\somepath\myDb.mdb;" & _
           "User Id=admin;" & _
           "Password="
Magine: so for magsbot you would use all that for the connect string.
        [ignore the &_  part, that's a C language convention for joining strings together;
         in magsbot you would just use one big string]
Magine: and in this case the provider is specified within the connect string, so you wouldn't put anything for the DBPROVIDER command in magsbot
Magine: so you would use
DBPROVIDER "";
DBCONNECT "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\somepath\myDb.mdb;User Id=admin;Password="
DBTABLE "mytable"
(note there are no line breaks within the quoted part of the above example)

Magine: of course you would substitude your own database filename for myDB.mdb and your table name for mytable.
Magine: now for an example, the magsbot zip package contains a MS Access database named mydatabase.mdb
Magine: and the correct settings are already in magsbot.ini, but they are turned off.
Magine: to turn them back on, edit magsbot.ini and find the [Database] section
Magine: and remove the semicolon ; from in front of

;Provider=Microsoft.Jet.OLEDB.4.0
;Connect=Data Source=MyDatabase.mdb;Persist Security Info=False
;Table=MyTable
Magine: you may also find Provider= and Connect= (with no string specified), and if so just delete those lines.
Magine: actually, you should shut down the bot before making those changes, then restart it afterward.
Magine: oh, and another thing
Magine: as long as you have the bot shut down :)
Magine: you should find out what version of ADO is on your computer
Magine: there's a little utility you can use for that, at http://www.turtleflight.com/DL/ADOOK.exe
Magine: download that and run it, to find the ADO version on your computer
ZebLith: okay, I have 2.1
Magine: and once you know, you can also set that in magsbot.ini
Magine: you can see in magsbot.ini there's a comment that shows the number to use for each version of ADO:
; set ADO according to the version of ADO you are using
; 0=1.5
; 1=2.0
; 2=2.1
; 3=2.5
; 4=2.6
; 5=2.7
ADO=5
Magine: for example for ADO 2.1 you would put ADO=2 in the [Database] section of magsbot.ini
Magine: after making those changes and restarting the bot, you can press Shift-F3 to open the database window
Magine: (or else use menu Actions/Database...)
Magine: then click the Set button on the database window
Magine: and you can see the example database, which has one item in it right now

(Note: make sure it says MyTable in the Table box.)

Magine: got it working?
Magine: and BTW, for the benefit of those reading the class log,
Magine: if you don't have ADO on your computer, or if you want a more recent version,
Magine: you can get it free at http://www.microsoft.com/data/download.htm
Magine: but if you have windows XP then you probably already have ADO
ZebLith: hmm, I got "The application requested an operation on an object with a reference to a closed or invalid Connection object."  bleh...  lemme look back through this.
Magine: ok
Magine: did you make the changes in magsbot.ini, so in the [Database] section you should have:

Provider=Microsoft.Jet.OLEDB.4.0
Connect=Data Source=MyDatabase.mdb;Persist Security Info=False
Table=MyTable
Magine: exactly that, since we are now using the example database included in the magsbot zip
Magine: and make sure there is no blank like
Magine: Provider=
Magine: etc.
Magine: while you're doing that, let me try to clarify something
ZebLith: okay
ZebLith: still trying...
Magine: there are 3 different ways to connect to a database in magsbot
Magine: or maybe 2, depending on how you look at it :D but anyway
Magine: the settings in magsbot.ini control which database is used in the database window
Magine: and you can change those settings in magsbot.ini before starting the bot (that's the first way)
Magine: or, you can change them when the bot is running using the DBPROVIDER, DBCONNECT and DBTABLE commands
Magine: (that's the second way, sort of)
Magine: (though it's kind of the same thing, in a sense)
Magine: and third way, which i'll discuss in more detail in a moment,
Magine: is to use the @dbopen function to get a handle to a database, which can then be manipulated separately from the database that shows on the database window
Magine: and i recommend that third way for most programming uses, especially if you are using more than one database at a time
Magine: ok...so are you having any luck? :)
ZebLith: Current error: "Error setting Database: ADO could not find the specified provider"  I have it set to Microsoft.Jet.OLEDB.4.0 (correct?)
Magine: yeah
Magine: or, try leaving provider blank
Magine: and put that as part of the connect string
Magine: but nevermind, i have it the way you just said, so that should work
Magine: what version of windows are you using, btw?
ZebLith: 98 first edition.
Magine: yow
Magine: could be you don't have the OLE stuff on there, i'm not sure
Magine: well, we can try a different method perhaps
Magine: so you know if ODBC is installed on your computer?
ZebLith: Nope, I don't.  How can I check?
Magine: open the control panel window
ZebLith: okay
Magine: see if there is something there that says "ODBC data sources"
Magine: or "Data Sources (ODBC)" or anything with ODBC in the name :)
ZebLith: there is.  with (32bit) after it
Magine: ok, cool
Magine: click on it and open it, and see if MS Access is listed there
Magine: but don't change anything :)
ZebLith: MS Access 97 Database is listed.
Magine: ok
Magine: you can close all that then
Magine: we can try ODBC i think
Magine: let me find the right connect string
Magine: i'll set mine up for that too, to make sure it works
ZebLith: okay. :)
Magine: ok,
Magine: for provider just put
Provider=
Magine: and for connect, put
Connect=Driver={Microsoft Access Driver (*.mdb)};Dbq=MyDatabase.mdb;Uid=admin;Pwd=
Magine: (my awb word wrapped that, but it should be all on the same line)
Magine: provider and connect on different lines of course
Magine: then
Table=MyTable
ZebLith: that did it! :D
ZebLith: It's up and working now. :)
Magine: ok, cool :)
Magine: so...
Magine: you can use the database window to manipulate data manually
Magine: the + button adds a record, the - button removes the selected record
Magine: the up-arrow button is undo,
Magine: the check mark button saves changes (but they are also saved automatically when you move to a new line)
Magine: the X button cancels changes if they haven't been saved
Magine: and the curving arrow button is refresh
Magine: the other buttons are for navigation, self-evident i think :)
ZebLith: heh ^^
Magine: now, when you use any of the database functions or commands in magsbot by themselves, they will affect the database shown in the database window
Magine: but that can be inconvenient for a lot of reasons
Magine: so the better way to do it, is to create a separate database handle with the @dbopen command
Magine: and then use the magsbot database commands within a DATASET clause
Magine: for example....
Magine: let's create a database handle...
Magine: actually let's create a button for that
Magine: so create a new button, and in it put
@@MyDatabase=@dbopen["","Driver={Microsoft Access Driver (*.mdb)};Dbq=MyDatabase.mdb;Uid=admin;Pwd=",MyTable];
Magine: name the button "Open MyDatabase" or something like that
Magine: then create another button
Magine: and in it put
DBCLOSE @MyDatabase
Magine: and if you want, you can create a row at the top of the behavior table
Magine: with the Event column containing STARTUP and the Action column containing CLICKBTN "Open MyDatabase"
Magine: (well, also include the category name in the CLICKBTN command, whatever tab you created your button on)
        (i.e. CLICKBTN "MyCategory/Open MyDatabase")
ZebLith: okay :)
Magine: ok, so all done? and click on the Open MyDatabase button you just made
ZebLith: okay open
Magine: ok, let's add another row to the behavior table, that will record visitor information as people arrive :)
Magine: create a new row, and put AVATARADD in the Event column.
Magine: ...uh, wait a sec, let me do the same things i was telling you, and get a handle open myself, heheh
ZebLith: lol okay :)
Magine: ok, so in the behavior table, Event should be AVATARADD, for the action put
dataset @MyDatabase {
dbtable MyTable;
dbactive 1;
if @dbfindfirst[$fmt["Name='%s'",$avname]]=0 {
 dbappend };
dbedit;
dbfield Name=$avname;
dbfield_ ID=@atr[avatar_citizen];
dbfield_ LastVisit=@now;
dbpost };
Magine: there
ZebLith: oops, didn't turn the row on.  testing again. ^^
Magine: ok
ZebLith: oh oops, it's read-only right now.  bleh
Magine: oh yeah (ZebLith's database was opened as "read only")
Magine: gee what version of magsbot are you using?
ZebLith: 4.0, heh
Magine: hm
Magine: ok, well i made a goof in some earlier version,
Magine: so the default ADO setting is read only
(actually the default setting was "unspecified", but it turned out that was interpreted as "read-only", so I changed the default in later versions of Magsbot)
Magine: but we can change that easily
Magine: first close that database handle by clicking the close button you made (With DBCLOSE etc in it)
Magine: then, on the database window, click the button that says ADO version...
ZebLith: bleh... " [20513728] DBClose failed: External exception C000001"
Magine: oh well don't worry about that :P
Magine: we're going to restart it anyway
Magine: just click the ADO version button [on the database window],
Magine: and in the LockType dropdown,
Magine: choose ltOptimistic
Magine: instead of ltReadOnly

Magine: then click Set again and make sure the data reappears
ZebLith: it did.
Magine: ok, then click your Open MyDatabase button again
ZebLith: okay
Magine: and let's leave [the world] and return, in order to test the AVATARADD line we added
Magine: so

Much chaos ensued at this point, as ZebLith's bot was giving him a lot of error messages for no reason we could determine at first. After prolonged messing around (which I've omitted here since it's not very instructive or easy to follow), during which we verified that ZebLith had the right code and the right lines in the .ini file, restarted the bot, tested this and that, I finally concluded that although the database file appeared to be opening correctly, in fact a non-existent file was appearing to be opened (and with no error message from the database driver to reveal the problem!), due probably to a Windows 98 incompatibility with the Access driver.

Magine: maybe it's a version thing
Magine: win 98 you're running?
ZebLith: yep, first edition.  maybe next time I should move my files over to my brother's computer, which has winME.  the only reason we use 98 here is become mother insists upon it.

...

Magine: i guess it must be a version problem, i can't see anything else it could be
Magine: i think what is happening is
Magine: that the @dbopen function is not really opening the right file
Magine: maybe it's trying to create a new file

...

Magine: so i think what is happening, is that somehow win98 doesn't recognize the file
Magine: so you get some kind of not-really-opened database
ZebLith: lol, with win98 i wouldn't doubt it.
Magine: maybe if you put the entire path for the database name, instead of just MyDatabase.mdb
ZebLith: well, I've held you here for far longer than planned. >_<  Family is getting irrate about how I've been on for almost four hours...  Perhaps we can test this theory next time, and I'll try moving everything onto a winME computer?
Magine: ok
Magine: email me when you get a chance and tell me how it goes :)
Magine: magine@turtleflight.com
Magine: this will make for a strange class log :D
ZebLith: okay.  thanks again for all your help, I really appreciate it :)
Magine: yw, glad you could make it :)
Magine: see ya later...
ZebLith: *waves*

to be continued... :D



A good url for SQL commands: http://users.pandora.be/pecop/sqlr/