In this step, we have our falling piece respond to 
	left-arrow, right-arrow, and down-arrow key presses by moving in the given 
	direction.  Also, for testing purposes, we will add temporary code that 
	changes the falling piece whenever any other key is pressed.  This code 
	will be removed after this step.
 
Actually, we only want to move in a given direction if it is 
	legal to do so.  There are two reasons why it may not be legal:  
	the falling piece may wind up off of the board, or a part of the falling 
	piece may collide with a non-empty cell on the board.  In either case, 
	we should not move the falling piece.  Among other consequences, this 
	means that for now, once pieces reach the bottom of the board, we will not 
	be able to move them any lower, yet we will not place them on the board.  
	That comes later.  For now, the piece will stay there until we use the 
	temporary test code to change the falling piece (which also places the new 
	falling piece back at the top-center of the board).
 
One approach would be to test if a move is legal first, and 
	if it is, then make the move.  That approach requires different code, 
	however, to test for each type of move we might make (left, right, down, 
	and, eventually, rotation), which is unnecessarily complicated.  An 
	easier approach is to blindly make the move, then test if the result 
	of the move is legal.  If it is not legal, then unmake the move.  
	In this way, a single legal move test can be used for any sort of move.  We will use this move-test-unmove design.
 
Explaining moveFallingPiece:
	Next, we will write a function that will move the falling piece a given 
	number of rows and columns:
	 def moveFallingPiece(canvas, drow, dcol)
	We use "drow" to signify a change in rows (the "d" in "drow" stands 
	for the mathematical symbol "delta", meaning change).  
	Similarly, "dcol" is the change in columns.  Consider:  a 
	move to the left would change our column by -1 (since columns go down 
	to the left), and keep our row constant.  Thus, with this function, we 
	can move to the left by calling moveFallingPiece(canvas,0,-1).  Similarly, we 
	can move to the right with moveFallingPiece(canvas,0,+1).  And to move down, 
	we hold our column constant and add one to our row:  
	moveFallingPiece(canvas,+1,0).
 
Writing moveFallingPiece:
	As noted above, we proceed in three steps.  First, we simply make the 
	move by modifying the canvas's data values storing the location of the 
	left-top corner of the falling piece.  Next, we test if this new location of the falling piece is legal.  
	We do this using top-down design, so we assume the function 
	fallingPieceIsLegal exists at this point, and we'll actually write it in a 
	moment.  If the new location is not legal (because it was off the board 
	or because it collided with a non-empty cell on the board), then we undo the 
	move we just made, by resetting the canvas's data values to their original 
	values prior to the call to moveFallingPiece.
 
Explaining fallingPieceIsLegal:
	This function is similar to drawFallingPiece.  It iterates over every 
	cell (every row and every column) in the fallingPiece, and for those cells which are part of the 
	falling piece (that is, where the falling piece list has a True value), 
	rather than draw the cell (as drawFallingPiece does), this method confirms 
	that:  (1) the cell is in fact on the board; and (2) the color at that 
	location on the board is the emptyColor.  If either of these checks 
	fails, the function immediately returns False.  If all the checks succeed 
	for every cell in the fallingPiece, the function returns True.
 
Writing keyPressed:
We modify the keyPressed handler to call moveFallingPiece 
	to move left, right, or down in response to left-arrow, right-arrow, or 
	down-arrow key presses (and to change the falling piece in response to any 
	other key press for now).
| David Kosbie |