ARTIFICIAL INTELLIGENCE FOR PONG
Pong was the first sports-based arcade videogame. Basically, it is a virtual version of table tennis. At the time of this project's conception, I had gone through a long period of time without touching neither Java, nor the subject of artificial intelligence. I felt like I neglected both of these long enough and that it was time to come up with a small project that will serve as practice. Making a game-engine for Pong - plus a challenging artificial player to play against - is just the kind of exercise I was looking for!
Table of contents
- Game rules
- Designing an artificial opponent
- Source code
- See also
Pong is governed by very simple rules. The virtual table is rectangular, with each player controlling a paddle on opposing sides. Let's call the sides the players occupy goals and the sides they do not walls. The ball is released in the center and bounces around upon contact with either paddles or walls. Each player's objective is to not let the ball touch its goal, since that constitutes a loss.
In all further discussion we will assume the players take the bottom/top sides of the table as their goals. Players can move their paddles left and right at constant top-speed. The ball is also moving at constant speed, and bounces off surfaces it collides with according to the following rules:
- Normally, the ball moves in constant speed in its current direction until it hits either a wall or a paddle (if it hits a goal, the game ends).
- Upon hitting a wall, the ball's movement direction is reflected across the surface normal, as if it were a ray of light bouncing off a mirror.
- Upon hitting a paddle, the ball's new direction depends on its distance from the paddle center: A hit dead on the middle results in a bounce direction that is straight-up. A hit on the edge will send the ball in a low-angled direction away.
Designing an artificial opponent
The making of the game-engine itself was not very eventful or exciting. The making of the AI, on the other hand, was a lot of fun. We started with a very simple game-plan, and iteratively identified its deficiencies and worked to amend them up to the point where the AI felt challenging enough.
The naive approach
The most elementary attempt at a virtual Pong player is a passive one. That is, a player that only cares for not losing - never mind winning. As such a player, our first thought in this direction might be that in order not to lose, we must always be there when the ball approaches our goal so we may block it. A simplistic approach to this problem would be simply tracking the ball's horizontal position at all times and moving our paddle towards it:
Unfortunately, as you can see above, this approach assumes that we can move our paddle at instant speed to any point. This of course is not true, and our strategy falls flat against a long-distance serve to the other side of the table.
Predicting the ball's position
Our naive strategy to the passive player problem acted as though the ball was about to hit our goal at any moment, even when this is obviously not the case: For example, when the ball is still a long ways away and moving in a direction that is more horizontal than vertical.
To remedy this, we take advantage of the fact that the rules that govern the ball's movement are deterministic and well-defined. Knowing the current ball position and velocity, we could look ahead into the future and compute its expected movement trajectory up until the next time it hits our goal. Then, we simply look at the position we predict it lands and move our paddle there straight away:
Already, this approach is a big improvement on our first attempt. However, as can be seen above, it is still easily exploited. The problem lies in the fact that the AI always serves the ball back with its paddle's center, which sends the ball in a purely vertical direction. A smart opponent will use this predictability to manipulate the AI into a corner, and then serve wide - where even though the AI correctly predicts the ball's position at its goal, it is too far away to block it in time.
Engaging the opponent
Clearly the passive approach is not working. A purely passive AI is too predictable and therefore too easily manipulated. A big part of this predictability stems from the fact it currently serves with its paddle's center, which sends the ball in a trajectory that is very easy for a human adversary to follow.
So if we are not always to serve with our paddle's center, how should we serve instead? What would a smart player do? An attractive answer is this: always serve so that the ball lands as further away as possible from the opponent's paddle position. To do this, we again make use of the deterministic nature of the simulation and compute the offset from our own paddle's center that will send the ball in the opposite direction of our opponent:
Much better! Playing against this AI is already quite challenging, and although the AI can still technically be exploited, such exploits requires quite the gameplay skill. All in all, we have achieved our objective of making a reasonably challenging artificial opponent for Pong.
You can view the source code and documentation on GitHub.
- The imgur album hosting the gifs on this page