Skip to content

Commit

Permalink
add shape shadow option, controls with arrows, enable move down
Browse files Browse the repository at this point in the history
  • Loading branch information
Korben11 committed Nov 28, 2019
1 parent 2b35947 commit d857d77
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 42 deletions.
130 changes: 94 additions & 36 deletions engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,88 +124,136 @@ static bool allowed (board_t board,shape_t *shape,int x,int y)
return (!occupied);
}

/* Set y coordinate of shadow */
static void place_shadow_to_bottom (board_t board,shape_t *shape,int x_shadow,int *y_shadow,int y) {
while (allowed(board,shape,x_shadow,y+1)) y++;
*y_shadow = y;
}

/* Move the shape left if possible */
static bool shape_left (board_t board,shape_t *shape,int *x,int y)
static bool shape_left (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
bool result = FALSE;
eraseshape (board,shape,*x,y);
if (allowed (board,shape,*x - 1,y))
eraseshape (*board,shape,engine->curx,engine->cury);
if (engine->shadow) eraseshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
if (allowed (*board,shape,engine->curx - 1,engine->cury))
{
(*x)--;
result = TRUE;
engine->curx--;
result = TRUE;
if (engine->shadow)
{
engine->curx_shadow--;
place_shadow_to_bottom(*board,shape,engine->curx_shadow,&engine->cury_shadow,engine->cury);
}
}
drawshape (board,shape,*x,y);
if (engine->shadow) drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
drawshape (*board,shape,engine->curx,engine->cury);
return result;
}

/* Move the shape right if possible */
static bool shape_right (board_t board,shape_t *shape,int *x,int y)
static bool shape_right (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
bool result = FALSE;
eraseshape (board,shape,*x,y);
if (allowed (board,shape,*x + 1,y))
eraseshape (*board,shape,engine->curx,engine->cury);
if (engine->shadow) eraseshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
if (allowed (*board,shape,engine->curx + 1,engine->cury))
{
(*x)++;
engine->curx++;
result = TRUE;
if (engine->shadow)
{
engine->curx_shadow++;
place_shadow_to_bottom(*board,shape,engine->curx_shadow,&engine->cury_shadow,engine->cury);
}
}
drawshape (board,shape,*x,y);
if (engine->shadow) drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
drawshape (*board,shape,engine->curx,engine->cury);
return result;
}

/* Rotate the shape if possible */
static bool shape_rotate (board_t board,shape_t *shape,int x,int y)
static bool shape_rotate (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
bool result = FALSE;
shape_t test;
eraseshape (board,shape,x,y);
eraseshape (*board,shape,engine->curx,engine->cury);
if (engine->shadow) eraseshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
memcpy (&test,shape,sizeof (shape_t));
fake_rotate (&test);
if (allowed (board,&test,x,y))
if (allowed (*board,&test,engine->curx,engine->cury))
{
memcpy (shape,&test,sizeof (shape_t));
result = TRUE;
if (engine->shadow) place_shadow_to_bottom(*board,shape,engine->curx_shadow,&engine->cury_shadow,engine->cury);
}
drawshape (board,shape,x,y);
if (engine->shadow) drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
drawshape (*board,shape,engine->curx,engine->cury);
return result;
}

/* Move the shape one row down if possible */
static bool shape_down (board_t board,shape_t *shape,int x,int *y)
static bool shape_down (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
bool result = FALSE;
eraseshape (board,shape,x,*y);
if (allowed (board,shape,x,*y + 1))
eraseshape (*board,shape,engine->curx,engine->cury);
if (engine->shadow) eraseshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
if (allowed (*board,shape,engine->curx,engine->cury + 1))
{
(*y)++;
engine->cury++;
result = TRUE;
if (engine->shadow) place_shadow_to_bottom(*board,shape,engine->curx_shadow,&engine->cury_shadow,engine->cury);
}
drawshape (board,shape,x,*y);
if (engine->shadow) drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
drawshape (*board,shape,engine->curx,engine->cury);
return result;
}

/* Check if shape can move down (= in the air) or not (= at the bottom */
/* of the board or on top of one of the resting shapes) */
static bool shape_bottom (board_t board,shape_t *shape,int x,int y)
static bool shape_bottom (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
bool result = FALSE;
eraseshape (board,shape,x,y);
result = !allowed (board,shape,x,y + 1);
drawshape (board,shape,x,y);
eraseshape (*board,shape,engine->curx,engine->cury);
if (engine->shadow) eraseshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
result = !allowed (*board,shape,engine->curx,engine->cury + 1);
if (engine->shadow) drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
drawshape (*board,shape,engine->curx,engine->cury);
return result;
}

/* Drop the shape until it comes to rest on the bottom of the board or */
/* on top of a resting shape */
static int shape_drop (board_t board,shape_t *shape,int x,int *y)
static int shape_drop (engine_t *engine)
{
board_t *board = &engine->board;
shape_t *shape = &engine->shapes[engine->curshape];
eraseshape (*board,shape,engine->curx,engine->cury);
int droppedlines = 0;
eraseshape (board,shape,x,*y);
while (allowed (board,shape,x,*y + 1))

if (engine->shadow) {
drawshape (*board,shape,engine->curx_shadow,engine->cury_shadow);
droppedlines = engine->cury_shadow - engine->cury;
engine->cury = engine->cury_shadow;
return droppedlines;
}

while (allowed (*board,shape,engine->curx,engine->cury + 1))
{
(*y)++;
engine->cury++;
droppedlines++;
}
drawshape (board,shape,x,*y);
drawshape (*board,shape,engine->curx,engine->cury);
return droppedlines;
}

Expand Down Expand Up @@ -256,10 +304,13 @@ void shuffle (int *array, size_t n)
void engine_init (engine_t *engine,void (*score_function)(engine_t *))
{
int i;
engine->shadow = FALSE;
engine->score_function = score_function;
/* intialize values */
engine->curx = 5;
engine->cury = 1;
engine->curx_shadow = 5;
engine->cury_shadow = 1;
engine->bag_iterator = 0;
/* create and randomize bag */
for (int j = 0; j < NUMSHAPES; j++) engine->bag[j] = j;
Expand All @@ -286,19 +337,23 @@ void engine_move (engine_t *engine,action_t action)
{
/* move shape to the left if possible */
case ACTION_LEFT:
if (shape_left (engine->board,&engine->shapes[engine->curshape],&engine->curx,engine->cury)) engine->status.moves++;
if (shape_left (engine)) engine->status.moves++;
break;
/* rotate shape if possible */
case ACTION_ROTATE:
if (shape_rotate (engine->board,&engine->shapes[engine->curshape],engine->curx,engine->cury)) engine->status.rotations++;
if (shape_rotate (engine)) engine->status.rotations++;
break;
/* move shape to the right if possible */
case ACTION_RIGHT:
if (shape_right (engine->board,&engine->shapes[engine->curshape],&engine->curx,engine->cury)) engine->status.moves++;
if (shape_right (engine)) engine->status.moves++;
break;
/* move shape to the down if possible */
case ACTION_DOWN:
if (shape_down (engine)) engine->status.moves++;
break;
/* drop shape to the bottom */
case ACTION_DROP:
engine->status.dropcount += shape_drop (engine->board,&engine->shapes[engine->curshape],engine->curx,&engine->cury);
engine->status.dropcount += shape_drop (engine);
}
}

Expand All @@ -312,7 +367,7 @@ void engine_move (engine_t *engine,action_t action)
*/
int engine_evaluate (engine_t *engine)
{
if (shape_bottom (engine->board,&engine->shapes[engine->curshape],engine->curx,engine->cury))
if (shape_bottom (engine))
{
/* update status information */
int dropped_lines = droplines(engine->board);
Expand All @@ -322,6 +377,8 @@ int engine_evaluate (engine_t *engine)
engine->score_function (engine);
engine->curx -= 5;
engine->curx = abs (engine->curx);
engine->curx_shadow -= 5;
engine->curx_shadow = abs (engine->curx_shadow);
engine->status.rotations = 4 - engine->status.rotations;
engine->status.rotations = engine->status.rotations > 0 ? 0 : engine->status.rotations;
engine->status.efficiency += engine->status.dropcount + engine->status.rotations + (engine->curx - engine->status.moves);
Expand All @@ -330,6 +387,8 @@ int engine_evaluate (engine_t *engine)
/* intialize values */
engine->curx = 5;
engine->cury = 1;
engine->curx_shadow = 5;
engine->cury_shadow = 1;
engine->curshape = engine->bag[engine->bag_iterator%NUMSHAPES];
/* shuffle bag before first item in bag would be reused */
if ((engine->bag_iterator+1) % NUMSHAPES == 0) shuffle(engine->bag, NUMSHAPES);
Expand All @@ -340,7 +399,6 @@ int engine_evaluate (engine_t *engine)
/* return games status */
return allowed (engine->board,&engine->shapes[engine->curshape],engine->curx,engine->cury) ? 0 : -1;
}
shape_down (engine->board,&engine->shapes[engine->curshape],engine->curx,&engine->cury);
shape_down (engine);
return 1;
}

5 changes: 3 additions & 2 deletions engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ typedef struct

typedef struct engine_struct
{
int curx,cury; /* coordinates of current piece */
bool shadow; /* show shadow */
int curx,cury,curx_shadow,cury_shadow; /* coordinates of current piece */
int curshape,nextshape; /* current & next shapes */
int score; /* score */
int bag_iterator; /* iterator for randomized bag */
Expand All @@ -90,7 +91,7 @@ typedef struct engine_struct
void (*score_function)(struct engine_struct *); /* score function */
} engine_t;

typedef enum { ACTION_LEFT, ACTION_ROTATE, ACTION_RIGHT, ACTION_DROP } action_t;
typedef enum { ACTION_LEFT, ACTION_ROTATE, ACTION_RIGHT, ACTION_DROP, ACTION_DOWN } action_t;

/*
* Global variables
Expand Down
6 changes: 5 additions & 1 deletion tint.6
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH TINT 6 "June 23, 2010"
.TH TINT 6 "Nov 28, 2019"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
Expand All @@ -20,6 +20,7 @@ tint \- clone of the original tint
.RI [ -n ]
.RI [ -d ]
.RI [ -b\ char ]
.RI [ -s ]
.SH DESCRIPTION
This manual page documents briefly the
.B tint
Expand All @@ -45,6 +46,9 @@ Draw dotted lines.
.TP
.B \-b <char>
Use the specified character (instead of spaces) to draw blocks.
.TP
.B \-s
Draw shadow of shape.
.SH AUTHOR
This manual page was written by Abraham van der Merwe <abz@debian.org>,
for the Debian GNU/Linux system (but may be used by others).
14 changes: 11 additions & 3 deletions tint.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@

static bool shownext;
static bool dottedlines;
static bool shadow;
static int level = MINLEVEL - 1,shapecount[NUMSHAPES];
static char blockchar = ' ';

Expand Down Expand Up @@ -505,6 +506,7 @@ static void showhelp ()
fprintf (stderr," -n Draw next shape\n");
fprintf (stderr," -d Draw vertical dotted lines\n");
fprintf (stderr," -b <char> Use this character to draw blocks instead of spaces\n");
fprintf (stderr," -s Draw shadow of shape\n");
exit (EXIT_FAILURE);
}

Expand Down Expand Up @@ -538,6 +540,8 @@ static void parse_options (int argc,char *argv[])
if (i >= argc || strlen(argv[i]) < 1) showhelp();
blockchar = argv[i][0];
}
else if (strcmp (argv[i],"-s") == 0)
shadow = TRUE;
else
{
fprintf (stderr,"Invalid option -- %s\n",argv[i]);
Expand Down Expand Up @@ -598,10 +602,11 @@ int main (int argc,char *argv[])
/* Initialize */
rand_init (); /* must be called before engine_init () */
engine_init (&engine,score_function); /* must be called before using engine.curshape */
finished = shownext = FALSE;
finished = shownext = shadow = FALSE;
memset (shapecount,0,NUMSHAPES * sizeof (int));
shapecount[engine.curshape]++;
parse_options (argc,argv); /* must be called after initializing variables */
engine.shadow = shadow;
if (level < MINLEVEL) choose_level ();
io_init ();
drawbackground ();
Expand All @@ -623,16 +628,20 @@ int main (int argc,char *argv[])
engine_move (&engine,ACTION_LEFT);
break;
case 'k':
case KEY_UP:
case '\n':
engine_move (&engine,ACTION_ROTATE);
break;
case 'l':
case KEY_RIGHT:
engine_move (&engine,ACTION_RIGHT);
break;
case ' ':
case KEY_DOWN:
engine_move (&engine,ACTION_DOWN);
break;
case ' ':
engine_move (&engine,ACTION_DROP);
finished = evaluate(&engine); /* prevent key press after drop */
break;
/* show next piece */
case 's':
Expand All @@ -644,7 +653,6 @@ int main (int argc,char *argv[])
break;
/* next level */
case 'a':
case KEY_UP:
if (level < MAXLEVEL)
{
level++;
Expand Down

0 comments on commit d857d77

Please sign in to comment.