Fri Nov 6 19:53:37 2015 UTC ()
PR/50411: Rin Okuyama: fix two bugs:
- clear blocks in the 0 row, otherwise the pile up forever.
- black (white) blocks are not shown as "next shape":


(christos)
diff -r1.30 -r1.31 src/games/tetris/screen.c
diff -r1.30 -r1.31 src/games/tetris/tetris.c

cvs diff -r1.30 -r1.31 src/games/tetris/screen.c (switch to unified diff)

--- src/games/tetris/screen.c 2015/07/07 22:53:25 1.30
+++ src/games/tetris/screen.c 2015/11/06 19:53:37 1.31
@@ -1,429 +1,429 @@ @@ -1,429 +1,429 @@
1/* $NetBSD: screen.c,v 1.30 2015/07/07 22:53:25 nat Exp $ */ 1/* $NetBSD: screen.c,v 1.31 2015/11/06 19:53:37 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek and Darren F. Provine. 8 * Chris Torek and Darren F. Provine.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * @(#)screen.c 8.1 (Berkeley) 5/31/93 34 * @(#)screen.c 8.1 (Berkeley) 5/31/93
35 */ 35 */
36 36
37/* 37/*
38 * Tetris screen control. 38 * Tetris screen control.
39 */ 39 */
40 40
41#include <sys/cdefs.h> 41#include <sys/cdefs.h>
42#include <sys/ioctl.h> 42#include <sys/ioctl.h>
43 43
44#include <setjmp.h> 44#include <setjmp.h>
45#include <signal.h> 45#include <signal.h>
46#include <stdio.h> 46#include <stdio.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49#include <term.h> 49#include <term.h>
50#include <termios.h> 50#include <termios.h>
51#include <unistd.h> 51#include <unistd.h>
52 52
53#ifndef sigmask 53#ifndef sigmask
54#define sigmask(s) (1 << ((s) - 1)) 54#define sigmask(s) (1 << ((s) - 1))
55#endif 55#endif
56 56
57#include "screen.h" 57#include "screen.h"
58#include "tetris.h" 58#include "tetris.h"
59 59
60static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */ 60static cell curscreen[B_SIZE]; /* 1 => standout (or otherwise marked) */
61static int curscore; 61static int curscore;
62static int isset; /* true => terminal is in game mode */ 62static int isset; /* true => terminal is in game mode */
63static struct termios oldtt; 63static struct termios oldtt;
64static void (*tstp)(int); 64static void (*tstp)(int);
65 65
66static void scr_stop(int); 66static void scr_stop(int);
67static void stopset(int) __dead; 67static void stopset(int) __dead;
68 68
69 69
70/* 70/*
71 * Routine used by tputs(). 71 * Routine used by tputs().
72 */ 72 */
73int 73int
74put(int c) 74put(int c)
75{ 75{
76 76
77 return (putchar(c)); 77 return (putchar(c));
78} 78}
79 79
80/* 80/*
81 * putstr() is for unpadded strings (either as in termcap(5) or 81 * putstr() is for unpadded strings (either as in termcap(5) or
82 * simply literal strings); putpad() is for padded strings with 82 * simply literal strings); putpad() is for padded strings with
83 * count=1. (See screen.h for putpad().) 83 * count=1. (See screen.h for putpad().)
84 */ 84 */
85#define putstr(s) (void)fputs(s, stdout) 85#define putstr(s) (void)fputs(s, stdout)
86 86
87static void 87static void
88moveto(int r, int c) 88moveto(int r, int c)
89{ 89{
90 char *buf; 90 char *buf;
91 91
92 buf = tiparm(cursor_address, r, c); 92 buf = tiparm(cursor_address, r, c);
93 if (buf != NULL) 93 if (buf != NULL)
94 putpad(buf); 94 putpad(buf);
95} 95}
96 96
97static void 97static void
98setcolor(int c) 98setcolor(int c)
99{ 99{
100 char *buf; 100 char *buf;
101 char monochrome[] = "\033[0m"; 101 char monochrome[] = "\033[0m";
102 if (nocolor == 1) 102 if (nocolor == 1)
103 return; 103 return;
104 if (set_a_foreground == NULL) 104 if (set_a_foreground == NULL)
105 return; 105 return;
106 106
107 if (c == 0 || c == 7) 107 if (c == 0 || c == 7)
108 buf = monochrome; 108 buf = monochrome;
109 else 109 else
110 buf = tiparm(set_a_foreground, c); 110 buf = tiparm(set_a_foreground, c);
111 if (buf != NULL) 111 if (buf != NULL)
112 putpad(buf); 112 putpad(buf);
113} 113}
114 114
115/* 115/*
116 * Set up from termcap. 116 * Set up from termcap.
117 */ 117 */
118void 118void
119scr_init(void) 119scr_init(void)
120{ 120{
121 121
122 setupterm(NULL, 0, NULL); 122 setupterm(NULL, 0, NULL);
123 if (clear_screen == NULL) 123 if (clear_screen == NULL)
124 stop("cannot clear screen"); 124 stop("cannot clear screen");
125 if (cursor_address == NULL || cursor_up == NULL) 125 if (cursor_address == NULL || cursor_up == NULL)
126 stop("cannot do random cursor positioning"); 126 stop("cannot do random cursor positioning");
127} 127}
128 128
129/* this foolery is needed to modify tty state `atomically' */ 129/* this foolery is needed to modify tty state `atomically' */
130static jmp_buf scr_onstop; 130static jmp_buf scr_onstop;
131 131
132static void 132static void
133stopset(int sig) 133stopset(int sig)
134{ 134{
135 sigset_t set; 135 sigset_t set;
136 136
137 (void) signal(sig, SIG_DFL); 137 (void) signal(sig, SIG_DFL);
138 (void) kill(getpid(), sig); 138 (void) kill(getpid(), sig);
139 sigemptyset(&set); 139 sigemptyset(&set);
140 sigaddset(&set, sig); 140 sigaddset(&set, sig);
141 (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); 141 (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0);
142 longjmp(scr_onstop, 1); 142 longjmp(scr_onstop, 1);
143} 143}
144 144
145static void 145static void
146scr_stop(int sig) 146scr_stop(int sig)
147{ 147{
148 sigset_t set; 148 sigset_t set;
149 149
150 scr_end(); 150 scr_end();
151 (void) kill(getpid(), sig); 151 (void) kill(getpid(), sig);
152 sigemptyset(&set); 152 sigemptyset(&set);
153 sigaddset(&set, sig); 153 sigaddset(&set, sig);
154 (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); 154 (void) sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0);
155 scr_set(); 155 scr_set();
156 scr_msg(key_msg, 1); 156 scr_msg(key_msg, 1);
157} 157}
158 158
159/* 159/*
160 * Set up screen mode. 160 * Set up screen mode.
161 */ 161 */
162void 162void
163scr_set(void) 163scr_set(void)
164{ 164{
165 struct winsize ws; 165 struct winsize ws;
166 struct termios newtt; 166 struct termios newtt;
167 sigset_t nsigset, osigset; 167 sigset_t nsigset, osigset;
168 void (*ttou)(int); 168 void (*ttou)(int);
169 169
170 sigemptyset(&nsigset); 170 sigemptyset(&nsigset);
171 sigaddset(&nsigset, SIGTSTP); 171 sigaddset(&nsigset, SIGTSTP);
172 sigaddset(&nsigset, SIGTTOU); 172 sigaddset(&nsigset, SIGTTOU);
173 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); 173 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);
174 if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN) 174 if ((tstp = signal(SIGTSTP, stopset)) == SIG_IGN)
175 (void) signal(SIGTSTP, SIG_IGN); 175 (void) signal(SIGTSTP, SIG_IGN);
176 if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN) 176 if ((ttou = signal(SIGTTOU, stopset)) == SIG_IGN)
177 (void) signal(SIGTTOU, SIG_IGN); 177 (void) signal(SIGTTOU, SIG_IGN);
178 /* 178 /*
179 * At last, we are ready to modify the tty state. If 179 * At last, we are ready to modify the tty state. If
180 * we stop while at it, stopset() above will longjmp back 180 * we stop while at it, stopset() above will longjmp back
181 * to the setjmp here and we will start over. 181 * to the setjmp here and we will start over.
182 */ 182 */
183 (void) setjmp(scr_onstop); 183 (void) setjmp(scr_onstop);
184 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); 184 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
185 Rows = 0, Cols = 0; 185 Rows = 0, Cols = 0;
186 if (ioctl(0, TIOCGWINSZ, &ws) == 0) { 186 if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
187 Rows = ws.ws_row; 187 Rows = ws.ws_row;
188 Cols = ws.ws_col; 188 Cols = ws.ws_col;
189 } 189 }
190 if (Rows == 0) 190 if (Rows == 0)
191 Rows = lines; 191 Rows = lines;
192 if (Cols == 0) 192 if (Cols == 0)
193 Cols = columns; 193 Cols = columns;
194 if (Rows < MINROWS || Cols < MINCOLS) { 194 if (Rows < MINROWS || Cols < MINCOLS) {
195 (void) fprintf(stderr, 195 (void) fprintf(stderr,
196 "the screen is too small: must be at least %dx%d, ", 196 "the screen is too small: must be at least %dx%d, ",
197 MINCOLS, MINROWS); 197 MINCOLS, MINROWS);
198 stop(""); /* stop() supplies \n */ 198 stop(""); /* stop() supplies \n */
199 } 199 }
200 if (tcgetattr(0, &oldtt) < 0) 200 if (tcgetattr(0, &oldtt) < 0)
201 stop("tcgetattr() fails"); 201 stop("tcgetattr() fails");
202 newtt = oldtt; 202 newtt = oldtt;
203 newtt.c_lflag &= ~(ICANON|ECHO); 203 newtt.c_lflag &= ~(ICANON|ECHO);
204 newtt.c_oflag &= ~OXTABS; 204 newtt.c_oflag &= ~OXTABS;
205 if (tcsetattr(0, TCSADRAIN, &newtt) < 0) 205 if (tcsetattr(0, TCSADRAIN, &newtt) < 0)
206 stop("tcsetattr() fails"); 206 stop("tcsetattr() fails");
207 ospeed = cfgetospeed(&newtt); 207 ospeed = cfgetospeed(&newtt);
208 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); 208 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);
209 209
210 /* 210 /*
211 * We made it. We are now in screen mode, modulo TIstr 211 * We made it. We are now in screen mode, modulo TIstr
212 * (which we will fix immediately). 212 * (which we will fix immediately).
213 */ 213 */
214 if (enter_ca_mode) 214 if (enter_ca_mode)
215 putstr(enter_ca_mode); 215 putstr(enter_ca_mode);
216 if (cursor_invisible) 216 if (cursor_invisible)
217 putstr(cursor_invisible); 217 putstr(cursor_invisible);
218 if (tstp != SIG_IGN) 218 if (tstp != SIG_IGN)
219 (void) signal(SIGTSTP, scr_stop); 219 (void) signal(SIGTSTP, scr_stop);
220 if (ttou != SIG_IGN) 220 if (ttou != SIG_IGN)
221 (void) signal(SIGTTOU, ttou); 221 (void) signal(SIGTTOU, ttou);
222 222
223 isset = 1; 223 isset = 1;
224 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); 224 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
225 scr_clear(); 225 scr_clear();
226} 226}
227 227
228/* 228/*
229 * End screen mode. 229 * End screen mode.
230 */ 230 */
231void 231void
232scr_end(void) 232scr_end(void)
233{ 233{
234 sigset_t nsigset, osigset; 234 sigset_t nsigset, osigset;
235 235
236 sigemptyset(&nsigset); 236 sigemptyset(&nsigset);
237 sigaddset(&nsigset, SIGTSTP); 237 sigaddset(&nsigset, SIGTSTP);
238 sigaddset(&nsigset, SIGTTOU); 238 sigaddset(&nsigset, SIGTTOU);
239 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); 239 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);
240 /* move cursor to last line */ 240 /* move cursor to last line */
241 if (cursor_to_ll) 241 if (cursor_to_ll)
242 putstr(cursor_to_ll); 242 putstr(cursor_to_ll);
243 else 243 else
244 moveto(Rows - 1, 0); 244 moveto(Rows - 1, 0);
245 /* exit screen mode */ 245 /* exit screen mode */
246 if (exit_ca_mode) 246 if (exit_ca_mode)
247 putstr(exit_ca_mode); 247 putstr(exit_ca_mode);
248 if (cursor_normal) 248 if (cursor_normal)
249 putstr(cursor_normal); 249 putstr(cursor_normal);
250 (void) fflush(stdout); 250 (void) fflush(stdout);
251 (void) tcsetattr(0, TCSADRAIN, &oldtt); 251 (void) tcsetattr(0, TCSADRAIN, &oldtt);
252 isset = 0; 252 isset = 0;
253 /* restore signals */ 253 /* restore signals */
254 (void) signal(SIGTSTP, tstp); 254 (void) signal(SIGTSTP, tstp);
255 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); 255 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
256} 256}
257 257
258void 258void
259stop(const char *why) 259stop(const char *why)
260{ 260{
261 261
262 if (isset) 262 if (isset)
263 scr_end(); 263 scr_end();
264 (void) fprintf(stderr, "aborting: %s\n", why); 264 (void) fprintf(stderr, "aborting: %s\n", why);
265 exit(1); 265 exit(1);
266} 266}
267 267
268/* 268/*
269 * Clear the screen, forgetting the current contents in the process. 269 * Clear the screen, forgetting the current contents in the process.
270 */ 270 */
271void 271void
272scr_clear(void) 272scr_clear(void)
273{ 273{
274 274
275 putpad(clear_screen); 275 putpad(clear_screen);
276 curscore = -1; 276 curscore = -1;
277 memset((char *)curscreen, 0, sizeof(curscreen)); 277 memset((char *)curscreen, 0, sizeof(curscreen));
278} 278}
279 279
280#if vax && !__GNUC__ 280#if vax && !__GNUC__
281typedef int regcell; /* pcc is bad at `register char', etc */ 281typedef int regcell; /* pcc is bad at `register char', etc */
282#else 282#else
283typedef cell regcell; 283typedef cell regcell;
284#endif 284#endif
285 285
286/* 286/*
287 * Update the screen. 287 * Update the screen.
288 */ 288 */
289void 289void
290scr_update(void) 290scr_update(void)
291{ 291{
292 cell *bp, *sp; 292 cell *bp, *sp;
293 regcell so, cur_so = 0; 293 regcell so, cur_so = 0;
294 int i, ccol, j; 294 int i, ccol, j;
295 sigset_t nsigset, osigset; 295 sigset_t nsigset, osigset;
296 static const struct shape *lastshape; 296 static const struct shape *lastshape;
297 297
298 sigemptyset(&nsigset); 298 sigemptyset(&nsigset);
299 sigaddset(&nsigset, SIGTSTP); 299 sigaddset(&nsigset, SIGTSTP);
300 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset); 300 (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);
301 301
302 /* always leave cursor after last displayed point */ 302 /* always leave cursor after last displayed point */
303 curscreen[D_LAST * B_COLS - 1] = -1; 303 curscreen[D_LAST * B_COLS - 1] = -1;
304 304
305 if (score != curscore) { 305 if (score != curscore) {
306 if (cursor_home) 306 if (cursor_home)
307 putpad(cursor_home); 307 putpad(cursor_home);
308 else 308 else
309 moveto(0, 0); 309 moveto(0, 0);
310 setcolor(0); 310 setcolor(0);
311 (void) printf("Score: %d", score); 311 (void) printf("Score: %d", score);
312 curscore = score; 312 curscore = score;
313 } 313 }
314 314
315 /* draw preview of nextpattern */ 315 /* draw preview of nextpattern */
316 if (showpreview && (nextshape != lastshape)) { 316 if (showpreview && (nextshape != lastshape)) {
317 static int r=5, c=2; 317 static int r=5, c=2;
318 int tr, tc, t;  318 int tr, tc, t;
319 319
320 lastshape = nextshape; 320 lastshape = nextshape;
321  321
322 /* clean */ 322 /* clean */
323 putpad(exit_standout_mode); 323 putpad(exit_standout_mode);
324 moveto(r-1, c-1); putstr(" "); 324 moveto(r-1, c-1); putstr(" ");
325 moveto(r, c-1); putstr(" "); 325 moveto(r, c-1); putstr(" ");
326 moveto(r+1, c-1); putstr(" "); 326 moveto(r+1, c-1); putstr(" ");
327 moveto(r+2, c-1); putstr(" "); 327 moveto(r+2, c-1); putstr(" ");
328 328
329 moveto(r-3, c-2); 329 moveto(r-3, c-2);
330 putstr("Next shape:"); 330 putstr("Next shape:");
331  331
332 /* draw */ 332 /* draw */
333 putpad(enter_standout_mode); 
334 setcolor(nextshape->color); 333 setcolor(nextshape->color);
 334 putpad(enter_standout_mode);
335 moveto(r, 2*c); 335 moveto(r, 2*c);
336 putstr(" "); 336 putstr(" ");
337 for(i=0; i<3; i++) { 337 for(i=0; i<3; i++) {
338 t = c + r*B_COLS; 338 t = c + r*B_COLS;
339 t += nextshape->off[i]; 339 t += nextshape->off[i];
340 340
341 tr = t / B_COLS; 341 tr = t / B_COLS;
342 tc = t % B_COLS; 342 tc = t % B_COLS;
343 343
344 moveto(tr, 2*tc); 344 moveto(tr, 2*tc);
345 putstr(" "); 345 putstr(" ");
346 } 346 }
347 putpad(exit_standout_mode); 347 putpad(exit_standout_mode);
348 } 348 }
349  349
350 bp = &board[D_FIRST * B_COLS]; 350 bp = &board[D_FIRST * B_COLS];
351 sp = &curscreen[D_FIRST * B_COLS]; 351 sp = &curscreen[D_FIRST * B_COLS];
352 for (j = D_FIRST; j < D_LAST; j++) { 352 for (j = D_FIRST; j < D_LAST; j++) {
353 ccol = -1; 353 ccol = -1;
354 for (i = 0; i < B_COLS; bp++, sp++, i++) { 354 for (i = 0; i < B_COLS; bp++, sp++, i++) {
355 if (*sp == (so = *bp)) 355 if (*sp == (so = *bp))
356 continue; 356 continue;
357 *sp = so; 357 *sp = so;
358 if (i != ccol) { 358 if (i != ccol) {
359 if (cur_so && move_standout_mode) { 359 if (cur_so && move_standout_mode) {
360 putpad(exit_standout_mode); 360 putpad(exit_standout_mode);
361 cur_so = 0; 361 cur_so = 0;
362 } 362 }
363 moveto(RTOD(j), CTOD(i)); 363 moveto(RTOD(j), CTOD(i));
364 } 364 }
365 if (enter_standout_mode) { 365 if (enter_standout_mode) {
366 if (so != cur_so) { 366 if (so != cur_so) {
367 setcolor(so); 367 setcolor(so);
368 putpad(so ? 368 putpad(so ?
369 enter_standout_mode : 369 enter_standout_mode :
370 exit_standout_mode); 370 exit_standout_mode);
371 cur_so = so; 371 cur_so = so;
372 } 372 }
373#ifdef DEBUG 373#ifdef DEBUG
374 char buf[3]; 374 char buf[3];
375 snprintf(buf, sizeof(buf), "%d%d", so, so); 375 snprintf(buf, sizeof(buf), "%d%d", so, so);
376 putstr(buf); 376 putstr(buf);
377#else 377#else
378 putstr(" "); 378 putstr(" ");
379#endif 379#endif
380 } else 380 } else
381 putstr(so ? "XX" : " "); 381 putstr(so ? "XX" : " ");
382 ccol = i + 1; 382 ccol = i + 1;
383 /* 383 /*
384 * Look ahead a bit, to avoid extra motion if 384 * Look ahead a bit, to avoid extra motion if
385 * we will be redrawing the cell after the next. 385 * we will be redrawing the cell after the next.
386 * Motion probably takes four or more characters, 386 * Motion probably takes four or more characters,
387 * so we save even if we rewrite two cells 387 * so we save even if we rewrite two cells
388 * `unnecessarily'. Skip it all, though, if 388 * `unnecessarily'. Skip it all, though, if
389 * the next cell is a different color. 389 * the next cell is a different color.
390 */ 390 */
391#define STOP (B_COLS - 3) 391#define STOP (B_COLS - 3)
392 if (i > STOP || sp[1] != bp[1] || so != bp[1]) 392 if (i > STOP || sp[1] != bp[1] || so != bp[1])
393 continue; 393 continue;
394 if (sp[2] != bp[2]) 394 if (sp[2] != bp[2])
395 sp[1] = -1; 395 sp[1] = -1;
396 else if (i < STOP && so == bp[2] && sp[3] != bp[3]) { 396 else if (i < STOP && so == bp[2] && sp[3] != bp[3]) {
397 sp[2] = -1; 397 sp[2] = -1;
398 sp[1] = -1; 398 sp[1] = -1;
399 } 399 }
400 } 400 }
401 } 401 }
402 if (cur_so) 402 if (cur_so)
403 putpad(exit_standout_mode); 403 putpad(exit_standout_mode);
404 (void) fflush(stdout); 404 (void) fflush(stdout);
405 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); 405 (void) sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
406} 406}
407 407
408/* 408/*
409 * Write a message (set!=0), or clear the same message (set==0). 409 * Write a message (set!=0), or clear the same message (set==0).
410 * (We need its length in case we have to overwrite with blanks.) 410 * (We need its length in case we have to overwrite with blanks.)
411 */ 411 */
412void 412void
413scr_msg(char *s, int set) 413scr_msg(char *s, int set)
414{ 414{
415  415
416 if (set || clr_eol == NULL) { 416 if (set || clr_eol == NULL) {
417 int l = strlen(s); 417 int l = strlen(s);
418 418
419 moveto(Rows - 2, ((Cols - l) >> 1) - 1); 419 moveto(Rows - 2, ((Cols - l) >> 1) - 1);
420 if (set) 420 if (set)
421 putstr(s); 421 putstr(s);
422 else 422 else
423 while (--l >= 0) 423 while (--l >= 0)
424 (void) putchar(' '); 424 (void) putchar(' ');
425 } else { 425 } else {
426 moveto(Rows - 2, 0); 426 moveto(Rows - 2, 0);
427 putpad(clr_eol); 427 putpad(clr_eol);
428 } 428 }
429} 429}

