optimized collision detection and better preprocessing for bastet (bastet algorithm almost twice as fast)

This commit is contained in:
Christian Kroll 2010-12-09 19:34:03 +00:00
parent a246779eff
commit 7deb41c236
5 changed files with 189 additions and 156 deletions

View File

@ -2,6 +2,7 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include "../../compat/pgmspace.h"
#include "../../config.h" #include "../../config.h"
#include "bucket.h" #include "bucket.h"
#include "piece.h" #include "piece.h"
@ -14,10 +15,12 @@
/** /**
* determines if piece is either hovering or gliding * determines if piece is either hovering or gliding
* @param pBucket the bucket we want information from * @param pBucket the bucket we want information from
* @return TETRIS_PFS_HOVERING or TETRIS_PFS_GLIDING * @return TETRIS_BUS_HOVERING or TETRIS_BUS_GLIDING
*/ */
tetris_bucket_status_t tetris_bucket_hoverStatus(tetris_bucket_t* pBucket) tetris_bucket_status_t tetris_bucket_hoverStatus(tetris_bucket_t* pBucket)
{ {
assert(pBucket != NULL);
// if the piece touches the dump we ensure that the status is "gliding" // if the piece touches the dump we ensure that the status is "gliding"
if (tetris_bucket_collision(pBucket, pBucket->nColumn, pBucket->nRow + 1)) if (tetris_bucket_collision(pBucket, pBucket->nColumn, pBucket->nRow + 1))
{ {
@ -115,7 +118,7 @@ void tetris_bucket_reset(tetris_bucket_t *pBucket)
// clear dump if it has been allocated in memory // clear dump if it has been allocated in memory
if (pBucket->dump != NULL) if (pBucket->dump != NULL)
{ {
memset(pBucket->dump, 0, pBucket->nHeight); memset(pBucket->dump, 0, pBucket->nHeight * sizeof(uint16_t));
} }
pBucket->status = TETRIS_BUS_READY; pBucket->status = TETRIS_BUS_READY;
@ -148,7 +151,7 @@ void tetris_bucket_insertPiece(tetris_bucket_t *pBucket,
{ {
assert((pBucket != NULL) && (pPiece != NULL) && (ppOldPiece != NULL)); assert((pBucket != NULL) && (pPiece != NULL) && (ppOldPiece != NULL));
// a piece can only be inserted in state TETRIS_PFS_READY // a piece can only be inserted in state TETRIS_BUS_READY
assert(pBucket->status == TETRIS_BUS_READY); assert(pBucket->status == TETRIS_BUS_READY);
// row mask is now meaningless // row mask is now meaningless
@ -182,94 +185,50 @@ uint8_t tetris_bucket_collision(tetris_bucket_t *pBucket,
int8_t nColumn, int8_t nColumn,
int8_t nRow) int8_t nRow)
{ {
assert(pBucket != NULL); // A piece is represented by 16 bits (4 bits per row where the LSB marks the
// left most position). The part of the bucket which is covered by the piece
// is converted to this format (including the bucket borders) so that a
// simple bitwise 'AND' tells us if the piece and the dump overlap.
// only allow coordinates which are within sane ranges // only allow coordinates which are within sane ranges
assert(pBucket != NULL);
assert((nColumn > -4) && (nColumn < pBucket->nWidth)); assert((nColumn > -4) && (nColumn < pBucket->nWidth));
assert((nRow > -4) && (nRow < pBucket->nHeight)); assert((nRow > -4) && (nRow < pBucket->nHeight));
// The rows of a piece get compared with the background one by one // left and right borders
// until either a collision occures or all rows are compared. Both the uint16_t nBucketPart = 0;
// piece row and the part of the bucket it covers are represented in
// 4 bits which were singled out from their corresponding uint16_t
// values and are aligned to LSB. In case where a piece overlaps with
// either the left or the right border we "enhance" the bucket part
// via bit shifting and set all bits representing the border to 1.
//
// NOTE: LSB represents the left most position.
uint16_t nPieceMap = tetris_piece_getBitmap(pBucket->pPiece);
uint16_t nBucketPart;
uint16_t nPieceRowMap;
// negative nRow values indicate that the piece hasn't fully entered the
// bucket yet which requires special treatment if the piece overlaps
// with either the left or the right border
if (nRow < 0)
{
uint16_t nBorderMask = 0x0000;
// piece overlaps with left border
if (nColumn < 0) if (nColumn < 0)
{ {
nBorderMask = 0x1111 << (-nColumn - 1); static uint16_t const nLeftPart[] PROGMEM = {0x7777, 0x3333, 0x1111};
nBucketPart = pgm_read_word(&nLeftPart[nColumn + 3]);
} }
// piece overlaps with right border else if (nColumn >= pBucket->nWidth - 3)
else if ((nColumn + 3) >= pBucket->nWidth)
{ {
nBorderMask = 0x8888 >> ((nColumn + 3) - pBucket->nWidth); static uint16_t const nRightPart[] PROGMEM = {0xEEEE, 0xCCCC, 0x8888};
nBucketPart = pgm_read_word(&nRightPart[pBucket->nWidth - nColumn - 1]);
} }
// return if piece collides with border // lower border
if ((nPieceMap & nBorderMask) != 0) if (nRow > pBucket->nHeight - 4)
{
return 1;
}
}
// here we check the part which has already entered the bucket
for (int8_t y = (nRow < 0) ? -nRow : 0; y < 4; ++y)
{
// current piece row overlaps with lower border
if ((y + nRow) >= pBucket->nHeight)
{
// all 4 bits represent the lower border
nBucketPart = 0x000F;
}
// piece overlaps with left border
else if (nColumn < 0)
{
// clear all bits we are not interested in
nBucketPart = (pBucket->dump[y + nRow] & (0x000F >> -nColumn));
// add zeros to the left (the bits "behind" the left border)
nBucketPart <<= -nColumn;
// set bits beyond left border to 1
nBucketPart |= 0x000F >> (4 + nColumn);
}
// piece overlaps with right border
else if ((nColumn + 3) >= pBucket->nWidth)
{
// align the bits we are interested in to LSB
// (thereby clearing the rest)
nBucketPart = pBucket->dump[y + nRow] >> nColumn;
// set bits beyond right border to 1
nBucketPart |= 0xFFF8 >> (nColumn + 3 - pBucket->nWidth);
}
// current row neither overlaps with left, right nor lower border
else
{
// clear all bits we are not interested in and align the
// remaing row to LSB
nBucketPart =
(pBucket->dump[y + nRow] & (0x000F << nColumn)) >> nColumn;
}
// clear all bits of the piece we are not interested in and
// align the remaing row to LSB
nPieceRowMap = (nPieceMap & (0x000F << (y << 2))) >> (y << 2);
// finally check for a collision
if ((nBucketPart & nPieceRowMap) != 0)
{ {
nBucketPart |= 0xFFFF << ((pBucket->nHeight - nRow) * 4);
}
int8_t const nStop = (nRow + 3) < pBucket->nHeight ?
nRow + 3 : pBucket->nHeight - 1;
// mask those blocks which are not covered by the piece
uint16_t nDumpMask = nColumn >= 0 ? 0x000F << nColumn : 0x000F >> -nColumn;
// value for shifting blocks to the corresponding part of the piece
int8_t nShift = -nColumn + (nRow < 0 ? 4 * -nRow : 0);
for (int8_t y = nRow >= 0 ? nRow : 0; y <= nStop; ++y)
{
uint16_t nTemp = pBucket->dump[y] & nDumpMask;
nBucketPart |= nShift >= 0 ? nTemp << nShift : nTemp >> -nShift;
if ((tetris_piece_getBitmap(pBucket->pPiece) & nBucketPart) != 0)
{
// collision
return 1; return 1;
} }
nShift += 4;
} }
// if we reach here, no collision was detected // if we reach here, no collision was detected
@ -412,7 +371,7 @@ void tetris_bucket_removeCompleteLines(tetris_bucket_t *pBucket)
{ {
assert(pBucket != NULL); assert(pBucket != NULL);
// rows can only be removed if we are in state TETRIS_PFS_DOCKED // rows can only be removed if we are in state TETRIS_BUS_DOCKED
assert(pBucket->status == TETRIS_BUS_DOCKED); assert(pBucket->status == TETRIS_BUS_DOCKED);
// bit mask of a full row // bit mask of a full row
@ -560,32 +519,49 @@ uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket,
int8_t tetris_bucket_predictDeepestRow(tetris_bucket_t *pBucket, int8_t tetris_bucket_predictDeepestRow(tetris_bucket_t *pBucket,
tetris_piece_t *pPiece, tetris_piece_t *pPiece,
int8_t nStartingRow,
int8_t nColumn) int8_t nColumn)
{ {
int8_t nRow = tetris_bucket_getPieceStartPos(pPiece); assert(pBucket != NULL);
assert(pPiece != NULL);
assert(nStartingRow >= -1 && nStartingRow < pBucket->nHeight);
assert(nColumn >= -3 && nColumn < pBucket->nWidth);
// exchange current piece of the bucket (to use its collision detection)
tetris_piece_t *pActualPiece = pBucket->pPiece; tetris_piece_t *pActualPiece = pBucket->pPiece;
pBucket->pPiece = pPiece; pBucket->pPiece = pPiece;
// is it actually possible to use this piece? // determine empty rows of the bottom of piece which may overlap the dump
if (tetris_bucket_collision(pBucket, (pBucket->nWidth - 2) / 2, nRow) || uint16_t nMap = tetris_piece_getBitmap(pPiece);
(tetris_bucket_collision(pBucket, nColumn, nRow))) int8_t nOffset = 0;
if ((nMap & 0xF000) != 0)
nOffset = 3;
else if ((nMap & 0xFF00) != 0)
nOffset = 2;
else if ((nMap & 0xFFF0) != 0)
nOffset = 1;
int8_t nRow = nStartingRow - nOffset;
// check if the piece collides with the left or the right wall
if ((nRow < -3) || (((nColumn < 0) || (nColumn >= pBucket->nWidth - 3)) &&
tetris_bucket_collision(pBucket, nColumn, nRow)))
{ {
// restore real piece nRow = TETRIS_BUCKET_INVALIDROW;
pBucket->pPiece = pActualPiece;
return -4;
} }
// determine deepest row // determine deepest row
nRow = (nRow < pBucket->nFirstMatterRow - 4) ? else
pBucket->nFirstMatterRow - 4 : nRow; {
while ((nRow < pBucket->nHeight) && while (!tetris_bucket_collision(pBucket, nColumn, nRow + 1))
(!tetris_bucket_collision(pBucket, nColumn, nRow + 1)))
{ {
++nRow; ++nRow;
} }
if ((nRow < 0) && (((nRow + 4) * 4) << nMap))
{
nRow = TETRIS_BUCKET_INVALIDROW;
}
}
// restore real piece // restore actual bucket piece
pBucket->pPiece = pActualPiece; pBucket->pPiece = pActualPiece;
return nRow; return nRow;
@ -597,16 +573,15 @@ int8_t tetris_bucket_predictCompleteLines(tetris_bucket_t *pBucket,
int8_t nRow, int8_t nRow,
int8_t nColumn) int8_t nColumn)
{ {
assert(nRow > -4);
int8_t nCompleteRows = 0; int8_t nCompleteRows = 0;
// bit mask of a full row // bit mask of a full row
uint16_t nFullRow = 0xFFFF >> (16 - pBucket->nWidth); uint16_t nFullRow = 0xFFFF >> (16 - pBucket->nWidth);
if (nRow > -4)
{
// determine sane start and stop values for the dump's index // determine sane start and stop values for the dump's index
int8_t nStartRow = int8_t nStartRow = ((nRow + 3) >= pBucket->nHeight) ?
((nRow + 3) >= pBucket->nHeight) ? pBucket->nHeight - 1 : nRow + 3; pBucket->nHeight - 1 : nRow + 3;
int8_t nStopRow = (nRow < 0) ? 0 : nRow; int8_t nStopRow = (nRow < 0) ? 0 : nRow;
uint16_t nPiece = tetris_piece_getBitmap(pPiece); uint16_t nPiece = tetris_piece_getBitmap(pPiece);
@ -615,8 +590,8 @@ int8_t tetris_bucket_predictCompleteLines(tetris_bucket_t *pBucket,
{ {
int8_t y = i - nRow; int8_t y = i - nRow;
// 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
// align the rest to LSB // rest to LSB
uint16_t nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2); uint16_t nPieceMap = (nPiece & (0x000F << (y << 2))) >> (y << 2);
// shift the remaining content to the current column // shift the remaining content to the current column
if (nColumn >= 0) if (nColumn >= 0)
@ -636,7 +611,6 @@ int8_t tetris_bucket_predictCompleteLines(tetris_bucket_t *pBucket,
++nCompleteRows; ++nCompleteRows;
} }
} }
}
return nCompleteRows; return nCompleteRows;
} }

View File

@ -6,6 +6,13 @@
#include "piece.h" #include "piece.h"
/***********
* defines *
***********/
#define TETRIS_BUCKET_INVALIDROW -4
/********* /*********
* types * * types *
*********/ *********/
@ -245,11 +252,13 @@ uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket,
* returns the deepest possible row for a given piece * returns the deepest possible row for a given piece
* @param pBucket the bucket on which we want to test a piece * @param pBucket the bucket on which we want to test a piece
* @param pPiece the piece which should be tested * @param pPiece the piece which should be tested
* @param nStartingRow the row where the collision detection should start
* @param nColumn the column where the piece should be dropped * @param nColumn the column where the piece should be dropped
* @return the row of the piece (bucket compliant coordinates) * @return the row of the piece (bucket compliant coordinates)
*/ */
int8_t tetris_bucket_predictDeepestRow(tetris_bucket_t *pBucket, int8_t tetris_bucket_predictDeepestRow(tetris_bucket_t *pBucket,
tetris_piece_t *pPiece, tetris_piece_t *pPiece,
int8_t nStartingRow,
int8_t nColumn); int8_t nColumn);

View File

@ -1,14 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include "bearing.h"
#include "tetris_main.h"
#include "variants.h"
#include "piece.h" #include "piece.h"
#include "bucket.h"
#include "view.h"
#include "input.h"
#include "highscore.h" #include "highscore.h"
#include "bucket.h"
#include "input.h"
#include "variants.h"
#include "view.h"
#include "tetris_main.h"
void tetris_main(tetris_variant_t const *const pVariantMethods) void tetris_main(tetris_variant_t const *const pVariantMethods)

View File

@ -27,17 +27,21 @@
***************************/ ***************************/
/** /**
* calculate the score impact of every column (without any prediction) * Preprocess values like sane starting points for the collision detection or
* @param pBastet bastet instance whose column heights should be calculated * the score impact of every unchanged column to speed up prediction routines.
* @param pBastet bastet instance which should be preprocessed
*/ */
void tetris_bastet_calcActualColumnsScoreImpact(tetris_bastet_variant_t *pBastet) void tetris_bastet_doPreprocessing(tetris_bastet_variant_t *pBastet)
{ {
// retrieve sane start and stop values for the column and row indices // retrieve sane start and stop values for the column and row indices
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket); int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
int8_t nStartRow = tetris_bucket_getHeight(pBastet->pBucket) - 1; int8_t nStartRow = tetris_bucket_getHeight(pBastet->pBucket) - 1;
int8_t nStopRow = tetris_bucket_getFirstMatterRow(pBastet->pBucket); int8_t nStopRow = tetris_bucket_getFirstMatterRow(pBastet->pBucket);
// printf("%d ", nStopRow);
// calculate the column heights of the actual bucket configuration // calculate the column heights of the actual bucket configuration
// NOTE: in this loop, pColScore contains the actual column heights,
// later it will contain the "score impact" of every unchanged column
for (int8_t y = nStartRow; y >= nStopRow; --y) for (int8_t y = nStartRow; y >= nStopRow; --y)
{ {
uint16_t nDumpRow = tetris_bucket_getDumpRow(pBastet->pBucket, y); uint16_t nDumpRow = tetris_bucket_getDumpRow(pBastet->pBucket, y);
@ -46,16 +50,65 @@ void tetris_bastet_calcActualColumnsScoreImpact(tetris_bastet_variant_t *pBastet
{ {
if ((nDumpRow & nColMask) != 0) if ((nDumpRow & nColMask) != 0)
{ {
pBastet->pActualColScoreImpact[x] = nStartRow - y + 1; pBastet->pColScore[x] = nStartRow - y + 1;
} }
nColMask <<= 1; nColMask <<= 1;
} }
} }
// printf("-------------------------------------------\n ");
// for (int i = 0; i < nWidth; ++i)
// {
// printf("%2d ", pBastet->pColScore[i]);
// }
// printf("\n");
// starting points for collision detection (to speedup things)
// calculate the maxima of the 4-tuples from column -3 to -1
pBastet->pStartingRow[0] = pBastet->pColScore[0];
pBastet->pStartingRow[1] = pBastet->pColScore[0] > pBastet->pColScore[1] ?
pBastet->pColScore[0] : pBastet->pColScore[1];
pBastet->pStartingRow[2] = pBastet->pStartingRow[1] > pBastet->pColScore[2]?
pBastet->pStartingRow[1] : pBastet->pColScore[2];
// calculate the maxima of the 4-tuples from column 0 to width-1
for (int8_t i = 0; i < nWidth; ++i)
{
int8_t t0 = pBastet->pColScore[i] > pBastet->pColScore[i + 1] ?
i : i + 1;
int8_t t1 = pBastet->pColScore[i + 2] > pBastet->pColScore[i + 3] ?
i + 2 : i + 3;
pBastet->pStartingRow[i + 3] =
pBastet->pColScore[t0] > pBastet->pColScore[t1] ?
pBastet->pColScore[t0] : pBastet->pColScore[t1];
}
// for (int i = 0; i < nWidth + 3; ++i)
// {
// printf("%2d ", pBastet->pStartingRow[i]);
// if (i == 2)
// printf("| ");
// }
// printf("\n");
// normalize to bucket geometry
for (uint8_t i = 0; i < nWidth + 3; ++i)
{
pBastet->pStartingRow[i] = nStartRow - pBastet->pStartingRow[i];
}
// calculate the score impact of every column // calculate the score impact of every column
for (int x = 0; x < nWidth; ++x) for (int x = 0; x < nWidth; ++x)
{ {
pBastet->pActualColScoreImpact[x] *= TETRIS_BASTET_HEIGHT_FACTOR; pBastet->pColScore[x] *= TETRIS_BASTET_HEIGHT_FACTOR;
} }
// for (int i = 0; i < nWidth + 3; ++i)
// {
// printf("%2d ", pBastet->pStartingRow[i]);
// if (i == 2)
// printf("| ");
// }
// printf("\n");
} }
@ -66,9 +119,8 @@ void tetris_bastet_calcActualColumnsScoreImpact(tetris_bastet_variant_t *pBastet
* @param nColum the column where the piece should be dropped * @param nColum the column where the piece should be dropped
* @param nStartCol the first column of the range to be predicted * @param nStartCol the first column of the range to be predicted
* @param nStopCol the last column of the range to be predicted * @param nStopCol the last column of the range to be predicted
* @return 0 if dropped piece would cause an overflow, 1 if prediction succeeds
*/ */
uint8_t tetris_bastet_calcPredictedColHeights(tetris_bastet_variant_t *pBastet, void tetris_bastet_calcPredictedColHeights(tetris_bastet_variant_t *pBastet,
tetris_piece_t *pPiece, tetris_piece_t *pPiece,
int8_t nDeepestRow, int8_t nDeepestRow,
int8_t nColumn, int8_t nColumn,
@ -80,11 +132,6 @@ uint8_t tetris_bastet_calcPredictedColHeights(tetris_bastet_variant_t *pBastet,
int8_t nHeight = 1; int8_t nHeight = 1;
uint16_t *pDump = tetris_bucket_predictBottomRow(&iterator, uint16_t *pDump = tetris_bucket_predictBottomRow(&iterator,
pBastet->pBucket, pPiece, nDeepestRow, nColumn); pBastet->pBucket, pPiece, nDeepestRow, nColumn);
if (pDump == NULL)
{
// an immediately returned NULL is caused by a full dump -> low score
return 0;
}
while (pDump != NULL) while (pDump != NULL)
{ {
uint16_t nColMask = 0x0001 << nStartCol; uint16_t nColMask = 0x0001 << nStartCol;
@ -99,7 +146,6 @@ uint8_t tetris_bastet_calcPredictedColHeights(tetris_bastet_variant_t *pBastet,
pDump = tetris_bucket_predictNextRow(&iterator); pDump = tetris_bucket_predictNextRow(&iterator);
++nHeight; ++nHeight;
} }
return 1;
} }
@ -186,7 +232,8 @@ void *tetris_bastet_construct(tetris_bucket_t *pBucket)
pBastet->pBucket = pBucket; pBastet->pBucket = pBucket;
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket); int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
pBastet->pActualColScoreImpact = (int8_t*) calloc(nWidth, sizeof(int8_t)); pBastet->pColScore = (uint16_t*) calloc(nWidth + 3, sizeof(uint16_t));
pBastet->pStartingRow = (int8_t*) calloc(nWidth + 3, sizeof(int8_t));
pBastet->pColHeights = (int8_t*) calloc(nWidth, sizeof(int8_t)); pBastet->pColHeights = (int8_t*) calloc(nWidth, sizeof(int8_t));
return pBastet; return pBastet;
@ -198,9 +245,9 @@ void tetris_bastet_destruct(void *pVariantData)
assert(pVariantData != 0); assert(pVariantData != 0);
tetris_bastet_variant_t *pBastetVariant = tetris_bastet_variant_t *pBastetVariant =
(tetris_bastet_variant_t *)pVariantData; (tetris_bastet_variant_t *)pVariantData;
if (pBastetVariant->pActualColScoreImpact != NULL) if (pBastetVariant->pColScore != NULL)
{ {
free(pBastetVariant->pActualColScoreImpact); free(pBastetVariant->pColScore);
} }
if (pBastetVariant->pColHeights != NULL) if (pBastetVariant->pColHeights != NULL)
{ {
@ -228,7 +275,13 @@ int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
// the row where the given piece collides // the row where the given piece collides
int8_t nDeepestRow = tetris_bucket_predictDeepestRow(pBastet->pBucket, int8_t nDeepestRow = tetris_bucket_predictDeepestRow(pBastet->pBucket,
pPiece, nColumn); pPiece, pBastet->pStartingRow[nColumn], 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 // modify score based on complete lines
int8_t nLines = tetris_bucket_predictCompleteLines(pBastet->pBucket, int8_t nLines = tetris_bucket_predictCompleteLines(pBastet->pBucket,
@ -251,13 +304,9 @@ int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1; nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1;
} }
// predicted column heights // predict column heights of this move
if (!tetris_bastet_calcPredictedColHeights(pBastet, pPiece, nDeepestRow, tetris_bastet_calcPredictedColHeights(pBastet, pPiece, nDeepestRow, nColumn,
nColumn, nStartCol, nStopCol)) nStartCol, nStopCol);
{
// in case the prediction fails we return the lowest possible score
return -32766;
}
// modify score based on predicted column heights // modify score based on predicted column heights
for (int x = 0; x < nWidth; ++x) for (int x = 0; x < nWidth; ++x)
@ -268,7 +317,7 @@ int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
} }
else else
{ {
nScore -= pBastet->pActualColScoreImpact[x]; nScore -= pBastet->pColScore[x];
} }
} }
@ -279,7 +328,7 @@ int16_t tetris_bastet_evaluateMove(tetris_bastet_variant_t *pBastet,
void tetris_bastet_evaluatePieces(tetris_bastet_variant_t *pBastet) void tetris_bastet_evaluatePieces(tetris_bastet_variant_t *pBastet)
{ {
// precache actual column heights // precache actual column heights
tetris_bastet_calcActualColumnsScoreImpact(pBastet); tetris_bastet_doPreprocessing(pBastet);
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket); int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
tetris_piece_t *pPiece = tetris_piece_construct(TETRIS_PC_LINE, tetris_piece_t *pPiece = tetris_piece_construct(TETRIS_PC_LINE,
TETRIS_PC_ANGLE_0); TETRIS_PC_ANGLE_0);

View File

@ -40,7 +40,8 @@ typedef struct tetris_bastet_variant_t
uint16_t nLines; /** number of completed lines */ uint16_t nLines; /** number of completed lines */
tetris_piece_t *pPreviewPiece; /** the piece for the preview */ tetris_piece_t *pPreviewPiece; /** the piece for the preview */
tetris_bucket_t *pBucket; /** bucket to be examined */ tetris_bucket_t *pBucket; /** bucket to be examined */
int8_t *pActualColScoreImpact; /** score impact of every column*/ uint16_t *pColScore; /** score impact of every column*/
int8_t *pStartingRow; /** starting point for collision*/
int8_t *pColHeights; /** predicted column heights */ int8_t *pColHeights; /** predicted column heights */
tetris_bastet_scorepair_t nPieceScore[7]; /** score for every piece */ tetris_bastet_scorepair_t nPieceScore[7]; /** score for every piece */
} }