Subversion Repositories HelenOS-historic

Rev

Rev 1524 | Rev 1538 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 $   */
  3.  
  4. /*-
  5.  * Copyright (c) 1992, 1993
  6.  *  The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * This code is derived from software contributed to Berkeley by
  9.  * Chris Torek and Darren F. Provine.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  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.
  22.  *
  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
  33.  * SUCH DAMAGE.
  34.  *
  35.  *  @(#)tetris.c    8.1 (Berkeley) 5/31/93
  36.  */
  37.  
  38. #ifndef lint
  39. static const char copyright[] =
  40. "@(#) Copyright (c) 1992, 1993\n\
  41.     The Regents of the University of California.  All rights reserved.\n";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * Tetris (or however it is spelled).
  46.  */
  47.  
  48. #include <sys/time.h>
  49. #include <sys/types.h>
  50.  
  51. #include <err.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.  
  62. cell    board[B_SIZE];
  63. int Rows, Cols;
  64. const struct shape *curshape;
  65. const struct shape *nextshape;
  66. long    fallrate;
  67. int score;
  68. //gid_t gid, egid;
  69. char    key_msg[100];
  70. int showpreview, classic;
  71.  
  72. static void elide(void);
  73. static void setup_board(void);
  74. const struct shape *randshape(void);
  75. void    onintr(int);
  76. void    usage(void);
  77.  
  78. /*
  79.  * Set up the initial board.  The bottom display row is completely set,
  80.  * along with another (hidden) row underneath that.  Also, the left and
  81.  * right edges are set.
  82.  */
  83. static void
  84. setup_board(void)
  85. {
  86.     int i;
  87.     cell *p;
  88.  
  89.     p = board;
  90.     for (i = B_SIZE; i; i--)
  91.         *p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
  92. }
  93.  
  94. /*
  95.  * Elide any full active rows.
  96.  */
  97. static void
  98. elide(void)
  99. {
  100.     int rows = 0;
  101.     int i, j, base;
  102.     cell *p;
  103.  
  104.     for (i = A_FIRST; i < A_LAST; i++) {
  105.         base = i * B_COLS + 1;
  106.         p = &board[base];
  107.         for (j = B_COLS - 2; *p++ != 0;) {
  108.             if (--j <= 0) {
  109.                 /* this row is to be elided */
  110.                 rows++;
  111.                 memset(&board[base], 0, B_COLS - 2);
  112.                 scr_update();
  113.                 tsleep();
  114.                 while (--base != 0)
  115.                     board[base + B_COLS] = board[base];
  116.                 scr_update();
  117.                 tsleep();
  118.                 break;
  119.             }
  120.         }
  121.     }
  122.     switch (rows) {
  123.     case 1:
  124.         score += 10;
  125.         break;
  126.     case 2:
  127.         score += 30;
  128.         break;
  129.     case 3:
  130.         score += 70;
  131.         break;
  132.     case 4:
  133.         score += 150;
  134.         break;
  135.     default:
  136.         break;
  137.     }
  138. }
  139.  
  140. const struct shape *
  141. randshape(void)
  142. {
  143.     const struct shape *tmp;
  144.     int i, j;
  145.  
  146.     tmp = &shapes[random() % 7];
  147.     j = random() % 4;
  148.     for (i = 0; i < j; i++)
  149.         tmp = &shapes[classic? tmp->rotc : tmp->rot];
  150.     return (tmp);
  151. }
  152.  
  153. static void srandomdev(void)
  154. {
  155.     struct timeval tv;
  156.  
  157.     gettimeofday(&tv, NULL);
  158.     srandom(tv.tv_sec + tv.tv_usec / 100000);
  159. }
  160.  
  161. int
  162. main(int argc, char *argv[])
  163. {
  164.     int pos, c;
  165.     char *keys;
  166.     int level = 2;
  167.     char key_write[6][10];
  168.     const char *errstr;
  169.     int ch, i, j;
  170.  
  171.     keys = "jkl pq";
  172.  
  173. //  gid = getgid();
  174. //  egid = getegid();
  175. //  setegid(gid);
  176.  
  177.     classic = showpreview = 0;
  178.  
  179. /*  while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */
  180. /*      switch(ch) { */
  181. /*      case 'c': */
  182. /*          /\* */
  183. /*           * this means: */
  184. /*           *  - rotate the other way; */
  185. /*           *  - no reverse video. */
  186. /*           *\/ */
  187. /*          classic = 1; */
  188. /*          break; */
  189. /*      case 'k': */
  190. /*          if (strlen(keys = optarg) != 6) */
  191. /*              usage(); */
  192. /*          break; */
  193. /*      case 'l': */
  194. /*          level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */
  195. /*              &errstr); */
  196. /*          if (errstr) */
  197. /*              errx(1, "level must be from %d to %d", */
  198. /*                  MINLEVEL, MAXLEVEL); */
  199. /*          break; */
  200. /*      case 'p': */
  201. /*          showpreview = 1; */
  202. /*          break; */
  203. /*      case 's': */
  204. /*          showscores(0); */
  205. /*          exit(0); */
  206. /*      default: */
  207. /*          usage(); */
  208. /*      } */
  209.  
  210. /*  argc -= optind; */
  211. /*  argv += optind; */
  212.  
  213. /*  if (argc) */
  214. /*      usage(); */
  215.  
  216.     fallrate = 1000000 / level;
  217.  
  218.     for (i = 0; i <= 5; i++) {
  219.         for (j = i+1; j <= 5; j++) {
  220.             if (keys[i] == keys[j])
  221.                 errx(1, "duplicate command keys specified.");
  222.         }
  223.         if (keys[i] == ' ')
  224.             strncpy(key_write[i], "<space>", sizeof key_write[i]);
  225.         else {
  226.             key_write[i][0] = keys[i];
  227.             key_write[i][1] = '\0';
  228.         }
  229.     }
  230.  
  231.     snprintf(key_msg, sizeof key_msg,
  232. "%s - left   %s - rotate   %s - right   %s - drop   %s - pause   %s - quit",
  233.         key_write[0], key_write[1], key_write[2], key_write[3],
  234.         key_write[4], key_write[5]);
  235.  
  236.     scr_init();
  237.     setup_board();
  238.  
  239.     srandomdev();
  240.     scr_set();
  241.  
  242.     pos = A_FIRST*B_COLS + (B_COLS/2)-1;
  243.     nextshape = randshape();
  244.     curshape = randshape();
  245.  
  246.     scr_msg(key_msg, 1);
  247.  
  248.     for (;;) {
  249.         place(curshape, pos, 1);
  250.         scr_update();
  251.         place(curshape, pos, 0);
  252.         c = tgetchar();
  253.         if (c < 0) {
  254.             /*
  255.              * Timeout.  Move down if possible.
  256.              */
  257.             if (fits_in(curshape, pos + B_COLS)) {
  258.                 pos += B_COLS;
  259.                 continue;
  260.             }
  261.  
  262.             /*
  263.              * Put up the current shape `permanently',
  264.              * bump score, and elide any full rows.
  265.              */
  266.             place(curshape, pos, 1);
  267.             score++;
  268.             elide();
  269.  
  270.             /*
  271.              * Choose a new shape.  If it does not fit,
  272.              * the game is over.
  273.              */
  274.             curshape = nextshape;
  275.             nextshape = randshape();
  276.             pos = A_FIRST*B_COLS + (B_COLS/2)-1;
  277.             if (!fits_in(curshape, pos))
  278.                 break;
  279.             continue;
  280.         }
  281.  
  282.         /*
  283.          * Handle command keys.
  284.          */
  285.         if (c == keys[5]) {
  286.             /* quit */
  287.             break;
  288.         }
  289.         if (c == keys[4]) {
  290.             static char msg[] =
  291.                 "paused - press RETURN to continue";
  292.  
  293.             place(curshape, pos, 1);
  294.             do {
  295.                 scr_update();
  296.                 scr_msg(key_msg, 0);
  297.                 scr_msg(msg, 1);
  298. //              (void) fflush(stdout);
  299.             } while (rwait((struct timeval *)NULL) == -1);
  300.             scr_msg(msg, 0);
  301.             scr_msg(key_msg, 1);
  302.             place(curshape, pos, 0);
  303.             continue;
  304.         }
  305.         if (c == keys[0]) {
  306.             /* move left */
  307.             if (fits_in(curshape, pos - 1))
  308.                 pos--;
  309.             continue;
  310.         }
  311.         if (c == keys[1]) {
  312.             /* turn */
  313.             const struct shape *new = &shapes[
  314.                 classic? curshape->rotc : curshape->rot];
  315.  
  316.             if (fits_in(new, pos))
  317.                 curshape = new;
  318.             continue;
  319.         }
  320.         if (c == keys[2]) {
  321.             /* move right */
  322.             if (fits_in(curshape, pos + 1))
  323.                 pos++;
  324.             continue;
  325.         }
  326.         if (c == keys[3]) {
  327.             /* move to bottom */
  328.             while (fits_in(curshape, pos + B_COLS)) {
  329.                 pos += B_COLS;
  330.                 score++;
  331.             }
  332.             continue;
  333.         }
  334.         if (c == '\f') {
  335.             scr_clear();
  336.             scr_msg(key_msg, 1);
  337.         }
  338.     }
  339.  
  340.     scr_clear();
  341.     scr_end();
  342.  
  343.     if (showpreview == 0)
  344.         (void)printf("Your score:  %d point%s  x  level %d  =  %d\n",
  345.             score, score == 1 ? "" : "s", level, score * level);
  346.     else {
  347.         (void)printf("Your score:  %d point%s x level %d x preview penalty %0.3f = %d\n",
  348.             score, score == 1 ? "" : "s", level, (double)PRE_PENALTY,
  349.             (int)(score * level * PRE_PENALTY));
  350.         score = score * PRE_PENALTY;
  351.     }
  352.     savescore(level);
  353.  
  354.     printf("\nHit RETURN to see high scores, ^C to skip.\n");
  355.  
  356.     while ((i = getchar()) != '\n')
  357.         if (i == EOF)
  358.             break;
  359.  
  360.     showscores(level);
  361.  
  362.     exit(0);
  363. }
  364.  
  365. /* void */
  366. /* onintr(int signo) */
  367. /* { */
  368. /*  scr_clear();        /\* XXX signal race *\/ */
  369. /*  scr_end();      /\* XXX signal race *\/ */
  370. /*  _exit(0); */
  371. /* } */
  372.  
  373. void
  374. usage(void)
  375. {
  376.     (void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n");
  377.     exit(1);
  378. }
  379.