Saturday, August 23, 2008

Adventures in F# - A Plant for Terrarium 2

Recently, my beloved Terrarium-game has reappeared from the neatherworlds of software. As some of you may know, Terrarium's intend was to showcase the back then rather new and exciting .NET platform version 1.x (not that it is not still exciting). Although from a gamer's perspective, the graphics weren't all to great, from a technology standpoint, it featured great things, such as Webservices, Reflection, etc.

At some point Terrarium ceased to exist, which was a shame, since the community was quite active developing plants, herbivores and carnivores for the virtual ecosystem that Terrarium simulates. I for myself, developed some simple creatures too (a simple decision-based/state-based agent), as part of a project I did during university for my AI course. More advanced (in comparison to my creature) could be imported showcasing great AI stuff such as A*, neural networks, planning, etc.

However, in an community effort, Terrarium was relaunched lately on codeplex and will hopefully see great new additions, such as a port to a more current version of the .NET platform and DirectX.

In a small attempt I tried to put my superficial F#  skills to work, and decided to port a plant organism to F#. My attempt can be seen in the following lines of code. For a C# version, see the codeplex discussion here. I decided to leave the comments from the discussion as is.

namespace CBPlant

We open a namespace for the plant organism


#light
#r "E:\\Path to OrganismBase.dll\\OrganismBase.dll"

We set the environment to lightweight and reference the OrganismBase.dll, which contains all the Terrarium2 stuff.


open System;;
open System.Drawing;;
open System.Collections;;
open System.IO;;
open OrganismBase;;


We open some namespaces, which we are going to use later and dive right into the code.

// Sample Herbivore

//Strategy

//This animal moves until it finds a food source and

//then stays there

// The following Assembly attributes must be applied to each

//Organism Assembly
[<assembly: OrganismClass("CBPlant.CBPlant")>] // The class that derives from Animal
[<assembly: AuthorInformation("XYZ", "x@y.z")>] // Provide Author Information
do()

Assembly-level attributes have to be declared via a global do() statement. See the discussion here.

//3.2 Plants 
//The definition of a plant is relatively easy since plants do not have to have any sort of movement defined to allow them to locate sources of food. 
//Each plant has three basic functions: 
//1. Grow 
//2. Reproduce by spreading seeds 
//3. Be eaten by herbivores 
//A plant organism does not need to contain any methods, it just has three properties that define how a plant functions. 
//4 
//1. The “MaximumEnergyPoints” property allows the developer to state how many energy points a herbivore will gain by consuming this plant. The maximum allowed is 10. 
//2. The “MatureSize” property which must be a number between 24 and 48 states the maximum size a plant can grow to when it has survived for some amount of time without being consumed. The smaller a plant is, the faster it will be able to reproduce. As a plant gets larger it will become easier for herbivores to see and will more likely be consumed. 
//3. The “SeedSpreadDistanceAttribute” states the maximum distance a plant can spread seeds from its current location. The maximum allowed is 100. These three properties alone are enough to define a functioning plant for the Terrarium game. 
// This value must be between 26 and 48, 26 means faster reproduction 
// while 48 would give more defense and attack power 
// Make it smaller for reproduction*) 
[<MatureSize(26)&gt;] 
[<SeedSpreadDistance(100)>

// Point Based Attributes 
// You get 100 points to distribute among these attributes to define 
// what your organism can do.Choose them based on the strategy your organism 
// will use. This organism hides and has good eyesight to find plants
[<MaximumEnergyPoints(10)>] 

type CBPlant () = 
  inherit Plant ()
  override cb.SerializePlant (m:MemoryStream) = ()
  override cb.DeserializePlant (m:MemoryStream) = ()
;;

We define a new plant type, called CBPlant (full CBPlant.CBPlant). This type is a subclass of the abstract class Plant. We have to implement Plant's two abstract members, which according to the example is just an empty method body. If we compile this by invoking

fsc OrganismBase.dll CBPlant.fs -a

A new library will be created, containing just this simple type.

Hopefully, I will get to play some more with F# and Terrarium doing some other stuff, like porting the Herbivore, Carnivore and start to add some real behaviour. 

No comments: