The First AI Plant Is Now Running

Wednesday, 20 August, 2008 by xorlabs

Strip debugging of the code referenced in the last post has resulted in several problems found and fixed. The modified code will be published probably during the coming weekend. With the fixes in place, the first plant’s script has been started. The plant is growing as expected, and should start to propagate early Friday morning. We hope to have a picture in the next post of the plant together with the seedlings it has spawned.

It’s here, sort of …

Saturday, 16 August, 2008 by xorlabs

Before we get started, I just want to say, “Thanks AlexM.  I appreciate your comments.”

The LSL script for the AI plant now has a completed first draft, which can be seen at this location.

The emphasis here is on “first draft” and there is no guarantee, or evidence, that as it exists it will work properly. It will undergo strip debugging during the next day or two, then testing will start. On that note, perhaps it is time for a little editorial commentary.

I’m Ingemar Zenovka, the founder of the XorLabs Research group in Second Life, and the one of our group who writes this blog. For quite a while now I’ve been doing software development for a living, but that is just about to change. Starting Tuesday of next week I start to work for a company whose principal responsibility is maintaining a great deal of the electric power grid in this State. Although my title is going to actually be Programmer Analyst, the work is going to primarily be specification and system integration of existing software packages, and helping to keep the part of the company’s massive computer system our group has responsibility for running properly. In other words, no more software development for a paycheck.

I won’t miss software development, because I won’t stop doing it. I’ll still be turning out all sorts of applications, some of which will be the topics of this blog. But it is unlikely that anyone will be putting a paycheck in my hand after this for actually creating lines of code.

The reason for this change is that the bureaucrats and paper pushers have just about sucked all the fun out of software development in the corporate world, with moronic things like The Agile Process, unit testing, UML, coding standards, etc. These pinheads have no understanding that programming isn’t science, technology, or bureaucracy. It’s an art and can’t be done effectively by robots.

The point of this is that the plant script is not going to be debugged in the manner prescribed by the so-called “Software Engineers”. It’s going to be done by spending a very long time looking at the code, running it through my mind and finding the errors, if there are any. It’s a much better way.

Ok, bitching’s out of the way. The next several blog entries will detail any problems that had to be fixed, and describe how the field of plants seems to be growing and spreading. After that, it will be time to get the bugs and the bug script running.

Excuses, excuses!

Sunday, 10 August, 2008 by xorlabs

As you can see, more about the plant and script was not forthcoming this past week.  There is Tropical Storm Edoard to blame, and a bit of laziness as well.  You often see the use of “we” in these posts; that’s not the Imperial We, it is just that I am speaking for the XorLabs Research group on SL, and your’s truly Ingemar Zenovka is the one doing all the writing here.  Anyway, there has been some progress on the script, and with a bit of luck we should be up and running in the next week (where have I heard that before!).

And now, the first AI plant

Saturday, 2 August, 2008 by xorlabs
Genus Aiplant, species GridGrass

Genus AiPlant, Species GridGrass

It’s our first leaf of grass, or maybe it’s a weed. In any case, it is a single prim, phantom and physical. That was the easy part. Not much effort was used to make it artistic, as the real effort will be in the AI script. Besides, if this thing is to multiply, we don’t want to over run the parcel’s prim count. Remember, we are eventually going to have bugs as well.

The script is going to require several elements:

  • Some means to manage its life span, including reproduction and life span.
  • Some means to provide food to the bugs when they are introduced.
  • Some means to receive parameter information.

The past several posts have pretty well covered the last element in the list. We’ll talk a bit about the first two elements in this post.

Being a plant, it is going to have to sprout, live a particular time, then die. During the course of that life, it will have a processing cycle, attending to its various life tasks each time through the processing loop. In the earlier part of its life it will grow somewhat, and towards the end of its life it will start to turn brown, die, and hence disappear. It will require another object to effect this life cycle, and that will be a seed. The seed will be quite small, and will be contained in the plant’s inventory. When the plant reaches the point of spreading its seed, it will place a copy of itself into the seed’s inventory then expel the seed. The seed itself will have a relatively simple script as well, being responsible for simply rezzing the plant in its inventory then deleting itself. The new copy of the plant will then proceed on its own independent life cycle.

Just in case there are still some of the uninitiated among you, “rezzing” is the Second Life term for pulling an object out of inventory and making an instance of it appear in the virtual world.

The plant will have a certain store of energy, simulating drawing sustenance from the soil. Being a living thing, it will become progressively less and less able to do this during its life, whereby its energy store will dwindle until it dies. Bugs feeding on it will tend to hasten this process as they draw their sustenance from the plant. The feeding process will be an adaptation of the protocol used in the ecosystem of the Second Nature 3 sim. Since there will be only one species of plant, and eventually one species of bug, that protocol can be simplified a bit.

A plant will be initialized to listen on a channel derived from its key. The uniqueness of the key will result in each plant listening on a unique channel. Bugs will start roaming around the ecopod, using the cyclical sensor function to detect nearby plants. When a plant is detected, the bug will get the plant’s key, and use the same algorithm the plant uses to derive the channel number. The bug will then send a message to that plant requesting energy, and the plant will respond. The plant loses a bit of energy, and the but gains some.

