Frams Bots - A Game for Framsticks GUI and Framsticks Theater 

Introduction

Framsbots was developed by Bartosz Szopka during Bio-inspired Computing and Systems course at Poznan University of Technology. The aim of this project was to create simple game as a .show script for the Framsticks Theater.

frambots_robots.png

Do you remember the classic Robots game? It the one where you are trying to escape from dozens of hostile robots. Robots are so concentrated on chasing you, that they don't see each other, so all you need is make them hit each other. Originally it was a console turn game, but Framsticks environment gives us opportunity to put idea of Robots game into real-time!

How to install

The whole game is built in three script files: framsbots.expdef (experiment definition), framsbots-levels.inc (game levels), and framsbots.show (theater show) - see the /scripts subdirectory in your Theater installation directory.

The whole game functionality is contained in framsbots.expdef and framsbots-levels.inc files, so you can also run it in Framsticks GUI application. You don't need a registered version, but playing is more joyful when using registered OpenGL graphics.

How to play

To start the game in Theater right-click on the window and choose Current show/Framsbots from the context menu. To start the game in Framsticks GUI choose Simulation/Parameters from the menu and in Experiment page of Parameters window change experiment definition to Framsbots. Click Apply and then Initialize experiment.

You will see standard square framsticks world with bunch of creatures around. See the one in the middle? This one is yours. You need to save it, because every other creature is trying to get it and eat it.

framsbots.png

At the beginning of each game level all the creatures are staying still. They are waiting for your move. To make your creature walking you need to tell it where to go. To do this just left-click somewhere around the world (or use double right-click) and your creature will go there. Remember that it's just a creature. It has its own brain and muscles so it doesn't always walk fast and directly to the destination point.

When your creature will start to move, so will hostile creatures. You need to avoid them. Watch how they walk towards your creature and move it trying to make your enemies hit each other. They loose lots of energy when they collide, so they'll soon die. There are to collision modes in a game: freeze and kill. In freeze mode dead enemies don't disappear from the world. Their bodies remain, so you can still use them to make living enemies hit them. In kill mode enemy creatures die and disappear.

Don't be afraid if there is only one living enemy left and there is nothing it can hit. The last living enemy is loosing energy when it chase you, so all you need is run away until it die.

When all enemies are gone you will move to the next game level. Every level defines its own world size, world band (teleport is really useful, so use it if you can), number of enemies, type of enemy creature and type of your creature.

Sometimes an apple will appear in the world. Don't be afraid, it's not poisoned :) When eating you gain energy and lives! You're enemies are carnivorous, so they don't eat apples ;)

As clicking is used to give direction to player's creature you can't turn or view the world as it is in other shows. To rotate the view during the game, use Shift+mouse drag. Mouse wheel zooms.

These are the rules. You can find out more by playing, so have fun :)

Inside the game

Framsticks environment is very powerful simulation tool, but implementing playable and joyful game for it is not as simple task as it seems to be. In this section more technical detail of implementation will be described.

Clicking:

When using onMouseClick() you have to remember that default mouse functions will be overridden. To use default mouse handling, onMouseClick() has to return 0 value. It is used in framsbots.expdef when Shift is pressed.

Creatures movement:

Framsticks' creatures have their own muscles and brains and their movement depend on them. It's not easy to make a creature go where we want. Smell neurons give an ability to navigate towards food or other creature, but it's not perfect. And what is more we want our creature not only to chase other creature. To make a game it's useful to make a creature walk towards clicked point.

Solution used in Framsbots game is quite simple but we need some assumptions: we have a creature that walks (if it is not interrupted it should walk as straight as possible) and we now how to change its direction (for example it has a bend muscle that simply turns the creature).

Let's look at the picture.

frambots_azimuth.png

We have a walking creature (the green one) and a point we want it to reach (an apple). The creature is walking straight and we can see that it wont get the apple if it walks like that. But we can compute the angle of a turn and tell the creature to turn. The angle can be easily computed as an angle between two vectors: walk vector and target vector. Walk vector (red one) is a vector of current creature's movement, and the target vector (green one) is a vector between creatures position and target point.

There is no problem to compute target vector as we can easily get coordinates of creatures position and clicked point, but what to do with walk vector?

Creature in Framsticks environment doesn't store information about it's rotation. We don't know where is the "head" of a creature and where is it's "back". We know that creature is walking straight (or nearly straight), so if we could know where the creature was some time ago, we'll be able to compute the vector between past position and current position.

So probably now you know what are those strange-looking red dots left by a creature. These are its previous positions. We can store them in creatures memory (in a game we use user3 field for it) and use them to compute walk vector.

If we finally have those two vectors computing angle between them is just simple arithmetic. Scalar product of vectors is used to compute cosine of the angle and vector product of vectors is used to check the direction of a turn. All we need now is scaling the value and put it into bending muscle.

If you want to check how it is implemented find saveCreaturePosition() and updateCreatureBend() functions in framsbots.expdef.

Defining your own creatures:

Definitions of creatures used in the game are stored in creatures global vector. Each creature definition is an array which fields are:

  1. name (string): simple name of a creature - will be added to creature's name when created
  2. genotype (string): genotype of a creature
  3. index of a bend muscle (integer): index of a bend muscle in creatures brain
  4. weight of distance to target when computing bend signal (float): if 0.0 then distance doesn't affect the bend signal; default is 0.02 that makes a creature turn less strongly when it is away from target.
  5. weight of current bend state when computing new one (float): newly computed bend signal can be averaged with current bend; use it if creature turns are not stable

If you add your creature don't forget to update enemyCreature and playerCreature experiment properties definitions in the last section of .expdef file.

Defining your own levels:

Definitions of levels used in the game are stored in levels global vector in framsbots-levels.inc file. Each level definition is an array which fields are:

  1. name (string): will be displayed in a game
  2. world size (float): size of a world
  3. world band (1 or 2): 1 - fence, 2 - teleport; value 0 is also possible but unlimited world is not useful in a game ;)
  4. world type (0 .. 2): 0 - flat, 1 - blocks, 3 - heights;
  5. world map (string): definition of world map
  6. number of enemies (integer)
  7. enemies collision freeze (0 or 1): 0 - kill mode, 1 - freeze mode
  8. enemy creature (integer): index of enemy creature in creatures definitions vector (-1 for random)
  9. player creature (integer): index of enemy creature in creatures definition vector (-1 for random)

If you add your level don't forget to update level experiment property definition in the last section of .expdef file.