source: mainline/uspace/app/tetris/tetris.c@ a35b458

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 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 <errno.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <stdint.h>
62#include <str.h>
63#include <getopt.h>
64#include "scores.h"
65#include "screen.h"
66#include "tetris.h"
67
68cell board[B_SIZE];
69
70int Rows;
71int Cols;
72
73const struct shape *curshape;
74const struct shape *nextshape;
75
76long fallrate;
77int score;
78char key_msg[100];
79int showpreview;
80int classic;
81
82static void elide(void);
83static void setup_board(void);
84static const struct shape *randshape(void);
85
86static void usage(void);
87
88static int firstgame = 1;
89
90/*
91 * Set up the initial board. The bottom display row is completely set,
92 * along with another (hidden) row underneath that. Also, the left and
93 * right edges are set.
94 */
95static void setup_board(void)
96{
97 int i;
98 cell *p = board;
99
100 for (i = B_SIZE; i; i--)
101 *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
102}
103
104/*
105 * Elide any full active rows.
106 */
107static void elide(void)
108{
109 int rows = 0;
110 int i;
111 int j;
112 int base;
113 cell *p;
114
115 for (i = A_FIRST; i < A_LAST; i++) {
116 base = i * B_COLS + 1;
117 p = &board[base];
118 for (j = B_COLS - 2; *p++ != 0;) {
119 if (--j <= 0) {
120 /* This row is to be elided */
121 rows++;
122 memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
123
124 scr_update();
125 tsleep();
126
127 while (--base != 0)
128 board[base + B_COLS] = board[base];
129
130 scr_update();
131 tsleep();
132
133 break;
134 }
135 }
136 }
137
138 switch (rows) {
139 case 1:
140 score += 10;
141 break;
142 case 2:
143 score += 30;
144 break;
145 case 3:
146 score += 70;
147 break;
148 case 4:
149 score += 150;
150 break;
151 default:
152 break;
153 }
154}
155
156const struct shape *randshape(void)
157{
158 const struct shape *tmp = &shapes[rand() % 7];
159 int i;
160 int j = rand() % 4;
161
162 for (i = 0; i < j; i++)
163 tmp = &shapes[classic ? tmp->rotc : tmp->rot];
164
165 return (tmp);
166}
167
168static void srandomdev(void)
169{
170 struct timeval tv;
171
172 gettimeofday(&tv, NULL);
173 srand(tv.tv_sec + tv.tv_usec / 100000);
174}
175
176static void tetris_menu_draw(int level)
177{
178 clear_screen();
179 moveto(5, 10);
180 puts("Tetris\n\n");
181
182 moveto(8, 10);
183 printf("Level = %d (press keys 1 - 9 to change)", level);
184 moveto(9, 10);
185 printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
186 moveto(12, 10);
187 printf("Press 'h' to show hiscore table.");
188 moveto(13, 10);
189 printf("Press 's' to start game.");
190 moveto(14, 10);
191 printf("Press 'q' to quit game.");
192 moveto(20, 10);
193 printf("In game controls:");
194 moveto(21, 0);
195 puts(key_msg);
196}
197
198static int tetris_menu(int *level)
199{
200 tetris_menu_draw(*level);
201 while (1) {
202 int i = getchar();
203
204 switch(i) {
205 case 'p':
206 showpreview = !showpreview;
207 moveto(9, 21);
208 if (showpreview)
209 printf("on ");
210 else
211 printf("off");
212 break;
213 case 'h':
214 loadscores();
215 showscores(firstgame);
216 tetris_menu_draw(*level);
217 break;
218 case 's':
219 firstgame = 0;
220 return 1;
221 case 'q':
222 return 0;
223 case '1':
224 case '2':
225 case '3':
226 case '4':
227 case '5':
228 case '6':
229 case '7':
230 case '8':
231 case '9':
232 *level = i - '0';
233 moveto(8, 18);
234 printf("%d", *level);
235 break;
236 }
237 }
238}
239
240int main(int argc, char *argv[])
241{
242 int pos;
243 int c;
244 const char *keys;
245 int level = 2;
246 char key_write[6][10];
247 int i;
248 int j;
249 int ch;
250
251 console = console_init(stdin, stdout);
252
253 keys = "jkl pq";
254
255 classic = 0;
256 showpreview = 1;
257
258 while ((ch = getopt(argc, argv, "ck:ps")) != -1)
259 switch(ch) {
260 case 'c':
261 /*
262 * this means:
263 * - rotate the other way
264 * - no reverse video
265 */
266 classic = 1;
267 break;
268 case 'k':
269 if (str_size(keys = optarg) != 6)
270 usage();
271 break;
272 case 'p':
273 showpreview = 1;
274 break;
275 case 's':
276 showscores(0);
277 exit(0);
278 default:
279 usage();
280 }
281
282 argc -= optind;
283 argv += optind;
284
285 if (argc)
286 usage();
287
288 for (i = 0; i <= 5; i++) {
289 for (j = i + 1; j <= 5; j++) {
290 if (keys[i] == keys[j]) {
291 fprintf(stderr, "duplicate command keys specified.");
292 abort();
293 }
294 }
295
296 if (keys[i] == ' ')
297 str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
298 else {
299 key_write[i][0] = keys[i];
300 key_write[i][1] = '\0';
301 }
302 }
303
304 snprintf(key_msg, sizeof(key_msg),
305 "%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
306 key_write[0], key_write[1], key_write[2], key_write[3],
307 key_write[4], key_write[5]);
308
309 scr_init();
310 if (loadscores() != EOK)
311 initscores();
312
313 while (tetris_menu(&level)) {
314 fallrate = 1000000 / level;
315
316 scr_clear();
317 setup_board();
318
319 srandomdev();
320 scr_set();
321
322 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
323 nextshape = randshape();
324 curshape = randshape();
325
326 scr_msg(key_msg, 1);
327
328 while (1) {
329 place(curshape, pos, 1);
330 scr_update();
331 place(curshape, pos, 0);
332 c = tgetchar();
333 if (c < 0) {
334 /*
335 * Timeout. Move down if possible.
336 */
337 if (fits_in(curshape, pos + B_COLS)) {
338 pos += B_COLS;
339 continue;
340 }
341
342 /*
343 * Put up the current shape `permanently',
344 * bump score, and elide any full rows.
345 */
346 place(curshape, pos, 1);
347 score++;
348 elide();
349
350 /*
351 * Choose a new shape. If it does not fit,
352 * the game is over.
353 */
354 curshape = nextshape;
355 nextshape = randshape();
356 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
357
358 if (!fits_in(curshape, pos))
359 break;
360
361 continue;
362 }
363
364 /*
365 * Handle command keys.
366 */
367 if (c == keys[5]) {
368 /* quit */
369 break;
370 }
371
372 if (c == keys[4]) {
373 static char msg[] =
374 "paused - press RETURN to continue";
375
376 place(curshape, pos, 1);
377 do {
378 scr_update();
379 scr_msg(key_msg, 0);
380 scr_msg(msg, 1);
381 console_flush(console);
382 } while (!twait());
383
384 scr_msg(msg, 0);
385 scr_msg(key_msg, 1);
386 place(curshape, pos, 0);
387 continue;
388 }
389
390 if (c == keys[0]) {
391 /* move left */
392 if (fits_in(curshape, pos - 1))
393 pos--;
394 continue;
395 }
396
397 if (c == keys[1]) {
398 /* turn */
399 const struct shape *new =
400 &shapes[classic ? curshape->rotc : curshape->rot];
401
402 if (fits_in(new, pos))
403 curshape = new;
404 continue;
405 }
406
407 if (c == keys[2]) {
408 /* move right */
409 if (fits_in(curshape, pos + 1))
410 pos++;
411 continue;
412 }
413
414 if (c == keys[3]) {
415 /* move to bottom */
416 while (fits_in(curshape, pos + B_COLS)) {
417 pos += B_COLS;
418 score++;
419 }
420 continue;
421 }
422
423 if (c == '\f') {
424 scr_clear();
425 scr_msg(key_msg, 1);
426 }
427 }
428
429 scr_clear();
430 loadscores();
431 insertscore(score, level);
432 savescores();
433 score = 0;
434 }
435
436 scr_clear();
437 printf("\nGame over.\n");
438 scr_end();
439
440 return 0;
441}
442
443void usage(void)
444{
445 fprintf(stderr, "%s", copyright);
446 fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
447 exit(1);
448}
449
450/** @}
451 */
Note: See TracBrowser for help on using the repository browser.