diff --git a/games/tetris/playfield.c b/games/tetris/playfield.c index e8467d6..8e19cac 100644 --- a/games/tetris/playfield.c +++ b/games/tetris/playfield.c @@ -2,8 +2,10 @@ #include #include #include +#include "stdio.h" #include "playfield.h" #include "piece.h" +#include "bast.h" /*************************** @@ -35,7 +37,7 @@ tetris_playfield_status_t tetris_playfield_hoverStatus(tetris_playfield_t* pPl) ****************************/ /* Function: tetris_playfield_construct - * Description: constructs a playfield with the given diemensions + * Description: constructs a playfield with the given dimensions * Argument nWidth: width of playfield (4 <= n <= 16) * Argument nHeight: height of playfield (4 <= n <= 124) * Return value: pointer to a newly created playfield @@ -515,8 +517,7 @@ int8_t tetris_playfield_getWidth(tetris_playfield_t *pPl) /* Function: tetris_playfield_getHeight - * Description: returns the height of the playfield - * Argument pPl: the playfield we want information from + * Description: returns the height of the ayfield we want information from * Return value: height of the playfield */ int8_t tetris_playfield_getHeight(tetris_playfield_t *pPl) @@ -695,49 +696,85 @@ int8_t tetris_playfield_predictCompleteLines(tetris_playfield_t *pPl, } -/* Function: tetris_playfield_predictDumpRow - * Description: predicts the appearance of a playfield row for a piece - * at a given column +/* Function: tetris_playfield_predictBottomRow + * Description: predicts the appearance of the bottom row of the + * playfield (for a piece at a given column) and + * initializes an iterator structure + * Argument pIt: [out] a pointer to an iterator which should be initialized * 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: appearance of the predicted dump row + * Return value: appearance of the predicted dump row at the bottom + */ +uint16_t* tetris_playfield_predictBottomRow(tetris_playfield_iterator_t *pIt, + tetris_playfield_t *pPl, + tetris_piece_t *pPiece, + int8_t nColumn) +{ + pIt->pPlayfield = pPl; + pIt->pPiece = pPiece; + pIt->nColumn = nColumn; + pIt->nDeepestPieceRow = + tetris_playfield_predictDeepestRow(pPl, pPiece, nColumn); + pIt->nFullRow = 0xFFFF >> (16 - pPl->nWidth); + pIt->nCurrentRow = pPl->nHeight - 1; + pIt->nRowBuffer = 0; + return tetris_playfield_predictNextRow(pIt); +} + + +/* Function: tetris_playfield_predictNextRow + * Description: predicts the appearance of the next row of the playfield + * (for a given iterator) + * Argument pIt: a pointer to a dump iterator + * Return value: appearance of the next predicted dump row */ -uint16_t tetris_playfield_predictDumpRow(tetris_playfield_t *pPl, - tetris_piece_t *pPiece, - int8_t nColumn, - int8_t nRow) +uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt) { - int8_t nPieceRow = tetris_playfield_predictDeepestRow(pPl, pPiece, nColumn); uint16_t nPieceMap = 0; - if (nPieceRow > -4) + if ((pIt->nDeepestPieceRow > -4) && (pIt->nCurrentRow >= 0)) { // determine sane start and stop values for the piece's indices - int8_t nStartRow = ((nPieceRow + 3) < pPl->nHeight) ? - (nPieceRow + 3) : pPl->nHeight - 1; + int8_t nStartRow = + ((pIt->nDeepestPieceRow + 3) < pIt->pPlayfield->nHeight) ? + (pIt->nDeepestPieceRow + 3) : pIt->pPlayfield->nHeight - 1; - uint16_t nPiece = tetris_piece_getBitmap(pPiece); + uint16_t nPiece = tetris_piece_getBitmap(pIt->pPiece); - if ((nRow <= nStartRow) && (nRow >= nPieceRow)) + if ((pIt->nCurrentRow <= nStartRow) && + (pIt->nCurrentRow >= pIt->nDeepestPieceRow)) { - int8_t y = nRow - nPieceRow; + int8_t y = pIt->nCurrentRow - pIt->nDeepestPieceRow; // 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) + if (pIt->nColumn >= 0) { - nPieceMap <<= nColumn; + nPieceMap <<= pIt->nColumn; } else { - nPieceMap >>= -nColumn; + nPieceMap >>= -pIt->nColumn; } } - } - return pPl->dump[nRow] | nPieceMap; + pIt->nRowBuffer = pIt->pPlayfield->dump[pIt->nCurrentRow--] | nPieceMap; + // don't return full (and therefore removed) rows + if (pIt->nRowBuffer == pIt->nFullRow) + { + // recursively determine next row + return tetris_playfield_predictNextRow(pIt); + } + else + { + return &pIt->nRowBuffer; + } + } + else + { + return NULL; + } } diff --git a/games/tetris/playfield.h b/games/tetris/playfield.h index 34bebed..b5e4a89 100644 --- a/games/tetris/playfield.h +++ b/games/tetris/playfield.h @@ -45,6 +45,20 @@ typedef struct tetris_playfield_t tetris_playfield_t; +// iterator for predicted dump rows +typedef struct tetris_playfield_iterator_t +{ + tetris_playfield_t *pPlayfield; // playfield to be examined + tetris_piece_t *pPiece; // piece which should be tested + int8_t nColumn; // the column where the piece should be dropped + int8_t nDeepestPieceRow; // the deepest possible row for a piece + uint16_t nFullRow; // value of a full row + int8_t nCurrentRow; // the actual row in the playfield + uint16_t nRowBuffer; // internal buffer for returned row values +} +tetris_playfield_iterator_t; + + /**************************** * construction/destruction * ****************************/ @@ -248,4 +262,31 @@ uint16_t tetris_playfield_predictDumpRow(tetris_playfield_t *pPl, int8_t nColumn, int8_t nRow); + +/* Function: tetris_playfield_predictBottomRow + * Description: predicts the appearance of the bottom row of the + * playfield (for a piece at a given column) and + * initializes an iterator structure + * Argument pIt: a pointer to an iterator which should be initialized + * 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: appearance of the predicted dump row at the bottom + */ +uint16_t* tetris_playfield_predictBottomRow(tetris_playfield_iterator_t *pIt, + tetris_playfield_t *pPl, + tetris_piece_t *pPiece, + int8_t nColumn); + + +/* Function: tetris_playfield_predictNextRow + * Description: predicts the appearance of the next row of the playfield + * (for a given iterator) + * Argument pIt: a pointer to a dump iterator + * Return value: appearance of the next predicted dump row + */ +uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt); + + + #endif /*TETRIS_PLAYFIELD_H_*/