# let the piece fall if it is time to fall if time.time() - lastFallTime > fallFreq: # see if the piece has landed if not isValidPosition(board, fallingPiece, adjY=1): # falling piece has landed, set it on the board addToBoard(board, fallingPiece) score += removeCompleteLines(board) level, fallFreq = calculateLevelAndFallFreq(score) fallingPiece = None else: # piece did not land, just move the piece down fallingPiece['y'] += 1 lastFallTime = time.time()
The rate that the piece is naturally moving down (that is, falling) is tracked by the
lastFallTime variable. If enough time has elapsed since the falling piece last fell down one space, lines 4  to 13  will handle dropping the piece by one space.
If the condition on line 4  is
True, then the piece has landed. The call to
addToBoard() will make the piece part of the board data structure (so that future pieces can land on it), and the
removeCompleteLines() call will handle erasing any complete lines on the board and pulling the boxes down. The
removeCompleteLines() function also returns an integer value of how many lines were removed, so we add this number to the score.
Because the score may have changed, we call the
calculateLevelAndFallFreq() function to update the current level and frequency that the pieces fall. And finally, we set the
fallingPiece variable to
None to indicate that the next piece should become the new falling piece, and a random new piece should be generated for the new next piece. (That is done on lines 195 to 199 at the beginning of the game loop.)
If the piece has not landed, we simply set its Y position down one space (on line 12 ) and reset
lastFallTime to the current time (on line 13 ).