[BACK]Return to tetris.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / games / tetris

Annotation of src/games/tetris/tetris.c, Revision 1.33

1.33    ! nia         1: /*     $NetBSD: tetris.c,v 1.32 2016/03/03 21:38:55 nat Exp $  */
1.2       cgd         2:
1.1       cgd         3: /*-
                      4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Chris Torek and Darren F. Provine.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
1.16      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
                     34:  *     @(#)tetris.c    8.1 (Berkeley) 5/31/93
                     35:  */
                     36:
1.3       lukem      37: #include <sys/cdefs.h>
1.1       cgd        38: #ifndef lint
1.19      lukem      39: __COPYRIGHT("@(#) Copyright (c) 1992, 1993\
                     40:  The Regents of the University of California.  All rights reserved.");
1.1       cgd        41: #endif /* not lint */
                     42:
                     43: /*
                     44:  * Tetris (or however it is spelled).
                     45:  */
                     46:
                     47: #include <sys/time.h>
                     48:
1.14      jsm        49: #include <err.h>
1.12      jsm        50: #include <fcntl.h>
1.1       cgd        51: #include <signal.h>
                     52: #include <stdio.h>
                     53: #include <stdlib.h>
                     54: #include <string.h>
                     55: #include <unistd.h>
                     56:
                     57: #include "input.h"
                     58: #include "scores.h"
                     59: #include "screen.h"
                     60: #include "tetris.h"
                     61:
1.13      jsm        62: cell   board[B_SIZE];          /* 1 => occupied, 0 => empty */
                     63:
                     64: int    Rows, Cols;             /* current screen size */
1.32      nat        65: int    Offset;                 /* used to center board & shapes */
1.13      jsm        66:
1.22      dholland   67: static const struct shape *curshape;
1.13      jsm        68: const struct shape *nextshape;
                     69:
                     70: long   fallrate;               /* less than 1 million; smaller => faster */
                     71:
                     72: int    score;                  /* the obvious thing */
1.12      jsm        73: gid_t  gid, egid;
1.13      jsm        74:
                     75: char   key_msg[100];
                     76: int    showpreview;
1.26      pgoyette   77: int    nocolor;
1.12      jsm        78:
1.22      dholland   79: static void elide(void);
                     80: static void setup_board(void);
                     81: static void onintr(int) __dead;
                     82: static void usage(void) __dead;
1.1       cgd        83:
                     84: /*
                     85:  * Set up the initial board.  The bottom display row is completely set,
                     86:  * along with another (hidden) row underneath that.  Also, the left and
                     87:  * right edges are set.
                     88:  */
                     89: static void
1.21      dholland   90: setup_board(void)
1.1       cgd        91: {
1.15      wiz        92:        int i;
                     93:        cell *p;
1.1       cgd        94:
                     95:        p = board;
                     96:        for (i = B_SIZE; i; i--)
1.25      christos   97:                *p++ = (i <= (2 * B_COLS) || (i % B_COLS) < 2) ? 7 : 0;
1.1       cgd        98: }
                     99:
                    100: /*
                    101:  * Elide any full active rows.
                    102:  */
                    103: static void
1.21      dholland  104: elide(void)
1.1       cgd       105: {
1.15      wiz       106:        int i, j, base;
                    107:        cell *p;
1.1       cgd       108:
                    109:        for (i = A_FIRST; i < A_LAST; i++) {
                    110:                base = i * B_COLS + 1;
                    111:                p = &board[base];
                    112:                for (j = B_COLS - 2; *p++ != 0;) {
                    113:                        if (--j <= 0) {
                    114:                                /* this row is to be elided */
1.4       perry     115:                                memset(&board[base], 0, B_COLS - 2);
1.1       cgd       116:                                scr_update();
                    117:                                tsleep();
                    118:                                while (--base != 0)
                    119:                                        board[base + B_COLS] = board[base];
1.31      christos  120:                                /* don't forget to clear 0th row */
                    121:                                memset(&board[1], 0, B_COLS - 2);
1.1       cgd       122:                                scr_update();
                    123:                                tsleep();
                    124:                                break;
                    125:                        }
                    126:                }
                    127:        }
                    128: }
                    129:
                    130: int
