Browse Source

slightly optimized prediction routines

feature/2015
Christian Kroll 14 years ago
parent
commit
b36bb8289e
  1. 87
      games/tetris/bucket.c
  2. 4
      games/tetris/bucket.h

87
games/tetris/bucket.c

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

4
games/tetris/bucket.h

@ -59,8 +59,8 @@ tetris_bucket_t;
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 nPieceMap; /** piece bitmap */
int8_t nShift; /** helper variable for piece bitmap shifts */
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 */

Loading…
Cancel
Save