added functions which predict the outcome of a piece drop
This commit is contained in:
parent
072964dc6d
commit
326585e5ac
|
@ -119,6 +119,26 @@ void tetris_playfield_reset(tetris_playfield_t *pPl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int8_t tetris_playfield_getPieceStartPos(tetris_piece_t *pPiece)
|
||||||
|
{
|
||||||
|
// set vertical start position (first piece row with matter at pos. 1)
|
||||||
|
uint16_t nPieceMap = tetris_piece_getBitmap(pPiece);
|
||||||
|
uint16_t nElementMask = 0xF000;
|
||||||
|
int8_t nRow = -3;
|
||||||
|
while ((nPieceMap & nElementMask) == 0)
|
||||||
|
{
|
||||||
|
++nRow;
|
||||||
|
nElementMask >>= 4;
|
||||||
|
}
|
||||||
|
if (nRow < 0)
|
||||||
|
{
|
||||||
|
++nRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Function: tetris_playfield_insertPiece
|
/* Function: tetris_playfield_insertPiece
|
||||||
* Description: inserts a new piece
|
* Description: inserts a new piece
|
||||||
* Argument pPl: playfield to perform action on
|
* Argument pPl: playfield to perform action on
|
||||||
|
@ -146,18 +166,7 @@ void tetris_playfield_insertPiece(tetris_playfield_t *pPl,
|
||||||
pPl->nColumn = (pPl->nWidth - 2) / 2;
|
pPl->nColumn = (pPl->nWidth - 2) / 2;
|
||||||
|
|
||||||
// set vertical start position (first piece row with matter at pos. 1)
|
// set vertical start position (first piece row with matter at pos. 1)
|
||||||
uint16_t nPieceMap = tetris_piece_getBitmap(pPl->pPiece);
|
pPl->nRow = tetris_playfield_getPieceStartPos(pPl->pPiece);
|
||||||
uint16_t nElementMask = 0xF000;
|
|
||||||
pPl->nRow = -3;
|
|
||||||
while ((nPieceMap & nElementMask) == 0)
|
|
||||||
{
|
|
||||||
++pPl->nRow;
|
|
||||||
nElementMask >>= 4;
|
|
||||||
}
|
|
||||||
if (pPl->nRow < 0)
|
|
||||||
{
|
|
||||||
++pPl->nRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// did we already collide with something?
|
// did we already collide with something?
|
||||||
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) == 1)
|
if (tetris_playfield_collision(pPl, pPl->nColumn, pPl->nRow) == 1)
|
||||||
|
@ -593,3 +602,142 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
|
||||||
return pPl->dump[nRow];
|
return pPl->dump[nRow];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Function: tetris_playfield_predictDeepestRow
|
||||||
|
* Description: returns the deepest possible row of a given piece
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Return value: the row of the piece (playfield compliant coordinates)
|
||||||
|
*/
|
||||||
|
int8_t tetris_playfield_predictDeepestRow(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn)
|
||||||
|
{
|
||||||
|
int8_t nRow = tetris_playfield_getPieceStartPos(pPiece);
|
||||||
|
tetris_piece_t *pActualPiece = pPl->pPiece;
|
||||||
|
pPl->pPiece = pPiece;
|
||||||
|
|
||||||
|
// is it actually possible to use this piece?
|
||||||
|
if (tetris_playfield_collision(pPl, (pPl->nWidth - 2) / 2, nRow) ||
|
||||||
|
(tetris_playfield_collision(pPl, nColumn, nRow)))
|
||||||
|
{
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine deepest row
|
||||||
|
while ((nRow < pPl->nHeight) &&
|
||||||
|
(!tetris_playfield_collision(pPl, nColumn, nRow + 1)))
|
||||||
|
{
|
||||||
|
++nRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore real piece
|
||||||
|
pPl->pPiece = pActualPiece;
|
||||||
|
|
||||||
|
return nRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function: tetris_playfield_predictCompleteLines
|
||||||
|
* Description: predicts the number of complete lines for a piece at
|
||||||
|
* a given column
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Return value: amount of complete lines
|
||||||
|
*/
|
||||||
|
int8_t tetris_playfield_predictCompleteLines(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn)
|
||||||
|
{
|
||||||
|
int8_t nCompleteRows = 0;
|
||||||
|
|
||||||
|
// bit mask of a full row
|
||||||
|
uint16_t nFullRow = 0xFFFF >> (16 - pPl->nWidth);
|
||||||
|
|
||||||
|
int8_t nRow = tetris_playfield_predictDeepestRow(pPl, pPiece, nColumn);
|
||||||
|
if (nRow > -4)
|
||||||
|
{
|
||||||
|
// determine sane start and stop values for the dump's index
|
||||||
|
int8_t nStartRow =
|
||||||
|
((nRow + 3) >= pPl->nHeight) ? pPl->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
|
||||||
|
{
|
||||||
|
nPieceMap >>= -nColumn;
|
||||||
|
}
|
||||||
|
// embed piece in dump map
|
||||||
|
uint16_t nDumpMap = pPl->dump[i] | nPieceMap;
|
||||||
|
|
||||||
|
// is current row a full row?
|
||||||
|
if ((nFullRow & nDumpMap) == nFullRow)
|
||||||
|
{
|
||||||
|
++nCompleteRows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nCompleteRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function: tetris_playfield_predictDumpRow
|
||||||
|
* Description: predicts the appearance of a playfield row for a piece
|
||||||
|
* at a given column
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Argument nRow: the row of interest
|
||||||
|
* Return value: amount of complete lines
|
||||||
|
*/
|
||||||
|
uint16_t tetris_playfield_predictDumpRow(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn,
|
||||||
|
int8_t nRow)
|
||||||
|
{
|
||||||
|
int8_t nPieceRow = tetris_playfield_predictDeepestRow(pPl, pPiece, nColumn);
|
||||||
|
uint16_t nPieceMap = 0;
|
||||||
|
|
||||||
|
if (nPieceRow > -4)
|
||||||
|
{
|
||||||
|
// determine sane start and stop values for the piece's indices
|
||||||
|
int8_t nStartRow = ((nPieceRow + 3) < pPl->nHeight) ?
|
||||||
|
(nPieceRow + 3) : pPl->nHeight - 1;
|
||||||
|
|
||||||
|
uint16_t nPiece = tetris_piece_getBitmap(pPiece);
|
||||||
|
|
||||||
|
if ((nRow <= nStartRow) && (nRow >= nPieceRow))
|
||||||
|
{
|
||||||
|
int8_t y = nRow - nPieceRow;
|
||||||
|
|
||||||
|
// 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 (nColumn >= 0)
|
||||||
|
{
|
||||||
|
nPieceMap <<= nColumn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nPieceMap >>= -nColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pPl->dump[nRow] | nPieceMap;
|
||||||
|
}
|
||||||
|
|
|
@ -209,5 +209,43 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
|
||||||
int8_t nRow);
|
int8_t nRow);
|
||||||
|
|
||||||
|
|
||||||
#endif /*TETRIS_PLAYFIELD_H_*/
|
/* Function: tetris_playfield_predictDeepestRow
|
||||||
|
* Description: returns the deepest possible row of a given piece
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Return value: the row of the piece (playfield compliant coordinates)
|
||||||
|
*/
|
||||||
|
int8_t tetris_playfield_predictDeepestRow(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn);
|
||||||
|
|
||||||
|
|
||||||
|
/* Function: tetris_playfield_predictCompleteLines
|
||||||
|
* Description: predicts the number of complete lines for a piece at
|
||||||
|
* a given column
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Return value: amount of complete lines
|
||||||
|
*/
|
||||||
|
int8_t tetris_playfield_predictCompleteLines(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn);
|
||||||
|
|
||||||
|
|
||||||
|
/* Function: tetris_playfield_predictDumpRow
|
||||||
|
* Description: predicts the appearance of a playfield row for a piece
|
||||||
|
* at a given column
|
||||||
|
* Argument pPl: the playfield on which we want to test a piece
|
||||||
|
* Argument pPiece: the piece which should be tested
|
||||||
|
* Argument nColumn: the column where the piece should be dropped
|
||||||
|
* Argument nRow: the row of interest
|
||||||
|
* Return value: amount of complete lines
|
||||||
|
*/
|
||||||
|
uint16_t tetris_playfield_predictDumpRow(tetris_playfield_t *pPl,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn,
|
||||||
|
int8_t nRow);
|
||||||
|
|
||||||
|
#endif /*TETRIS_PLAYFIELD_H_*/
|
||||||
|
|
Loading…
Reference in New Issue