borgware-2d/games/tetris/variant_std.c

275 lines
6.3 KiB
C

/**
* \addtogroup tetris
* @{
*/
/**
* @file variant_std.c
* @brief Implementation of the standard Tetris module.
* @details The routines of this file provide selection of new pieces, line
* counting, score calculation, high score management, adjustment of
* the bucket's bearing and so on.
* @author Christian Kroll
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include "../../config.h"
#include "../../random/prng.h"
#include "../../compat/pgmspace.h"
#include "../../menu/menu.h"
#include "bearing.h"
#include "piece.h"
#include "highscore.h"
#include "bucket.h"
#include "input.h"
#include "variants.h"
#include "tetris_main.h"
#include "variant_std.h"
/***********
* defines *
***********/
#ifdef RANDOM_SUPPORT
#define RANDOM8() random8()
#else
#define RANDOM8() rand()
#endif
/***************
* entry point *
***************/
#ifdef GAME_TETRIS
#ifdef MENU_SUPPORT
// Tetris icon, MSB is leftmost pixel
static uint8_t const tetris_icon[8] PROGMEM =
{ 0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0 };
game_descriptor_t tetris_game_descriptor
__attribute__((section(".game_descriptors"))) =
{
&tetris,
tetris_icon,
};
#endif
void tetris(void)
{
tetris_main(&tetrisStdVariant);
}
#endif
/****************************
* construction/destruction *
****************************/
#ifdef GAME_TETRIS
tetris_variant_t const tetrisStdVariant =
{
&tetris_std_construct,
&tetris_std_destruct,
&tetris_std_choosePiece,
&tetris_std_singleDrop,
&tetris_std_completeDrop,
&tetris_std_removedLines,
&tetris_std_getScore,
&tetris_std_getHighscore,
&tetris_std_setHighscore,
&tetris_std_getHighscoreName,
&tetris_std_setHighscoreName,
&tetris_std_getLevel,
&tetris_std_getLines,
&tetris_std_getPreviewPiece,
&tetris_std_getHighscoreIndex,
&tetris_std_setLastInput,
&tetris_std_getBearing
};
#endif
void *tetris_std_construct(tetris_bucket_t *pBucket)
{
tetris_standard_variant_t *pStdVariant = (tetris_standard_variant_t *)
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() % 5, TETRIS_PC_ANGLE_0);
return pStdVariant;
}
void tetris_std_destruct(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
tetris_piece_destruct(pStdVariant->pPreviewPiece);
free(pStdVariant);
}
/*****************************
* variant related functions *
*****************************/
tetris_piece_t* tetris_std_choosePiece(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
tetris_piece_t *pPiece = pStdVariant->pPreviewPiece;
pStdVariant->pPreviewPiece =
tetris_piece_construct(RANDOM8() % 7, TETRIS_PC_ANGLE_0);
return pPiece;
}
void tetris_std_singleDrop(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
++pStdVariant->nScore;
}
void tetris_std_completeDrop(void *pVariantData,
uint8_t nLines)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
pStdVariant->nScore += nLines * 2u;
}
void tetris_std_removedLines(void *pVariantData,
uint8_t nRowMask)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
uint8_t nLines = tetris_bucket_calculateLines(nRowMask);
assert(nLines <= 4);
pStdVariant->nLines += nLines;
pStdVariant->nLevel = ((pStdVariant->nLines / 10) < TETRIS_INPUT_LEVELS) ?
(pStdVariant->nLines / 10) : (TETRIS_INPUT_LEVELS - 1);
static uint16_t const nScoreTable[] PROGMEM = {0, 50, 150, 250, 400};
pStdVariant->nScore += pgm_read_word(&nScoreTable[nLines]);
}
/*****************
* get functions *
*****************/
uint16_t tetris_std_getScore(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nScore;
}
uint16_t tetris_std_getHighscore(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nHighscore;
}
void tetris_std_setHighscore(void *pVariantData,
uint16_t nHighscore)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
pStdVariant->nHighscore = nHighscore;
}
uint16_t tetris_std_getHighscoreName(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nHighscoreName;
}
void tetris_std_setHighscoreName(void *pVariantData,
uint16_t nHighscoreName)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
pStdVariant->nHighscoreName = nHighscoreName;
}
uint8_t tetris_std_getLevel(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nLevel;
}
uint16_t tetris_std_getLines(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nLines;
}
tetris_piece_t* tetris_std_getPreviewPiece(void *pVariantData)
{
assert(pVariantData != 0);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->pPreviewPiece;
}
tetris_highscore_index_t tetris_std_getHighscoreIndex(void *pVariantData)
{
return TETRIS_HISCORE_TETRIS;
}
void tetris_std_setLastInput(void *pVariantData,
tetris_input_command_t inCmd,
uint8_t bMoveOk)
{
}
tetris_bearing_t tetris_std_getBearing(void *pVariantData)
{
assert (pVariantData != NULL);
tetris_standard_variant_t *pStdVariant =
(tetris_standard_variant_t *)pVariantData;
return pStdVariant->nBearing;
}
/*@}*/