27 enum { ERASE_PIECE, DRAW_PIECE };
29 enum { BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE };
31 /* dimensions of the whole screen */
35 /* dimensions of the playfield */
38 /* offset of the playfield from the left side of the screen */
42 #define CHAR(c, fg, bg) \
43 ((uint16_t)(c) | ((uint16_t)(fg) << 12) | ((uint16_t)(bg) << 8))
45 int scr[SCR_COLS * SCR_ROWS];
47 static int collision(int piece, const int *pos);
48 static void stick(int piece, const int *pos);
49 static void draw_piece(int piece, const int *pos, int rot, int mode);
50 static void drawbg(void);
51 static void wrtile(int tileid);
54 static int pos[2], next_pos[2];
55 static int cur_piece = -1;
56 static int cur_rot, prev_rot;
70 #define FIRST_PIECE_TILE TILE_IPIECE
72 static uint16_t tiles[][2] = {
73 { CHAR(' ', BLACK, BLACK), CHAR(' ', BLACK, BLACK) }, /* black tile */
74 { CHAR(' ', WHITE, WHITE), CHAR(' ', WHITE, WHITE) }, /* playfield background */
75 { CHAR(G_CHECKER, WHITE, BLACK), CHAR(G_CHECKER, WHITE, BLACK) }, /* well separator */
76 { CHAR(' ', CYAN, CYAN), CHAR(' ', CYAN, CYAN) }, /* straight */
77 { CHAR(' ', BLUE, BLUE), CHAR(' ', BLUE, BLUE) }, /* box */
78 { CHAR(' ', GREEN, GREEN), CHAR(' ', GREEN, GREEN) }, /* J */
79 { CHAR(' ', YELLOW, YELLOW), CHAR(' ', YELLOW, YELLOW) }, /* L */
80 { CHAR(' ', MAGENTA, MAGENTA), CHAR(' ', MAGENTA, MAGENTA) }, /* S */
81 { CHAR(' ', RED, BLACK), CHAR(' ', RED, BLACK) }, /* T */
82 { CHAR(' ', RED, RED), CHAR(' ', RED, RED) }, /* Z */
98 /* fill the screen buffer, and draw */
99 for(i=0; i<SCR_ROWS; i++) {
100 for(j=0; j<SCR_COLS; j++) {
101 if(i > PF_ROWS || j < PF_XOFFS - 1 || j > PF_XOFFS + PF_COLS) {
103 } else if((i == PF_ROWS && j >= PF_XOFFS && j < PF_XOFFS + PF_COLS) ||
104 j == PF_XOFFS - 1 || j == PF_XOFFS + PF_COLS) {
119 void cleanup_game(void)
124 long update(long msec)
126 static long prev_tick;
129 dt = msec - prev_tick;
132 while(dt >= tick_interval) {
134 next_pos[0] = pos[0] + 1;
135 if(collision(cur_piece, next_pos)) {
136 next_pos[0] = pos[0];
137 fprintf(stderr, "stick at row %d col %d\n", pos[0], pos[1]);
138 stick(cur_piece, next_pos);
143 cur_piece = rand() % NUM_PIECES;
144 prev_rot = cur_rot = 0;
145 fprintf(stderr, "spawn: %d\n", cur_piece);
146 pos[0] = piece_spawnpos[cur_piece][0];
147 next_pos[0] = pos[0] + 1;
148 pos[1] = next_pos[1] = PF_COLS / 2 + piece_spawnpos[cur_piece][1];
155 if(cur_piece >= 0 && (memcmp(pos, next_pos, sizeof pos) != 0 || cur_rot != prev_rot)) {
156 draw_piece(cur_piece, pos, prev_rot, ERASE_PIECE);
157 draw_piece(cur_piece, next_pos, cur_rot, DRAW_PIECE);
158 memcpy(pos, next_pos, sizeof pos);
161 return tick_interval - dt;
168 static void runesc(int csi, char *buf)
170 if(csi != C0) return;
175 game_input('w'); /* up */
178 game_input('s'); /* down */
181 game_input('d'); /* right */
184 game_input('a'); /* left */
192 void game_input(int c)
196 static char escbuf[64];
218 if(c < 0x20 || c >= 0x80) {
223 escbuf[esctop++] = c;
230 runesc(prevcsi, escbuf);
250 next_pos[1] = pos[1] - 1;
251 if(collision(cur_piece, next_pos)) {
252 next_pos[1] = pos[1];
257 next_pos[1] = pos[1] + 1;
258 if(collision(cur_piece, next_pos)) {
259 next_pos[1] = pos[1];
266 cur_rot = (cur_rot + 1) & 3;
267 if(collision(cur_piece, next_pos)) {
273 next_pos[0] = pos[0] + 1;
274 if(collision(cur_piece, next_pos)) {
275 next_pos[0] = pos[0];
280 fprintf(stderr, "unhandled input: %x\n", c);
285 static int collision(int piece, const int *pos)
288 unsigned char *p = pieces[piece][cur_rot];
291 int x = PF_XOFFS + pos[1] + BLKX(*p);
292 int y = PF_YOFFS + pos[0] + BLKY(*p);
295 if(scr[y * SCR_COLS + x] != TILE_PF) return 1;
301 static void stick(int piece, const int *pos)
304 unsigned char *p = pieces[piece][cur_rot];
307 int x = PF_XOFFS + pos[1] + BLKX(*p);
308 int y = PF_YOFFS + pos[0] + BLKY(*p);
311 scr[y * SCR_COLS + x] = piece + FIRST_PIECE_TILE;
320 static void draw_piece(int piece, const int *pos, int rot, int mode)
323 int tile = mode == ERASE_PIECE ? TILE_PF : FIRST_PIECE_TILE + piece;
324 unsigned char *p = pieces[piece][rot];
327 int x = PF_XOFFS + pos[1] + BLKX(*p);
328 int y = PF_YOFFS + pos[0] + BLKY(*p);
333 ansi_setcursor(y, x * 2);
339 static void drawbg(void)
344 for(i=0; i<SCR_ROWS; i++) {
345 ansi_setcursor(i, 0);
346 for(j=0; j<SCR_COLS; j++) {
352 static void wrtile(int tileid)
357 uint16_t c = tiles[tileid][i];
358 unsigned char cc = c & 0xff;
359 unsigned char ca = c >> 8;
361 ansi_ibmchar(cc, ca);