🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Ants from totwgpg

Started by
1 comment, last by Zul 22 years ago
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):
  
         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;
  
anyone know what''s happening here? I want to help these ants!
oh hai
Advertisement
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
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