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
RevLine 
[79ae36dd]1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
[e9a3c52]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 *
[79ae36dd]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.
[e9a3c52]43 *
44 */
45
[b2951e2]46/** @addtogroup tetris Tetris
[ebe70f1]47 * @brief Tetris ported from OpenBSD
48 * @{
[b2951e2]49 */
50/** @file
51 */
52
[9260102]53static volatile const char copyright[] =
[ebe70f1]54 "@(#) Copyright (c) 1992, 1993\n"
55 "\tThe Regents of the University of California. All rights reserved.\n";
[e9a3c52]56
57#include <sys/time.h>
[d4b9d28]58#include <errno.h>
[e9a3c52]59#include <stdio.h>
60#include <stdlib.h>
[582a0b8]61#include <stdint.h>
[19f857a]62#include <str.h>
[ebe70f1]63#include <getopt.h>
[e9a3c52]64#include "scores.h"
65#include "screen.h"
66#include "tetris.h"
67
[ebe70f1]68cell board[B_SIZE];
69
70int Rows;
71int Cols;
72
[e9a3c52]73const struct shape *curshape;
74const struct shape *nextshape;
75
[ebe70f1]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;
[e9a3c52]89
90/*
[ebe70f1]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
[e9a3c52]93 * right edges are set.
94 */
[ebe70f1]95static void setup_board(void)
[e9a3c52]96{
97 int i;
[ebe70f1]98 cell *p = board;
[a35b458]99
[e9a3c52]100 for (i = B_SIZE; i; i--)
[ebe70f1]101 *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
[e9a3c52]102}
103
104/*
105 * Elide any full active rows.
106 */
[ebe70f1]107static void elide(void)
[e9a3c52]108{
109 int rows = 0;
[ebe70f1]110 int i;
111 int j;
112 int base;
[e9a3c52]113 cell *p;
[a35b458]114
[e9a3c52]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) {
[ebe70f1]120 /* This row is to be elided */
[e9a3c52]121 rows++;
[ebe70f1]122 memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
[a35b458]123
[e9a3c52]124 scr_update();
125 tsleep();
[a35b458]126
[e9a3c52]127 while (--base != 0)
128 board[base + B_COLS] = board[base];
[a35b458]129
[e9a3c52]130 scr_update();
131 tsleep();
[a35b458]132
[e9a3c52]133 break;
134 }
135 }
136 }
[a35b458]137
[e9a3c52]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
[ebe70f1]156const struct shape *randshape(void)
[e9a3c52]157{
[c718bda]158 const struct shape *tmp = &shapes[rand() % 7];
[ebe70f1]159 int i;
[c718bda]160 int j = rand() % 4;
[a35b458]161
[e9a3c52]162 for (i = 0; i < j; i++)
[ebe70f1]163 tmp = &shapes[classic ? tmp->rotc : tmp->rot];
[a35b458]164
[e9a3c52]165 return (tmp);
166}
[c594489]167
168static void srandomdev(void)
169{
170 struct timeval tv;
[a35b458]171
[c594489]172 gettimeofday(&tv, NULL);
[c718bda]173 srand(tv.tv_sec + tv.tv_usec / 100000);
[c594489]174}
[e9a3c52]175
[1b20da0]176static void tetris_menu_draw(int level)
[9996ed5]177{
[ebe70f1]178 clear_screen();
179 moveto(5, 10);
180 puts("Tetris\n\n");
[a35b458]181
[ebe70f1]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);
[9996ed5]196}
197
[ebe70f1]198static int tetris_menu(int *level)
[9996ed5]199{
200 tetris_menu_draw(*level);
201 while (1) {
[ebe70f1]202 int i = getchar();
[a35b458]203
[9996ed5]204 switch(i) {
205 case 'p':
206 showpreview = !showpreview;
[ebe70f1]207 moveto(9, 21);
[9996ed5]208 if (showpreview)
209 printf("on ");
210 else
211 printf("off");
212 break;
213 case 'h':
[d4b9d28]214 loadscores();
[9996ed5]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':
[ebe70f1]228 case '6':
[9996ed5]229 case '7':
230 case '8':
231 case '9':
232 *level = i - '0';
[ebe70f1]233 moveto(8, 18);
[9996ed5]234 printf("%d", *level);
235 break;
236 }
237 }
238}
239
[ebe70f1]240int main(int argc, char *argv[])
[e9a3c52]241{
[ebe70f1]242 int pos;
243 int c;
[a405563]244 const char *keys;
[e9a3c52]245 int level = 2;
246 char key_write[6][10];
[ebe70f1]247 int i;
248 int j;
249 int ch;
[a35b458]250
[79ae36dd]251 console = console_init(stdin, stdout);
[a35b458]252
[e9a3c52]253 keys = "jkl pq";
[a35b458]254
[9996ed5]255 classic = 0;
[79ae36dd]256 showpreview = 1;
[a35b458]257
[ebe70f1]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 }
[a35b458]281
[ebe70f1]282 argc -= optind;
283 argv += optind;
[a35b458]284
[ebe70f1]285 if (argc)
286 usage();
[a35b458]287
[e9a3c52]288 for (i = 0; i <= 5; i++) {
[ebe70f1]289 for (j = i + 1; j <= 5; j++) {
[f538ef3]290 if (keys[i] == keys[j]) {
291 fprintf(stderr, "duplicate command keys specified.");
292 abort();
293 }
[e9a3c52]294 }
[a35b458]295
[e9a3c52]296 if (keys[i] == ' ')
[ebe70f1]297 str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
[e9a3c52]298 else {
299 key_write[i][0] = keys[i];
300 key_write[i][1] = '\0';
301 }
302 }
[a35b458]303
[ebe70f1]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]);
[a35b458]308
[9996ed5]309 scr_init();
[d4b9d28]310 if (loadscores() != EOK)
311 initscores();
312
[9996ed5]313 while (tetris_menu(&level)) {
[237867d]314 fallrate = 1000000 / level;
[a35b458]315
[9996ed5]316 scr_clear();
317 setup_board();
[a35b458]318
[9996ed5]319 srandomdev();
320 scr_set();
[a35b458]321
[ebe70f1]322 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
[9996ed5]323 nextshape = randshape();
324 curshape = randshape();
[a35b458]325
[9996ed5]326 scr_msg(key_msg, 1);
[a35b458]327
[ebe70f1]328 while (1) {
[9996ed5]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 }
[a35b458]341
[9996ed5]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();
[a35b458]349
[9996ed5]350 /*
351 * Choose a new shape. If it does not fit,
352 * the game is over.
353 */
354 curshape = nextshape;
355 nextshape = randshape();
[ebe70f1]356 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
[a35b458]357
[9996ed5]358 if (!fits_in(curshape, pos))
359 break;
[a35b458]360
[e9a3c52]361 continue;
362 }
[a35b458]363
[e9a3c52]364 /*
[9996ed5]365 * Handle command keys.
[e9a3c52]366 */
[9996ed5]367 if (c == keys[5]) {
368 /* quit */
[e9a3c52]369 break;
370 }
[a35b458]371
[9996ed5]372 if (c == keys[4]) {
373 static char msg[] =
374 "paused - press RETURN to continue";
[a35b458]375
[9996ed5]376 place(curshape, pos, 1);
377 do {
378 scr_update();
379 scr_msg(key_msg, 0);
380 scr_msg(msg, 1);
[79ae36dd]381 console_flush(console);
382 } while (!twait());
[a35b458]383
[9996ed5]384 scr_msg(msg, 0);
385 scr_msg(key_msg, 1);
386 place(curshape, pos, 0);
387 continue;
388 }
[a35b458]389
[9996ed5]390 if (c == keys[0]) {
391 /* move left */
392 if (fits_in(curshape, pos - 1))
393 pos--;
394 continue;
395 }
[a35b458]396
[9996ed5]397 if (c == keys[1]) {
398 /* turn */
[ebe70f1]399 const struct shape *new =
400 &shapes[classic ? curshape->rotc : curshape->rot];
[a35b458]401
[9996ed5]402 if (fits_in(new, pos))
403 curshape = new;
404 continue;
405 }
[a35b458]406
[9996ed5]407 if (c == keys[2]) {
408 /* move right */
409 if (fits_in(curshape, pos + 1))
410 pos++;
411 continue;
412 }
[a35b458]413
[9996ed5]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 }
[a35b458]422
[9996ed5]423 if (c == '\f') {
424 scr_clear();
425 scr_msg(key_msg, 1);
426 }
427 }
[a35b458]428
[9996ed5]429 scr_clear();
[d4b9d28]430 loadscores();
[9996ed5]431 insertscore(score, level);
[d4b9d28]432 savescores();
[ebe70f1]433 score = 0;
[0aa024b1]434 }
[a35b458]435
[0aa024b1]436 scr_clear();
[ebe70f1]437 printf("\nGame over.\n");
[9996ed5]438 scr_end();
[a35b458]439
[501a8ba]440 return 0;
[e9a3c52]441}
442
[ebe70f1]443void usage(void)
[e9a3c52]444{
[0b2d369]445 fprintf(stderr, "%s", copyright);
[ebe70f1]446 fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");
[e9a3c52]447 exit(1);
448}
[b2951e2]449
450/** @}
451 */
Note: See TracBrowser for help on using the repository browser.