CritterWorld is a simulation of the habitat of a group of small cybernetic creatures, called Critters. They run around in mazes, eat food to gain energy and lose energy when they move, and sometimes they fight with each other.
What makes them interesting is that you have to program their “brains” to determine how they behave. See image.
Last year, Critters were given the goal of having to surviving as long as possible whilst fighting with each other over a limited resource (food). That turned out not to be as exciting as it sounds, so this year we‟ve added a twist: Critters now must compete in a race to be the first to reach a designated area of the map, shown by a green circle. (See the picture above.) The Critter with the fastest average time into the circle is the winner. Of course, they still need food and can still fight with each other on the way to the finish line.
Our plan is to run a fun competition in the final week of classes to let you pit your Critter brains against each other. Sorry, there will be no prizes or awards; only the unending admiration of your colleagues should you win!
Whilst this might seem like a somewhat trivial game, such simulations have a long and respected history. A similar idea first appeared in the late 1970‟s on the Apple II as “Robot Wars,” coded by the famous game developer Silas Warner, who also wrote the original, 2D, view-from-above version of “Castle Wolfenstein.”1 Since the original, the idea has been resurrected numerous times and is now considered a classic – though perhaps somewhat under-recognised and under- appreciated – subgenre of computer gaming.
It also has serious aspects: Similar simulations were the motivation for the first implementation of object oriented programming in the late 1960s, and are closely related to current research into artificial intelligence and multi-agent systems. The latest version of CritterWorld is available on Course Resources. Your job is to:
These two tasks are detailed below:
You must (re-)create a Configuration class to maintain the configuration options for CritterWorld. It used to exist, but Dave accidently deleted it. You‟ll see comments in the source code where the references to it used to be. Dave replaced the references to the Configuration class with explicit literals, as he hastily tried to cover up evidence of his abject idiocy by fixing the program so it would still run.
You must also write the code to edit, save, and load the configuration options. You may write any other classes you need to complete this task. You should create a modal form to allow the CritterWorld user to edit the configuration properties. The file format you use to store the configuration options is up to you.
Once you‟ve created the Configuration class, you‟ll need to determine a reasonable range of values for each property in the Configuration class, and include appropriate code to make sure that each property cannot go outside its reasonable range of values.
Despite being unable to recall even what he had for breakfast, through some lesser miracle of cognitive retrieval, Dave managed to remember one of the property definitions from the Configuration class and it is included here as an example: See image.
See how RefreshRate cannot go lower than 5 or above 60? You should do something similar for all properties that need to be constrained to a reasonable range. You need to search through the source code for CritterWorld to find all of the commented out references to Utilily.GetConfiguration() to find all of the configuration options that need to be edited. This will tell you the Properties you need to provide in the Configuration class. For example, for the refresh rate, you will see the following code: See image.
Once you have implemented your Configuration class correctly, you can uncomment the line above and remove the line that sets framesPerSecond to 12. Note that you will also need to uncomment the following lines in Utility.cs:
// static Configuration configuration = null;
And: See image.
This just creates a new instance of a configuration class if one does not already exist. Finally, you need to add code to the method editConfigurationToolStripMenuItem_Click in CritterWorldForm.cs to call the configuration edit dialog and update the contents of the Configuration class with the changes.
The CritterWorld executable (provided to you) contains all of the logic required to handle the bodies of Critters. However, in order to run, Critters also need brains. CritterWorld dynamically loads the brains for Critters from dynamic link libraries2 (class libraries) at run-time and creates a Critter for each brain that it loads.
You must write a brain for a Critter. The specifications of the classes you need to provide are provided in the Appendix below. More information will be given in the lecture on 28th March. The aim is for your Critter to reach the specified destination as quickly as possible. At a minimum, the Critter controlled by the brain written by you should be able to do the following:
The behaviour exhibited by the Critter control is completely up to you. I am looking for imagination and some thought to be applied to how your Critter behaves.
You have been provided with a Visual Studio solution that contains much of the code for CritterWorld. You must use this solution as your starting point. It has been set up with all of the references that you code will need and contains the executable and other dynamic link libraries you need in order to do this assignment.
Read this assignment specification carefully! It contains all of the information you need. Although the CritterWorld environment will include programming concepts you have not seen before (such as multi-threading), you have covered everything you need to complete this assignment in this module.
Like so many software projects, CritterWorld is a work in progress. The authors will release one or more updates to CritterWorld any time from now until up to a week before the hand-in date in order to fix bugs and/or add enhancements. You may have to alter your code to adapt to changes in the CritterWorld code.
Developing code in the face of changing infrastructure and requirements is a fundamental and inescapable reality of the software business. It is something we will explore further in next year‟s Team Software Development module or Applied Game Development.
When you run CritterWorld, to start the Critters, select World->Start World from the main menu. All of the Critters that have brains will be created. As you will see, five demonstration Critters have been supplied for your Critter to interact with. Food will also be displayed in the world for your Critter to eat. Food gives your Critter energy. When your Critter moves or interacts with other creatures, it loses energy. When a Critter eats a piece of food, the food will disappear and a new food source will be created somewhere else in the world. Food sources decay after a certain time period and new pieces of food will appear (unless configured not to) in random locations to replace them.
To test your critter(s) ability to locate the objective, select World->Start Campaign. Then you can use the appropriate calls on the ICritter interface to find the destination your critter needs to reach.
If the energy of your Critter goes below zero, your Critter will die.
If you are having problems, select Settings->Display Log Window to open a window that displays diagnostic messages that might be helpful.
You have been provided with a Visual Studio 2010 solution called CritterWorld. This is the entirety of CritterWorld. The solution, as provided, will build and execute so you can see the actions of five demonstration Critters.
When CritterWorld is executed, it looks for dynamic link library files (DLLs) in the same folder as itself. In each DLL found, CritterWorld looks for a class that implements the interface ICritterFactory. If a class that implements ICritterFactory is found, a new instance of that class is created. The DLL must also contain at least one class that implements the ICritterBrain interface. You need to write the classes that implement ICritterFactory and ICritterBrain.
The following is a definition of ICritterFactory: See image.
It consists of one method, CreateCritterBrains, which returns an array of objects that implement the interface ICritterBrain. In most cases, the array will only contain one element, but the design allows for a DLL to contain more than one brain (this is done in DemoCritter.dll).
ICritterBrain is defined as follows: See image.
The properties that you need to implement are as follows:
The methods that you need to implement are as follows. All methods need to exist, but it is acceptable for any of them to be empty:
The Body property in your class will be set to reference an object that implements ICritter. This provides the following properties and methods that you can use. See image.
The properties implemented by ICritter are:
The methods implemented by ICritter are:
Many of the Notify methods provide a reference to an object that implements IWorldObject or IOtherCritter. These provide two additional properties if you wish to use them (IOtherCritter inherits from IWorldObject): See image.
These provide the X and Y co-ordinates of the other object.
These are some additional comments that might be useful when you are deciding on the behaviour of your Critter and might help you with the assignment: