// The following counts the number of cells (0..4) of a piece that would
        // be eliminated by dropping the piece.
        public int CountPieceCellsEliminated
        (
            STPiece piece
        )
        {
            if (null == this.mCells)
            {
                return(0);
            }

            if (false == piece.IsValid( ))
            {
                return(0);
            }

            // Copy piece and board so that this measurement is not destructive.
            STBoard copyOfBoard = new STBoard();

            copyOfBoard.CopyFrom(this);

            STPiece copyOfPiece = new STPiece();

            copyOfPiece.CopyFrom(piece);


            // Drop copy of piece on to the copy of the board
            copyOfBoard.FullDropAndCommitPieceToBoard(copyOfPiece);


            // Scan rows.  For each full row, check all board Y values for the
            // piece.  If any board Y of the piece matches the full row Y,
            // increment the total eliminated cells.
            int pieceCellsEliminated = 0;


            int width  = 0;
            int height = 0;

            width  = copyOfBoard.GetWidth( );
            height = copyOfBoard.GetHeight( );

            int y = 0;

            for (y = 1; y <= height; y++)
            {
                bool fullRow = false;
                fullRow = true; // hypothesis

                int x = 0;
                for (x = 1; ((x <= width) && (true == fullRow)); x++)
                {
                    byte cellValue = (byte)0;
                    cellValue = copyOfBoard.GetCell(x, y);
                    if ((byte)0 == cellValue)
                    {
                        fullRow = false;
                    }
                }

                if (true == fullRow)
                {
                    // Find any matching board-relative Y values in dropped copy of piece.
                    int totalCells = 0;
                    totalCells = piece.GetTotalCells( );

                    int cellIndex = 0;
                    for (cellIndex = 1; cellIndex <= totalCells; cellIndex++)
                    {
                        int boardX = 0;
                        int boardY = 0;
                        copyOfPiece.GetTranslatedCellXY(cellIndex, ref boardX, ref boardY);
                        if (boardY == y)
                        {
                            pieceCellsEliminated++;  // Moohahahaaa!
                        }
                    }
                }
            }

            return(pieceCellsEliminated);
        }
        public void DetermineAccessibleTranslationsForPieceOrientation
        (
            STPiece piece,
            ref bool movePossible, // false == no moves possible
            ref int minDeltaX,     // displacement to left-most limit
            ref int maxDeltaX      // displacement to right-most limit
        )
        {
            movePossible = false; // false == no moves possible
            minDeltaX    = 0;     // displacement to left-most limit
            maxDeltaX    = 0;     // displacement to right-most limit


            if (null == this.mCells)
            {
                return;
            }

            if (false == piece.IsValid())
            {
                return;
            }


            // Get dimensions of board
            int width = 0;

            width = this.GetWidth();
            // int height = 0;
            // height = this.GetHeight();


            STPiece tempPiece             = new STPiece();
            bool    moveAcceptable        = false;
            int     trialTranslationDelta = 0;


            // Check if we can move at all.
            moveAcceptable =
                this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(piece);
            if (true == moveAcceptable)
            {
                movePossible = true;
            }
            else
            {
                return;
            }


            // Scan from center to left to find left limit.
            bool stillAcceptable = true;

            for
            (
                trialTranslationDelta = 0;
                ((trialTranslationDelta >= (-(width))) && (true == stillAcceptable));
                trialTranslationDelta--
            )
            {
                // Copy piece to temp and translate
                tempPiece.CopyFrom(piece);
                tempPiece.Translate(trialTranslationDelta, 0);

                moveAcceptable =
                    this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece);

                if (true == moveAcceptable)
                {
                    minDeltaX = trialTranslationDelta;
                }
                else
                {
                    stillAcceptable = false;
                }
            }


            // Scan from center to right to find right limit.
            stillAcceptable = true;
            for
            (
                trialTranslationDelta = 0;
                ((trialTranslationDelta <= width) && (true == stillAcceptable));
                trialTranslationDelta++
            )
            {
                // Copy piece to temp and translate
                tempPiece.CopyFrom(piece);
                tempPiece.Translate(trialTranslationDelta, 0);

                moveAcceptable =
                    this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece);

                if (true == moveAcceptable)
                {
                    maxDeltaX = trialTranslationDelta;
                }
                else
                {
                    stillAcceptable = false;
                }
            }
        }
        public void DropPieceAsFarAsPossibleButDoNotModifyBoard
        (
            STPiece piece
        )
        {
            if (null == this.mCells)
            {
                return;
            }

            if (false == piece.IsValid( ))
            {
                return;
            }


            // Special case: cannot place piece at starting location.
            bool goalAcceptable = false;

            goalAcceptable =
                this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(piece);

            if (false == goalAcceptable)
            {
                // cannot drop piece at all
                return;
            }



            // Try successively larger drop distances, up to the point of failure.
            // The last successful drop distance becomes our drop distance.
            int  boardHeight = 0;
            int  lastSuccessfulDropDistance = 0;
            bool firstFailureEncountered    = false;
            int  trialDropDistance          = 0;

            boardHeight = this.GetHeight();

            STPiece tempPiece = new STPiece();

            tempPiece.CopyFrom(piece);

            for
            (
                trialDropDistance = 0;
                ((false == firstFailureEncountered) && (trialDropDistance <= boardHeight));
                trialDropDistance++
            )
            {
                // Set temporary piece to new trial Y
                tempPiece.SetY(piece.GetY( ) - trialDropDistance);

                goalAcceptable =
                    this.DetermineIfPieceIsWithinBoardAndDoesNotOverlapOccupiedCells(tempPiece);

                if (false == goalAcceptable)
                {
                    // We failed to drop this far.  Stop drop search.
                    firstFailureEncountered = true;
                }
                else
                {
                    lastSuccessfulDropDistance = trialDropDistance;
                }
            }

            // Simply update the piece Y value.
            piece.SetY(piece.GetY( ) - lastSuccessfulDropDistance);
        }