source: mainline/uspace/app/tetris/tetris.c@ 3061bc1

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

style: Remove trailing whitespace on non-empty lines, in certain file types.

Command used: tools/srepl '\([^[:space:]]\)\s\+$' '\1' -- *.c *.h *.py *.sh *.s *.S *.ag

  • Property mode set to 100644
File size: 8.6 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;
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;
[ebe70f1]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));
123
[e9a3c52]124 scr_update();
125 tsleep();
[ebe70f1]126
[e9a3c52]127 while (--base != 0)
128 board[base + B_COLS] = board[base];
[ebe70f1]129
[e9a3c52]130 scr_update();
131 tsleep();
[ebe70f1]132
[e9a3c52]133 break;
134 }
135 }
136 }
[ebe70f1]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;
[ebe70f1]161
[e9a3c52]162 for (i = 0; i < j; i++)
[ebe70f1]163 tmp = &shapes[classic ? tmp->rotc : tmp->rot];
164
[e9a3c52]165 return (tmp);
166}
[c594489]167
168static void srandomdev(void)
169{
170 struct timeval tv;
[ebe70f1]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");
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);
[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();
[9996ed5]203
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;
250
[79ae36dd]251 console = console_init(stdin, stdout);
252
[e9a3c52]253 keys = "jkl pq";
[ebe70f1]254
[9996ed5]255 classic = 0;
[79ae36dd]256 showpreview = 1;
[237867d]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 }
281
282 argc -= optind;
283 argv += optind;
284
285 if (argc)
286 usage();
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 }
[ebe70f1]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 }
[ebe70f1]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
[9996ed5]309 scr_init();
[d4b9d28]310 if (loadscores() != EOK)
311 initscores();
312
[9996ed5]313 while (tetris_menu(&level)) {
[237867d]314 fallrate = 1000000 / level;
315
[9996ed5]316 scr_clear();
317 setup_board();
[ebe70f1]318
[9996ed5]319 srandomdev();
320 scr_set();
[ebe70f1]321
322 pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
[9996ed5]323 nextshape = randshape();
324 curshape = randshape();
[ebe70f1]325
[9996ed5]326 scr_msg(key_msg, 1);
[ebe70f1]327
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 }
[ebe70f1]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();
[ebe70f1]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;
357
[9996ed5]358 if (!fits_in(curshape, pos))
359 break;
[ebe70f1]360
[e9a3c52]361 continue;
362 }
[ebe70f1]363
[e9a3c52]364 /*
[9996ed5]365 * Handle command keys.
[e9a3c52]366 */
[9996ed5]367 if (c == keys[5]) {
368 /* quit */
[e9a3c52]369 break;
370 }
[ebe70f1]371
[9996ed5]372 if (c == keys[4]) {
373 static char msg[] =
374 "paused - press RETURN to continue";
[ebe70f1]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());
[ebe70f1]383
[9996ed5]384 scr_msg(msg, 0);
385 scr_msg(key_msg, 1);
386 place(curshape, pos, 0);
387 continue;
388 }
[ebe70f1]389
[9996ed5]390 if (c == keys[0]) {
391 /* move left */
392 if (fits_in(curshape, pos - 1))
393 pos--;
394 continue;
395 }
[ebe70f1]396
[9996ed5]397 if (c == keys[1]) {
398 /* turn */
[ebe70f1]399 const struct shape *new =
400 &shapes[classic ? curshape->rotc : curshape->rot];
401
[9996ed5]402 if (fits_in(new, pos))
403 curshape = new;
404 continue;
405 }
[ebe70f1]406
[9996ed5]407 if (c == keys[2]) {
408 /* move right */
409 if (fits_in(curshape, pos + 1))
410 pos++;
411 continue;
412 }
[ebe70f1]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 }
[ebe70f1]422
[9996ed5]423 if (c == '\f') {
424 scr_clear();
425 scr_msg(key_msg, 1);
426 }
427 }
428
429 scr_clear();
[d4b9d28]430 loadscores();
[9996ed5]431 insertscore(score, level);
[d4b9d28]432 savescores();
[ebe70f1]433 score = 0;
[0aa024b1]434 }
435
436 scr_clear();
[ebe70f1]437 printf("\nGame over.\n");
[9996ed5]438 scr_end();
[ebe70f1]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.