
A farm is one of the first picks to grow your settlement as it acts the primary source of food-supply for a town—no changes so far, but we lately revisited the old model and replaced it with the above version, which features some nice and detailed touches.

A scholar leads a secluded life at a scholar’s quarter or at a university and devotes himself to teaching and studying and thus helps to raise the enlightenment of an associated settlement. Scholars help to counter the negative effects of nearby graveyards.

One of the key-characteristics of each settlement is its enlightenment, which in turn raises public order and the general happiness of all inhabitants. Enlightenment is “produced” by a either a scholar (see image, to the left) or by an upgraded university (to the right). A scholar is one of the structures which is going to be build at a later stage of the game, as it needs a guildhall as a prerequisite.

A guildmaster presides over workshops and guildhalls and raises the crafts-level of a settlement. He regularly issues temp-jobs and other quests.

Introducing the workshop, industrial hub of almost each settlement. Even though a workshop increases the level of pollution of its city, it is nonetheless indispensable, because an upgraded workshop (called a “guildhall”) acts as a prerequisite for certain other important structures, like the healer. Also, a guildhall is the place where you can pick up temp-jobs.
International research-firm Wiley is currently offering their study “Who plays, how much, and why? Debunking the stereotypical gamer profile” for free, a very interesting read. While nearly every developer in the field of virtual worlds seems to be focussed on entering the teen- and pre-teen market, it is funny to read that the majority of all gamers are more than thirty years old.
By the way, we already assumed a year ago that this is the largest target-group when it comes to games and virtual worlds—it’s always nice to be proven right… ![]()
Let’s take a quick look on how to parse VRML for any of the open-source 3D-engines like Away3D, Papervision or Sandy3D. To be more specific, I am talking about VRML2 (.WRL), which can be exported with any standard 3D-software. Unfortunately, some 3D-packages translate VRML geometry-nodes as IndexedFaceSets only, which is basically just a long list of vertices and not suitable for this method of parsing—an example for such unsuitable encoding is Cinema4D. You will need a 3D-package which encodes appropriate geometry-nodes, like 3DMax.
The actual parsing is no rocket-science—since VRML is a human-readable format, you mainly have to deal with string operations nested inside an array-filter loop. Let’s take a look at typical VRML-grammar first:
#VRML V2.0 utf8
# Produced by 3D Studio MAX VRML97 exporter, Version 9, Revision 1
# MAX File: level.max, Date: Sat Sep 6 8:00:00 2008
DEF myTestBox Transform {
translation 317 100 -57
children [
Transform {
translation 0 11.5 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0.03137 0.2392 0.5412
}
}
geometry Box { size 20 23 20 }
}
] }
]
}
Above you can easily spot all necessary information to parse and recreate the according scene in Actionscript: primitives and their names, coordinates and dimensions. Here is some basic code as a starting-point:
private var container:TransformGroup;
/*for Away3D change TransformGroup to ObjectContainer3D*/
private var vrmlString:String;
/*return-type TransformGroup is for Sandy3D,
for Away3D choose ObjectContainer3D instead*/
private function parseVRML( $vrmlString:String ) : TransformGroup
{
this.vrmlString = $vrmlString;
var nodesInclCamera:Array = vrmlString.split( ‘DEF ‘ );
/* remove VRML-header */
nodesInclCamera.shift();
/*exclude camera-node*/
var nodesExclCamera:Array = nodesInclCamera.filter( filterCamera );
container = new TransformGroup( ‘container’ );
/*Away3D: container = new ObjectContainer3D();*/
/*iterate over all geometry-nodes*/
nodesExclCamera.forEach( processNode );
return container;
};
private function filterCamera( element:*, index:int, arr:Array ):Boolean
{
return ( element.match( ‘Camera’ ) == null );
};
private function processNode( element:*, index:int, arr:Array ) : void
{
var helperArray:Array = element.split( ‘geometry ‘ );
var primitive:String = helperArray[ 1 ].substr( 0, helperArray[ 1 ].indexOf( ‘ ‘ ) );
var properties:Object = new Object();
properties.name = element.substr(0, element.indexOf( ‘ ‘ );
/*parse size*/
var sizeSub:String = element.substr( element.indexOf( ‘size’ )+5, element.length);
var sizeSplit:Array = sizeSub.split( ‘ ‘ );
properties.width = sizeSplit[ 0 ];
properties.height = sizeSplit[ 1 ];
properties.depth = sizeSplit[ 2 ];
/*parse position*/
var transSub:String = element.substr( element.indexOf( ‘translation’ )+12,
element.indexOf( ‘ children’ ) );
var transSplit:Array = transSub.split( ‘ ‘ );
properties.x = transSplit[ 0 ];
properties.y = transSplit[ 1 ];
properties.z = transSplit[ 2 ];
/*parse rotation*/
/*properties are called rotateX, rotateY and rotateZ in Sandy
Away3d: change to rotationX, rotationY and rotationZ*/
if ( element.match( ‘rotation’ ) != null)
{
var rotSub:String = element.substr( element.indexOf( ‘rotation’ )+9,
element.indexOf( ‘ children’ ) );
var rotSplit:Array = rotSub.split( ‘ ‘ );
properties.rotateX= Number( rotSplit[ 0 ] ) * Number( rotSplit[ 3 ] ) * 100;
properties.rotateY= Number( rotSplit[ 1 ] ) * Number( rotSplit[ 3 ] ) * 100;
properties.rotateZ= Number( rotSplit[ 2 ] ) * Number( rotSplit[ 3 ] ) * 100;
}
container.addChild( this[ ‘_create’ + primitive ]( properties ) );
};
/*return-type for Away3D is Cube instead*/
private function _createBox( properties: Object ) : Box
{
var shape:Box = new Box();
/*Away3D: var shape:Cube = new Cube();*/
for( var p:String in properties ) shape[ p ] = properties[ p ];
return shape;
};
The first filter separates the camera-node from the other primitives. You can either delete this node (like in this case), or even use it to create your 3D-camera at this point:
var nodesExclCamera:Array = nodesInclCamera.filter( filterCamera );
private function filterCamera( element:*, index:int, arr:Array ):Boolean
{
return ( element.match( ‘Camera’ ) == null );
};
The second filter iterates over all geometry-nodes. Here you can add code to build the actual 3D. This example calls a dynamic function depending on the type of geometry-node (like Box, Sphere and so on)—of course this works only with the types of primitives supported by your 3D-engine of choice. Also keep in mind that the different engines have different names for their primitives; a cubic shape’s Class is called “Cube” in Away3D and “Box” in Sandy3D. Generally, Sandy3D is very conforming to VRML-grammar (good work, guys):
container.addChild( this[ ‘_create’ + primitive ]( properties ) );
The function call passes an object which stores all according values. The function then returns the appropriate primitive:
/*return-type for Away3D is Cube instead*/
private function _createBox( properties: Object ) : Box
{
var shape:Box = new Box();
/*Away3D: var shape:Cube = new Cube();*/
for( var p:String in properties ) shape[ p ] = properties[ p ];
return shape;
};
That’s the general technique. I am not going to cover the rest here, like applying textures and so on. VRML stores texturing- and shading-information in Appearance- and Material-nodes, which can be parsed in a similar fashion, I think you get the point—happy coding…

Healers resides at a (big surprise) healer’s home or at a hospital. Their main duty is to raise the level of medical supply for the according settlement, but they will occasionally ask adventurers to accomplish quests (like fetching medicinal herbs).