1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37: #include <sys/cdefs.h>
38: #ifndef lint
39: __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
40: The Regents of the University of California. All rights reserved.\n");
41: #endif
42:
43:
44:
45:
46:
47: #include <sys/time.h>
48:
49: #include <err.h>
50: #include <fcntl.h>
51: #include <signal.h>
52: #include <stdio.h>
53: #include <stdlib.h>
54: #include <string.h>
55: #include <unistd.h>
56:
57: #include "input.h"
58: #include "scores.h"
59: #include "screen.h"
60: #include "tetris.h"
61:
62: cell board[B_SIZE];
63:
64: int Rows, Cols;
65:
66: const struct shape *curshape;
67: const struct shape *nextshape;
68:
69: long fallrate;
70:
71: int score;
72: gid_t gid, egid;
73:
74: char key_msg[100];
75: int showpreview;
76:
77: static void elide(void);
78: static void setup_board(void);
79: int main(int, char **);
80: void onintr(int) __attribute__((__noreturn__));
81: void usage(void) __attribute__((__noreturn__));
82:
83:
84:
85:
86:
87:
88: static void
89: setup_board()
90: {
91: int i;
92: cell *p;
93:
94: p = board;
95: for (i = B_SIZE; i; i--)
96: *p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
97: }
98:
99:
100:
101:
102: static void
103: elide()
104: {
105: int i, j, base;
106: cell *p;
107:
108: for (i = A_FIRST; i < A_LAST; i++) {
109: base = i * B_COLS + 1;
110: p = &board[base];
111: for (j = B_COLS - 2; *p++ != 0;) {
112: if (--j <= 0) {
113:
114: memset(&board[base], 0, B_COLS - 2);
115: scr_update();
116: tsleep();
117: while (--base != 0)
118: board[base + B_COLS] = board[base];
119: scr_update();
120: tsleep();
121: break;
122: }
123: }
124: }
125: }
126:
127: int
128: main(argc, argv)
129: int argc;
130: char *argv[];
131: {
132: int pos, c;
133: const char *keys;
134: int level = 2;
135: char key_write[6][10];
136: int ch, i, j;
137: int fd;
138:
139: gid = getgid();
140: egid = getegid();
141: setegid(gid);
142:
143: fd = open("/dev/null", O_RDONLY);
144: if (fd < 3)
145: exit(1);
146: close(fd);
147:
148: keys = "jkl pq";
149:
150: while ((ch = getopt(argc, argv, "k:l:ps")) != -1)
151: switch(ch) {
152: case 'k':
153: if (strlen(keys = optarg) != 6)
154: usage();
155: break;
156: case 'l':
157: level = atoi(optarg);
158: if (level < MINLEVEL || level > MAXLEVEL) {
159: errx(1, "level must be from %d to %d",
160: MINLEVEL, MAXLEVEL);
161: }
162: break;
163: case 'p':
164: showpreview = 1;
165: break;
166: case 's':
167: showscores(0);
168: exit(0);
169: case '?':
170: default:
171: usage();
172: }
173:
174: argc -= optind;
175: argv += optind;
176:
177: if (argc)
178: usage();
179:
180: fallrate = 1000000 / level;
181:
182: for (i = 0; i <= 5; i++) {
183: for (j = i+1; j <= 5; j++) {
184: if (keys[i] == keys[j]) {
185: errx(1, "duplicate command keys specified.");
186: }
187: }
188: if (keys[i] == ' ')
189: strcpy(key_write[i], "<space>");
190: else {
191: key_write[i][0] = keys[i];
192: key_write[i][1] = '\0';
193: }
194: }
195:
196: sprintf(key_msg,
197: "%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
198: key_write[0], key_write[1], key_write[2], key_write[3],
199: key_write[4], key_write[5]);
200:
201: (void)signal(SIGINT, onintr);
202: scr_init();
203: setup_board();
204:
205: srandom(getpid());
206: scr_set();
207:
208: pos = A_FIRST*B_COLS + (B_COLS/2)-1;
209: nextshape = randshape();
210: curshape = randshape();
211:
212: scr_msg(key_msg, 1);
213:
214: for (;;) {
215: place(curshape, pos, 1);
216: scr_update();
217: place(curshape, pos, 0);
218: c = tgetchar();
219: if (c < 0) {
220:
221:
222:
223: if (fits_in(curshape, pos + B_COLS)) {
224: pos += B_COLS;
225: continue;
226: }
227:
228:
229:
230:
231:
232: place(curshape, pos, 1);
233: score++;
234: elide();
235:
236:
237:
238:
239:
240: curshape = nextshape;
241: nextshape = randshape();
242: pos = A_FIRST*B_COLS + (B_COLS/2)-1;
243: if (!fits_in(curshape, pos))
244: break;
245: continue;
246: }
247:
248:
249:
250:
251: if (c == keys[5]) {
252:
253: break;
254: }
255: if (c == keys[4]) {
256: static char msg[] =
257: "paused - press RETURN to continue";
258:
259: place(curshape, pos, 1);
260: do {
261: scr_update();
262: scr_msg(key_msg, 0);
263: scr_msg(msg, 1);
264: (void) fflush(stdout);
265: } while (rwait((struct timeval *)NULL) == -1);
266: scr_msg(msg, 0);
267: scr_msg(key_msg, 1);
268: place(curshape, pos, 0);
269: continue;
270: }
271: if (c == keys[0]) {
272:
273: if (fits_in(curshape, pos - 1))
274: pos--;
275: continue;
276: }
277: if (c == keys[1]) {
278:
279: const struct shape *new = &shapes[curshape->rot];
280:
281: if (fits_in(new, pos))
282: curshape = new;
283: continue;
284: }
285: if (c == keys[2]) {
286:
287: if (fits_in(curshape, pos + 1))
288: pos++;
289: continue;
290: }
291: if (c == keys[3]) {
292:
293: while (fits_in(curshape, pos + B_COLS)) {
294: pos += B_COLS;
295: score++;
296: }
297: continue;
298: }
299: if (c == '\f') {
300: scr_clear();
301: scr_msg(key_msg, 1);
302: }
303: }
304:
305: scr_clear();
306: scr_end();
307:
308: (void)printf("Your score: %d point%s x level %d = %d\n",
309: score, score == 1 ? "" : "s", level, score * level);
310: savescore(level);
311:
312: printf("\nHit RETURN to see high scores, ^C to skip.\n");
313:
314: while ((i = getchar()) != '\n')
315: if (i == EOF)
316: break;
317:
318: showscores(level);
319:
320: exit(0);
321: }
322:
323: void
324: onintr(signo)
325: int signo __attribute__((__unused__));
326: {
327: scr_clear();
328: scr_end();
329: exit(0);
330: }
331:
332: void
333: usage()
334: {
335: (void)fprintf(stderr, "usage: tetris-bsd [-ps] [-k keys] [-l level]\n");
336: exit(1);
337: }