I just saw an interesting video blog post by the CTO of Devexpress entitled Pac-Man and Object-Oriented Programming, in which Julian talks about how we’ve been doing object-oriented programming for 20 years now (or even more than that if you come from the SmallTalk world) and how we, as OOP/OOD programmers and designers think about programming. He then quickly moves on to comparing that to a game of Pac-Man.
Now Pac-Man was a great video game developed by Namco in Japan back in 1979 and it was released in Europe and the US the year after. The game was an instant success, maybe because it was different from most of the other video games of the time, such as Space Invaders, Galaxy, and Asteroids, which was mainly shoot ‘em up games in which you should kill and/or destroy everything you saw (much unlike video games of today where we have 3D FPS games in which you walk around and kill/destroy everything you see… Oh, wait there isn’t that much of a difference, is there?). In Pac-Man you play this pie-chart looking character that walks around in a maze eating dots at the same time as you’re trying to avoid getting caught by one of the four colorful ghosts that are, for some reason, hunting you.
Whoops… Sorry! I got a bit nostalgic there for a moment and sort of strayed away from the topic. This blog post was supposed to be about object oriented programming and design and not about gaming. So let’s get back on track, shall we?
If you, as an OOP developer, would design the Pac-Man game today, how would you go about it? You should probably create a class for Pac-Man and another for the ghosts that hunts him. Well, they might actually be subclasses of a common character class since they do share some very basic logic such as they can’t walk through walls and other basic elements that you can think of. But they would still be 2 different classes. You might also have a Maze class that draws the actual maze and have some other logic like knowing which level you’re playing and such. The dots and power ups might also be different classes.
But the logic of the ghosts aren’t that easy. How will they go about to chase Pac-Man? They obviously need to know about his position but how do you calculate the closest path to get to him? The ghosts can’t go through a wall so you must calculate the nearest path around the maze. Doing that in every game cycle on a modern day computer is not such a big deal, but Pac-Man came out back in 1979 and the CPUs used at the time couldn’t do that and still produce a fast pacing game.
The solution Julian suggested was that maybe the ghosts in the game are like blood-hounds and Pac-Man is given away a scent as he moves around in the maze. The square in the maze Pac-Man just left gets a value that as Pac-Man moves on decreases in value until the scent has evaporated. This way the ghosts has no real knowledge about Pac-Man at all since they are just following a scent. The scent itself is now a property of the maze object and not of the ghost object. Julian called this anti-object oriented programming since the logic is not in the “real-world” object of the ghost (is that really a real-world object?). So by changing the logic of the ghost not to actually hunt Pac-Man but to follow a scent when they find it and also added some logic to the maze class, the anti-object, which you probably only used for drawing before.
I love this example since it’s an example of thinking-out-of-the-box when it comes to OOP and OOD. Instead of always trying very hard to make the classes as close to real-world objects as possible make a few changes and simplify the whole idea.
To be completely fair here, this is actually not how the AI of the ghosts in the original game was designed. If you’re interested I invite you to read the Pac-Man Dossier especially chapter 3 and chapter 4 that explains how the actual AI for the ghosts was created. But the fact that the actual design was different is beside the point. Julian showed a simple solution to a hard problem you might face when you’re doing object oriented design.