def isOnBoard(x, y): return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT def isValidPosition(board, piece, adjX=0, adjY=0): # Return True if the piece is within the board and not colliding for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): isAboveBoard = y + piece['y'] + adjY < 0 if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK: continue if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY): return False if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK: return False return True
isOnBoard() is a simple function which checks that the XY coordinates that are passed represent valid values that exist on the board. As long as both the XY coordinates are not less
0 or greater than or equal to the
BOARDHEIGHT constants, then the function returns
isValidPosition() function is given a board data structure and a piece data structure, and returns
True if all the boxes in the piece are both on the board and not overlapping any boxes on the board. This is done by taking the piece’s XY coordinates (which is really the coordinate of the upper right box on the 5x5 boxes for the piece) and adding the coordinate inside the piece data structure. Here’s a couple pictures to help illustrate this:
On the left board, the falling piece’s (that is, the top left corner of the falling piece’s) XY coordinates are \( (2, 3) \) on the board. But the boxes inside the falling piece’s coordinate system have their own coordinates. To find the "board" coordinates of these pieces, we just have to add the "board" coordinates of the falling piece’s top left box and the "piece" coordinates of the boxes.
On the left board, the falling piece’s boxes are at the following "piece" coordinates:
\[ (2, 2), (3, 2), (1, 3), (2, 3) \nonumber \]
When we add the \( (2, 3) \) coordinate (the piece’s coordinates on the board) to these coordinates, it looks like this:
\[ (2 + 2, 2 + 3), (3 + 2, 2 + 3), (1 + 2, 3 + 3), (2 + 2, 3 + 3) \nonumber \]
After adding the \( (2, 3) \) coordinate the boxes are at the following "board" coordinates:
\[ (4, 5), (5, 5), (3, 6), (4, 6) \nonumber \]
And now that we can figure out where the falling piece’s boxes are as board coordinates, we can see if they overlap with the landed boxes that are already on the board. The nested
for loops on lines 7  and 8  go through each of the possible coordinates on the falling piece.
We want to check if a box of the falling piece is either off of the board or overlapping a box on the board. (Although one exception is if the box is above the board, which is where it could be when the falling piece just begins falling.) Line 9  creates a variable named
isAboveBoard that is set to
True if the box on the falling piece at the coordinates pointed to be x and y is above the board. Otherwise it is set to
if statement on line 10  checks if the space on the piece is above the board or is blank. If either of those is
True, then the code executes a continue statement and goes to the next iteration. (Note that the end of line 10  has
[y][x] instead of
[x][y]. This is because the coordinates in the
PIECES data structure are reversed. See the previous section, "Setting Up the Piece Templates").
if statement on line 12  checks that the piece’s box is not located on the board. The
if statement on line 14  checks that the board space the piece’s box is located is not blank. If either of these conditions are
True, then the
isValidPosition() function will return
False. Notice that these
if statements also adjust the coordinates for the
adjY parameters that were passed in to the function.
If the code goes through the nested
for loop and hasn’t found a reason to return
False, then the position of the piece must be valid and so the function returns
True on line 16 .