Why do Pinky and Inky behave differently when Pac-Man moves up?

Original author: Don Hodges
  • Transfer
In the game Pac-Man (and in many clones and sequels), it was found that the ghosts of Pinky and Inky pursue Pac-Man, determining the point to follow in the direction in which he is moving. For example, Pinky usually follows the point, which is located four units from Pac-Man´a in the direction of its movement. However, if Pac-Man moves up, this destination becomes a point four points up and four units to the left relative to Pac-Man. Ghost Inky has a similar behavior when Pac-Man moves up. Why does Pinky and Inky have different behaviors when Pac-Man moves up?

In short, in my opinion, due to a software bug. Here is the evidence.



Pac-Man encodes directions in at least two ways. One way Pac-Man writes directions using one byte with the following values: Right = 0, Down = 1, Left = 2, and Up = 3.

Another way is when Pac-Man writes directions using a two-byte pair to write a vector directions in the following way. All hexadecimal values ​​are written with the prefix #, and can be viewed in memory locations from address # 32FF to # 3306.

Right = (#FF, 00)

Down = (00, 01)

Left = (01, 00)

Up = (00, #FF)

#FF (decimal 255) is used as -1, for Z80 8-bit math. Consider an example: The



coordinates of the points (XX, YY) are given in hexadecimal notation. Let Pac-Man at point (# 26, # 2F).

The game calculates the positions of the four points surrounding the given one by adding a two-byte direction vector to the coordinates of the given point.

To calculate the position of the point to the right of Pac-Man´a, you need to add a two-byte number "Right" (# FF, 00) to (# 26, # 2F). Since FF is used as -1, we get the coordinates of the point (# 25, # 2F), which is located to the right of Pac-Man´a. To calculate the point below Pac-Man’a, you need to add the two-byte number “Down” (00.01) to (# 26, # 2F). We get (# 26, # 30), the point that is located directly below the Pac-Man´s. To calculate the position of the point to the left of Pac-Man´a, you need to add the two-byte number “Left” (01.00) to (# 26, # 2F). Get (# 27, # 2F), the point that is located to the left of Pac-Man´a. To calculate the position of a point above the Pac-Man, add the double-byte “Up” number (00, # FF) to (# 26, # 2F). Since FF is used as -1, we get the coordinates of the point (# 26, # 2E), which is located directly above the Pac-Man´s.

All this works correctly only when we work with unit coordinates separately, which is the only correct way to perform these arithmetic operations, taking into account the presence of possible negative numbers. For example, in the code at # 2000, there is a procedure that performs these actions correctly:

2000 FD7E00 LD A, (IY + # 00); load the Y coordinate into register A
2003 DD8600 ADD A, (IX + # 00); add the y-coordinate of the displacement vector
2006 6F LD L, A; save result to L
2007 FD7E01 LD A, (IY + # 01); load X coordinate into register A
200A DD8601 ADD A, (IX + # 01); add the x-coordinate of the displacement vector
200 D 67 LD H, A; save result in H
200E C9 RET; return


This procedure is used to load a new position in a two-byte register pair HL at a given initial position specified in register IY and a direction vector specified in register IX. It works correctly because the addition of the X and Y coordinates is done separately.

The problem occurs when the game tries to calculate, for example, the target point for Pinky. The game code defines Pinky's goal as a point four points from Pac-Man’s, relative to the direction of his movement.

To calculate this point, the code takes the direction vector of Pac-Man and adds it to itself, thereby doubling it. Then he doubles the result, getting a value four times greater than the original.The problem is that the X and Y coordinates do not add up separately, they add up at the same time. A bug occurs when the Up vector is computed. Here is an excerpt from Pac-Man’s assembler code for the Z80, the code that contains the code is highlighted:

; Pac-Man Pinky targeting subroutine
278E ED5B394D LD DE, (# 4D39); load in position Pac-Man´a in DE
2792 2A1C4D LD HL, (# 4D1C); upload to HL Pac-Man’s direction vector
2795 29 ADD HL, HL; [bug !!!] double the Pac-Man’s direction vector
2796 29 ADD HL, HL; [bug !!!] quadruple the Pac-Man’s direction vector
2797 19 ADD HL, DE; [bug !!!] add result to position to get target point


The following table will show the results of this procedure (relative to Pac-Man’s zero position):
Vector nameThe initial value of HL and the result2xHL and result4xHL and result
To the right# FF00 (-1.0)# FE00 (-2.0)# FC00 (-4.0)
Way down# 0001 (0,1)# 0002 (0.2)# 0004 (0.4)
To the left# 0100 (1,0)# 0200 (2,0)# 0400 (4.0)
Up# 00FF (1, -1)# 01FE (2, -2)# 03FC (4, -4)


HL is a two-byte register pair of Z80. On line # 2792, the X coordinate of the vector is loaded into H, the Y coordinate of the vector is loaded into L.

When the vector for the Right direction is being processed, HL contains # FF00. The instruction in line # 2792 adds this value by itself, after which register pair HL contains # FE00, and the transfer flag is set, due to the overflow of register H. But the program ignores the transfer flag and uses only a numerical value, which is interpreted as -2 . When doubling occurs on line # 2796, the value # FC00 appears in HL, which is the correct value of -4. The carry flag is ignored. When an addition occurs with the position of Pac-Man, the transfer flag is set again as a result of the transfer, which, in other matters, is again ignored by the program. The desired result is achieved: the new point is located in 4 units to the right of Pac-Man´a.

Bug in action



However, when the vector for the Up direction is used, on line # 2792, # 00FF is loaded into the register pair HL. When doubling occurs on the next line, HL contains # 01FE. Instead of discarding the overflow flag, as happened when processing the vector for the “Right” direction, doubling the Y coordinate leads to overflow with the transfer flag being transferred to the X coordinate. This leads to damage to the vector, since the vector shifts not only up, but also to the left. The next doubling gives the value # 03FC, which, when added to Pac-Man’s coordinates, results in a new point 4 points up and to the left.



I believe this is a bug, and it is not intentional, because the same command is used for all four directions. In other words,the code does not start a separate procedure for processing the "Up" direction, however, for the "Up" direction, the procedure gives an unexpected, different result from other directions . Given the low-level nature of the problem, I doubt that programmers were aware of this. If they knew this, then they apparently ignored this problem. Nevertheless, I doubt that they would leave this bug if they knew about it.

Also popular now: