Browse Source

squeezed 216 bytes

feature/2015
Christian Kroll 14 years ago
parent
commit
a8d2f7b47b
  1. 7
      games/tetris/bucket.h
  2. 42
      games/tetris/highscore.c
  3. 36
      games/tetris/highscore.h
  4. 16
      games/tetris/input.c
  5. 9
      games/tetris/input.h
  6. 55
      games/tetris/variant_bastet.c
  7. 12
      games/tetris/variant_bastet.h
  8. 9
      games/tetris/variant_fp.h
  9. 19
      games/tetris/variant_std.c
  10. 14
      games/tetris/variant_std.h
  11. 4
      games/tetris/variants.h

7
games/tetris/bucket.h

@ -2,6 +2,7 @@
#define BUCKET_H_
#include <stdint.h>
#include <limits.h>
#include "../../config.h"
#include "piece.h"
@ -11,6 +12,8 @@
***********/
#define TETRIS_BUCKET_INVALIDROW -4
#define TETRIS_BUCKET_MAX_COLUMNS (INT8_MAX - 4)
#define TETRIS_BUCKET_MAX_ROWS
/*********
@ -85,7 +88,7 @@ tetris_bucket_iterator_t;
/**
* constructs a bucket with the given dimensions
* @param nWidth width of bucket (4 <= n <= 16)
* @param nHeight height of bucket (4 <= n <= 124)
* @param nHeight height of bucket (4 <= n <= TETRIS_BUCKET_MAX_COLUMNS)
* @return pointer to a newly created bucket
*/
tetris_bucket_t *tetris_bucket_construct(int8_t nWidth,
@ -291,7 +294,7 @@ inline static tetris_bucket_status_t tetris_bucket_getStatus(tetris_bucket_t *p)
/**
* returns the given row of the dump (as bitmap)
* @param pBucket the bucket we want information from
* @param nRow the number of the row (0 <= nRow <= 124)
* @param nRow the number of the row (0 <= nRow <= TETRIS_BUCKET_MAX_COLUMNS)
* @return bitmap of the requested row (LSB is leftmost column)
*/
inline static uint16_t tetris_bucket_getDumpRow(tetris_bucket_t *pBucket,

42
games/tetris/highscore.c

@ -1,6 +1,7 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "../../config.h"
#include "../../scrolltext/scrolltext.h"
#include "../../joystick/joystick.h"
@ -24,7 +25,7 @@ uint16_t tetris_highscore_inputName(void)
while (1)
{
// we need our own blink interval
nBlink = (nBlink + 1) % 4;
nBlink = (nBlink + 1) % 4u;
// construct command for scrolltext and execute
static uint8_t const nOffset[3] = {15, 19, 23};
@ -100,42 +101,5 @@ uint16_t tetris_highscore_retrieveHighscore(tetris_highscore_index_t nIndex)
eeprom_read_word(&tetris_highscore[nIndex]);
// a score of 65535 is most likely caused by uninitialized EEPROM addresses
if (nHighscore == 65535)
{
nHighscore = 0;
}
return nHighscore;
}
void tetris_highscore_saveHighscore(tetris_highscore_index_t nIndex,
uint16_t nHighscore)
{
if (nHighscore > tetris_highscore_retrieveHighscore(nIndex))
{
eeprom_write_word(&tetris_highscore[nIndex], nHighscore);
}
}
uint16_t tetris_highscore_retrieveHighscoreName(tetris_highscore_index_t nIdx)
{
uint16_t nHighscoreName =
eeprom_read_word(&tetris_highscore_name[nIdx]);
// a value of 65535 is most likely caused by uninitialized EEPROM addresses
if (nHighscoreName == 65535)
{
nHighscoreName = 0;
}
return nHighscoreName;
}
void tetris_highscore_saveHighscoreName(tetris_highscore_index_t nIndex,
uint16_t nHighscoreName)
{
eeprom_write_word(&tetris_highscore_name[nIndex], nHighscoreName);
return nHighscore == UINT16_MAX ? 0 : nHighscore;
}

36
games/tetris/highscore.h

@ -2,6 +2,8 @@
#define TETRIS_HIGHSCORE_H_
#include <stdint.h>
#include "../../compat/eeprom.h"
/**
* indexes for different tetris variants
@ -20,6 +22,13 @@ enum tetris_highscore_index
typedef enum tetris_highscore_index tetris_highscore_index_t;
#endif
// global array for the high score
extern uint16_t tetris_highscore[TETRIS_HISCORE_END] EEMEM;
// global array for the champion's initials
extern uint16_t tetris_highscore_name[TETRIS_HISCORE_END] EEMEM;
/**
* lets the user enter his initials (three characters)
* @return name packed into a uint16_t
@ -37,11 +46,18 @@ uint16_t tetris_highscore_retrieveHighscore(tetris_highscore_index_t nIndex);
/**
* saves the high score into the storage (EEPROM)
* @param nIndex the variant dependent index of the high score
* @param nIdx the variant dependent index of the high score
* @param nHighscoreName the high score
*/
inline static
void tetris_highscore_saveHighscore(tetris_highscore_index_t nIndex,
uint16_t nHighscore);
uint16_t nHighscore)
{
if (nHighscore > tetris_highscore_retrieveHighscore(nIndex))
{
eeprom_write_word(&tetris_highscore[nIndex], nHighscore);
}
}
/**
@ -49,7 +65,14 @@ void tetris_highscore_saveHighscore(tetris_highscore_index_t nIndex,
* @param nIdx the variant dependent index of the high score
* @return the initials of the champion packed into a uint16_t
*/
uint16_t tetris_highscore_retrieveHighscoreName(tetris_highscore_index_t nIdx);
inline static
uint16_t tetris_highscore_retrieveHighscoreName(tetris_highscore_index_t nIdx)
{
uint16_t nHighscoreName =
eeprom_read_word(&tetris_highscore_name[nIdx]);
return nHighscoreName;
}
/**
@ -57,7 +80,12 @@ uint16_t tetris_highscore_retrieveHighscoreName(tetris_highscore_index_t nIdx);
* @param nIndex the variant dependent index of the high score
* @param nHighscoreName the initials of the champion packed into a uint16_t
*/
inline static
void tetris_highscore_saveHighscoreName(tetris_highscore_index_t nIndex,
uint16_t nHighscoreName);
uint16_t nHighscoreName)
{
eeprom_write_word(&tetris_highscore_name[nIndex], nHighscoreName);
}
#endif /*TETRIS_HIGHSCORE_H_*/

16
games/tetris/input.c

@ -140,23 +140,11 @@ static void tetris_input_chatterProtect(tetris_input_t *pIn,
* @return mapped tetris command
* @see tetris_input_command_t
*/
static
tetris_input_command_t tetris_input_mapCommand(tetris_bearing_t nBearing,
tetris_input_command_t nCmd)
{
static tetris_input_command_t const nMapping[] PROGMEM =
{
TETRIS_INCMD_DOWN, TETRIS_INCMD_ROT_CW, TETRIS_INCMD_RIGHT,
TETRIS_INCMD_LEFT,
TETRIS_INCMD_RIGHT, TETRIS_INCMD_LEFT, TETRIS_INCMD_ROT_CW,
TETRIS_INCMD_DOWN,
TETRIS_INCMD_ROT_CW, TETRIS_INCMD_DOWN, TETRIS_INCMD_LEFT,
TETRIS_INCMD_RIGHT
};
return (nBearing == TETRIS_BEARING_0) || (nCmd >= TETRIS_INCMD_ROT_CCW) ?
nCmd : (PM(nMapping[(nBearing - 1) * 4 + nCmd]));
return (nCmd < TETRIS_INCMD_ROT_CCW) ? (nCmd - nBearing + 4) % 4u : nCmd;
}

9
games/tetris/input.h

@ -33,9 +33,9 @@
*/
enum tetris_input_command
{
TETRIS_INCMD_LEFT, /**< move piece left */
TETRIS_INCMD_RIGHT, /**< move piece right */
TETRIS_INCMD_DOWN, /**< lower piece by one row */
TETRIS_INCMD_LEFT, /**< move piece left */
TETRIS_INCMD_ROT_CW, /**< rotate clockwise */
TETRIS_INCMD_ROT_CCW, /**< rotate counter clockwise */
TETRIS_INCMD_DROP, /**< move piece to the ground immediately */
@ -43,6 +43,13 @@ enum tetris_input_command
TETRIS_INCMD_PAUSE, /**< pause the game */
TETRIS_INCMD_NONE /**< idle (must alway be the last one) */
};
/* R D L C
* RDLC 0 1 2 3
* DLCR -1 -1 -1 -1
* LCRD -2 -2 -2 -2
* CRDL -3 -3 -3 -3
*/
#ifdef NDEBUG
typedef uint8_t tetris_input_command_t;
#else

55
games/tetris/variant_bastet.c

@ -2,6 +2,7 @@
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <limits.h>
#include "../../random/prng.h"
#include "../../compat/pgmspace.h"
#include "../../menu/menu.h"
@ -21,6 +22,12 @@
#define TETRIS_BASTET_HEIGHT_FACTOR 5
#ifdef RANDOM_SUPPORT
#define RANDOM8() random8()
#else
#define RANDOM8() (rand() % (UINT8_MAX + 1))
#endif
/***************************
* non-interface functions *
@ -34,21 +41,18 @@
static void tetris_bastet_doPreprocessing(tetris_bastet_variant_t *pBastet)
{
// retrieve sane start and stop values for the column and row indices
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
int8_t nStartRow = tetris_bucket_getHeight(pBastet->pBucket) - 1;
int8_t nStopRow = tetris_bucket_getFirstTaintedRow(pBastet->pBucket);
int8_t const nWidth = tetris_bucket_getWidth(pBastet->pBucket);
int8_t const nStartRow = tetris_bucket_getHeight(pBastet->pBucket) - 1;
int8_t const nStopRow = tetris_bucket_getFirstTaintedRow(pBastet->pBucket);
// clear old precalculated scores
for (uint8_t i = 0; i < nWidth + 3; ++i)
{
pBastet->pColScore[i] = 0;
}
// clear old precalculated scores (last three elements are always 0)
memset(pBastet->pColScore, 0, nWidth * sizeof(int16_t));
// calculate the column heights of the actual bucket configuration
// NOTE: in this loop, pColScore contains the actual column heights,
// NOTE: in this loop, pColScore stores the actual column heights,
// later it will contain the "score impact" of every unchanged column
for (int8_t y = nStartRow; y >= nStopRow; --y)
{
uint16_t nDumpRow = tetris_bucket_getDumpRow(pBastet->pBucket, y);
uint16_t const nDumpRow = tetris_bucket_getDumpRow(pBastet->pBucket, y);
uint16_t nColMask = 0x0001;
for (uint8_t x = 0; x < nWidth; ++x)
{
@ -70,25 +74,21 @@ static void tetris_bastet_doPreprocessing(tetris_bastet_variant_t *pBastet)
// calculate the maxima of the 4-tuples from column 0 to width-1
for (uint8_t i = 0; i < nWidth; ++i)
{
// casting from int16_t to int8_t is safe here, since at this point
// pColScore only contains column heights which never exceed INT8_MAX-4
int8_t t0 = pBastet->pColScore[i] > pBastet->pColScore[i + 1] ?
i : i + 1;
pBastet->pColScore[i] : pBastet->pColScore[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];
pBastet->pColScore[i + 2] : pBastet->pColScore[i + 3];
pBastet->pStartingRow[i + 3] = t0 > t1 ? t0 : t1;
}
// normalize to bucket geometry
for (uint8_t i = 0; i < nWidth + 3; ++i)
for (uint8_t i = nWidth + 3; i--;)
{
// normalize to bucket geometry
pBastet->pStartingRow[i] = nStartRow - pBastet->pStartingRow[i];
}
// calculate the score impact of every column
for (uint8_t x = 0; x < nWidth; ++x)
{
pBastet->pColScore[x] *= TETRIS_BASTET_HEIGHT_FACTOR;
// finally calculate the score impact of every column
pBastet->pColScore[i] *= TETRIS_BASTET_HEIGHT_FACTOR;
}
}
@ -309,7 +309,7 @@ void *tetris_bastet_construct(tetris_bucket_t *pBucket)
pBastet->pBucket = pBucket;
int8_t nWidth = tetris_bucket_getWidth(pBastet->pBucket);
pBastet->pColScore = (uint16_t*) calloc(nWidth + 3, sizeof(uint16_t));
pBastet->pColScore = (int16_t*) calloc(nWidth + 3, sizeof(int16_t));
pBastet->pStartingRow = (int8_t*) calloc(nWidth + 3, sizeof(int8_t));
pBastet->pColHeights = (int8_t*) calloc(nWidth, sizeof(int8_t));
@ -349,7 +349,7 @@ tetris_piece_t* tetris_bastet_choosePiece(void *pVariantData)
// perturb score (-2 to +2) to avoid stupid tie handling
for (uint8_t i = 0; i < 7; ++i)
{
pBastet->nPieceScore[i].nScore += random8() % 5 - 2;
pBastet->nPieceScore[i].nScore += RANDOM8() % 5 - 2;
}
// sort pieces by their score in ascending order
@ -366,7 +366,7 @@ tetris_piece_t* tetris_bastet_choosePiece(void *pVariantData)
tetris_piece_t *pPiece = NULL;
uint8_t const nPercent[4] = {191, 235, 250, 255};
uint8_t const nRnd = random8();
uint8_t const nRnd = RANDOM8();
for (uint8_t i = 0; i < 4; ++i)
{
if (nRnd <= nPercent[i])
@ -503,7 +503,8 @@ tetris_highscore_index_t tetris_bastet_getHighscoreIndex(void *pVariantData)
void tetris_bastet_setLastInput(void *pVariantData,
tetris_input_command_t inCmd)
tetris_input_command_t inCmd,
uint8_t bMoveOk)
{
return;
}

12
games/tetris/variant_bastet.h

@ -40,7 +40,7 @@ typedef struct tetris_bastet_variant
uint16_t nLines; /** number of completed lines */
tetris_piece_t *pPreviewPiece; /** the piece for the preview */
tetris_bucket_t *pBucket; /** bucket to be examined */
uint16_t *pColScore; /** score impact of every column*/
int16_t *pColScore; /** score impact of every column*/
int8_t *pStartingRow; /** starting point for collision*/
int8_t *pColHeights; /** predicted column heights */
tetris_bastet_scorepair_t nPieceScore[7]; /** score for every piece */
@ -192,12 +192,14 @@ tetris_highscore_index_t tetris_bastet_getHighscoreIndex(void *pVariantData);
/**
* informs the bastet instance about the player's last move
* @param pVariantData the variant data object we want to modify
* @param inCmd player's last command
* inform the Bastet instance about the player's last input
* @param pVariantData the Bastet object we want to modify
* @param inCmd the last issued command
* @param bMoveOk 1 if the last move was possible, otherwise 0
*/
void tetris_bastet_setLastInput(void *pVariantData,
tetris_input_command_t inCmd);
tetris_input_command_t inCmd,
uint8_t bMoveOk);
/**

9
games/tetris/variant_fp.h

@ -33,7 +33,14 @@ tetris_variant_t const tetrisFpVariant;
tetris_highscore_index_t tetris_fp_getHighscoreIndex(void *pVariantData);
/**
* inform the First Person Tetris instance about the player's last input
* @param pVariantData the First Person Tetris data object we want to modify
* @param inCmd the last issued command
* @param bMoveOk 1 if the last move was possible, otherwise 0
*/
void tetris_fp_setLastInput(void *pVariantData,
tetris_input_command_t inCmd);
tetris_input_command_t inCmd,
uint8_t bMoveOk);
#endif /*VARIANT_FP_H_*/

19
games/tetris/variant_std.c

@ -16,6 +16,17 @@
#include "variant_std.h"
/***********
* defines *
***********/
#ifdef RANDOM_SUPPORT
#define RANDOM8() random8()
#else
#define RANDOM8() rand()
#endif
/***************
* entry point *
***************/
@ -74,8 +85,9 @@ void *tetris_std_construct(tetris_bucket_t *pBucket)
malloc(sizeof(tetris_standard_variant_t));
assert(pStdVariant != NULL);
memset(pStdVariant, 0, sizeof(tetris_standard_variant_t));
// don't begin with S and Z pieces according to official tetris guidelines
pStdVariant->pPreviewPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_piece_construct(RANDOM8() % 5, TETRIS_PC_ANGLE_0);
return pStdVariant;
}
@ -103,7 +115,7 @@ tetris_piece_t* tetris_std_choosePiece(void *pVariantData)
(tetris_standard_variant_t *)pVariantData;
tetris_piece_t *pPiece = pStdVariant->pPreviewPiece;
pStdVariant->pPreviewPiece =
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
tetris_piece_construct(RANDOM8() % 7, TETRIS_PC_ANGLE_0);
return pPiece;
}
@ -241,7 +253,8 @@ tetris_highscore_index_t tetris_std_getHighscoreIndex(void *pVariantData)
void tetris_std_setLastInput(void *pVariantData,
tetris_input_command_t inCmd)
tetris_input_command_t inCmd,
uint8_t bMoveOk)
{
}

14
games/tetris/variant_std.h

@ -175,10 +175,22 @@ tetris_piece_t* tetris_std_getPreviewPiece(void *pVariantData);
tetris_highscore_index_t tetris_std_getHighscoreIndex(void *pVariantData);
/**
* inform the Tetris instance about the player's last input
* @param pVariantData the Tetris data object we want to modify
* @param inCmd the last issued command
* @param bMoveOk 1 if the last move was possible, otherwise 0
*/
void tetris_std_setLastInput(void *pVariantData,
tetris_input_command_t inCmd);
tetris_input_command_t inCmd,
uint8_t bMoveOk);
/**
* returns the bearing which is requested by the Tetris instance
* @param pVariantData the variant data object we want information from
* @return always TETRIS_BEARING_0 as we don't change the bearing in Bastet
*/
tetris_bearing_t tetris_std_getBearing(void *pVariantData);
#endif /*VARIANT_STD_H_*/

4
games/tetris/variants.h

@ -134,9 +134,11 @@ typedef struct tetris_variant
* inform the variant about the player's last input
* @param pVariantData the variant data object we want to modify
* @param inCmd the last issued command
* @param bMoveOk 1 if the last move was possible, otherwise 0
*/
void (*setLastInput)(void *pVariantData,
tetris_input_command_t inCmd);
tetris_input_command_t inCmd,
uint8_t bMoveOk);
/**
* retrieves the variant's preferred bearing of the bucket

Loading…
Cancel
Save