1.21      dholland  131: main(int argc, char *argv[])
1.1       cgd       132: {
1.15      wiz       133:        int pos, c;
                    134:        const char *keys;
                    135:        int level = 2;
1.28      mrg       136: #define NUMKEYS 7
                    137:        char key_write[NUMKEYS][10];
1.1       cgd       138:        int ch, i, j;
1.12      jsm       139:        int fd;
                    140:
                    141:        gid = getgid();
                    142:        egid = getegid();
                    143:        setegid(gid);
                    144:
                    145:        fd = open("/dev/null", O_RDONLY);
                    146:        if (fd < 3)
                    147:                exit(1);
                    148:        close(fd);
1.1       cgd       149:
1.28      mrg       150:        keys = "jkl pqn";
1.1       cgd       151:
1.27      pgoyette  152:        while ((ch = getopt(argc, argv, "bk:l:ps")) != -1)
1.1       cgd       153:                switch(ch) {
1.27      pgoyette  154:                case 'b':
1.26      pgoyette  155:                        nocolor = 1;
                    156:                        break;
1.1       cgd       157:                case 'k':
1.28      mrg       158:                        if (strlen(keys = optarg) != NUMKEYS)
1.1       cgd       159:                                usage();
                    160:                        break;
                    161:                case 'l':
                    162:                        level = atoi(optarg);
                    163:                        if (level < MINLEVEL || level > MAXLEVEL) {
1.14      jsm       164:                                errx(1, "level must be from %d to %d",
                    165:                                     MINLEVEL, MAXLEVEL);
1.1       cgd       166:                        }
                    167:                        break;
1.7       hubertf   168:                case 'p':
                    169:                        showpreview = 1;
                    170:                        break;
1.1       cgd       171:                case 's':
                    172:                        showscores(0);
                    173:                        exit(0);
                    174:                case '?':
                    175:                default:
                    176:                        usage();
                    177:                }
                    178:
                    179:        argc -= optind;
                    180:        argv += optind;
                    181:
                    182:        if (argc)
                    183:                usage();
                    184:
                    185:        fallrate = 1000000 / level;
                    186:
1.28      mrg       187:        for (i = 0; i <= (NUMKEYS-1); i++) {
                    188:                for (j = i+1; j <= (NUMKEYS-1); j++) {
1.1       cgd       189:                        if (keys[i] == keys[j]) {
1.14      jsm       190:                                errx(1, "duplicate command keys specified.");
1.1       cgd       191:                        }
                    192:                }
                    193:                if (keys[i] == ' ')
                    194:                        strcpy(key_write[i], "<space>");
                    195:                else {
                    196:                        key_write[i][0] = keys[i];
                    197:                        key_write[i][1] = '\0';
                    198:                }
                    199:        }
                    200:
1.20      dholland  201:        snprintf(key_msg, sizeof(key_msg),
1.29      dholland  202: "%s - left  %s - rotate  %s - right  %s - drop  %s - pause  %s - quit  %s - down",
1.1       cgd       203:                key_write[0], key_write[1], key_write[2], key_write[3],
1.28      mrg       204:                key_write[4], key_write[5], key_write[6]);
1.1       cgd       205:
                    206:        (void)signal(SIGINT, onintr);
                    207:        scr_init();
                    208:        setup_board();
                    209:
                    210:        scr_set();
                    211:
                    212:        pos = A_FIRST*B_COLS + (B_COLS/2)-1;
1.6       hubertf   213:        nextshape = randshape();
1.1       cgd       214:        curshape = randshape();
                    215:
                    216:        scr_msg(key_msg, 1);
                    217:
                    218:        for (;;) {
                    219:                place(curshape, pos, 1);
                    220:                scr_update();
                    221:                place(curshape, pos, 0);
                    222:                c = tgetchar();
                    223:                if (c < 0) {
                    224:                        /*
                    225:                         * Timeout.  Move down if possible.
                    226:                         */
                    227:                        if (fits_in(curshape, pos + B_COLS)) {
                    228:                                pos += B_COLS;
                    229:                                continue;
                    230:                        }
                    231:
                    232:                        /*
                    233:                         * Put up the current shape `permanently',
                    234:                         * bump score, and elide any full rows.
                    235:                         */
                    236:                        place(curshape, pos, 1);
                    237:                        score++;
                    238:                        elide();
                    239:
                    240:                        /*
                    241:                         * Choose a new shape.  If it does not fit,
                    242:                         * the game is over.
                    243:                         */
1.6       hubertf   244:                        curshape = nextshape;
                    245:                        nextshape = randshape();
1.1       cgd       246:                        pos = A_FIRST*B_COLS + (B_COLS/2)-1;
                    247:                        if (!fits_in(curshape, pos))
                    248:                                break;
                    249:                        continue;
                    250:                }
                    251:
                    252:                /*
                    253:                 * Handle command keys.
                    254:                 */
                    255:                if (c == keys[5]) {
                    256:                        /* quit */
                    257:                        break;
                    258:                }
                    259:                if (c == keys[4]) {
                    260:                        static char msg[] =
                    261:                            "paused - press RETURN to continue";
                    262:
                    263:                        place(curshape, pos, 1);
                    264:                        do {
                    265:                                scr_update();
                    266:                                scr_msg(key_msg, 0);
                    267:                                scr_msg(msg, 1);
                    268:                                (void) fflush(stdout);
1.24      plunky    269:                        } while (rwait(NULL) == -1);
1.1       cgd       270:                        scr_msg(msg, 0);
                    271:                        scr_msg(key_msg, 1);
                    272:                        place(curshape, pos, 0);
                    273:                        continue;
                    274:                }
                    275:                if (c == keys[0]) {
                    276:                        /* move left */
                    277:                        if (fits_in(curshape, pos - 1))
                    278:                                pos--;
                    279:                        continue;
                    280:                }
                    281:                if (c == keys[1]) {
                    282:                        /* turn */
1.10      jsm       283:                        const struct shape *new = &shapes[curshape->rot];
1.1       cgd       284:
                    285:                        if (fits_in(new, pos))
                    286:                                curshape = new;
                    287:                        continue;
                    288:                }
                    289:                if (c == keys[2]) {
                    290:                        /* move right */
                    291:                        if (fits_in(curshape, pos + 1))
                    292:                                pos++;
                    293:                        continue;
                    294:                }
                    295:                if (c == keys[3]) {
                    296:                        /* move to bottom */
                    297:                        while (fits_in(curshape, pos + B_COLS)) {
                    298:                                pos += B_COLS;
                    299:                                score++;
                    300:                        }
                    301:                        continue;
                    302:                }
1.28      mrg       303:                if (c == keys[6]) {
                    304:                        /* move down */
                    305:                        if (fits_in(curshape, pos + B_COLS)) {
                    306:                                pos += B_COLS;
                    307:                                score++;
                    308:                        }
                    309:                        continue;
                    310:                }
1.6       hubertf   311:                if (c == '\f') {
1.1       cgd       312:                        scr_clear();
1.6       hubertf   313:                        scr_msg(key_msg, 1);
                    314:                }
1.1       cgd       315:        }
                    316:
                    317:        scr_clear();
                    318:        scr_end();
                    319:
                    320:        (void)printf("Your score:  %d point%s  x  level %d  =  %d\n",
                    321:            score, score == 1 ? "" : "s", level, score * level);
                    322:        savescore(level);
                    323:
                    324:        printf("\nHit RETURN to see high scores, ^C to skip.\n");
                    325:
                    326:        while ((i = getchar()) != '\n')
                    327:                if (i == EOF)
                    328:                        break;
                    329:
                    330:        showscores(level);
                    331:
                    332:        exit(0);
                    333: }
                    334:
1.22      dholland  335: static void
1.21      dholland  336: onintr(int signo __unused)
1.1       cgd       337: {
                    338:        scr_clear();
                    339:        scr_end();
                    340:        exit(0);
                    341: }
                    342:
1.22      dholland  343: static void
1.21      dholland  344: usage(void)
1.1       cgd       345: {
1.30      dholland  346:        (void)fprintf(stderr, "usage: %s [-bps] [-k keys] [-l level]\n",
1.23      pgoyette  347:            getprogname());
1.1       cgd       348:        exit(1);
                    349: }

CVSweb <webmaster@jp.NetBSD.org>