Subversion Repositories HelenOS

Rev

Rev 1590 | Rev 1688 | 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. /** @addtogroup tetris Tetris
  39.  * @brief   Tetris ported from OpenBSD
  40.  * @{
  41.  */
  42. /** @file
  43.  */
  44.  
  45. #ifndef lint
  46. static const char copyright[] =
  47. "@(#) Copyright (c) 1992, 1993\n\
  48.     The Regents of the University of California.  All rights reserved.\n";
  49. #endif /* not lint */
  50.  
  51. /*
  52.  * Tetris (or however it is spelled).
  53.  */
  54.  
  55. #include <sys/time.h>
  56. #include <sys/types.h>
  57.  
  58. #include <err.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <unistd.h>
  63.  
  64. #include "input.h"
  65. #include "scores.h"
  66. #include "screen.h"
  67. #include "tetris.h"
  68.  
  69. cell    board[B_SIZE];
  70. int Rows, Cols;
  71. const struct shape *curshape;
  72. const struct shape *nextshape;
  73. long    fallrate;
  74. int score;
  75. //gid_t gid, egid;
  76. char    key_msg[100];
  77. int showpreview, classic;
  78.  
  79. static void elide(void);
  80. static void setup_board(void);
  81. const struct shape *randshape(void);
  82. void    onintr(int);
  83. void    usage(void);
  84.  
  85. /*
  86.  * Set up the initial board.  The bottom display row is completely set,
  87.  * along with another (hidden) row underneath that.  Also, the left and
  88.  * right edges are set.
  89.  */
  90. static void
  91. setup_board(void)
  92. {
  93.     int i;
  94.     cell *p;
  95.  
  96.     p = board;
  97.     for (i = B_SIZE; i; i--)
  98.         *p++ = i <= (2 * B_COLS) || (i % B_COLS) < 2;
  99. }
  100.  
  101. /*
  102.  * Elide any full active rows.
  103.  */
  104. static void
  105. elide(void)
  106. {
  107.     int rows = 0;
  108.     int i, j, base;
  109.     cell *p;
  110.  
  111.     for (i = A_FIRST; i < A_LAST; i++) {
  112.         base = i * B_COLS + 1;
  113.         p = &board[base];
  114.         for (j = B_COLS - 2; *p++ != 0;) {
  115.             if (--j <= 0) {
  116.                 /* this row is to be elided */
  117.                 rows++;
  118.                 memset(&board[base], 0, B_COLS - 2);
  119.                 scr_update();
  120.                 tsleep();
  121.                 while (--base != 0)
  122.                     board[base + B_COLS] = board[base];
  123.                 scr_update();
  124.                 tsleep();
  125.                 break;
  126.             }
  127.         }
  128.     }
  129.     switch (rows) {
  130.     case 1:
  131.         score += 10;
  132.         break;
  133.     case 2:
  134.         score += 30;
  135.         break;
  136.     case 3:
  137.         score += 70;
  138.         break;
  139.     case 4:
  140.         score += 150;
  141.         break;
  142.     default:
  143.         break;
  144.     }
  145. }
  146.  
  147. const struct shape *
  148. randshape(void)
  149. {
  150.     const struct shape *tmp;
  151.     int i, j;
  152.  
  153.     tmp = &shapes[random() % 7];
  154.     j = random() % 4;
  155.     for (i = 0; i < j; i++)
  156.         tmp = &shapes[classic? tmp->rotc : tmp->rot];
  157.     return (tmp);
  158. }
  159.  
  160. static void srandomdev(void)
  161. {
  162.     struct timeval tv;
  163.  
  164.     gettimeofday(&tv, NULL);
  165.     srandom(tv.tv_sec + tv.tv_usec / 100000);
  166. }
  167.  
  168. static void tetris_scores(int firstgame)
  169. {
  170. }
  171.  
  172. static void tetris_menu_draw(int level)
  173. {
  174.         clear_screen();
  175.         moveto(5,10);
  176.         puts("Tetris\n\n");
  177.            
  178.         moveto(8,10);
  179.         printf("Level = %d (press keys 1 - 9 to change)",level);
  180.         moveto(9,10);
  181.         printf("Preview is %s (press 'p' to change)", (showpreview?"on ":"off"));
  182.         moveto(12,10);
  183.         printf("Press 'h' to show hiscore table.");
  184.         moveto(13,10);
  185.         printf("Press 's' to start game.");
  186.         moveto(14,10);
  187.         printf("Press 'q' to quit game.");
  188.         moveto(20,10);
  189.         printf("In game controls:");
  190.         moveto(21,0);
  191.         puts(key_msg);
  192. }
  193.  
  194. static int tetris_menu(int *level)
  195. {
  196.     static int firstgame = 1;
  197.     int i;
  198. /*  if (showpreview == 0)
  199.         (void)printf("Your score:  %d point%s  x  level %d  =  %d\n",
  200.             score, score == 1 ? "" : "s", level, score * level);
  201.     else {
  202.         (void)printf("Your score:  %d point%s x level %d x preview penalty %0.3f = %d\n",
  203.             score, score == 1 ? "" : "s", level, (double)PRE_PENALTY,
  204.             (int)(score * level * PRE_PENALTY));
  205.         score = score * PRE_PENALTY;
  206.     }
  207.     savescore(level);
  208.  
  209.     showscores(level);
  210.    
  211.     printf("\nHit 's' to new game, 'q' to quit.\n");
  212. */
  213.     tetris_menu_draw(*level);
  214.     while (1) {
  215.    
  216.         i = getchar();
  217.        
  218.         switch(i) {
  219.             case 'p':
  220.                 showpreview = !showpreview;
  221.                 moveto(9,21);
  222.                 if (showpreview)
  223.                     printf("on ");
  224.                 else
  225.                     printf("off");
  226.                    
  227.                 break;
  228.             case 'h':
  229.                 showscores(firstgame);
  230.                 tetris_menu_draw(*level);
  231.                 break;
  232.             case 's':
  233.                 firstgame = 0;
  234.                 return 1;
  235.             case 'q':
  236.                 return 0;
  237.             case '1':
  238.             case '2':
  239.             case '3':
  240.             case '4':
  241.             case '5':
  242.             case '6':      
  243.             case '7':
  244.             case '8':
  245.             case '9':
  246.                 *level = i - '0';
  247.                 moveto(8,18);
  248.                 printf("%d", *level);
  249.                 break;
  250.         }
  251.     }
  252.    
  253. }
  254.  
  255. int
  256. main(int argc, char *argv[])
  257. {
  258.     int pos, c;
  259.     char *keys;
  260.     int level = 2;
  261.     char key_write[6][10];
  262.     const char *errstr;
  263.     int ch, i, j;
  264.  
  265.     keys = "jkl pq";
  266.  
  267. //  gid = getgid();
  268. //  egid = getegid();
  269. //  setegid(gid);
  270.  
  271.     classic = 0;
  272.     showpreview = 1;
  273.  
  274. /*  while ((ch = getopt(argc, argv, "ck:l:ps")) != -1) */
  275. /*      switch(ch) { */
  276. /*      case 'c': */
  277. /*          /\* */
  278. /*           * this means: */
  279. /*           *  - rotate the other way; */
  280. /*           *  - no reverse video. */
  281. /*           *\/ */
  282. /*          classic = 1; */
  283. /*          break; */
  284. /*      case 'k': */
  285. /*          if (strlen(keys = optarg) != 6) */
  286. /*              usage(); */
  287. /*          break; */
  288. /*      case 'l': */
  289. /*          level = (int)strtonum(optarg, MINLEVEL, MAXLEVEL, */
  290. /*              &errstr); */
  291. /*          if (errstr) */
  292. /*              errx(1, "level must be from %d to %d", */
  293. /*                  MINLEVEL, MAXLEVEL); */
  294. /*          break; */
  295. /*      case 'p': */
  296. /*          showpreview = 1; */
  297. /*          break; */
  298. /*      case 's': */
  299. /*          showscores(0); */
  300. /*          exit(0); */
  301. /*      default: */
  302. /*          usage(); */
  303. /*      } */
  304.  
  305. /*  argc -= optind; */
  306. /*  argv += optind; */
  307.  
  308. /*  if (argc) */
  309. /*      usage(); */
  310.  
  311.     fallrate = 1000000 / level;
  312.  
  313.     for (i = 0; i <= 5; i++) {
  314.         for (j = i+1; j <= 5; j++) {
  315.             if (keys[i] == keys[j])
  316.                 errx(1, "duplicate command keys specified.");
  317.         }
  318.         if (keys[i] == ' ')
  319.             strncpy(key_write[i], "<space>", sizeof key_write[i]);
  320.         else {
  321.             key_write[i][0] = keys[i];
  322.             key_write[i][1] = '\0';
  323.         }
  324.     }
  325.  
  326.     snprintf(key_msg, sizeof key_msg,
  327. "%s - left   %s - rotate   %s - right   %s - drop   %s - pause   %s - quit",
  328.         key_write[0], key_write[1], key_write[2], key_write[3],
  329.         key_write[4], key_write[5]);
  330.  
  331.     scr_init();
  332.     initscores();
  333.     while (tetris_menu(&level)) {
  334.  
  335.  
  336.         scr_clear();
  337.         setup_board();
  338.    
  339.         srandomdev();
  340.         scr_set();
  341.    
  342.         pos = A_FIRST*B_COLS + (B_COLS/2)-1;
  343.         nextshape = randshape();
  344.         curshape = randshape();
  345.    
  346.         scr_msg(key_msg, 1);
  347.    
  348.         for (;;) {
  349.             place(curshape, pos, 1);
  350.             scr_update();
  351.             place(curshape, pos, 0);
  352.             c = tgetchar();
  353.             if (c < 0) {
  354.                 /*
  355.                  * Timeout.  Move down if possible.
  356.                  */
  357.                 if (fits_in(curshape, pos + B_COLS)) {
  358.                     pos += B_COLS;
  359.                     continue;
  360.                 }
  361.    
  362.                 /*
  363.                  * Put up the current shape `permanently',
  364.                  * bump score, and elide any full rows.
  365.                  */
  366.                 place(curshape, pos, 1);
  367.                 score++;
  368.                 elide();
  369.    
  370.                 /*
  371.                  * Choose a new shape.  If it does not fit,
  372.                  * the game is over.
  373.                  */
  374.                 curshape = nextshape;
  375.                 nextshape = randshape();
  376.                 pos = A_FIRST*B_COLS + (B_COLS/2)-1;
  377.                 if (!fits_in(curshape, pos))
  378.                     break;
  379.                 continue;
  380.             }
  381.    
  382.             /*
  383.              * Handle command keys.
  384.              */
  385.             if (c == keys[5]) {
  386.                 /* quit */
  387.                 break;
  388.             }
  389.             if (c == keys[4]) {
  390.                 static char msg[] =
  391.                     "paused - press RETURN to continue";
  392.    
  393.                 place(curshape, pos, 1);
  394.                 do {
  395.                     scr_update();
  396.                     scr_msg(key_msg, 0);
  397.                     scr_msg(msg, 1);
  398.     //              (void) fflush(stdout);
  399.                 } while (rwait((struct timeval *)NULL) == -1);
  400.                 scr_msg(msg, 0);
  401.                 scr_msg(key_msg, 1);
  402.                 place(curshape, pos, 0);
  403.                 continue;
  404.             }
  405.             if (c == keys[0]) {
  406.                 /* move left */
  407.                 if (fits_in(curshape, pos - 1))
  408.                     pos--;
  409.                 continue;
  410.             }
  411.             if (c == keys[1]) {
  412.                 /* turn */
  413.                 const struct shape *new = &shapes[
  414.                     classic? curshape->rotc : curshape->rot];
  415.    
  416.                 if (fits_in(new, pos))
  417.                     curshape = new;
  418.                 continue;
  419.             }
  420.             if (c == keys[2]) {
  421.                 /* move right */
  422.                 if (fits_in(curshape, pos + 1))
  423.                     pos++;
  424.                 continue;
  425.             }
  426.             if (c == keys[3]) {
  427.                 /* move to bottom */
  428.                 while (fits_in(curshape, pos + B_COLS)) {
  429.                     pos += B_COLS;
  430.                     score++;
  431.                 }
  432.                 continue;
  433.             }
  434.             if (c == '\f') {
  435.                 scr_clear();
  436.                 scr_msg(key_msg, 1);
  437.             }
  438.         }
  439.        
  440.         scr_clear();
  441.         insertscore(score, level);
  442.     }
  443.    
  444.     scr_clear();
  445.     printf("\n\n\n\t\tGame over.\n");
  446. /* 
  447.     while ((i = getchar()) != '\n')
  448.         if (i == EOF)
  449.             break
  450. */
  451.     scr_end();
  452.     exit(0);
  453. }
  454.  
  455. /* void */
  456. /* onintr(int signo) */
  457. /* { */
  458. /*  scr_clear();        /\* XXX signal race *\/ */
  459. /*  scr_end();      /\* XXX signal race *\/ */
  460. /*  _exit(0); */
  461. /* } */
  462.  
  463. void
  464. usage(void)
  465. {
  466.     (void)fprintf(stderr, "usage: tetris [-ps] [-k keys] [-l level]\n");
  467.     exit(1);
  468. }
  469.  
  470. /** @}
  471.  */
  472.  
  473.