Now comes the hard part. An ecological balance must be maintains so that the bugs don’t multiply so fast and eat so much that the plants are all eaten up[. However, the bugs must multiply at a rate to sustain their population. Both the plant and bug population must be in balance. Parameters in the bug and plant scripts will have to be adjusted to maintain that balance, and that will have to be done experimentally over a period of time. An enhanced version of the XML-RPC application previously described will periodically transmit adjustments based on how our bug and plant population progresses.

The plant and seed scripts should be ready sometime next week, and we hope to start the plants reproducing. Our next post will have the details of these scripts.

… and the prototype system is complete.

Friday, 25 July, 2008 by xorlabs
The XML-RPC Receiver

The XML-RPC Receiver

With the completion of the LSL script which is resident in the object shown above, our prototype XML-RPC communication system is complete. It has served as a proof of concept system, but is not fully developed to serve the needs of the artificial life ecosystem we are planning. However, the code used is easily adaptable to our subsequent uses, or uses you may have for that matter. With that in mind, let’s examine the code. The LSL script is displayed on our website.

The state_entry() event handler in the default state calls the LSL function llOpenRemoteDataChannel(). The server will respond by calling the event handler function remote_data() right below it. This is the same event handler which the server will call later when XML-RPC messages are received by the Linden Server from our offline application., The event handler determines which type of call using a conditional on the value of the integer argument type. When the value of this argument is REMOTE_DATA_CHANNEL, the assigned channel ID is stored, and also transmitted to our website using LSL’s HTTP capability. There the channel ID is stored in a table in our database by the ASP page which is addressed. The offline application accesses that table when it runs to get the channel ID for its message formation.

Note that the state_entry() event handler in the default state is called every time the script is reset, which of course is every time a script is edited and saved when editing with the Second Life viewer. Also, note that in the default state there is an on_rez() event handler. It will be called each time the object is rezzed out of the inventory and it will cause the script to be reset as well.

Once the channel is assigned by the Linden server, and it is receiving XML-RPC messages, it will parse the XML received. It then will call the remote_data() event handler, passing the string parameter and the integer parameter transmitted by our offline application. The LSL script is thus relieved of the requirement of parsing the XML data, leaving that up to the Linden server. As a purely diagnostic check, and to satisfy the requirement that a scripted object must make an XML-RPC reply, the parameters received are simply echoed back. As you recall, the integer parameter is not used in the prototype system, but it must be included in the initial message and the response to satisfy the message format requirements.

Once the parameters are received, they are stored in global variables, and a function is called to distribute the parameters to the AI objects. The two currently identified floating point parameters are still in the CSV string, and would be sorted out by the receiving AI life. Should additional parameters be identified later, they would simply added to the CSV string. This seems simpler, allowing the XML-RPC receiver code to be independent of the eventual number of parameters to be passed,

Note that the parameter values are distributed using the llSay() function. This requires that any receiving AI objects be within 20 meters of the receiver. Considering the size of our ecopod, some sort of secondary distribution system of objects would actually be required to distribute parameter messages to all AI objects so contained.

This completes our series on XML-RPC with .NET and LSL. There is still much to do to develop the AI objects in the ecopod, although that will not be the principal topic in this blog. Instead, we will continue to concentrate on enhancing LSL by adding capability from offline machines using .NET.

We’re Almost Done.

Thursday, 24 July, 2008 by xorlabs

The Prototype Offline Application

The offline C# application shown in the screen shot above is complete and working. The top button causes an access to our database on ZenovkaTek.com which will return the desired parameters for our AI plant scripted object. Clicking the second button will similarly access the ZenovkaTek.com database, this time returning the channel ID. The channel ID is requested by the scripted object on Second Life and transmitted to a page on ZenovkaTek.com which posts it in the database. Of course, we could also just type those values into the text boxes. The real story is what happens when the third button, labeled “Transmit” is clicked. The code for the event handler for the “Transmit” button is posted on our website.

The posted code begins by using the RequestMessage class previously described. An instance is created and fed the channel ID, the two parameter values as a comma delineated string, plus a randomly generated integer value. The latter value is only there because the XML format of the message requires there to be a single integer parameter. The resulting XML message, stripped of all newlines and tabs, is returned by the GetMessageString() method of the RequestMessage class.

The code which follows sets values for the HTTP headers, declaring the method to be POST and the mime type to be application/x-www-urlencoded. Finally, the URL of the Linden server which will receive the message, xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi, is used in the argument of the WebRequest.Create() method to create an instance of HttpWebRequest. That will initiate the HTTP request. Once the XML-RPC message is written into the HttpWebRequest object’s request stream, and the request stream is closed, the HTTP request can be initiated.

The HTTP request is initiated by calling the HttpWebRequest object’s GetResponse() method. Note that it is called in a try/catch block. You can see in the catch part of the block that there are clearly a lot of things that could go wrong, and the switch statement is there to see which, if any, of these errors would have caused the problem. The cause of an exception, should one be thrown, would be printed out on the status printout.

The Linden server handled the parsing of the incoming XML, extracting the parameters and sending them to the scripted object. As you will see in our next post, the scripted object simply returns any parameters to the Linden server, and the Linden server will formulate the return XML message and send it to the requesting offline application. Our application will then have to handle the parsing and parameter extraction after the response is received. Currently, the scripted object is simply echoing the values it received. You can see in the status readout in the screen shot of the application that what was sent out was correctly echoed back and received.

The XML parsing uses the so-called LINQ to XML axis methods of the XElement class. The return XML looks exactly like the XML which was sent out, except for the name of the root element. Our application sent an XML message with a root element <methodCall> and the return XML has a root element <methodResponse>. Recall from a previous post that the three values transmitted, hence the three values echoed back are (1) the channel ID; (2) the Growth Rate and Average Life Span values concatenated in a comma delineated string; and (3) an integer value thrown in to fill out the Linden defined XML message. Each are contained within a <member> </member> tag pair. Within that tag pair the message is further partitioned into a name and a value as shown in the message exceprt below:

                    <member>
                        <name>Channel</name>
                        <value><string>6df57cf4-68b7-b958-5b6c-10cb9f2fa391</string></value>
                    </member>
                    <member>
                        <name>StringValue</name>
                        <value><string>6.35,1.58</string></value>
                    </member>
                    <member>
                        <name>IntValue</name>
                        <value><int>1413957003</int></value>
                    </member>

Parsing is additionally complicated by the fact that each member value is further encapsulated in a tag pair which declares the data type of the value. Additionally, our code must separate out the Growth Rate and Average Life Span values which must be returned as a comma delineated string. Once that is done, the result is printed on the status readout as you can see in the screen shot at the beginning of the post.

The LSL script is complete to the extent that it requests a channel ID, receives the parameters passed to it by the Linden server, and correctly echoes them back to our offline application. We have a few more things to do with the script, and the scripted object in which it resides, and will post that information next time.

Our next post will complete the prototype phase of the project, and illustrate the various techniques necessary to use XML-RPC with LSL scripted objects on Second Life. There will still be quite a bit to do with the AI objects, as we will show you in subsequent posts.

… and the problem is solved!

Wednesday, 23 July, 2008 by xorlabs

The page posted on our website has been corrected. There were actually two problems. The first was that the XML message was not well formed. Notice that each of the parameters in the message should be bracketed with tags indicating the data type. The original LINQ to XML code in C# failed to add those tags, so not surprisingly, the Linden server’s parser rejected it.

The second problem was that the XML string returned by the XElement class ToString() method neatly adds tabs and newlines so that the XML looks good when printed out. Unfortunately the Linden server’s XML parser chokes on the resulting string. Adding a couple of lines of code removing the tabs and newlines results in one long string, but makes everything work just fine.

The class as you now see it is working in a prototype C# application which is correctly transmitting XML-RPC to a scripted object and is receiving an echo of the parameter values being returned by the scripted object from SL. We will show you the LINQ to XML code which parses the return message and the completed LSL script probably during or before the weekend.

Opps!

Tuesday, 22 July, 2008 by xorlabs

Further testing has determined that there is an error in the code we provided for the class which creates the XML-RPC message to send to the scripted object. It will get fixed as soon as possible, and the correct code will be posted.

Using LINQ to XML

Sunday, 20 July, 2008 by xorlabs

Our next installment describing the implementation XML-RPC shows how to create the XML-RPC request message using LINQ to XML. The WordPress text editor is a bit unsuited for proper display of code, or XML for that matter, so we have posted the page on our website . We show the XML format of the request message together with the C# class which produces it. Coming next will be the C# code which will perform the HTTP to get the request message to the scripted.

Once we have the message on its way to the scripted object, the focus switches to LSL as we show how the message is handled. The Linden server will parse the XML and simply return the arguments to the script. The script will provide a return message which the Linden server will format into an XML reply message. To complete our work, we will show how LINQ to XML will parse the message and get the data which is returned.

… And, We’re Back.

Saturday, 19 July, 2008 by xorlabs

The problem we experienced with our online database at 1and1.com seems to have vanished, at least for now, meaning that our search for a more reliable provider of web space can be done at a more leisurely pace. Now the intent is not to let this blog degenerate into a tirade about the unreliable service 1and1.com can provide. There are, however, a couple of closing notes.

Some earlier posts mentioned 1and1.com in a more or less favorable light. Now that their motto is, “When tech support seems to be needed, seem to provide it”, we don’t want to be thought to be promoting 1and1.com in any way, or giving the impression that we are satisfied with their service.

Finally, a bit of irony. The problem encountered was that the 1and1.com page where one administers the database would never load. This morning, 1and1.com sent an email inviting us to take a survey on how well tech support helped. The email provided a link to a 1and1.com page where the survey could be taken. Unfortunately, that page would never finish loading.