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

  1. /*
  2. # GENERIC X-WINDOW-BASED TETRIS
  3. #
  4. #    utils.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. #include    "bitmaps/ticon.xbm"
  30. #include    "bitmaps/rot00.xbm"
  31. #include    "bitmaps/rot01.xbm"
  32. #include    "bitmaps/rot02.xbm"
  33. #include    "bitmaps/rot03.xbm"
  34. #include    "bitmaps/rot04.xbm"
  35. #include    "bitmaps/rot05.xbm"
  36. #include    "bitmaps/rot06.xbm"
  37. #include    "bitmaps/rot07.xbm"
  38. #include    "bitmaps/rot08.xbm"
  39. #include    "bitmaps/rot09.xbm"
  40. #include    "bitmaps/rot10.xbm"
  41. #include    "bitmaps/rot11.xbm"
  42. #include    "bitmaps/rot12.xbm"
  43. #include    "bitmaps/rot13.xbm"
  44. #include    "bitmaps/rot14.xbm"
  45.  
  46. Atom            delw;
  47.  
  48. static GC       revGC, bigGC, tinyGC, xorGC;
  49. static GC       thingGCs[NUM_THINGS];
  50.  
  51. static char    *winName = "GENERIC TETRIS";
  52. static char    *iconName = "TETRIS";
  53.  
  54. static int      titleLen, titleWidth, authorLen, authorWidth;
  55. static int      titleX, titleY, authorX, authorY;
  56. static int      sX;
  57. static int      sLevelY, sRowsY, sScoreY;
  58.  
  59. static int      topRWidth, topWidth, topHeight, topMidX, topMidY;
  60. static int      frameX, frameY, frameW, frameH;
  61.  
  62. static char    *bitmap_data[NUM_BITMAPS] = {
  63.     rot00_bits, rot01_bits, rot02_bits, rot03_bits, rot04_bits, rot05_bits,
  64.     rot06_bits, rot07_bits, rot08_bits, rot09_bits, rot10_bits, rot11_bits,
  65.     rot12_bits, rot13_bits, rot14_bits
  66. };
  67.  
  68. static thing_t  possible[][4] = {
  69.     {
  70.     {{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 0},
  71.     {{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 1},
  72.     {{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 2},
  73.     {{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 3}
  74.     },
  75.  
  76.     {
  77.     {{{0, 2, 0, 0}, {0, 10, 0, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 0},
  78.     {{{2, 0, 0, 0}, {12, 5, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 1},
  79.     {{{6, 1, 0, 0}, {10, 0, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 2},
  80.     {{{4, 5, 3, 0}, {0, 0, 8, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 3}
  81.     },
  82.  
  83.     {
  84.     {{{2, 0, 0, 0}, {10, 0, 0, 0}, {12, 1, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 0},
  85.     {{{6, 5, 1, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 1},
  86.     {{{4, 3, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 2},
  87.     {{{0, 0, 2, 0}, {4, 5, 9, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 3}
  88.     },
  89.  
  90.     {
  91.     {{{0, 2, 0, 0}, {4, 11, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 0},
  92.     {{{0, 2, 0, 0}, {4, 13, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 1},
  93.     {{{2, 0, 0, 0}, {14, 1, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 2},
  94.     {{{4, 7, 1, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 3}
  95.     },
  96.  
  97.     {
  98.     {{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 0},
  99.     {{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 1},
  100.     {{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 2},
  101.     {{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 3}
  102.     },
  103.  
  104.     {
  105.     {{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 0},
  106.     {{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 1},
  107.     {{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 2},
  108.     {{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 3}
  109.     },
  110.  
  111.     {
  112.     {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 0},
  113.     {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 1},
  114.     {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 2},
  115.     {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 3}
  116.     }
  117. };
  118.  
  119. static char    *thingFGs[NUM_THINGS] = {
  120.     "Magenta", "ForestGreen", "Blue", "Red", "DarkTurquoise", "Black", "Brown"
  121. };
  122.  
  123. static Pixmap   pms[NUM_BITMAPS];
  124.  
  125. static thing_t  curThing, nextThing;
  126. static struct {
  127.     int             pm_num, cid;
  128. }               field[ROWS][COLS];
  129.  
  130. /* ------------------------------------------------------------------ */
  131.  
  132. static int
  133. nrand(n)
  134.     int             n;
  135. {
  136.     return (int) (LRAND() % n);
  137. }
  138.  
  139. /* ------------------------------------------------------------------ */
  140.  
  141. unsigned long
  142. getColor(name)
  143.     char            name[];
  144. {
  145.     XColor          tmp;
  146.  
  147.     if (!useColor) {
  148.     return BlackPixel(display, screen_num);
  149.     }
  150.     if (XParseColor(display, colormap, name, &tmp) == 0) {
  151.     (void) fprintf(stderr, "Tetris: invalid color '%s'.\n", name);
  152.     return BlackPixel(display, screen_num);
  153.     }
  154.     if (XAllocColor(display, colormap, &tmp) == 0) {
  155.     (void) fprintf(stderr, "Tetris: can't allocate color '%s'.\n", name);
  156.     return BlackPixel(display, screen_num);
  157.     }
  158.     return tmp.pixel;
  159. }
  160.  
  161. /* ------------------------------------------------------------------ */
  162.  
  163. void
  164. inits(argc, argv)
  165.     int             argc;
  166.     char           *argv[];
  167. {
  168.     XSetWindowAttributes att;
  169.     unsigned int    attvm;
  170.     XTextProperty   wName, iName;
  171.     XClassHint      classhints;
  172.     XEvent          ev;
  173.     XGCValues       gcv;
  174.     unsigned long   gcvm;
  175.     int             i, j;
  176.  
  177.     SRAND(time(NULL));
  178.     for (i = 0; i < COLS; i++)
  179.     for (j = 0; j < ROWS; j++)
  180.         if ((j >= ROWS - prefilled) && (nrand(2) == 0)) {
  181.         field[j][i].pm_num = 0;
  182.         field[j][i].cid = nrand(NUM_THINGS);
  183.         } else {
  184.         field[j][i].pm_num = -1;
  185.         field[j][i].cid = 0;
  186.         }
  187.  
  188.     titleLen = strlen(MSG_TITLE);
  189.     titleWidth = XTextWidth(bigFont, MSG_TITLE, titleLen);
  190.     authorLen = strlen(MSG_AUTHOR);
  191.     authorWidth = XTextWidth(tinyFont, MSG_AUTHOR, authorLen);
  192.  
  193.     frameW = BOXSIZE * COLS;
  194.     frameH = BOXSIZE * ROWS;
  195.     topRWidth = BOXSIZE * THINGSIZE + OFFSET * 2;
  196.     topHeight = frameH + OFFSET * 2 + 4;
  197.     if (titleWidth > topRWidth)
  198.     topRWidth = titleWidth;
  199.     if (authorWidth > topRWidth)
  200.     topRWidth = authorWidth;
  201.     topMidX = frameW + OFFSET * 2 + 4;
  202.     topMidY = topHeight / 2 + bigFont->ascent;
  203.     topWidth = topMidX + topRWidth;
  204.     frameX = frameY = OFFSET + 2;
  205.  
  206.     titleX = (topRWidth - titleWidth) / 2 + topMidX;
  207.     titleY = OFFSET + 2 + bigFont->ascent;
  208.     authorX = (topRWidth - authorWidth) / 2 + topMidX;
  209.     authorY = OFFSET + 2 + bigFont->ascent + bigFont->descent + tinyFont->ascent;
  210.  
  211.     sX = topMidX + OFFSET;
  212.     sScoreY = topHeight - OFFSET - 2 - tinyFont->descent;
  213.     sRowsY = sScoreY - tinyFont->descent - tinyFont->ascent - 2;
  214.     sLevelY = sRowsY - tinyFont->descent - tinyFont->ascent - 2;
  215.  
  216.     sizehints.width = (sizehints.min_width =
  217.     (sizehints.max_width = topWidth));
  218.     sizehints.height = (sizehints.min_height =
  219.     (sizehints.max_height = topHeight));
  220.  
  221.     theCursor = XCreateFontCursor(display, XC_exchange);
  222.  
  223.     /* arrow keys */
  224.     XRebindKeysym(display, XK_R10, NULL, 0,
  225.     (unsigned char *) "j", sizeof(unsigned char));
  226.     XRebindKeysym(display, XK_Left, NULL, 0,
  227.     (unsigned char *) "j", sizeof(unsigned char));
  228.     XRebindKeysym(display, XK_R11, NULL, 0,
  229.     (unsigned char *) "k", sizeof(unsigned char));
  230.     XRebindKeysym(display, XK_R12, NULL, 0,
  231.     (unsigned char *) "l", sizeof(unsigned char));
  232.     XRebindKeysym(display, XK_Right, NULL, 0,
  233.     (unsigned char *) "l", sizeof(unsigned char));
  234.  
  235.     /* create windows */
  236.     attvm = CWBackPixel | CWEventMask | CWDontPropagate | CWCursor;
  237.     att.background_pixel = bg;
  238.     att.event_mask = ExposureMask | KeyPressMask |
  239.     StructureNotifyMask | FocusChangeMask;
  240.     att.do_not_propagate_mask = KeyReleaseMask |
  241.     ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
  242.     ButtonMotionMask | Button1MotionMask | Button2MotionMask |
  243.     Button3MotionMask | Button4MotionMask | Button5MotionMask;
  244.     att.cursor = theCursor;
  245.  
  246.     mainWin = XCreateWindow(display, DefaultRootWindow(display),
  247.     sizehints.x, sizehints.y, topWidth, topHeight, 0,
  248.     CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
  249.  
  250.     attvm = CWBackPixel | CWBorderPixel | CWEventMask;
  251.     att.border_pixel = fg;
  252.     att.event_mask = ExposureMask;
  253.  
  254.     blockWin = XCreateWindow(display, mainWin,
  255.     frameX-2, frameY-2, frameW, frameH, 2,
  256.     CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
  257.  
  258.     /* WM hints */
  259.     XStringListToTextProperty(&winName, 1, &wName);
  260.     XStringListToTextProperty(&iconName, 1, &iName);
  261.  
  262.     wmhints.icon_pixmap = XCreateBitmapFromData(display,
  263.     mainWin, ticon_bits, ticon_width, ticon_height);
  264.     classhints.res_name = "tetris";
  265.     classhints.res_class = "Tetris";
  266.  
  267.     XSetWMProperties(display, mainWin, &wName, &iName,
  268.     argv, argc, &sizehints, &wmhints, &classhints);
  269.  
  270.     delw = XInternAtom(display, "WM_DELETE_WINDOW", False);
  271.     XSetWMProtocols(display, mainWin, &delw, 1);
  272.  
  273.     /* GC's */
  274.  
  275.     gcvm = GCForeground | GCBackground | GCFunction |
  276.     GCFont | GCGraphicsExposures;
  277.  
  278.     gcv.function = GXcopy;
  279.     gcv.foreground = fg;
  280.     gcv.background = bg;
  281.     gcv.font = bigFont->fid;
  282.     gcv.graphics_exposures = False;
  283.     bigGC = XCreateGC(display, mainWin, gcvm, &gcv);
  284.  
  285.     gcv.font = tinyFont->fid;
  286.     tinyGC = XCreateGC(display, mainWin, gcvm, &gcv);
  287.  
  288.     gcv.foreground = bg;
  289.     gcv.background = fg;
  290.     revGC = XCreateGC(display, mainWin, gcvm, &gcv);
  291.  
  292.     gcv.background = bg;
  293.     for (i = 0; i < NUM_THINGS; i++) {
  294.     gcv.foreground = getColor(thingFGs[i]);
  295.     if (gcv.foreground == bg)
  296.         gcv.foreground = fg;
  297.     thingGCs[i] = XCreateGC(display, blockWin, gcvm, &gcv);
  298.     }
  299.  
  300.     gcv.foreground = fg;
  301.     gcv.function = GXxor;
  302.     xorGC = XCreateGC(display, blockWin, gcvm, &gcv);
  303.  
  304.     /* pixmaps */
  305.  
  306.     for (i = 0; i < NUM_BITMAPS; i++) {
  307.     pms[i] = (Pixmap) XCreateBitmapFromData(display, blockWin,
  308.         bitmap_data[i], BOXSIZE, BOXSIZE);
  309.     }
  310.  
  311.     /* new things */
  312.     newThing();
  313.     newThing();
  314.  
  315.     /* the last thing is to wait for mapped */
  316.     XMapWindow(display, blockWin);
  317.     XMapRaised(display, mainWin);
  318.     XNextEvent(display, &ev);
  319.     sleep(1);
  320. }
  321.  
  322. /* ------------------------------------------------------------------ */
  323.  
  324. void
  325. newThing()
  326. {
  327.     curThing = nextThing;
  328.     nextThing = possible[nrand(NUM_THINGS)][nrand(4)];
  329.     nextThing.xpos = nrand(COLS - nextThing.size + 1);
  330. }
  331.  
  332. /* ------------------------------------------------------------------ */
  333.  
  334. void
  335. drawTitle()
  336. {
  337.     XDrawString(display, mainWin, bigGC,
  338.     titleX, titleY, MSG_TITLE, titleLen);
  339.     XDrawString(display, mainWin, tinyGC,
  340.     authorX, authorY, MSG_AUTHOR, authorLen);
  341. }
  342.  
  343. /* ------------------------------------------------------------------ */
  344.  
  345. void
  346. drawStatus()
  347. {
  348.     char            buf[30];
  349.  
  350.     (void) sprintf(buf, "Score: %d", score);
  351.     XDrawImageString(display, mainWin, tinyGC, sX, sScoreY, buf, strlen(buf));
  352.  
  353.     (void) sprintf(buf, "Level: %d    ", level);
  354.     XDrawImageString(display, mainWin, tinyGC, sX, sLevelY, buf, strlen(buf));
  355.  
  356.     (void) sprintf(buf, "Rows: %d", rows);
  357.     XDrawImageString(display, mainWin, tinyGC, sX, sRowsY, buf, strlen(buf));
  358. }
  359.  
  360. /* ------------------------------------------------------------------ */
  361.  
  362. static void
  363. drawBox(win, pmid, cid, x, y)
  364.     Window          win;
  365.     int             pmid, cid, x, y;
  366. {
  367.     XCopyPlane(display, pms[pmid], win, thingGCs[cid], 0, 0,
  368.     BOXSIZE, BOXSIZE, x, y, (unsigned long) 1);
  369. }
  370.  
  371. /* ------------------------------------------------------------------ */
  372.  
  373. static void
  374. clearBox(x, y)
  375.     int             x, y;
  376. {
  377.     XFillRectangle(display, blockWin, revGC, x, y, BOXSIZE, BOXSIZE);
  378. }
  379.  
  380. /* ------------------------------------------------------------------ */
  381.  
  382. void
  383. drawField()
  384. {
  385.     int             i, j;
  386.  
  387.     for (i = 0; i < COLS; i++)
  388.     for (j = 0; j < ROWS; j++)
  389.         if (field[j][i].pm_num >= 0)
  390.         drawBox(blockWin, field[j][i].pm_num, field[j][i].cid,
  391.             i * BOXSIZE, j * BOXSIZE);
  392. }
  393.  
  394. /* ------------------------------------------------------------------ */
  395.  
  396. void
  397. drawThing()
  398. {
  399.     int             i, j;
  400.  
  401.     for (i = 0; i < curThing.size; i++)
  402.     for (j = 0; j < curThing.size; j++)
  403.         if (curThing.map[j][i])
  404.         drawBox(blockWin, curThing.map[j][i], curThing.px,
  405.             (curThing.xpos + i) * BOXSIZE,
  406.             (curThing.ypos + j) * BOXSIZE);
  407. }
  408.  
  409. /* ------------------------------------------------------------------ */
  410.  
  411. void
  412. drawThingDiff(old)
  413.     thing_t        *old;
  414. {
  415.     int             i, j, ox, oy;
  416.  
  417.     for (i = 0; i < curThing.size; i++)
  418.     for (j = 0; j < curThing.size; j++)
  419.         if (curThing.map[j][i])
  420.         drawBox(blockWin, curThing.map[j][i], curThing.px,
  421.             (curThing.xpos + i) * BOXSIZE,
  422.             (curThing.ypos + j) * BOXSIZE);
  423.  
  424.     for (i = 0; i < curThing.size; i++)
  425.     for (j = 0; j < curThing.size; j++) {
  426.         ox = old->xpos + i - curThing.xpos;
  427.         oy = old->ypos + j - curThing.ypos;
  428.         if (old->map[j][i] && 
  429.             ((ox < 0) || (ox >= curThing.size) ||
  430.             (oy < 0) || (oy >= curThing.size) ||
  431.             !curThing.map[oy][ox]))
  432.         clearBox((old->xpos + i) * BOXSIZE, (old->ypos + j) * BOXSIZE);
  433.     }
  434. }
  435.  
  436. /* ------------------------------------------------------------------ */
  437.  
  438. void
  439. drawNext()
  440. {
  441.     int             x, y;
  442.     int             i, j;
  443.  
  444.     x = topMidX + (topRWidth - nextThing.size * BOXSIZE) / 2;
  445.     y = topMidY - nextThing.size * BOXSIZE / 2;
  446.     for (i = 0; i < nextThing.size; i++)
  447.     for (j = 0; j < nextThing.size; j++)
  448.         if (nextThing.map[j][i])
  449.         drawBox(mainWin, nextThing.map[j][i], nextThing.px,
  450.         x + i * BOXSIZE, y + j * BOXSIZE);
  451. }
  452.  
  453. /* ------------------------------------------------------------------ */
  454.  
  455. void
  456. clearNext()
  457. {
  458.     XFillRectangle(display, mainWin, revGC,
  459.     topMidX, topMidY - BOXSIZE * 2, topRWidth, BOXSIZE * 4);
  460. }
  461.  
  462. /* ------------------------------------------------------------------ */
  463.  
  464. void
  465. banner(msg)
  466.     char            msg[];
  467. {
  468.     int             mlen = strlen(msg);
  469.     int             w = XTextWidth(bigFont, msg, mlen);
  470.     int             x = (topRWidth - w)/2 + topMidX;
  471.  
  472.     XFillRectangle(display, mainWin, revGC,
  473.     x - 60, topMidY - bigFont->ascent - 5,
  474.     w + 120, bigFont->ascent + bigFont->descent + 10);
  475.     XDrawString(display, mainWin, bigGC, x, topMidY, msg, mlen);
  476. }
  477.  
  478. /* ------------------------------------------------------------------ */
  479.  
  480. void
  481. putBox()
  482. {
  483.     int             i, j;
  484.     int             x = curThing.xpos, y = curThing.ypos;
  485.  
  486.     for (i = 0; i < curThing.size; i++)
  487.     for (j = 0; j < curThing.size; j++)
  488.         if (curThing.map[j][i]) {
  489.         field[y + j][x + i].pm_num = curThing.map[j][i];
  490.         field[y + j][x + i].cid = curThing.px;
  491.         }
  492. }
  493.  
  494. /* ------------------------------------------------------------------ */
  495.  
  496. Bool
  497. overlapping()
  498. {
  499.     int             i, j;
  500.     int             x = curThing.xpos, y = curThing.ypos;
  501.  
  502.     for (i = 0; i < curThing.size; i++)
  503.     for (j = 0; j < curThing.size; j++)
  504.         if (curThing.map[j][i]) {
  505.         if ((y + j >= ROWS) || (x + i < 0) || (x + i >= COLS))
  506.             return True;
  507.         if (field[y + j][x + i].pm_num >= 0)
  508.             return True;
  509.         }
  510.  
  511.     return False;
  512. }
  513.  
  514. /* ------------------------------------------------------------------ */
  515.  
  516. Bool
  517. atBottom()
  518. {
  519.     int             i, j;
  520.     int             x = curThing.xpos, y = curThing.ypos;
  521.  
  522.     for (i = 0; i < curThing.size; i++)
  523.     for (j = 0; j < curThing.size; j++)
  524.         if (curThing.map[j][i]) {
  525.         if ((y + j >= ROWS - 1) || (x + i < 0) || (x + i >= COLS))
  526.             return True;
  527.         if (field[y + j + 1][x + i].pm_num >= 0)
  528.             return True;
  529.         }
  530.  
  531.     return False;
  532. }
  533.  
  534. /* ------------------------------------------------------------------ */
  535.  
  536. void
  537. tryMove(move)
  538.     move_t          move;
  539. {
  540.     thing_t         old;
  541.  
  542.     old = curThing;
  543.  
  544.     switch (move) {
  545.     case FALL:
  546.     curThing.ypos ++;
  547.     break;
  548.  
  549.     case DROP:
  550.     do {
  551.         curThing.ypos ++;
  552.         score += level + prefilled;
  553.     } while (!overlapping());
  554.     curThing.ypos --;
  555.     break;
  556.  
  557.     case ROTATE:
  558.     curThing = possible[old.px][(old.py + 3) % 4];
  559.     curThing.xpos = old.xpos;
  560.     curThing.ypos = old.ypos;
  561.     break;
  562.  
  563.     case LEFT:
  564.     curThing.xpos --;
  565.     break;
  566.  
  567.     case RIGHT:
  568.     curThing.xpos ++;
  569.     break;
  570.     }
  571.  
  572.     if (!overlapping())
  573.     drawThingDiff(&old);
  574.     else
  575.     curThing = old;
  576. }
  577.  
  578. /* ------------------------------------------------------------------ */
  579.  
  580. int
  581. checkLines()
  582. {
  583.     int             lSet[ROWS], nset = 0;
  584.     int             i, j, y;
  585.  
  586.     for (j = 0; j < ROWS; j++) {
  587.     lSet[j] = 0;
  588.     for (i = 0; i < COLS; i++)
  589.         if (field[j][i].pm_num >= 0)
  590.         lSet[j] ++;
  591.     if (lSet[j] == COLS)
  592.         nset ++;
  593.     }
  594.  
  595.     if (nset) {
  596.     for (i = 0; i < ((NUM_FLASHES / nset) % 2) * 2; i ++) {
  597.         for (j = 0; j < ROWS; j++) {
  598.         if (lSet[j] == COLS)
  599.             XFillRectangle(display, blockWin, xorGC,
  600.             0, j * BOXSIZE, frameW, BOXSIZE);
  601.         }
  602.         XFlush(display);
  603.     }
  604.  
  605.     for (j = ROWS-1; j >= 0; j--) {
  606.         if (lSet[j] == COLS) {
  607.         for (y = j; y > 0; y--)
  608.             for (i = 0; i < COLS; i++)
  609.             field[y][i] = field[y-1][i];
  610.         for (i = 0; i < COLS; i++)
  611.             field[0][i].pm_num = -1;
  612.  
  613.         XCopyArea(display, blockWin, blockWin, tinyGC,
  614.             0, 0, frameW, j * BOXSIZE, 0, BOXSIZE);
  615.         
  616.         XFillRectangle(display, blockWin, revGC,
  617.             0, 0, frameW, BOXSIZE);
  618.  
  619.         for (i = j; i > 0; i--)
  620.             lSet[i] = lSet[i-1];
  621.         lSet[0] = 0;
  622.         
  623.         j++;
  624.         XFlush(display);
  625.         }
  626.     }
  627.  
  628.     if (beep) XBell(display, BVOLUME);
  629.     XSync(display, False);
  630.     }
  631.  
  632.     return nset;
  633. }
  634.  
  635. /* ------------------------------------------------------------------ */
  636.  
  637. void
  638. realTime(tv)
  639.     struct timeval *tv;
  640. {
  641.     while (tv->tv_usec < 0) {
  642.     tv->tv_sec --;
  643.     tv->tv_usec += MILLION;
  644.     }
  645.     while (tv->tv_usec >= MILLION) {
  646.     tv->tv_sec ++;
  647.     tv->tv_usec -= MILLION;
  648.     }
  649. }
  650.  
  651. /* ------------------------------------------------------------------ */
  652.