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
52 static volatile const char copyright
[] =
53 "@(#) Copyright (c) 1992, 1993\n"
54 "\tThe Regents of the University of California. All rights reserved.\n";
73 const struct shape
*curshape
;
74 const struct shape
*nextshape
;
82 static void elide(void);
83 static void setup_board(void);
84 static const struct shape
*randshape(void);
86 static void usage(void);
88 static int firstgame
= 1;
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
93 * right edges are set.
95 static void setup_board(void)
100 for (i
= B_SIZE
; i
; i
--)
101 *p
++ = (i
<= (2 * B_COLS
) || (i
% B_COLS
) < 2) ? 0x0000ff : 0x000000;
105 * Elide any full active rows.
107 static void elide(void)
115 for (i
= A_FIRST
; i
< A_LAST
; i
++) {
116 base
= i
* B_COLS
+ 1;
121 /* This row is to be elided */
123 memset(&board
[base
], 0, sizeof(cell
) * (B_COLS
- 2));
129 board
[base
+ B_COLS
] = board
[base
];
157 const struct shape
*randshape(void)
159 const struct shape
*tmp
= &shapes
[rand() % 7];
163 for (i
= 0; i
< j
; i
++)
164 tmp
= &shapes
[classic
? tmp
->rotc
: tmp
->rot
];
169 static void srandomdev(void)
174 srand(ts
.tv_sec
+ ts
.tv_nsec
/ 100000000);
177 static void tetris_menu_draw(int level
)
184 printf("Level = %d (press keys 1 - 9 to change)", level
);
186 printf("Preview is %s (press 'p' to change)", (showpreview
? "on " : "off"));
188 printf("Press 'h' to show hiscore table.");
190 printf("Press 's' to start game.");
192 printf("Press 'q' to quit game.");
194 printf("In game controls:");
196 printf("%s", key_msg
);
199 static int tetris_menu(int *level
)
201 tetris_menu_draw(*level
);
207 showpreview
= !showpreview
;
216 showscores(firstgame
);
217 tetris_menu_draw(*level
);
235 printf("%d", *level
);
241 int main(int argc
, char *argv
[])
247 char key_write
[6][10];
252 console
= console_init(stdin
, stdout
);
259 while ((ch
= getopt(argc
, argv
, "ck:ps")) != -1)
264 * - rotate the other way
270 if (str_size(keys
= optarg
) != 6)
289 for (i
= 0; i
<= 5; i
++) {
290 for (j
= i
+ 1; j
<= 5; j
++) {
291 if (keys
[i
] == keys
[j
]) {
292 fprintf(stderr
, "duplicate command keys specified.");
298 str_cpy(key_write
[i
], sizeof(key_write
[i
]), "<space>");
300 key_write
[i
][0] = keys
[i
];
301 key_write
[i
][1] = '\0';
305 snprintf(key_msg
, sizeof(key_msg
),
306 "%s - left %s - rotate %s - right %s - drop %s - pause %s - quit",
307 key_write
[0], key_write
[1], key_write
[2], key_write
[3],
308 key_write
[4], key_write
[5]);
311 if (loadscores() != EOK
)
314 while (tetris_menu(&level
)) {
315 fallrate
= 1000000 / level
;
323 pos
= A_FIRST
* B_COLS
+ (B_COLS
/ 2) - 1;
324 nextshape
= randshape();
325 curshape
= randshape();
330 place(curshape
, pos
, 1);
332 place(curshape
, pos
, 0);
336 * Timeout. Move down if possible.
338 if (fits_in(curshape
, pos
+ B_COLS
)) {
344 * Put up the current shape `permanently',
345 * bump score, and elide any full rows.
347 place(curshape
, pos
, 1);
352 * Choose a new shape. If it does not fit,
355 curshape
= nextshape
;
356 nextshape
= randshape();
357 pos
= A_FIRST
* B_COLS
+ (B_COLS
/ 2) - 1;
359 if (!fits_in(curshape
, pos
))
366 * Handle command keys.
375 "paused - press RETURN to continue";
377 place(curshape
, pos
, 1);
382 console_flush(console
);
387 place(curshape
, pos
, 0);
393 if (fits_in(curshape
, pos
- 1))
400 const struct shape
*new =
401 &shapes
[classic
? curshape
->rotc
: curshape
->rot
];
403 if (fits_in(new, pos
))
410 if (fits_in(curshape
, pos
+ 1))
417 while (fits_in(curshape
, pos
+ B_COLS
)) {
432 insertscore(score
, level
);
438 printf("\nGame over.\n");
446 fprintf(stderr
, "%s", copyright
);
447 fprintf(stderr
, "usage: tetris [-ps] [-k keys]\n");