OK, first let''s start with some basics.
The code underneath is not compilable, I didn''t try it, I didn''t compile it, it''s just pseudo-code.
The reasons for this are :
1. I don''t have a compiler handy right now.
2. I don''t know you, but *I* am a coder. And I find it easier to read a well explained pseudo-code and do it myself than try to figure out what the heck another programmer was trying to do. It teaches more, I am prouder because I can say that "I did it myself". And if it doesn''t work, I''ll be able to say it''s because you didn''t implement it correctly
![](wink.gif)
Another thing, to avoid putting it everywhere throughout the text : This is Awfully basic, maybe not very well thought, but that''s the whole point... take this, tweak it, expand it, and when you get there, look back to where you started and be proud of yourself
![](smile.gif)
So here it is.
First some basic ides about the field we will be playing in :
The world is grid based. Each cell of land can contain a rock, a food unit, or an ant.
Food is moveable, ants move around the place, rocks just sit.
Every object takes one cell, no more, no less. This means you can code all this in text mode, in VGA, etc.
Now, the ant class, this is our actor in this program. First we have to think about it !
Our ants can :
move around freely, avoid rocks.
look for food, carry it around, take it, drop it.
We create some basic stats for the ants :
.position : an (x,y) coordinate in our world.
speed : an (x,y) vector that serve to move around, and thus to indicate which way we are facing.
for (0,1) we would be facing S (yes, we work with screen coordinates, where x goes from left to right, y goes from top to bottom).
.carrying : a boolean indicating if we have a food unit on our back.
.state : indicate the current "state" of the ant.
This creates some questions we have to answer.
How do we deal with movement, do the ants move straight, randomly, go towards the nearest food, etc.
As well, when do we decide to take food, or drop it ?
I want my ants to walk somewhat randomly, but with some sort of straight lines.
So here is the idea, our ants will have three basic states: WALKiNG, SEARCHING, HARVESTING
As well, they will have a think() function, that will execute only when said so.
So we add another member variable to our ant class :
.think_delay : this is the number of turns until the think function executes by itself. Decreases by one every turn.
When in default mode (WALKING), the ant walks straight, until it bounces into something, in which case it goes into a SEARCHING state, and executes the think() routine. Otherwise, it goes on until the think_delay reaches 0, at which point it executes the think() routine as well.
The think_delay is set to a random number (this will be the length of a straight line) and we turn by a random amount, before returning.
When in SEARCHING mode, we want to see if there is something edible nearby, if not we look if there is a rock ahead, rotate to avoid it, and go back to WALkING mode. If there is some food ahead, we go in HARVEStING mode (yes! harvesters ants)
In HARVESTING mode, we test if we can take or drop food :
if we have food, we test to see if we drop it. If not carrying, we test to see if we take it.
To decide whether to take food or not, we use a simple formula :
pT = 1 - n/8
Where pT is the probability to take the food unit (0 -> 1)
Where n is the number of food units on the 8 nearby cells.
Note that the probability is 1 for a lonely food cell.
To decide whether to drop food or not, it''s the complementary formula ...
pD = n/8
Where pD is the probability to drop the carried food.
When we have decided, we do a 180° turn (to avoid redo test the next turn ...) and go back to WALKING mode.
OK, I think it''s pretty much enough to get started. But to help you a bit, here is the pseudo code, C++ style.
//!!!THiS IS NOT C++ ... This WONT compile!!!//
struct Position
{
float x;
float y;
}
//a basic type for later
enum State
{
WALKING, SEARCHING, HARVESTiNG
}
//ants are NEVER idling around
![](wink.gif)
class Ant
{
private :
Position pos; //position
Position dir;
//direction (since we use floats, you could use non-integer values,
//say Sin and Cos, and do some more realistic lines than one of 8 directions)
boolean carrying;
State state;
int think_delay;
public :
update(); // executed every turn.
int think(); //the core of the AI
![](smile.gif)
rotate(); //make the ant turn around
move(); //guess !
int smellfood();
//it tells how many food units are around a given position
//by default, the ant position, but you might want to change that to the food unit in front of the ant.
//as well, you might want to use a wider area than the 8 nearby cells ?
//NB : actually, we might use a percentage, "how many percents of the area around this point is food ?"
}
Ant::update()
{
if ( world[pos.x+dir.x,pos.y+dir.y] != GROUND ) //there is something in front of us
{
think_delay = 0;
state = SEARCHING;
}
else if (state==WALKING) move(); //continue walking
think_delay--; //decrease think_delay
if (think_delay <= 0) think_delay=think(); //is it time to use our neurons ?
![](smile.gif)
}
int Ant::think()
{
switch state
{
case WALKING :
//we just modify heading and next think_delay.
//eventually, randomly switch to SEARCHING mode. If so, set think_delay to 0, we will think next frame.
//otherwise
//take a random new direction
//take a random new think_delay.
break;
case SEARCHING :
//we have stopped and switched to "hungry mode"
//is there something in front of us.
if ( world[pos.x+dir.x,pos.y+dir.y] == ROCK ) //a rock, avoid it
{
//set the state to WALKiNG
//rotate to avoid it
//set a random think_delay
}
else if ( world[pos.x+dir.x,pos.y+dir.y] == FOOD ) //haydeeho !!!
{
//Set state to HARVESTING
//set think_delay to 0
}
else
//try to find the nearest food unit
//rotate to face it
//set the think_delay to distance + 1 (so we don''t turn just before we bump into the food)
//set the state to WALKING (maybe there would be the need for a new state ? TRACKING ? ...)
break;
case HARVESTING :
//we are dealing with some food in front of use now.
if (carrying==TRUE) //we have already some food.
{
if ( random(1.0) < pD ) //we decide to drop our own food next to the existing food units
{
//drop food. set carrying to FALSE
//set state to WALKING
//rotate 180° to avoid bump into oter food or the one we just dropped ...
//set the think_delay to a random value
}
}
else if (carrying==FALSE) //Huuuuungeeeeeer !
{
if ( random(1.0) < pT ) //we decide to take the lonely food unit
{
//set carrying to TRUE
//set state to WAlKING
//rotate 180°
//set the think_delay to a random number
}
}
break;
default :
//errr ... what the heck would the program be doing here ?
![](smile.gif)
break;
}
} //end the Ant::think() definition.
Well ... that''s pretty much all you need to go out and play.
So try it out, tell me what you think.
Post your comments, your improvements (there is more than enough room for this
![](wink.gif)
), your questions.
Maybe I could write an article, if there is the demand for it, I''ll be happy to help (in which case I''ll have to write compilable source code ... ).
What do you think ?
youpla :-P
(I could make shorter posts ... but that wouldn''t be ahw anymore)
-----------------------------Sancte Isidore ora pro nobis !