cvs diff -r1.30 -r1.31 src/games/tetris/tetris.c (switch to unified diff)

--- src/games/tetris/tetris.c 2015/06/13 04:53:13 1.30
+++ src/games/tetris/tetris.c 2015/11/06 19:53:37 1.31
@@ -1,347 +1,349 @@ @@ -1,347 +1,349 @@
1/* $NetBSD: tetris.c,v 1.30 2015/06/13 04:53:13 dholland Exp $ */ 1/* $NetBSD: tetris.c,v 1.31 2015/11/06 19:53:37 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek and Darren F. Provine. 8 * Chris Torek and Darren F. Provine.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * @(#)tetris.c 8.1 (Berkeley) 5/31/93 34 * @(#)tetris.c 8.1 (Berkeley) 5/31/93
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38#ifndef lint 38#ifndef lint
39__COPYRIGHT("@(#) Copyright (c) 1992, 1993\ 39__COPYRIGHT("@(#) Copyright (c) 1992, 1993\
40 The Regents of the University of California. All rights reserved."); 40 The Regents of the University of California. All rights reserved.");
41#endif /* not lint */ 41#endif /* not lint */
42 42
43/* 43/*
44 * Tetris (or however it is spelled). 44 * Tetris (or however it is spelled).
45 */ 45 */
46 46
47#include <sys/time.h> 47#include <sys/time.h>
48 48
49#include <err.h> 49#include <err.h>
50#include <fcntl.h> 50#include <fcntl.h>
51#include <signal.h> 51#include <signal.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <stdlib.h> 53#include <stdlib.h>
54#include <string.h> 54#include <string.h>
55#include <unistd.h> 55#include <unistd.h>
56 56
57#include "input.h" 57#include "input.h"
58#include "scores.h" 58#include "scores.h"
59#include "screen.h" 59#include "screen.h"
60#include "tetris.h" 60#include "tetris.h"
61 61
62cell board[B_SIZE]; /* 1 => occupied, 0 => empty */ 62cell board[B_SIZE]; /* 1 => occupied, 0 => empty */
63 63
64int Rows, Cols; /* current screen size */ 64int Rows, Cols; /* current screen size */
65 65
66static const struct shape *curshape; 66static const struct shape *curshape;
67const struct shape *nextshape; 67const struct shape *nextshape;
68 68
69long fallrate; /* less than 1 million; smaller => faster */ 69long fallrate; /* less than 1 million; smaller => faster */
70 70
71int score; /* the obvious thing */ 71int score; /* the obvious thing */
72gid_t gid, egid; 72gid_t gid, egid;
73 73
74char key_msg[100]; 74char key_msg[100];
75int showpreview; 75int showpreview;
76int nocolor; 76int nocolor;
77 77
78static void elide(void); 78static void elide(void);
79static void setup_board(void); 79static void setup_board(void);
80static void onintr(int) __dead; 80static void onintr(int) __dead;
81static void usage(void) __dead; 81static void usage(void) __dead;
82 82
83/* 83/*
84 * Set up the initial board. The bottom display row is completely set, 84 * Set up the initial board. The bottom display row is completely set,
85 * along with another (hidden) row underneath that. Also, the left and 85 * along with another (hidden) row underneath that. Also, the left and
86 * right edges are set. 86 * right edges are set.
87 */ 87 */
88static void 88static void
89setup_board(void) 89setup_board(void)
90{ 90{
91 int i; 91 int i;
92 cell *p; 92 cell *p;
93 93
94 p = board; 94 p = board;
95 for (i = B_SIZE; i; i--) 95 for (i = B_SIZE; i; i--)
96 *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 7 : 0; 96 *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 7 : 0;
97} 97}
98 98
99/* 99/*
100 * Elide any full active rows. 100 * Elide any full active rows.
101 */ 101 */
102static void 102static void
103elide(void) 103elide(void)
104{ 104{
105 int i, j, base; 105 int i, j, base;
106 cell *p; 106 cell *p;
107 107
108 for (i = A_FIRST; i < A_LAST; i++) { 108 for (i = A_FIRST; i < A_LAST; i++) {
109 base = i * B_COLS + 1; 109 base = i * B_COLS + 1;
110 p = &board[base]; 110 p = &board[base];
111 for (j = B_COLS - 2; *p++ != 0;) { 111 for (j = B_COLS - 2; *p++ != 0;) {
112 if (--j <= 0) { 112 if (--j <= 0) {
113 /* this row is to be elided */ 113 /* this row is to be elided */
114 memset(&board[base], 0, B_COLS - 2); 114 memset(&board[base], 0, B_COLS - 2);
115 scr_update(); 115 scr_update();
116 tsleep(); 116 tsleep();
117 while (--base != 0) 117 while (--base != 0)
118 board[base + B_COLS] = board[base]; 118 board[base + B_COLS] = board[base];
 119 /* don't forget to clear 0th row */
 120 memset(&board[1], 0, B_COLS - 2);
119 scr_update(); 121 scr_update();
120 tsleep(); 122 tsleep();
121 break; 123 break;
122 } 124 }
123 } 125 }
124 } 126 }
125} 127}
126 128
127int 129int
128main(int argc, char *argv[]) 130main(int argc, char *argv[])
129{ 131{
130 int pos, c; 132 int pos, c;
131 const char *keys; 133 const char *keys;
132 int level = 2; 134 int level = 2;
133#define NUMKEYS 7 135#define NUMKEYS 7
134 char key_write[NUMKEYS][10]; 136 char key_write[NUMKEYS][10];
135 int ch, i, j; 137 int ch, i, j;
136 int fd; 138 int fd;
137 139
138 gid = getgid(); 140 gid = getgid();
139 egid = getegid(); 141 egid = getegid();
140 setegid(gid); 142 setegid(gid);
141 143
142 fd = open("/dev/null", O_RDONLY); 144 fd = open("/dev/null", O_RDONLY);
143 if (fd < 3) 145 if (fd < 3)
144 exit(1); 146 exit(1);
145 close(fd); 147 close(fd);
146 148
147 keys = "jkl pqn"; 149 keys = "jkl pqn";
148 150
149 while ((ch = getopt(argc, argv, "bk:l:ps")) != -1) 151 while ((ch = getopt(argc, argv, "bk:l:ps")) != -1)
150 switch(ch) { 152 switch(ch) {
151 case 'b': 153 case 'b':
152 nocolor = 1; 154 nocolor = 1;
153 break; 155 break;
154 case 'k': 156 case 'k':
155 if (strlen(keys = optarg) != NUMKEYS) 157 if (strlen(keys = optarg) != NUMKEYS)
156 usage(); 158 usage();
157 break; 159 break;
158 case 'l': 160 case 'l':
159 level = atoi(optarg); 161 level = atoi(optarg);
160 if (level < MINLEVEL || level > MAXLEVEL) { 162 if (level < MINLEVEL || level > MAXLEVEL) {
161 errx(1, "level must be from %d to %d", 163 errx(1, "level must be from %d to %d",
162 MINLEVEL, MAXLEVEL); 164 MINLEVEL, MAXLEVEL);
163 } 165 }
164 break; 166 break;
165 case 'p': 167 case 'p':
166 showpreview = 1; 168 showpreview = 1;
167 break; 169 break;
168 case 's': 170 case 's':
169 showscores(0); 171 showscores(0);
170 exit(0); 172 exit(0);
171 case '?': 173 case '?':
172 default: 174 default:
173 usage(); 175 usage();
174 } 176 }
175 177
176 argc -= optind; 178 argc -= optind;
177 argv += optind; 179 argv += optind;
178 180
179 if (argc) 181 if (argc)
180 usage(); 182 usage();
181 183
182 fallrate = 1000000 / level; 184 fallrate = 1000000 / level;
183 185
184 for (i = 0; i <= (NUMKEYS-1); i++) { 186 for (i = 0; i <= (NUMKEYS-1); i++) {
185 for (j = i+1; j <= (NUMKEYS-1); j++) { 187 for (j = i+1; j <= (NUMKEYS-1); j++) {
186 if (keys[i] == keys[j]) { 188 if (keys[i] == keys[j]) {
187 errx(1, "duplicate command keys specified."); 189 errx(1, "duplicate command keys specified.");
188 } 190 }
189 } 191 }
190 if (keys[i] == ' ') 192 if (keys[i] == ' ')
191 strcpy(key_write[i], "<space>"); 193 strcpy(key_write[i], "<space>");
192 else { 194 else {
193 key_write[i][0] = keys[i]; 195 key_write[i][0] = keys[i];
194 key_write[i][1] = '\0'; 196 key_write[i][1] = '\0';
195 } 197 }
196 } 198 }
197 199
198 snprintf(key_msg, sizeof(key_msg), 200 snprintf(key_msg, sizeof(key_msg),
199"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit %s - down", 201"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit %s - down",
200 key_write[0], key_write[1], key_write[2], key_write[3], 202 key_write[0], key_write[1], key_write[2], key_write[3],
201 key_write[4], key_write[5], key_write[6]); 203 key_write[4], key_write[5], key_write[6]);
202 204
203 (void)signal(SIGINT, onintr); 205 (void)signal(SIGINT, onintr);
204 scr_init(); 206 scr_init();
205 setup_board(); 207 setup_board();
206 208
207 srandom(getpid()); 209 srandom(getpid());
208 scr_set(); 210 scr_set();
209 211
210 pos = A_FIRST*B_COLS + (B_COLS/2)-1; 212 pos = A_FIRST*B_COLS + (B_COLS/2)-1;
211 nextshape = randshape(); 213 nextshape = randshape();
212 curshape = randshape(); 214 curshape = randshape();
213 215
214 scr_msg(key_msg, 1); 216 scr_msg(key_msg, 1);
215 217
216 for (;;) { 218 for (;;) {
217 place(curshape, pos, 1); 219 place(curshape, pos, 1);
218 scr_update(); 220 scr_update();
219 place(curshape, pos, 0); 221 place(curshape, pos, 0);
220 c = tgetchar(); 222 c = tgetchar();
221 if (c < 0) { 223 if (c < 0) {
222 /* 224 /*
223 * Timeout. Move down if possible. 225 * Timeout. Move down if possible.
224 */ 226 */
225 if (fits_in(curshape, pos + B_COLS)) { 227 if (fits_in(curshape, pos + B_COLS)) {
226 pos += B_COLS; 228 pos += B_COLS;
227 continue; 229 continue;
228 } 230 }
229 231
230 /* 232 /*
231 * Put up the current shape `permanently', 233 * Put up the current shape `permanently',
232 * bump score, and elide any full rows. 234 * bump score, and elide any full rows.
233 */ 235 */
234 place(curshape, pos, 1); 236 place(curshape, pos, 1);
235 score++; 237 score++;
236 elide(); 238 elide();
237 239
238 /* 240 /*
239 * Choose a new shape. If it does not fit, 241 * Choose a new shape. If it does not fit,
240 * the game is over. 242 * the game is over.
241 */ 243 */
242 curshape = nextshape; 244 curshape = nextshape;
243 nextshape = randshape(); 245 nextshape = randshape();
244 pos = A_FIRST*B_COLS + (B_COLS/2)-1; 246 pos = A_FIRST*B_COLS + (B_COLS/2)-1;
245 if (!fits_in(curshape, pos)) 247 if (!fits_in(curshape, pos))
246 break; 248 break;
247 continue; 249 continue;
248 } 250 }
249 251
250 /* 252 /*
251 * Handle command keys. 253 * Handle command keys.
252 */ 254 */
253 if (c == keys[5]) { 255 if (c == keys[5]) {
254 /* quit */ 256 /* quit */
255 break; 257 break;
256 } 258 }
257 if (c == keys[4]) { 259 if (c == keys[4]) {
258 static char msg[] = 260 static char msg[] =
259 "paused - press RETURN to continue"; 261 "paused - press RETURN to continue";
260 262
261 place(curshape, pos, 1); 263 place(curshape, pos, 1);
262 do { 264 do {
263 scr_update(); 265 scr_update();
264 scr_msg(key_msg, 0); 266 scr_msg(key_msg, 0);
265 scr_msg(msg, 1); 267 scr_msg(msg, 1);
266 (void) fflush(stdout); 268 (void) fflush(stdout);
267 } while (rwait(NULL) == -1); 269 } while (rwait(NULL) == -1);
268 scr_msg(msg, 0); 270 scr_msg(msg, 0);
269 scr_msg(key_msg, 1); 271 scr_msg(key_msg, 1);
270 place(curshape, pos, 0); 272 place(curshape, pos, 0);
271 continue; 273 continue;
272 } 274 }
273 if (c == keys[0]) { 275 if (c == keys[0]) {
274 /* move left */ 276 /* move left */
275 if (fits_in(curshape, pos - 1)) 277 if (fits_in(curshape, pos - 1))
276 pos--; 278 pos--;
277 continue; 279 continue;
278 } 280 }
279 if (c == keys[1]) { 281 if (c == keys[1]) {
280 /* turn */ 282 /* turn */
281 const struct shape *new = &shapes[curshape->rot]; 283 const struct shape *new = &shapes[curshape->rot];
282 284
283 if (fits_in(new, pos)) 285 if (fits_in(new, pos))
284 curshape = new; 286 curshape = new;
285 continue; 287 continue;
286 } 288 }
287 if (c == keys[2]) { 289 if (c == keys[2]) {
288 /* move right */ 290 /* move right */
289 if (fits_in(curshape, pos + 1)) 291 if (fits_in(curshape, pos + 1))
290 pos++; 292 pos++;
291 continue; 293 continue;
292 } 294 }
293 if (c == keys[3]) { 295 if (c == keys[3]) {
294 /* move to bottom */ 296 /* move to bottom */
295 while (fits_in(curshape, pos + B_COLS)) { 297 while (fits_in(curshape, pos + B_COLS)) {
296 pos += B_COLS; 298 pos += B_COLS;
297 score++; 299 score++;
298 } 300 }
299 continue; 301 continue;
300 } 302 }
301 if (c == keys[6]) { 303 if (c == keys[6]) {
302 /* move down */ 304 /* move down */
303 if (fits_in(curshape, pos + B_COLS)) { 305 if (fits_in(curshape, pos + B_COLS)) {
304 pos += B_COLS; 306 pos += B_COLS;
305 score++; 307 score++;
306 } 308 }
307 continue; 309 continue;
308 } 310 }
309 if (c == '\f') { 311 if (c == '\f') {
310 scr_clear(); 312 scr_clear();
311 scr_msg(key_msg, 1); 313 scr_msg(key_msg, 1);
312 } 314 }
313 } 315 }
314 316
315 scr_clear(); 317 scr_clear();
316 scr_end(); 318 scr_end();
317 319
318 (void)printf("Your score: %d point%s x level %d = %d\n", 320 (void)printf("Your score: %d point%s x level %d = %d\n",
319 score, score == 1 ? "" : "s", level, score * level); 321 score, score == 1 ? "" : "s", level, score * level);
320 savescore(level); 322 savescore(level);
321 323
322 printf("\nHit RETURN to see high scores, ^C to skip.\n"); 324 printf("\nHit RETURN to see high scores, ^C to skip.\n");
323 325
324 while ((i = getchar()) != '\n') 326 while ((i = getchar()) != '\n')
325 if (i == EOF) 327 if (i == EOF)
326 break; 328 break;
327 329
328 showscores(level); 330 showscores(level);
329 331
330 exit(0); 332 exit(0);
331} 333}
332 334
333static void 335static void
334onintr(int signo __unused) 336onintr(int signo __unused)
335{ 337{
336 scr_clear(); 338 scr_clear();
337 scr_end(); 339 scr_end();
338 exit(0); 340 exit(0);
339} 341}
340 342
341static void 343static void
342usage(void) 344usage(void)
343{ 345{
344 (void)fprintf(stderr, "usage: %s [-bps] [-k keys] [-l level]\n", 346 (void)fprintf(stderr, "usage: %s [-bps] [-k keys] [-l level]\n",
345 getprogname()); 347 getprogname());
346 exit(1); 348 exit(1);
347} 349}