case ANT_SEARCH_FOOD: // hungry and searching for food
{
// in this state the ant is looking for food based on its memory
// if the memory is blank then random walks
// if the ant gets to a location and cant find any food where its
// memory found some then the memory for that food location is degraded by 1
// searching takes 2 units of energy per cycle
#if 0
ants[index].varsI[ANT_INDEX_AI_STATE] = ANT_SEARCH_FOOD;
// start off by scanning for food
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S1_SCAN;
// initialize targets tp 0
ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] = 0;
ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] = 0;
#endif
// test substate
switch(ants[index].varsI[ANT_INDEX_AI_SUBSTATE])
{
case ANT_SEARCH_FOOD_S1_SCAN:
{
// this state is transient and doesn''t persist, so
// no energy expended by it
// scan for a "hot" cell
float max_energy = 0;
int cell_x = 0, cell_y = 0;
for (int index_x = 0; index_x < 16; index_x++)
for (int index_y = 0; index_y < 16; index_y++)
// does this cell have more food?
if (ants_mem[index].cell[index_x][index_y] > max_energy)
{
// update new max
max_energy = ants_mem[index].cell[index_x][index_y];
cell_x = index_x; cell_y = index_y;
} // end if
// test max and see if we have a winner?
if (max_energy > 0)
{
// vector to this cell
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S3_VECTOR_2CELL;
// send to cell center
ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] = 30*cell_x+15;
ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] = 30*cell_y+15;
// set counters to 0
ants[index].counter_1 = ants[index].counter_2 = 0;
} // end if
else
{
// go into wander mode, no knowledge of food
// vector to this cell
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S2_WANDER;
// set counters
ants[index].counter_1 = RAND_RANGE(100,150);
ants[index].counter_2 = 0;
} // end else
} break;
case ANT_SEARCH_FOOD_S2_WANDER:
{
// wander and look for food, when done wandering go back and scan
// burn food
ants[index].varsI[ANT_INDEX_HUNGER_LEVEL]+=1;
// move the ant
ants[index].x+=ant_movements_x[ants[index].varsI[ANT_INDEX_DIRECTION]];
ants[index].y+=ant_movements_y[ants[index].varsI[ANT_INDEX_DIRECTION]];
// test if ant is done with direction and needs a new one
if (--ants[index].counter_2 < 0)
{
// set direction
ants[index].varsI[ANT_INDEX_DIRECTION] = RAND_RANGE(ANT_ANIM_UP, ANT_ANIM_LEFT);
// time in this new direction
ants[index].counter_2 = RAND_RANGE(10, 100);
// start animation
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if new direction
// update memory with presence of food
int ant_cell_x = ants[index].x / 30;
int ant_cell_y = ants[index].y / 30;
// this updates the i,jth memory cell in ant with info about food
float food_near_ant = Food_Near_Ant(ant_cell_x, ant_cell_y);
ants_mem[index].cell[ant_cell_x][ant_cell_y] =
ANT_MEMORY_RESIDUAL_RATE*ants_mem[index].cell[ant_cell_x][ant_cell_y] +
(1-ANT_MEMORY_RESIDUAL_RATE)*food_near_ant;
// test if we just bumped into some food
if (food_near_ant > 0)
{
// find highest source of food
int food_x = -1;
int food_y = -1;
// find the highest food source in cell
int food_id = Max_Food_In_Cell(ant_cell_x, ant_cell_y, &food_x, &food_y);
// pre-empt into vector 2 food
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] =
ANT_SEARCH_FOOD_S4_VECTOR_2FOOD;
// send to exact position
ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] = food_x;
ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] = food_y;
// set target id of food
ants[index].varsI[ANT_INDEX_FOOD_TARGET_ID] = food_id;
// set counters to 0
ants[index].counter_1 = ants[index].counter_2 = 0;
} // end if
// test if we are done with this state and need to go back to scan
else
if (--ants[index].counter_1 < 0)
{
// go back to scan state
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S1_SCAN;
} // end if
} break;
case ANT_SEARCH_FOOD_S3_VECTOR_2CELL:
{
// this substate vectors the ant to the center of the cell, once
// there the ant "looks" to see if there actually is any food, if so
// vectors to it, else goes back and scans
// burn food
ants[index].varsI[ANT_INDEX_HUNGER_LEVEL]+=2;
// pick direction
int dx = ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] - ants[index].x;
int dy = ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] - ants[index].y;
// pick maxium delta to move in
if (abs(dx) >= abs(dy))
{
// x dominate
if (dx > 0)
{
// move right
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_RIGHT)
{
// start animation right
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_RIGHT;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].x+=ant_movements_x[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end if
else
if (dx < 0)
{
// move left
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_LEFT)
{
// start animation left
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_LEFT;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].x+=ant_movements_x[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end else
} // end if x
else
{
// y dominate
if (dy > 0)
{
// move down
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_DOWN)
{
// start animation down
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_DOWN;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].y+=ant_movements_y[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end if
else
if (dy < 0)
{
// move up
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_UP)
{
// start animation down
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_UP;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].y+=ant_movements_y[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end else
} // end else
// update memory image ????
// update memory with presence of food
int ant_cell_x = ants[index].x / 30;
int ant_cell_y = ants[index].y / 30;
// this updates the i,jth memory cell in ant with info about food
float food_near_ant = Food_Near_Ant(ant_cell_x, ant_cell_y);
ants_mem[index].cell[ant_cell_x][ant_cell_y] =
ANT_MEMORY_RESIDUAL_RATE*ants_mem[index].cell[ant_cell_x][ant_cell_y] +
(1-ANT_MEMORY_RESIDUAL_RATE)*food_near_ant;
// now test if target reached
if (abs(ants[index].x - ants[index].varsI[ANT_INDEX_FOOD_TARGET_X]) < 4 &&
abs(ants[index].y - ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y]) < 4)
{
// center of cell reached, now find the biggest piece of food and
// vector to it, if none exist then go back to scan
// compute cell position
int ant_cell_x = ants[index].x / 30;
int ant_cell_y = ants[index].y / 30;
// this updates the i,jth memory cell in ant with info about food
float food_near_ant = Food_Near_Ant(ant_cell_x, ant_cell_y);
// test if we just bumped into some food
if (food_near_ant > 0)
{
// find highest source of food
int food_x = -1;
int food_y = -1;
// find the highest food source in cell
int food_id = Max_Food_In_Cell(ant_cell_x, ant_cell_y, &food_x, &food_y);
// pre-empt into vector 2 food
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] =
ANT_SEARCH_FOOD_S4_VECTOR_2FOOD;
// send to exact position
ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] = food_x;
ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] = food_y;
// set target id of food
ants[index].varsI[ANT_INDEX_FOOD_TARGET_ID] = food_id;
// set counters to 0
ants[index].counter_1 = ants[index].counter_2 = 0;
} // end if
else
{
// set mode to scan
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S1_SCAN;
} // end else
} // end if
} break;
case ANT_SEARCH_FOOD_S4_VECTOR_2FOOD:
{
// this substate vectors the ant to the exact x,y of the food
// once there, tests to see if there is food there, if so eats it,
// else go to scan
// burn food
ants[index].varsI[ANT_INDEX_HUNGER_LEVEL]+=2;
// pick direction
int dx = ants[index].varsI[ANT_INDEX_FOOD_TARGET_X] - ants[index].x;
int dy = ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y] - ants[index].y;
// pick maxium delta to move in
if (abs(dx) >= abs(dy))
{
// x dominate
if (dx > 0)
{
// move right
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_RIGHT)
{
// start animation right
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_RIGHT;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].x+=ant_movements_x[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end if
else
if (dx < 0)
{
// move left
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_LEFT)
{
// start animation left
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_LEFT;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].x+=ant_movements_x[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end else
} // end if x
else
{
// y dominate
if (dy > 0)
{
// move down
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_DOWN)
{
// start animation down
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_DOWN;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].y+=ant_movements_y[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end if
else
if (dy < 0)
{
// move up
if (ants[index].varsI[ANT_INDEX_DIRECTION] != ANT_ANIM_UP)
{
// start animation down
ants[index].varsI[ANT_INDEX_DIRECTION] = ANT_ANIM_UP;
Set_Animation_BOB(&ants[index], ants[index].varsI[ANT_INDEX_DIRECTION]);
} // end if
ants[index].y+=ant_movements_y[ants[index].varsI[ANT_INDEX_DIRECTION]];
} // end else
} // end else
// update memory image ????
// update memory with presence of food
int ant_cell_x = ants[index].x / 30;
int ant_cell_y = ants[index].y / 30;
// this updates the i,jth memory cell in ant with info about food
float food_near_ant = Food_Near_Ant(ant_cell_x, ant_cell_y);
ants_mem[index].cell[ant_cell_x][ant_cell_y] =
ANT_MEMORY_RESIDUAL_RATE*ants_mem[index].cell[ant_cell_x][ant_cell_y] +
(1-ANT_MEMORY_RESIDUAL_RATE)*food_near_ant;
// now test if target reached
if (abs(ants[index].x - ants[index].varsI[ANT_INDEX_FOOD_TARGET_X]) < 4 &&
abs(ants[index].y - ants[index].varsI[ANT_INDEX_FOOD_TARGET_Y]) < 4)
{
// food reached, now find the biggest piece of food and
// vector to it, if none exist then go back to scan
// is there any food left?
if (ants[index].varsI[ANT_INDEX_FOOD_TARGET_ID] > 0)
{
// thank god!
Set_New_State(ANT_EATING, index, ants[index].varsI[ANT_INDEX_FOOD_TARGET_ID],0);
} // end if
else
{
// go back to scan
ants[index].varsI[ANT_INDEX_AI_SUBSTATE] = ANT_SEARCH_FOOD_S1_SCAN;
} // end if
} // end if
} break;
case ANT_SEARCH_FOOD_S5: break;
case ANT_SEARCH_FOOD_S6: break;
case ANT_SEARCH_FOOD_S7: break;
default: break;
} // end switch
} break;
Ants from totwgpg
I''ve been playing with example 12.3 from Lamothe''s book (Tricks of the Windows GPG) and am trying to figure out what''s wrong with the code. This example is showing off AI memory using a set number of ants and piles of food. The ants wander around randomly until they get hungry, then they mosey on over to the food for some mnm''s (they update their memory of where the food is as they wander). If they don''t get to the food in time, they die. Now, the example seems to work fine, except that eventually, one (usually many) of the ants wanders over to a food pile and gets in a state loop between substates ANT_SEARCH_FOOD_S3_VECTOR_2CELL and ANT_SEARCH_FOOD_S4_VECTOR_2FOOD Basically the first tells them to go to the center of the cell with the food, the second tells them to go to the highest value mnm, but then it kicks back.
here''s some code (switch off of ant op):
anyone know what''s happening here? I want to help these ants!
oh hai
It is highly unlikely that anyone is going to wade through your code to work out what it''s doing. You would be far better served by writing out the algorithm that your code implements. That way we can check the algorithm for errors that might produce the errant behaviour. If the algorithm is not at fault, then the problem is one of debugging, and there are more appropriate places to get help with that.
Cheers,
Timkin
Cheers,
Timkin
quote:
Original post by Timkin
It is highly unlikely that anyone is going to wade through your code to work out what it''s doing. You would be far better served by writing out the algorithm that your code implements. That way we can check the algorithm for errors that might produce the errant behaviour. If the algorithm is not at fault, then the problem is one of debugging, and there are more appropriate places to get help with that.
Cheers,
Timkin
Well I figured out what was wrong, and it wasn''t the algorithm. In one of the checks to see if food was existent, the code author (not I) had done a check off of the food morsel''s id rather then the energy value of the food. So everytime an ant wanted to eat food_id 0, he got confused and looped until he died (poor little guy). I''m sorry for the huge code dump, but I thought that the algorithm was the problem and didn''t know what I should put up to give an idea of what I was working with. I was really hoping that someone who had read this book may have noticed the same problem and knew what was causing it. But the ants have been debugged now so no worries.
Pun intended.
"I''ve never seen that. I''ve never seen anybody drive their garbage down to the side of the street and bang the hell out of it with a stick. I''ve never seen that."
oh hai
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement