diff --git a/games/tetris/bucket.c b/games/tetris/bucket.c index f002094..99536c7 100644 --- a/games/tetris/bucket.c +++ b/games/tetris/bucket.c @@ -55,9 +55,12 @@ tetris_bucket_t *tetris_bucket_construct(int8_t nWidth, if (pBucket->dump != NULL) { // setting requested attributes - pBucket->nFirstMatterRow = nHeight - 1; + pBucket->nFirstTaintedRow = nHeight; pBucket->nWidth = nWidth; pBucket->nHeight = nHeight; + // bit mask of a full row + pBucket->nFullRow = 0xFFFF >> (16 - pBucket->nWidth); + tetris_bucket_reset(pBucket); return pBucket; @@ -290,8 +293,8 @@ void tetris_bucket_advancePiece(tetris_bucket_t *pBucket) break; } } - pBucket->nFirstMatterRow = (pBucket->nFirstMatterRow > nPieceRow) ? - nPieceRow : pBucket->nFirstMatterRow; + pBucket->nFirstTaintedRow = (pBucket->nFirstTaintedRow > nPieceRow) ? + nPieceRow : pBucket->nFirstTaintedRow; // the piece has finally been docked pBucket->status = TETRIS_BUS_DOCKED; @@ -374,144 +377,53 @@ void tetris_bucket_removeCompleteLines(tetris_bucket_t *pBucket) // rows can only be removed if we are in state TETRIS_BUS_DOCKED assert(pBucket->status == TETRIS_BUS_DOCKED); - // bit mask of a full row - uint16_t nFullRow = 0xFFFF >> (16 - pBucket->nWidth); - // bit mask (only 4 bits) that tells us if the n-th row after the // current nRow is complete (n-th bit set to 1, LSB represents nRow itself) - uint8_t nRowMask = 0; - - // determine sane start and stop values for the dump' index - int8_t nStartRow = ((pBucket->nRow + 3) >= pBucket->nHeight) ? - pBucket->nHeight - 1 : pBucket->nRow + 3; - int8_t nStopRow = (pBucket->nRow < 0) ? 0 : pBucket->nRow; + pBucket->nRowMask = 0; - // dump index variables - // for incomplete rows, both variables will be decremented + // only consider rows which are affected by the piece (from low to high) + // for incomplete rows, both i and nShiftIndex will be decremented // for complete rows, only i gets decremented - int8_t nLowestRow = nStartRow; - - // save old value for the first dump index with matter - int8_t nFormerFirstMatterRow = pBucket->nFirstMatterRow; - - // this loop only considers rows which are affected by the piece - for (int8_t i = nStartRow; i >= nStopRow; --i) + int8_t nLowestRow = (pBucket->nRow + 3) < pBucket->nHeight ? + pBucket->nRow + 3 : pBucket->nHeight - 1; + int8_t nShiftIndex = nLowestRow; + for (int8_t i = nLowestRow; i >= pBucket->nFirstTaintedRow; --i) { // is current row a full row? - if ((nFullRow & pBucket->dump[i]) == nFullRow) + if ((pBucket->nFullRow & pBucket->dump[i]) == pBucket->nFullRow) { - // adjust value for the highest row with matter - pBucket->nFirstMatterRow++; - // set corresponding bit for the row mask - // nRowMask |= 0x08 >> (nStartRow - i); - nRowMask |= 0x01 << (i - pBucket->nRow); + pBucket->nRowMask |= 0x01 << (i - pBucket->nRow); } else { - // if nLowestRow and i differ, the dump has to be shifted - if (i < nLowestRow) + // if nShiftIndex and i differ, the dump has to be shifted + if (i < nShiftIndex) + { + pBucket->dump[nShiftIndex] = pBucket->dump[i]; + } + // if there were no completed lines within the range covered by the + // piece, we don't need to look for those any further + else if ((nLowestRow - i) >= 3) { - pBucket->dump[nLowestRow] = pBucket->dump[i]; + break; } - --nLowestRow; + --nShiftIndex; } } - - // if rows have been removed, this loop shifts the rest of the dump - uint8_t nComplete = nLowestRow - nStopRow + 1; - if (nComplete > 0) + // any completed rows removed? + if (pBucket->nRowMask != 0) { - for (int8_t i = nStopRow - 1; nLowestRow >= nFormerFirstMatterRow; --i) + // clear space from which the rows have been shifted away + for (int8_t i = nShiftIndex; i >= pBucket->nFirstTaintedRow; --i) { - // is the row we are copying from below the upper border? - if (i >= nFormerFirstMatterRow) - { - // just copy from that row - pBucket->dump[nLowestRow] = pBucket->dump[i]; - } - else - { - // rows above the upper border are always empty - pBucket->dump[nLowestRow] = 0; - } - --nLowestRow; + pBucket->dump[i] = 0; } + pBucket->nFirstTaintedRow = nShiftIndex + 1; } // ready to get the next piece pBucket->status = TETRIS_BUS_READY; - - pBucket->nRowMask = nRowMask; -} - - -/***************** - * get functions * - *****************/ - -int8_t tetris_bucket_getWidth(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nWidth; -} - - -int8_t tetris_bucket_getHeight(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nHeight; -} - - -tetris_piece_t *tetris_bucket_getPiece(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->pPiece; -} - - -int8_t tetris_bucket_getColumn(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nColumn; -} - - -int8_t tetris_bucket_getRow(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nRow; -} - - -int8_t tetris_bucket_getFirstMatterRow(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nFirstMatterRow; -} - - -uint8_t tetris_bucket_getRowMask(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->nRowMask; -} - - -tetris_bucket_status_t tetris_bucket_getStatus(tetris_bucket_t *pBucket) -{ - assert(pBucket != NULL); - return pBucket->status; -} - - -uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket, - int8_t nRow) -{ - assert(pBucket != NULL); - assert((0 <= nRow) && (nRow < pBucket->nHeight)); - return pBucket->dump[nRow]; } @@ -625,7 +537,6 @@ uint16_t* tetris_bucket_predictBottomRow(tetris_bucket_iterator_t *pIt, pIt->pBucket = pBucket; pIt->pPiece = pPiece; pIt->nColumn = nColumn; - pIt->nFullRow = 0xFFFF >> (16 - pBucket->nWidth); pIt->nCurrentRow = pBucket->nHeight - 1; pIt->nRowBuffer = 0; @@ -635,8 +546,8 @@ uint16_t* tetris_bucket_predictBottomRow(tetris_bucket_iterator_t *pIt, (pIt->nPieceHighestRow + 3) : pBucket->nHeight - 1; // don't return any trailing rows which are empty, so we look for a stop row - pIt->nStopRow = pBucket->nFirstMatterRow < nRow ? - pBucket->nFirstMatterRow : nRow; + pIt->nStopRow = pBucket->nFirstTaintedRow < nRow ? + pBucket->nFirstTaintedRow : nRow; pIt->nStopRow = pIt->nStopRow < 0 ? 0 : pIt->nStopRow; return tetris_bucket_predictNextRow(pIt); @@ -672,7 +583,7 @@ uint16_t* tetris_bucket_predictNextRow(tetris_bucket_iterator_t *pIt) pIt->nRowBuffer = pIt->pBucket->dump[pIt->nCurrentRow--] | nPieceMap; // don't return full (and therefore removed) rows - if (pIt->nRowBuffer == pIt->nFullRow) + if (pIt->nRowBuffer == pIt->pBucket->nFullRow) { // recursively determine next (?) row instead return tetris_bucket_predictNextRow(pIt); diff --git a/games/tetris/bucket.h b/games/tetris/bucket.h index c306f0d..51a0365 100644 --- a/games/tetris/bucket.h +++ b/games/tetris/bucket.h @@ -48,7 +48,8 @@ typedef struct tetris_bucket_t int8_t nRow; /** vert. piece pos. (0 is top) */ uint8_t nRowMask; /** removed lines relative to nRow */ tetris_bucket_status_t status; /** status of the bucket */ - int8_t nFirstMatterRow; /** top most row which has matter */ + int8_t nFirstTaintedRow; /** top most row which has matter */ + uint16_t nFullRow; /** value of a full row */ uint16_t *dump; /** bucket itself */ } tetris_bucket_t; @@ -60,7 +61,6 @@ typedef struct tetris_bucket_iterator_t tetris_bucket_t *pBucket; /** bucket to be examined */ tetris_piece_t *pPiece; /** piece which should be tested */ int8_t nColumn; /** column where piece should be dropped */ - uint16_t nFullRow; /** value of a full row */ int8_t nCurrentRow; /** the actual row in the bucket */ int8_t nPieceHighestRow; /** the highest row index of the piece */ int8_t nPieceLowestRow; /** the lowest row index of the piece */ @@ -177,7 +177,11 @@ void tetris_bucket_removeCompleteLines(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return width of the bucket */ -int8_t tetris_bucket_getWidth(tetris_bucket_t *pBucket); +inline static int8_t tetris_bucket_getWidth(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nWidth; +} /** @@ -185,7 +189,11 @@ int8_t tetris_bucket_getWidth(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return height of the bucket */ -int8_t tetris_bucket_getHeight(tetris_bucket_t *pBucket); +inline static int8_t tetris_bucket_getHeight(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nHeight; +} /** @@ -193,7 +201,11 @@ int8_t tetris_bucket_getHeight(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return pointer to the currently falling piece */ -tetris_piece_t *tetris_bucket_getPiece(tetris_bucket_t *pBucket); +inline static tetris_piece_t *tetris_bucket_getPiece(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->pPiece; +} /** @@ -201,7 +213,11 @@ tetris_piece_t *tetris_bucket_getPiece(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return column of the currently falling piece */ -int8_t tetris_bucket_getColumn(tetris_bucket_t *pBucket); +inline static int8_t tetris_bucket_getColumn(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nColumn; +} /** @@ -209,7 +225,11 @@ int8_t tetris_bucket_getColumn(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return row of the currently falling piece */ -int8_t tetris_bucket_getRow(tetris_bucket_t *pBucket); +inline static int8_t tetris_bucket_getRow(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nRow; +} /** @@ -217,7 +237,11 @@ int8_t tetris_bucket_getRow(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return highest row with matter */ -int8_t tetris_bucket_getFirstMatterRow(tetris_bucket_t *pBucket); +inline static int8_t tetris_bucket_getFirstTaintedRow(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nFirstTaintedRow; +} /** @@ -225,7 +249,11 @@ int8_t tetris_bucket_getFirstMatterRow(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return bit mask of removed lines (relative to current position) */ -uint8_t tetris_bucket_getRowMask(tetris_bucket_t *pBucket); +inline static uint8_t tetris_bucket_getRowMask(tetris_bucket_t *pBucket) +{ + assert(pBucket != NULL); + return pBucket->nRowMask; +} /** @@ -233,7 +261,11 @@ uint8_t tetris_bucket_getRowMask(tetris_bucket_t *pBucket); * @param pBucket the bucket we want information from * @return status of the bucket (see tetris_bucket_status_t) */ -tetris_bucket_status_t tetris_bucket_getStatus(tetris_bucket_t *pBucket); +inline static tetris_bucket_status_t tetris_bucket_getStatus(tetris_bucket_t *p) +{ + assert(p != NULL); + return p->status; +} /** @@ -242,8 +274,13 @@ tetris_bucket_status_t tetris_bucket_getStatus(tetris_bucket_t *pBucket); * @param nRow the number of the row (0 <= nRow <= 124) * @return bitmap of the requested row (LSB is leftmost column) */ -uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket, - int8_t nRow); +inline static uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket, + int8_t nRow) +{ + assert(pBucket != NULL); + assert((0 <= nRow) && (nRow < pBucket->nHeight)); + return pBucket->dump[nRow]; +} #ifdef GAME_BASTET