Have you ever experienced one of those moments of clarity when you realize that one of the fundamental assumptions that you had been making is false, and that if you’re going to have to do a lot of work to make up for your mistake?  If so then you can relate to what has been going on with the Web Critters project over the past few weeks.

When I last wrote an update I was on a roll, pushing through the final stages of a level two complex adaptive system (or so I thought) with my generic CAS engine.  I was writing the main generational processing routine, which is a relatively simple loop structure when the problem hit me full in the face.

I had developed all of my interactions to work with ICell objects, however in order to produce an extensible solution I needed to operate using IAgent objects instead.  An agent represents a multicellular construct, while a cell is just that – a single cell with no attachments.  (Confused?  See here.)  While I am no where near allowing multicellular evolution to take place, hardcoding using ICell for now and then trying to refactor to use IAgent later would be nightmarish.

A middle ground

Given that I needed to implement IAgent in the short term, I was forced to figure out a solution that wasn’t too much work now and yet would not slam any doors closed later in the development cycle.  While I considered a handful of options, I finally settled upon the notion of creating an “interaction contact point” on all IAgent objects.  When invoked, the SetInteractionContactPoint method nominates one of the agent’s cells at random and henceforth all interactions on that agent will use the contact point until SetInteractionContactPoint is called again.

This has some potentially interesting implications in practice that I will not be able to assess until multi-agents are a possibility.  In particular, I am intrigued by the fact that multicellular web critters will be able to show different “faces” to competitors in the environment, albeit at random.  A multi-agent could stack the deck in favor of a certain outcome by harboring multiple copies of the same cell, which could prove to be intriguing as well.

But that wasn’t my only problem.

Where do critters live?

I had always anticipated treating ILocation objects in the environment in a similar manner to IAgents in order to facilitate web critters that not only contained multiple ICells, but also entire IAgents.  To achieve this I had IAgent implement the ILocation interface, which basically required a list of resource nodes and agents.  Unfortunately this bombed in practice since an IAgent also needs to implement IInteractable (in order to participate in interactions) and doesn’t need a lot of the other properties that come along with a full blown location object.

To resolve some of the conflicts that arose, I ended up defining a new interface, IBoundry, that looks like this:

public interface IBoundary
   List<IAgent> Agents { get; }
   List<IResourceNode> CurrentResources { get; }

I could then define my locations and agents in a manner that did not conflict:

public interface IAgent : IBoundary, IInteractable
   List<ICell> Cells { get; }
   bool CanReplicate(double reproductionThreshold);
   bool IsEligableForDeath { get; }
   void SetInteractionContactPoint();
   void ProcessReservoir();

public interface ILocation : IBoundary
   int UpkeepCost { get; set; }
   List<ILocation> Connections { get; }
   List<IResourceNode> ResourceAllocation { get; }
   void ConnectTo(ILocation location);
   void RefreshResourcePool();
   void ChargeUpkeep();

The one issue that this refactor did not solve was that the IInteractable interface calls for a property named Reservoir (List<Resource>) to be included while the IBoundary interface  contains a property named CurrentResources (List<ResourceNode>). The two seem redundant at a glance.

To get around this issue I decided that – in the context of an IAgent – the Reservoir would represent the resources that the Agent had accumulated during the current time step (generation), while the CurrentResources property would serve as a longer term storage mechanism.  To enforce this I added a ProcessReservoir method that, at the end of every generation, converts new resources in the reservoir to resource nodes.  Long term, agents that live inside of an agent will use this resource pool as their source of energy, and will not be able to directly access the environment.

In hindsight, John Holland’s ECHO design contains a Boundary class that serves a similar purpose to the one I have designed.  I had hoped that my Location abstraction would remove the need for the boundaries, however I was proven wrong.

Next steps

The main CAS engine is complete and I am ready to start testing.  I will need to invest some time into creating a framework from which I can bootstrap, run, and monitor a simulation so that I can ensure that everything seems to be working.  I should also probably build in some mechanism to serialize the current state of a simulation to disc, and then load a dormant simulation back up.

I’m not sure how long all of this will take, but I’m hoping to have the first test run completed in no more than a month’s time.

Leave a Reply



© 2004-2010 - Systemic Babble is created and maintained by Andrew Anderson. Suffusion WordPress theme by Sayontan Sinha