home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume15 / gtetrs3 / part01 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  53.7 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v15i044:  gtetris3 -  Generic Tetris for X11, V2.0.1, Part01/02
  5. Message-ID: <4205@master.CNA.TEK.COM>
  6. Date: 15 Jan 93 01:32:08 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1951
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1543
  11.  
  12. Submitted-by: "Qiang Alex Zhao" <azhao@cs.arizona.edu>
  13. Posting-number: Volume 15, Issue 44
  14. Archive-name: gtetris3/Part01
  15. Supersedes: gtetris2: Volume 15, Issue 5-6
  16. Environment: X11R4/5, Xlib
  17.  
  18.     [This is major rewrite of the popular Generic Tetris game for X.  -br]
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 1 (of 2)."
  27. # Contents:  README MANIFEST X11 bitmaps playing.c tetris.c tetris.h
  28. #   utils.c
  29. # Wrapped by billr@saab on Wed Jan 13 19:41:27 1993
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'README' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'README'\"
  33. else
  34. echo shar: Extracting \"'README'\" \(4720 characters\)
  35. sed "s/^X//" >'README' <<'END_OF_FILE'
  36. X    GENERIC TETRIS
  37. X    ==============    Yet Another Tetris Game on X, V2.0.1
  38. X
  39. X
  40. XWHY ANOTHER?
  41. X
  42. X    Because this one is simple, easy to build, and portable -- actually
  43. X    the blocks are bigger, more comfortable for your eyes. It only uses
  44. X    Xlib -- no "toolkit" kind of thing. People have tested it on the
  45. X    following platforms:
  46. X
  47. X    DEC 5000        Ultrix 4.2A    X11R4
  48. X    Iris 4D            IRIX 4.0.1    Motif
  49. X    Sun4, SPARCstation    SunOS 4.1.1    X11R4, X11R5
  50. X    Sequent S81        DYNIX 3.2.0    X11R5
  51. X
  52. X    If your's is not in this list, please let me know -- thanks. The
  53. X    most updated source could be found on export.lcs.mit.edu under
  54. X    /contrib.
  55. X
  56. X    A System V port (Sequent Dynix/ptx) for earlier versions has been
  57. X    added by "Hans-Wolfgang Loidl" (hwloidl@risc.uni-linz.ac.at). The
  58. X    source can be retrieved by anonymous FTP to:
  59. X    Host:    melmac.risc.uni-linz.ac.at
  60. X    File:    /pub/misc/gtetris.tar.Z
  61. X
  62. X
  63. XHOW TO BUILD?
  64. X
  65. X    Edit the Imakefile for appropriate settings of variable SCOREFILE
  66. X    and RANDOM, then do:
  67. X    xmkmf
  68. X    make
  69. X
  70. X    "Tetris" is the game. It only lists the top 15 players at the end,
  71. X    each player may has at most three scores. With the option "-s",
  72. X    "tetris" will list all the scores.
  73. X
  74. X
  75. XANYTHING SPECIAL IN PLAYING?
  76. X
  77. X    Use 'j' to move left; 'l' to move right; 'k' to rotate. Left-handed
  78. X    people may want to use 's', 'd', 'f' respectively. Use the space
  79. X    bar to drop a block quickly. Do you want to try the arrow keys?
  80. X
  81. X    Use CTRL-L key combination to redraw -- in case the program messes
  82. X    somthing up.
  83. X
  84. X    As usual, '+' and '-' will speed up or lower down the speed. Note
  85. X    that you don't need to press the SHIFT key -- '=' and '_' also
  86. X    work. The 'b' key can be used to toggle "beep" and 'n' toggles
  87. X    "show next".
  88. X
  89. X    If you press 'p', the game will be paused, and the window will be
  90. X    iconified -- just in case your boss suddenly appears at your door.
  91. X    ;o) When the tetris window loses its focus, it also goes to
  92. X    "paused" mode except it doesn't iconify itself.
  93. X
  94. X    Refer to the man page for detailed command line options.
  95. X
  96. X
  97. XFOUND A BUG?
  98. X
  99. X    Send bugs (or their reports, or fixes) to the author:
  100. X
  101. X    Qiang Alex Zhao,    azhao@cs.arizona.edu
  102. X    Computer Science Department
  103. X    University of Arizona
  104. X    Tucson, AZ 85721
  105. X
  106. X    Refter to the "COPYRIGHT" notice in the "COPYRIGHT" file (yeah, as
  107. X    its name implies). And note: my first name is *NOT* spelled as
  108. X    "Quiang" nor "Quang".
  109. X
  110. X
  111. XHISTORY -- Oh no, not again: I failed my history course!
  112. XWell ... ACKNOWLEDGEMENTS
  113. X
  114. X    Since the days of V1.8, I have got many responses over the net.
  115. X    Thanks go to people who helped me in improving the program.
  116. X
  117. X  [Jan 12, 93]  V2.0.1: added arrow keys. Changed error handling method
  118. X        in locking score file, suggested by Hellmut Golde
  119. X        <golde@cs.washington.edu>.
  120. X
  121. X  [Jan 10, 93]  V2.0.0: Complete rewrite. Enhanced layout. Added
  122. X        resource management and "next piece". Changes made for
  123. X        Sony workstations, suggested by Masato Ogawa
  124. X        <ogawa@sm.sony.co.jp>. Included four X11 header files
  125. X        in case some system doesn't have them. Fixed block
  126. X        clearing bug found by Benjamin Kroop
  127. X        <bkroop@sunlab.cit.cornell.edu>.
  128. X
  129. X  [Nov 13, 92]  Black Friday -- V1.8.1: numerious minor changes. Made
  130. X        score listing built in.
  131. X
  132. X  [Oct 08, 92]  V1.8: Corrected some typos, <herbison@erlang.enet.dec.com>.
  133. X        Added man-page.  Gregg Townsend <gmt@cs.arizona.edu>
  134. X        provided hints for some problems on HP-UX. Imakefile.
  135. X        Richard van Denzel suggest modifications for HP-UX.
  136. X
  137. X  [Sep 30, 92]    V1.7: Richard van Denzel <raet-sh!richard@relay.nluug.nl>
  138. X        reported bugs on HP-UX 8.0.
  139. X
  140. X  [Sep 27, 92]  V1.6: Changed speed coefficients. Improved window
  141. X        manager hints. Several rows at once worth more points.
  142. X
  143. X  [Sep 25, 92]  V1.5: HP-UX fixes by "Richard van Denzel"
  144. X        <raet-sh!richard@relay.nluug.nl>. Added 'b' to toggle
  145. X        "beep". Rewrote window creation/initialization to fix
  146. X        the "losing input focus" problem.
  147. X
  148. X  [Sep 24, 92]  V1.4: Added <sys/select.h> and -lbsd for AIX (by "Daryl
  149. X        Green" <darylg@amex-trs.com>).
  150. X
  151. X  [Sep 23, 92]  V1.3: Scoring -- a line in a higher level worth more
  152. X        points; "tscores" program. Submitted to
  153. X        comp.sources.games (volumn 15, issues 1-2; it has
  154. X        nothing to do with GNU, but it was called "gtetris",
  155. X        pronounced as "Gee, tetris", by the newsgroup
  156. X        moderator).
  157. X
  158. X  [Sep ??, 92]  First set of versions, 1.0 through 1.2 -- developed and
  159. X        tested at the University of Arizona. Put on
  160. X        export.lcs.mit.edu.
  161. X
  162. X        I studied an old tetris game for X10, wrote by Wayne
  163. X        Christopher <faustus@cs.berkeley.edu> in 1988; then I
  164. X        adopted the ideas in representing those "blocks" and
  165. X        rotating them, and added X11 stuff.  Also I learned a
  166. X        lot from Nathan Sidwell's great game "xmris", e.g.  the
  167. X        "iconifying pause".
  168. X
  169. END_OF_FILE
  170. if test 4720 -ne `wc -c <'README'`; then
  171.     echo shar: \"'README'\" unpacked with wrong size!
  172. fi
  173. # end of 'README'
  174. fi
  175. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  176.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  177. else
  178. echo shar: Extracting \"'MANIFEST'\" \(1075 characters\)
  179. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  180. X   File Name        Archive #    Description
  181. X-----------------------------------------------------------
  182. X COPYRIGHT                  2    
  183. X Imakefile                  2    
  184. X MANIFEST                   1    This shipping list
  185. X README                     1    
  186. X X11                        1    
  187. X X11/Xfuncproto.h           2    
  188. X X11/Xfuncs.h               2    
  189. X X11/Xos.h                  2    
  190. X X11/Xosdefs.h              2    
  191. X bitmaps                    1    
  192. X bitmaps/rot00.xbm          2    
  193. X bitmaps/rot01.xbm          2    
  194. X bitmaps/rot02.xbm          2    
  195. X bitmaps/rot03.xbm          2    
  196. X bitmaps/rot04.xbm          2    
  197. X bitmaps/rot05.xbm          2    
  198. X bitmaps/rot06.xbm          2    
  199. X bitmaps/rot07.xbm          2    
  200. X bitmaps/rot08.xbm          2    
  201. X bitmaps/rot09.xbm          2    
  202. X bitmaps/rot10.xbm          2    
  203. X bitmaps/rot11.xbm          2    
  204. X bitmaps/rot12.xbm          2    
  205. X bitmaps/rot13.xbm          2    
  206. X bitmaps/rot14.xbm          2    
  207. X bitmaps/ticon.xbm          2    
  208. X playing.c                  1    
  209. X tetris.c                   1    
  210. X tetris.h                   1    
  211. X tetris.man                 2    
  212. X utils.c                    1    
  213. END_OF_FILE
  214. if test 1075 -ne `wc -c <'MANIFEST'`; then
  215.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  216. fi
  217. # end of 'MANIFEST'
  218. fi
  219. if test ! -d 'X11' ; then
  220.     echo shar: Creating directory \"'X11'\"
  221.     mkdir 'X11'
  222. fi
  223. if test ! -d 'bitmaps' ; then
  224.     echo shar: Creating directory \"'bitmaps'\"
  225.     mkdir 'bitmaps'
  226. fi
  227. if test -f 'playing.c' -a "${1}" != "-c" ; then 
  228.   echo shar: Will not clobber existing file \"'playing.c'\"
  229. else
  230. echo shar: Extracting \"'playing.c'\" \(9187 characters\)
  231. sed "s/^X//" >'playing.c' <<'END_OF_FILE'
  232. X/*
  233. X# GENERIC X-WINDOW-BASED TETRIS
  234. X#
  235. X#    playing.c
  236. X#
  237. X###
  238. X#
  239. X#  Copyright (C) 1992, 1993     Qiang Alex Zhao, azhao@cs.arizona.edu
  240. X#        Computer Science Dept, University of Arizona
  241. X#
  242. X#            All Rights Reserved
  243. X#
  244. X#  Permission to use, copy, modify, and distribute this software and
  245. X#  its documentation for any purpose and without fee is hereby granted,
  246. X#  provided that the above copyright notice appear in all copies and
  247. X#  that both that copyright notice and this permission notice appear in
  248. X#  supporting documentation, and that the name of the author not be
  249. X#  used in advertising or publicity pertaining to distribution of the
  250. X#  software without specific, written prior permission.
  251. X#
  252. X#  This program is distributed in the hope that it will be "playable",
  253. X#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  254. X#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  255. X#
  256. X*/
  257. X
  258. X#include    "tetris.h"
  259. X
  260. Xstatic Bool     paused = False;
  261. X
  262. Xstatic int      speeds[NUM_LEVELS] = {
  263. X    100, 92, 84, 76, 68, 60, 53, 46, 39, 32, 26, 20, 15, 10, 6, 3, 1, 0};
  264. Xstatic int      thresh[NUM_LEVELS] = {
  265. X    10, 20, 30, 40, 50, 60, 70, 80, 90,
  266. X    100, 110, 120, 130, 140, 150, 160, 170, 180};
  267. X
  268. Xstatic struct timeval nextFall, now, delay;
  269. Xstatic struct timezone tzone = {0, 0};
  270. X
  271. X/* ------------------------------------------------------------------ */
  272. X
  273. Xvoid
  274. Xplaying()
  275. X{
  276. X    Bool            resetTime = True;
  277. X
  278. X    score = prefilled * level * 10;
  279. X    while (True) {
  280. X    if (resetTime) {
  281. X        (void) gettimeofday(&nextFall, &tzone);
  282. X        nextFall.tv_usec += 10000 * speeds[level];
  283. X        realTime(&nextFall);
  284. X    } else {
  285. X        int             writefd = 0, exceptfd = 0;
  286. X        int             readfd = 1 << ConnectionNumber(display);
  287. X
  288. X        (void) gettimeofday(&now, &tzone);
  289. X        delay.tv_sec = nextFall.tv_sec - now.tv_sec;
  290. X        delay.tv_usec = nextFall.tv_usec - now.tv_usec;
  291. X        realTime(&delay);
  292. X        if (delay.tv_sec >= 0) {    /* sleep */
  293. X        (void) select(sizeof(int) * 8, (fd_set *) &readfd,
  294. X               (fd_set *) & writefd, (fd_set *) & exceptfd, &delay);
  295. X        }
  296. X    }
  297. X    (void) gettimeofday(&now, &tzone);
  298. X    if ((now.tv_sec > nextFall.tv_sec) ||
  299. X        ((now.tv_sec == nextFall.tv_sec) &&
  300. X        (now.tv_usec > nextFall.tv_usec))) {
  301. X        (void) evGotNewThing(True);
  302. X        resetTime = True;
  303. X    } else {
  304. X        resetTime = evGotNewThing(False);
  305. X    }
  306. X    }
  307. X    /* never come to here */
  308. X}
  309. X
  310. X/* ------------------------------------------------------------------ */
  311. X
  312. XBool
  313. XevGotNewThing(falldown)
  314. X    Bool            falldown;
  315. X{
  316. X    XEvent          ev;
  317. X    Bool            gotNew = False;
  318. X    char            buf[4];
  319. X
  320. X    if (!paused && falldown)
  321. X    gotNew = moveOne(FALL) || gotNew;
  322. X
  323. X    while (XPending(display)) {
  324. X    XNextEvent(display, &ev);
  325. X    switch (ev.type) {
  326. X    case KeyPress:
  327. X        if (!XLookupString(&ev.xkey, buf, 4, NULL, NULL))
  328. X        break;
  329. X
  330. X        switch (buf[0]) {
  331. X        case 'j':
  332. X        case 's':
  333. X        if (!paused)
  334. X            gotNew = moveOne(LEFT) || gotNew;
  335. X        break;
  336. X
  337. X        case 'k':
  338. X        case 'd':
  339. X        if (!paused)
  340. X            gotNew = moveOne(ROTATE) || gotNew;
  341. X        break;
  342. X
  343. X        case 'l':
  344. X        case 'f':
  345. X        if (!paused)
  346. X            gotNew = moveOne(RIGHT) || gotNew;
  347. X        break;
  348. X
  349. X        case ' ':
  350. X        case '\n':
  351. X        if (!paused)
  352. X            gotNew = moveOne(DROP) || gotNew;
  353. X        break;
  354. X
  355. X        case 'q':
  356. X        case 'Q':
  357. X        gameOver();
  358. X        break;
  359. X
  360. X        case '+':
  361. X        case '=':
  362. X        if (!paused)
  363. X            if (level < NUM_LEVELS - 1) {
  364. X            level++;
  365. X            drawStatus();
  366. X            }
  367. X        break;
  368. X
  369. X        case '-':
  370. X        case '_':
  371. X        if (!paused)
  372. X            if (level > 0) {
  373. X            level--;
  374. X            drawStatus();
  375. X            }
  376. X        break;
  377. X
  378. X        case 'b':
  379. X        case 'B':
  380. X        beep = !beep;
  381. X        if (beep)
  382. X            XBell(display, BVOLUME);
  383. X        break;
  384. X
  385. X        case 'p':
  386. X        case 'P':
  387. X        if (beep)
  388. X            XBell(display, BVOLUME);
  389. X        paused = !paused;
  390. X        if (paused) {
  391. X            /* "... Hi boss, I'm working hard as usual ..." */
  392. X            banner(MSG_PAUSED);
  393. X            (void) XIconifyWindow(display, mainWin, screen_num);
  394. X        } else {
  395. X            clearNext();
  396. X            if (showNext)
  397. X            drawNext();
  398. X        }
  399. X        XSync(display, False);
  400. X        break;
  401. X
  402. X        case '\014':
  403. X        XClearWindow(display, mainWin);
  404. X        XClearWindow(display, blockWin);
  405. X        redrawAll();
  406. X        if (paused)
  407. X            banner(MSG_PAUSED);
  408. X        XSync(display, False);
  409. X        break;
  410. X
  411. X        case 'n':
  412. X        case 'N':
  413. X        if (!paused) {
  414. X            showNext = !showNext;
  415. X            if (showNext) {
  416. X            drawNext();
  417. X            } else {
  418. X            clearNext();
  419. X            }
  420. X            XSync(display, False);
  421. X        }
  422. X        break;
  423. X
  424. X        default:
  425. X        XBell(display, 0);
  426. X        XSync(display, False);
  427. X        break;
  428. X        }
  429. X
  430. X        break;
  431. X
  432. X    case UnmapNotify:
  433. X        paused = True;
  434. X        break;
  435. X
  436. X    case FocusOut:
  437. X        paused = True;
  438. X        banner(MSG_PAUSED);
  439. X        break;
  440. X
  441. X    case Expose:
  442. X        if (ev.xexpose.count == 0) {
  443. X        redrawAll();
  444. X        if (paused)
  445. X            banner(MSG_PAUSED);
  446. X        }
  447. X        break;
  448. X
  449. X    case ClientMessage:
  450. X        if ((Atom) ev.xclient.data.l[0] == delw)
  451. X        gameOver();
  452. X        break;
  453. X
  454. X    case DestroyNotify:
  455. X        exit(0);
  456. X        break;
  457. X    }
  458. X    }
  459. X
  460. X    XSync(display, False);
  461. X    return gotNew;
  462. X}
  463. X
  464. X/* ------------------------------------------------------------------ */
  465. X
  466. Xvoid
  467. XredrawAll()
  468. X{
  469. X    drawTitle();
  470. X    drawStatus();
  471. X    drawField();
  472. X    drawThing();
  473. X    if (showNext)
  474. X    drawNext();
  475. X}
  476. X
  477. X/* ------------------------------------------------------------------ */
  478. X
  479. XBool
  480. XmoveOne(move)
  481. X    move_t          move;
  482. X{
  483. X    XEvent          ev;
  484. X    int             lines;
  485. X
  486. X    if ((move == DROP) || ((move == FALL) && atBottom())) {
  487. X    tryMove(move);
  488. X    putBox();
  489. X    lines = checkLines();
  490. X    score += prefilled * prefilled + lines + 1;
  491. X    score += (showNext ? 3 : 5) * level * level * lines * lines;
  492. X    rows += lines;
  493. X    if (rows > thresh[level])
  494. X        level ++;
  495. X    drawStatus();
  496. X    newThing();
  497. X    if (showNext) {
  498. X        clearNext();
  499. X        drawNext();
  500. X    }
  501. X    XSync(display, False);
  502. X    while (XPending(display))
  503. X        XNextEvent(display, &ev);
  504. X    if (overlapping())
  505. X        gameOver();
  506. X    drawThing();
  507. X    return True;
  508. X    } else {
  509. X    tryMove(move);
  510. X    if (rows > thresh[level]) {
  511. X        level ++;
  512. X        drawStatus();
  513. X    }
  514. X    return False;
  515. X    }
  516. X}
  517. X
  518. X/* ------------------------------------------------------------------ */
  519. X
  520. Xstatic void
  521. XaddScore()
  522. X{
  523. X    time_t          tloc;
  524. X    char            buff[2][SCORESIZE];
  525. X    char            lockfile[FILENAMELEN];
  526. X    int             fd, lfd;
  527. X    int             tmp, ptmp, s1;
  528. X    int             mycount = 0;
  529. X    Bool            saved = False, trickle = False;
  530. X
  531. X    time(&tloc);
  532. X    (void) strcpy(myscore.mydate, asctime(localtime(&tloc)));
  533. X    (void) sprintf(myscore.score, "%9d", score);
  534. X    (void) sprintf(myscore.level, "%3d", level);
  535. X    (void) sprintf(myscore.rows, "%4d", rows);
  536. X
  537. X    (void) fprintf(stderr, "\n- %s", myscore.mydate);
  538. X    (void) fprintf(stderr, "- Your final score is %d,", score);
  539. X    (void) fprintf(stderr, " at level %d with %d rows.\n\n", level, rows);
  540. X
  541. X    if ((fd = open(SCOREFILE, O_CREAT | O_RDWR, 0644)) < 0) {
  542. X    (void) fprintf(stderr, "Cannot write the score-file!\n");
  543. X    return;
  544. X    }
  545. X
  546. X    /* lock */
  547. X    (void) strcpy(lockfile, SCOREFILE);
  548. X    (void) strcat(lockfile, ".lock");
  549. X    while (((lfd = open(lockfile, O_CREAT | O_EXCL, 0644)) < 0) &&
  550. X        errno == EEXIST)
  551. X    sleep(1);
  552. X
  553. X    if (lfd < 0) {
  554. X    (void) perror("Error in creating the score-file lock-file");
  555. X    (void) fprintf(stderr, "Score not recorded - sorry.\n");
  556. X    return;
  557. X    }
  558. X
  559. X    tmp = 0;
  560. X    ptmp = 1;
  561. X    bcopy((char *) &myscore, buff[1], SCORESIZE);
  562. X
  563. X    while (read(fd, buff[tmp], SCORESIZE) == SCORESIZE) {
  564. X    sscanf(((score_t *)buff[tmp])->score, " %d", &s1);
  565. X    if (!saved && (s1 <= score)) {
  566. X        trickle = True;
  567. X        saved = True;
  568. X        mycount++;
  569. X    }
  570. X    if (!strncmp(myscore.myname, ((score_t *) buff[tmp])->myname,
  571. X        NAMELEN)) {
  572. X        mycount++;
  573. X    }
  574. X    /* Then check if we should trickle the score */
  575. X    if (trickle) {
  576. X        lseek(fd, (off_t) -SCORESIZE, SEEK_CUR);
  577. X        write(fd, buff[ptmp], SCORESIZE);
  578. X        ptmp = tmp;
  579. X        tmp = (tmp + 1) % 2;
  580. X    }
  581. X    /*
  582. X     * As we trickle, we add up records owned by me. Once we hit max,
  583. X     * we throw it away, and stop trickling.
  584. X     */
  585. X    if ((mycount > MAXSCORES) || ((mycount == MAXSCORES) && !trickle)) {
  586. X        trickle = False;
  587. X        break;
  588. X    }
  589. X    }    /* while */
  590. X
  591. X    if (trickle) {
  592. X    write(fd, buff[ptmp], SCORESIZE);
  593. X    }
  594. X    if (!saved && (mycount < MAXSCORES)) {
  595. X    write(fd, (char *) &myscore, SCORESIZE);
  596. X    }
  597. X
  598. X    /* unlock */
  599. X    close(lfd);
  600. X    (void) unlink(lockfile);
  601. X    close(fd);
  602. X}
  603. X
  604. X/* ------------------------------------------------------------------ */
  605. X
  606. Xvoid
  607. XgameOver()
  608. X{
  609. X    banner(MSG_END);
  610. X    XFlush(display);
  611. X    addScore();
  612. X    showScores(SHOWSCORES);
  613. X    XCloseDisplay(display);
  614. X    exit(0);
  615. X}
  616. X
  617. X/* ------------------------------------------------------------------ */
  618. X
  619. Xvoid
  620. XshowScores(num)
  621. X    int             num;
  622. X{
  623. X    int             fd, i = 0;
  624. X    score_t         curs;
  625. X
  626. X    if ((fd = open(SCOREFILE, O_RDONLY, 0644)) < 0)
  627. X    return;
  628. X
  629. X    (void) fprintf(stderr, "            GENERIC TETRIS  HALL OF FAME\n\n");
  630. X    (void) fprintf(stderr,
  631. X    "   # USER            SCORE   L    R  HOST         DATE\n");
  632. X
  633. X    while (read(fd, (char *) &curs, SCORESIZE) == SCORESIZE) {
  634. X    i++;
  635. X    if ((num == 0) || (i <= num))
  636. X        (void) fprintf(stderr, "%4d %-12s%9s %3s %4s  %-12s %-s",
  637. X        i, curs.myname, curs.score, curs.level, curs.rows,
  638. X        curs.myhost, curs.mydate);
  639. X    }
  640. X    close(fd);
  641. X    (void) fprintf(stderr, "There are %d scores to date.\n", i);
  642. X}
  643. X
  644. X/* ------------------------------------------------------------------ */
  645. END_OF_FILE
  646. if test 9187 -ne `wc -c <'playing.c'`; then
  647.     echo shar: \"'playing.c'\" unpacked with wrong size!
  648. fi
  649. # end of 'playing.c'
  650. fi
  651. if test -f 'tetris.c' -a "${1}" != "-c" ; then 
  652.   echo shar: Will not clobber existing file \"'tetris.c'\"
  653. else
  654. echo shar: Extracting \"'tetris.c'\" \(11770 characters\)
  655. sed "s/^X//" >'tetris.c' <<'END_OF_FILE'
  656. X/*
  657. X# GENERIC X-WINDOW-BASED TETRIS
  658. X#
  659. X#    tetris.c
  660. X#
  661. X###
  662. X#
  663. X#  Copyright (C) 1992, 1993     Qiang Alex Zhao, azhao@cs.arizona.edu
  664. X#        Computer Science Dept, University of Arizona
  665. X#
  666. X#            All Rights Reserved
  667. X#
  668. X#  Permission to use, copy, modify, and distribute this software and
  669. X#  its documentation for any purpose and without fee is hereby granted,
  670. X#  provided that the above copyright notice appear in all copies and
  671. X#  that both that copyright notice and this permission notice appear in
  672. X#  supporting documentation, and that the name of the author not be
  673. X#  used in advertising or publicity pertaining to distribution of the
  674. X#  software without specific, written prior permission.
  675. X#
  676. X#  This program is distributed in the hope that it will be "playable",
  677. X#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  678. X#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  679. X#
  680. X*/
  681. X
  682. X#include "tetris.h"
  683. X
  684. X/*** variables ***/
  685. X
  686. Xchar            myDisplayName[256];
  687. XDisplay        *display;
  688. Xint             screen_num;
  689. XVisual         *visual;
  690. XBool            useColor = True;
  691. XColormap        colormap;
  692. XWindow          mainWin, blockWin;
  693. XCursor          theCursor;
  694. XXFontStruct    *bigFont, *tinyFont;
  695. Xunsigned long   fg, bg;
  696. X
  697. XXSizeHints      sizehints = {
  698. X    PMinSize | PMaxSize | PPosition | PSize | USSize,
  699. X    0, 0,            /* x, y */
  700. X    0, 0,            /* w, h */
  701. X    0, 0,            /* min w, min h */
  702. X    0, 0,            /* max w, max h */
  703. X    0, 0,            /* inc, not set */
  704. X    0, 0, 0, 0            /* aspect ratio, not set */
  705. X};
  706. XXSizeHints      iconsizehints = {
  707. X    PPosition | PSize,
  708. X    0, 0,            /* x, y */
  709. X    48, 48,            /* w, h */
  710. X    0, 0,            /* min w, min h */
  711. X    0, 0,            /* max w, max h */
  712. X    0, 0,            /* inc, not set */
  713. X    0, 0, 0, 0            /* aspect ratio, not set */
  714. X};
  715. XXWMHints        wmhints = {
  716. X    InputHint | StateHint | IconPixmapHint,
  717. X    True,            /* input mode */
  718. X    NormalState,        /* normal */
  719. X    0,                /* icon pixmap */
  720. X    0,                /* icon window */
  721. X    0, 0,            /* icon position */
  722. X    0                /* icon mask pixmap - not used */
  723. X};
  724. X
  725. Xchar            myHome[FILENAMELEN];
  726. Xint             level = 3, prefilled = 0, score = 0, rows = 0;
  727. XBool            showNext = False, beep = False;
  728. Xscore_t         myscore;
  729. X
  730. Xstatic int      opTableEntries = 15;
  731. Xstatic XrmOptionDescRec opTable[] = {
  732. X    {"-s", ".scoresOnly", XrmoptionIsArg, (caddr_t) NULL},
  733. X    {"-l", "*startLevel", XrmoptionSepArg, (caddr_t) NULL},
  734. X    {"-p", "*preFilledLines", XrmoptionSepArg, (caddr_t) NULL},
  735. X    {"-showNext", "*showNext", XrmoptionNoArg, (caddr_t) "on"},
  736. X    {"-beep", "*beep", XrmoptionNoArg, (caddr_t) "on"},
  737. X    {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
  738. X    {"-geometry", "*geometry", XrmoptionSepArg, (caddr_t) NULL},
  739. X    {"-iconGeometry", "*iconGeometry", XrmoptionSepArg, (caddr_t) NULL},
  740. X    {"-background", "*background", XrmoptionSepArg, (caddr_t) NULL},
  741. X    {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL},
  742. X    {"-foreground", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
  743. X    {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL},
  744. X    {"-bigFont", "*bigFont", XrmoptionSepArg, (caddr_t) NULL},
  745. X    {"-tinyFont", "*tinyFont", XrmoptionSepArg, (caddr_t) NULL},
  746. X    {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}
  747. X};
  748. Xstatic XrmDatabase cmmDB = (XrmDatabase) NULL, rDB = (XrmDatabase) NULL;
  749. X
  750. Xstatic void parseOpenDisp();
  751. Xstatic void Usage();
  752. Xstatic void getDefaults();
  753. X
  754. X/* ------------------------------------------------------------------ */
  755. X
  756. Xvoid
  757. Xmain(argc, argv)
  758. X    int             argc;
  759. X    char           *argv[];
  760. X{
  761. X    (void) fprintf(stderr,
  762. X           "                 GENERIC TETRIS V2.0.1\n");
  763. X    (void) fprintf(stderr,
  764. X     "Copyright (C) 1992-93      Q. Alex Zhao, azhao@cs.arizona.edu\n");
  765. X    (void) fprintf(stderr,
  766. X         "       Computer Science Dept, University of Arizona\n\n");
  767. X    (void) fprintf(stderr,
  768. X           "GENERIC TETRIS comes with ABSOLUTELY NO WARRANTY.\n\n");
  769. X
  770. X    parseOpenDisp(&argc, argv);
  771. X    getDefaults();
  772. X    inits(argc, argv);
  773. X    playing();
  774. X    /* never come to here */
  775. X}
  776. X
  777. X/* ------------------------------------------------------------------ */
  778. X
  779. Xstatic void
  780. XparseOpenDisp(argc, argv)
  781. X    int            *argc;
  782. X    char           *argv[];
  783. X{
  784. X    struct passwd  *pw;
  785. X    XrmValue        value;
  786. X    char           *str_type[20];
  787. X    XVisualInfo     vtmp, *vinfo;
  788. X    int             n = 1;
  789. X
  790. X    XrmInitialize();
  791. X
  792. X    myDisplayName[0] = '\0';
  793. X
  794. X    XrmParseCommand(&cmmDB, opTable, opTableEntries, argv[0], argc, argv);
  795. X
  796. X    /* check for any arguments left */
  797. X    if (*argc != 1) {
  798. X    Usage(argv[0]);
  799. X    }
  800. X    /* only print out the scores? */
  801. X    if (XrmGetResource(cmmDB, "tetris.scoresOnly", "Tetris.ScoresOnly",
  802. X               str_type, &value) == True) {
  803. X    showScores(0);
  804. X    exit(0);
  805. X    }
  806. X    /* get display now */
  807. X    if (XrmGetResource(cmmDB, "tetris.display", "Tetris.Display",
  808. X               str_type, &value) == True)
  809. X    (void) strncpy(myDisplayName, value.addr, (int) value.size);
  810. X
  811. X    if (!(display = XOpenDisplay(myDisplayName))) {
  812. X    (void) fprintf(stderr, "%s: Can't open display '%s'\n",
  813. X               argv[0], XDisplayName(myDisplayName));
  814. X    exit(1);
  815. X    }
  816. X    screen_num = DefaultScreen(display);
  817. X    visual = DefaultVisual(display, screen_num);
  818. X    colormap = DefaultColormap(display, screen_num);
  819. X    vtmp.visualid = XVisualIDFromVisual(visual);
  820. X    if ((vinfo = XGetVisualInfo(display, VisualIDMask, &vtmp, &n)) != NULL) {
  821. X    if ((vinfo->class == GrayScale) || (vinfo->class == StaticGray)) {
  822. X        useColor = False;
  823. X    }
  824. X    XFree((unsigned char *) vinfo);
  825. X    } else {
  826. X    useColor = False;
  827. X    }
  828. X
  829. X    /* setup user information */
  830. X    (void) gethostname(myscore.myhost, NAMELEN);
  831. X    setpwent();
  832. X    pw = getpwuid(getuid());
  833. X    endpwent();
  834. X    if (pw == NULL) {        /* impossible? */
  835. X    (void) sprintf(myscore.myname, "%d", getuid());
  836. X    myHome[0] = '.';
  837. X    myHome[1] = '/';
  838. X    myHome[2] = '\0';
  839. X    } else {
  840. X    (void) strncpy(myscore.myname, pw->pw_name, NAMELEN);
  841. X    (void) strncpy(myHome, pw->pw_dir, FILENAMELEN);
  842. X    }
  843. X    myscore.myname[NAMELEN - 1] = '\0';
  844. X    myscore.myhost[NAMELEN - 1] = '\0';
  845. X    myHome[FILENAMELEN - 1] = '\0';
  846. X}
  847. X
  848. X/* ------------------------------------------------------------------ */
  849. X
  850. Xstatic void
  851. XUsage(argv0)
  852. X    char           *argv0;
  853. X{
  854. X    (void) fprintf(stderr,
  855. X    "Usage: %s [-s] [-l <starting level>] [-p <prefilled rows>]\n", argv0);
  856. X    (void) fprintf(stderr,
  857. X    "   [-display <display>] [-geometry <geometry>] [-iconGeometry\n");
  858. X    (void) fprintf(stderr,
  859. X    "   <icon geometry>] [-fg <foreground>] [-bg <background>]\n");
  860. X    (void) fprintf(stderr,
  861. X    "   [-bigFont <font>] [-tinyFont <font>] [-showNext] [-beep]\n");
  862. X    (void) fprintf(stderr,
  863. X    "   [-xrm <resource specifications>]\n");
  864. X
  865. X    exit(1);
  866. X}
  867. X
  868. X/* ------------------------------------------------------------------ */
  869. X
  870. Xstatic void
  871. XgetDefaults()
  872. X{
  873. X    XrmDatabase     homeDB, serverDB, appDB;
  874. X    char            filenamebuf[FILENAMELEN];
  875. X    char           *filename = &filenamebuf[0];
  876. X    char           *env;
  877. X    char           *classname = "Tetris";
  878. X    char            name[255], geoStr[20], icongeoStr[20];
  879. X    XrmValue        value;
  880. X    char           *str_type[20];
  881. X    int             x, y;
  882. X    unsigned int    w, h;
  883. X    long            flags;
  884. X
  885. X    (void) strcpy(name, "/usr/lib/X11/app-defaults/");
  886. X    (void) strcat(name, classname);
  887. X
  888. X    /* Get application defaults file, if any */
  889. X    appDB = XrmGetFileDatabase(name);
  890. X    (void) XrmMergeDatabases(appDB, &rDB);
  891. X
  892. X    if (XResourceManagerString(display) != NULL) {
  893. X    serverDB = XrmGetStringDatabase(XResourceManagerString(display));
  894. X    } else {
  895. X    (void) strcpy(filename, myHome);
  896. X    (void) strcat(filename, "/.Xdefaults");
  897. X    serverDB = XrmGetFileDatabase(filename);
  898. X    }
  899. X    XrmMergeDatabases(serverDB, &rDB);
  900. X
  901. X    if ((env = getenv("XENVIRONMENT")) == NULL) {
  902. X    int             len;
  903. X
  904. X    env = &filenamebuf[0];
  905. X    (void) strcpy(env, myHome);
  906. X    len = strlen(env);
  907. X    (void) gethostname(env + len, FILENAMELEN - len);
  908. X    }
  909. X    homeDB = XrmGetFileDatabase(env);
  910. X    XrmMergeDatabases(homeDB, &rDB);
  911. X
  912. X    XrmMergeDatabases(cmmDB, &rDB);
  913. X
  914. X    /* starting levels */
  915. X
  916. X    if (XrmGetResource(cmmDB, "tetris.startLevel", "Tetris.StartLevel",
  917. X               str_type, &value) == True) {
  918. X    if ((sscanf(value.addr, "%d", &level) <= 0) ||
  919. X        (level < 0) || (level >= NUM_LEVELS)) {
  920. X        (void) fprintf(stderr, "Tetris: Invalid level.\n");
  921. X        exit(1);
  922. X    }
  923. X    }
  924. X
  925. X    /* prefilled lines */
  926. X
  927. X    if (XrmGetResource(cmmDB, "tetris.preFilledLines", "Tetris.PreFilledLines",
  928. X               str_type, &value) == True) {
  929. X    if ((sscanf(value.addr, "%d", &prefilled) <= 0) ||
  930. X        (prefilled < 0) || (prefilled >= ROWS - THINGSIZE)) {
  931. X        (void) fprintf(stderr, "Tetris: Invalid prefilled lines.\n");
  932. X        exit(1);
  933. X    }
  934. X    }
  935. X
  936. X    /* show next */
  937. X
  938. X    if (XrmGetResource(cmmDB, "tetris.showNext", "Tetris.ShowNext",
  939. X            str_type, &value) == True) {
  940. X    showNext = True;
  941. X    }
  942. X
  943. X    /* beep */
  944. X
  945. X    if (XrmGetResource(cmmDB, "tetris.beep", "Tetris.Beep",
  946. X            str_type, &value) == True) {
  947. X    beep = True;
  948. X    }
  949. X
  950. X    /*** get foreground/background colors ***/
  951. X
  952. X    if (XrmGetResource(rDB, "tetris.foreground", "Tetris.Foreground",
  953. X               str_type, &value) == True) {
  954. X    (void) strncpy(name, value.addr, (int) value.size);
  955. X    fg = getColor(name);
  956. X    } else
  957. X    fg = BlackPixel(display, screen_num);
  958. X
  959. X    if (XrmGetResource(rDB, "tetris.background", "Tetris.Background",
  960. X               str_type, &value) == True) {
  961. X    (void) strncpy(name, value.addr, (int) value.size);
  962. X    bg = getColor(name);
  963. X    } else
  964. X    bg = WhitePixel(display, screen_num);
  965. X
  966. X    if (bg == fg) {
  967. X    bg = WhitePixel(display, screen_num);
  968. X    fg = BlackPixel(display, screen_num);
  969. X    }
  970. X
  971. X    /*** get geometry info ***/
  972. X
  973. X    if (XrmGetResource(rDB, "tetris.geometry", "Tetris.Geometry",
  974. X               str_type, &value) == True) {
  975. X    (void) strncpy(geoStr, value.addr, (int) value.size);
  976. X    } else {
  977. X    geoStr[0] = '\0';
  978. X    }
  979. X
  980. X    flags = XParseGeometry(geoStr, &x, &y, &w, &h);
  981. X    if ((WidthValue | HeightValue) & flags)
  982. X    Usage("tetris");
  983. X
  984. X    if (XValue & flags) {
  985. X    if (XNegative & flags)
  986. X        x = DisplayWidth(display, screen_num) + x - sizehints.width;
  987. X    sizehints.x = x;
  988. X    }
  989. X    if (YValue & flags) {
  990. X    if (YNegative & flags)
  991. X        y = DisplayHeight(display, screen_num) + y - sizehints.height;
  992. X    sizehints.y = y;
  993. X    }
  994. X
  995. X    /*** get icon geometry info ***/
  996. X
  997. X    if (XrmGetResource(rDB, "tetris.iconGeometry", "Tetris.IconGeometry",
  998. X               str_type, &value) == True) {
  999. X    (void) strncpy(icongeoStr, value.addr, (int) value.size);
  1000. X    } else {
  1001. X    icongeoStr[0] = '\0';
  1002. X    }
  1003. X
  1004. X    flags = XParseGeometry(icongeoStr, &x, &y, &w, &h);
  1005. X    if ((WidthValue | HeightValue) & flags)
  1006. X    Usage("tetris");
  1007. X
  1008. X    if (XValue & flags) {
  1009. X    if (XNegative & flags)
  1010. X        x = DisplayWidth(display, screen_num) + x - iconsizehints.width;
  1011. X    wmhints.flags |= IconPositionHint;
  1012. X    wmhints.icon_x = x;
  1013. X    iconsizehints.x = x;
  1014. X    }
  1015. X    if (YValue & flags) {
  1016. X    if (YNegative & flags)
  1017. X        y = DisplayHeight(display, screen_num) + y - iconsizehints.height;
  1018. X    wmhints.flags |= IconPositionHint;
  1019. X    wmhints.icon_y = y;
  1020. X    iconsizehints.y = y;
  1021. X    }
  1022. X
  1023. X    /*** get fonts ***/
  1024. X
  1025. X    if (XrmGetResource(rDB, "tetris.bigFont", "tetris.BigFont",
  1026. X               str_type, &value) == True) {
  1027. X    (void) strncpy(name, value.addr, (int) value.size);
  1028. X    } else {
  1029. X    (void) strcpy(name, BIGFONT);
  1030. X    }
  1031. X    if ((bigFont = XLoadQueryFont(display, name)) == NULL) {
  1032. X    (void) fprintf(stderr, "Tetris: can't open font '%s'.\n", name);
  1033. X    exit(1);
  1034. X    }
  1035. X    if (XrmGetResource(rDB, "tetris.tinyFont", "tetris.TinyFont",
  1036. X               str_type, &value) == True) {
  1037. X    (void) strncpy(name, value.addr, (int) value.size);
  1038. X    } else {
  1039. X    (void) strcpy(name, TINYFONT);
  1040. X    }
  1041. X    if ((tinyFont = XLoadQueryFont(display, name)) == NULL) {
  1042. X    (void) fprintf(stderr, "Tetris: can't open font '%s'.\n", name);
  1043. X    exit(1);
  1044. X    }
  1045. X
  1046. X    /*
  1047. X     * clean up
  1048. X     */
  1049. X    XrmDestroyDatabase(rDB);
  1050. X}
  1051. X
  1052. X/* ------------------------------------------------------------------ */
  1053. END_OF_FILE
  1054. if test 11770 -ne `wc -c <'tetris.c'`; then
  1055.     echo shar: \"'tetris.c'\" unpacked with wrong size!
  1056. fi
  1057. # end of 'tetris.c'
  1058. fi
  1059. if test -f 'tetris.h' -a "${1}" != "-c" ; then 
  1060.   echo shar: Will not clobber existing file \"'tetris.h'\"
  1061. else
  1062. echo shar: Extracting \"'tetris.h'\" \(4561 characters\)
  1063. sed "s/^X//" >'tetris.h' <<'END_OF_FILE'
  1064. X/*
  1065. X# GENERIC X-WINDOW-BASED TETRIS
  1066. X#
  1067. X#    tetris.h
  1068. X#
  1069. X###
  1070. X#
  1071. X#  Copyright (C) 1992, 1993     Qiang Alex Zhao, azhao@cs.arizona.edu
  1072. X#        Computer Science Dept, University of Arizona
  1073. X#
  1074. X#            All Rights Reserved
  1075. X#
  1076. X#  Permission to use, copy, modify, and distribute this software and
  1077. X#  its documentation for any purpose and without fee is hereby granted,
  1078. X#  provided that the above copyright notice appear in all copies and
  1079. X#  that both that copyright notice and this permission notice appear in
  1080. X#  supporting documentation, and that the name of the author not be
  1081. X#  used in advertising or publicity pertaining to distribution of the
  1082. X#  software without specific, written prior permission.
  1083. X#
  1084. X#  This program is distributed in the hope that it will be "playable",
  1085. X#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  1086. X#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  1087. X#
  1088. X*/
  1089. X
  1090. X/*** Common headers ***/
  1091. X
  1092. X#include    <stdio.h>
  1093. X#include    <math.h>
  1094. X#include    <pwd.h>
  1095. X#include    <errno.h>
  1096. X
  1097. X#include    <X11/Xlib.h>
  1098. X#include    <X11/Xutil.h>
  1099. X#include    <X11/Xresource.h>
  1100. X#include    <X11/cursorfont.h>
  1101. X#include    <X11/keysym.h>
  1102. X#include    <X11/Xos.h>
  1103. X#include    <X11/Xfuncs.h>
  1104. X#include    <X11/Xfuncproto.h>
  1105. X
  1106. X#ifndef    X_NOT_STDC_ENV
  1107. X#include    <stdlib.h>
  1108. X#else
  1109. Xextern char    *getenv(
  1110. X#if    NeedFunctionPrototypes
  1111. X    char *
  1112. X#endif
  1113. X);
  1114. X#endif
  1115. X
  1116. X#ifdef    X_NOT_POSIX
  1117. Xextern int      getuid(
  1118. X#if    NeedFunctionPrototypes
  1119. X    void
  1120. X#endif
  1121. X);
  1122. Xextern struct passwd *getpwuid(
  1123. X#if    NeedFunctionPrototypes
  1124. X    int
  1125. X#endif
  1126. X);
  1127. X#endif
  1128. X
  1129. X#ifdef    _AIX
  1130. X#include    <sys/select.h>
  1131. X#endif
  1132. X
  1133. X/*** for lseek ***/
  1134. X
  1135. X#ifndef    SEEK_SET
  1136. X#define    SEEK_SET    L_SET
  1137. X#endif
  1138. X
  1139. X#ifndef    SEEK_CUR
  1140. X#define    SEEK_CUR    L_INCR
  1141. X#endif
  1142. X
  1143. X#ifndef    SEEK_END
  1144. X#define    SEEK_END    L_XTND
  1145. X#endif
  1146. X
  1147. X/*** random generator ***/
  1148. X
  1149. X#if    defined(HAS_48)        /* Use lrand48() and srand48() */
  1150. X#define    LRAND()        lrand48()
  1151. X#define    SRAND(X)    srand48((long) (X))
  1152. Xextern long     lrand48(
  1153. X#if    NeedFunctionPrototypes
  1154. X    void
  1155. X#endif
  1156. X);
  1157. X
  1158. X#else
  1159. X#if    defined(HAS_RANDOM)    /* Use random() and srandom() */
  1160. X
  1161. X#define    LRAND()        random()
  1162. X#define    SRAND(X)    srandom((unsigned int) (X))
  1163. Xextern long     random(
  1164. X#if    NeedFunctionPrototypes
  1165. X    void
  1166. X#endif
  1167. X);
  1168. X
  1169. X#else                /* Use rand() and srand() */
  1170. X
  1171. X#define    LRAND()        ((long) rand())
  1172. X#define    SRAND(X)    srand(X)
  1173. X
  1174. X#endif
  1175. X#endif
  1176. X
  1177. X/*** constants ***/
  1178. X
  1179. X#ifndef    SCOREFILE
  1180. X#define    SCOREFILE    "/usr/games/lib/tetris.scores"
  1181. X#endif
  1182. X
  1183. X#define    BIGFONT        "12x24"
  1184. X#define    TINYFONT    "6x12"
  1185. X#define    BVOLUME        -90
  1186. X#define NUM_FLASHES    16
  1187. X
  1188. X#define    MILLION        1000000
  1189. X#define    MAXSCORES    3
  1190. X#define    SHOWSCORES    15
  1191. X#define    NAMELEN        12
  1192. X#define    FILENAMELEN    1024
  1193. X
  1194. X#define    MSG_PAUSED    "PAUSED"
  1195. X#define    MSG_END        "GAME OVER"
  1196. X#define    MSG_TITLE    "TETRIS"
  1197. X#define    MSG_AUTHOR    "by Qiang Alex Zhao"
  1198. X
  1199. X#define    NUM_LEVELS    18
  1200. X#define    ROWS        20
  1201. X#define    COLS        10
  1202. X
  1203. X#define    BOXSIZE        30
  1204. X#define    OFFSET        20
  1205. X#define    THINGSIZE    4
  1206. X#define    NUM_THINGS    7
  1207. X#define NUM_BITMAPS    15
  1208. X
  1209. X/*** types ***/
  1210. X
  1211. Xtypedef enum {FALL, DROP, ROTATE, LEFT, RIGHT} move_t;
  1212. X
  1213. Xtypedef struct {
  1214. X    char            myname[NAMELEN], myhost[NAMELEN], mydate[27];
  1215. X    char            score[10];
  1216. X    char            level[4];
  1217. X    char            rows[5];
  1218. X}               score_t;
  1219. X#define    SCORESIZE    sizeof(score_t)
  1220. X
  1221. Xtypedef struct {
  1222. X    int             map[THINGSIZE][THINGSIZE];
  1223. X    int             xpos, ypos;
  1224. X    int             size, px, py;
  1225. X}               thing_t;
  1226. X
  1227. X/*** variables defined in "tetris.c" ***/
  1228. X
  1229. Xextern Display *display;
  1230. Xextern int      screen_num;
  1231. Xextern Visual  *visual;
  1232. Xextern Bool     useColor;
  1233. Xextern Colormap colormap;
  1234. Xextern Window   mainWin, blockWin;
  1235. Xextern Cursor   theCursor;
  1236. Xextern XFontStruct *bigFont, *tinyFont;
  1237. Xextern unsigned long fg, bg;
  1238. X
  1239. Xextern XSizeHints sizehints, iconsizehints;
  1240. Xextern XWMHints wmhints;
  1241. X
  1242. Xextern char     myHome[FILENAMELEN];
  1243. Xextern int      level, prefilled, score, rows;
  1244. Xextern Bool     showNext, beep;
  1245. Xextern score_t  myscore;
  1246. X
  1247. X/*** variables defined in "utils.c" ***/
  1248. X
  1249. Xextern Atom     delw;
  1250. X
  1251. X/*** variables defined in "playing.c" ***/
  1252. X
  1253. X/*** functions ***/
  1254. X
  1255. Xextern unsigned long getColor();
  1256. Xextern void     showScores();
  1257. Xextern void     inits();
  1258. Xextern void     playing();
  1259. Xextern void     realTime();
  1260. Xextern void     newThing();
  1261. Xextern Bool     evGotNewThing();
  1262. Xextern void     redrawAll();
  1263. Xextern void     drawTitle();
  1264. Xextern void     drawStatus();
  1265. Xextern void     drawField();
  1266. Xextern void     drawThing();
  1267. Xextern void     drawThingDiff();
  1268. Xextern void     drawNext();
  1269. Xextern void     gameOver();
  1270. Xextern void     banner();
  1271. Xextern void     clearNext();
  1272. Xextern void     putBox();
  1273. Xextern void     tryMove();
  1274. Xextern Bool     atBottom();
  1275. Xextern Bool     overlapping();
  1276. Xextern int      checkLines();
  1277. X
  1278. END_OF_FILE
  1279. if test 4561 -ne `wc -c <'tetris.h'`; then
  1280.     echo shar: \"'tetris.h'\" unpacked with wrong size!
  1281. fi
  1282. # end of 'tetris.h'
  1283. fi
  1284. if test -f 'utils.c' -a "${1}" != "-c" ; then 
  1285.   echo shar: Will not clobber existing file \"'utils.c'\"
  1286. else
  1287. echo shar: Extracting \"'utils.c'\" \(18011 characters\)
  1288. sed "s/^X//" >'utils.c' <<'END_OF_FILE'
  1289. X/*
  1290. X# GENERIC X-WINDOW-BASED TETRIS
  1291. X#
  1292. X#    utils.c
  1293. X#
  1294. X###
  1295. X#
  1296. X#  Copyright (C) 1992, 1993     Qiang Alex Zhao, azhao@cs.arizona.edu
  1297. X#        Computer Science Dept, University of Arizona
  1298. X#
  1299. X#            All Rights Reserved
  1300. X#
  1301. X#  Permission to use, copy, modify, and distribute this software and
  1302. X#  its documentation for any purpose and without fee is hereby granted,
  1303. X#  provided that the above copyright notice appear in all copies and
  1304. X#  that both that copyright notice and this permission notice appear in
  1305. X#  supporting documentation, and that the name of the author not be
  1306. X#  used in advertising or publicity pertaining to distribution of the
  1307. X#  software without specific, written prior permission.
  1308. X#
  1309. X#  This program is distributed in the hope that it will be "playable",
  1310. X#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  1311. X#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  1312. X#
  1313. X*/
  1314. X
  1315. X#include    "tetris.h"
  1316. X
  1317. X#include    "bitmaps/ticon.xbm"
  1318. X#include    "bitmaps/rot00.xbm"
  1319. X#include    "bitmaps/rot01.xbm"
  1320. X#include    "bitmaps/rot02.xbm"
  1321. X#include    "bitmaps/rot03.xbm"
  1322. X#include    "bitmaps/rot04.xbm"
  1323. X#include    "bitmaps/rot05.xbm"
  1324. X#include    "bitmaps/rot06.xbm"
  1325. X#include    "bitmaps/rot07.xbm"
  1326. X#include    "bitmaps/rot08.xbm"
  1327. X#include    "bitmaps/rot09.xbm"
  1328. X#include    "bitmaps/rot10.xbm"
  1329. X#include    "bitmaps/rot11.xbm"
  1330. X#include    "bitmaps/rot12.xbm"
  1331. X#include    "bitmaps/rot13.xbm"
  1332. X#include    "bitmaps/rot14.xbm"
  1333. X
  1334. XAtom            delw;
  1335. X
  1336. Xstatic GC       revGC, bigGC, tinyGC, xorGC;
  1337. Xstatic GC       thingGCs[NUM_THINGS];
  1338. X
  1339. Xstatic char    *winName = "GENERIC TETRIS";
  1340. Xstatic char    *iconName = "TETRIS";
  1341. X
  1342. Xstatic int      titleLen, titleWidth, authorLen, authorWidth;
  1343. Xstatic int      titleX, titleY, authorX, authorY;
  1344. Xstatic int      sX;
  1345. Xstatic int      sLevelY, sRowsY, sScoreY;
  1346. X
  1347. Xstatic int      topRWidth, topWidth, topHeight, topMidX, topMidY;
  1348. Xstatic int      frameX, frameY, frameW, frameH;
  1349. X
  1350. Xstatic char    *bitmap_data[NUM_BITMAPS] = {
  1351. X    rot00_bits, rot01_bits, rot02_bits, rot03_bits, rot04_bits, rot05_bits,
  1352. X    rot06_bits, rot07_bits, rot08_bits, rot09_bits, rot10_bits, rot11_bits,
  1353. X    rot12_bits, rot13_bits, rot14_bits
  1354. X};
  1355. X
  1356. Xstatic thing_t  possible[][4] = {
  1357. X    {
  1358. X    {{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 0},
  1359. X    {{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 1},
  1360. X    {{{0, 0, 0, 0}, {4, 5, 5, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 4, 0, 2},
  1361. X    {{{0, 2, 0, 0}, {0, 10, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}}, 0, 0, 4, 0, 3}
  1362. X    },
  1363. X
  1364. X    {
  1365. X    {{{0, 2, 0, 0}, {0, 10, 0, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 0},
  1366. X    {{{2, 0, 0, 0}, {12, 5, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 1},
  1367. X    {{{6, 1, 0, 0}, {10, 0, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 2},
  1368. X    {{{4, 5, 3, 0}, {0, 0, 8, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 1, 3}
  1369. X    },
  1370. X
  1371. X    {
  1372. X    {{{2, 0, 0, 0}, {10, 0, 0, 0}, {12, 1, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 0},
  1373. X    {{{6, 5, 1, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 1},
  1374. X    {{{4, 3, 0, 0}, {0, 10, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 2},
  1375. X    {{{0, 0, 2, 0}, {4, 5, 9, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 2, 3}
  1376. X    },
  1377. X
  1378. X    {
  1379. X    {{{0, 2, 0, 0}, {4, 11, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 0},
  1380. X    {{{0, 2, 0, 0}, {4, 13, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 1},
  1381. X    {{{2, 0, 0, 0}, {14, 1, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 2},
  1382. X    {{{4, 7, 1, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 3, 3}
  1383. X    },
  1384. X
  1385. X    {
  1386. X    {{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 0},
  1387. X    {{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 1},
  1388. X    {{{2, 0, 0, 0}, {12, 3, 0, 0}, {0, 8, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 2},
  1389. X    {{{0, 6, 1, 0}, {4, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 4, 3}
  1390. X    },
  1391. X
  1392. X    {
  1393. X    {{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 0},
  1394. X    {{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 1},
  1395. X    {{{0, 2, 0, 0}, {6, 9, 0, 0}, {8, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 2},
  1396. X    {{{4, 3, 0, 0}, {0, 12, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 3, 5, 3}
  1397. X    },
  1398. X
  1399. X    {
  1400. X    {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 0},
  1401. X    {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 1},
  1402. X    {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 2},
  1403. X    {{{6, 3, 0, 0}, {12, 9, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, 0, 0, 2, 6, 3}
  1404. X    }
  1405. X};
  1406. X
  1407. Xstatic char    *thingFGs[NUM_THINGS] = {
  1408. X    "Magenta", "ForestGreen", "Blue", "Red", "DarkTurquoise", "Black", "Brown"
  1409. X};
  1410. X
  1411. Xstatic Pixmap   pms[NUM_BITMAPS];
  1412. X
  1413. Xstatic thing_t  curThing, nextThing;
  1414. Xstatic struct {
  1415. X    int             pm_num, cid;
  1416. X}               field[ROWS][COLS];
  1417. X
  1418. X/* ------------------------------------------------------------------ */
  1419. X
  1420. Xstatic int
  1421. Xnrand(n)
  1422. X    int             n;
  1423. X{
  1424. X    return (int) (LRAND() % n);
  1425. X}
  1426. X
  1427. X/* ------------------------------------------------------------------ */
  1428. X
  1429. Xunsigned long
  1430. XgetColor(name)
  1431. X    char            name[];
  1432. X{
  1433. X    XColor          tmp;
  1434. X
  1435. X    if (!useColor) {
  1436. X    return BlackPixel(display, screen_num);
  1437. X    }
  1438. X    if (XParseColor(display, colormap, name, &tmp) == 0) {
  1439. X    (void) fprintf(stderr, "Tetris: invalid color '%s'.\n", name);
  1440. X    return BlackPixel(display, screen_num);
  1441. X    }
  1442. X    if (XAllocColor(display, colormap, &tmp) == 0) {
  1443. X    (void) fprintf(stderr, "Tetris: can't allocate color '%s'.\n", name);
  1444. X    return BlackPixel(display, screen_num);
  1445. X    }
  1446. X    return tmp.pixel;
  1447. X}
  1448. X
  1449. X/* ------------------------------------------------------------------ */
  1450. X
  1451. Xvoid
  1452. Xinits(argc, argv)
  1453. X    int             argc;
  1454. X    char           *argv[];
  1455. X{
  1456. X    XSetWindowAttributes att;
  1457. X    unsigned int    attvm;
  1458. X    XTextProperty   wName, iName;
  1459. X    XClassHint      classhints;
  1460. X    XEvent          ev;
  1461. X    XGCValues       gcv;
  1462. X    unsigned long   gcvm;
  1463. X    int             i, j;
  1464. X
  1465. X    SRAND(time(NULL));
  1466. X    for (i = 0; i < COLS; i++)
  1467. X    for (j = 0; j < ROWS; j++)
  1468. X        if ((j >= ROWS - prefilled) && (nrand(2) == 0)) {
  1469. X        field[j][i].pm_num = 0;
  1470. X        field[j][i].cid = nrand(NUM_THINGS);
  1471. X        } else {
  1472. X        field[j][i].pm_num = -1;
  1473. X        field[j][i].cid = 0;
  1474. X        }
  1475. X
  1476. X    titleLen = strlen(MSG_TITLE);
  1477. X    titleWidth = XTextWidth(bigFont, MSG_TITLE, titleLen);
  1478. X    authorLen = strlen(MSG_AUTHOR);
  1479. X    authorWidth = XTextWidth(tinyFont, MSG_AUTHOR, authorLen);
  1480. X
  1481. X    frameW = BOXSIZE * COLS;
  1482. X    frameH = BOXSIZE * ROWS;
  1483. X    topRWidth = BOXSIZE * THINGSIZE + OFFSET * 2;
  1484. X    topHeight = frameH + OFFSET * 2 + 4;
  1485. X    if (titleWidth > topRWidth)
  1486. X    topRWidth = titleWidth;
  1487. X    if (authorWidth > topRWidth)
  1488. X    topRWidth = authorWidth;
  1489. X    topMidX = frameW + OFFSET * 2 + 4;
  1490. X    topMidY = topHeight / 2 + bigFont->ascent;
  1491. X    topWidth = topMidX + topRWidth;
  1492. X    frameX = frameY = OFFSET + 2;
  1493. X
  1494. X    titleX = (topRWidth - titleWidth) / 2 + topMidX;
  1495. X    titleY = OFFSET + 2 + bigFont->ascent;
  1496. X    authorX = (topRWidth - authorWidth) / 2 + topMidX;
  1497. X    authorY = OFFSET + 2 + bigFont->ascent + bigFont->descent + tinyFont->ascent;
  1498. X
  1499. X    sX = topMidX + OFFSET;
  1500. X    sScoreY = topHeight - OFFSET - 2 - tinyFont->descent;
  1501. X    sRowsY = sScoreY - tinyFont->descent - tinyFont->ascent - 2;
  1502. X    sLevelY = sRowsY - tinyFont->descent - tinyFont->ascent - 2;
  1503. X
  1504. X    sizehints.width = (sizehints.min_width =
  1505. X    (sizehints.max_width = topWidth));
  1506. X    sizehints.height = (sizehints.min_height =
  1507. X    (sizehints.max_height = topHeight));
  1508. X
  1509. X    theCursor = XCreateFontCursor(display, XC_exchange);
  1510. X
  1511. X    /* arrow keys */
  1512. X    XRebindKeysym(display, XK_R10, NULL, 0,
  1513. X    (unsigned char *) "j", sizeof(unsigned char));
  1514. X    XRebindKeysym(display, XK_Left, NULL, 0,
  1515. X    (unsigned char *) "j", sizeof(unsigned char));
  1516. X    XRebindKeysym(display, XK_R11, NULL, 0,
  1517. X    (unsigned char *) "k", sizeof(unsigned char));
  1518. X    XRebindKeysym(display, XK_R12, NULL, 0,
  1519. X    (unsigned char *) "l", sizeof(unsigned char));
  1520. X    XRebindKeysym(display, XK_Right, NULL, 0,
  1521. X    (unsigned char *) "l", sizeof(unsigned char));
  1522. X
  1523. X    /* create windows */
  1524. X    attvm = CWBackPixel | CWEventMask | CWDontPropagate | CWCursor;
  1525. X    att.background_pixel = bg;
  1526. X    att.event_mask = ExposureMask | KeyPressMask |
  1527. X    StructureNotifyMask | FocusChangeMask;
  1528. X    att.do_not_propagate_mask = KeyReleaseMask |
  1529. X    ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
  1530. X    ButtonMotionMask | Button1MotionMask | Button2MotionMask |
  1531. X    Button3MotionMask | Button4MotionMask | Button5MotionMask;
  1532. X    att.cursor = theCursor;
  1533. X
  1534. X    mainWin = XCreateWindow(display, DefaultRootWindow(display),
  1535. X    sizehints.x, sizehints.y, topWidth, topHeight, 0,
  1536. X    CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
  1537. X
  1538. X    attvm = CWBackPixel | CWBorderPixel | CWEventMask;
  1539. X    att.border_pixel = fg;
  1540. X    att.event_mask = ExposureMask;
  1541. X
  1542. X    blockWin = XCreateWindow(display, mainWin,
  1543. X    frameX-2, frameY-2, frameW, frameH, 2,
  1544. X    CopyFromParent, InputOutput, CopyFromParent, attvm, &att);
  1545. X
  1546. X    /* WM hints */
  1547. X    XStringListToTextProperty(&winName, 1, &wName);
  1548. X    XStringListToTextProperty(&iconName, 1, &iName);
  1549. X
  1550. X    wmhints.icon_pixmap = XCreateBitmapFromData(display,
  1551. X    mainWin, ticon_bits, ticon_width, ticon_height);
  1552. X    classhints.res_name = "tetris";
  1553. X    classhints.res_class = "Tetris";
  1554. X
  1555. X    XSetWMProperties(display, mainWin, &wName, &iName,
  1556. X    argv, argc, &sizehints, &wmhints, &classhints);
  1557. X
  1558. X    delw = XInternAtom(display, "WM_DELETE_WINDOW", False);
  1559. X    XSetWMProtocols(display, mainWin, &delw, 1);
  1560. X
  1561. X    /* GC's */
  1562. X
  1563. X    gcvm = GCForeground | GCBackground | GCFunction |
  1564. X    GCFont | GCGraphicsExposures;
  1565. X
  1566. X    gcv.function = GXcopy;
  1567. X    gcv.foreground = fg;
  1568. X    gcv.background = bg;
  1569. X    gcv.font = bigFont->fid;
  1570. X    gcv.graphics_exposures = False;
  1571. X    bigGC = XCreateGC(display, mainWin, gcvm, &gcv);
  1572. X
  1573. X    gcv.font = tinyFont->fid;
  1574. X    tinyGC = XCreateGC(display, mainWin, gcvm, &gcv);
  1575. X
  1576. X    gcv.foreground = bg;
  1577. X    gcv.background = fg;
  1578. X    revGC = XCreateGC(display, mainWin, gcvm, &gcv);
  1579. X
  1580. X    gcv.background = bg;
  1581. X    for (i = 0; i < NUM_THINGS; i++) {
  1582. X    gcv.foreground = getColor(thingFGs[i]);
  1583. X    if (gcv.foreground == bg)
  1584. X        gcv.foreground = fg;
  1585. X    thingGCs[i] = XCreateGC(display, blockWin, gcvm, &gcv);
  1586. X    }
  1587. X
  1588. X    gcv.foreground = fg;
  1589. X    gcv.function = GXxor;
  1590. X    xorGC = XCreateGC(display, blockWin, gcvm, &gcv);
  1591. X
  1592. X    /* pixmaps */
  1593. X
  1594. X    for (i = 0; i < NUM_BITMAPS; i++) {
  1595. X    pms[i] = (Pixmap) XCreateBitmapFromData(display, blockWin,
  1596. X        bitmap_data[i], BOXSIZE, BOXSIZE);
  1597. X    }
  1598. X
  1599. X    /* new things */
  1600. X    newThing();
  1601. X    newThing();
  1602. X
  1603. X    /* the last thing is to wait for mapped */
  1604. X    XMapWindow(display, blockWin);
  1605. X    XMapRaised(display, mainWin);
  1606. X    XNextEvent(display, &ev);
  1607. X    sleep(1);
  1608. X}
  1609. X
  1610. X/* ------------------------------------------------------------------ */
  1611. X
  1612. Xvoid
  1613. XnewThing()
  1614. X{
  1615. X    curThing = nextThing;
  1616. X    nextThing = possible[nrand(NUM_THINGS)][nrand(4)];
  1617. X    nextThing.xpos = nrand(COLS - nextThing.size + 1);
  1618. X}
  1619. X
  1620. X/* ------------------------------------------------------------------ */
  1621. X
  1622. Xvoid
  1623. XdrawTitle()
  1624. X{
  1625. X    XDrawString(display, mainWin, bigGC,
  1626. X    titleX, titleY, MSG_TITLE, titleLen);
  1627. X    XDrawString(display, mainWin, tinyGC,
  1628. X    authorX, authorY, MSG_AUTHOR, authorLen);
  1629. X}
  1630. X
  1631. X/* ------------------------------------------------------------------ */
  1632. X
  1633. Xvoid
  1634. XdrawStatus()
  1635. X{
  1636. X    char            buf[30];
  1637. X
  1638. X    (void) sprintf(buf, "Score: %d", score);
  1639. X    XDrawImageString(display, mainWin, tinyGC, sX, sScoreY, buf, strlen(buf));
  1640. X
  1641. X    (void) sprintf(buf, "Level: %d    ", level);
  1642. X    XDrawImageString(display, mainWin, tinyGC, sX, sLevelY, buf, strlen(buf));
  1643. X
  1644. X    (void) sprintf(buf, "Rows: %d", rows);
  1645. X    XDrawImageString(display, mainWin, tinyGC, sX, sRowsY, buf, strlen(buf));
  1646. X}
  1647. X
  1648. X/* ------------------------------------------------------------------ */
  1649. X
  1650. Xstatic void
  1651. XdrawBox(win, pmid, cid, x, y)
  1652. X    Window          win;
  1653. X    int             pmid, cid, x, y;
  1654. X{
  1655. X    XCopyPlane(display, pms[pmid], win, thingGCs[cid], 0, 0,
  1656. X    BOXSIZE, BOXSIZE, x, y, (unsigned long) 1);
  1657. X}
  1658. X
  1659. X/* ------------------------------------------------------------------ */
  1660. X
  1661. Xstatic void
  1662. XclearBox(x, y)
  1663. X    int             x, y;
  1664. X{
  1665. X    XFillRectangle(display, blockWin, revGC, x, y, BOXSIZE, BOXSIZE);
  1666. X}
  1667. X
  1668. X/* ------------------------------------------------------------------ */
  1669. X
  1670. Xvoid
  1671. XdrawField()
  1672. X{
  1673. X    int             i, j;
  1674. X
  1675. X    for (i = 0; i < COLS; i++)
  1676. X    for (j = 0; j < ROWS; j++)
  1677. X        if (field[j][i].pm_num >= 0)
  1678. X        drawBox(blockWin, field[j][i].pm_num, field[j][i].cid,
  1679. X            i * BOXSIZE, j * BOXSIZE);
  1680. X}
  1681. X
  1682. X/* ------------------------------------------------------------------ */
  1683. X
  1684. Xvoid
  1685. XdrawThing()
  1686. X{
  1687. X    int             i, j;
  1688. X
  1689. X    for (i = 0; i < curThing.size; i++)
  1690. X    for (j = 0; j < curThing.size; j++)
  1691. X        if (curThing.map[j][i])
  1692. X        drawBox(blockWin, curThing.map[j][i], curThing.px,
  1693. X            (curThing.xpos + i) * BOXSIZE,
  1694. X            (curThing.ypos + j) * BOXSIZE);
  1695. X}
  1696. X
  1697. X/* ------------------------------------------------------------------ */
  1698. X
  1699. Xvoid
  1700. XdrawThingDiff(old)
  1701. X    thing_t        *old;
  1702. X{
  1703. X    int             i, j, ox, oy;
  1704. X
  1705. X    for (i = 0; i < curThing.size; i++)
  1706. X    for (j = 0; j < curThing.size; j++)
  1707. X        if (curThing.map[j][i])
  1708. X        drawBox(blockWin, curThing.map[j][i], curThing.px,
  1709. X            (curThing.xpos + i) * BOXSIZE,
  1710. X            (curThing.ypos + j) * BOXSIZE);
  1711. X
  1712. X    for (i = 0; i < curThing.size; i++)
  1713. X    for (j = 0; j < curThing.size; j++) {
  1714. X        ox = old->xpos + i - curThing.xpos;
  1715. X        oy = old->ypos + j - curThing.ypos;
  1716. X        if (old->map[j][i] && 
  1717. X            ((ox < 0) || (ox >= curThing.size) ||
  1718. X            (oy < 0) || (oy >= curThing.size) ||
  1719. X            !curThing.map[oy][ox]))
  1720. X        clearBox((old->xpos + i) * BOXSIZE, (old->ypos + j) * BOXSIZE);
  1721. X    }
  1722. X}
  1723. X
  1724. X/* ------------------------------------------------------------------ */
  1725. X
  1726. Xvoid
  1727. XdrawNext()
  1728. X{
  1729. X    int             x, y;
  1730. X    int             i, j;
  1731. X
  1732. X    x = topMidX + (topRWidth - nextThing.size * BOXSIZE) / 2;
  1733. X    y = topMidY - nextThing.size * BOXSIZE / 2;
  1734. X    for (i = 0; i < nextThing.size; i++)
  1735. X    for (j = 0; j < nextThing.size; j++)
  1736. X        if (nextThing.map[j][i])
  1737. X        drawBox(mainWin, nextThing.map[j][i], nextThing.px,
  1738. X        x + i * BOXSIZE, y + j * BOXSIZE);
  1739. X}
  1740. X
  1741. X/* ------------------------------------------------------------------ */
  1742. X
  1743. Xvoid
  1744. XclearNext()
  1745. X{
  1746. X    XFillRectangle(display, mainWin, revGC,
  1747. X    topMidX, topMidY - BOXSIZE * 2, topRWidth, BOXSIZE * 4);
  1748. X}
  1749. X
  1750. X/* ------------------------------------------------------------------ */
  1751. X
  1752. Xvoid
  1753. Xbanner(msg)
  1754. X    char            msg[];
  1755. X{
  1756. X    int             mlen = strlen(msg);
  1757. X    int             w = XTextWidth(bigFont, msg, mlen);
  1758. X    int             x = (topRWidth - w)/2 + topMidX;
  1759. X
  1760. X    XFillRectangle(display, mainWin, revGC,
  1761. X    x - 60, topMidY - bigFont->ascent - 5,
  1762. X    w + 120, bigFont->ascent + bigFont->descent + 10);
  1763. X    XDrawString(display, mainWin, bigGC, x, topMidY, msg, mlen);
  1764. X}
  1765. X
  1766. X/* ------------------------------------------------------------------ */
  1767. X
  1768. Xvoid
  1769. XputBox()
  1770. X{
  1771. X    int             i, j;
  1772. X    int             x = curThing.xpos, y = curThing.ypos;
  1773. X
  1774. X    for (i = 0; i < curThing.size; i++)
  1775. X    for (j = 0; j < curThing.size; j++)
  1776. X        if (curThing.map[j][i]) {
  1777. X        field[y + j][x + i].pm_num = curThing.map[j][i];
  1778. X        field[y + j][x + i].cid = curThing.px;
  1779. X        }
  1780. X}
  1781. X
  1782. X/* ------------------------------------------------------------------ */
  1783. X
  1784. XBool
  1785. Xoverlapping()
  1786. X{
  1787. X    int             i, j;
  1788. X    int             x = curThing.xpos, y = curThing.ypos;
  1789. X
  1790. X    for (i = 0; i < curThing.size; i++)
  1791. X    for (j = 0; j < curThing.size; j++)
  1792. X        if (curThing.map[j][i]) {
  1793. X        if ((y + j >= ROWS) || (x + i < 0) || (x + i >= COLS))
  1794. X            return True;
  1795. X        if (field[y + j][x + i].pm_num >= 0)
  1796. X            return True;
  1797. X        }
  1798. X
  1799. X    return False;
  1800. X}
  1801. X
  1802. X/* ------------------------------------------------------------------ */
  1803. X
  1804. XBool
  1805. XatBottom()
  1806. X{
  1807. X    int             i, j;
  1808. X    int             x = curThing.xpos, y = curThing.ypos;
  1809. X
  1810. X    for (i = 0; i < curThing.size; i++)
  1811. X    for (j = 0; j < curThing.size; j++)
  1812. X        if (curThing.map[j][i]) {
  1813. X        if ((y + j >= ROWS - 1) || (x + i < 0) || (x + i >= COLS))
  1814. X            return True;
  1815. X        if (field[y + j + 1][x + i].pm_num >= 0)
  1816. X            return True;
  1817. X        }
  1818. X
  1819. X    return False;
  1820. X}
  1821. X
  1822. X/* ------------------------------------------------------------------ */
  1823. X
  1824. Xvoid
  1825. XtryMove(move)
  1826. X    move_t          move;
  1827. X{
  1828. X    thing_t         old;
  1829. X
  1830. X    old = curThing;
  1831. X
  1832. X    switch (move) {
  1833. X    case FALL:
  1834. X    curThing.ypos ++;
  1835. X    break;
  1836. X
  1837. X    case DROP:
  1838. X    do {
  1839. X        curThing.ypos ++;
  1840. X        score += level + prefilled;
  1841. X    } while (!overlapping());
  1842. X    curThing.ypos --;
  1843. X    break;
  1844. X
  1845. X    case ROTATE:
  1846. X    curThing = possible[old.px][(old.py + 3) % 4];
  1847. X    curThing.xpos = old.xpos;
  1848. X    curThing.ypos = old.ypos;
  1849. X    break;
  1850. X
  1851. X    case LEFT:
  1852. X    curThing.xpos --;
  1853. X    break;
  1854. X
  1855. X    case RIGHT:
  1856. X    curThing.xpos ++;
  1857. X    break;
  1858. X    }
  1859. X
  1860. X    if (!overlapping())
  1861. X    drawThingDiff(&old);
  1862. X    else
  1863. X    curThing = old;
  1864. X}
  1865. X
  1866. X/* ------------------------------------------------------------------ */
  1867. X
  1868. Xint
  1869. XcheckLines()
  1870. X{
  1871. X    int             lSet[ROWS], nset = 0;
  1872. X    int             i, j, y;
  1873. X
  1874. X    for (j = 0; j < ROWS; j++) {
  1875. X    lSet[j] = 0;
  1876. X    for (i = 0; i < COLS; i++)
  1877. X        if (field[j][i].pm_num >= 0)
  1878. X        lSet[j] ++;
  1879. X    if (lSet[j] == COLS)
  1880. X        nset ++;
  1881. X    }
  1882. X
  1883. X    if (nset) {
  1884. X    for (i = 0; i < ((NUM_FLASHES / nset) % 2) * 2; i ++) {
  1885. X        for (j = 0; j < ROWS; j++) {
  1886. X        if (lSet[j] == COLS)
  1887. X            XFillRectangle(display, blockWin, xorGC,
  1888. X            0, j * BOXSIZE, frameW, BOXSIZE);
  1889. X        }
  1890. X        XFlush(display);
  1891. X    }
  1892. X
  1893. X    for (j = ROWS-1; j >= 0; j--) {
  1894. X        if (lSet[j] == COLS) {
  1895. X        for (y = j; y > 0; y--)
  1896. X            for (i = 0; i < COLS; i++)
  1897. X            field[y][i] = field[y-1][i];
  1898. X        for (i = 0; i < COLS; i++)
  1899. X            field[0][i].pm_num = -1;
  1900. X
  1901. X        XCopyArea(display, blockWin, blockWin, tinyGC,
  1902. X            0, 0, frameW, j * BOXSIZE, 0, BOXSIZE);
  1903. X        
  1904. X        XFillRectangle(display, blockWin, revGC,
  1905. X            0, 0, frameW, BOXSIZE);
  1906. X
  1907. X        for (i = j; i > 0; i--)
  1908. X            lSet[i] = lSet[i-1];
  1909. X        lSet[0] = 0;
  1910. X        
  1911. X        j++;
  1912. X        XFlush(display);
  1913. X        }
  1914. X    }
  1915. X
  1916. X    if (beep) XBell(display, BVOLUME);
  1917. X    XSync(display, False);
  1918. X    }
  1919. X
  1920. X    return nset;
  1921. X}
  1922. X
  1923. X/* ------------------------------------------------------------------ */
  1924. X
  1925. Xvoid
  1926. XrealTime(tv)
  1927. X    struct timeval *tv;
  1928. X{
  1929. X    while (tv->tv_usec < 0) {
  1930. X    tv->tv_sec --;
  1931. X    tv->tv_usec += MILLION;
  1932. X    }
  1933. X    while (tv->tv_usec >= MILLION) {
  1934. X    tv->tv_sec ++;
  1935. X    tv->tv_usec -= MILLION;
  1936. X    }
  1937. X}
  1938. X
  1939. X/* ------------------------------------------------------------------ */
  1940. END_OF_FILE
  1941. if test 18011 -ne `wc -c <'utils.c'`; then
  1942.     echo shar: \"'utils.c'\" unpacked with wrong size!
  1943. fi
  1944. # end of 'utils.c'
  1945. fi
  1946. echo shar: End of archive 1 \(of 2\).
  1947. cp /dev/null ark1isdone
  1948. MISSING=""
  1949. for I in 1 2 ; do
  1950.     if test ! -f ark${I}isdone ; then
  1951.     MISSING="${MISSING} ${I}"
  1952.     fi
  1953. done
  1954. if test "${MISSING}" = "" ; then
  1955.     echo You have unpacked both archives.
  1956.     rm -f ark[1-9]isdone
  1957. else
  1958.     echo You still need to unpack the following archives:
  1959.     echo "        " ${MISSING}
  1960. fi
  1961. ##  End of shell archive.
  1962. exit 0
  1963.