home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume15 / gtetris2 / part01 / utils.c < prev   
C/C++ Source or Header  |  1993-01-27  |  20KB  |  851 lines

  1. /*
  2. # GENERIC X-WINDOW-BASED TETRIS
  3. #
  4. #    tetris.c
  5. #
  6. ###
  7. #
  8. #  Copyright (C) 1992    Qiang Alex Zhao
  9. #            Computer Science Dept, University of Arizona
  10. #            azhao@cs.arizona.edu
  11. #
  12. #            All Rights Reserved
  13. #
  14. #  Permission to use, copy, modify, and distribute this software and
  15. #  its documentation for any purpose and without fee is hereby granted,
  16. #  provided that the above copyright notice appear in all copies and
  17. #  that both that copyright notice and this permission notice appear in
  18. #  supporting documentation, and that the name of the author not be
  19. #  used in advertising or publicity pertaining to distribution of the
  20. #  software without specific, written prior permission.
  21. #
  22. #  This program is distributed in the hope that it will be "playable",
  23. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  25. #
  26. */
  27.  
  28. #include "tetris.h"
  29. #include "data.h"
  30.  
  31. void
  32. normTimeVal(tv)
  33.     struct timeval *tv;
  34. {
  35.     while (tv->tv_usec < 0) {
  36.     tv->tv_sec--;
  37.     tv->tv_usec += MILLION;
  38.     }
  39.     while (tv->tv_usec >= MILLION) {
  40.     tv->tv_sec++;
  41.     tv->tv_usec -= MILLION;
  42.     }
  43.     return;
  44. }
  45.  
  46. void
  47. fallDown(field, thingp, eat)
  48.     field_t        *field;
  49.     thing_t       **thingp;
  50.     Bool            eat;
  51. {
  52.     int             lines;
  53.     XEvent          event;
  54.  
  55.     putBoxes(field, *thingp);
  56.  
  57.     lines = checkLine(field);
  58.     field->score += 5 + 4 * field->level * field->level * lines * lines;
  59.     field->lines += lines;
  60.     if (field->lines >= thresh[field->level])
  61.         field->level++;
  62.     updateScore(field);
  63.  
  64.     free((char *) *thingp);
  65.     if (eat) {
  66.     *thingp = NULL;
  67.     while (XPending(disp)) XNextEvent(disp, &event);
  68.     }
  69.     *thingp = makeNewThing(field);
  70.     if (overlapping(field, *thingp)) die(field);
  71.     drawThing(field, *thingp);
  72. }
  73.  
  74. void
  75. handleEvents(field, thingp, fall_down)
  76.     field_t        *field;
  77.     thing_t       **thingp;
  78.     Bool            fall_down;
  79. {
  80.     static Bool     frozen = False;
  81.     XEvent          event;
  82.     char            s[4];
  83.  
  84.     if (frozen) fall_down = False;
  85.  
  86.     if (!*thingp) {
  87.     *thingp = makeNewThing(field);
  88.     if (overlapping(field, *thingp)) die(field);
  89.     drawThing(field, *thingp);
  90.     XSync(disp, 0);
  91.     }
  92.     if (fall_down && atBottom(field, *thingp)) {
  93.     fallDown(field, thingp, False);
  94.     fall_down = False;
  95.     }
  96.     if (!XPending(disp) && !frozen)
  97.     moveOne(field, *thingp, NONE, fall_down);
  98.  
  99.     while (XPending(disp)) {
  100.     if (overlapping(field, *thingp)) die(field);
  101.  
  102.     XNextEvent(disp, &event);
  103.     switch (event.type) {
  104.     case KeyPress:
  105.         if (!XLookupString((XKeyEvent *) &event, s, 4, NULL, NULL)) break;
  106.         switch (*s) {
  107.         case 'j':        /* Move left. */
  108.         case 'J':
  109.         case 's':
  110.         case 'S':
  111.         if (!frozen)
  112.             moveOne(field, *thingp, LEFT, fall_down);
  113.         break;
  114.  
  115.         case 'k':        /* Rotate. */
  116.         case 'K':
  117.         case 'd':
  118.         case 'D':
  119.         if (!frozen)
  120.             moveOne(field, *thingp, ROTATE, fall_down);
  121.         break;
  122.  
  123.         case 'l':        /* Move right. */
  124.         case 'L':
  125.         case 'f':
  126.         case 'F':
  127.         if (!frozen)
  128.             moveOne(field, *thingp, RIGHT, fall_down);
  129.         break;
  130.  
  131.         case ' ':        /* Drop. */
  132.         case '\n':
  133.         if (!frozen) {
  134.             moveOne(field, *thingp, DROP, fall_down);
  135.             fallDown(field, thingp, True);
  136.         }
  137.         return;
  138.         break;
  139.  
  140.         case 'q':        /* Quit. */
  141.         case 'Q':
  142.         die(field);
  143.         break;
  144.  
  145.         case '+':        /* Speed up. */
  146.         case '=':
  147.         if (field->level < NUM_LEVELS - 1) {
  148.             field->level++;
  149.             updateScore(field);
  150.         }
  151.         break;
  152.  
  153.         case '-':        /* Slow down. */
  154.         case '_':
  155.         if (field->level > 0) {
  156.             field->level--;
  157.             updateScore(field);
  158.         }
  159.         break;
  160.  
  161.         case 'b':
  162.         case 'B':
  163.         beep = !beep;
  164.         if (beep) XBell(disp, -90);
  165.         break;
  166.  
  167.         case '\023':    /* Freeze / continue. */
  168.         case 'p':
  169.         case 'P':
  170.         if (beep) XBell(disp, -90);
  171.         frozen = (frozen ? False : True);
  172.         if (frozen) {
  173.         /* "... Hi Boss, I'm working hard as usual ..." */
  174.             XIconifyWindow(disp, field->frame, rootScreen);
  175.         } else {
  176.             XClearWindow(disp, field->win);
  177.             drawField(field);
  178.             if (*thingp) drawThing(field, *thingp);
  179.         }
  180.         XFlush(disp);
  181.         break;
  182.  
  183.         case '\014':        /* Redraw. */
  184.         XClearWindow(disp, field->win);
  185.         drawField(field);
  186.         if (*thingp)
  187.             drawThing(field, *thingp);
  188.         /* flow to next */
  189.  
  190.         default:
  191.         XBell(disp, -90);
  192.         XFlush(disp);
  193.         break;
  194.         }
  195.         break;        /* processing key press */
  196.  
  197.     case UnmapNotify:
  198.         frozen = True;
  199.         break;
  200.  
  201.     case Expose:
  202.         if (event.xexpose.count == 0) {
  203.             drawField(field);
  204.             if (*thingp) drawThing(field, *thingp);
  205.             if (frozen) banner(field, PAUSED_MESG);
  206.         }
  207.         XFlush(disp);
  208.         break;
  209.  
  210.     case ClientMessage:
  211.         if ((Atom) event.xclient.data.l[0] == field->delw)
  212.         die(field);
  213.         break;
  214.  
  215.     case DestroyNotify:
  216.         die(field);
  217.         break;
  218.  
  219.     }
  220.  
  221.     fall_down = False;
  222.     }
  223.  
  224.     return;
  225. }
  226.  
  227. void
  228. moveOne(field, thing, what, fall_down)
  229.     field_t        *field;
  230.     thing_t        *thing;
  231.     command_t       what;
  232.     Bool            fall_down;
  233. {
  234.     thing_t         old;
  235.  
  236.     old = *thing;
  237.  
  238.     if (tryMove(field, thing, what, fall_down))
  239.     drawThingDiff(field, thing, &old);
  240.  
  241.     XSync(disp, 0);
  242.     return;
  243. }
  244.  
  245. Bool
  246. tryMove(field, thing, what, fall_down)
  247.     field_t        *field;
  248.     thing_t        *thing;
  249.     command_t       what;
  250.     Bool            fall_down;
  251. {
  252.     int             x, y;
  253.     thing_t         temp;
  254.     Bool            ok = True;
  255.  
  256.     temp = *thing;
  257.  
  258.     if (fall_down) temp.ypos--;
  259.  
  260.     switch (what) {
  261.     case LEFT:
  262.     temp.xpos--;
  263.     break;
  264.  
  265.     case RIGHT:
  266.     temp.xpos++;
  267.     break;
  268.  
  269.     case ROTATE:
  270.     rotateThing(&temp);
  271.     break;
  272.  
  273.     case DROP:
  274.     while (!overlapping(field, &temp)) {
  275.         field->score += field->level;
  276.         temp.ypos--;
  277.     }
  278.     temp.ypos++;
  279.     break;
  280.  
  281.     case NONE:
  282.     break;
  283.     }
  284.  
  285.     for (x = 0; (x < temp.size) && ok; x++)
  286.     for (y = 0; (y < temp.size) && ok; y++) {
  287.         if (temp.map[x][y]) {
  288.         if ((temp.xpos + x < 0) ||
  289.             (temp.xpos + x >= field->width) ||
  290.             (temp.ypos + y < 0) ||
  291.             (temp.ypos + y >= field->height) ||
  292.             (field->full[temp.xpos + x]
  293.              [temp.ypos + y]))
  294.             ok = False;
  295.         }
  296.     }
  297.  
  298.     if (ok) *thing = temp;
  299.  
  300.     if (overlapping(field, thing)) {
  301.     return False;
  302.     } else {
  303.     return True;
  304.     }
  305. }
  306.  
  307. Bool
  308. atBottom(field, thing)
  309.     field_t        *field;
  310.     thing_t        *thing;
  311. {
  312.     int             x, y;
  313.  
  314.     for (x = 0; x < thing->size; x++)
  315.     for (y = 0; y < thing->size; y++)
  316.         if (thing->map[x][y]) {
  317.         if (thing->ypos + y <= 0)
  318.             return True;
  319.         if (field->full[thing->xpos + x]
  320.             [thing->ypos + y - 1])
  321.             return True;
  322.         }
  323.     return False;
  324. }
  325.  
  326. void
  327. drawThing(field, thing)
  328.     field_t        *field;
  329.     thing_t        *thing;
  330. {
  331.     int             x, y;
  332.  
  333.     for (x = 0; x < thing->size; x++)
  334.     for (y = 0; y < thing->size; y++)
  335.         if (thing->map[x][y])
  336.         doBox(field, thing->xpos + x, thing->ypos + y,
  337.               thing->map[x][y]);
  338.     return;
  339. }
  340.  
  341. void
  342. drawThingDiff(field, thing, oldthing)
  343.     field_t        *field;
  344.     thing_t        *thing, *oldthing;
  345. {
  346.     int             x, y;
  347.     int             ox, oy;
  348.  
  349.     for (x = 0; x < thing->size; x++)
  350.     for (y = 0; y < thing->size; y++) {
  351.         ox = x - oldthing->xpos + thing->xpos;
  352.         oy = y - oldthing->ypos + thing->ypos;
  353.         if (thing->map[x][y])
  354.         doBox(field, thing->xpos + x, thing->ypos + y,
  355.               thing->map[x][y]);
  356.     }
  357.     for (x = 0; x < thing->size; x++)
  358.     for (y = 0; y < thing->size; y++) {
  359.         ox = x - thing->xpos + oldthing->xpos;
  360.         oy = y - thing->ypos + oldthing->ypos;
  361.         if (oldthing->map[x][y] &&
  362.             ((ox < 0) || (ox >= thing->size) ||
  363.              (oy < 0) || (oy >= thing->size) ||
  364.              !thing->map[ox][oy]))
  365.         doBox(field, oldthing->xpos + x,
  366.               oldthing->ypos + y,
  367.               0);
  368.     }
  369.     return;
  370. }
  371.  
  372. void
  373. doBox(field, x, y, pat)
  374.     field_t        *field;
  375.     int             x, y;
  376.     int             pat;
  377. {
  378.     if ((x < 0) || (x >= field->width) || (y < 0) || (y >= field->height))
  379.     abort();
  380.     if (pat == 0)
  381.     XFillRectangle(disp, field->win, gc_w2,
  382.                x * BOX_WIDTH + X_MARGIN,
  383.                ytr((y + 1) * BOX_HEIGHT + Y_MARGIN) - 1,
  384.                BOX_WIDTH + 1, BOX_HEIGHT + 1);
  385.     else {
  386.     if (rootDepth == 1) {
  387.         pat = pat % 16 - 1;
  388.         XCopyPlane(disp, patterns[pat].pixmap, field->win, gc_w,
  389.                0, 0,
  390.                BOX_WIDTH, BOX_HEIGHT,
  391.                x * BOX_WIDTH + X_MARGIN,
  392.                ytr((y + 1) * BOX_HEIGHT + Y_MARGIN), 1);
  393.     } else {
  394.         pat -= 1;
  395.         XCopyPlane(disp, patterns[pat].pixmap, field->win,
  396.                gc_pat[pat],
  397.                0, 0,
  398.                BOX_WIDTH, BOX_HEIGHT,
  399.                x * BOX_WIDTH + X_MARGIN,
  400.                ytr((y + 1) * BOX_HEIGHT + Y_MARGIN), 1);
  401.     }
  402.     }
  403.     return;
  404. }
  405.  
  406. Bool
  407. overlapping(field, thing)
  408.     field_t        *field;
  409.     thing_t        *thing;
  410. {
  411.     int             x, y;
  412.  
  413.     for (x = 0; x < thing->size; x++)
  414.     for (y = 0; y < thing->size; y++) {
  415.         if (thing->map[x][y] && (thing->ypos + y < 0))
  416.         return True;
  417.         if (thing->map[x][y] && field->full[thing->xpos + x]
  418.             [thing->ypos + y])
  419.         return True;
  420.     }
  421.     return False;
  422. }
  423.  
  424. int
  425. putBoxes(field, thing)
  426.     field_t        *field;
  427.     thing_t        *thing;
  428. {
  429.     int             x, y;
  430.     int             highest = 0;
  431.  
  432.     for (x = 0; x < thing->size; x++)
  433.     for (y = 0; y < thing->size; y++)
  434.         if (thing->map[x][y]) {
  435.         if ((thing->xpos + x < 0) ||
  436.             (thing->xpos + x >= field->width) ||
  437.             (thing->ypos + y < 0) ||
  438.             (thing->ypos + y >= field->height))
  439.             abort();
  440.         field->full[thing->xpos + x][thing->ypos + y]
  441.             = thing->map[x][y];
  442.         if (thing->ypos + y > highest)
  443.             highest = thing->ypos + y;
  444.         }
  445.     return highest;
  446. }
  447.  
  448. field_t        *
  449. initField(width, height, lines_full, argc, argv)
  450.     int             width, height, lines_full, argc;
  451.     char           *argv[];
  452. {
  453.     XTextProperty   wName, iName;
  454.     XWMHints        wmhints;
  455.     XClassHint      classhints;
  456.     unsigned int    attvm;
  457.     XSetWindowAttributes att;
  458.     Cursor          cursor;
  459.     XSizeHints      sh;
  460.     field_t        *field = (field_t *) malloc(sizeof(field_t));
  461.     int             x, y, w, h;;
  462.  
  463.     w = width * BOX_WIDTH + 2 * X_MARGIN;
  464.     h = height * BOX_HEIGHT + 2 * Y_MARGIN + TITLE_HEIGHT;
  465.  
  466.     field->width = width;
  467.     field->height = height;
  468.     field->score = 0;
  469.     field->level = 1;
  470.     field->lines = 0;
  471.  
  472.     cursor = XCreateFontCursor(disp, XC_exchange);
  473.  
  474.     /* create window */
  475.     attvm = CWBackPixel | CWBorderPixel | CWEventMask | 
  476.     CWDontPropagate | CWCursor;
  477.     att.background_pixel = bgcolor.pixel;
  478.     att.border_pixel = bdcolor.pixel;
  479.     att.event_mask = ExposureMask | StructureNotifyMask;
  480.     att.do_not_propagate_mask = KeyPressMask | KeyReleaseMask |
  481.     ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
  482.     ButtonMotionMask | Button1MotionMask | Button2MotionMask |
  483.     Button3MotionMask | Button4MotionMask | Button5MotionMask ;
  484.     att.cursor = cursor;
  485.  
  486.     field->frame = XCreateWindow(disp, DefaultRootWindow(disp),
  487.     BASE_XPOS, BASE_YPOS, w, h, BORDER_WIDTH, CopyFromParent,
  488.     InputOutput, CopyFromParent, attvm, &att);
  489.  
  490.     /* title */
  491.     assert(XStringListToTextProperty(&winName, 1, &wName), "Window Name");
  492.     assert(XStringListToTextProperty(&iconName, 1, &iName), "Icon Name");
  493.  
  494.     /* size hints */
  495.     sh.flags = PSize | PMinSize | PMaxSize;
  496.     sh.width = (sh.min_width = (sh.max_width = w));
  497.     sh.height = (sh.min_height = (sh.max_height = h));
  498.  
  499.     /* wm hints */
  500.     wmhints.initial_state = NormalState;
  501.     wmhints.input = True;
  502.     wmhints.icon_pixmap = None;
  503.     wmhints.flags = StateHint | InputHint | IconPixmapHint;
  504.     classhints.res_name = argv[0];
  505.     classhints.res_class = "GTetris";
  506.  
  507.     /* set wm properties */
  508.     XSetWMProperties(disp, field->frame, &wName, &iName,
  509.     argv, argc, &sh, &wmhints, &classhints);
  510.  
  511.     /* get ready to receive WM_DELETE_WINDOW */
  512.     field->delw = XInternAtom(disp, "WM_DELETE_WINDOW", False);
  513.     XSetWMProtocols(disp, field->frame, &(field->delw), 1);
  514.  
  515.     /* "title" sub-window */
  516.     field->title = XCreateSimpleWindow(disp, field->frame,
  517.     -BORDER_WIDTH, -BORDER_WIDTH, w, TITLE_HEIGHT, BORDER_WIDTH,
  518.     bdcolor.pixel, bgcolor.pixel);
  519.     XSelectInput(disp, field->title, KeyPressMask | ExposureMask);
  520.  
  521.     /* "ground" sub-window */
  522.     field->win = XCreateSimpleWindow(disp, field->frame,
  523.     -BORDER_WIDTH, TITLE_HEIGHT - BORDER_WIDTH, w, h - TITLE_HEIGHT,
  524.     BORDER_WIDTH, bdcolor.pixel, bgcolor.pixel);
  525.     XSelectInput(disp, field->win, KeyPressMask | ExposureMask);
  526.  
  527.     if (rootDepth == 1)
  528.     num_patterns = NUM_BITMAPS;
  529.  
  530.     field->full = (int **) malloc(sizeof(int *) * width);
  531.     for (x = 0; x < width; x++) {
  532.     field->full[x] = (int *) malloc(sizeof(int) * height);
  533.     for (y = 0; y < height; y++)
  534.         if ((y < lines_full) && nrandom(2))
  535.         field->full[x][y] = nrandom(num_patterns);
  536.         else
  537.         field->full[x][y] = 0;
  538.     }
  539.  
  540.     /* loading fonts */
  541.     field->tfont = XLoadQueryFont(disp, TITLE_FONT);
  542.     field->sfont = XLoadQueryFont(disp, SCORE_FONT);
  543.     if (field->tfont == NULL) {
  544.     field->tfont = XLoadQueryFont(disp, TITLE_FONT2);
  545.     assert(field->tfont, "Title Font");
  546.     }
  547.     if (field->sfont == NULL) {
  548.     field->sfont = XLoadQueryFont(disp, SCORE_FONT2);
  549.     assert(field->sfont, "Banner Font");
  550.     }
  551.  
  552.     field->winheight = field->height * BOX_HEIGHT + 2 * Y_MARGIN;
  553.     field->winwidth = field->width * BOX_WIDTH + 2 * X_MARGIN;
  554.  
  555.     /* map windows */
  556.     XMapWindow(disp, field->title);
  557.     XMapWindow(disp, field->win);
  558.     XMapRaised(disp, field->frame);
  559.  
  560.     gcv.function = GXcopy;
  561.     gcv.foreground = bdcolor.pixel;
  562.     gcv.background = bgcolor.pixel;
  563.  
  564.     gc_t = XCreateGC(disp, field->title,
  565.     (GCForeground | GCBackground | GCFunction), &gcv);
  566.     gc_w = XCreateGC(disp, field->win,
  567.     (GCForeground | GCBackground | GCFunction), &gcv);
  568.  
  569.     gcv.background = bdcolor.pixel;
  570.     gcv.foreground = bgcolor.pixel;
  571.  
  572.     gc_w2 = XCreateGC(disp, field->win, (GCForeground | GCBackground |
  573.                      GCFunction), &gcv);
  574.  
  575.     text.function = GXcopy;
  576.     text.font = field->tfont->fid;
  577.     text.foreground = bdcolor.pixel;
  578.     text.background = bgcolor.pixel;
  579.     gc_ttx = XCreateGC(disp, field->title, (GCFunction | GCFont |
  580.                        GCForeground | GCBackground), &text);
  581.     text.font = field->sfont->fid;
  582.     gc_wtx = XCreateGC(disp, field->title, (GCFunction | GCFont |
  583.                        GCForeground | GCBackground), &text);
  584.  
  585.     XFlush(disp);
  586.     return (field);
  587. }
  588.  
  589. void
  590. drawField(field)
  591.     field_t        *field;
  592. {
  593.     int             x, y;
  594.  
  595.     for (x = 0; x < field->width; x++)
  596.     for (y = 0; y < field->height; y++)
  597.         doBox(field, x, y, field->full[x][y]);
  598.  
  599.     XDrawImageString(disp, field->title, gc_ttx, 5, 30, "TETRIS", 6);
  600.  
  601.     updateScore(field);
  602.  
  603.     XFlush(disp);
  604.     return;
  605. }
  606.  
  607. void
  608. updateScore(field)
  609.     field_t        *field;
  610. {
  611.     char            buf[100];
  612.  
  613.     (void) sprintf(buf, "Score: %-7d", field->score);
  614.     XDrawImageString(disp, field->title, gc_wtx,
  615.              SCORE_XPOS1, SCORE_YPOS1, buf, strlen(buf));
  616.  
  617.     (void) sprintf(buf, "Level: %-7d", field->level);
  618.     XDrawImageString(disp, field->title, gc_wtx,
  619.              SCORE_XPOS1, SCORE_YPOS2, buf, strlen(buf));
  620.  
  621.     (void) sprintf(buf, "Lines: %-7d", field->lines);
  622.     XDrawImageString(disp, field->title, gc_wtx,
  623.              SCORE_XPOS2, SCORE_YPOS2, buf, strlen(buf));
  624.  
  625.     XFlush(disp);
  626.     return;
  627. }
  628.  
  629. thing_t        *
  630. makeNewThing(field)
  631.     field_t        *field;
  632. {
  633.     int             i, j, k;
  634.     int             pat;
  635.     int             whichone;
  636.     thing_t        *thing = (thing_t *) malloc(sizeof(thing_t));
  637.  
  638.     i = 0;
  639.     for (j = 0; j < NUM_POSSIBLE; j++)
  640.     i += possible[j].probability;
  641.  
  642.     k = nrandom(i);
  643.  
  644.     for (j = 0; j < NUM_POSSIBLE; j++) {
  645.     k -= possible[j].probability;
  646.     if (k < 0)
  647.         break;
  648.     }
  649.  
  650.     *thing = possible[j];
  651.     whichone = j;
  652.     for (i = 0; i < thing->size; i++)
  653.     for (j = 0; j < thing->size; j++)
  654.         if (thing->map[i][j]) {
  655.         pat = 1;
  656.         if (i != 0 && thing->map[i - 1][j])
  657.             pat += 1;
  658.         if (j != 0 && thing->map[i][j - 1])
  659.             pat += 2;
  660.         if (i < thing->size - 1 && thing->map[i + 1][j])
  661.             pat += 4;
  662.         if (j < thing->size - 1 && thing->map[i][j + 1])
  663.             pat += 8;
  664.         thing->map[i][j] = pat + whichone * 16;
  665.         }
  666.     for (i = nrandom(4); i > 0; i--)
  667.     rotateThing(thing);
  668.  
  669.     thing->ypos = field->height - thing->size;
  670.     thing->xpos = nrandom((field->width - 2 * thing->size) + thing->size);
  671.  
  672.     return (thing);
  673. }
  674.  
  675. void
  676. rotateThing(thing)
  677.     thing_t        *thing;
  678. {
  679.     thing_t         temp;
  680.     int             lpoint = thing->size;
  681.     int             nlpoint = thing->size;
  682.     int             x, y;
  683.     int             pattype;
  684.  
  685.     temp = *thing;
  686.     for (x = 0; x < thing->size; x++)
  687.     for (y = 0; y < thing->size; y++)
  688.         if (thing->map[x][y] && (lpoint < y))
  689.         lpoint = y;
  690.  
  691.     for (x = 0; x < thing->size; x++)
  692.     for (y = 0; y < thing->size; y++) {
  693.         pattype = (temp.map[y][thing->size - x - 1] - 1) / 16;
  694.         thing->map[x][y] =
  695.         ((((temp.map[y][thing->size - x - 1] & 15) - 1) * 2) % 15 + 1)
  696.         + pattype * 16;
  697.         if (thing->map[x][y] < 0)
  698.         thing->map[x][y] = 0;
  699.     }
  700.  
  701.     for (x = 0; x < thing->size; x++)
  702.     for (y = 0; y < thing->size; y++)
  703.         if (thing->map[x][y] && (nlpoint < y))
  704.         nlpoint = y;
  705.  
  706.     thing->ypos += lpoint - nlpoint;
  707.  
  708.     return;
  709. }
  710.  
  711. int
  712. checkLine(field)
  713.     field_t        *field;
  714. {
  715.     int            *set = (int *) malloc(sizeof(int) * field->height);
  716.     int             i, x, y, nset = 0, h;
  717.  
  718.     for (y = 0; y < field->height; y++) {
  719.     for (x = 0; x < field->width; x++)
  720.         if (!field->full[x][y])
  721.         break;
  722.     if (x == field->width) {
  723.         set[y] = 1;
  724.         nset++;
  725.     } else
  726.         set[y] = 0;
  727.     }
  728.  
  729.     if (nset) {
  730.     for (i = 0; i < NUM_FLASHES / nset; i++) {
  731.         for (y = 0; y < field->height; y++)
  732.         if (set[y]) {
  733.             XFillRectangle(disp, field->win, gc_w,
  734.                    X_MARGIN,
  735.                    ytr((y + 1) * BOX_HEIGHT +
  736.                        Y_MARGIN),
  737.                    field->width * BOX_WIDTH,
  738.                    BOX_HEIGHT);
  739.             XFlush(disp);
  740.         }
  741.     }
  742.     for (y = 0; y < field->height; y++)
  743.         if (set[y]) {
  744.         for (i = y; i < field->height - 1; i++)
  745.             for (x = 0; x < field->width; x++)
  746.             field->full[x][i] =
  747.                 field->full[x][i + 1];
  748.         for (x = 0; x < field->width; x++)
  749.             field->full[x][field->height - 1] = 0;
  750.  
  751.         h = (field->height - y - 1) * BOX_HEIGHT;
  752.         if (h > field->winheight - BOX_HEIGHT -
  753.             Y_MARGIN)
  754.             h = field->winheight - BOX_HEIGHT -
  755.             Y_MARGIN;
  756.         XCopyArea(disp, field->win, field->win, gc_w,
  757.               X_MARGIN, Y_MARGIN,
  758.               field->winwidth, h,
  759.               X_MARGIN, BOX_HEIGHT + Y_MARGIN);
  760.  
  761.         for (i = y; i < field->height - 1; i++)
  762.             set[i] = set[i + 1];
  763.         set[field->height - 1] = 0;
  764.         y--;
  765.         }
  766.     if (beep) XBell(disp, -90);
  767.     XSync(disp, 0);
  768.     }
  769.     free((char *) set);
  770.  
  771.     return nset;
  772. }
  773.  
  774. void
  775. initPixmaps(field)
  776.     field_t        *field;
  777. {
  778.     Pixmap          bms[NUM_BITMAPS];
  779.     int             i, j;
  780.     char           *lastFg = "", *lastBg = "";
  781.     XColor          lastFgC, lastBgC;
  782.  
  783.     for (i = 0; i < NUM_BITMAPS; i++) {
  784.     bms[i] = XCreateBitmapFromData(disp, field->win,
  785.                        bitmap_data[i].data,
  786.                        bitmap_data[i].width,
  787.                        bitmap_data[i].height);
  788.     assert(bms[i], "Bitmap");
  789.     }
  790.     if (rootDepth == 1) {
  791.     for (i = 0; i < NUM_BITMAPS; i++) {
  792.         patterns[i].pixmap = bms[i];
  793.     }
  794.     return;
  795.     }
  796.     for (i = 0; i < NUM_PATTERNS; i++) {
  797.     j = 0;
  798.     if (strcmp(patterns[i].fgname, lastFg) != 0) {
  799.         assert(XParseColor(disp, cmap,
  800.         patterns[i].fgname, &patterns[i].fg), "Parse Color");
  801.         assert(XAllocColor(disp, cmap, &patterns[i].fg), "Allocate Color");
  802.         lastFg = patterns[i].fgname;
  803.         lastFgC = patterns[i].fg;
  804.         j = 1;
  805.     } else {
  806.         patterns[i].fg = lastFgC;
  807.     }
  808.     if (strcmp(patterns[i].bgname, lastBg) != 0) {
  809.         assert(XParseColor(disp, cmap,
  810.         patterns[i].bgname, &patterns[i].bg), "Parse Color");
  811.         assert(XAllocColor(disp, cmap, &patterns[i].bg), "Allocate Color");
  812.         lastBg = patterns[i].bgname;
  813.         lastBgC = patterns[i].bg;
  814.         j = 1;
  815.     } else {
  816.         patterns[i].bg = lastBgC;
  817.     }
  818.  
  819.     if (j) {
  820.         color.function = GXcopy;
  821.         color.foreground = patterns[i].fg.pixel;
  822.         color.background = patterns[i].bg.pixel;
  823.  
  824.         gc_pat[i] = XCreateGC(disp, field->win, (GCForeground |
  825.                     GCBackground | GCFunction), &color);
  826.     } else
  827.         gc_pat[i] = gc_pat[i - 1];
  828.  
  829.     patterns[i].pixmap = bms[patterns[i].whichbitmap];
  830.     assert(patterns[i].pixmap, "Pixmap");
  831.     }
  832.     return;
  833. }
  834.  
  835. int
  836. nrandom(n)
  837.     int             n;
  838. {
  839.     return ((((double) random()) / ((double) 0x7fffffff)) * n);
  840. }
  841.  
  842. void
  843. Usage(argv)
  844.     char          **argv;
  845. {
  846.     fprintf(stderr, "Usage:  %s [ starting_level [ rows_pre-filled ] ]\n\n",
  847.     argv[0]);
  848.     exit(255);
  849. }
  850.  
  851.