303 lines
7.6 KiB
C
303 lines
7.6 KiB
C
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/xpm.h>
|
|
|
|
#include <libdockapp/wmgeneral.h>
|
|
|
|
#include "wmtetris.xpm"
|
|
#include "wmtetris-mask.xbm"
|
|
|
|
#define TEMPORAL_RESOLUTION 10000
|
|
#define INITIAL_DELAY 250000
|
|
#define FAST_MODE_DELAY 30000
|
|
#define DELAY_INCREMENT 20000
|
|
|
|
#define BLOCK_SIZE 3
|
|
#define BOARD_POS_X 4
|
|
#define BOARD_POS_Y 6
|
|
#define BOARD_WIDTH 13
|
|
#define BOARD_HEIGHT 18
|
|
#define NEXT_POS_X 46
|
|
#define NEXT_POS_Y 7
|
|
|
|
#define BUTTONC 6
|
|
#define BUTTON_NONE 0
|
|
#define BUTTON_ROTATE_LEFT 1
|
|
#define BUTTON_ROTATE_RIGHT 2
|
|
#define BUTTON_MOVE_LEFT 3
|
|
#define BUTTON_MOVE_RIGHT 4
|
|
#define BUTTON_MOVE_DOWN 5
|
|
|
|
static int buttons[6][4] = {
|
|
{ 0, 0, 64, 64},
|
|
{43, 31, 51, 40},
|
|
{52, 31, 60, 40},
|
|
{43, 41, 51, 50},
|
|
{52, 41, 60, 50},
|
|
{43, 51, 60, 60}
|
|
};
|
|
|
|
static int initial_figures[7][4][2] = {
|
|
{ {0, 1}, {1, 1}, {2, 1}, {3, 1} },
|
|
{ {0, 1}, {1, 1}, {2, 1}, {2, 2} },
|
|
{ {0, 2}, {1, 2}, {2, 2}, {2, 1} },
|
|
{ {0, 2}, {1, 1}, {1, 2}, {2, 2} },
|
|
{ {0, 2}, {1, 2}, {1, 1}, {2, 1} },
|
|
{ {0, 1}, {1, 1}, {1, 2}, {2, 2} },
|
|
{ {1, 1}, {2, 1}, {1, 2}, {2, 2} }
|
|
};
|
|
|
|
unsigned char board[BOARD_WIDTH][BOARD_HEIGHT];
|
|
int score=0;
|
|
|
|
int which_button(int x, int y);
|
|
int rotate_figure(int direction, int figure[4][2], int fig_x, int fig_y);
|
|
void draw_figure(int figure[4][2], int type, int x, int y);
|
|
void draw_next_figure(int figure[4][2], int type);
|
|
void general_draw_figure(int base_x, int base_y, int figure[4][2],
|
|
int type, int x, int y);
|
|
void full_refresh();
|
|
int check_figure_position(int fig_x, int fig_y, int figure[4][2]);
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int i, x, y, step, input, fast_mode, progress,
|
|
fig_x, fig_y, new_figure=1, figure_type, next_figure_type;
|
|
int figure[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} },
|
|
next_figure[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
|
|
XEvent event;
|
|
|
|
srand(time(NULL));
|
|
|
|
for (y = 0; y < BOARD_HEIGHT; y++)
|
|
for (x = 0; x < BOARD_WIDTH; x++)
|
|
board[x][y] = 0;
|
|
|
|
openXwindow(argc, argv, wmtetris_xpm, (char *)wmtetris_mask_bits,
|
|
wmtetris_mask_width, wmtetris_mask_height);
|
|
copyXPMArea(64, 0, 64, 64, 0, 0);
|
|
RedrawWindow();
|
|
|
|
fast_mode=0;
|
|
figure_type = random() % 7;
|
|
for (i = 0; i < 4; i++) {
|
|
figure[i][0] = initial_figures[figure_type][i][0];
|
|
figure[i][1] = initial_figures[figure_type][i][1];
|
|
}
|
|
next_figure_type = random() % 7;
|
|
for (i = 0; i < 4; i++) {
|
|
next_figure[i][0] = initial_figures[next_figure_type][i][0];
|
|
next_figure[i][1] = initial_figures[next_figure_type][i][1];
|
|
}
|
|
draw_next_figure(next_figure, next_figure_type);
|
|
fig_x = BOARD_WIDTH / 2 - 1;
|
|
fig_y = 0;
|
|
draw_figure(figure, figure_type, fig_x, fig_y);
|
|
RedrawWindow();
|
|
|
|
while (1) {
|
|
if (check_figure_position(fig_x, fig_y + 1, figure)) {
|
|
new_figure = 0;
|
|
draw_figure(figure, -1, fig_x, fig_y);
|
|
fig_y++;
|
|
} else {
|
|
new_figure = 1;
|
|
for (i = 0; i < 4; i++) {
|
|
board [fig_x + figure[i][0]] [fig_y + figure[i][1]] = figure_type + 1;
|
|
}
|
|
|
|
progress=0;
|
|
for (y = 0; y < BOARD_HEIGHT; y++) {
|
|
for (x = 0; x < BOARD_WIDTH; x++)
|
|
if (!board[x][y])
|
|
break;
|
|
if (x == BOARD_WIDTH) {
|
|
for (i = y; i > 0; i--)
|
|
for (x = 0; x < BOARD_WIDTH; x++)
|
|
board[x][i] = board[x][i-1];
|
|
progress++;
|
|
}
|
|
}
|
|
score += progress*progress;
|
|
|
|
full_refresh();
|
|
|
|
i = score;
|
|
for (x = 3; x >= 0; x--) {
|
|
copyXPMArea(4 * (i % 10), 100, 3, 5, 44 + 4*x, 24);
|
|
i /= 10;
|
|
}
|
|
|
|
figure_type = next_figure_type;
|
|
next_figure_type = random() % 7;
|
|
for (i = 0; i < 4; i++) {
|
|
figure[i][0] = next_figure[i][0];
|
|
figure[i][1] = next_figure[i][1];
|
|
next_figure[i][0] = initial_figures[next_figure_type][i][0];
|
|
next_figure[i][1] = initial_figures[next_figure_type][i][1];
|
|
}
|
|
draw_next_figure(next_figure, next_figure_type);
|
|
fig_x = BOARD_WIDTH / 2 - 1;
|
|
fig_y = 0;
|
|
}
|
|
draw_figure(figure, figure_type, fig_x, fig_y);
|
|
RedrawWindow();
|
|
|
|
if (new_figure) {
|
|
if (!check_figure_position(fig_x, fig_y, figure)) {
|
|
copyXPMArea(64, 64, 23, 15, 12, 24);
|
|
RedrawWindow();
|
|
while (1) {
|
|
XNextEvent(display, &event);
|
|
if (event.type == ButtonPress)
|
|
break;
|
|
if (event.type == Expose)
|
|
RedrawWindow();
|
|
}
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
for (step = 0; step < (fast_mode ? FAST_MODE_DELAY / TEMPORAL_RESOLUTION : INITIAL_DELAY / TEMPORAL_RESOLUTION); step++) {
|
|
while (XPending(display)) {
|
|
input = 0;
|
|
|
|
XNextEvent(display, &event);
|
|
switch (event.type) {
|
|
case ButtonRelease:
|
|
fast_mode = 0;
|
|
break;
|
|
case ButtonPress:
|
|
if (!(input =
|
|
which_button(event.xbutton.x, event.xbutton.y))) {
|
|
/*
|
|
switch (event.xbutton.button) {
|
|
case 1:
|
|
input = BUTTON_MOVE_LEFT;
|
|
break;
|
|
case 3:
|
|
input = BUTTON_MOVE_RIGHT;
|
|
break;
|
|
case 2:
|
|
input = BUTTON_ROTATE_RIGHT;
|
|
break;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
if (input) {
|
|
draw_figure(figure, -1, fig_x, fig_y);
|
|
switch (input) {
|
|
case BUTTON_ROTATE_LEFT:
|
|
rotate_figure(0, figure, fig_x, fig_y);
|
|
break;
|
|
case BUTTON_ROTATE_RIGHT:
|
|
rotate_figure(1, figure, fig_x, fig_y);
|
|
break;
|
|
case BUTTON_MOVE_LEFT:
|
|
if (check_figure_position(fig_x - 1, fig_y, figure))
|
|
fig_x--;
|
|
break;
|
|
case BUTTON_MOVE_RIGHT:
|
|
if (check_figure_position(fig_x + 1, fig_y, figure))
|
|
fig_x++;
|
|
break;
|
|
case BUTTON_MOVE_DOWN:
|
|
fast_mode = 1;
|
|
break;
|
|
}
|
|
draw_figure(figure, figure_type, fig_x, fig_y);
|
|
RedrawWindow();
|
|
}
|
|
}
|
|
usleep(TEMPORAL_RESOLUTION);
|
|
}
|
|
}
|
|
}
|
|
|
|
int which_button(int x, int y) {
|
|
int i;
|
|
|
|
for (i = BUTTONC - 1; i >= 0; i--) {
|
|
if ((buttons[i][0] <= x && x < buttons[i][2]) &&
|
|
(buttons[i][1] <= y && y < buttons[i][3]))
|
|
break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int rotate_figure(int direction, int figure[4][2], int fig_x, int fig_y) {
|
|
int i, temp[4][2];
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
temp[i][0] = direction ? 3 - figure[i][1] : figure[i][1];
|
|
temp[i][1] = direction ? figure[i][0] : 3 - figure[i][0];
|
|
}
|
|
if (check_figure_position(fig_x, fig_y, temp)) {
|
|
for (i = 0; i < 4; i++) {
|
|
figure[i][0] = temp[i][0];
|
|
figure[i][1] = temp[i][1];
|
|
}
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void draw_figure(int figure[4][2], int type, int x, int y) {
|
|
general_draw_figure(BOARD_POS_X, BOARD_POS_Y, figure, type, x, y);
|
|
}
|
|
|
|
void draw_next_figure(int figure[4][2], int type) {
|
|
copyXPMArea(64 + NEXT_POS_X, NEXT_POS_Y, BLOCK_SIZE * 4, BLOCK_SIZE * 4,
|
|
NEXT_POS_X, NEXT_POS_Y);
|
|
general_draw_figure(NEXT_POS_X, NEXT_POS_Y, figure, type, 0, 0);
|
|
}
|
|
|
|
void general_draw_figure(int base_x, int base_y, int figure[4][2],
|
|
int type, int x, int y)
|
|
{
|
|
int i, block_x, block_y;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
block_x = base_x + BLOCK_SIZE * (x + figure[i][0]);
|
|
block_y = base_y + BLOCK_SIZE * (y + figure[i][1]);
|
|
if (type == -1)
|
|
copyXPMArea(64 + block_x, block_y, BLOCK_SIZE, BLOCK_SIZE, block_x, block_y);
|
|
else
|
|
copyXPMArea(0, 64 + BLOCK_SIZE * type, BLOCK_SIZE, BLOCK_SIZE, block_x, block_y);
|
|
}
|
|
}
|
|
|
|
void full_refresh() {
|
|
int x, y;
|
|
|
|
for (y = 0; y < BOARD_HEIGHT; y++)
|
|
for (x = 0; x < BOARD_WIDTH; x++)
|
|
if (board[x][y])
|
|
copyXPMArea(0, 64 + BLOCK_SIZE * (board[x][y] - 1), BLOCK_SIZE, BLOCK_SIZE,
|
|
BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y);
|
|
else
|
|
copyXPMArea(64 + BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y,
|
|
BLOCK_SIZE, BLOCK_SIZE,
|
|
BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y);
|
|
}
|
|
|
|
int check_figure_position(int fig_x, int fig_y, int figure[4][2]) {
|
|
int i, x, y;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
x = fig_x + figure[i][0];
|
|
y = fig_y + figure[i][1];
|
|
if ((x < 0) || (x >= BOARD_WIDTH) || (y < 0) || (y >= BOARD_HEIGHT))
|
|
return 0;
|
|
if (board[x][y])
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|