2 * Copyright (c) 2011 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
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
35 * Based upon BSD Tetris
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California.
39 * Distributed under BSD license.
41 * This code is derived from software contributed to Berkeley by
42 * Chris Torek and Darren F. Provine.
46 /** @addtogroup tetris Tetris
47 * @brief Tetris ported from OpenBSD
53 static volatile const char copyright
[] =
54 "@(#) Copyright (c) 1992, 1993\n"
55 "\tThe Regents of the University of California. All rights reserved.\n";
58 #include <sys/types.h>
75 const struct shape
*curshape
;
76 const struct shape
*nextshape
;
84 static void elide(void);
85 static void setup_board(void);
86 static const struct shape
*randshape(void);
88 static void usage(void);
90 static int firstgame
= 1;
93 * Set up the initial board. The bottom display row is completely set,
94 * along with another (hidden) row underneath that. Also, the left and
95 * right edges are set.
97 static void setup_board(void)
102 for (i
= B_SIZE
; i
; i
--)
103 *p
++ = (i
<= (2 * B_COLS
) || (i
% B_COLS
) < 2) ? 0x0000ff : 0x000000;
107 * Elide any full active rows.
109 static void elide(void)
117 for (i
= A_FIRST
; i
< A_LAST
; i
++) {
118 base
= i
* B_COLS
+ 1;
120 for (j
= B_COLS
- 2; *p
++ != 0;) {
122 /* This row is to be elided */
124 memset(&board
[base
], 0, sizeof(cell
) * (B_COLS
- 2));
130 board
[base
+ B_COLS
] = board
[base
];
158 const struct shape
*randshape(void)
160 const struct shape
*tmp
= &shapes
[random() % 7];
162 int j
= random() % 4;
164 for (i
= 0; i
< j
; i
++)
165 tmp
= &shapes
[classic
? tmp
->rotc
: tmp
->rot
];
170 static void srandomdev(void)
174 gettimeofday(&tv
, NULL
);
175 srandom(tv
.tv_sec
+ tv
.tv_usec
/ 100000);
178 static void tetris_menu_draw(int level
)
185 printf("Level = %d (press keys 1 - 9 to change)", level
);
187 printf("Preview is %s (press 'p' to change)", (showpreview
? "on ": "off"));
189 printf("Press 'h' to show hiscore table.");
191 printf("Press 's' to start game.");
193 printf("Press 'q' to quit game.");
195 printf("In game controls:");
200 static int tetris_menu(int *level
)
202 tetris_menu_draw(*level
);
208 showpreview
= !showpreview
;
217 showscores(firstgame
);
218 tetris_menu_draw(*level
);
236 printf("%d", *level
);
242 int main(int argc
, char *argv
[])
248 char key_write
[6][10];
253 console
= console_init(stdin
, stdout
);
260 while ((ch
= getopt(argc
, argv
, "ck:ps")) != -1)
265 * - rotate the other way
271 if (str_size(keys
= optarg
) != 6)
290 for (i
= 0; i
<= 5; i
++) {
291 for (j
= i
+ 1; j
<= 5; j
++) {
292 if (keys
[i
] == keys
[j
])
293 errx(1, "%s", "duplicate command keys specified.");
297 str_cpy(key_write
[i
], sizeof(key_write
[i
]), "<space>");
299 key_write
[i
][0] = keys
[i
];
300 key_write
[i
][1] = '\0';
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]);
310 if (loadscores() != EOK
)
313 while (tetris_menu(&level
)) {
314 fallrate
= 1000000 / level
;
322 pos
= A_FIRST
* B_COLS
+ (B_COLS
/ 2) - 1;
323 nextshape
= randshape();
324 curshape
= randshape();
329 place(curshape
, pos
, 1);
331 place(curshape
, pos
, 0);
335 * Timeout. Move down if possible.
337 if (fits_in(curshape
, pos
+ B_COLS
)) {
343 * Put up the current shape `permanently',
344 * bump score, and elide any full rows.
346 place(curshape
, pos
, 1);
351 * Choose a new shape. If it does not fit,
354 curshape
= nextshape
;
355 nextshape
= randshape();
356 pos
= A_FIRST
* B_COLS
+ (B_COLS
/ 2) - 1;
358 if (!fits_in(curshape
, pos
))
365 * Handle command keys.
374 "paused - press RETURN to continue";
376 place(curshape
, pos
, 1);
381 console_flush(console
);
386 place(curshape
, pos
, 0);
392 if (fits_in(curshape
, pos
- 1))
399 const struct shape
*new =
400 &shapes
[classic
? curshape
->rotc
: curshape
->rot
];
402 if (fits_in(new, pos
))
409 if (fits_in(curshape
, pos
+ 1))
416 while (fits_in(curshape
, pos
+ B_COLS
)) {
431 insertscore(score
, level
);
437 printf("\nGame over.\n");
445 fprintf(stderr
, "usage: tetris [-ps] [-k keys]\n");