source: mainline/uspace/dist/src/c/demos/tetris/tetris.c@ f1380b7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** Attributations
30 *
31 * tetris.c 8.1 (Berkeley) 5/31/93
32 * NetBSD: tetris.c,v 1.2 1995/04/22 07:42:47 cgd
33 * OpenBSD: tetris.c,v 1.21 2006/04/20 03:24:12 ray
34 *
35 * Based upon BSD Tetris
36 *
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California.
39 * Distributed under BSD license.
40 *
41 * This code is derived from software contributed to Berkeley by
42 * Chris Torek and Darren F. Provine.
43 *
44 */
45
46/** @addtogroup tetris Tetris
47 * @brief Tetris ported from OpenBSD
48 * @{
49 */
50/** @file
51 */
52
53static volatile const char copyright[] =
54 "@(#) Copyright (c) 1992, 1993\n"
55 "\tThe Regents of the University of California. All rights reserved.\n";
56
57#include <sys/time.h>
58#include <err.h>
59#include <errno.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <stdint.h>
63#include <str.h>
64#include <getopt.h>
65#include "scores.h"
66#include "screen.h"
67#include "tetris.h"
68
69cell board[B_SIZE];
70
71int Rows;
72int Cols;
73
74const struct shape *curshape;
75const struct shape *nextshape;
76
77long fallrate;
78int score;
79char key_msg[100];
80int showpreview;
81int classic;
82
83static void elide(void);
84static void setup_board(void);
85static const struct shape *randshape(void);
86
87static void usage(void);
88
89static int firstgame = 1;
90
91/*
92 * Set up the initial board. The bottom display row is completely set,
93 * along with another (hidden) row underneath that. Also, the left and
94 * right edges are set.
95 */
96static void setup_board(void)
97{
98 int i;
99 cell *p = board;
100
101 for (i = B_SIZE; i; i--)
102 *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
103}
104
105/*
106 * Elide any full active rows.
107 */
108static void elide(void)
109{
110 int rows = 0;
111 int i;
112 int j;
113 int base;
114 cell *p;
115
116 for (i = A_FIRST; i < A_LAST; i++) {
117 base = i * B_COLS + 1;
118 p = &board[base];
119 for (j = B_COLS - 2; *p++ != 0;) {
120 if (--j <= 0) {
121 /* This row is to be elided */
122 rows++;
123 memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
124
125 scr_update();
126 tsleep();
127
128 while (--base != 0)
129 board[base + B_COLS] = board[base];
130
131 scr_update();
132 tsleep();
133
134 break;
135 }
136 }
137 }
138
139 switch (rows) {
140 case 1:
141 score += 10;
142 break;
143 case 2:
144 score += 30;
145 break;
146 case 3:
147 score += 70;
148 break;
149 case 4:
150 score += 150;
151 break;
152 default:
153 break;
154 }
155}
156
157const struct shape *randshape(void)
158{
159 const struct shape *tmp = &shapes[rand() % 7];
160 int i;
161 int j = rand() % 4;
162
163 for (i = 0; i < j; i++)
164 tmp = &shapes[classic ? tmp->rotc : tmp->rot];
165
166 return (tmp);
167}
168
169static void srandomdev(void)
170{
171 struct timeval tv;
172
173 gettimeofday(&tv, NULL);
174 srand(tv.tv_sec + tv.tv_usec / 100000);
175}
176
177static void tetris_menu_draw(int level)
178{
179 clear_screen();
180 moveto(5, 10);
181 puts("Tetris\n\n");
182
183 moveto(8, 10);
184 printf("Level = %d (press keys 1 - 9 to change)", level);
185 moveto(9, 10);
186 printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
187 moveto(12, 10);
188 printf("Press 'h' to show hiscore table.");
189 moveto(13, 10);
190 printf("Press 's' to start game.");
191 moveto(14, 10);
192 printf("Press 'q' to quit game.");
193 moveto(20, 10);
194 printf("In game controls:");
195 moveto(21, 0);
196 puts(key_msg);
197}
198
199static int tetris_menu(int *level)
200{
201 tetris_menu_draw(*level);
202 while (1) {
203 int i = getchar();
204
205 switch(i) {
206 case 'p':
207 showpreview = !showpreview;
208 moveto(9, 21);
209 if (showpreview)
210 printf("on ");
211 else
212 printf("off");
213 break;
214 case 'h':
215 loadscores();
216 showscores(firstgame);
217 tetris_menu_draw(*level);
218 break;
219 case 's':
220 firstgame = 0;
221 return 1;
222 case 'q':
223 return 0;
224 case '1':
225 case '2':
226 case '3':
227 case '4':
228 case '5':
229 case '6':
230 case '7':
231 case '8':
232 case '9':
233 *level = i - '0';
234 moveto(8, 18);
235 printf("%d", *level);
236 break;
237 }
238 }
239}
240
241int main(int argc, char *argv[])
242{
243 int pos;
244 int c;
245 const char *keys;
246 int level = 2;
247 char key_write[6][10];
248 int i;
249 int j;
250 int ch;
251
252 console = console_init(stdin, stdout);
253
254 keys = "jkl pq";
255
256 classic = 0;
257 showpreview = 1;
258
259 while ((ch = getopt(argc, argv, "ck:ps")) != -1)
260 switch(ch) {
261 case 'c':
262 /*
263 * this means:
264 * - rotate the other way
265 * - no reverse video
266 */
267 classic = 1;
268 break;
269 case 'k':
270 if (str_size(keys = optarg) != 6)
271 usage();
272 break;
273 case 'p':
274 showpreview = 1;
275 break;
276 case 's':
277 showscores(0);
278 exit(0);
279 default:
280 usage();
281 }
282
283 argc -= optind;
284 argv += optind;
285
286 if (argc)
287 usage();
288
289 for (i = 0; i <= 5; i++) {
290 for (j = i + 1; j <= 5; j++) {
291 if (keys[i] == keys[j])
292 errx(1, "%s", "duplicate command keys specified.");
293 }
294
295 if (keys[i] == ' ')
296 str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
297 else {
298 key_write[i][0] = keys[i];
299 key_write[i][1] = '\0';
300 }
301 }
302
303 snprintf(key_msg, sizeof(key_msg),
304 "%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
305 key_write[0], key_write[1], key_write[2], key_write[3],
306 key_write[4], key_write[5]);
307
308 scr_init();
309 if (loadscores() != EOK)
310 initscores();
311
312 while (tetris_menu(&level)) {
313 fallrate = 1000000 / level;
314
315 scr_clear();
316 setup_board();
317
318 srandomdev();
319 scr_set();
320
321 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
322 nextshape = randshape();
323 curshape = randshape();
324
325 scr_msg(key_msg, 1);
326
327 while (1) {
328 place(curshape, pos, 1);
329 scr_update();
330 place(curshape, pos, 0);
331 c = tgetchar();
332 if (c < 0) {
333 /*
334 * Timeout. Move down if possible.
335 */
336 if (fits_in(curshape, pos + B_COLS)) {
337 pos += B_COLS;
338 continue;
339 }
340
341 /*
342 * Put up the current shape `permanently',
343 * bump score, and elide any full rows.
344 */
345 place(curshape, pos, 1);
346 score++;
347 elide();
348
349 /*
350 * Choose a new shape. If it does not fit,
351 * the game is over.
352 */
353 curshape = nextshape;
354 nextshape = randshape();
355 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
356
357 if (!fits_in(curshape, pos))
358 break;
359
360 continue;
361 }
362
363 /*
364 * Handle command keys.
365 */
366 if (c == keys[5]) {
367 /* quit */
368 break;
369 }
370
371 if (c == keys[4]) {
372 static char msg[] =
373 "paused - press RETURN to continue";
374
375 place(curshape, pos, 1);
376 do {
377 scr_update();
378 scr_msg(key_msg, 0);
379 scr_msg(msg, 1);
380 console_flush(console);
381 } while (!twait());
382
383 scr_msg(msg, 0);
384 scr_msg(key_msg, 1);
385 place(curshape, pos, 0);
386 continue;
387 }
388
389 if (c == keys[0]) {
390 /* move left */
391 if (fits_in(curshape, pos - 1))
392 pos--;
393 continue;
394 }
395
396 if (c == keys[1]) {
397 /* turn */
398 const struct shape *new =
399 &shapes[classic ? curshape->rotc : curshape->rot];
400
401 if (fits_in(new, pos))
402 curshape = new;
403 continue;
404 }
405
406 if (c == keys[2]) {
407 /* move right */
408 if (fits_in(curshape, pos + 1))
409 pos++;
410 continue;
411 }
412
413 if (c == keys[3]) {
414 /* move to bottom */
415 while (fits_in(curshape, pos + B_COLS)) {
416 pos += B_COLS;
417 score++;
418 }
419 continue;
420 }
421
422 if (c == '\f') {
423 scr_clear();
424 scr_msg(key_msg, 1);
425 }
426 }
427
428 scr_clear();
429 loadscores();
430 insertscore(score, level);
431 savescores();
432 score = 0;
433 }
434
435 scr_clear();
436 printf("\nGame over.\n");
437 scr_end();
438
439 return 0;
440}
441
442void usage(void)
443{
444 fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
445 exit(1);
446}
447
448/** @}
449 */
Note: See TracBrowser for help on using the repository browser.