🎉 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!

help fixing pacman ai

Started by
7 comments, last by stooge_dev 21 years, 6 months ago
I'm having a difficulty time figuring out how to right AI for pacman. Right now I have 3 ghosts which are Aggressor, Bloodhound, and Bloodhound2. The Aggressor is suppose to act like a homing missile of course it doesn't right now. The problem with it is that it doesn't follow pacman. The bloodhound is suppose to follow pacman base on the Scent left on the tiles. However, sometimes it'll get stuck and not move. Bloodhound2 has the similar problems. Also, is there any way that I could clean up the code and reduce the amount? Thank you
  
#include "pacman1.h"
#include "ai.h"


void moveAggressor(void) // Blue ghost

{
	ghosts[0].oldy = ghosts[0].y;
	ghosts[0].oldx = ghosts[0].x;

  if(pacman.flee == 1)
   {
      if(ghosts[0].x > pacman.x)
         ghosts[0].direction = LEFT;
      else if (ghosts[0].y > pacman.y)
         ghosts[0].direction = UP;
      else if(ghosts[0].x < pacman.y)
         ghosts[0].direction = RIGHT;
      else if(ghosts[0].y < pacman.x)
         ghosts[0].direction = DOWN;
   }
   else if(pacman.x > ghosts[0].x)
      ghosts[0].direction = RIGHT;
   else if(pacman.y > ghosts[0].y)
      ghosts[0].direction = DOWN;
   else if(pacman.x < ghosts[0].x)
      ghosts[0].direction = LEFT;
   else if(pacman.y < ghosts[0].y)
      ghosts[0].direction = UP;

   if(ghosts[0].direction == UP)
     { ghosts[0].y--;
       ghosts[0].sprNum = BLUEGHOST4_BMP;
     }
   else if(ghosts[0].direction == DOWN)
     {
      ghosts[0].y++;
      ghosts[0].sprNum = BLUEGHOST1_BMP;
     }
   else if(ghosts[0].direction == LEFT)
     {
      ghosts[0].x--;
      ghosts[0].sprNum = BLUEGHOST3_BMP;
     }
   else if(ghosts[0].direction == RIGHT)
     {
      ghosts[0].x++;
      ghosts[0].sprNum = BLUEGHOST2_BMP;
     }


	if(level[ghosts[0].y][ghosts[0].x] == 1 || (ghosts[0].y < 0) || (ghosts[0].y > 14) || (ghosts[0].x < 0) || (ghosts[0].x > 19))
	{
		ghosts[0].y = ghosts[0].oldy;
		ghosts[0].x = ghosts[0].oldx;
	}
}
/*****************************************************************************/
void moveBloodhound(void) // Green ghost
{
   int dir = 0;
	ghosts[1].oldy = ghosts[1].y;
	ghosts[1].oldx = ghosts[1].x;

   if(pacman.flee == 1)
   {
      if(ghosts[1].x > pacman.x)
         ghosts[1].direction = LEFT;
      else if (ghosts[1].y > pacman.y)
         ghosts[1].direction = UP;
      else if(ghosts[1].x < pacman.y)
         ghosts[1].direction = RIGHT;
      else if(ghosts[1].y < pacman.x)
         ghosts[1].direction = DOWN;
   }
   else if(levelScent[ghosts[1].y][ghosts[1].x] == BLANK)
      {
         dir = rand() % 4+1;
         if(dir == UP)
            ghosts[1].direction = UP;
         else if(dir == DOWN)
            ghosts[1].direction = DOWN;
         else if(dir == LEFT)
            ghosts[1].direction = LEFT;
         else if(dir == RIGHT)
            ghosts[1].direction = RIGHT;
      }
   else if(levelScent[ghosts[1].y][ghosts[1].x] == UP)
      ghosts[1].direction = UP;
   else if(levelScent[ghosts[1].y][ghosts[1].x] == DOWN)
      ghosts[1].direction = DOWN;
   else if(levelScent[ghosts[1].y][ghosts[1].x] == LEFT)
      ghosts[1].direction = LEFT;
   else if(levelScent[ghosts[1].y][ghosts[1].x] == RIGHT)
      ghosts[1].direction = RIGHT;

   if(ghosts[1].direction == UP)
     { ghosts[1].y--;
       ghosts[1].sprNum = GREENGHOST4_BMP;
     }
   else if(ghosts[1].direction == DOWN)
     {
      ghosts[1].y++;
      ghosts[1].sprNum = GREENGHOST1_BMP;
     }
   else if(ghosts[1].direction == LEFT)
     {
      ghosts[1].x--;
      ghosts[1].sprNum = GREENGHOST3_BMP;
     }
   else if(ghosts[1].direction == RIGHT)
     {
      ghosts[1].x++;
      ghosts[1].sprNum = GREENGHOST2_BMP;
     }

  if(level[ghosts[1].y][ghosts[1].x] == 1 || (ghosts[1].y < 0) || (ghosts[1].y > 14) || (ghosts[1].x < 0) || (ghosts[1].x > 19))
	{
		ghosts[1].y = ghosts[1].oldy;
		ghosts[1].x = ghosts[1].oldx;
	}
}
/*****************************************************************************/
void moveBloodhound2(void) // Red ghost

