Advertisement
Guest User

Blarger

a guest
Nov 3rd, 2013
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.07 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <assert.h>
  4.  
  5. // ANY OTHER HEADERS HERE
  6.  
  7. using namespace std;
  8.  
  9. #define IS_ANT_LABEL(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '+')
  10. enum AntDirection { NORTH, EAST, SOUTH, WEST };
  11. const int FIELD_WIDTH = 5;
  12. const int FIELD_HEIGHT = 6;
  13. const int MAX_MEMORY = 100; //for ant memory
  14.  
  15. const int MOUND_X = 1;
  16. const int MOUND_Y = 3;
  17.  
  18. const int MAX_ANTS = 8;
  19.  
  20. int num_ants = 0;
  21. AntDirection dir_assign = NORTH;
  22.  
  23. //holds x and y values. Useful for the PathHome variable of tracking memory for the Ant
  24. struct Vector2
  25. {
  26.     int x, y;
  27.     Vector2() {}
  28.     Vector2(int X, int Y) : x(X), y(Y) {}
  29. };
  30.  
  31. struct Ant {
  32.     int x, y; // 0-based
  33.     char label;
  34.     AntDirection preferred_dir;
  35.     bool have_food;
  36.  
  37.     //holds memory of visited positions on field. 0 for non visited, and 1 for have visited.
  38.     bool MemField[FIELD_HEIGHT][FIELD_WIDTH];
  39.  
  40.     //holds a list of positions the ant has occupied thus far. Used to allow the ant to return home.
  41.     Vector2 PathHome[MAX_MEMORY];
  42.     int steps_thus_far; //how many steps the ant has taken since it was spawned
  43.  
  44.  
  45.     Ant() {
  46.         x = y = label = 0;
  47.         preferred_dir = NORTH;
  48.         have_food = false;
  49.         steps_thus_far = 0;
  50.        
  51.         //initialize memory field with ant mound set to 1. Every other area is set to 0.
  52.         for(int i=0; i<FIELD_HEIGHT; i++)
  53.         {
  54.             for(int k=0; k<FIELD_WIDTH; k++)
  55.             {
  56.                 if(i == MOUND_Y && k == MOUND_X)
  57.                 {
  58.                     MemField[i][k] = 1;
  59.                 }
  60.                 else
  61.                 {
  62.                     MemField[i][k] = 0;
  63.                 }
  64.             }
  65.         }
  66.     }
  67. };
  68. Ant ants[MAX_ANTS];
  69.  
  70. string AntField[FIELD_HEIGHT] = {
  71.   "...X.",
  72.   "XX.X.",
  73.   "...X.",
  74.   "._.X*",
  75.   "...X.",
  76.   ".....",
  77. };
  78.  
  79.  
  80. string fieldToString()
  81. {
  82.     string field_copy[FIELD_HEIGHT];
  83.     copy(AntField, AntField+FIELD_HEIGHT, field_copy);
  84.     for (int a = 0; a < num_ants; a++)
  85.         if (IS_ANT_LABEL(field_copy[ants[a].y][ants[a].x]))
  86.             field_copy[ants[a].y][ants[a].x] = '+';
  87.         else
  88.             field_copy[ants[a].y][ants[a].x] = ants[a].label;
  89.     string result;
  90.     for (int y = 0; y < FIELD_HEIGHT; y++)
  91.     {
  92.         result += field_copy[y];
  93.         result += "\n";
  94.     }
  95.     return result;
  96. }
  97.  
  98. void tickMound()
  99. {
  100.     //Check to see if mound can produce more ants. If so, assign a new ant onto the field and its preferred direction.
  101.     if(num_ants < MAX_ANTS)
  102.     {
  103.         ants[num_ants].label = (char)(((int)'0')+num_ants); //assign its unique ID
  104.         ants[num_ants].PathHome[0] = Vector2(MOUND_X, MOUND_Y);
  105.  
  106.         int prefDir = num_ants % 4; //since there's 4 cardinal directions, modulus by 4 to automatically assign
  107.  
  108.         switch(prefDir)
  109.         {
  110.         case 0:
  111.             {
  112.                 ants[num_ants].preferred_dir = NORTH;
  113.                 break;
  114.             }
  115.         case 1:
  116.             {
  117.                 ants[num_ants].preferred_dir = EAST;
  118.                 break;
  119.             }
  120.         case 2:
  121.             {
  122.                 ants[num_ants].preferred_dir = SOUTH;
  123.                 break;
  124.             }
  125.         case 3:
  126.             {
  127.                 ants[num_ants].preferred_dir = WEST;
  128.                 break;
  129.             }
  130.         }
  131.        
  132.         //now assign ant's x and y based on position of ant mound
  133.        
  134.         ants[num_ants].x = MOUND_X;
  135.         ants[num_ants].y = MOUND_Y;
  136.         ants[num_ants].MemField[MOUND_Y][MOUND_X] = 1;
  137.  
  138.         //finally increase the number of ants by 1
  139.         num_ants++;
  140.     }
  141. }
  142.  
  143. /*
  144.     Checks to see if ant can walk in chosen direction and returns true if successful. Called from tickAnts() normally.
  145. */
  146. bool tryWalk(Ant& ant, AntDirection dir)
  147. {
  148.     //For each direction, check to see if the ant can move in that direction, assuming it's not a boundary,
  149.     //obstacle, or a visited area. If it can, update its position and memory variables.
  150.     switch(dir)
  151.     {
  152.         case NORTH:
  153.             {
  154.                 if(ant.y - 1 < 0) //if the ant is at the edge, it can't move
  155.                     return false;
  156.                 else if(ant.y > 0) //the ant is not against the edge
  157.                 {
  158.                     //if there's an obstacle in the way or the ant has already went to the next location, don't move
  159.                     if(AntField[ant.y-1][ant.x] == 'X' || ant.MemField[ant.y-1][ant.x] == 1)
  160.                     {
  161.                         return false;
  162.                     }
  163.                
  164.                     else
  165.                     {
  166.                         if(ant.steps_thus_far < MAX_MEMORY)
  167.                         {
  168.                             ant.steps_thus_far++;
  169.                             ant.y--;
  170.                             ant.MemField[ant.y][ant.x] = 1;
  171.                             ant.PathHome[ant.steps_thus_far] = Vector2(ant.x, ant.y);
  172.                             return true;
  173.                         }
  174.                         else
  175.                         {
  176.                             cout << "Ant " << ant.label << " ran out of position memory.";
  177.                             return false;
  178.                         }
  179.                     }
  180.                    
  181.                 }
  182.                 else
  183.                 { return false; }
  184.                 break;
  185.             }
  186.         case EAST:
  187.             {
  188.                 if(ant.x + 1 > FIELD_WIDTH-1)
  189.                     return false;
  190.                 else if(ant.x < FIELD_WIDTH-1)
  191.                 {
  192.                     if(AntField[ant.y][ant.x + 1] == 'X' || ant.MemField[ant.y][ant.x+1] == 1)
  193.                     {
  194.                         return false;
  195.                     }
  196.                     else
  197.                     {
  198.                         if(ant.steps_thus_far < MAX_MEMORY)
  199.                         {
  200.                             ant.steps_thus_far++;
  201.                             ant.x++;
  202.                             ant.MemField[ant.y][ant.x] = 1;
  203.                             ant.PathHome[ant.steps_thus_far] = Vector2(ant.x, ant.y);
  204.                             return true;
  205.                         }
  206.                         else
  207.                         {
  208.                             cout << "Ant " << ant.label << " ran out of position memory.";
  209.                             return false;
  210.                         }
  211.                     }
  212.                 }
  213.                 else
  214.                 { return false; }
  215.                 break;
  216.             }
  217.  
  218.         case SOUTH:
  219.             {
  220.                 if(ant.y + 1 > FIELD_HEIGHT-1)
  221.                     return false;
  222.                 else if(ant.y < FIELD_HEIGHT-1)    
  223.                 {
  224.                     if(AntField[ant.y+1][ant.x] == 'X' || ant.MemField[ant.y+1][ant.x] == 1)
  225.                     {
  226.                         return false;
  227.                     }
  228.                     else
  229.                     {
  230.                         if(ant.steps_thus_far < MAX_MEMORY)
  231.                         {
  232.                             ant.steps_thus_far++;
  233.                             ant.y++;
  234.                             ant.MemField[ant.y][ant.x] = 1;
  235.                             ant.PathHome[ant.steps_thus_far] = Vector2(ant.x, ant.y);
  236.                             return true;
  237.                         }
  238.                         else
  239.                         {
  240.                             cout << "Ant " << ant.label << " ran out of position memory.";
  241.                             return false;
  242.                         }
  243.                     }
  244.                    
  245.                 }
  246.                 else
  247.                 { return false;}
  248.                 break;
  249.  
  250.             }
  251.  
  252.         case WEST:
  253.             {
  254.                 if(ant.x - 1 < 0)
  255.                     return false;
  256.                 else if(ant.x > 0)
  257.                 {
  258.                     if(AntField[ant.y][ant.x - 1] == 'X' || ant.MemField[ant.y][ant.x-1] == 1)
  259.                         return false;
  260.                     else
  261.                     {
  262.                         if(ant.steps_thus_far < MAX_MEMORY)
  263.                         {
  264.                             ant.steps_thus_far++;
  265.                             ant.x--;
  266.                             ant.MemField[ant.y][ant.x] = 1;
  267.                             ant.PathHome[ant.steps_thus_far] = Vector2(ant.x, ant.y);
  268.                             return true;
  269.                         }
  270.                         else
  271.                         {
  272.                             cout << "Ant " << ant.label << " ran out of position memory.";
  273.                             return false;
  274.                         }
  275.                     }
  276.                 }
  277.                 else
  278.                 { return false; }
  279.                 break;
  280.             }
  281.     }
  282. }
  283.  
  284. /*
  285.     Iterate through each available ant, having them move in their preferred direction. Check to see if it has food or not.
  286.  
  287.     have_food = true:
  288.         The ant follows its previous course back to the mound. If it reaches the mound, change have_food to false, reset
  289.         the ant's memory, and have it resume looking for food.
  290.  
  291.     have_food = false:
  292.         First check to see if the ant can move in its desired direction with tryWalk(). If false, the ant will
  293.         attempt to move in the next cardinal direction. If tryWalk() becomes false for all directions, the ant will
  294.         not move.
  295.        
  296.         If tryWalk() becomes true, the ant's position is updated to the new position. The new position is also assigned
  297.         1 in the ant's MemField to have it remember where it has walked.
  298.        
  299.         If it lands on food, change its have_food status to true.
  300. */
  301. void tickAnts()
  302. {
  303.     for(int i = 0; i < num_ants; i++)
  304.     {
  305.         int steps = ants[i].steps_thus_far;
  306.  
  307.         steps--;
  308.         if (steps < 0)
  309.             steps = 0;
  310.  
  311.        
  312.         if(ants[i].have_food)
  313.         {
  314.             ants[i].x = ants[i].PathHome[steps].x;
  315.             ants[i].y = ants[i].PathHome[steps].y;
  316.             ants[i].steps_thus_far--;
  317.  
  318.             //Check to see if the ant has arrived back at the mound.
  319.             if(ants[i].x == MOUND_X && ants[i].y == MOUND_Y)
  320.             {
  321.                 ants[i].have_food = false;
  322.  
  323.                 //clear its memory
  324.                 for(int j = 0; j < FIELD_HEIGHT; j++)
  325.                 {
  326.                     for(int k = 0; k < FIELD_WIDTH; k++)
  327.                     {
  328.                         ants[i].MemField[j][k] = 0;
  329.                     }
  330.                 }
  331.  
  332.                 //Resetting steps_thus_far to zero. The PathHome values will be overwritten naturally.
  333.                 ants[i].steps_thus_far = 0;
  334.             }
  335.         }
  336.         else
  337.         {
  338.             //have_food = false
  339.            
  340.             //Check to see if ant can move in its desired direction. If so, proceed and check for food.
  341.             //Otherwise, try the other directions.
  342.             bool moved = false;
  343.  
  344.             moved = tryWalk(ants[i], ants[i].preferred_dir);
  345.  
  346.             //try the other three directions based on the ant's preferred direction, going clockwise.
  347.             //If neither of them come up true, the ant will not move.
  348.             if(!moved)
  349.             {
  350.                 if(ants[i].preferred_dir == NORTH)
  351.                 {
  352.                     moved = tryWalk(ants[i], EAST);
  353.                     if (!moved)
  354.                     {
  355.                         moved = tryWalk(ants[i], SOUTH);
  356.  
  357.                         if(!moved)
  358.                             moved = tryWalk(ants[i], WEST);
  359.                     }
  360.                 }
  361.  
  362.                 else if(ants[i].preferred_dir == EAST)
  363.                 {
  364.                     moved = tryWalk(ants[i], SOUTH);
  365.                     if (!moved)
  366.                     {
  367.                         moved = tryWalk(ants[i], WEST);
  368.  
  369.                         if(!moved)
  370.                             moved = tryWalk(ants[i], NORTH);
  371.                     }
  372.                 }
  373.                 else if(ants[i].preferred_dir == SOUTH)
  374.                 {
  375.                     moved = tryWalk(ants[i], WEST);
  376.                     if (!moved)
  377.                     {
  378.                         moved = tryWalk(ants[i], NORTH);
  379.  
  380.                         if(!moved)
  381.                             moved = tryWalk(ants[num_ants], EAST);
  382.                     }
  383.                 }
  384.                 else if(ants[i].preferred_dir == WEST)
  385.                 {
  386.                     moved = tryWalk(ants[i], NORTH);
  387.                     if (!moved)
  388.                     {
  389.                         moved = tryWalk(ants[i], EAST);
  390.  
  391.                         if(!moved)
  392.                             moved = tryWalk(ants[i], SOUTH);
  393.                     }
  394.                 }
  395.             }
  396.        
  397.            
  398.             //check for food if the ant moved to a new location
  399.             if(moved)
  400.             {
  401.                 if(AntField[ants[i].y][ants[i].x] == '*')
  402.                 {
  403.                     //have ant change its food status and remove the food from the field
  404.                     ants[i].have_food = true;
  405.                     AntField[ants[i].y][ants[i].x] = '.';
  406.                 }
  407.             }
  408.         }
  409.     }
  410. }
  411.  
  412. void timeStep(int numsteps)
  413. {
  414.     for (int i = 0; i < numsteps; i++)
  415.     {
  416.         tickMound();
  417.         tickAnts();
  418.         cout << fieldToString();
  419.     }
  420. }
  421.  
  422. int main()
  423. {
  424.     timeStep(5);
  425.    
  426.     assert(fieldToString() == ".0.X.\nXX.X.\n34.X.\n._.X*\n...X.\n2..1.\n");
  427.  
  428.     timeStep(5);
  429.     assert(fieldToString() == "+3.X.\nXX.X.\n.72X.\n._.X*\n6..X.\n....+\n");
  430.  
  431.     timeStep(5);
  432.     assert(fieldToString() == "+..X.\nXX.X.\n...X.\n.16X*\n...X.\n...52\n");
  433.  
  434.     timeStep(5);
  435.     assert(fieldToString() == "+..X.\nXX.X.\n...X.\n._5X*\n...X6\n...21\n");
  436.  
  437.     timeStep(5);
  438.     assert(fieldToString() == "+..X.\nXX.X.\n.2.X.\n._.X*\n...X5\n..61.\n");
  439.  
  440.     return 0;
  441. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement