made some functions static, removed a stupid bug ina prediction routine
This commit is contained in:
parent
e206a60e3f
commit
093790c3d3
|
@ -17,7 +17,7 @@
|
||||||
* @param pBucket the bucket we want information from
|
* @param pBucket the bucket we want information from
|
||||||
* @return TETRIS_BUS_HOVERING or TETRIS_BUS_GLIDING
|
* @return TETRIS_BUS_HOVERING or TETRIS_BUS_GLIDING
|
||||||
*/
|
*/
|
||||||
tetris_bucket_status_t tetris_bucket_hoverStatus(tetris_bucket_t* pBucket)
|
static tetris_bucket_status_t tetris_bucket_hoverStatus(tetris_bucket_t* pBucket)
|
||||||
{
|
{
|
||||||
assert(pBucket != NULL);
|
assert(pBucket != NULL);
|
||||||
|
|
||||||
|
@ -92,23 +92,6 @@ void tetris_bucket_destruct(tetris_bucket_t *pBucket)
|
||||||
* bucket related functions *
|
* bucket related functions *
|
||||||
*******************************/
|
*******************************/
|
||||||
|
|
||||||
uint8_t tetris_bucket_calculateLines(uint8_t nRowMask)
|
|
||||||
{
|
|
||||||
uint8_t nMask = 0x0001;
|
|
||||||
uint8_t nLines = 0;
|
|
||||||
for (uint8_t i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
if ((nMask & nRowMask) != 0)
|
|
||||||
{
|
|
||||||
++nLines;
|
|
||||||
}
|
|
||||||
nMask <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void tetris_bucket_reset(tetris_bucket_t *pBucket)
|
void tetris_bucket_reset(tetris_bucket_t *pBucket)
|
||||||
{
|
{
|
||||||
assert(pBucket != NULL);
|
assert(pBucket != NULL);
|
||||||
|
@ -520,7 +503,7 @@ uint16_t* tetris_bucket_predictNextRow(tetris_bucket_iterator_t *pIt)
|
||||||
nTemp << pIt->nShift : nTemp >> -pIt->nShift;
|
nTemp << pIt->nShift : nTemp >> -pIt->nShift;
|
||||||
pIt->nPieceMap <<= 4;
|
pIt->nPieceMap <<= 4;
|
||||||
}
|
}
|
||||||
pIt->nCurrentRow = pIt->pBucket->dump[pIt->nCurrentRow--] | nTemp;
|
pIt->nRowBuffer = pIt->pBucket->dump[pIt->nCurrentRow--] | nTemp;
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,7 +100,27 @@ void tetris_bucket_destruct(tetris_bucket_t *pBucket);
|
||||||
* @param nRowMask row mask from which the no. of lines will be calculated
|
* @param nRowMask row mask from which the no. of lines will be calculated
|
||||||
* @return number of lines of the row mask
|
* @return number of lines of the row mask
|
||||||
*/
|
*/
|
||||||
uint8_t tetris_bucket_calculateLines(uint8_t nRowMask);
|
inline static uint8_t tetris_bucket_calculateLines(uint8_t nRowMask)
|
||||||
|
{
|
||||||
|
uint8_t nLines = 0;
|
||||||
|
if (nRowMask & 0x01)
|
||||||
|
{
|
||||||
|
++nLines;
|
||||||
|
}
|
||||||
|
if (nRowMask & 0x02)
|
||||||
|
{
|
||||||
|
++nLines;
|
||||||
|
}
|
||||||
|
if (nRowMask & 0x04)
|
||||||
|
{
|
||||||
|
++nLines;
|
||||||
|
}
|
||||||
|
if (nRowMask & 0x08)
|
||||||
|
{
|
||||||
|
++nLines;
|
||||||
|
}
|
||||||
|
return nLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
* @param pIn pointer to an input object
|
* @param pIn pointer to an input object
|
||||||
* @param cmd the command whose counter should be set
|
* @param cmd the command whose counter should be set
|
||||||
*/
|
*/
|
||||||
void tetris_input_chatterProtect(tetris_input_t *pIn,
|
static void tetris_input_chatterProtect(tetris_input_t *pIn,
|
||||||
tetris_input_command_t cmd)
|
tetris_input_command_t cmd)
|
||||||
{
|
{
|
||||||
// never exceed the index
|
// never exceed the index
|
||||||
|
@ -165,7 +165,7 @@ tetris_input_command_t tetris_input_mapCommand(tetris_bearing_t nBearing,
|
||||||
* @return interpreted joystick command
|
* @return interpreted joystick command
|
||||||
* @see tetris_input_command_t
|
* @see tetris_input_command_t
|
||||||
*/
|
*/
|
||||||
tetris_input_command_t tetris_input_queryJoystick(tetris_input_t *pIn)
|
static tetris_input_command_t tetris_input_queryJoystick(tetris_input_t *pIn)
|
||||||
{
|
{
|
||||||
// map port input to a tetris command
|
// map port input to a tetris command
|
||||||
tetris_input_command_t cmdJoystick;
|
tetris_input_command_t cmdJoystick;
|
||||||
|
|
|
@ -155,6 +155,105 @@ int tetris_bastet_qsortCompare(void const *pa,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculates a score for a piece at a given column
|
||||||
|
* @param pBastet the bastet instance of interest
|
||||||
|
* @param pPiece the piece to be tested
|
||||||
|
* @param nColum the column where the piece should be dropped
|
||||||
|
* @return score for the given move
|
||||||
|
*/
|
||||||
|
static int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
|
||||||
|
tetris_piece_t *pPiece,
|
||||||
|
int8_t nColumn)
|
||||||
|
{
|
||||||
|
// initial score of the given piece
|
||||||
|
int16_t nScore = -32000;
|
||||||
|
|
||||||
|
// the row where the given piece collides
|
||||||
|
int8_t nDeepestRow = tetris_bucket_predictDeepestRow(pBastet->pBucket,
|
||||||
|
pPiece, pBastet->pStartingRow[nColumn + 3], nColumn);
|
||||||
|
|
||||||
|
// in case the prediction fails we return the lowest possible score
|
||||||
|
if (nDeepestRow == TETRIS_BUCKET_INVALIDROW)
|
||||||
|
{
|
||||||
|
return -32766;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modify score based on complete lines
|
||||||
|
int8_t nLines = tetris_bucket_predictCompleteLines(pBastet->pBucket,
|
||||||
|
pPiece, nDeepestRow, nColumn);
|
||||||
|
nScore += 5000 * nLines;
|
||||||
|
|
||||||
|
// determine a sane range of columns whose heights we want to predict
|
||||||
|
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
|
||||||
|
int8_t nStartCol, nStopCol;
|
||||||
|
// if lines have been removed, we need to recalculate all column heights
|
||||||
|
if (nLines != 0)
|
||||||
|
{
|
||||||
|
nStartCol = 0;
|
||||||
|
nStopCol = nWidth - 1;
|
||||||
|
}
|
||||||
|
// if no lines were removed, we only need to recalculate a few columns
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nStartCol = (nColumn < 0) ? 0 : nColumn;
|
||||||
|
nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// predict column heights of this move
|
||||||
|
tetris_bastet_calcPredictedColHeights(pBastet, pPiece, nDeepestRow, nColumn,
|
||||||
|
nStartCol, nStopCol);
|
||||||
|
|
||||||
|
// modify score based on predicted column heights
|
||||||
|
for (int x = 0; x < nWidth; ++x)
|
||||||
|
{
|
||||||
|
if ((x >= nStartCol) && (x <= nStopCol))
|
||||||
|
{
|
||||||
|
nScore -= TETRIS_BASTET_HEIGHT_FACTOR * pBastet->pColHeights[x];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nScore -= pBastet->pColScore[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculates the best possible score for every piece
|
||||||
|
* @param pBastet the bastet instance of interest
|
||||||
|
*/
|
||||||
|
static void tetris_bastet_evaluatePieces(tetris_bastet_variant_t *pBastet)
|
||||||
|
{
|
||||||
|
// precache actual column heights
|
||||||
|
tetris_bastet_doPreprocessing(pBastet);
|
||||||
|
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
|
||||||
|
tetris_piece_t *pPiece = tetris_piece_construct(TETRIS_PC_LINE,
|
||||||
|
TETRIS_PC_ANGLE_0);
|
||||||
|
for (int8_t nBlock = TETRIS_PC_LINE; nBlock <= TETRIS_PC_Z; ++nBlock)
|
||||||
|
{
|
||||||
|
int16_t nMaxScore = -32768;
|
||||||
|
tetris_piece_setShape(pPiece, nBlock);
|
||||||
|
int8_t nAngleCount = tetris_piece_getAngleCount(pPiece);
|
||||||
|
for (int8_t nAngle = TETRIS_PC_ANGLE_0; nAngle < nAngleCount; ++nAngle)
|
||||||
|
{
|
||||||
|
tetris_piece_setAngle(pPiece, nAngle);
|
||||||
|
for (int8_t nCol = -3; nCol < nWidth; ++nCol)
|
||||||
|
{
|
||||||
|
int16_t nScore = tetris_bastet_evaluateMove(pBastet,
|
||||||
|
pPiece, nCol);
|
||||||
|
nMaxScore = nMaxScore > nScore ? nMaxScore : nScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pBastet->nPieceScore[nBlock].shape = nBlock;
|
||||||
|
pBastet->nPieceScore[nBlock].nScore = nMaxScore;
|
||||||
|
}
|
||||||
|
tetris_piece_destruct(pPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
* entry point *
|
* entry point *
|
||||||
***************/
|
***************/
|
||||||
|
@ -247,94 +346,6 @@ void tetris_bastet_destruct(void *pVariantData)
|
||||||
* bastet related functions *
|
* bastet related functions *
|
||||||
****************************/
|
****************************/
|
||||||
|
|
||||||
int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
|
|
||||||
tetris_piece_t *pPiece,
|
|
||||||
int8_t nColumn)
|
|
||||||
{
|
|
||||||
// initial score of the given piece
|
|
||||||
int16_t nScore = -32000;
|
|
||||||
|
|
||||||
// the row where the given piece collides
|
|
||||||
int8_t nDeepestRow = tetris_bucket_predictDeepestRow(pBastet->pBucket,
|
|
||||||
pPiece, pBastet->pStartingRow[nColumn + 3], nColumn);
|
|
||||||
|
|
||||||
// in case the prediction fails we return the lowest possible score
|
|
||||||
if (nDeepestRow == TETRIS_BUCKET_INVALIDROW)
|
|
||||||
{
|
|
||||||
return -32766;
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify score based on complete lines
|
|
||||||
int8_t nLines = tetris_bucket_predictCompleteLines(pBastet->pBucket,
|
|
||||||
pPiece, nDeepestRow, nColumn);
|
|
||||||
nScore += 5000 * nLines;
|
|
||||||
|
|
||||||
// determine a sane range of columns whose heights we want to predict
|
|
||||||
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
|
|
||||||
int8_t nStartCol, nStopCol;
|
|
||||||
// if lines have been removed, we need to recalculate all column heights
|
|
||||||
if (nLines != 0)
|
|
||||||
{
|
|
||||||
nStartCol = 0;
|
|
||||||
nStopCol = nWidth - 1;
|
|
||||||
}
|
|
||||||
// if no lines were removed, we only need to recalculate a few columns
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nStartCol = (nColumn < 0) ? 0 : nColumn;
|
|
||||||
nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// predict column heights of this move
|
|
||||||
tetris_bastet_calcPredictedColHeights(pBastet, pPiece, nDeepestRow, nColumn,
|
|
||||||
nStartCol, nStopCol);
|
|
||||||
|
|
||||||
// modify score based on predicted column heights
|
|
||||||
for (int x = 0; x < nWidth; ++x)
|
|
||||||
{
|
|
||||||
if ((x >= nStartCol) && (x <= nStopCol))
|
|
||||||
{
|
|
||||||
nScore -= TETRIS_BASTET_HEIGHT_FACTOR * pBastet->pColHeights[x];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nScore -= pBastet->pColScore[x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void tetris_bastet_evaluatePieces(tetris_bastet_variant_t *pBastet)
|
|
||||||
{
|
|
||||||
// precache actual column heights
|
|
||||||
tetris_bastet_doPreprocessing(pBastet);
|
|
||||||
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
|
|
||||||
tetris_piece_t *pPiece = tetris_piece_construct(TETRIS_PC_LINE,
|
|
||||||
TETRIS_PC_ANGLE_0);
|
|
||||||
for (int8_t nBlock = TETRIS_PC_LINE; nBlock <= TETRIS_PC_Z; ++nBlock)
|
|
||||||
{
|
|
||||||
int16_t nMaxScore = -32768;
|
|
||||||
tetris_piece_setShape(pPiece, nBlock);
|
|
||||||
int8_t nAngleCount = tetris_piece_getAngleCount(pPiece);
|
|
||||||
for (int8_t nAngle = TETRIS_PC_ANGLE_0; nAngle < nAngleCount; ++nAngle)
|
|
||||||
{
|
|
||||||
tetris_piece_setAngle(pPiece, nAngle);
|
|
||||||
for (int8_t nCol = -3; nCol < nWidth; ++nCol)
|
|
||||||
{
|
|
||||||
int16_t nScore = tetris_bastet_evaluateMove(pBastet,
|
|
||||||
pPiece, nCol);
|
|
||||||
nMaxScore = nMaxScore > nScore ? nMaxScore : nScore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pBastet->nPieceScore[nBlock].shape = nBlock;
|
|
||||||
pBastet->nPieceScore[nBlock].nScore = nMaxScore;
|
|
||||||
}
|
|
||||||
tetris_piece_destruct(pPiece);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tetris_piece_t* tetris_bastet_choosePiece(void *pVariantData)
|
tetris_piece_t* tetris_bastet_choosePiece(void *pVariantData)
|
||||||
{
|
{
|
||||||
assert(pVariantData != 0);
|
assert(pVariantData != 0);
|
||||||
|
|
|
@ -73,25 +73,6 @@ void tetris_bastet_destruct(void *pVariantData);
|
||||||
* bastet related functions *
|
* bastet related functions *
|
||||||
****************************/
|
****************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* calculates a score for a piece at a given column
|
|
||||||
* @param pBastet the bastet instance of interest
|
|
||||||
* @param pPiece the piece to be tested
|
|
||||||
* @param nColum the column where the piece should be dropped
|
|
||||||
* @return score for the given move
|
|
||||||
*/
|
|
||||||
int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
|
|
||||||
tetris_piece_t *pPiece,
|
|
||||||
int8_t nColumn);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* calculates the best possible score for every piece
|
|
||||||
* @param pBastet the bastet instance of interest
|
|
||||||
*/
|
|
||||||
void tetris_bastet_evaluatePieces(tetris_bastet_variant_t *pBastet);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* chooses a new worst possible piece
|
* chooses a new worst possible piece
|
||||||
* @param pVariantData the variant instance of interest
|
* @param pVariantData the variant instance of interest
|
||||||
|
|
|
@ -122,28 +122,30 @@
|
||||||
* @param y y-coordinate of the pixel
|
* @param y y-coordinate of the pixel
|
||||||
* @param nColor Color of the pixel
|
* @param nColor Color of the pixel
|
||||||
*/
|
*/
|
||||||
void tetris_view_setpixel(tetris_bearing_t nBearing,
|
static void tetris_view_setpixel(tetris_bearing_t nBearing,
|
||||||
uint8_t x,
|
uint8_t x,
|
||||||
uint8_t y,
|
uint8_t y,
|
||||||
uint8_t nColor)
|
uint8_t nColor)
|
||||||
{
|
{
|
||||||
x = VIEWCOLS - 1 - x;
|
x = VIEWCOLS - 1 - x;
|
||||||
|
|
||||||
|
pixel px;
|
||||||
switch (nBearing)
|
switch (nBearing)
|
||||||
{
|
{
|
||||||
case TETRIS_BEARING_0:
|
case TETRIS_BEARING_0:
|
||||||
setpixel((pixel){x, y}, nColor);
|
px = (pixel){x, y};
|
||||||
break;
|
break;
|
||||||
case TETRIS_BEARING_90:
|
case TETRIS_BEARING_90:
|
||||||
setpixel((pixel){y, VIEWCOLS - 1 - x}, nColor);
|
px = (pixel){y, VIEWCOLS - 1 - x};
|
||||||
break;
|
break;
|
||||||
case TETRIS_BEARING_180:
|
case TETRIS_BEARING_180:
|
||||||
setpixel((pixel){VIEWCOLS - 1 - x, VIEWROWS - 1 - y}, nColor);
|
px = (pixel){VIEWCOLS - 1 - x, VIEWROWS - 1 - y};
|
||||||
break;
|
break;
|
||||||
case TETRIS_BEARING_270:
|
case TETRIS_BEARING_270:
|
||||||
setpixel((pixel){VIEWROWS - 1 - y, x}, nColor);
|
px = (pixel){VIEWROWS - 1 - y, x};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
setpixel(px, nColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,7 +157,7 @@ void tetris_view_setpixel(tetris_bearing_t nBearing,
|
||||||
* @param y y-coordinate of the line
|
* @param y y-coordinate of the line
|
||||||
* @param nColor Color of the line
|
* @param nColor Color of the line
|
||||||
*/
|
*/
|
||||||
void tetris_view_drawHLine(tetris_bearing_t nBearing,
|
inline static void tetris_view_drawHLine(tetris_bearing_t nBearing,
|
||||||
uint8_t x1,
|
uint8_t x1,
|
||||||
uint8_t x2,
|
uint8_t x2,
|
||||||
uint8_t y,
|
uint8_t y,
|
||||||
|
@ -178,7 +180,7 @@ void tetris_view_drawHLine(tetris_bearing_t nBearing,
|
||||||
* @param y2 second y-coordinate of the line
|
* @param y2 second y-coordinate of the line
|
||||||
* @param nColor Color of the line
|
* @param nColor Color of the line
|
||||||
*/
|
*/
|
||||||
void tetris_view_drawVLine(tetris_bearing_t nBearing,
|
inline static void tetris_view_drawVLine(tetris_bearing_t nBearing,
|
||||||
uint8_t x,
|
uint8_t x,
|
||||||
uint8_t y1,
|
uint8_t y1,
|
||||||
uint8_t y2,
|
uint8_t y2,
|
||||||
|
@ -197,7 +199,7 @@ void tetris_view_drawVLine(tetris_bearing_t nBearing,
|
||||||
* helper function to dim the piece color if game is paused
|
* helper function to dim the piece color if game is paused
|
||||||
* @param pV pointer to the view whose pause status is of interest
|
* @param pV pointer to the view whose pause status is of interest
|
||||||
*/
|
*/
|
||||||
uint8_t tetris_view_getPieceColor(tetris_view_t *pV)
|
inline static uint8_t tetris_view_getPieceColor(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
if (pV->modeCurrent == TETRIS_VIMO_RUNNING)
|
if (pV->modeCurrent == TETRIS_VIMO_RUNNING)
|
||||||
{
|
{
|
||||||
|
@ -214,7 +216,7 @@ uint8_t tetris_view_getPieceColor(tetris_view_t *pV)
|
||||||
* redraws the dump and the falling piece (if necessary)
|
* redraws the dump and the falling piece (if necessary)
|
||||||
* @param pV pointer to the view on which the dump should be drawn
|
* @param pV pointer to the view on which the dump should be drawn
|
||||||
*/
|
*/
|
||||||
void tetris_view_drawDump(tetris_view_t *pV)
|
static void tetris_view_drawDump(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
assert(pV->pBucket != NULL);
|
assert(pV->pBucket != NULL);
|
||||||
if (tetris_bucket_getRow(pV->pBucket) <= -4)
|
if (tetris_bucket_getRow(pV->pBucket) <= -4)
|
||||||
|
@ -222,60 +224,36 @@ void tetris_view_drawDump(tetris_view_t *pV)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tetris_bearing_t nBearing =
|
|
||||||
pV->pVariantMethods->getBearing(pV->pVariant);
|
|
||||||
|
|
||||||
int8_t nPieceRow = tetris_bucket_getRow(pV->pBucket);
|
|
||||||
uint16_t nRowMap;
|
|
||||||
uint16_t nElementMask;
|
|
||||||
|
|
||||||
tetris_bucket_status_t status = tetris_bucket_getStatus(pV->pBucket);
|
|
||||||
for (int8_t nRow = TETRIS_VIEW_HEIGHT_DUMP - 1; nRow >= 0; --nRow)
|
for (int8_t nRow = TETRIS_VIEW_HEIGHT_DUMP - 1; nRow >= 0; --nRow)
|
||||||
{
|
{
|
||||||
nRowMap = tetris_bucket_getDumpRow(pV->pBucket, nRow);
|
uint16_t nRowMap = tetris_bucket_getDumpRow(pV->pBucket, nRow);
|
||||||
|
|
||||||
// if a piece is hovering or gliding it needs to be drawn
|
// if a piece is hovering or gliding it needs to be drawn
|
||||||
if ((status == TETRIS_BUS_HOVERING) || (status == TETRIS_BUS_GLIDING) ||
|
int8_t nPieceRow = tetris_bucket_getRow(pV->pBucket);
|
||||||
(status == TETRIS_BUS_GAMEOVER))
|
tetris_bucket_status_t status = tetris_bucket_getStatus(pV->pBucket);
|
||||||
|
if (((status == TETRIS_BUS_HOVERING) || (status == TETRIS_BUS_GLIDING)
|
||||||
|
|| (status == TETRIS_BUS_GAMEOVER)) && (nRow >= nPieceRow)
|
||||||
|
&& (nRow <= nPieceRow + 3))
|
||||||
{
|
{
|
||||||
if ((nRow >= nPieceRow) && (nRow <= nPieceRow + 3))
|
|
||||||
{
|
|
||||||
int8_t y = nRow - nPieceRow;
|
|
||||||
int8_t nColumn = tetris_bucket_getColumn(pV->pBucket);
|
int8_t nColumn = tetris_bucket_getColumn(pV->pBucket);
|
||||||
uint16_t nPieceMap =
|
uint16_t nPieceMap =
|
||||||
tetris_piece_getBitmap(tetris_bucket_getPiece(pV->pBucket));
|
tetris_piece_getBitmap(tetris_bucket_getPiece(pV->pBucket));
|
||||||
// clear all bits of the piece we are not interested in and
|
// clear all bits of the piece we are not interested in and
|
||||||
// align the remaining row to LSB
|
// align the remaining row to LSB
|
||||||
|
int8_t y = nRow - nPieceRow;
|
||||||
nPieceMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2);
|
nPieceMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2);
|
||||||
// shift remaining part to current column
|
// shift remaining part to current column and embed piece into view
|
||||||
if (nColumn >= 0)
|
nRowMap |= nColumn >= 0 ?
|
||||||
{
|
nPieceMap << nColumn : nPieceMap >> -nColumn;
|
||||||
nPieceMap <<= nColumn;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nPieceMap >>= -nColumn;
|
|
||||||
}
|
|
||||||
// cut off unwanted stuff
|
|
||||||
// nPieceMap &= 0x03ff;
|
|
||||||
// finally embed piece into the view
|
|
||||||
nRowMap |= nPieceMap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nElementMask = 0x0001;
|
uint16_t nElementMask = 0x0001;
|
||||||
|
|
||||||
for (int8_t x = 0; x < TETRIS_VIEW_WIDTH_DUMP; ++x)
|
for (int8_t x = 0; x < TETRIS_VIEW_WIDTH_DUMP; ++x)
|
||||||
{
|
{
|
||||||
unsigned char nColor;
|
unsigned char nColor = (nRowMap & nElementMask) ?
|
||||||
if ((nRowMap & nElementMask) != 0)
|
tetris_view_getPieceColor(pV) : TETRIS_VIEW_COLORSPACE;
|
||||||
{
|
tetris_bearing_t const nBearing =
|
||||||
nColor = tetris_view_getPieceColor(pV);
|
pV->pVariantMethods->getBearing(pV->pVariant);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nColor = TETRIS_VIEW_COLORSPACE;
|
|
||||||
}
|
|
||||||
tetris_view_setpixel(nBearing, TETRIS_VIEW_XOFFSET_DUMP + x,
|
tetris_view_setpixel(nBearing, TETRIS_VIEW_XOFFSET_DUMP + x,
|
||||||
TETRIS_VIEW_YOFFSET_DUMP + nRow, nColor);
|
TETRIS_VIEW_YOFFSET_DUMP + nRow, nColor);
|
||||||
nElementMask <<= 1;
|
nElementMask <<= 1;
|
||||||
|
@ -283,13 +261,14 @@ void tetris_view_drawDump(tetris_view_t *pV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TETRIS_VIEW_XOFFSET_PREVIEW
|
#ifdef TETRIS_VIEW_XOFFSET_PREVIEW
|
||||||
/**
|
/**
|
||||||
* redraws the preview window
|
* redraws the preview window
|
||||||
* @param pV pointer to the view on which the piece should be drawn
|
* @param pV pointer to the view on which the piece should be drawn
|
||||||
* @param pPc pointer to the piece for the preview window (may be NULL)
|
* @param pPc pointer to the piece for the preview window (may be NULL)
|
||||||
*/
|
*/
|
||||||
void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc)
|
static void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc)
|
||||||
{
|
{
|
||||||
tetris_bearing_t nBearing =
|
tetris_bearing_t nBearing =
|
||||||
pV->pVariantMethods->getBearing(pV->pVariant);
|
pV->pVariantMethods->getBearing(pV->pVariant);
|
||||||
|
@ -350,7 +329,7 @@ void tetris_view_drawPreviewPiece(tetris_view_t *pV, tetris_piece_t *pPc)
|
||||||
* @param pV pointer to the view on which the borders should be drawn
|
* @param pV pointer to the view on which the borders should be drawn
|
||||||
* @param nColor the color for the border
|
* @param nColor the color for the border
|
||||||
*/
|
*/
|
||||||
void tetris_view_drawBorders(tetris_view_t *pV,
|
static void tetris_view_drawBorders(tetris_view_t *pV,
|
||||||
uint8_t nColor)
|
uint8_t nColor)
|
||||||
{
|
{
|
||||||
tetris_bearing_t nBearing =
|
tetris_bearing_t nBearing =
|
||||||
|
@ -453,7 +432,7 @@ void tetris_view_drawBorders(tetris_view_t *pV,
|
||||||
* lets the borders blink to notify player of a level change
|
* lets the borders blink to notify player of a level change
|
||||||
* @param pV pointer to the view whose borders should blink
|
* @param pV pointer to the view whose borders should blink
|
||||||
*/
|
*/
|
||||||
void tetris_view_blinkBorders(tetris_view_t *pV)
|
static void tetris_view_blinkBorders(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < TETRIS_VIEW_BORDER_BLINK_COUNT; ++i)
|
for (uint8_t i = 0; i < TETRIS_VIEW_BORDER_BLINK_COUNT; ++i)
|
||||||
{
|
{
|
||||||
|
@ -469,12 +448,13 @@ void tetris_view_blinkBorders(tetris_view_t *pV)
|
||||||
* lets complete lines blink to emphasize their removal
|
* lets complete lines blink to emphasize their removal
|
||||||
* @param pV pointer to the view whose complete lines should blink
|
* @param pV pointer to the view whose complete lines should blink
|
||||||
*/
|
*/
|
||||||
void tetris_view_blinkLines(tetris_view_t *pV)
|
static void tetris_view_blinkLines(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
|
|
||||||
// reduce necessity of pointer arithmetic
|
// reduce necessity of pointer arithmetic
|
||||||
int8_t nRow = tetris_bucket_getRow(pV->pBucket);
|
int8_t nRow = tetris_bucket_getRow(pV->pBucket);
|
||||||
uint8_t nRowMask = tetris_bucket_getRowMask(pV->pBucket);
|
uint8_t nRowMask = tetris_bucket_getRowMask(pV->pBucket);
|
||||||
|
int8_t nMask = 0x01;
|
||||||
|
|
||||||
tetris_bearing_t nBearing =
|
tetris_bearing_t nBearing =
|
||||||
pV->pVariantMethods->getBearing(pV->pVariant);
|
pV->pVariantMethods->getBearing(pV->pVariant);
|
||||||
|
@ -493,7 +473,7 @@ void tetris_view_blinkLines(tetris_view_t *pV)
|
||||||
for (uint8_t j = 0; j <= nDeepestRowOffset; ++j)
|
for (uint8_t j = 0; j <= nDeepestRowOffset; ++j)
|
||||||
{
|
{
|
||||||
// is current line a complete line?
|
// is current line a complete line?
|
||||||
if ((nRowMask & (0x01 << j)) != 0)
|
if ((nRowMask & (nMask << j)) != 0)
|
||||||
{
|
{
|
||||||
// draw line in current color
|
// draw line in current color
|
||||||
uint8_t y = nRow + j;
|
uint8_t y = nRow + j;
|
||||||
|
@ -502,7 +482,6 @@ void tetris_view_blinkLines(tetris_view_t *pV)
|
||||||
|
|
||||||
uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE
|
uint8_t nColor = (nColIdx == 0 ? TETRIS_VIEW_COLORFADE
|
||||||
: TETRIS_VIEW_COLORPIECE);
|
: TETRIS_VIEW_COLORPIECE);
|
||||||
// setpixel((pixel){14 - x, y}, nColor);
|
|
||||||
tetris_view_setpixel(nBearing,
|
tetris_view_setpixel(nBearing,
|
||||||
TETRIS_VIEW_XOFFSET_DUMP + x,
|
TETRIS_VIEW_XOFFSET_DUMP + x,
|
||||||
TETRIS_VIEW_YOFFSET_DUMP + y,
|
TETRIS_VIEW_YOFFSET_DUMP + y,
|
||||||
|
@ -522,7 +501,7 @@ void tetris_view_blinkLines(tetris_view_t *pV)
|
||||||
* displays completed Lines (0-99)
|
* displays completed Lines (0-99)
|
||||||
* @param pV pointer to the view
|
* @param pV pointer to the view
|
||||||
*/
|
*/
|
||||||
void tetris_view_showLineNumbers(tetris_view_t *pV)
|
static void tetris_view_showLineNumbers(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
|
|
||||||
tetris_bearing_t nBearing =
|
tetris_bearing_t nBearing =
|
||||||
|
@ -578,7 +557,7 @@ void tetris_view_showLineNumbers(tetris_view_t *pV)
|
||||||
* @param nHighscoreName the champion's initials packed into a uint16_t
|
* @param nHighscoreName the champion's initials packed into a uint16_t
|
||||||
* @param pszName pointer to an array of char for the unpacked initials
|
* @param pszName pointer to an array of char for the unpacked initials
|
||||||
*/
|
*/
|
||||||
void tetris_view_formatHighscoreName(uint16_t nHighscoreName,
|
static void tetris_view_formatHighscoreName(uint16_t nHighscoreName,
|
||||||
char *pszName)
|
char *pszName)
|
||||||
{
|
{
|
||||||
pszName[0] = ((nHighscoreName >> 10) & 0x1F) + 65;
|
pszName[0] = ((nHighscoreName >> 10) & 0x1F) + 65;
|
||||||
|
@ -653,13 +632,6 @@ void tetris_view_getDimensions(int8_t *w,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm)
|
|
||||||
{
|
|
||||||
pV->modeOld = pV->modeCurrent;
|
|
||||||
pV->modeCurrent = vm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void tetris_view_update(tetris_view_t *pV)
|
void tetris_view_update(tetris_view_t *pV)
|
||||||
{
|
{
|
||||||
assert(pV != NULL);
|
assert(pV != NULL);
|
||||||
|
|
|
@ -88,7 +88,12 @@ void tetris_view_getDimensions(int8_t *w,
|
||||||
* @param pV pointer to the view whose mode should be set
|
* @param pV pointer to the view whose mode should be set
|
||||||
* @param vm see definition of tetris_view_mode_t
|
* @param vm see definition of tetris_view_mode_t
|
||||||
*/
|
*/
|
||||||
void tetris_view_setViewMode(tetris_view_t *pV, tetris_view_mode_t vm);
|
inline static void tetris_view_setViewMode(tetris_view_t *const pV,
|
||||||
|
tetris_view_mode_t const vm)
|
||||||
|
{
|
||||||
|
pV->modeOld = pV->modeCurrent;
|
||||||
|
pV->modeCurrent = vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue