Last time we said that it is not enough to create one model of the world with which the brain will interact. To test the behavior of the brain in various situations it is necessary to have on hand a variety of such models. And for this you need two things: the first is the ability to easily and quickly create models, and the second is the ability to reuse the created models, changing their configuration.
Looking at these requirements, I have the following thoughts:
- modularity, loadable libraries with extensions;
- configuration via XML;
- model representation in the form of a tree of objects;
Also, when creating the models themselves, I would like to write as little code as possible, because the
laziness model will need more than one and not two. Here we need to remember that the brain, when interacting with the environment, receives information from it, transforms it and returns the result. The environment, in turn, receives this information, transforms it again and returns the result to the brain. This is the whole point - the information goes in a circle.
Technically, only information conversions could be modeled. No labyrinths, no food, whistles and bells. There is only one object - the World, which plays ping-pong bytes with the brain. I would love to look at this process, but I would not wish the enemy to create such a model.
')
Object-world is a bad metaphor that does not fit into any brain. When we look at the world, we do not see information - we see objects that have certain properties. Therefore, I would like to work with the metaphors of objects and their properties when modeling the world. The problem is that for this you will need to write additional code, which, as it turned out, it is not necessary to write at all, and in general is too lazy.
Therefore, a compromise was found. In the code you need to describe only the transformation of information, and objects with properties will be created declaratively.
Tutorial ["Part 1"]
This is a couple of words about why I did what I did, end and you can proceed to practice. Last time, some ideas were demonstrated on what the process of modeling the world might look like. Today it will be a tutorial that will guide you through this process from the very beginning to the end.
To work, we need the .NET Framework 3.5, the development environment for it, and the latest version of Alan.Platform
source code . To begin with, we will create a solution with one class library (.dll), copy the Platform.Core project from Alan.Platform into it and add a link to it to our class library. This library will contain various elements on the basis of which then the world will be constructed.
As is customary in tutorials, the created model will be fairly simple, but no more than is required. In our case it will be a board divided into cells. Objects will be located on the cells of the board, so their coordinates can be determined by two numbers.
Let's start by marking our newly created library with the ElementsLib attribute, so that the Platform.Constructor can use the elements defined in it:
[assembly: Platform.Core.Concrete.ElementsLibAttribute]
The most suitable place for this is the AssemblyInfo.cs file. Next, add a new CellBoard class to the library that will represent our checkered board. Let it be a board for the game of checkers. Then only one type of object can be placed on it - a checker, which has two properties: X and Y. Thus, our CellBoard class takes the following form:
using System;
using Platform.Core.Elements;
using Platform.Core.Concrete;
namespace Checkers
{
[PropertySet( "Checker" , "X" , "Y" )]
public class CellBoard : Layout
{
public override bool ValidatePropertySet(PropertySet ps)
{
throw new NotImplementedException();
}
}
}
What have we just done? The brain has several channels through which it receives information of a different type. Therefore, it is logical to manage information of one type using a separate object. This object is the operator. Layout is a class derived from an operator that is designed to manage information of a special type — information about the location of objects.
Location information is special because it has the potential to affect other types of information. For example, if you bring a fragrant bun to us, then its smell will become stronger.
Let's go back to our CellBoard. The PropertySet attribute, as you might guess, declares the names of the object type and its properties. There may be several such attributes, and they all indicate with what types of objects and their properties the operator can work.
ValidatePropertySet we will not need, so leave it as is. Although the class implementation is not yet available, we can try to construct something based on it. To do this, you need to add to our solution the Platform.Constructor project from Alan.Platform, a new console project and add a link to the designer to the console project.
Platform.Constructor helps to create a ready-made model of the world from a variety of elements. It is very simple to use a constructor - it is enough to describe the desired end result in XML. What we now do.
The XML schema is pretty simple. If you want to see hints for tags and attributes, you can connect it to your favorite editor. You can find the scheme in
Alan Platform \ Platform.Constructor \ config.xsd.
This is how the description of a 2x2 board looks like, in the corners of which there is a checker:
<? xml version ="1.0" ? >
< component xmlns ="http://alan.codeplex.com/constructor/world" >
< operator name ="Checkers.CellBoard" />
< component >
< propertySet name ="Checker" operator ="Checkers.CellBoard" >
< property name ="X" value ="0" />
< property name ="Y" value ="0" />
</ propertySet >
</ component >
< component >
< propertySet name ="Checker" operator ="Checkers.CellBoard" >
< property name ="X" value ="1" />
< property name ="Y" value ="1" />
</ propertySet >
</ component >
</ component >
Here we see our newly created operator and two components (checkers) for which we did not write code at all. If someone still does not fully understand the idea of ​​a PropertySet, then imagine that this is a projection of an object onto an operator. That is, each object (component) consists of several sets of properties, one per operator (type of information).
You can not pay attention so far that all this is enclosed in another root component. Yes, theoretically, the components can be infinitely nested in each other, but it is not entirely clear how this can be used.
So, if you pass this XML document to the constructor, it will return the same root component, which, in theory, is our board with checkers. To check this, we use ObjectDumper. Add it to our console project, and also do not forget to add a link to our library of elements, as the designer expects to find it in the same folder as itself.
The Main function should look something like this:
using System;
using System.Xml.Linq;
namespace Tutorial
{
class Program
{
public static void Main( string [] args)
{
var constructor = new Platform.Constructor.Constructor();
constructor.CollectElementsIndex();
// XML, .
var config = XDocument .Load(args[0]);
// .
var rootComponent = constructor.Construct(config);
ObjectDumper.Write(rootComponent, 2);
Console .Write( "Press any key to continue . . . " );
Console .ReadKey( true );
}
}
}
All that remains is to pass the address of our XML document to Main. To do this, set the Copy to output property for it - PreserveNewest. And in the properties of the console project, specify the command line arguments - config.xml.
This is what should end up:

Container - reference to the parent component. The root component is null.
Components - a set of child components.
Clients - a special type of components, which later.
Operators - a set of child statements.
Layout is one of the operators.
Properties - information about the properties of the component. The root component has no properties.
Id is a unique identifier. At the root component, it is always 0, and for its children it is 1, 2, 3, etc.
In general, the tree structure corresponds to the one that was in XML. Is that the properties of the components are not divided into sets of properties, since here it is not necessary. Components in this model are present only in order to make users familiar with seeing objects with properties.
In fact, the brain will not interact with the components, either directly or even indirectly. It will interact with the operators in which this property data is stored. And those that are in the components become irrelevant almost immediately. To update them, you will have to manually call UpdateProperties ().
This is where the first part of the tutorial ends. His main goal was to show how the work with Alan.Platform looks like. The archive with the result can be downloaded
here . In the next part, we will try to create a graphical representation of our checkers using Platform.Explorer.
PS The Main function has the following line “constructor.CollectElementsIndex ();”, which, as you might guess, indexes the elements. Here is how it works:
1. Creates an AppDomain to temporarily load libraries into it.
2. It loads into the created AppDomain all * .dll files that are in the same folder as the constructor (or rather, AppDomain.Current.BaseDirectory).
3. It eliminates libraries in which there is no ElementsLib attribute.
4. In the remaining libraries, it finds types that correspond to the elements of the world model tree.
5. Fills the index with necessary information about these elements.
6. Unloads the AppDomain with libraries.
Further, the created index can be used to create a tree of elements based on XML, if necessary, loading the libraries in which these elements are defined. This is what the index looks like:
Those wishing to participate in the project or use it to create something, please contact the LAN or knock on the jabber:
openminded@xdsl.byThe second part of