{
    int dir = 0;
	ghosts[2].oldy = ghosts[2].y;
	ghosts[2].oldx = ghosts[2].x;

   if(pacman.flee == 1)
   {
      if(ghosts[2].x > pacman.x)
         ghosts[2].direction = LEFT;
      else if (ghosts[2].y > pacman.y)
         ghosts[2].direction = UP;
      else if(ghosts[2].x < pacman.y)
         ghosts[2].direction = RIGHT;
      else if(ghosts[2].y < pacman.x)
         ghosts[2].direction = DOWN;
   }
   else if(levelScent[ghosts[2].y][ghosts[2].x] == BLANK || ((rand() % 50) < 30))
      {
         dir = rand() % 4;
         if(dir == UP)
            ghosts[2].direction = UP;
         else if(dir == DOWN)
            ghosts[2].direction = DOWN;
         else if(dir == LEFT)
            ghosts[2].direction = LEFT;
         else if(dir == RIGHT)
            ghosts[2].direction = RIGHT;
      }
   else if(levelScent[ghosts[2].y][ghosts[2].x] == UP)
      ghosts[2].direction = UP;
   else if(levelScent[ghosts[2].y][ghosts[2].x] == DOWN)
      ghosts[2].direction = DOWN;
   else if(levelScent[ghosts[2].y][ghosts[2].x] == LEFT)
      ghosts[2].direction = LEFT;
   else if(levelScent[ghosts[2].y][ghosts[2].x] == RIGHT)
      ghosts[2].direction = RIGHT;

   if(ghosts[2].direction == UP)
     { ghosts[2].y--;
       ghosts[2].sprNum = REDGHOST4_BMP;
     }
   else if(ghosts[2].direction == DOWN)
     {
      ghosts[2].y++;
      ghosts[2].sprNum = REDGHOST1_BMP;
     }
   else if(ghosts[2].direction == LEFT)
     {
      ghosts[2].x--;
      ghosts[2].sprNum = REDGHOST3_BMP;
     }
   else if(ghosts[2].direction == RIGHT)
     {
      ghosts[2].x++;
      ghosts[2].sprNum = REDGHOST2_BMP;
     }

  if(level[ghosts[2].y][ghosts[2].x] == 1 || (ghosts[2].y < 0) || (ghosts[2].y > 14) || (ghosts[2].x < 0) || (ghosts[2].x > 19))
	{
		ghosts[2].y = ghosts[2].oldy;
		ghosts[2].x = ghosts[2].oldx;
	}
}

  
[edited by - stooge_dev on December 30, 2002 8:47:26 AM]
Advertisement
how are you setting this variable in your code?
pacman.flee == 1

it might be the root of the problem

Shahid Anwar
Shahid Anwar
.
---Yesterday is history, tomorrow is a mystery, today is a gift and that's why it's called the present.
Personally I''d move the ghosts like this:

Check the position of the PacMan.

Since PacMan only has 4 directions, we only have to check if he''s up, down, left or right.

If he''s up, move up unless there''s a wall, if he is also left/right move left/right.

same for the other directions.

This way he won''t be really smart btw, he''ll get stuck in corners, a better way would be to check the position of the pacman and set waypoints to follow, this way he will never get stuck, but a smart player can still exploit this by using corners so he''ll set way points around the corners and then quickly move the other way.

I''d use something like the first means(check if there''s a direct way available to the pacman, a way that was not last position, if so move that way, otherwise find a way using waypoints and start moving that route, or follow waypoints if available)

Ofcourse this doesn''t help your question, but you didn''t ppost the entire agressor code anyways.
---Yesterday is history, tomorrow is a mystery, today is a gift and that's why it's called the present.
If I remember correctly the original pacman AI contained one ghost which went straight for the pacman, another which tried to ambush him at the next intersection, and another that hung around the bonuses, the last one was totally random.

But since tis your game do waht you like.
Daemin(Dominik Grabiec)
Hi.
I am not a real expert. I am on my PacMan game, too! I think you can enhance the AI if you make an array which holds the positions you have visited. This way you won''t be stuck anywhere but still if you get trapped there should be an indication so that you can go on a previously visited position.
Im nowhere close to being an expert... but perhaps you can check where the pacman is then check if a wall is in the wall, if not move towards him. If not then check along a wall until the square moves in an x or y towards pacmans position. If it goes beyond a certain point check the other direction, each time go further than the first. Just checking.
There was a pac-man programming competition at this forum: http://www.gamecoding.org.uk/forum/ late last year. You could ask some of the people there, since there was a lot of conversation about ghost AI.

I did not enter the competetion, although I thought a lot about it, since I was considering it. I am not going to repeat exactly what I said there, but generally this is what I would do:

1. If the ghost is in a corridor, make it continue to move through it until it reachs an intersection in which it can move in more than 1 direction.

2. Never make a ghost go back in the same direction it just came from. The original game followed this rule (with the exception of when ghosts entered 'scatter mode', which happens only a few times every level)

In other words, make the ghost move until it hits a wall, and then make it change direction, but NEVER in the direction it came from. You will notice AI is only introduced when there is a choice of direction.

Follow these rules, will make the ghosts move nicely, even if you have no AI at all (just random). For the game to be hard, the ghost must follow pacman in some way, at least some of the time.

I should note the original game had modes that turned on/off during a level in which pacman was chased and not, to give the player some breathing time.

Take a look here:
http://jongy.tripod.com/SoundofEating.htm
for some information on the original game.

Particulary this page:
http://jongy.tripod.com/GhostPsychology.html

Jason Doucette
www.jasondoucette.com

(edit - i forgot this forum does not automatically change URLs into clickable URLs...)

[edited by - Jason Doucette on January 11, 2003 2:12:58 PM]
Jason Doucette / Xona.comDuality: ZF — Xbox 360 classic arcade shmup featuring Dual Play
This is a perfect opportunity for my Precalculated Pathfinding technique.

If you had a node at every junction or corner, then you''d be able to navigate the maze quickly and easily. It would also take care of situations such as wrapping (going off one side of the level and coming on the other). The maze doesn''t change, so there''s no worrying about dynamic networks.

Superpig
- saving pigs from untimely fates, and when he''s not doing that, runs The Binary Refinery.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

This topic is closed to new replies.

Advertisement