Advertisement
Nickpips

Pacman AI

Mar 26th, 2016 (edited)
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.17 KB | None | 0 0
  1. int getDirection( int targetX, int targetY, int ghostX, int ghostY, int incX, int incY, Maze& maze )
  2. {
  3.     // Initialize Values
  4.     std::vector<int> pref( 4 );
  5.     std::vector<int> directions( 4 );
  6.     std::vector<int> distancesSorted( 4 );
  7.     int distances[] = { 0,0,0,0 };
  8.  
  9.     // Get distances
  10.     distances[UP] = (ghostX-targetX)*(ghostX-targetX)+(ghostY-1-targetY)*(ghostY-1-targetY);
  11.     distances[DOWN] = (ghostX-targetX)*(ghostX-targetX)+(ghostY+1-targetY)*(ghostY+1-targetY);
  12.     distances[LEFT] = (ghostX-1-targetX)*(ghostX-1-targetX)+(ghostY-targetY)*(ghostY-targetY);
  13.     distances[RIGHT] = (ghostX+1-targetX)*(ghostX+1-targetX)+(ghostY-targetY)*(ghostY-targetY);
  14.  
  15.     for( int i = 0; i < 4; i++ )
  16.     {
  17.         // pref: Directions in order of desirability
  18.         pref[i] = 0;
  19.         // directions: Valid ways to move (To populate pref)
  20.         directions[i] = i;
  21.         // distancesSorted: Distances, to be sorted
  22.         distancesSorted[i] = distances[i];
  23.     }
  24.  
  25.     std::sort( distancesSorted.begin(), distancesSorted.end() );
  26.  
  27.     for( int i = 3; i >= 0; i-- )
  28.     {
  29.         // poss: Containing ties (Ties are broken randomly)
  30.         std::vector<int> poss( 0 );
  31.  
  32.         // dist: smallest distance
  33.         int dist = distancesSorted[i];
  34.  
  35.         // Populate poss
  36.         for( int j : directions )
  37.             if( distances[j] == dist )
  38.                 poss.push_back( j );
  39.  
  40.         // Randomly shuffle to break the tie
  41.         std::random_shuffle( poss.begin(), poss.end() );
  42.  
  43.         // Get the winning direction
  44.         int dir = poss.back();
  45.  
  46.         // Remove from list of directions to populate pref with
  47.         for( auto ind = directions.begin(); ind != directions.end(); ind++ )
  48.             if( *ind == dir )
  49.             {
  50.                 directions.erase( ind );
  51.                 break;
  52.             }
  53.  
  54.         // Populate pref with direction
  55.         pref[i] = dir;
  56.     }
  57.  
  58.     // Direction to be returned
  59.     int dir = -1;
  60.  
  61.     for( int i = 0; i < 4; i++ )
  62.     {
  63.         // Get most preferable direction
  64.         dir = pref.at( i );
  65.  
  66.         // If not running into a wall, and not flipping around, return
  67.         if(        (dir == UP       && !maze.getTile( ghostX, ghostY - 1 ).getWall()    && !(incX == 0 && incY == +1))
  68.                 || (dir == DOWN     && !maze.getTile( ghostX, ghostY + 1 ).getWall()    && !(incX == 0 && incY == -1))
  69.                 || (dir == LEFT     && !maze.getTile( ghostX - 1, ghostY ).getWall()    && !(incX == +1 && incY == 0))
  70.                 || (dir == RIGHT    && !maze.getTile( ghostX + 1, ghostY ).getWall()    && !(incX == -1 && incY == 0)) )
  71.             break;
  72.     }
  73.  
  74.     return dir;
  75. }
  76.  
  77. int flick( Ghost& c )
  78. {
  79.     // Get direction info
  80.     int incX = c.getXInc();
  81.     int incY = c.getYInc();
  82.     int dir;
  83.  
  84.     // Set direction to oppose current direction
  85.     if( incX == 0 && incY == -1 )
  86.         dir = DOWN;
  87.     if( incX == 0 && incY == 1 )
  88.         dir = UP;
  89.     if( incX == -1 && incY == 0 )
  90.         dir = RIGHT;
  91.     if( incX == 1 && incY == 0 )
  92.         dir = LEFT;
  93.  
  94.     // Change and return direction
  95.     c.changeDirection( Direction( dir ) );
  96.     return dir;
  97. }
  98.  
  99. // TODO: Proper include location
  100. #include <time.h>
  101.  
  102. void GameElements::moveGhosts()
  103. {
  104.     // TODO: Remove static variables
  105.     static int lasttime = time( nullptr );
  106.     static int fright[] = { false, false, false, false };
  107.     static std::vector<int> scatter = { 7,7,5,5 };
  108.     static std::vector<int> chase = { 20,20,20,-1 };
  109.     static bool chasing = false;
  110.  
  111.    
  112.     // Initialize
  113.     Tiles pacman = this->getPacmanPos();
  114.     int pacX = pacman.getX();
  115.     int pacY = pacman.getY();
  116.     Tiles pos;
  117.  
  118.     // ??why??
  119.     // TODO Fix .getX() and .getY()
  120.     std::swap( pacX, pacY );
  121.  
  122.     { // BLINKY
  123.  
  124.         // Move if possible
  125.         pos = maze.getTile( red.getX() + red.getXInc(), red.getY() + red.getYInc() );
  126.         if( !pos.getWall() )
  127.         {
  128.             red.move();
  129.         }
  130.  
  131.         // Default Location
  132.         int tarX = 10000;
  133.         int tarY = -10000;
  134.  
  135.         // Save Variables
  136.         int gX = red.getX();
  137.         int gY = red.getY();
  138.         int incX = red.getXInc();
  139.         int incY = red.getYInc();
  140.         int dir;
  141.  
  142.         if( red.getFrightened() == true )
  143.         {
  144.             // Flick back immediately
  145.             if( !fright[0] )
  146.             {
  147.                 dir = flick( red );
  148.                 // Prepare for random movement
  149.                 fright[0] = true;
  150.             } else
  151.             {
  152.                 // Go randomly
  153.                 tarX = 10000 * (rand() % 3 - 1);
  154.                 tarY = 10000 * (rand() % 3 - 1);
  155.  
  156.                 dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  157.             }
  158.         } else
  159.         {
  160.             // Reset for next time
  161.             fright[0] = false;
  162.  
  163.             // Blinky goes straight
  164.             if( red.getChase() == true )
  165.             {
  166.                 tarX = pacX;
  167.                 tarY = pacY;
  168.             }
  169.  
  170.             dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  171.         }
  172.  
  173.         // Update direction
  174.         red.changeDirection( Direction(dir) );
  175.     }
  176.  
  177.     { // PINKY
  178.         pos = maze.getTile( pink.getX() + pink.getXInc(), pink.getY() + pink.getYInc() );
  179.         if( !pos.getWall() )
  180.         {
  181.             pink.move();
  182.         }
  183.  
  184.         int tarX = -10000;
  185.         int tarY = -10000;
  186.         int gX = pink.getX();
  187.         int gY = pink.getY();
  188.         int incX = pink.getXInc();
  189.         int incY = pink.getYInc();
  190.         int dir;
  191.  
  192.         if( pink.getFrightened() == true )
  193.         {
  194.             if( !fright[1] )
  195.             {
  196.                 dir = flick( pink );
  197.                 fright[1] = true;
  198.             } else
  199.             {
  200.                 tarX = 10000 * (rand() % 3 - 1);
  201.                 tarY = 10000 * (rand() % 3 - 1);
  202.  
  203.                 dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  204.             }
  205.         } else
  206.         {
  207.             fright[1] = false;
  208.             if( pink.getChase() == true )
  209.             {
  210.                 tarX = pacX + 4*this->pacman.getXInc();
  211.                 tarY = pacY + 4*this->pacman.getYInc();
  212.             }
  213.  
  214.             dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  215.         }
  216.  
  217.         pink.changeDirection( Direction( dir ) );
  218.     }
  219.  
  220.     { // INKY
  221.         pos = maze.getTile( blue.getX() + blue.getXInc(), blue.getY() + blue.getYInc() );
  222.         if( !pos.getWall() )
  223.         {
  224.             blue.move();
  225.         }
  226.  
  227.         int tarX = 10000;
  228.         int tarY = 10000;
  229.         int gX = blue.getX();
  230.         int gY = blue.getY();
  231.         int incX = blue.getXInc();
  232.         int incY = blue.getYInc();
  233.         int dir;
  234.  
  235.         if( blue.getFrightened() == true )
  236.         {
  237.             if( !fright[2] )
  238.             {
  239.                 dir = flick( blue );
  240.                 fright[2] = true;
  241.             } else
  242.             {
  243.                 tarX = 10000 * (rand() % 3 - 1);
  244.                 tarY = 10000 * (rand() % 3 - 1);
  245.  
  246.                 dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  247.             }
  248.         } else
  249.         {
  250.             fright[2] = false;
  251.             if( blue.getChase() == true )
  252.             {
  253.                 tarX = red.getX()+2*(pacX-red.getX());
  254.                 tarY = red.getY()+2*(pacY-red.getY());
  255.             }
  256.  
  257.             dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  258.         }
  259.  
  260.         blue.changeDirection( Direction( dir ) );
  261.     }
  262.  
  263.  
  264.     { // CLYDE
  265.         pos = maze.getTile( orange.getX() + orange.getXInc(), orange.getY() + orange.getYInc() );
  266.         if( !pos.getWall() )
  267.         {
  268.             orange.move();
  269.         }
  270.  
  271.         int tarX = -10000;
  272.         int tarY = 10000;
  273.         int gX = orange.getX();
  274.         int gY = orange.getY();
  275.         int incX = orange.getXInc();
  276.         int incY = orange.getYInc();
  277.         int dir;
  278.  
  279.         if( orange.getFrightened() == true )
  280.         {
  281.             if( !fright[3] )
  282.             {
  283.                 dir = flick( orange );
  284.                 fright[3] = true;
  285.             } else
  286.             {
  287.                 tarX = 10000 * (rand() % 3 - 1);
  288.                 tarY = 10000 * (rand() % 3 - 1);
  289.  
  290.                 dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  291.             }
  292.         } else
  293.         {
  294.             fright[3] = false;
  295.             if( orange.getChase() == true )
  296.             {
  297.                 if( (pacX-orange.getX())*(pacX-orange.getX()) + (pacY-orange.getY())*(pacY-orange.getY()) > 64 )
  298.                 {
  299.                     tarX = pacX;
  300.                     tarY = pacY;
  301.                 }
  302.             }
  303.  
  304.             dir = getDirection( tarX, tarY, gX, gY, incX, incY, maze );
  305.         }
  306.  
  307.         orange.changeDirection( Direction( dir ) );
  308.     }
  309.  
  310.     // Control chase modes
  311.     if( chasing == true )
  312.     {
  313.         // If scatter time eached
  314.         if( time( nullptr ) >= lasttime + chase.at( 0 ) && chase.at( 0 ) != -1 )
  315.         {
  316.             // Remove used data
  317.             chase.erase(chase.begin());
  318.  
  319.             // Reset timer
  320.             lasttime = time( nullptr );
  321.  
  322.             // Set chase mode
  323.             chasing = false;
  324.             red.setChase( chasing );
  325.             pink.setChase( chasing );
  326.             blue.setChase( chasing );
  327.             orange.setChase( chasing );
  328.  
  329.             // Ghosts must swap direction ("flick back")
  330.             flick( red );
  331.             flick( pink );
  332.             flick( blue );
  333.             flick( orange );
  334.         }
  335.     } else
  336.     {
  337.         // If chase time reached
  338.         if( time( nullptr ) >= lasttime + scatter.at( 0 ) )
  339.         {
  340.             // Remove used data
  341.             scatter.erase(scatter.begin());
  342.  
  343.             // Reset timer
  344.             lasttime = time( nullptr );
  345.  
  346.             // Set chase mode
  347.             chasing = true;
  348.             red.setChase( chasing );
  349.             pink.setChase( chasing );
  350.             blue.setChase( chasing );
  351.             orange.setChase( chasing );
  352.  
  353.             // Ghosts must swap direction ("flick back")
  354.             flick( red );
  355.             flick( pink );
  356.             flick( blue );
  357.             flick( orange );
  358.         }
  359.     }
  360. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement