Exemple #1
0
/*
 * Tetris Guidlines say wallkicks first try to move left, attempt rotation
 * again. Then if that fails, we try again but by moving to the right.
 */
static int try_wall_kick(struct blocks *block, enum blocks_input_cmd cmd)
{
	/* Try to move left and rotate again. */
	if (translate_block(block, MOVE_LEFT) == 1) {
		if (rotate_block(block, cmd) == 1)
			return 1;
	}

	/* undo previous translation */
	translate_block(block, MOVE_RIGHT);

	/* Try to move right and rotate again. */
	if (translate_block(block, MOVE_RIGHT) == 1) {
		if (rotate_block(block, cmd) == 1)
			return 1;
	}

	return 0;
}
Exemple #2
0
void merge_group(struct group *group, struct group *child)
{
    struct groupdata *groupdata = group->data;
    struct groupdata *childdata = child->data;

    for (size_t i = 0; i < ptrarray_count(childdata->blocks); ++i)
    {
        struct block *copy = copy_block(get_ptrarray(childdata->blocks, i));
        translate_block(copy, &child->position);
        push_ptrarray(groupdata->blocks, copy);
    }

    for (size_t i = 0; i < ptrarray_count(childdata->groups); ++i)
    {
        struct group *copy = copy_group(get_ptrarray(childdata->groups, i));
        vec3_add(&copy->position, &copy->position, &child->position);
        insert_group(group, copy);
    }

    destroy_group(child);
    update_group_vertexarray(group);
}
Exemple #3
0
/*
 * User input. Hopefully self explanatory.
 *
 * Input keys are currently:
 * 	F1 pause
 * 	F3 quit
 *
 * 	wasdqe
 * 	- w hard drops a piece to the bottom.
 * 	- a/d move left/right respectively.
 * 	- s soft drops one row.
 * 	- qe rotate counter clockwise/clockwise repectively.
 *
 * 	- space is used to hold the currently falling block.
 */
void *blocks_input(void *vp)
{
	(void) vp; /* unused */
	
	int ch;

	if (!CURRENT_BLOCK())
		return NULL;

	while ((ch = getch())) {
		/* prevent modification of the game from blocks_loop in the
		 * other thread */
		pthread_mutex_lock(&pgame->lock);

		switch (ch) {
		case KEY_F(1):
			pgame->pause = !pgame->pause;
			goto draw_game;
		case KEY_F(3):
			pgame->pause = false;
			pgame->quit = true;
			goto draw_game;
		}

		/* remove the current piece from the board */
		unwrite_cur_block();

		/* modify it */
		switch (toupper(ch)) {
		case 'A':
			translate_block(CURRENT_BLOCK(), MOVE_LEFT);
			break;
		case 'D':
			translate_block(CURRENT_BLOCK(), MOVE_RIGHT);
			break;
		case 'S':
			if (drop_block(CURRENT_BLOCK()))
				CURRENT_BLOCK()->soft_drop++;
			else
				CURRENT_BLOCK()->lock_delay = 1E9 -1;
			break;
		case 'W':
			/* drop the block to the bottom of the game */
			while (drop_block(CURRENT_BLOCK()))
				CURRENT_BLOCK()->hard_drop++;

			/* XXX */
			CURRENT_BLOCK()->lock_delay = 1E9 -1;
			break;
		case 'Q':
			if (!rotate_block(CURRENT_BLOCK(), ROT_LEFT))
			{
				try_wall_kick(CURRENT_BLOCK(), ROT_LEFT);
			}
			break;
		case 'E':
			if (!rotate_block(CURRENT_BLOCK(), ROT_RIGHT))
			{
				try_wall_kick(CURRENT_BLOCK(), ROT_RIGHT);
			}
			break;
		case ' ': {
			struct blocks *tmp;

			/* We can hold each block exactly once */
			if (CURRENT_BLOCK()->hold == true)
				break;

			tmp = CURRENT_BLOCK();

			/* Effectively swap the first and second elements in
			 * the linked list. The "Current Block" is element 2.
			 * And the "Hold Block" is element 1. So we remove the
			 * current block and reinstall it at the head, pushing
			 * the hold block to the current position.
			 */
			LIST_REMOVE(tmp, entries);
			LIST_INSERT_HEAD(&pgame->blocks_head, tmp, entries);

			reset_block(HOLD_BLOCK());
			HOLD_BLOCK()->hold = true;

			break;
			}
		}

		/* then rewrite it */
		write_cur_block();

		draw_game:

		screen_draw_game();
		pthread_mutex_unlock(&pgame->lock);
	}

	return NULL;
}
Exemple #4
0
static void translate_block_(block *block, void *data)
{
    translate_block(block, data);
}