Monday, 5 September 2011

More on the NPC as a cloud in opensim vanilla

K so i tinkered around and it turns out that it wasn't the server at all, it was imprudence.

When I went to LBSA plaza nobody could see me. I was a cloud to them. So it would seem that although I could see myself in imprudence, everyone else saw me as a cloud. Stands to reason then that if I loaded my current appearance (a cloud) into an NPC then I would also see the NPC as a cloud.

Turns out the simple fix (from Qandy Saw at LBSA plaza) is this:

Go to Preferences > Graphics and click Anisotropic filtering on then save settings.
Everyone else will then be able to see you.

At that point you can rezz the NPCs.

Sunday, 4 September 2011

Update to Opensim NPCs

Looks like Justin Clark Casey did some work on the vanilla opensim end.
From my reading of it, it doesn't look like it's as far along as the aurora code. That said if it can be gotten to work, most of the aurora code could theoretically be ported.

The advantage of getting it to work with Opensim is of course that most of the open metaverse servers run on OpenSim instead of Aurora and you can connect it to OSGrid.

Unfortunately, when I tried it by bringing up my own region on osgrid, the NPCs while they do appear, remain as clouds. I must be doing something wrong but don't have time right now to go figure out what.

That said, a few days ago I got a demo from Haplo Voss and the NPC on his region did load the appearance so I'm probably just doing something stupid.

Justin Clark Casey's wiki for OpenSim NPCs is here: http://opensimulator.org/wiki/OSSLNPC

Also: An interesting rumor is that the big grid i.e. Linden grid is going to implement server side NPCs at some point.

Saturday, 18 June 2011

Nearly there

So I think I have basically all the pieces for a basic zombie game. Right now it works on my local so I've been looking for a place that will give me a full grid with root access. Looks like opensimhosting is the guy. Darren Williams was super helpful and got me up and running quickly.

Next piece is to re-hack my spawn-follow-attack code so that it works with aurora-master. Revolution Smythe moves so fast that it's hard to keep up lol. I move at a snails pace.

Anyways, I have a gun script that works as long as you have osCauseDamage set to true wherever that is in the .ini files (looking now) and also have damage set for your region.

Also I'm playing with zbrush so I can make my own meshes/sculpties. So far I've been able to make an ugle-assed set of wooden hair that is about as bad as the worst freebies and likewise I've been able to make a pretty clunky looking rifle but it's early days and a lot of fun.

Monday, 30 May 2011

Update

So I got the NPC code up to the point where it can follow you pretty successfully and then kill you. Additionally I wrote a piece of code that reads a ZHAO II formatted notecard out of the template avatar's inventory and uses the UUIDs it finds there for such animations as MeleeAttack, ProjectileAttack, Die etc etc. That way it makes it much easier for someone inworld to customize the appearance and animation behavior of NPCs without the need to get access to the code-base. It just makes things easier, really.

Anyways, then...Revolution Smythe who is a complete and total genius, extended Christy's Astar pathfinding code so that the follow code is better, the NPCs can follow you up stairs, round walls, over walls, fly after you etc etc.

