slightly optimized prediction routines

This commit is contained in:
Christian Kroll 2010-12-12 21:17:42 +00:00
parent 4ce8ac5421
commit b36bb8289e
2 changed files with 38 additions and 55 deletions

View File

@ -199,6 +199,7 @@ uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket,
assert((nRow > -4) && (nRow < pBucket->nHeight)); assert((nRow > -4) && (nRow < pBucket->nHeight));
// left and right borders // left and right borders
uint16_t const nPieceMap = tetris_piece_getBitmap(pBucket->pPiece);
uint16_t nBucketPart = 0; uint16_t nBucketPart = 0;
if (nColumn < 0) if (nColumn < 0)
{ {
@ -226,7 +227,7 @@ uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket,
{ {
uint16_t nTemp = pBucket->dump[y] & nDumpMask; uint16_t nTemp = pBucket->dump[y] & nDumpMask;
nBucketPart |= nShift >= 0 ? nTemp << nShift : nTemp >> -nShift; nBucketPart |= nShift >= 0 ? nTemp << nShift : nTemp >> -nShift;
if ((tetris_piece_getBitmap(pBucket->pPiece) & nBucketPart) != 0) if ((nPieceMap & nBucketPart) != 0)
{ {
// collision // collision
return 1; return 1;
@ -485,43 +486,32 @@ int8_t tetris_bucket_predictCompleteLines(tetris_bucket_t *pBucket,
int8_t nRow, int8_t nRow,
int8_t nColumn) int8_t nColumn)
{ {
assert(nRow > -4); assert(pBucket != NULL);
assert(pPiece != NULL);
assert(nRow > -4 && nRow < pBucket->nHeight);
assert(nColumn > -4 && nColumn < pBucket->nWidth);
// initialization
int8_t nCompleteRows = 0; int8_t nCompleteRows = 0;
uint16_t nPieceMap = tetris_piece_getBitmap(pPiece);
// bit mask of a full row int8_t nStartRow = nRow;
uint16_t nFullRow = 0xFFFF >> (16 - pBucket->nWidth); int8_t const nStopRow = (nRow + 3) >= pBucket->nHeight ?
// determine sane start and stop values for the dump's index
int8_t nStartRow = ((nRow + 3) >= pBucket->nHeight) ?
pBucket->nHeight - 1 : nRow + 3; pBucket->nHeight - 1 : nRow + 3;
int8_t nStopRow = (nRow < 0) ? 0 : nRow; if (nRow < 0)
uint16_t nPiece = tetris_piece_getBitmap(pPiece);
for (int8_t i = nStartRow; i >= nStopRow; --i)
{ {
int8_t y = i - nRow; nPieceMap >>= -nRow * 4;
nStartRow = 0;
}
// clear all bits of the piece we are not interested in and align the for (int8_t y = nStartRow; y <= nStopRow; ++y)
// rest to LSB {
uint16_t nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2); uint16_t nTemp = nPieceMap & 0x000F;
// shift the remaining content to the current column nTemp = nColumn >= 0 ? nTemp << nColumn : nTemp >> -nColumn;
if (nColumn >= 0) if ((pBucket->dump[y] ^ nTemp) == pBucket->nFullRow)
{
nPieceMap <<= nColumn;
}
else
{
nPieceMap >>= -nColumn;
}
// embed piece in dump map
uint16_t nDumpMap = pBucket->dump[i] | nPieceMap;
// is current row a full row?
if ((nFullRow & nDumpMap) == nFullRow)
{ {
++nCompleteRows; ++nCompleteRows;
} }
nPieceMap >>= 4;
} }
return nCompleteRows; return nCompleteRows;
@ -535,8 +525,6 @@ uint16_t* tetris_bucket_predictBottomRow(tetris_bucket_iterator_t *pIt,
int8_t nColumn) int8_t nColumn)
{ {
pIt->pBucket = pBucket; pIt->pBucket = pBucket;
pIt->pPiece = pPiece;
pIt->nColumn = nColumn;
pIt->nCurrentRow = pBucket->nHeight - 1; pIt->nCurrentRow = pBucket->nHeight - 1;
pIt->nRowBuffer = 0; pIt->nRowBuffer = 0;
@ -545,6 +533,14 @@ uint16_t* tetris_bucket_predictBottomRow(tetris_bucket_iterator_t *pIt,
pIt->nPieceLowestRow = ((pIt->nPieceHighestRow + 3) < pBucket->nHeight) ? pIt->nPieceLowestRow = ((pIt->nPieceHighestRow + 3) < pBucket->nHeight) ?
(pIt->nPieceHighestRow + 3) : pBucket->nHeight - 1; (pIt->nPieceHighestRow + 3) : pBucket->nHeight - 1;
// prepare piece bitmap for faster detection of complete lines
pIt->nPieceMap = tetris_piece_getBitmap(pPiece);
if ((nRow + 3) >= pBucket->nHeight)
{
pIt->nPieceMap <<= (nRow + 4 - pBucket->nHeight) * 4;
}
pIt->nShift = nColumn - 12;
// don't return any trailing rows which are empty, so we look for a stop row // don't return any trailing rows which are empty, so we look for a stop row
pIt->nStopRow = pBucket->nFirstTaintedRow < nRow ? pIt->nStopRow = pBucket->nFirstTaintedRow < nRow ?
pBucket->nFirstTaintedRow : nRow; pBucket->nFirstTaintedRow : nRow;
@ -556,32 +552,19 @@ uint16_t* tetris_bucket_predictBottomRow(tetris_bucket_iterator_t *pIt,
uint16_t* tetris_bucket_predictNextRow(tetris_bucket_iterator_t *pIt) uint16_t* tetris_bucket_predictNextRow(tetris_bucket_iterator_t *pIt)
{ {
uint16_t nPieceMap = 0;
if ((pIt->nPieceHighestRow > -4) && (pIt->nCurrentRow >= pIt->nStopRow)) if ((pIt->nPieceHighestRow > -4) && (pIt->nCurrentRow >= pIt->nStopRow))
{ {
uint16_t nPiece = tetris_piece_getBitmap(pIt->pPiece); uint16_t nTemp = 0;
// embed piece if it is there
if ((pIt->nCurrentRow <= pIt->nPieceLowestRow) && if ((pIt->nCurrentRow <= pIt->nPieceLowestRow) &&
(pIt->nCurrentRow >= pIt->nPieceHighestRow)) (pIt->nCurrentRow >= pIt->nPieceHighestRow))
{ {
int8_t y = pIt->nCurrentRow - pIt->nPieceHighestRow; uint16_t nTemp = pIt->nPieceMap & 0xF000;
nTemp |= pIt->nShift >= 0 ?
// clear all bits of the piece we are not interested in and nTemp << pIt->nShift : nTemp >> -pIt->nShift;
// align the rest to LSB pIt->nPieceMap <<= 4;
nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2);
// shift the remaining content to the current column
if (pIt->nColumn >= 0)
{
nPieceMap <<= pIt->nColumn;
}
else
{
nPieceMap >>= -pIt->nColumn;
}
} }
pIt->nCurrentRow = pIt->pBucket->dump[pIt->nCurrentRow--] | nTemp;
pIt->nRowBuffer = pIt->pBucket->dump[pIt->nCurrentRow--] | nPieceMap;
// don't return full (and therefore removed) rows // don't return full (and therefore removed) rows
if (pIt->nRowBuffer == pIt->pBucket->nFullRow) if (pIt->nRowBuffer == pIt->pBucket->nFullRow)
{ {

View File

@ -59,8 +59,8 @@ tetris_bucket_t;
typedef struct tetris_bucket_iterator_t typedef struct tetris_bucket_iterator_t
{ {
tetris_bucket_t *pBucket; /** bucket to be examined */ tetris_bucket_t *pBucket; /** bucket to be examined */
tetris_piece_t *pPiece; /** piece which should be tested */ uint16_t nPieceMap; /** piece bitmap */
int8_t nColumn; /** column where piece should be dropped */ int8_t nShift; /** helper variable for piece bitmap shifts */
int8_t nCurrentRow; /** the actual row in the bucket */ int8_t nCurrentRow; /** the actual row in the bucket */
int8_t nPieceHighestRow; /** the highest row index of the piece */ int8_t nPieceHighestRow; /** the highest row index of the piece */
int8_t nPieceLowestRow; /** the lowest row index of the piece */ int8_t nPieceLowestRow; /** the lowest row index of the piece */