#include "defs.h" int block_can_drop(int shape_no, int xpos, int ypos, int rot) { int y, c; /* take shape matrix column by column (from the left to the right) and compare it against bucket bottom & bucket content (from the bottom to top of shape matrix) */ /* set row index to the bottom of the shape matrix */ c = 4; /* seek from bottom to the verge of shape */ while ((c >= 0) && ((shape[shape_no].table[c][rot] & 16) == 0)) c--; /* calculate y position of shape verge */ y = ypos + c + 1; /* check if this position is inside of the bucket */ if ((c != -1) && (y >= 0)) /* check if this position is inside of the bucket and free */ if ((y == UHEIGHT) || (grid[xpos + 0][y] != 0)) return (0); c = 4; while ((c >= 0) && ((shape[shape_no].table[c][rot] & 8) == 0)) c--; y = ypos + c + 1; if ((c != -1) && (y >= 0)) if ((y == UHEIGHT) || (grid[xpos + 1][y] != 0)) return (0); c = 4; while ((c >= 0) && ((shape[shape_no].table[c][rot] & 4) == 0)) c--; y = ypos + c + 1; if ((c != -1) && (y >= 0)) if ((y == UHEIGHT) || (grid[xpos + 2][y] != 0)) return (0); c = 4; while ((c >= 0) && ((shape[shape_no].table[c][rot] & 2) == 0)) c--; y = ypos + c + 1; if ((c != -1) && (y >= 0)) if ((y == UHEIGHT) || (grid[xpos + 3][y] != 0)) return (0); c = 4; while ((c >= 0) && ((shape[shape_no].table[c][rot] & 1) == 0)) c--; y = ypos + c + 1; if ((c != -1) && (y >= 0)) if ((y == UHEIGHT) || (grid[xpos + 4][y] != 0)) return (0); return (1); } int block_can_left(int shape_no, int xpos, int ypos, int rot) { int x, c; int y0, y1, y2, y3, y4; int t0, t1, t2, t3, t4; t0 = shape[shape_no].table[0][rot]; /* Bit map of 1st Row */ t1 = shape[shape_no].table[1][rot]; /* Bit map of 2nd Row */ t2 = shape[shape_no].table[2][rot]; /* Bit map of 3rd Row */ t3 = shape[shape_no].table[3][rot]; /* Bit map of 4th Row */ t4 = shape[shape_no].table[4][rot]; /* Bit map of 5th Row */ y0 = ypos; y1 = ypos + 1; y2 = ypos + 2; y3 = ypos + 3; y4 = ypos + 4; c = 4; while ((c >= 0) && ((t0 & (1 << c)) == 0)) c--; x = xpos - 1 + (4 - c); if (c != -1) if ((x < 0) || ((y0 >= 0) && (grid[x][y0] != 0))) return (0); c = 4; while ((c >= 0) && ((t1 & (1 << c)) == 0)) c--; x = xpos - 1 + (4 - c); if (c != -1) if ((x < 0) || ((y1 >= 0) && (grid[x][y1] != 0))) return (0); c = 4; while ((c >= 0) && ((t2 & (1 << c)) == 0)) c--; x = xpos - 1 + (4 - c); if (c != -1) if ((x < 0) || ((y2 >= 0) && (grid[x][y2] != 0))) return (0); c = 4; while ((c >= 0) && ((t3 & (1 << c)) == 0)) c--; x = xpos - 1 + (4 - c); if (c != -1) if ((x < 0) || ((y3 >= 0) && (grid[x][y3] != 0))) return (0); c = 4; while ((c >= 0) && ((t4 & (1 << c)) == 0)) c--; x = xpos - 1 + (4 - c); if (c != -1) if ((x < 0) || ((y4 >= 0) && (grid[x][y4] != 0))) return (0); return 1; } int block_can_right(int shape_no, int xpos, int ypos, int rot) { int x, c; int y0, y1, y2, y3, y4; int t0, t1, t2, t3, t4; t0 = shape[shape_no].table[0][rot]; /* Bit map of 1st Row */ t1 = shape[shape_no].table[1][rot]; /* Bit map of 2nd Row */ t2 = shape[shape_no].table[2][rot]; /* Bit map of 3rd Row */ t3 = shape[shape_no].table[3][rot]; /* Bit map of 4th Row */ t4 = shape[shape_no].table[4][rot]; /* Bit map of 4th Row */ y0 = ypos; y1 = ypos + 1; y2 = ypos + 2; y3 = ypos + 3; y4 = ypos + 4; c = 0; while ((c < 5) && ((t0 & (1 << c)) == 0)) c++; x = xpos + 1 + (4 - c); if ((c != 5) && (x >= 0)) if ((x == UWIDTH) || ((y0 >= 0) && (grid[x][y0] != 0))) return (0); c = 0; while ((c < 5) && ((t1 & (1 << c)) == 0)) c++; x = xpos + 1 + (4 - c); if ((c != 5) && (x >= 0)) if ((x == UWIDTH) || ((y1 >= 0) && (grid[x][y1] != 0))) return (0); c = 0; while ((c < 5) && ((t2 & (1 << c)) == 0)) c++; x = xpos + 1 + (4 - c); if ((c != 5) && (x >= 0)) if ((x == UWIDTH) || ((y2 >= 0) && (grid[x][y2] != 0))) return (0); c = 0; while ((c < 5) && ((t3 & (1 << c)) == 0)) c++; x = xpos + 1 + (4 - c); if ((c != 5) && (x >= 0)) if ((x == UWIDTH) || ((y3 >= 0) && (grid[x][y3] != 0))) return (0); c = 0; while ((c < 5) && ((t4 & (1 << c)) == 0)) c++; x = xpos + 1 + (4 - c); if ((c != 5) && (x >= 0)) if ((x == UWIDTH) || ((y4 >= 0) && (grid[x][y4] != 0))) return (0); return 1; } int check_rot(int shape_no, int xpos, int ypos, int newrot) { int i; int ti; /* Bit map of i'th row */ int yi; /* Y position on i'th row */ int x0, x1, x2, x3, x4; x0 = xpos; x1 = xpos + 1; x2 = xpos + 2; x3 = xpos + 3; x4 = xpos + 4; yi = ypos; for (i = 0; i < 5; yi++, i++) { if ((yi) >= 0) { ti = shape[shape_no].table[i][newrot]; if (ti & 16) if ((x0 < 0) || (x0 >= UWIDTH) || (grid[x0][yi] == 1)) return 0; if (ti & 8) if ((x1 < 0) || (x1 >= UWIDTH) || (grid[x1][yi] == 1)) return 0; if (ti & 4) if ((x2 < 0) || (x2 >= UWIDTH) || (grid[x2][yi] == 1)) return 0; if (ti & 2) if ((x3 < 0) || (x3 >= UWIDTH) || (grid[x3][yi] == 1)) return 0; if (ti & 1) if ((x4 < 0) || (x4 >= UWIDTH) || (grid[x4][yi] == 1)) return 0; } } return 1; } void remove_full_lines(int y) { int y1, y2, x; int lines_at_once = 0; /* we check out 5 consecutive lines, one by one, starting with current row */ for (y1 = y; y1 < y + 5 && y1 < UHEIGHT; y1++) { for (x = 0; x < UWIDTH; x++) if (grid[x][y1] == 0) break; /* if we encounter a full line */ if ( x == UWIDTH ) { lines_at_once++; /* we collapse bucket content by 1 line */ for (y2 = y1; y2 > 0; y2--) /* we replace a line by one above */ for (x = 0; x < UWIDTH; x++) grid[x][y2] = grid[x][y2 - 1]; /* and clear newly inserted line (at the top of bucket) */ for (x = 0; x < UWIDTH; x++) grid[x][0] = 0; /* remove a full line "visually" */ scdelete(y1); /* insert "visually" an empty line (at the top of bucket) */ scinsert(0); lines++; } } if (lines_at_once) score += ((shape[shape_no].pointv[rot] + (UHEIGHT - ypos)) * (level - next + 1) * factorial(lines_at_once)); } void update_highscore_table(void) { int i, j; char buff[MAXDATELEN+1]; struct utsname utsname; struct tm *loctime; time_t curtime; /* re-read high-score table in case someone else on the network is * playing at the same time */ read_high_scores(); /* Next line finds score greater than current one */ for (i = 0; ((i < HIGH_SCORES_TABLE_SIZE) && (score >= high_scores[i].score)); i++); i--; if ((score_position = i) >= 0) { for (j = 0; j < i; j++) high_scores[j] = high_scores[j + 1]; strncpy(high_scores[i].name, name, MAXNAMELEN); high_scores[i].score = score; high_scores[i].lines = lines; high_scores[i].level = level; if ( uname(&utsname) < 0 ) strncpy(high_scores[i].hostname, "unknown-host", MAXHOSTLEN); else strncpy(high_scores[i].hostname, utsname.nodename, MAXHOSTLEN); curtime = time(NULL); loctime = localtime(&curtime); strftime(buff, MAXDATELEN+1, "%m/%d/%y %H:%M", loctime); strcpy(high_scores[i].date, buff); write_high_scores(); } } void read_high_scores(void) { FILE *fp; int i, size; char j, *s; if ((fp = fopen(HIGH_SCORES_TABLE, "r")) == NULL) { fprintf(stderr, "pentix: no high scores file\n"); return; } size = sizeof(high_scores); s = (char *) &high_scores; bzero(s, size); j = 0; for (i = 0; i < size ; i++) *s++ = (getc(fp) ^ (quotations[13][j++ & 0x3f] | 0x80)); fclose(fp); } void write_high_scores(void) { FILE *fp; int i, size; char j, *s; if ((fp = fopen(HIGH_SCORES_TABLE, "w")) == NULL) { fprintf(stderr, "pentix: couldn't open high scores file %s\n", HIGH_SCORES_TABLE); return; } j = 0; s = (char *) &high_scores; for (i = 0; i < (size = sizeof(high_scores)); i++) putc(*s++ ^ (quotations[13][j++ & 0x3f] | 0x80), fp); fclose(fp); } void print_high_scores(void) { int i; char buf[BUFSIZ]; /* re-read high-score table in case someone else on the network is * playing at the same time */ read_high_scores(); clear(); scmove(13, 1); attrset(COLOR_PAIR(WHITE)|A_BOLD); addstr("PENTIX 16 highest results"); scmove(13, 2); addstr("==========================="); scmove(7, 4); attrset(COLOR_PAIR(WHITE)); addstr("Pos Name Score Lines Level Date "); scmove(7, 5); addstr("=== ======== ======= ===== === =============="); for ( i = 0; i < HIGH_SCORES_TABLE_SIZE; i++ ) { sprintf(buf, "%3d %8s %7d %5d %3d %14s\n", HIGH_SCORES_TABLE_SIZE - i, high_scores[i].name, high_scores[i].score, high_scores[i].lines, high_scores[i].level, high_scores[i].date); scmove(7, 21-i); addstr(buf); } } void read_quotations(void) { FILE *fp; char buf[BUFSIZ]; if ((fp = fopen(QUOTATIONS_TABLE, "r")) == NULL) { fprintf(stderr, "pentix: no quotations file\n"); return; } qcount = 0; do { fgets(buf, BUFSIZ, fp); if (!feof(fp)) { strcpy(quotations[qcount], buf); qcount++; } } while(!feof(fp)); fclose(fp); } void print_quotation(void) { scmove(0, 23); attrset(COLOR_PAIR(YELLOW)|A_BOLD); addstr(quotations[random() % qcount]); } void print_authors(void) { int i; char *authors[] = { "\n", "pentix v2.4\n", "by Andy Tchoritch \n", "Mon Oct 9 11:16:10 EEST 2000\n\n", "- game idea\n", "inspired by the original msdos version of pentix\n", "by Marta & Adrian Soncodi (C) 1986 ICE/APP\n", "which is based on the original version of tetris\n", "by Alexey Pazhitnov (C) 1985\n\n", "- source code\n", "based on the version of tetris ported to linux\n" "by Zeyd M. Ben-Halim ,\n", "based on the version of tetris modified to run on ascii terminals\n", "by Roberto Biancardi <..!unido!tmpmbx!deejay!i2ack!usixth!bob>,\n", "based on the version of tetris posted\n", "by Phill Everson \n", "and Martyn Shortley ,\n", "based on the version posted to comp.sources.games\n" "by Adam Marguilies \n\n", "hit any key to continue...\n", NULL }; for ( i=0; authors[i] != NULL; i++ ) addstr(authors[i]); waituser(); } void print_help(void) { int i, c; char *help[] = { "\n\n\n\n\n", " Use the following keys :\n\n", " 7 to move piece to the left\n", " 8 to rotate piece\n", " 9 to move piece to the right\n\n", " space bar to drop piece\n\n", " 1 to switch next on/off\n", " 6 to increase level\n", " 2 PANIC button (immediate exit)\n", " ESC to start a new game\n", "\n\n\n\n", " You can skip the intro by pressing any key\n", " or 0..7 for the level\n", NULL }; move(0, 0); attrset(COLOR_PAIR(GREEN)); for ( i=0; help[i] != NULL; i++ ) addstr(help[i]); c = waituser(); if (isdigit(c)) level = atoi((const char *) &c) & 7; else setup_level(); } void setup_level(void) { int c; clear(); move(14, 20); attrset(COLOR_PAIR(YELLOW)|A_BOLD); addstr("What's your level ? [0..7]"); do { c = waituser(); } while (!isdigit(c)); level = atoi((const char *) &c) & 7; } void show_score(int on) { char l1[32], l2[32], l3[32], r1[32], r2[32], r3[32]; char *lp1, *lp2, *lp3, *rp1, *rp2, *rp3; if ( on ) { sprintf(lp1 = l1, "Your level: %d", level); sprintf(lp2 = l2, "Full lines: %d", lines); sprintf(lp3 = l3, " SCORE: %d", score); sprintf(rp1 = r1, "Champion: %s", high_scores[HIGH_SCORES_TABLE_SIZE-1].name); sprintf(rp2 = r2, "Hostname: %s", high_scores[HIGH_SCORES_TABLE_SIZE-1].hostname); sprintf(rp3 = r3, "Record: %d", high_scores[HIGH_SCORES_TABLE_SIZE-1].score); } else { lp1 = lp2 = lp3 = " "; rp1 = rp2 = rp3 = " "; } attrset(COLOR_PAIR(GREEN)); scmove(2, 2); addstr(lp1); scmove(2, 3); addstr(lp2); scmove(2, 5); addstr(lp3); attrset(COLOR_PAIR(YELLOW)|A_BOLD); scmove(27, 2); addstr(rp1); scmove(27, 3); addstr(rp2); scmove(27, 5); addstr(rp3); } int factorial(int x) { if (x == 1) return 1; else return x * factorial(x - 1); } int usec_delta(int next, int prev) { if (next < prev) prev -= 1000000; return next - prev; }