Outstanding are getting the avatars to die (right now they won't die and mercilessly kill you over and over lol) and also some client side weapons/gun scripts.

The piece I'm working on currently is trying to get the avatars to play a "dying" animation once their health points go to zero or below. It's not working yet and it's been especially entertaining trying to get a chance to run a "kill" script while being relentlessly pursued by NPCs intent on your gory death. Fun times were had by all LOL.

Also: I borked my branch on github somehow when I tried to merge the code from the main branch over the weekend. Not being a github expert I don't know how to clean it up and it's just a big hassle really so I took the easy way out and just created a new repository with just the NPC project (i.e. aurora/botmanager). Since my code should just be a drag and drop replacement for the aurora/botmanager in the main branch that should make things much easier. Especially for those who have been unable to get my branch to compile (nod of the head to Enrico).

Saturday, 28 May 2011

How to add 32 bit launcher into the project

If you get a fresh virgin copy of aurora from the github master branch it will compile just fine in VS2008 but depending on the machine you have it might not run. This is the case on my machine so I spoke to Rev and he said I need to add the 32 bit launcher to be able to debug it in vs2008.
So on the right hand side in the solution explorer panel, right click on "solution 'Aurora'" right at the top and choose "add reference" then go looking for OpenSim/Tools/32bitlauncher and find the project.

You might also have problems with SmarthThreadPool, which is found in openSim/tools/smartthreadpool.

Tuesday, 10 May 2011

k so proof of concept of killer NPC attack bot

After struggling with the animation code and non-active damage code I eventually code a proof of concept attack bot to work.

It's hard-coded at the minute and basically what it does is it follows the prey avatar and when it gets close enough if it's in attack mode (which it is) it proceeds to play the hardcoded attack animation. It also reduces the prey avatar's health points by 10 each time until the prey avatar's health points reach zero. It will continue to dog the avatar even if the avatar moves away until it kills them. At the point at which it kills them the predator NPC goes out of attack mode and just sits there.

Obviously some more complicated AI would be good. For example, it would be good if an idle bot also attacked. So maybe what needs to happen is that the sensor prim makes all not attacking bots attack the nearest avatar. Anyways, the proof of concept works so now I need to think about how to improve on it and especially remove the hardcoded animations to make it easier for others. Probably the next step is to get it to be able to use ZHAO cards or a modified version for attacking animations et cetera.

Anyways the code is here:
https://github.com/x8ball/Aurora-Sim/commit/4d9ef599515a770be20602c934854ad51d9309ed#diff-1

Wednesday, 4 May 2011

Server side AO on the bot

Additionally on the to-do list is a server side AO for the bot using a standard ZHAO notecard.
The plan is to create a fixed directory called aurora/bin/ao whereby each bot's AO animation list will be inside a notecard formatted in standard ZHAO format and called the name of the seeding avie used to seed the bot. i.e. a bot called "test bot" seeded from avie John Doe would have a notecard called JohnDoe.txt (for example) inside aurora/bin/ao.

This code is lower down the priority list in the to-do's but it's in there. Before I do this I'm going to finish the detect-spawn-follow-attack code which will also involve digging into the LSL collision or sensor stuff. The scripting engine seems to be a little flaky in that scripts sometimes don't work (I tried the collision code last night and it didn't work very well so as a backup I could write something into the botmanager code but I digress).

So returning to the Server side AO, we will need code to pick up directories and code to read files etc. Clues to that code should be in the following code snippet:

private void FindDefaultLSLScript()
{
if (!Directory.Exists(ScriptEnginesPath))
{
try
{
Directory.CreateDirectory(ScriptEnginesPath);
}
catch (Exception)
{
}
}
string Dir = Path.Combine(Path.Combine(Environment.CurrentDirectory, ScriptEnginesPath), "default.lsl");
if (File.Exists(Dir))
{
string defaultScript = File.ReadAllText(Dir);
foreach (Scene scene in m_Scenes)
{
ILLClientInventory inventoryModule = scene.RequestModuleInterface();
if (inventoryModule != null)
inventoryModule.DefaultLSLScript = defaultScript;
}
}
}

Working on the detect-spawn-follow-attack code

So what I'm working on (loosely) at the moment is basically a detect-spawn-and-attack method a la left 4 dead or else call of duty. So basically an avie walks close to a spawning point, the spawning region detects the avie's presence, spawns a bot, sets the bot to follow the avie and sets the bots belligerence level to "hostile".

Then the bot will follow the avie till it gets close enough and then it will attack which means run the appropriate attack anim and then call the code to do damage to the avie.

Rather than do all of this code myself I can piggyback on the existing follow code and at the same time change the belligerence state to hostile. Then I can mod the code that stops the avie from walking when it's close enough (in the follow code) to instead check to see the attack state and take appropriate action instead.

So here's the follow code in rexbot.cs with the appropriate places to mod commented:

//this is the follow code
CurrentFollowTimeBeforeUpdate++;
if (CurrentFollowTimeBeforeUpdate == FollowTimeBeforeUpdate)
{
Vector3 diffAbsPos = FollowSP.AbsolutePosition - m_scenePresence.AbsolutePosition;
if (Math.Abs (diffAbsPos.X) > m_closeToPoint || Math.Abs (diffAbsPos.Y) > m_closeToPoint)
{
NavMesh mesh = new NavMesh ();

bool fly = FollowSP.PhysicsActor == null ? ShouldFly : FollowSP.PhysicsActor.Flying;
mesh.AddEdge (0, 1, fly ? TravelMode.Fly : TravelMode.Walk);
mesh.AddNode (m_scenePresence.AbsolutePosition); //Give it the current pos so that it will know where to start

mesh.AddEdge (1, 2, fly ? TravelMode.Fly : TravelMode.Walk);
mesh.AddNode (FollowSP.AbsolutePosition); //Give it the new point so that it will head toward it
SetPath (mesh, 0, false, 10000, false); //Set and go
}
else //distance is less than the follow range.
//in here (the else block) we need to check if we are to attack

//(if the bot is hostile we attack
//otherwise we just stop the bot
{
//if the bot is hostile we attack
//attack code goes here
//else
//Stop the bot then
State = RexBotState.Idle;
m_walkTime.Stop ();
m_startTime.Stop ();
}
//Reset the time
CurrentFollowTimeBeforeUpdate = -1;
}

Friday, 29 April 2011

The following is the code that will let you access rexbot code from the botAPI

I've been scratching my head trying to figure out how to access the RexBot code from inworld.

Obviously when things are stable and the game AI is built in to the RexBot code it should run smoothly, but there will be need for hooks into the bot itself from inworld so that I can test it. That leads to the need for me to be able to access the methods and properties of the RexBot code from within the botAPI. Basically they exhibit two different interfaces. Rexbot is IClientAPI and botAPI doesn't have IClientAPI.

Luckily however, we can get access to the Rexbot code through the botmanager code. What I had to do was add a function to the botmanager code which pulled out the appropriate rexbot from the internal private m_bots collection of bots. From there I can get access to the public members.
Which is exactly what I need to do in order to be able to easily test. So *now* I believe I'm well on the way to being able to make the changes I want to make.

public void botSetState(string bot, string State)
{
//this is a test case of being able to get access to a property
//of the actual rexbot itself through the botAPI
IBotManager manager = World.RequestModuleInterface();
if (manager != null)
{
RexBot rxbot;
rxbot = (RexBot)manager.GetBot(UUID.Parse(bot));
//follow up with this
switch (State.ToLower())
{
case "walking":
rxbot.State = RexBot.RexBotState.Walking;
break;
case "idle":
rxbot.State = RexBot.RexBotState.Idle;
break;
case "flying":
rxbot.State = RexBot.RexBotState.Flying;
break;

default:
rxbot.State = RexBot.RexBotState.Unknown;
break;
}
}

}

Thursday, 28 April 2011

Code to animate the avatar

Here's a rebased version of Christy Lock's code which will animate the bot:

Add the following code to the Bot_API.cs in the Botmanager module:

public void botAnimate(string bot, string AnimationUUID)
{
m_host.ParentEntity.Scene.ForEachScenePresence(delegate(IScenePresence sp)
{
// this should be the bot id
if (sp.UUID == UUID.Parse(bot))
{
sp.Animator.AddAnimation(UUID.Parse(AnimationUUID), UUID.Zero);
}
});

}

Code to determine the distance between NPC and human's avatar

One of the code snippets I need to do is determine the distance between the NPC and the human avatar in order to determine if I should be running the animation code or not. There's already existing code by Christy Lock to do that for her AStar pathfinding class. This is a rebased version of it which should do the trick hopefully:

Vector3 diffAbsPos = FollowedSP.AbsolutePosition - m_botscenePresence.AbsolutePosition;
if (Math.Abs (diffAbsPos.X) < m_closeToPoint || Math.Abs (diffAbsPos.Y) < m_closeToPoint)
{
// run the attack code here which includes animation and reducing the health points of
// the attacked human, possibly pushing et cetera depending on the force applied
}

So what this does is get a vector between the scenepresence of the followed avatar (i.e. the human) and the scenepresence of the bot. Then it does some math which amounts to checking if either of the X or Y coordinates of the vector are less than the closetopoint (which is 1 i.e. one unit). Depending on the animation to be run, this could vary but 1 unit is good for now.

On decision trees and goal oriented planning

I like to do a lot of research before I actually start coding so I read up on the latest in AI gaming theory and it turns out that the most lifelike NPCs utilize something called goal oriented planning. I kind of know what this is: it's a sequence of steps to get to a goal i.e. a decision tree.

Where it differs from a decision tree is that a decision tree is typically a hard coded best-estimate of the route to get from where you are now to a planned goal (whether it's a physical location or a state or an action or whatever).

But if we switch it up a little bit and allow competing sub-goals to compete for the fastest path to the goal and update the subgoals-in-running and various choices of paths to the goal then we have something more interesting and this is in fact the goal oriented planning situation I'm reading about.

What's interesting about this is that it means effectively that pathfinding and goal oriented planning are exactly the same thing. In other words A Star (or A*). So I need to dig into A* a little more.

Interestingly, Christy Lock has been bending my ear about A* for pathfinding already and she has already coded some A* into the code, so maybe it could be switched up a little to handle pathfinding to a goal.

But that's for later. For now I'm going to stick to a simplified attack decision tree for the first step.

Any case, here is pseudo code (from wikipedia) for the A* algorithm in case anyone is interested.

function A*(start,goal)
closedset := the empty set // The set of nodes already evaluated.
openset := set containing the initial node // The set of tentative nodes to be evaluated.
came_from := the empty map // The map of navigated nodes.

g_score[start] := 0 // Cost from start along best known path.
h_score[start] := heuristic_cost_estimate(start, goal)
f_score[start] := h_score[start] // Estimated total cost from start to goal through y.

while openset is not empty
x := the node in openset having the lowest f_score[] value
if x = goal
return reconstruct_path(came_from, came_from[goal])

remove x from openset
add x to closedset
foreach y in neighbor_nodes(x)
if y in closedset
continue
tentative_g_score := g_score[x] + dist_between(x,y)

if y not in openset
add y to openset
tentative_is_better := true
else if tentative_g_score < g_score[y]
tentative_is_better := true
else
tentative_is_better := false

if tentative_is_better = true
came_from[y] := x
g_score[y] := tentative_g_score
h_score[y] := heuristic_cost_estimate(y, goal)
f_score[y] := g_score[y] + h_score[y]

return failure


function reconstruct_path(came_from, current_node)
if came_from[current_node] is set
p = reconstruct_path(came_from, came_from[current_node])
return (p + current_node)
else
return current_node

K so Christy solved the animation problem

The Awesome Christy Lock solved the animation thing even while I was writing the last post. I'll post the code later on tonight for how to do it.

So for me the next thing is to implement a simple spawn/locate human/move closer/attack/defend/withdraw decision tree.

The code to get the position of the nearest avatar could be in the chat code because I'm vaguely sure I saw a function that returns the avatar's location who chatted the message.

If that code is generic, it should be useable to determine the distance to the avatar so the decision tree should look like this:

Spawn!
Is human near enough to me that I can start the attack animation?
Nope
Move closer
Is human near enough to me that I can start the attack animation?
Yup
Start the attack animation
etc

Alternatively I could just do this:
Spawn!
Is human near enough to me that I can start the attack animation?
Nope
Run the follow avatar code
Is human near enough to me that I can start the attack animation?
Yup
Start the attack animation
etc

Then after that it would hook up to some kind of code that determined the human's hit points and damage he/she was taking etc or fed it directly into the health monitor you see in damage enabled areas when using imprudence.

Animations: k so that's interesting

So that's interesting.

I've dug through the code of osAvatarPlayAnimation and it ultimately leads back to SendAnimation which is a virtual member of the IClientAPI interface which is an interface of RexBot.cs and the old GenericNPCCharacter.cs.

But there's nothing in it. i.e. no implementation.

But yet I know the the osAvatarPlayAnimation works because I've already called it from a script inworld on an Aurora Sim.

So I guess I have to try it again but leave a breakpoint in the code to see where it goes. Maybe then I can cut and paste the relevant sections of the code into the bot so we don't need to set the threat level to high and call it inworld, but instead have it run on the server code.

Coding up animations

One of the things that it will be useful for an NPC to do is run animations.

Consider:

A human player walks down a street past a bot-spawning prim. A script in this prim detects the human player and boots up the decision tree which cascades through the criteria until the decision is taken to spawn an NPC in an angry hostile state with the goal of attacking the human interloper.

So the bot spawns, moves forward into range and then needs to attack. One of the things it should do when attacking (in order to make the experience enjoyable for the human player) is play a reasonable animation which is relevant to the attack.

So... it's necessary to code in some kind of animations to the bot. One of the things we'll need to do is make sure that it's only bots that can be animated or else the potential for griefing would be astronomical. We obviously don't want the ability to script any other player to perform a random animation without their permission, so we need a permissions check built in to make sure that it is in fact a bot and not a human player. That's easy enough to do though.

So the next piece is the actual animation code. Currently that's sitting in the OSSL_API.cs, which I think is not the right place for the code for bots because to run it you need the threat level to be high. Animating a bot is not a high threat level even though animating another human character against their will might be. Any case, I'm going to see if I can't hack up something from the code and put it into the bot code. The following are the two relevant functions, startanimation and stopanimation:

public void osAvatarPlayAnimation(string avatar, string animation)
{
ScriptProtection.CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarPlayAnimation", m_host, "OSSL");

UUID avatarID = (UUID)avatar;


if (World.Entities.ContainsKey((UUID)avatar) && World.Entities[avatarID] is ScenePresence)
{
ScenePresence target = (ScenePresence)World.Entities[avatarID];
if (target != null)
{
UUID animID=UUID.Zero;
lock (m_host.TaskInventory)
{
foreach (KeyValuePair inv in m_host.TaskInventory)
{
if (inv.Value.Name == animation)
{
if (inv.Value.Type == (int)AssetType.Animation)
animID = inv.Value.AssetID;
continue;
}
}
}
if (animID == UUID.Zero)
target.Animator.AddAnimation(animation, m_host.UUID);
else
target.Animator.AddAnimation(animID, m_host.UUID);
}
}
}

public void osAvatarStopAnimation(string avatar, string animation)
{
ScriptProtection.CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarStopAnimation", m_host, "OSSL");

UUID avatarID = (UUID)avatar;


if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence)
{
ScenePresence target = (ScenePresence)World.Entities[avatarID];
if (target != null)
{
UUID animID=UUID.Zero;
lock (m_host.TaskInventory)
{
foreach (KeyValuePair inv in m_host.TaskInventory)
{
if (inv.Value.Name == animation)
{
if (inv.Value.Type == (int)AssetType.Animation)
animID = inv.Value.AssetID;
continue;
}
}
}

if (animID == UUID.Zero)
target.Animator.RemoveAnimation(animation);
else
target.Animator.RemoveAnimation(animID);
}
}
}

Wednesday, 27 April 2011

K so here's the AIML stuff as promised

Do this.

Go get the AIMLBot source here: http://ntoll.org/file_download/18

Next, unzip the contents and open the solution with Visual C# 2008. It will ask you to convert it to a C# 2008 file. Do it.

Next, go take a look inside the folder where you extracted the AIMLBot solution. There will be a file called "AIML.zip". Extract this file into a folder in the aurora bin directory called aiml.
i.e. aurora\bin\aiml

You will have to create the aiml folder first of course.

Next step is to open up the aurora solution and select the main solution right at the top. Right click this main solution and choose "add new project". Browse to the C# 2008 solution of AIMLBot that you created earlier and add it to the project.

Next find the subproject in the aurora solution called Aurora.botmanager and right click it and choose "Add Reference". On the Add Reference window choose the "projects" tab (should be the third tab at the top) and find and select the AIMLBot project you just previously added as a new project to the main aurora solution.

Next open the C# source file RexBot.cs and add the line "using AIMLBot;" underneath the line which says using System.IO; right at the top of the file after the copyright stuff.

At this stage we are ready to rock and roll and you have successfully added AIMLBot to the project. Now we need to enable it. Do the following steps:


Just before the first C# property in RexBot.cs "public RexBotState State", add a declaration for the AIMLBot: add this line
private cBot myBot;


Next you have to actually instantiate the bot. So find the following constructor function:
// creates new bot on the default location
public RexBot(Scene scene, AgentCircuitData data)

Right at the end of this constructor function after "UniqueId++;", add the following line:
myBot = new cBot(false);

Now we have the bot instantiated. So we just need to listen for it now.
So find the function SendChatMessage which says this:
"public void SendChatMessage (string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible)"

Add the following lines of code in the function:

String fromNameLower = fromName.ToLower();
String firstNameLower = m_firstName.ToLower();
String lastNameLower = m_lastName.ToLower();
String NameLower = firstNameLower + " " + lastNameLower;
if (fromNameLower.Contains(NameLower) || message.Length==0 || source!=(byte)ChatSourceType.Agent )
{
return;
}


cResponse reply = myBot.chat(message, NameLower);

this.SendChatMessage(1, reply.getOutput());



Your bots are now self aware. Long live Skynet!

AIML: Success!

So I managed to get it going. It's a complete hack and I don't have the code handy right now (I'll post it later tonight) but the gist of it is this:

I tracked down an older and simpler copy of the AIMLBot C# source which was written against the really, really old (in computing terms) dot net 1.0 library. I figured that given that it was so ancient, the 2008 c# compiler should be able to upgrade this easily since there've been a lot of years in between.

I was right. So I downloaded the code, made it into a C# 2008 project and added said project to the aurora sim codebase. Then I added a reference in the aurora.botmanager subproject to the AIMLBot project and added a line of Using AIMLBot; to the namespace references at the top.

Then I was able to access the functions in AIMLBot so it was then a case of looking for "what has the user said to the bot?" and "what is the bot's response to what the user has said?" types of calls in the AIMLBot code.

Luckily there a fairly straightforward piece of sample code whereby there was a simple form where you typed into a text box and the bot responded in another textbox with it's answer, so I cut and pasted that code into the right places in the rexbot.cs class and ran it.

No joy. It still crashed out because the bot decided to talk itself into an infinite loop and crashed the stack.

Luckily I was able to track down the venerable Latif Khalifa, author of the awesome piece of client side software, radegast. I know he had basically solved the infinite feedback loop because the AIMLBot code is already in radegast, just I couldn't figure out the hooks.
He pointed me to the one line of code in radegast and I just translated that into the equivalent in the rexbot.

Basically it's a check to make sure that it's a human speaking and that it doesn't have the same name as the bot or else is not an empty message. That basically takes care of all the crappy messages which send the bot into infinite tailspin.

Result was I got a server side bot that talks. Suh-weet.

It still has a glitch though in that the bot refers to *everyone* as "unknown user".
But that's positively a minor issue for now which I'll work on later.

Later tonight I'll post the code on here because I'm too dumb to figure out how to commit to github without overwriting my own changes LOL.

Saturday, 23 April 2011

So a small piece of progress

Trying to hunt down where/how the bot code listens for chat messages.
In the Bot_API.cs code there is a botSendChatMessage function which you can use to send messages from the bot. What I wanted was the event to intercept whereby chat messages are being actively listened for by the bot. Obviously the botSendChatMessage isn't it since this is a function you call rather than a function that responds to chat events.

So where is it?

I couldn't find it and had to ask the guys. Rev Smythe (genius) told me it was in the EventManager code so all I had to do was put a breakpoint there, type a chat message in and watch what happens. So the event fires when someone chats. It goes and gets a list of scenepresences and then fires a SendChatMessage function to each of the individual scenepresences.

Our particular scenepresence (i.e. the bot) was indeed found and it called RexBot.cs's implementation of SendChatMessage (which is empty....) so perhaps something could go there.

But wait (I'm typing this as I go through the code LOL) there's something else.... in the RexBot.cs code is an event called OnBotChatFromViewer.

Hmmmm I wonder if that's what I'm looking for.

Hmmm no. It didn't get called. The only code that does get called is RexBot.cs SendChatMessage. OK so that's where I'm going to have to intercept the chats and send them to pandorabots...

Friday, 22 April 2011

AIML: Progress of a sort

So I played around with the Aurora NPC code trying to implement the AIML code. I didn't really come to any firm conclusions and have more questions than answers or results, so this post is more of a ramble more than anything else or in other words, I'm collecting my thoughts and dumping them out as an unparsed stream here...

Some observations are that Ken's code (found here): http://kennethrougeau.com/geekery/opensim-server-side-npc-experiments-day-three/

is actually client side code which hooks up with the website pandorabots. Ken explains it better than I do on the page but the gist of it is you sign up for a pandorabot, get an ID for it (which is generated by the site) then you send your text which you commented to the NPC bot to the web site via an LSL httprequest post and get a request back which you then parse and call the NPC say command with the result. Though it's functional the drawback is you need a prim for each bot with a listening script in it. Don't like that too much to be honest.

The way Radegast does it is much cleaner: the radegast bot itself listens and then calls the AIMLbot code which is on sourceforge. Problem is: it's *seriously* complicated. I was looking for something which would be basically *call this* *send this back*. Unfortunately I couldn't find anything like that on the first hack attempt. Basically my head exploded. So the interrim step is to get Ken's LSL client code working with the aurora bots for now kind of as a proof of concept. Then I'll try to dig deeper into radegast or else ask Khalifa. I believe I've seen his sig on the aurora-dev channel so who knows, he might answer enough to be able to push it ahead.

Unanswered questions: if I were to implement some kind of mash-up whereby I get the radegast listen code to work but instead of being able to implement an AIML parse, I instead server-side code up some httpRequests and Responses, far as I know they are synchronous calls. So if I send an HTTP POST request up to a website, will the region code just hang there until the response comes back? That would be kind of ugly. There ought to be an asynchronous call. But unfortunately my .net coding skillz aren't up to speed on that kind of thing so it might not be the best. In an ideal world, the AIMLBot guy would explain how to parse the AIML so I didn't need to futz around with httprequest etc and could just use AIML directly. On the other hand, I could do a metric ton of reading about how AIML works and just code something up myself....

Anyways. Onwards....

Back on the case

So got the code compiled, a dev environment set up.
Test scenario worked: I can create bots etc. Now to hack the code.

First thing I'm going to do is see if I can't hack Ken's AIML client side code into the bot API...