// returns true if we're continuing to fall, false if we've reached bottom or bumped into another piece
        public bool CanStillFall(FallingBlocksPiece piece)
        {
            // move the piece down
            piece.Translate(FallingBlocksPiece.Direction.Down);

            // get all the rectangles for the pieces already in place
            //List<Rectangle> allRectangles = new List<Rectangle>();
            //foreach (FallingBlocksPiece tpiece in PieceList) // todo if rectangle is not visible, do not include (for efficiency reasons)
            //{
            //    allRectangles.AddRange(tpiece.TransformedRectangles[tpiece.Orientation]);
            // }

            // get all the rectangles for the current piece
            List <Rectangle> rectangleList = piece.TransformedRectangles[piece.Orientation].OfType <Rectangle>().ToList(); // convert array to list

            // if there is a collision
            //bool collision = IsCollision(allRectangles, piece.TransformedRectangles[piece.Orientation]);
            bool collision = CheckForCollision(piece /*.TransformedRectangles[piece.Orientation]*/);

            if (collision)
            {
                // move the piece back up
                piece.Translate(FallingBlocksPiece.Direction.Up);

                // check to see if the piece is at the very top and can't be moved
                var y_queryPiece = from Point p in piece.TransformedPoints[piece.Orientation] select p.Y;
                int ymax         = y_queryPiece.Max();

                if (ymax == (piece.MaxHeight[piece.Orientation] + FallingBlocksGame.XOffset))
                {
                    this.updateTimer(false); // game over
                    return(true);
                }

                return(false);
            }

            // if we got this far, there is no collision with another piece, so highest y value for this piece (bottom most coord)
            // to see if we are at bottom of screen
            var y_query = from Point p in piece.TransformedPoints[piece.Orientation] select p.Y;
            int ymax2   = y_query.Max();

            if (ymax2 < FallingBlocksGame.YMax)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        private void DropTheRow(int rowToDrop)
        {
            List <int> piecesToDrop = new List <int>(); // pieces on this row to drop

            int ycoord = (rowToDrop * FallingBlocksGame.ColumnHeight) + XOffset;

            // for every piece
            for (int pNdx = 0; pNdx < PieceList.Count; pNdx++)
            {
                FallingBlocksPiece piece = PieceList[pNdx];
                int orientation          = piece.Orientation;
                int num = piece.PieceNum;

                // for each rectangle in this piece
                for (int rndx = 0; rndx < piece.TransformedRectangles[orientation].Length; rndx++)
                {
                    Rectangle rect = piece.TransformedRectangles[orientation][rndx];

                    // if this rectangle is on the drop row
                    if (rect.Y == ycoord)
                    {
                        if (!piecesToDrop.Contains(num))
                        {
                            piecesToDrop.Add(num);
                        }
                    }
                }
            }

            for (int pNdx = 0; pNdx < PieceList.Count; pNdx++)
            {
                FallingBlocksPiece piece = PieceList[pNdx];

                // this code lifted from FillOccupied, but note how currentRow is computed differently
                int orientation = piece.Orientation;
                var y_query     = from Point p in piece.TransformedPoints[orientation] select p.Y;
                int ymax        = y_query.Max();
                int currentRow  = ((ymax - FallingBlocksGame.YOffset) / FallingBlocksGame.ColumnHeight) - 1;
                currentRow = (ymax / FallingBlocksGame.ColumnHeight) - 1;
                {
                    // if piece on or above rowToDrop
                    if ((piecesToDrop.Contains(piece.PieceNum)) || (currentRow < rowToDrop))
                    {
                        piece.Translate(FallingBlocksPiece.Direction.Down);
                    }

                    System.Threading.Thread.Sleep(DramaticPauseMS);
                    updatePaint();
                }
            }
        }
        // returns true if the character was processed by the control; otherwise, false.
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData) // http://stackoverflow.com/questions/4378865/detect-arrow-key-keydown-for-the-whole-window
        {
            if (keyData == Keys.Left)
            {
                currentPiece.Translate(FallingBlocksPiece.Direction.Left);
                if (FallingBlocksGame.CheckForCollision(currentPiece))
                {
                    currentPiece.Translate(FallingBlocksPiece.Direction.Right);
                }
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if (keyData == Keys.Right)
            {
                currentPiece.Translate(FallingBlocksPiece.Direction.Right);
                if (FallingBlocksGame.CheckForCollision(currentPiece))
                {
                    currentPiece.Translate(FallingBlocksPiece.Direction.Left);
                }
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if (keyData == Keys.Up)
            {
                currentPiece.Rotate(FallingBlocksPiece.Direction.Up);
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if (keyData == Keys.Down)
            {
                currentPiece.Rotate(FallingBlocksPiece.Direction.Down);
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if (keyData == Keys.Space)
            {
                if (currentPiece == null)
                {
                    return(true);
                }
                timerPieceDrop.Enabled = false;
                FallingBlocksGame.DropPiece(currentPiece);
                DebugPieceLocation(currentPiece);
                NextPiece();
                timerPieceDrop.Enabled = true;
                return(true);
            }
            else if (keyData == Keys.U) // moves piece up - not standard FallingBlocks, but useful during development
            {
                currentPiece.Translate(FallingBlocksPiece.Direction.UpDebug);
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if (keyData == Keys.Z) // "undo" movement of piece - not standard FallingBlocks, but useful during development
            {
                FallingBlocksGame.PieceList.RemoveAt(FallingBlocksGame.PieceList.Count - 1);
                this.pbFallingBlocks.Invalidate();
                return(true);
            }
            else if ((keyData == Keys.Escape) || (keyData == Keys.P))
            {
                if (btnPause.Text != "Start")
                {
                    btnPause_Click(null, null);
                }
                return(true);
            }

            return(base.ProcessCmdKey(ref msg, keyData));
        }