+/* $NetBSD: tetris.c,v 1.30 2015/06/13 04:53:13 dholland Exp $ */
+
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* @(#)tetris.c 8.1 (Berkeley) 5/31/93
*/
+#include <sys/cdefs.h>
#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1992, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993\
+ The Regents of the University of California. All rights reserved.");
#endif /* not lint */
/*
#include <sys/time.h>
+#include <err.h>
+#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "screen.h"
#include "tetris.h"
-void onintr __P((int));
-void usage __P((void));
+cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
+
+int Rows, Cols; /* current screen size */
+
+static const struct shape *curshape;
+const struct shape *nextshape;
+
+long fallrate; /* less than 1 million; smaller => faster */
+
+int score; /* the obvious thing */
+gid_t gid, egid;
+
+char key_msg[100];
+int showpreview;
+int nocolor;
+
+static void elide(void);
+static void setup_board(void);
+static void onintr(int) __dead;
+static void usage(void) __dead;
/*
* Set up the initial board. The bottom display row is completely set,
* right edges are set.
*/
static void
-setup_board()
+setup_board(void)
{
- register int i;
- register cell *p;
+ int i;
+ cell *p;
p = board;
for (i = B_SIZE; i; i--)
-#ifndef mips
- *p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
-#else /* work around compiler bug */
- *p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2 ? 1 : 0;
-#endif
+ *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 7 : 0;
}
/*
* Elide any full active rows.
*/
static void
-elide()
+elide(void)
{
- register int i, j, base;
- register cell *p;
+ int i, j, base;
+ cell *p;
for (i = A_FIRST; i < A_LAST; i++) {
base = i * B_COLS + 1;
for (j = B_COLS - 2; *p++ != 0;) {
if (--j <= 0) {
/* this row is to be elided */
- bzero(&board[base], B_COLS - 2);
+ memset(&board[base], 0, B_COLS - 2);
scr_update();
tsleep();
while (--base != 0)
}
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
- register int pos, c;
- register struct shape *curshape;
- register char *keys;
- register int level = 2;
- char key_write[6][10];
+ int pos, c;
+ const char *keys;
+ int level = 2;
+#define NUMKEYS 7
+ char key_write[NUMKEYS][10];
int ch, i, j;
+ int fd;
+
+ gid = getgid();
+ egid = getegid();
+ setegid(gid);
+
+ fd = open("/dev/null", O_RDONLY);
+ if (fd < 3)
+ exit(1);
+ close(fd);
- keys = "jkl pq";
+ keys = "jkl pqn";
- while ((ch = getopt(argc, argv, "k:l:s")) != EOF)
+ while ((ch = getopt(argc, argv, "bk:l:ps")) != -1)
switch(ch) {
+ case 'b':
+ nocolor = 1;
+ break;
case 'k':
- if (strlen(keys = optarg) != 6)
+ if (strlen(keys = optarg) != NUMKEYS)
usage();
break;
case 'l':
level = atoi(optarg);
if (level < MINLEVEL || level > MAXLEVEL) {
- (void)fprintf(stderr,
- "tetris: level must be from %d to %d",
- MINLEVEL, MAXLEVEL);
- exit(1);
+ errx(1, "level must be from %d to %d",
+ MINLEVEL, MAXLEVEL);
}
break;
+ case 'p':
+ showpreview = 1;
+ break;
case 's':
showscores(0);
exit(0);
fallrate = 1000000 / level;
- for (i = 0; i <= 5; i++) {
- for (j = i+1; j <= 5; j++) {
+ for (i = 0; i <= (NUMKEYS-1); i++) {
+ for (j = i+1; j <= (NUMKEYS-1); j++) {
if (keys[i] == keys[j]) {
- (void)fprintf(stderr,
- "%s: Duplicate command keys specified.\n",
- argv[0]);
- exit (1);
+ errx(1, "duplicate command keys specified.");
}
}
if (keys[i] == ' ')
}
}
- sprintf(key_msg,
-"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
+ snprintf(key_msg, sizeof(key_msg),
+"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit %s - down",
key_write[0], key_write[1], key_write[2], key_write[3],
- key_write[4], key_write[5]);
+ key_write[4], key_write[5], key_write[6]);
(void)signal(SIGINT, onintr);
scr_init();
scr_set();
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
+ nextshape = randshape();
curshape = randshape();
scr_msg(key_msg, 1);
* Choose a new shape. If it does not fit,
* the game is over.
*/
- curshape = randshape();
+ curshape = nextshape;
+ nextshape = randshape();
pos = A_FIRST*B_COLS + (B_COLS/2)-1;
if (!fits_in(curshape, pos))
break;
scr_msg(key_msg, 0);
scr_msg(msg, 1);
(void) fflush(stdout);
- } while (rwait((struct timeval *)NULL) == -1);
+ } while (rwait(NULL) == -1);
scr_msg(msg, 0);
scr_msg(key_msg, 1);
place(curshape, pos, 0);
}
if (c == keys[1]) {
/* turn */
- struct shape *new = &shapes[curshape->rot];
+ const struct shape *new = &shapes[curshape->rot];
if (fits_in(new, pos))
curshape = new;
}
continue;
}
- if (c == '\f')
+ if (c == keys[6]) {
+ /* move down */
+ if (fits_in(curshape, pos + B_COLS)) {
+ pos += B_COLS;
+ score++;
+ }
+ continue;
+ }
+ if (c == '\f') {
scr_clear();
+ scr_msg(key_msg, 1);
+ }
}
scr_clear();
exit(0);
}
-void
-onintr(signo)
- int signo;
+static void
+onintr(int signo __unused)
{
scr_clear();
scr_end();
exit(0);
}
-void
-usage()
+static void
+usage(void)
{
- (void)fprintf(stderr, "usage: tetris [-s] [-l level] [-keys]\n");
+ (void)fprintf(stderr, "usage: %s [-bps] [-k keys] [-l level]\n",
+ getprogname());
exit(1);
}