synced with my personal Bastet tree
This commit is contained in:
parent
957457ef37
commit
903072815b
|
@ -13,13 +13,13 @@ ifeq ($(ANIMATION_MATRIX),y)
|
|||
SRC += matrix.c
|
||||
endif
|
||||
|
||||
ifeq ($(ANIMATION_STONEFLY),y)
|
||||
SRC += stonefly.c
|
||||
endif
|
||||
ifeq ($(ANIMATION_STONEFLY),y)
|
||||
SRC += stonefly.c
|
||||
endif
|
||||
|
||||
ifeq ($(ANIMATION_FLYINGDOTS),y)
|
||||
SRC += flyingdots.c
|
||||
endif
|
||||
ifeq ($(ANIMATION_FLYINGDOTS),y)
|
||||
SRC += flyingdots.c
|
||||
endif
|
||||
|
||||
ifeq ($(ANIMATION_GAMEOFLIFE),y)
|
||||
SRC += gameoflife.c
|
||||
|
|
|
@ -19,7 +19,7 @@ export HOSTCC
|
|||
|
||||
# flags for the compiler
|
||||
CFLAGS ?= -Wall -W -Wno-unused-parameter -Wno-sign-compare
|
||||
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline
|
||||
CFLAGS += -g -Os -std=gnu99 -fgnu89-inline -DNDEBUG
|
||||
|
||||
# flags for the linker
|
||||
LDFLAGS += -T ./avr5.x -mmcu=$(MCU)
|
||||
|
@ -33,7 +33,7 @@ MACHINE = $(shell uname -m)
|
|||
#$(info $(OSTYPE))
|
||||
|
||||
ifeq ($(OSTYPE),cygwin)
|
||||
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O2 -D_WIN32 -mno-cygwin
|
||||
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -mno-cygwin
|
||||
LDFLAGS_SIM = -Wl -mno-cygwin -T simulator/i386pe.x
|
||||
LIBS_SIM = -lglut32 -lglu32 -lopengl32
|
||||
else
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "animations/programm.h"
|
||||
#include "animations/matrix.h"
|
||||
#include "animations/gameoflife.h"
|
||||
#include "animations/stonefly.h"
|
||||
#include "animations/stonefly.h"
|
||||
#include "animations/flyingdots.h"
|
||||
#include "borg_hw/borg_hw.h"
|
||||
#include "can/borg_can.h"
|
||||
|
@ -92,12 +92,12 @@ void display_loop(){
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATION_STONEFLY
|
||||
case 9:
|
||||
stonefly();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATION_STONEFLY
|
||||
case 9:
|
||||
stonefly();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATION_GAMEOFLIFE
|
||||
case 10:
|
||||
gameoflife();
|
||||
|
@ -109,10 +109,10 @@ void display_loop(){
|
|||
flyingdots();
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ANIMATION_MHERWEG
|
||||
case 11:
|
||||
case 11:
|
||||
flydots();
|
||||
lines1();
|
||||
dots1();
|
||||
movinglines();
|
||||
|
@ -141,10 +141,9 @@ void display_loop(){
|
|||
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 42:
|
||||
mode = 1;
|
||||
break;
|
||||
case 42:
|
||||
mode = 1;
|
||||
break;
|
||||
|
||||
#ifdef MENU_SUPPORT
|
||||
case 43:
|
||||
|
|
|
@ -2,6 +2,7 @@ mainmenu_option next_comment
|
|||
comment "Games"
|
||||
|
||||
dep_bool "tetris" GAME_TETRIS $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
dep_bool "bastet" GAME_BASTET $GAME_TETRIS
|
||||
dep_bool "space invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
dep_bool "snake" GAME_SNAKE $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@ TOPDIR = ../..
|
|||
|
||||
include $(TOPDIR)/defaults.mk
|
||||
|
||||
SRC = piece.c playfield.c view.c logic.c input.c bast.c
|
||||
ifeq ($(GAME_BASTET),y)
|
||||
SRC = piece.c playfield.c view.c logic.c input.c bast.c
|
||||
else
|
||||
SRC = piece.c playfield.c view.c logic.c input.c
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../random/prng.h"
|
||||
#include "piece.h"
|
||||
#include "playfield.h"
|
||||
#include "bast.h"
|
||||
|
@ -13,18 +14,46 @@
|
|||
/* Function: tetris_bastet_clearColHeights;
|
||||
* Description: resets the array for the column heights
|
||||
* Argument pBastet: bastet instance whose array should be reset
|
||||
* Argument nStart: start index
|
||||
* Argument nStop: stop index
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_bastet_clearColHeights(tetris_bastet_t *pBastet)
|
||||
void tetris_bastet_clearColHeights(tetris_bastet_t *pBastet,
|
||||
int8_t nStart,
|
||||
int8_t nStop)
|
||||
{
|
||||
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
|
||||
for (int i = 0; i < nWidth; ++i)
|
||||
for (int i = nStart; i <= nStop; ++i)
|
||||
{
|
||||
pBastet->pColHeights[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_bastet_qsortCompare
|
||||
* Description: compare function for quick sorting the pieces by score
|
||||
* Argument pa: the first value to compare
|
||||
* Argument pb: the second value to compare
|
||||
* Return value: void
|
||||
*/
|
||||
int tetris_bastet_qsortCompare(const void *pa, const void *pb)
|
||||
{
|
||||
tetris_bastet_scorepair_t *pScoreA = (tetris_bastet_scorepair_t *)pa;
|
||||
tetris_bastet_scorepair_t *pScoreB = (tetris_bastet_scorepair_t *)pb;
|
||||
if (pScoreA->nScore == pScoreB->nScore)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (pScoreA->nScore < pScoreB->nScore)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* construction/destruction *
|
||||
****************************/
|
||||
|
@ -43,7 +72,7 @@ tetris_bastet_t* tetris_bastet_construct(tetris_playfield_t *pPl)
|
|||
|
||||
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
|
||||
pBastet->pColHeights = (int8_t*) calloc(nWidth, sizeof(int8_t));
|
||||
tetris_bastet_clearColHeights(pBastet);
|
||||
tetris_bastet_clearColHeights(pBastet, 0, nWidth - 1);
|
||||
|
||||
return pBastet;
|
||||
}
|
||||
|
@ -87,20 +116,46 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
|
|||
pPiece, nColumn);
|
||||
nScore += 5000 * nLines;
|
||||
|
||||
// determine sane start and stop columns whose heights we want to calculate
|
||||
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
|
||||
int8_t nStartCol = ((nColumn - 1) < 0) ? 0 : nColumn - 1;
|
||||
int8_t nStopCol;
|
||||
// do we start at the left most position?
|
||||
if (nColumn <= -3)
|
||||
{
|
||||
// in case we start at the left most position we calculate all heights
|
||||
nStopCol = nWidth - 1;
|
||||
// reset all column heights to zero
|
||||
tetris_bastet_clearColHeights(pBastet, 0 , nWidth);
|
||||
}
|
||||
// if not, only calculate columns which are affected by the piece
|
||||
else
|
||||
{
|
||||
nStopCol = (nColumn + 3) < nWidth ? nColumn + 3 : nWidth - 1;
|
||||
// clear affected column heights to prevent miscalculations
|
||||
tetris_bastet_clearColHeights(pBastet, nStartCol, nStopCol);
|
||||
}
|
||||
|
||||
// go through every row and calculate column heights
|
||||
tetris_playfield_iterator_t iterator;
|
||||
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
|
||||
int8_t nHeight = 1;
|
||||
uint16_t *pDump = tetris_playfield_predictBottomRow(&iterator,
|
||||
pBastet->pPlayfield, pPiece, nColumn);
|
||||
if (pDump == NULL)
|
||||
{
|
||||
// an immediately returned NULL is caused by a full dump -> low score
|
||||
return -32766;
|
||||
}
|
||||
while (pDump != NULL)
|
||||
{
|
||||
for (int x = 0; x < nWidth; ++x)
|
||||
uint16_t nColMask = 0x0001 << nStartCol;
|
||||
for (int x = nStartCol; x <= nStopCol; ++x)
|
||||
{
|
||||
if ((*pDump & (0x0001 << x)) != 0)
|
||||
if ((*pDump & nColMask) != 0)
|
||||
{
|
||||
pBastet->pColHeights[x] = nHeight;
|
||||
}
|
||||
nColMask <<= 1;
|
||||
}
|
||||
pDump = tetris_playfield_predictNextRow(&iterator);
|
||||
++nHeight;
|
||||
|
@ -111,8 +166,84 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
|
|||
nScore -= 5 * pBastet->pColHeights[x];
|
||||
}
|
||||
|
||||
// reset column height array for later use
|
||||
tetris_bastet_clearColHeights(pBastet);
|
||||
|
||||
return nScore;
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_bastet_minimax
|
||||
* Description: calculates the best possible score for every piece
|
||||
* Argument pBastet: the bastet instance of interest
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_bastet_minimax(tetris_bastet_t *pBastet)
|
||||
{
|
||||
int8_t nWidth = tetris_playfield_getWidth(pBastet->pPlayfield);
|
||||
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_changeShape(pPiece, nBlock);
|
||||
int8_t nAngleCount = tetris_piece_angleCount(pPiece);
|
||||
for (int8_t nAngle = TETRIS_PC_ANGLE_0; nAngle < nAngleCount; ++nAngle)
|
||||
{
|
||||
tetris_piece_changeAngle(pPiece, nAngle);
|
||||
for (int8_t nCol = -3; nCol < nWidth; ++nCol)
|
||||
{
|
||||
int16_t nScore = tetris_bastet_evalPos(pBastet, pPiece, nCol);
|
||||
nMaxScore = nMaxScore > nScore ? nMaxScore : nScore;
|
||||
}
|
||||
}
|
||||
pBastet->nPieceScores[nBlock].shape = nBlock;
|
||||
pBastet->nPieceScores[nBlock].nScore = nMaxScore;
|
||||
}
|
||||
tetris_piece_destruct(pPiece);
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_bastet_choosePiece
|
||||
* Description: calculates the worst possible piece
|
||||
* Argument pBastet: the bastet instance of interest
|
||||
* Return value: the worst possible piece
|
||||
*/
|
||||
tetris_piece_t* tetris_bastet_choosePiece(tetris_bastet_t *pBastet)
|
||||
{
|
||||
const uint8_t nPercent[7] = {75, 92, 98, 100, 100, 100, 100};
|
||||
tetris_bastet_minimax(pBastet);
|
||||
|
||||
// perturb score (-2 to +2) to avoid stupid tie handling
|
||||
for (uint8_t i = 0; i < 7; ++i)
|
||||
{
|
||||
pBastet->nPieceScores[i].nScore += random8() % 5 - 2;
|
||||
}
|
||||
|
||||
qsort(pBastet->nPieceScores, 7, sizeof(tetris_bastet_scorepair_t),
|
||||
&tetris_bastet_qsortCompare);
|
||||
|
||||
uint8_t rnd = rand() % 100;
|
||||
for (uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
if (rnd < nPercent[i])
|
||||
{
|
||||
return tetris_piece_construct(pBastet->nPieceScores[i].shape,
|
||||
TETRIS_PC_ANGLE_0);
|
||||
}
|
||||
}
|
||||
|
||||
//should not arrive here
|
||||
return tetris_piece_construct(pBastet->nPieceScores[0].shape,
|
||||
TETRIS_PC_ANGLE_0);
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_bastet_choosePreviewPiece
|
||||
* Description: returns the best possible piece
|
||||
* (run tetris_bastet_choosePiece first!)
|
||||
* Argument pBastet: the bastet instance of interest
|
||||
* Return value: the worst possible piece
|
||||
*/
|
||||
tetris_piece_t* tetris_bastet_choosePreviewPiece(tetris_bastet_t *pBastet)
|
||||
{
|
||||
return tetris_piece_construct(pBastet->nPieceScores[6].shape,
|
||||
TETRIS_PC_ANGLE_0);
|
||||
}
|
||||
|
|
|
@ -9,10 +9,19 @@
|
|||
* types *
|
||||
*********/
|
||||
|
||||
typedef struct tetris_bastet_scorepair_t
|
||||
{
|
||||
tetris_piece_shape_t shape;
|
||||
int16_t nScore;
|
||||
}
|
||||
tetris_bastet_scorepair_t;
|
||||
|
||||
|
||||
typedef struct tetris_bastet_t
|
||||
{
|
||||
tetris_playfield_t *pPlayfield; // the playfield to be examined
|
||||
int8_t *pColHeights; // array of calculated column heights
|
||||
tetris_playfield_t *pPlayfield; // the playfield to be examined
|
||||
int8_t *pColHeights; // array of calculated heights
|
||||
tetris_bastet_scorepair_t nPieceScores[7]; // score for every piece
|
||||
}
|
||||
tetris_bastet_t;
|
||||
|
||||
|
@ -52,4 +61,17 @@ int16_t tetris_bastet_evalPos(tetris_bastet_t *pBastet,
|
|||
tetris_piece_t *pPiece,
|
||||
int8_t nColumn);
|
||||
|
||||
|
||||
/* Function: tetris_bastet_minimax
|
||||
* Description: calculates the best possible score for every piece
|
||||
* Argument pBastet: the bastet instance of interest
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_bastet_minimax();
|
||||
|
||||
|
||||
tetris_piece_t* tetris_bastet_choosePiece(tetris_bastet_t *pBastet);
|
||||
|
||||
tetris_piece_t* tetris_bastet_choosePreviewPiece(tetris_bastet_t *pBastet);
|
||||
|
||||
#endif /* BAST_H_ */
|
||||
|
|
|
@ -8,37 +8,54 @@
|
|||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "../../autoconf.h"
|
||||
#include "../../compat/eeprom.h"
|
||||
#include "../../compat/pgmspace.h"
|
||||
#include "../../menu/menu.h"
|
||||
#include "../../random/prng.h"
|
||||
|
||||
#include "logic.h"
|
||||
#include "piece.h"
|
||||
#include "playfield.h"
|
||||
#include "view.h"
|
||||
#include "input.h"
|
||||
#include "../../random/prng.h"
|
||||
|
||||
#ifdef GAME_BASTET
|
||||
#include "bast.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EEMEM
|
||||
/***********************
|
||||
* Highscore in EEPROM *
|
||||
***********************/
|
||||
/***********************
|
||||
* Highscore in EEPROM *
|
||||
***********************/
|
||||
|
||||
uint16_t tetris_logic_nHighscore EEMEM;
|
||||
uint16_t tetris_logic_nHighscore EEMEM;
|
||||
#endif
|
||||
|
||||
// MSB is leftmost pixel
|
||||
static uint8_t icon[8] PROGMEM =
|
||||
{0x0f, 0x0f, 0xc3, 0xdb, 0xdb, 0xc3, 0xf0, 0xf0}; // Tetris icon
|
||||
|
||||
// Tetris icon, MSB is leftmost pixel
|
||||
void tetris();
|
||||
|
||||
game_descriptor_t tetris_game_descriptor __attribute__((section(".game_descriptors"))) ={
|
||||
&tetris,
|
||||
icon,
|
||||
static uint8_t 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,
|
||||
};
|
||||
|
||||
#ifdef GAME_BASTET
|
||||
// Bastet icon, MSB is leftmost pixel
|
||||
static uint8_t bastet_icon[8] PROGMEM =
|
||||
{ 0x81, 0xc3, 0xff, 0x99, 0xff, 0xff, 0x66, 0x3c };
|
||||
game_descriptor_t bastet_game_descriptor
|
||||
__attribute__((section(".game_descriptors"))) =
|
||||
{
|
||||
&tetris_bastet,
|
||||
bastet_icon,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/***************************
|
||||
* non-interface functions *
|
||||
|
@ -104,7 +121,7 @@ void tetris_logic_saveHighscore(uint16_t nHighscore)
|
|||
*/
|
||||
tetris_logic_t *tetris_logic_construct()
|
||||
{
|
||||
tetris_logic_t *pLogic = (tetris_logic_t *)malloc(sizeof(tetris_logic_t));
|
||||
tetris_logic_t *pLogic = (tetris_logic_t *) malloc(sizeof(tetris_logic_t));
|
||||
assert(pLogic != NULL);
|
||||
memset(pLogic, 0, sizeof(tetris_logic_t));
|
||||
return pLogic;
|
||||
|
@ -130,7 +147,28 @@ void tetris_logic_destruct(tetris_logic_t *pLogic)
|
|||
* Description: runs the tetris game
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris ()
|
||||
void tetris()
|
||||
{
|
||||
tetris_main(0);
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_bastet
|
||||
* Description: runs the bastet game
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_bastet()
|
||||
{
|
||||
tetris_main(1);
|
||||
}
|
||||
|
||||
|
||||
/* Function: tetris_main
|
||||
* Description: runs the tetris game
|
||||
* Argument nBastet: 0 for normal Tetris, 1 for Bastet
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_main(int8_t nBastet)
|
||||
{
|
||||
// get view dependent dimensions of the playfield
|
||||
int8_t nWidth;
|
||||
|
@ -145,6 +183,9 @@ void tetris ()
|
|||
tetris_playfield_t *pPl = tetris_playfield_construct(nWidth, nHeight);
|
||||
tetris_input_t *pIn = tetris_input_construct();
|
||||
tetris_view_t *pView = tetris_view_construct(pLogic, pPl);
|
||||
#ifdef GAME_BASTET
|
||||
tetris_bastet_t *pBastet;
|
||||
#endif
|
||||
|
||||
// runtime variable
|
||||
int8_t nPieceRow;
|
||||
|
@ -157,15 +198,28 @@ void tetris ()
|
|||
}
|
||||
|
||||
// initialize current and next piece
|
||||
tetris_piece_t *pPiece = NULL;
|
||||
tetris_piece_t *pNextPiece = pPiece =
|
||||
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
|
||||
tetris_piece_t *pPiece;
|
||||
tetris_piece_t *pNextPiece;
|
||||
#ifdef GAME_BASTET
|
||||
if (nBastet)
|
||||
{
|
||||
pBastet = tetris_bastet_construct(pPl);
|
||||
pNextPiece = pPiece = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
pNextPiece = pPiece =
|
||||
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
|
||||
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
|
||||
#ifdef GAME_BASTET
|
||||
}
|
||||
#endif
|
||||
|
||||
// the view only monitors the logic and the playfield object for the game
|
||||
// status so we must put information like the next piece or the current
|
||||
// highscore to a place where the view can find it
|
||||
tetris_logic_setHighscore(pLogic, nHighscore);
|
||||
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
|
||||
|
||||
// pace flag
|
||||
tetris_input_pace_t inPace;
|
||||
|
@ -178,22 +232,45 @@ void tetris ()
|
|||
{
|
||||
// the playfield awaits a new piece
|
||||
case TETRIS_PFS_READY:
|
||||
// make preview piece the current piece and create new preview piece
|
||||
pPiece = pNextPiece;
|
||||
pNextPiece =
|
||||
tetris_piece_construct(random8() % 7, TETRIS_PC_ANGLE_0);
|
||||
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
|
||||
|
||||
// insert new piece into playfield
|
||||
tetris_piece_t *pOldPiece;
|
||||
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
|
||||
|
||||
// destruct old piece (if it exists) since we don't need it anymore
|
||||
if (pOldPiece != NULL)
|
||||
#ifdef GAME_BASTET
|
||||
if (nBastet)
|
||||
{
|
||||
tetris_piece_destruct(pOldPiece);
|
||||
pOldPiece = NULL;
|
||||
if (pPiece != NULL)
|
||||
{
|
||||
tetris_piece_destruct(pPiece);
|
||||
}
|
||||
if (pNextPiece != NULL)
|
||||
{
|
||||
tetris_piece_destruct(pNextPiece);
|
||||
}
|
||||
pPiece = tetris_bastet_choosePiece(pBastet);
|
||||
pNextPiece = tetris_bastet_choosePreviewPiece(pBastet);
|
||||
tetris_piece_t *pOldPiece;
|
||||
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
|
||||
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// make preview piece the current piece and create new preview piece
|
||||
pPiece = pNextPiece;
|
||||
pNextPiece = tetris_piece_construct(random8() % 7,
|
||||
TETRIS_PC_ANGLE_0);
|
||||
tetris_logic_setPreviewPiece(pLogic, pNextPiece);
|
||||
|
||||
// insert new piece into playfield
|
||||
tetris_piece_t *pOldPiece;
|
||||
tetris_playfield_insertPiece(pPl, pPiece, &pOldPiece);
|
||||
|
||||
// destruct old piece (if it exists) since we don't need it anymore
|
||||
if (pOldPiece != NULL)
|
||||
{
|
||||
tetris_piece_destruct(pOldPiece);
|
||||
pOldPiece = NULL;
|
||||
}
|
||||
#ifdef GAME_BASTET
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
// a piece is hovering and can be controlled by the player
|
||||
|
@ -296,7 +373,6 @@ void tetris ()
|
|||
// and whether the level gets changed
|
||||
tetris_logic_removedLines(pLogic, tetris_playfield_getRowMask(pPl));
|
||||
tetris_input_setLevel(pIn, tetris_logic_getLevel(pLogic));
|
||||
|
||||
break;
|
||||
|
||||
// avoid compiler warnings
|
||||
|
@ -320,6 +396,12 @@ void tetris ()
|
|||
}
|
||||
|
||||
// clean up
|
||||
#ifdef GAME_BASTET
|
||||
if (nBastet)
|
||||
{
|
||||
tetris_bastet_destruct(pBastet);
|
||||
}
|
||||
#endif
|
||||
tetris_view_destruct(pView);
|
||||
tetris_input_destruct(pIn);
|
||||
tetris_playfield_destruct(pPl);
|
||||
|
@ -374,18 +456,18 @@ void tetris_logic_removedLines(tetris_logic_t *pLogic,
|
|||
|
||||
switch (nLines)
|
||||
{
|
||||
case 1:
|
||||
pLogic->nScore += 50;
|
||||
break;
|
||||
case 2:
|
||||
pLogic->nScore += 150;
|
||||
break;
|
||||
case 3:
|
||||
pLogic->nScore += 250;
|
||||
break;
|
||||
case 4:
|
||||
pLogic->nScore += 400;
|
||||
break;
|
||||
case 1:
|
||||
pLogic->nScore += 50;
|
||||
break;
|
||||
case 2:
|
||||
pLogic->nScore += 150;
|
||||
break;
|
||||
case 3:
|
||||
pLogic->nScore += 250;
|
||||
break;
|
||||
case 4:
|
||||
pLogic->nScore += 400;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,20 @@ void tetris_logic_destruct(tetris_logic_t *pLogic);
|
|||
void tetris();
|
||||
|
||||
|
||||
/* Function: tetris_bastet
|
||||
* Description: runs the bastet game
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_bastet();
|
||||
|
||||
|
||||
/* Function: tetris_main
|
||||
* Description: runs the tetris game
|
||||
* Argument nBastet: 0 for normal Tetris, 1 for Bastet
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_main(int8_t nBastet);
|
||||
|
||||
/* Function: tetris_logic_singleDrop
|
||||
* Description: add points which result from single step dropping
|
||||
* Argument pLogic: the logic object we want to modify
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include "../../autoconf.h"
|
||||
#include "playfield.h"
|
||||
#include "piece.h"
|
||||
#include "bast.h"
|
||||
|
||||
|
||||
/***************************
|
||||
|
@ -58,6 +58,7 @@ tetris_playfield_t *tetris_playfield_construct(int8_t nWidth,
|
|||
if (pPlayfield->dump != NULL)
|
||||
{
|
||||
// setting desired attributes
|
||||
pPlayfield->nFirstMatterRow = nHeight - 1;
|
||||
pPlayfield->nWidth = nWidth;
|
||||
pPlayfield->nHeight = nHeight;
|
||||
tetris_playfield_reset(pPlayfield);
|
||||
|
@ -336,6 +337,20 @@ void tetris_playfield_advancePiece(tetris_playfield_t *pPl)
|
|||
pPl->dump[i] |= nPieceMap;
|
||||
}
|
||||
|
||||
// update value for the highest row with matter
|
||||
int8_t nPieceRow = pPl->nRow;
|
||||
uint16_t nMask = 0x000F;
|
||||
for (int i = 0; i < 4; ++i, nMask <<= 4)
|
||||
{
|
||||
if ((nMask & nPiece) != 0)
|
||||
{
|
||||
nPieceRow += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pPl->nFirstMatterRow = (pPl->nFirstMatterRow > nPieceRow) ?
|
||||
nPieceRow : pPl->nFirstMatterRow;
|
||||
|
||||
// the piece has finally been docked
|
||||
pPl->status = TETRIS_PFS_DOCKED;
|
||||
}
|
||||
|
@ -456,6 +471,9 @@ void tetris_playfield_removeCompleteLines(tetris_playfield_t *pPl)
|
|||
// is current row a full row?
|
||||
if ((nFullRow & pPl->dump[i]) == nFullRow)
|
||||
{
|
||||
// adjust value for the highest row with matter
|
||||
pPl->nFirstMatterRow++;
|
||||
|
||||
// set corresponding bit for the row mask
|
||||
// nRowMask |= 0x08 >> (nStartRow - i);
|
||||
nRowMask |= 0x01 << (i - pPl->nRow);
|
||||
|
@ -602,6 +620,9 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
|
|||
return pPl->dump[nRow];
|
||||
}
|
||||
|
||||
|
||||
#ifdef GAME_BASTET
|
||||
|
||||
/* Function: tetris_playfield_predictDeepestRow
|
||||
* Description: returns the deepest possible row of a given piece
|
||||
* Argument pPl: the playfield on which we want to test a piece
|
||||
|
@ -621,10 +642,14 @@ int8_t tetris_playfield_predictDeepestRow(tetris_playfield_t *pPl,
|
|||
if (tetris_playfield_collision(pPl, (pPl->nWidth - 2) / 2, nRow) ||
|
||||
(tetris_playfield_collision(pPl, nColumn, nRow)))
|
||||
{
|
||||
// restore real piece
|
||||
pPl->pPiece = pActualPiece;
|
||||
|
||||
return -4;
|
||||
}
|
||||
|
||||
// determine deepest row
|
||||
nRow = (nRow < pPl->nFirstMatterRow - 4) ? pPl->nFirstMatterRow - 4 : nRow;
|
||||
while ((nRow < pPl->nHeight) &&
|
||||
(!tetris_playfield_collision(pPl, nColumn, nRow + 1)))
|
||||
{
|
||||
|
@ -777,3 +802,5 @@ uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GAME_BASTET */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define TETRIS_PLAYFIELD_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "../../autoconf.h"
|
||||
#include "piece.h"
|
||||
|
||||
|
||||
|
@ -40,6 +41,7 @@ typedef struct tetris_playfield_t
|
|||
int8_t nRow; // vert. piece pos. (0 is top)
|
||||
uint8_t nRowMask; // removed lines relative to nRow (bitmap)
|
||||
tetris_playfield_status_t status; // status
|
||||
int8_t nFirstMatterRow; // first row (from top) which contains matter
|
||||
uint16_t *dump; // playfield itself
|
||||
}
|
||||
tetris_playfield_t;
|
||||
|
@ -223,6 +225,8 @@ uint16_t tetris_playfield_getDumpRow(tetris_playfield_t *pPl,
|
|||
int8_t nRow);
|
||||
|
||||
|
||||
#ifdef GAME_BASTET
|
||||
|
||||
/* Function: tetris_playfield_predictDeepestRow
|
||||
* Description: returns the deepest possible row of a given piece
|
||||
* Argument pPl: the playfield on which we want to test a piece
|
||||
|
@ -287,6 +291,6 @@ uint16_t* tetris_playfield_predictBottomRow(tetris_playfield_iterator_t *pIt,
|
|||
*/
|
||||
uint16_t* tetris_playfield_predictNextRow(tetris_playfield_iterator_t *pIt);
|
||||
|
||||
|
||||
#endif /* GAME_BASTET */
|
||||
|
||||
#endif /*TETRIS_PLAYFIELD_H_*/
|
||||
|
|
|
@ -30,10 +30,12 @@
|
|||
#define TETRIS_VIEW_LINE_BLINK_DELAY 75
|
||||
|
||||
// colors of game elements
|
||||
#define TETRIS_VIEW_COLORSPACE 0
|
||||
#define TETRIS_VIEW_COLORBORDER 1
|
||||
#define TETRIS_VIEW_COLORFADE 2
|
||||
#define TETRIS_VIEW_COLORPIECE 3
|
||||
#define TETRIS_VIEW_COLORSPACE 0
|
||||
#define TETRIS_VIEW_COLORBORDER 1
|
||||
#define TETRIS_VIEW_COLORFADE 2
|
||||
#define TETRIS_VIEW_COLORPIECE 3
|
||||
#define TETRIS_VIEW_COLORPAUSE 1
|
||||
#define TETRIS_VIEW_COLORCOUNTER 2
|
||||
|
||||
|
||||
/***************************
|
||||
|
@ -53,7 +55,7 @@ uint8_t tetris_view_getPieceColor (tetris_view_t *pV)
|
|||
}
|
||||
else
|
||||
{
|
||||
return TETRIS_VIEW_COLORBORDER;
|
||||
return TETRIS_VIEW_COLORPAUSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,17 +209,18 @@ void tetris_view_drawBorders(uint8_t nColor)
|
|||
setpixel((pixel){4, y}, nColor);
|
||||
setpixel((pixel){15, y}, nColor);
|
||||
}
|
||||
|
||||
for (y = 0; y < 5; ++y)
|
||||
{
|
||||
for (x = 0; x <= 3; ++x){
|
||||
|
||||
if ((y<1 || y>3) || (x<1 || y>3)){
|
||||
setpixel((pixel){x, y}, nColor);
|
||||
setpixel((pixel){x, y + 11}, nColor);
|
||||
}
|
||||
for (x = 0; x <= 3; ++x)
|
||||
{
|
||||
if ((y < 1 || y > 3) || (x < 1 || y > 3))
|
||||
{
|
||||
setpixel((pixel){x, y}, nColor);
|
||||
setpixel((pixel){x, y + 11}, nColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -287,69 +290,39 @@ void tetris_view_blinkLines(tetris_playfield_t *pPl)
|
|||
/* Function: tetris_view_showLineNumbers
|
||||
* Description: displays completed Lines (0-99)
|
||||
* Argmument pV: pointer to the view
|
||||
* Argument nColor: color
|
||||
* Return value: void
|
||||
*/
|
||||
void tetris_view_showLineNumbers (tetris_view_t *pV, uint8_t nColor)
|
||||
void tetris_view_showLineNumbers(tetris_view_t *pV)
|
||||
{
|
||||
//Get number of completed lines
|
||||
uint8_t Lines = tetris_logic_getLines(pV->pLogic);
|
||||
uint8_t nPen;
|
||||
// get number of completed lines
|
||||
uint8_t nLines = tetris_logic_getLines(pV->pLogic);
|
||||
|
||||
int x=0, y=0, i;
|
||||
int ones, tens;
|
||||
|
||||
ones= Lines%10;
|
||||
tens=(Lines/10)%10;
|
||||
// get decimal places
|
||||
int8_t nOnes = nLines % 10;
|
||||
int8_t nTens = (nLines / 10) % 10;
|
||||
|
||||
//pick drawing color, dark if ones=0, faded otherwise (bright counter gets confused with piece preview)
|
||||
if ((ones%10)!=0)
|
||||
nPen=TETRIS_VIEW_COLORFADE;
|
||||
else nPen=TETRIS_VIEW_COLORSPACE;
|
||||
|
||||
//Draws ones in the upper part of the border as a 3x3 square with 0-9 pixels
|
||||
//Start at column 1
|
||||
y=1;
|
||||
for (i=1;i<=9;i++)
|
||||
{
|
||||
//Start at line 1, increase every loop cycle
|
||||
x++;
|
||||
|
||||
//the square is just three pixels wide, start over in next column once the row is full
|
||||
if (x%4==0)
|
||||
// draws the decimal places as 3x3 squares with 9 pixels
|
||||
for (int i = 0, x = 1, y = 1; i < 9; ++i)
|
||||
{
|
||||
y++;
|
||||
x=1;
|
||||
// pick drawing color
|
||||
uint8_t nOnesPen = nOnes > i ?
|
||||
TETRIS_VIEW_COLORCOUNTER : TETRIS_VIEW_COLORSPACE;
|
||||
uint8_t nTensPen = nTens > i ?
|
||||
TETRIS_VIEW_COLORCOUNTER : TETRIS_VIEW_COLORSPACE;
|
||||
// wrap lines if required
|
||||
if ((x % 4) == 0)
|
||||
{
|
||||
y++;
|
||||
x = 1;
|
||||
}
|
||||
// ones
|
||||
setpixel((pixel){x, y}, nOnesPen);
|
||||
// tens (increment x, add vertical offset for lower part of the border)
|
||||
setpixel((pixel){x++, y + 11}, nTensPen);
|
||||
}
|
||||
setpixel((pixel){x,y}, nPen);
|
||||
//only draw as many ones as there are, make the rest of the square dark.
|
||||
if (i==ones) nPen=TETRIS_VIEW_COLORSPACE;
|
||||
}
|
||||
|
||||
//back to normal color, but only if tens is not divisible by 10
|
||||
if ((tens%10)!=0)
|
||||
nPen=TETRIS_VIEW_COLORFADE;
|
||||
else nPen=TETRIS_VIEW_COLORSPACE;
|
||||
|
||||
//Draws ones in the lower part of the border as a 3x3 square with 0-9 pixels
|
||||
x=0;
|
||||
y=12; //offset for lower part of the border
|
||||
for (i=1;i<=9;i++)
|
||||
{
|
||||
x++; //Start at line 1, increase every loop cycle
|
||||
|
||||
//the square is just three pixels wide, start over in next column once the row is full
|
||||
if (x%4==0)
|
||||
{
|
||||
y++;
|
||||
x=1;
|
||||
}
|
||||
setpixel((pixel){x,y}, nPen);
|
||||
//only draw as many ones as there are, make the rest of the square dark.
|
||||
if (i==tens) nPen=TETRIS_VIEW_COLORSPACE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* construction/destruction *
|
||||
****************************/
|
||||
|
@ -441,7 +414,7 @@ void tetris_view_update(tetris_view_t *pV)
|
|||
if (tetris_playfield_getRowMask(pV->pPl) != 0)
|
||||
{
|
||||
tetris_view_blinkLines(pV->pPl);
|
||||
tetris_view_showLineNumbers(pV, TETRIS_VIEW_COLORPIECE);
|
||||
tetris_view_showLineNumbers(pV);
|
||||
}
|
||||
|
||||
// draw preview piece
|
||||
|
|
Loading…
Reference in New Issue