home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume15 / gtetris3 / part01 / playing.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  9KB  |  414 lines

  1. /*
  2. # GENERIC X-WINDOW-BASED TETRIS
  3. #
  4. #    playing.c
  5. #
  6. ###
  7. #
  8. #  Copyright (C) 1992, 1993     Qiang Alex Zhao, azhao@cs.arizona.edu
  9. #        Computer Science Dept, University of Arizona
  10. #
  11. #            All Rights Reserved
  12. #
  13. #  Permission to use, copy, modify, and distribute this software and
  14. #  its documentation for any purpose and without fee is hereby granted,
  15. #  provided that the above copyright notice appear in all copies and
  16. #  that both that copyright notice and this permission notice appear in
  17. #  supporting documentation, and that the name of the author not be
  18. #  used in advertising or publicity pertaining to distribution of the
  19. #  software without specific, written prior permission.
  20. #
  21. #  This program is distributed in the hope that it will be "playable",
  22. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. #
  25. */
  26.  
  27. #include    "tetris.h"
  28.  
  29. static Bool     paused = False;
  30.  
  31. static int      speeds[NUM_LEVELS] = {
  32.     100, 92, 84, 76, 68, 60, 53, 46, 39, 32, 26, 20, 15, 10, 6, 3, 1, 0};
  33. static int      thresh[NUM_LEVELS] = {
  34.     10, 20, 30, 40, 50, 60, 70, 80, 90,
  35.     100, 110, 120, 130, 140, 150, 160, 170, 180};
  36.  
  37. static struct timeval nextFall, now, delay;
  38. static struct timezone tzone = {0, 0};
  39.  
  40. /* ------------------------------------------------------------------ */
  41.  
  42. void
  43. playing()
  44. {
  45.     Bool            resetTime = True;
  46.  
  47.     score = prefilled * level * 10;
  48.     while (True) {
  49.     if (resetTime) {
  50.         (void) gettimeofday(&nextFall, &tzone);
  51.         nextFall.tv_usec += 10000 * speeds[level];
  52.         realTime(&nextFall);
  53.     } else {
  54.         int             writefd = 0, exceptfd = 0;
  55.         int             readfd = 1 << ConnectionNumber(display);
  56.  
  57.         (void) gettimeofday(&now, &tzone);
  58.         delay.tv_sec = nextFall.tv_sec - now.tv_sec;
  59.         delay.tv_usec = nextFall.tv_usec - now.tv_usec;
  60.         realTime(&delay);
  61.         if (delay.tv_sec >= 0) {    /* sleep */
  62.         (void) select(sizeof(int) * 8, (fd_set *) &readfd,
  63.                (fd_set *) & writefd, (fd_set *) & exceptfd, &delay);
  64.         }
  65.     }
  66.     (void) gettimeofday(&now, &tzone);
  67.     if ((now.tv_sec > nextFall.tv_sec) ||
  68.         ((now.tv_sec == nextFall.tv_sec) &&
  69.         (now.tv_usec > nextFall.tv_usec))) {
  70.         (void) evGotNewThing(True);
  71.         resetTime = True;
  72.     } else {
  73.         resetTime = evGotNewThing(False);
  74.     }
  75.     }
  76.     /* never come to here */
  77. }
  78.  
  79. /* ------------------------------------------------------------------ */
  80.  
  81. Bool
  82. evGotNewThing(falldown)
  83.     Bool            falldown;
  84. {
  85.     XEvent          ev;
  86.     Bool            gotNew = False;
  87.     char            buf[4];
  88.  
  89.     if (!paused && falldown)
  90.     gotNew = moveOne(FALL) || gotNew;
  91.  
  92.     while (XPending(display)) {
  93.     XNextEvent(display, &ev);
  94.     switch (ev.type) {
  95.     case KeyPress:
  96.         if (!XLookupString(&ev.xkey, buf, 4, NULL, NULL))
  97.         break;
  98.  
  99.         switch (buf[0]) {
  100.         case 'j':
  101.         case 's':
  102.         if (!paused)
  103.             gotNew = moveOne(LEFT) || gotNew;
  104.         break;
  105.  
  106.         case 'k':
  107.         case 'd':
  108.         if (!paused)
  109.             gotNew = moveOne(ROTATE) || gotNew;
  110.         break;
  111.  
  112.         case 'l':
  113.         case 'f':
  114.         if (!paused)
  115.             gotNew = moveOne(RIGHT) || gotNew;
  116.         break;
  117.  
  118.         case ' ':
  119.         case '\n':
  120.         if (!paused)
  121.             gotNew = moveOne(DROP) || gotNew;
  122.         break;
  123.  
  124.         case 'q':
  125.         case 'Q':
  126.         gameOver();
  127.         break;
  128.  
  129.         case '+':
  130.         case '=':
  131.         if (!paused)
  132.             if (level < NUM_LEVELS - 1) {
  133.             level++;
  134.             drawStatus();
  135.             }
  136.         break;
  137.  
  138.         case '-':
  139.         case '_':
  140.         if (!paused)
  141.             if (level > 0) {
  142.             level--;
  143.             drawStatus();
  144.             }
  145.         break;
  146.  
  147.         case 'b':
  148.         case 'B':
  149.         beep = !beep;
  150.         if (beep)
  151.             XBell(display, BVOLUME);
  152.         break;
  153.  
  154.         case 'p':
  155.         case 'P':
  156.         if (beep)
  157.             XBell(display, BVOLUME);
  158.         paused = !paused;
  159.         if (paused) {
  160.             /* "... Hi boss, I'm working hard as usual ..." */
  161.             banner(MSG_PAUSED);
  162.             (void) XIconifyWindow(display, mainWin, screen_num);
  163.         } else {
  164.             clearNext();
  165.             if (showNext)
  166.             drawNext();
  167.         }
  168.         XSync(display, False);
  169.         break;
  170.  
  171.         case '\014':
  172.         XClearWindow(display, mainWin);
  173.         XClearWindow(display, blockWin);
  174.         redrawAll();
  175.         if (paused)
  176.             banner(MSG_PAUSED);
  177.         XSync(display, False);
  178.         break;
  179.  
  180.         case 'n':
  181.         case 'N':
  182.         if (!paused) {
  183.             showNext = !showNext;
  184.             if (showNext) {
  185.             drawNext();
  186.             } else {
  187.             clearNext();
  188.             }
  189.             XSync(display, False);
  190.         }
  191.         break;
  192.  
  193.         default:
  194.         XBell(display, 0);
  195.         XSync(display, False);
  196.         break;
  197.         }
  198.  
  199.         break;
  200.  
  201.     case UnmapNotify:
  202.         paused = True;
  203.         break;
  204.  
  205.     case FocusOut:
  206.         paused = True;
  207.         banner(MSG_PAUSED);
  208.         break;
  209.  
  210.     case Expose:
  211.         if (ev.xexpose.count == 0) {
  212.         redrawAll();
  213.         if (paused)
  214.             banner(MSG_PAUSED);
  215.         }
  216.         break;
  217.  
  218.     case ClientMessage:
  219.         if ((Atom) ev.xclient.data.l[0] == delw)
  220.         gameOver();
  221.         break;
  222.  
  223.     case DestroyNotify:
  224.         exit(0);
  225.         break;
  226.     }
  227.     }
  228.  
  229.     XSync(display, False);
  230.     return gotNew;
  231. }
  232.  
  233. /* ------------------------------------------------------------------ */
  234.  
  235. void
  236. redrawAll()
  237. {
  238.     drawTitle();
  239.     drawStatus();
  240.     drawField();
  241.     drawThing();
  242.     if (showNext)
  243.     drawNext();
  244. }
  245.  
  246. /* ------------------------------------------------------------------ */
  247.  
  248. Bool
  249. moveOne(move)
  250.     move_t          move;
  251. {
  252.     XEvent          ev;
  253.     int             lines;
  254.  
  255.     if ((move == DROP) || ((move == FALL) && atBottom())) {
  256.     tryMove(move);
  257.     putBox();
  258.     lines = checkLines();
  259.     score += prefilled * prefilled + lines + 1;
  260.     score += (showNext ? 3 : 5) * level * level * lines * lines;
  261.     rows += lines;
  262.     if (rows > thresh[level])
  263.         level ++;
  264.     drawStatus();
  265.     newThing();
  266.     if (showNext) {
  267.         clearNext();
  268.         drawNext();
  269.     }
  270.     XSync(display, False);
  271.     while (XPending(display))
  272.         XNextEvent(display, &ev);
  273.     if (overlapping())
  274.         gameOver();
  275.     drawThing();
  276.     return True;
  277.     } else {
  278.     tryMove(move);
  279.     if (rows > thresh[level]) {
  280.         level ++;
  281.         drawStatus();
  282.     }
  283.     return False;
  284.     }
  285. }
  286.  
  287. /* ------------------------------------------------------------------ */
  288.  
  289. static void
  290. addScore()
  291. {
  292.     time_t          tloc;
  293.     char            buff[2][SCORESIZE];
  294.     char            lockfile[FILENAMELEN];
  295.     int             fd, lfd;
  296.     int             tmp, ptmp, s1;
  297.     int             mycount = 0;
  298.     Bool            saved = False, trickle = False;
  299.  
  300.     time(&tloc);
  301.     (void) strcpy(myscore.mydate, asctime(localtime(&tloc)));
  302.     (void) sprintf(myscore.score, "%9d", score);
  303.     (void) sprintf(myscore.level, "%3d", level);
  304.     (void) sprintf(myscore.rows, "%4d", rows);
  305.  
  306.     (void) fprintf(stderr, "\n- %s", myscore.mydate);
  307.     (void) fprintf(stderr, "- Your final score is %d,", score);
  308.     (void) fprintf(stderr, " at level %d with %d rows.\n\n", level, rows);
  309.  
  310.     if ((fd = open(SCOREFILE, O_CREAT | O_RDWR, 0644)) < 0) {
  311.     (void) fprintf(stderr, "Cannot write the score-file!\n");
  312.     return;
  313.     }
  314.  
  315.     /* lock */
  316.     (void) strcpy(lockfile, SCOREFILE);
  317.     (void) strcat(lockfile, ".lock");
  318.     while (((lfd = open(lockfile, O_CREAT | O_EXCL, 0644)) < 0) &&
  319.         errno == EEXIST)
  320.     sleep(1);
  321.  
  322.     if (lfd < 0) {
  323.     (void) perror("Error in creating the score-file lock-file");
  324.     (void) fprintf(stderr, "Score not recorded - sorry.\n");
  325.     return;
  326.     }
  327.  
  328.     tmp = 0;
  329.     ptmp = 1;
  330.     bcopy((char *) &myscore, buff[1], SCORESIZE);
  331.  
  332.     while (read(fd, buff[tmp], SCORESIZE) == SCORESIZE) {
  333.     sscanf(((score_t *)buff[tmp])->score, " %d", &s1);
  334.     if (!saved && (s1 <= score)) {
  335.         trickle = True;
  336.         saved = True;
  337.         mycount++;
  338.     }
  339.     if (!strncmp(myscore.myname, ((score_t *) buff[tmp])->myname,
  340.         NAMELEN)) {
  341.         mycount++;
  342.     }
  343.     /* Then check if we should trickle the score */
  344.     if (trickle) {
  345.         lseek(fd, (off_t) -SCORESIZE, SEEK_CUR);
  346.         write(fd, buff[ptmp], SCORESIZE);
  347.         ptmp = tmp;
  348.         tmp = (tmp + 1) % 2;
  349.     }
  350.     /*
  351.      * As we trickle, we add up records owned by me. Once we hit max,
  352.      * we throw it away, and stop trickling.
  353.      */
  354.     if ((mycount > MAXSCORES) || ((mycount == MAXSCORES) && !trickle)) {
  355.         trickle = False;
  356.         break;
  357.     }
  358.     }    /* while */
  359.  
  360.     if (trickle) {
  361.     write(fd, buff[ptmp], SCORESIZE);
  362.     }
  363.     if (!saved && (mycount < MAXSCORES)) {
  364.     write(fd, (char *) &myscore, SCORESIZE);
  365.     }
  366.  
  367.     /* unlock */
  368.     close(lfd);
  369.     (void) unlink(lockfile);
  370.     close(fd);
  371. }
  372.  
  373. /* ------------------------------------------------------------------ */
  374.  
  375. void
  376. gameOver()
  377. {
  378.     banner(MSG_END);
  379.     XFlush(display);
  380.     addScore();
  381.     showScores(SHOWSCORES);
  382.     XCloseDisplay(display);
  383.     exit(0);
  384. }
  385.  
  386. /* ------------------------------------------------------------------ */
  387.  
  388. void
  389. showScores(num)
  390.     int             num;
  391. {
  392.     int             fd, i = 0;
  393.     score_t         curs;
  394.  
  395.     if ((fd = open(SCOREFILE, O_RDONLY, 0644)) < 0)
  396.     return;
  397.  
  398.     (void) fprintf(stderr, "            GENERIC TETRIS  HALL OF FAME\n\n");
  399.     (void) fprintf(stderr,
  400.     "   # USER            SCORE   L    R  HOST         DATE\n");
  401.  
  402.     while (read(fd, (char *) &curs, SCORESIZE) == SCORESIZE) {
  403.     i++;
  404.     if ((num == 0) || (i <= num))
  405.         (void) fprintf(stderr, "%4d %-12s%9s %3s %4s  %-12s %-s",
  406.         i, curs.myname, curs.score, curs.level, curs.rows,
  407.         curs.myhost, curs.mydate);
  408.     }
  409.     close(fd);
  410.     (void) fprintf(stderr, "There are %d scores to date.\n", i);
  411. }
  412.  
  413. /* ------------------------------------------------------------------ */
  414.