1
/* $OpenBSD: tetris.c,v 1.21 2006/04/20 03:24:12 ray Exp $ */
2
/* $NetBSD: tetris.c,v 1.2 1995/04/22 07:42:47 cgd Exp $ */
5
* Copyright (c) 1992, 1993
6
* The Regents of the University of California. All rights reserved.
8
* This code is derived from software contributed to Berkeley by
9
* Chris Torek and Darren F. Provine.
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
* 3. Neither the name of the University nor the names of its contributors
20
* may be used to endorse or promote products derived from this software
21
* without specific prior written permission.
23
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
* @(#)tetris.c 8.1 (Berkeley) 5/31/93
38
/** @addtogroup tetris Tetris
39
* @brief Tetris ported from OpenBSD
45
static const char copyright[] =
46
"@(#) Copyright (c) 1992, 1993\n"
47
"\tThe Regents of the University of California. All rights reserved.\n";
50
#include <sys/types.h>
69
const struct shape *curshape;
70
const struct shape *nextshape;
78
static void elide(void);
79
static void setup_board(void);
80
static const struct shape *randshape(void);
82
static void usage(void);
84
static int firstgame = 1;
87
* Set up the initial board. The bottom display row is completely set,
88
* along with another (hidden) row underneath that. Also, the left and
89
* right edges are set.
91
static void setup_board(void)
96
for (i = B_SIZE; i; i--)
97
*p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 0x0000ff : 0x000000;
101
* Elide any full active rows.
103
static void elide(void)
111
for (i = A_FIRST; i < A_LAST; i++) {
112
base = i * B_COLS + 1;
114
for (j = B_COLS - 2; *p++ != 0;) {
116
/* This row is to be elided */
118
memset(&board[base], 0, sizeof(cell) * (B_COLS - 2));
124
board[base + B_COLS] = board[base];
152
const struct shape *randshape(void)
154
const struct shape *tmp = &shapes[random() % 7];
156
int j = random() % 4;
158
for (i = 0; i < j; i++)
159
tmp = &shapes[classic ? tmp->rotc : tmp->rot];
164
static void srandomdev(void)
168
gettimeofday(&tv, NULL);
169
srandom(tv.tv_sec + tv.tv_usec / 100000);
172
static void tetris_menu_draw(int level)
179
printf("Level = %d (press keys 1 - 9 to change)", level);
181
printf("Preview is %s (press 'p' to change)", (showpreview ? "on ": "off"));
183
printf("Press 'h' to show hiscore table.");
185
printf("Press 's' to start game.");
187
printf("Press 'q' to quit game.");
189
printf("In game controls:");
194
static int tetris_menu(int *level)
196
tetris_menu_draw(*level);
202
showpreview = !showpreview;
211
showscores(firstgame);
212
tetris_menu_draw(*level);
230
printf("%d", *level);
236
int main(int argc, char *argv[])
242
char key_write[6][10];
252
while ((ch = getopt(argc, argv, "ck:ps")) != -1)
257
* - rotate the other way
263
if (str_size(keys = optarg) != 6)
282
for (i = 0; i <= 5; i++) {
283
for (j = i + 1; j <= 5; j++) {
284
if (keys[i] == keys[j])
285
errx(1, "duplicate command keys specified.");
289
str_cpy(key_write[i], sizeof(key_write[i]), "<space>");
291
key_write[i][0] = keys[i];
292
key_write[i][1] = '\0';
296
snprintf(key_msg, sizeof(key_msg),
297
"%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
298
key_write[0], key_write[1], key_write[2], key_write[3],
299
key_write[4], key_write[5]);
302
if (loadscores() != EOK)
305
while (tetris_menu(&level)) {
306
fallrate = 1000000 / level;
314
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
315
nextshape = randshape();
316
curshape = randshape();
321
place(curshape, pos, 1);
323
place(curshape, pos, 0);
327
* Timeout. Move down if possible.
329
if (fits_in(curshape, pos + B_COLS)) {
335
* Put up the current shape `permanently',
336
* bump score, and elide any full rows.
338
place(curshape, pos, 1);
343
* Choose a new shape. If it does not fit,
346
curshape = nextshape;
347
nextshape = randshape();
348
pos = A_FIRST * B_COLS + (B_COLS / 2) - 1;
350
if (!fits_in(curshape, pos))
357
* Handle command keys.
366
"paused - press RETURN to continue";
368
place(curshape, pos, 1);
373
(void) fflush(stdout);
374
} while (rwait((struct timeval *) NULL) == -1);
378
place(curshape, pos, 0);
384
if (fits_in(curshape, pos - 1))
391
const struct shape *new =
392
&shapes[classic ? curshape->rotc : curshape->rot];
394
if (fits_in(new, pos))
401
if (fits_in(curshape, pos + 1))
408
while (fits_in(curshape, pos + B_COLS)) {
423
insertscore(score, level);
429
printf("\nGame over.\n");
437
fprintf(stderr, "usage: tetris [-ps] [-k keys]\n");