source: mainline/uspace/app/tetris/tetris.c@ 6969eea3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6969eea3 was 8d2dd7f2, checked in by Jakub Jermar <jakub@…>, 9 years ago

Reduce the number of files that include <sys/types.h>

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