home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume10 / xbd / part02 < prev    next >
Encoding:
Internet Message Format  |  1990-11-04  |  59.9 KB

  1. Path: uunet!jarthur!usc!cs.utexas.edu!sun-barr!newstop!sun!news
  2. From: news@sun.Eng.Sun.COM (news)
  3. Newsgroups: comp.sources.x
  4. Subject: v10i047: xbd -- Boulder-dash (a game), Part02/03
  5. Message-ID: <144426@sun.Eng.Sun.COM>
  6. Date: 1 Nov 90 05:56:35 GMT
  7. References: <csx-10i046:xbd@uunet.UU.NET>
  8. Sender: news@sun.Eng.Sun.COM
  9. Organization: Sun Microsystems, Inc. - Mtn View, CA
  10. Lines: 2336
  11. Approved: argv@sun.com
  12.  
  13. Submitted-by: ethz!houttuin (Jeroen Houttuin)
  14. Posting-number: Volume 10, Issue 47
  15. Archive-name: xbd/part02
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then feed it
  20. # into a shell via "sh file" or similar.  To overwrite existing files,
  21. # type "sh file -c".
  22. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  23. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  24. # Contents:  xbd/Imakefile xbd/Makefile.orig xbd/README xbd/README.1.2
  25. #   xbd/bitmap xbd/default xbd/field.c xbd/patchlevel.h xbd/scores
  26. #   xbd/scores.c xbd/shared.c xbd/xbd.c xbd/xbd.h xbd/xbd.man
  27. #   xbd/xbde.c
  28. # Wrapped by houttuin@ural on Fri Oct 26 10:16:13 1990
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive."'
  32. if test -f 'xbd/Imakefile' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'xbd/Imakefile'\"
  34. else
  35.   echo shar: Extracting \"'xbd/Imakefile'\" \(2153 characters\)
  36.   sed "s/^X//" >'xbd/Imakefile' <<'END_OF_FILE'
  37. X#/*********************************************/
  38. X#/* you just keep on pushing my luck over the */
  39. X#/*           BOULDER        DASH             */
  40. X#/*                                           */
  41. X#/*Imakefile:christos@guillemin.EE.CORNELL.edu*/
  42. X#/*********************************************/
  43. X
  44. XGAME            = xbd
  45. XEDITOR          = xbde
  46. XPROGRAMS        = ${GAME} ${EDITOR}
  47. XCDEBUGFLAGS     = -O
  48. XSCOREFONT       = -adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1
  49. XSCORESIZE       = 18
  50. XMANDIR          = /usr/local/man/man6
  51. XBINDIR          = /usr/local/games
  52. XLIBDIR          = /usr/local/games/lib/xbd
  53. XDEFINES         = -DLIB=\"${LIBDIR}\" \
  54. X                  -DSCOREFONT=\"${SCOREFONT}\" \
  55. X                  -DSCORESIZE=${SCORESIZE}
  56. XLOCAL_LIBRARIES = $(XLIB)
  57. XSYS_LIBRARIES   = -lm
  58. XLEVELS          = xbdlev001 xbdlev002 xbdlev003 xbdlev004 xbdlev005 \
  59. X                  xbdlev006 xbdlev007 xbdlev008 xbdlev009 xbdlev010 \
  60. X                  xbdlev011 xbdlev012 xbdlev013 xbdlev014 xbdlev015 \
  61. X                  xbdlev016 xbdlev017 xbdlev018 xbdlev019 xbdlev020 \
  62. X                  xbdlev021 xbdlev022 xbdlev023 xbdlev024 xbdlev025 \
  63. X                  xbdlev026 xbdlev027 xbdlev028 xbdlev029 xbdlev030 \
  64. X                  xbdlev031 xbdlev032 xbdlev033 xbdlev034 xbdlev035 \
  65. X                  xbdlev036 xbdlev037 xbdlev038
  66. X
  67. XOBJS1   = xbd.o shared.o field.o scores.o
  68. XOBJS2   = xbde.o shared.o
  69. X
  70. XSRCS1   = xbd.o shared.o field.o scores.o
  71. XSRCS2   = xbde.o shared.o
  72. X
  73. XAllTarget(${PROGRAMS})
  74. XNormalProgramTarget(${GAME},${OBJS1},,$(LOCAL_LIBRARIES),)
  75. XNormalProgramTarget(${EDITOR},${OBJS2},,$(LOCAL_LIBRARIES),)
  76. XInstallProgramWithFlags(${GAME},${BINDIR}/${GAME},-s -m 4755 -o games)
  77. XInstallProgramWithFlags(${EDITOR},${BINDIR}/${EDITOR},-s -o games)
  78. X
  79. Xinstall.man:: xbd.man
  80. X        ${INSTALL} -c -m 0444 xbd.man ${MANDIR}/xbd.6
  81. X
  82. Xinstall:: ${PROGRAMS}
  83. X        -mkdir ${LIBDIR}
  84. X        chown games ${LIBDIR}
  85. X        touch ${LIBDIR}/scores
  86. X        chown games ${LIBDIR}/scores
  87. X        (cp ${LEVELS} ${LIBDIR})
  88. X        cp default ${LIBDIR}
  89. X        (cd ${LIBDIR}; \
  90. X         chown games ${LEVELS} default scores; \
  91. X         chmod 644   ${LEVELS} default scores;)
  92. END_OF_FILE
  93.   if test 2153 -ne `wc -c <'xbd/Imakefile'`; then
  94.     echo shar: \"'xbd/Imakefile'\" unpacked with wrong size!
  95.   fi
  96.   # end of 'xbd/Imakefile'
  97. fi
  98. if test -f 'xbd/Makefile.orig' -a "${1}" != "-c" ; then 
  99.   echo shar: Will not clobber existing file \"'xbd/Makefile.orig'\"
  100. else
  101.   echo shar: Extracting \"'xbd/Makefile.orig'\" \(1033 characters\)
  102.   sed "s/^X//" >'xbd/Makefile.orig' <<'END_OF_FILE'
  103. X#/* you just keep on pushing my luck over the */
  104. X#/*           BOULDER        DASH             */
  105. X
  106. XGAME = xbd
  107. XEDITOR = xbde
  108. X
  109. X#BIN = /usr/local/bin
  110. XBIN = ${HOME}/xbd
  111. XLIB = ${HOME}/xbd
  112. X
  113. X# manual pages
  114. XMAN = /usr/man
  115. X
  116. XSCOREFONT = -adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1
  117. XSCORESIZE = 18
  118. X
  119. XCC = cc
  120. X
  121. XCFLAGS = -g
  122. XLDFLAGS = -g
  123. X
  124. Xall: ${GAME} ${EDITOR}
  125. X
  126. Xinstall: all
  127. X    -mkdir ${LIB}
  128. X    cp ${GAME} ${EDITOR} ${BIN}
  129. X    chmod 4755 ${BIN}/${GAME}
  130. X    touch ${LIB}/scores
  131. X    chmod 644 ${LIB}/xbdlev*
  132. X    chmod 644 ${LIB}/default
  133. X    chmod 644 ${LIB}/scores
  134. X    cp xbd.man ${MAN}
  135. X
  136. Xupdate: all
  137. X    cp ${GAME} ${EDITOR} ${BIN}
  138. X    chmod 4755 ${BIN}/${GAME}
  139. X
  140. Xclean:
  141. X    rm -f *.o core ${GAME} ${EDITOR}
  142. X
  143. XSRCS = xbd.c shared.c field.c scores.c
  144. XOBJS = xbd.o shared.o field.o scores.o
  145. X
  146. Xlint:
  147. X    lint -DLIB=\"${LIB}\" -DSCOREFONT=\"${SCOREFONT}\" \
  148. X    -DSCORESIZE=${SCORESIZE} ${SRCS}
  149. X
  150. X${GAME}: ${OBJS}
  151. X    ${CC} ${LDFLAGS} -o ${GAME} ${OBJS} -lX11
  152. X
  153. X${EDITOR}: xbde.o shared.o
  154. X    ${CC} ${LDFLAGS} -o ${EDITOR} xbde.o shared.o -lX11
  155. X
  156. X.c.o:
  157. X    ${CC} ${CFLAGS} -c -DLIB=\"${LIB}\" $<
  158. END_OF_FILE
  159.   if test 1033 -ne `wc -c <'xbd/Makefile.orig'`; then
  160.     echo shar: \"'xbd/Makefile.orig'\" unpacked with wrong size!
  161.   fi
  162.   chmod +x 'xbd/Makefile.orig'
  163.   # end of 'xbd/Makefile.orig'
  164. fi
  165. if test -f 'xbd/README' -a "${1}" != "-c" ; then 
  166.   echo shar: Will not clobber existing file \"'xbd/README'\"
  167. else
  168.   echo shar: Extracting \"'xbd/README'\" \(414 characters\)
  169.   sed "s/^X//" >'xbd/README' <<'END_OF_FILE'
  170. XBoulder-dash is still in an experimental phase.  Mail your
  171. Xbug reports,  interesting new levels, ideas to the author
  172. Xor to xbd@ks.id.ethz.ch.
  173. X
  174. X
  175. X
  176. X
  177. X
  178. XDON'T DISTRIBUTE ANY MODIFIED VERSIONS !
  179. X
  180. X
  181. X
  182. X
  183. XJeroen Houttuin
  184. XInformatikdienste-Kommunikationssysteme
  185. XETH Zentrum RZ-H7
  186. XCH-8092 Zurich
  187. Xtel +41-1-2565837
  188. Xfax +41-1-2615389
  189. Xe-mail: houttuin@ks.id.ethz.ch
  190. XX.400 : C=CH;ADMD=ARCOM;PRMD=SWITCH;O=ETHZ;OU=id;OU=ks;S=houttuin
  191. END_OF_FILE
  192.   if test 414 -ne `wc -c <'xbd/README'`; then
  193.     echo shar: \"'xbd/README'\" unpacked with wrong size!
  194.   fi
  195.   # end of 'xbd/README'
  196. fi
  197. if test -f 'xbd/README.1.2' -a "${1}" != "-c" ; then 
  198.   echo shar: Will not clobber existing file \"'xbd/README.1.2'\"
  199. else
  200.   echo shar: Extracting \"'xbd/README.1.2'\" \(842 characters\)
  201.   sed "s/^X//" >'xbd/README.1.2' <<'END_OF_FILE'
  202. X-Time limits per level are implemented.
  203. X-Every level has a name now.
  204. X-You can now also DRAW blocks in the editor.
  205. X-People can now create levels by setting the environment variable XBDLIB
  206. X to point to a directory that they can write to.
  207. X-Tinkle walls were implemented (character 't'). Every level has a tinkle
  208. X duration parameter.
  209. X
  210. X-For new ideas, levels etc. a distribution list has been created:
  211. X    xbd@ks.id.ethz.ch
  212. X
  213. X-Thanks for improvements:
  214. X    Tad.Davis@Central.Sun.com
  215. X    Fernando Mira da Silva <fcr@joyce.inesc.pt>
  216. X    Josh Siegel <siegel@Sun.com>
  217. X    ccsteve@cc.uq.oz.au
  218. X    George Ferguson <ferguson@cs.rochester.edu>
  219. X    Charles D. Farnum <farnum@cypress.Berkeley.edu>
  220. X    Lloyd Taylor <lloyd@aplcen.apl.jhu.edu>
  221. X    Michael Glad <glad@daimi.aau.dk>
  222. X
  223. X-Special thanks for Imakefile and most bug fixes :
  224. X    Christos S. Zoulas <christos@hyperion.EE.CORNELL.edu>
  225. END_OF_FILE
  226.   if test 842 -ne `wc -c <'xbd/README.1.2'`; then
  227.     echo shar: \"'xbd/README.1.2'\" unpacked with wrong size!
  228.   fi
  229.   # end of 'xbd/README.1.2'
  230. fi
  231. if test ! -d 'xbd/bitmap' ; then
  232.     echo shar: Creating directory \"'xbd/bitmap'\"
  233.     mkdir 'xbd/bitmap'
  234. fi
  235. if test -f 'xbd/default' -a "${1}" != "-c" ; then 
  236.   echo shar: Will not clobber existing file \"'xbd/default'\"
  237. else
  238.   echo shar: Extracting \"'xbd/default'\" \(979 characters\)
  239.   sed "s/^X//" >'xbd/default' <<'END_OF_FILE'
  240. X26 35 15 12 0 0 200 200 1000 Default_level
  241. XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
  242. XS        b             e    bp    S
  243. XS  www www w w w   ww  www www    S
  244. XS  wrw wrw w w w   w w w   wrw    S
  245. XS  www w w w w w   w w ww  www   nS
  246. XS  wrw wpw wBwrw   wrw w   wwe    S
  247. XS  wwwlwww www www ww  www wnw    S
  248. XS                                 S
  249. XS            bd bd                S
  250. XS    gwww    wwwww  wwwww  w   w  S
  251. XS     wl w   w   w  wdbb   w   w  S
  252. XS     w   w  w   w  w      w   w  S
  253. XS     wB  wg wwEBw  w      w   w  S
  254. XS     wBB wg ww Bw  w      w   w  S
  255. XS     wBB wg ww Bw  w      w   w  S
  256. XSgbg  wBB wg ww Bw  w d    wp  w  S
  257. XSglg  wBBBwg wwwww  wtttw  w   W nS
  258. XSglg  wBBBwg w   w      w  w   w  S
  259. XSggg  w   wg w   w      w  w   w  S
  260. XSglg  w   wg w   w      w  w   w nS
  261. XSgeg  w   w  w   w      w  w   w  S
  262. XSgbg  we w   w   w      w  w   w  S
  263. XSg g gwww   rw   w  twwtw  w   w  S
  264. XSg g                              S
  265. XSgeg        n    e               ES
  266. XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
  267. END_OF_FILE
  268.   if test 979 -ne `wc -c <'xbd/default'`; then
  269.     echo shar: \"'xbd/default'\" unpacked with wrong size!
  270.   fi
  271.   # end of 'xbd/default'
  272. fi
  273. if test -f 'xbd/field.c' -a "${1}" != "-c" ; then 
  274.   echo shar: Will not clobber existing file \"'xbd/field.c'\"
  275. else
  276.   echo shar: Extracting \"'xbd/field.c'\" \(13876 characters\)
  277.   sed "s/^X//" >'xbd/field.c' <<'END_OF_FILE'
  278. X/*********************************************/
  279. X/* you just keep on pushing my luck over the */
  280. X/*           BOULDER        DASH             */
  281. X/*                                           */
  282. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  283. X/*********************************************/
  284. X
  285. X#include <stdio.h>
  286. X#include <X11/Xlib.h>
  287. X#include <X11/keysym.h>
  288. X#include <X11/Xutil.h>
  289. X#include <signal.h>
  290. X#include <sys/time.h>
  291. X#include <sys/timeb.h>
  292. X#include "xbd.h"
  293. X
  294. Xvoid
  295. Xblink(i, j)
  296. X  int             i, j;
  297. X{
  298. X  field[i][j].changed = True;
  299. X}
  300. X
  301. Xvoid
  302. Xmove_cell(i, j, ii, jj)
  303. X  int             i, j, ii, jj;
  304. X{
  305. X  field[ii][jj] = field[i][j];
  306. X  field[ii][jj].speed = 1;
  307. X  field[ii][jj].changed = True;
  308. X  field[ii][jj].dir = ((ii - i) == 1) ? S : ((i - ii) == 1) ? N : ((jj - j) == 1) ? E : W;
  309. X  set_cell(i, j, SPACE);
  310. X}
  311. X
  312. Xvoid
  313. Xexplode(a, b, stage)
  314. X  int             a, b, stage;
  315. X{
  316. X  if (field[a][b].content != STEEL)
  317. X  {
  318. X    set_cell(a, b, EXPLOSION);
  319. X    field[a][b].stage = stage;    /* dirty fix, not what stage was meant for */
  320. X  }
  321. X}
  322. X
  323. XBool
  324. Xmove_nucbal(i, j, t)
  325. X  int             i, j, t;
  326. X{
  327. X  ii = (!t) ? (i + y - 1) % y : i;
  328. X  if (!t)
  329. X    jj = j;
  330. X  else
  331. X    switch (field[i][j].dir)
  332. X    {
  333. X    case E:
  334. X      jj = (t == 1) ? (j + x - 1) % x : (j + 1) % x;
  335. X      break;
  336. X    case W:
  337. X    default:
  338. X      jj = (t == 2) ? (j + x - 1) % x : (j + 1) % x;
  339. X      break;
  340. X    }
  341. X  switch (field[ii][jj].content)
  342. X  {
  343. X  case SPACE:
  344. X    move_cell(i, j, ii, jj);
  345. X    return (True);
  346. X  case NUCBAL:
  347. X    explode(i, j, DIAEXPLO);
  348. X    explode(ii, jj, DIAEXPLO);
  349. X    return (True);
  350. X  default:
  351. X    if (field[i][j].dir == N)
  352. X      field[i][j].dir = E;
  353. X    else
  354. X      field[i][j].dir = ((field[i][j].dir + 2) % 4);    /* turn around */
  355. X    return (False);
  356. X  }
  357. X}
  358. X
  359. XBool
  360. Xmove_monster(content, direction)
  361. X  char            content, direction;
  362. X{
  363. X  switch (direction)
  364. X  {
  365. X  case N:
  366. X    ii = (i + y - 1) % y;
  367. X    jj = j;
  368. X    break;
  369. X  case E:
  370. X    jj = (j + 1) % x;
  371. X    ii = i;
  372. X    break;
  373. X  case S:
  374. X    ii = (i + 1) % y;
  375. X    jj = j;
  376. X    break;
  377. X  default:
  378. X    jj = (j + x - 1) % x;
  379. X    ii = i;
  380. X    break;            /* default must be SOMEthing, West */
  381. X  }
  382. X  switch (field[ii][jj].content)
  383. X  {
  384. X  case SPACE:
  385. X    if (!field[ii][jj].changed)
  386. X    {
  387. X      move_cell(i, j, ii, jj);
  388. X      field[ii][jj].dir = direction;
  389. X      return (True);
  390. X    } else
  391. X      return (False);
  392. X    break;
  393. X  case BOULDER:
  394. X  case DIAMOND:
  395. X    if ((direction == N) && (field[ii][jj].speed != 0))
  396. X      if (content == RMONSTER)
  397. X      {
  398. X    explode(i, j, DIAEXPLO);
  399. X    return (True);
  400. X      } else if (content == LMONSTER)
  401. X      {
  402. X    explode(i, j, SPACEEXPLO);
  403. X    return (True);
  404. X      } else
  405. X    return (False);
  406. X    else
  407. X      return (False);
  408. X    break;
  409. X  default:
  410. X    return (False);
  411. X    break;
  412. X  }
  413. X  return (False);
  414. X}
  415. X
  416. XBool
  417. Xsearch_destroy(content)
  418. X  char            content;
  419. X{
  420. X  ii = (i + y - 1) % y;
  421. X  jj = (j + x - 1) % x;
  422. X  if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB)
  423. X  {
  424. X    set_cell(i, j, SPACE);
  425. X    if (field[i][jj].content == PLAYER)
  426. X    {
  427. X      lives--;
  428. X      scoreobs = True;
  429. X    }
  430. X    if (content == RMONSTER)
  431. X      explode(i, jj, DIAEXPLO);
  432. X    else
  433. X      explode(i, jj, SPACEEXPLO);
  434. X    return (True);
  435. X  } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB)
  436. X  {
  437. X    set_cell(i, j, SPACE);
  438. X    if (field[ii][j].content == PLAYER)
  439. X    {
  440. X      lives--;
  441. X      scoreobs = True;
  442. X    }
  443. X    if (content == RMONSTER)
  444. X      explode(ii, j, DIAEXPLO);
  445. X    else
  446. X      explode(ii, j, SPACEEXPLO);
  447. X    return (True);
  448. X  } else
  449. X  {
  450. X    ii = (i + 1) % y;
  451. X    jj = (j + 1) % x;
  452. X    if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB)
  453. X    {
  454. X      set_cell(i, j, SPACE);
  455. X      if (field[i][jj].content == PLAYER)
  456. X      {
  457. X    lives--;
  458. X    scoreobs = True;
  459. X      }
  460. X      if (content == RMONSTER)
  461. X    explode(i, jj, DIAEXPLO);
  462. X      else
  463. X    explode(i, jj, SPACEEXPLO);
  464. X      return (True);
  465. X    } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB)
  466. X    {
  467. X      set_cell(i, j, SPACE);
  468. X      if (field[ii][j].content == PLAYER)
  469. X      {
  470. X    lives--;
  471. X    scoreobs = True;
  472. X      }
  473. X      if (content == RMONSTER)
  474. X    explode(ii, j, DIAEXPLO);
  475. X      else
  476. X    explode(ii, j, SPACEEXPLO);
  477. X      return (True);
  478. X    } else
  479. X      return (False);
  480. X  }
  481. X}
  482. X
  483. Xvoid
  484. Xpropagate(i, j, dias)
  485. X  int             i, j;
  486. X  Bool            dias;
  487. X{
  488. X  int             t, it, jt;
  489. X  if (dias)
  490. X    set_cell(i, j, DIAMOND);
  491. X  else
  492. X  {
  493. X    field[i][j].checked = PROPAGATED;
  494. X    field[i][j].caught = True;
  495. X  }
  496. X  for (t = 0; (t < 4); ++t)
  497. X  {
  498. X    it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i;    /* neigbour
  499. X                                     * right,up,left,down */
  500. X    jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j;    /* neigbour
  501. X                                     * right,up,left,down */
  502. X    switch (field[it][jt].content)
  503. X    {
  504. X    case BLOB:
  505. X      if (field[it][jt].checked != PROPAGATED)
  506. X    propagate(it, jt, dias);
  507. X      break;
  508. X    case SPACE:
  509. X    case GRASS:
  510. X      if (!(rand() % (blobbreak + 1)))
  511. X      {
  512. X    set_cell(it, jt, BLOB);
  513. X    field[it][jt].checked = PROPAGATED;
  514. X    field[it][jt].caught = True;
  515. X      }
  516. X      break;
  517. X    default:
  518. X      break;
  519. X    }
  520. X  }
  521. X}
  522. X
  523. XBool
  524. Xcaught(i, j)
  525. X  int             i, j;
  526. X{
  527. X  Bool            Free;
  528. X  int             t, it, jt;
  529. X
  530. X  field[i][j].checked = 1;
  531. X  Free = False;
  532. X
  533. X  for (t = 0; ((t < 4) && !Free); ++t)
  534. X  {
  535. X    it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i;    /* neigbour
  536. X                                     * right,up,left,down */
  537. X    jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j;    /* neigbour
  538. X                                     * right,up,left,down */
  539. X
  540. X    switch (field[it][jt].content)
  541. X    {
  542. X    case SPACE:
  543. X    case GRASS:
  544. X    case RMONSTER:
  545. X    case LMONSTER:
  546. X    case EATER:
  547. X      Free = True;
  548. X      break;
  549. X    case BLOB:
  550. X      Free = (Free || ((field[it][jt].checked == 1) ? !field[i][j].caught
  551. X               : !caught(it, jt)
  552. X               )
  553. X    );
  554. X      break;
  555. X    default:
  556. X      break;
  557. X    }
  558. X  }
  559. X  field[i][j].caught != Free;
  560. X  return (!Free);
  561. X}
  562. X
  563. Xvoid
  564. Xdiaboulderproc(i, j)
  565. X  int             i, j;
  566. X{
  567. X  if (field[i][j].content == DIAMOND)
  568. X    blink(i, j);
  569. X  ii = (ii + 1) % y;
  570. X  field[i][j].dir = NODIR;
  571. X  switch (field[ii][j].content)
  572. X  {
  573. X  case SPACE:            /* directly underneath */
  574. X    move_cell(i, j, ii, j);
  575. X    field[ii][j].speed = 1;
  576. X    break;
  577. X  case PLAYER:
  578. X    if (field[i][j].speed)
  579. X    {
  580. X      set_cell(i, j, SPACE);
  581. X      explode(ii, j, SPACEEXPLO);
  582. X      lives--;
  583. X      scoreobs = True;
  584. X    }
  585. X    break;
  586. X  case LMONSTER:
  587. X  case EATER:
  588. X    if (field[i][j].speed)
  589. X    {
  590. X      set_cell(i, j, SPACE);
  591. X      explode(ii, j, SPACEEXPLO);
  592. X    }
  593. X    break;
  594. X  case RMONSTER:
  595. X    if (field[i][j].speed)
  596. X    {
  597. X      set_cell(i, j, SPACE);
  598. X      explode(ii, j, DIAEXPLO);
  599. X    }
  600. X    break;
  601. X  case TINKLE:
  602. X    if (field[i][j].speed)
  603. X    {
  604. X      tinkact = True;
  605. X      field[ii][j].stage = field[i][j].content;
  606. X      field[ii][j].speed = 1;
  607. X      set_cell(i, j, SPACE);
  608. X      break;
  609. X    }
  610. X    break;
  611. X  case WALL:
  612. X  case BOULDER:
  613. X  case DIAMOND:
  614. X  case EXPLOSION:
  615. X    jj = (j + 1) % x;
  616. X    if (field[i][jj].content == SPACE && field[ii][jj].content == SPACE)
  617. X    {
  618. X      move_cell(i, j, i, jj);
  619. X      field[i][jj].speed = 0;
  620. X    } else
  621. X    {
  622. X      jj = (j - 1) % x;
  623. X      if (field[i][jj].content == SPACE
  624. X      && field[ii][jj].content == SPACE)
  625. X      {
  626. X    move_cell(i, j, i, jj);
  627. X    field[i][jj].speed = 0;
  628. X      } else
  629. X    field[i][j].speed = 0;
  630. X    }
  631. X    break;
  632. X  default:
  633. X    field[i][j].speed = 0;
  634. X    break;
  635. X  }
  636. X}
  637. X
  638. Xvoid
  639. Xcalculate_field()
  640. X{
  641. X  players = 0;
  642. X  /* Iterate through each horizontal line */
  643. X  if (!time)
  644. X    curorder = KILL;
  645. X  for (i = y - 1; i >= 0; --i)
  646. X  {
  647. X    for (j = 0; j < x; ++j)
  648. X    {
  649. X      if (!(field[i][j].changed))
  650. X      {
  651. X    ii = i;
  652. X    jj = j;
  653. X    switch (field[i][j].content)
  654. X    {
  655. X    case PLAYER:
  656. X      players++;
  657. X      switch (curorder)    /* find cell player wants to go to */
  658. X      {
  659. X      case STAND:
  660. X        break;
  661. X      case UP:
  662. X        ii = (i + y - 1) % y;
  663. X        break;
  664. X      case DOWN:
  665. X        ii = (i + 1) % y;
  666. X        break;
  667. X      case LEFT:
  668. X        jj = (j + x - 1) % x;
  669. X        break;
  670. X      case RIGHT:
  671. X        jj = (j + 1) % x;
  672. X        break;
  673. X      }
  674. X      if (!(curorder == STAND) && !(field[i][j].changed))
  675. X      {
  676. X        if (curorder == KILL)
  677. X        {
  678. X          set_cell(i, j, EXPLOSION);
  679. X          lives--;
  680. X          scoreobs = True;
  681. X          break;
  682. X        }
  683. X        switch (field[ii][jj].content)    /* check cell player wants to
  684. X                         * go to */
  685. X        {
  686. X        case SPACE:
  687. X        case GRASS:
  688. X        case DIAMOND:
  689. X          if (field[ii][jj].content == DIAMOND)
  690. X          {
  691. X        if (curorder == UP && field[ii][jj].speed)
  692. X          break;
  693. X        score += diapoints;
  694. X        if (diareq)
  695. X          diareq--;
  696. X        scoreobs = True;
  697. X          }
  698. X          if (steal)
  699. X        set_cell(ii, jj, SPACE);
  700. X          else
  701. X        move_cell(i, j, ii, jj);
  702. X          break;
  703. X        case BOULDER:
  704. X          jjj = (2 * jj - j + x) % x;    /* the cell behind the
  705. X                         * boulder */
  706. X          if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) &&
  707. X          !(field[ii][jj].dir == E))
  708. X          {
  709. X        move_cell(i, jj, i, jjj);
  710. X        field[i][jjj].speed = 0;
  711. X        if (!steal)
  712. X        {
  713. X          move_cell(i, j, i, jj);
  714. X        }
  715. X          }
  716. X          break;
  717. X        case EXIT:
  718. X          if (diareq < 1)
  719. X          {
  720. X        if (!steal)
  721. X          move_cell(i, j, ii, jj);
  722. X        else
  723. X          set_cell(ii, jj, SPACE);
  724. X        if (!levincreased)
  725. X        {
  726. X          levelnum++;
  727. X          lives++;
  728. X          levincreased = True;
  729. X          for (jj = time / 10; jj > 0; --jj)
  730. X          {
  731. X            score += 10;
  732. X            draw_score();
  733. X            XFlush(disp);
  734. X          }
  735. X        }
  736. X        gamestop = True;
  737. X        stoplevel = True;
  738. X          }
  739. X          break;
  740. X        }
  741. X      }
  742. X      blink(i, j);
  743. X      break;
  744. X    case DIAMOND:
  745. X    case BOULDER:
  746. X      diaboulderproc(i, j);
  747. X      break;
  748. X    case EATER:
  749. X      if (!field[i][j].speed)
  750. X      {
  751. X        for (jjj = 0; ((!field[i][j].changed) && (jjj < 4)); ++jjj)
  752. X        {
  753. X          ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i;
  754. X          jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j;
  755. X          switch (field[ii][jj].content)
  756. X          {
  757. X          case PLAYER:
  758. X        lives--;
  759. X        scoreobs = True;
  760. X          case DIAMOND:
  761. X        if (field[ii][jj].speed && (ii == i - 1) && (jj == j))
  762. X          break;
  763. X          case BLOB:
  764. X          case LMONSTER:
  765. X          case RMONSTER:
  766. X          case NUCBAL:
  767. X        move_cell(i, j, ii, jj);
  768. X        break;
  769. X          default:
  770. X        break;
  771. X          }
  772. X        }
  773. X      } else
  774. X      {
  775. X        jjj = field[i][j].dir;
  776. X        ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i;
  777. X        jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j;
  778. X        switch (field[ii][jj].content)
  779. X        {
  780. X        case LMONSTER:
  781. X        case BLOB:
  782. X        case SPACE:
  783. X        case GRASS:
  784. X        case DIAMOND:
  785. X        case RMONSTER:
  786. X        case PLAYER:
  787. X        case NUCBAL:
  788. X          if (field[ii][jj].content == PLAYER)
  789. X          {
  790. X        lives--;
  791. X        scoreobs = True;
  792. X          }
  793. X          move_cell(i, j, ii, jj);
  794. X          break;
  795. X        case BOULDER:
  796. X          jjj = (2 * jj - j + x) % x;    /* the cell behind the
  797. X                         * boulder */
  798. X          if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) && !(field[ii][jj].dir == E))
  799. X          {
  800. X        move_cell(i, jj, i, jjj);
  801. X        move_cell(i, j, i, jj);
  802. X          } else
  803. X        field[i][j].speed = 0;
  804. X          break;
  805. X        default:
  806. X          field[i][j].speed = 0;
  807. X          break;
  808. X        }
  809. X      }
  810. X      blink(i, j);
  811. X      break;
  812. X    case RMONSTER:
  813. X      blink(i, j);
  814. X      if (search_destroy(RMONSTER))
  815. X        break;
  816. X      jjj = 3;
  817. X      while (jjj >= 0 && !move_monster(RMONSTER, (field[i][j].dir + jjj + 2) % 4))
  818. X        jjj--;
  819. X      break;
  820. X    case LMONSTER:
  821. X      blink(i, j);
  822. X      if (search_destroy(LMONSTER))
  823. X        break;
  824. X      jjj = 0;
  825. X      while (jjj <= 4 && !move_monster(LMONSTER, (field[i][j].dir + jjj + 3) % 4))
  826. X        jjj++;
  827. X      break;
  828. X    case EXPLOSION:
  829. X      jjj = field[i][j].stage;
  830. X      if (!(jjj % 5))    /* this is the initiating explosion */
  831. X      {
  832. X        jjj++;        /* use jjj for setting new stage */
  833. X        ii = (i + 1) % y;
  834. X        jj = (j + 1) % x;
  835. X        explode(i, j, jjj);
  836. X        explode(i, jj, jjj);
  837. X        explode(ii, j, jjj);
  838. X        explode(ii, jj, jjj);
  839. X        ii = (i + y - 1) % y;
  840. X        explode(ii, j, jjj);
  841. X        explode(ii, jj, jjj);
  842. X        jj = (j + x - 1) % x;
  843. X        explode(ii, jj, jjj);
  844. X        explode(i, jj, jjj);
  845. X        ii = (i + 1) % y;
  846. X        explode(ii, jj, jjj);
  847. X      } else
  848. X      {
  849. X        if (jjj % 10 < 3)
  850. X          field[i][j].stage++;
  851. X        else if (jjj > DIAEXPLO)
  852. X        {
  853. X          set_cell(i, j, DIAMOND);
  854. X        } else if (jjj > BOULDEXPLO)
  855. X        {
  856. X          set_cell(i, j, BOULDER);
  857. X        } else if (jjj > SPACEEXPLO)
  858. X        {
  859. X          set_cell(i, j, SPACE);
  860. X        } else
  861. X          field[i][j].stage++;
  862. X      }
  863. X      break;
  864. X    case EXIT:
  865. X      blink(i, j);
  866. X      break;
  867. X    case BLOB:
  868. X      blobcells++;
  869. X      if (blobcollapse)
  870. X        set_cell(i, j, BOULDER);
  871. X      else
  872. X      {
  873. X        if (blobcells > critical)
  874. X          blobcollapse = True;
  875. X        else
  876. X        {
  877. X          if (!field[i][j].checked)
  878. X          {
  879. X        if (caught(i, j))
  880. X          propagate(i, j, DIAMOND);
  881. X        else
  882. X          propagate(i, j, False);
  883. X          }
  884. X          field[i][j].checked = False;
  885. X          field[i][j].caught = True;
  886. X        }
  887. X      }
  888. X      blink(i, j);
  889. X      break;
  890. X    case NUCBAL:
  891. X      for (jjj = 0; ((jjj < 3) && !move_nucbal(i, j, jjj)); ++jjj);
  892. X      blink(i, j);
  893. X      break;
  894. X    case MAGICWALL:
  895. X      jj = (j + x - 1) % x;
  896. X      if (field[i][jj].content == SPACE)
  897. X        set_cell(i, jj, MAGICWALL);
  898. X      jj = (j + 1) % x;
  899. X      if (field[i][jj].content == SPACE)
  900. X        set_cell(i, jj, MAGICWALL);
  901. X      break;
  902. X    case TINKLE:
  903. X      if (tinkact)
  904. X      {
  905. X        blink(i, j);
  906. X        if (tinkdur > 0)
  907. X        {
  908. X          switch (field[i][j].stage)
  909. X          {
  910. X          case BOULDER:
  911. X        {
  912. X          field[i][j].content = DIAMOND;
  913. X          diaboulderproc(i, j);
  914. X          break;
  915. X        }
  916. X          case DIAMOND:
  917. X        {
  918. X          field[i][j].content = BOULDER;
  919. X          diaboulderproc(i, j);
  920. X          break;
  921. X        }
  922. X          default:
  923. X        break;
  924. X          }
  925. X        }
  926. X      }
  927. X      set_cell(i, j, TINKLE);    /* reset to empty tinkle wall */
  928. X      break;
  929. X    default:
  930. X      break;
  931. X    }
  932. X      }
  933. X    }
  934. X  }
  935. X  curorder = STAND;        /* reset orders */
  936. X  blobcells = 0;
  937. X  pgc = (pgc == pgc1) ? ((rand() % 22) == 0) ? pgc2 : pgc1 :
  938. X    pgc1;
  939. X  dgc = (dgc == dgc1) ? dgc2 : dgc1;
  940. X  lgc = (lgc == lgc1) ? lgc2 : lgc1;
  941. X  rgc = (rgc == rgc1) ? rgc2 : rgc1;
  942. X  egc = (egc == egc1) ? egc2 : egc1;
  943. X  Bgc = (Bgc == Bgc1) ? Bgc2 : Bgc1;
  944. X  if (tinkact)
  945. X    tgc = (tgc == tgc1) ? tgc2 : tgc1;
  946. X  if (!diareq)
  947. X  {
  948. X    Egc = (Egc == Egc1) ? Egc2 : Egc1;
  949. X    if (diareq == 0)
  950. X    {
  951. X      diapoints = extradiapoints;
  952. X      scoreobs = True;
  953. X    }
  954. X  }
  955. X}
  956. END_OF_FILE
  957.   if test 13876 -ne `wc -c <'xbd/field.c'`; then
  958.     echo shar: \"'xbd/field.c'\" unpacked with wrong size!
  959.   fi
  960.   # end of 'xbd/field.c'
  961. fi
  962. if test -f 'xbd/patchlevel.h' -a "${1}" != "-c" ; then 
  963.   echo shar: Will not clobber existing file \"'xbd/patchlevel.h'\"
  964. else
  965.   echo shar: Extracting \"'xbd/patchlevel.h'\" \(21 characters\)
  966.   sed "s/^X//" >'xbd/patchlevel.h' <<'END_OF_FILE'
  967. X#define PATCHLEVEL 0
  968. END_OF_FILE
  969.   if test 21 -ne `wc -c <'xbd/patchlevel.h'`; then
  970.     echo shar: \"'xbd/patchlevel.h'\" unpacked with wrong size!
  971.   fi
  972.   # end of 'xbd/patchlevel.h'
  973. fi
  974. if test -f 'xbd/scores' -a "${1}" != "-c" ; then 
  975.   echo shar: Will not clobber existing file \"'xbd/scores'\"
  976. else
  977.   echo shar: Extracting \"'xbd/scores'\" \(405 characters\)
  978.   sed "s/^X//" >'xbd/scores' <<'END_OF_FILE'
  979. X2800 27 30 houttuin 
  980. X1833 12 14 houttuin 
  981. X1770 22 23 houttuin 
  982. X1690 15 16 houttuin 
  983. X1680 37 38 houttuin 
  984. X1626 27 29 houttuin 
  985. X1350 36 36 houttuin 
  986. X1302 2 4 houttuin 
  987. X1284 17 18 houttuin 
  988. X1160 37 37 houttuin 
  989. X1120 77 78 houttuin 
  990. X1110 2 3 houttuin 
  991. X1020 77 77 houttuin 
  992. X960 25 25 houttuin 
  993. X955 2 3 houttuin 
  994. X950 36 36 houttuin 
  995. X934 13 14 houttuin 
  996. X930 16 16 houttuin 
  997. X902 2 3 houttuin 
  998. X883 33 34 houttuin 
  999. END_OF_FILE
  1000.   if test 405 -ne `wc -c <'xbd/scores'`; then
  1001.     echo shar: \"'xbd/scores'\" unpacked with wrong size!
  1002.   fi
  1003.   # end of 'xbd/scores'
  1004. fi
  1005. if test -f 'xbd/scores.c' -a "${1}" != "-c" ; then 
  1006.   echo shar: Will not clobber existing file \"'xbd/scores.c'\"
  1007. else
  1008.   echo shar: Extracting \"'xbd/scores.c'\" \(3472 characters\)
  1009.   sed "s/^X//" >'xbd/scores.c' <<'END_OF_FILE'
  1010. X/*********************************************/
  1011. X/* you just keep on pushing my luck over the */
  1012. X/*           BOULDER        DASH             */
  1013. X/*                                           */
  1014. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  1015. X/*********************************************/
  1016. X
  1017. X#include <stdio.h>
  1018. X#include <X11/Xlib.h>
  1019. X#include <X11/keysym.h>
  1020. X#include "xbd.h"
  1021. X
  1022. Xchar           *getenv();
  1023. X
  1024. X#define NUMHIGH 20        /* Number of high scores that will be
  1025. X                 * remembered */
  1026. X
  1027. X/* Add a high score to the high score list */
  1028. Xvoid
  1029. Xadd_score()
  1030. X{
  1031. X  /* Structure containing top game results */
  1032. X  struct
  1033. X  {
  1034. X    int             score;    /* Final score */
  1035. X    int             slev, elev;    /* Starting and ending level */
  1036. X    char            desc[80];    /* Text description */
  1037. X  }               tops[NUMHIGH], next;
  1038. X  FILE           *sfile;    /* High score file */
  1039. X  char            buf[200];
  1040. X  register int    i;
  1041. X  int             numscore, cur, numgame;
  1042. X
  1043. X  /* Generate name of high score file */
  1044. X  sprintf(buf, "%s/scores", LIB);
  1045. X  /* Open high score file */
  1046. X  sfile = fopen(buf, "r");
  1047. X  /* Set default values for number of games and high scores */
  1048. X  numscore = 0;
  1049. X  numgame = 0;
  1050. X  /* If file is readable, load in old high score list */
  1051. X  if (sfile != NULL)
  1052. X  {
  1053. X    /* Extract score information from line */
  1054. X    while (fgets(buf, 200, sfile) && numscore < NUMHIGH)
  1055. X    {
  1056. X      sscanf(buf, "%d %d %d %[^\n]", &(next.score), &(next.slev), &(next.elev),
  1057. X         next.desc);
  1058. X      tops[numscore] = next;
  1059. X      numscore++;
  1060. X    }
  1061. X    fclose(sfile);
  1062. X  }
  1063. X  /* Contruct the structure containing the score for this game */
  1064. X  next.score = score;
  1065. X  next.slev = levelstart;
  1066. X  next.elev = levelnum;
  1067. X#ifndef hpux
  1068. X  sprintf(next.desc, "%s ", getenv("USER"));
  1069. X#else
  1070. X  sprintf(next.desc, "%s ", getenv("LOGNAME"));
  1071. X#endif
  1072. X  cur = -1;
  1073. X  /* Insert new score in old high score list */
  1074. X  if (numscore < NUMHIGH || tops[NUMHIGH - 1].score < next.score)
  1075. X  {
  1076. X    /* Iterate through high score list */
  1077. X    for (i = (numscore >= NUMHIGH ? NUMHIGH - 2 : numscore - 1); i >= 0; i--)
  1078. X    {
  1079. X      /* Look for place for insertion */
  1080. X      if (next.score > tops[i].score)
  1081. X    tops[i + 1] = tops[i];    /* Move old scores down one place in list */
  1082. X      else
  1083. X    break;            /* Found spot for insertion */
  1084. X    }
  1085. X    tops[i + 1] = next;        /* Overwrite entry in high score list */
  1086. X    cur = i + 1;        /* Remember where new high score was inserted */
  1087. X    /* Increment the number of high scores */
  1088. X    if (numscore < NUMHIGH)
  1089. X      numscore++;
  1090. X  }
  1091. X  /* Increment and print the number of games played */
  1092. X  /* Print out new high score list */
  1093. X  for (i = 0; i < numscore; ++i)
  1094. X  {
  1095. X    /* Flag new high score with a leading > */
  1096. X    if (i == cur)
  1097. X      putchar('*');
  1098. X    else
  1099. X      putchar(' ');
  1100. X    printf("%-16s- Died on level %3d. Started on level %3d.  Score: %8d.\n",
  1101. X       tops[i].desc, tops[i].elev, tops[i].slev, tops[i].score);
  1102. X  }
  1103. X  /* If current game did not make it to the high score list, print it */
  1104. X  /* afterwords */
  1105. X  if (cur == -1)
  1106. X  {
  1107. X    puts("You are quite disappointing:");
  1108. X    printf("*%-16s- Died on level %3d. Started on level %3d.  Score: %8d.\n",
  1109. X       next.desc, next.elev, next.slev, next.score);
  1110. X  }
  1111. X  /* Save new high score list to score file */
  1112. X  sprintf(buf, "%s/scores", LIB);
  1113. X  sfile = fopen(buf, "w");
  1114. X  if (sfile == NULL)
  1115. X  {
  1116. X    perror(buf);
  1117. X    return;
  1118. X  }
  1119. X  for (i = 0; i < numscore; ++i)
  1120. X    fprintf(sfile, "%d %d %d %s\n", tops[i].score, tops[i].slev,
  1121. X        tops[i].elev, tops[i].desc);
  1122. X  fclose(sfile);
  1123. X}
  1124. END_OF_FILE
  1125.   if test 3472 -ne `wc -c <'xbd/scores.c'`; then
  1126.     echo shar: \"'xbd/scores.c'\" unpacked with wrong size!
  1127.   fi
  1128.   # end of 'xbd/scores.c'
  1129. fi
  1130. if test -f 'xbd/shared.c' -a "${1}" != "-c" ; then 
  1131.   echo shar: Will not clobber existing file \"'xbd/shared.c'\"
  1132. else
  1133.   echo shar: Extracting \"'xbd/shared.c'\" \(9674 characters\)
  1134.   sed "s/^X//" >'xbd/shared.c' <<'END_OF_FILE'
  1135. X/*********************************************/
  1136. X/* you just keep on pushing my luck over the */
  1137. X/*          BOULDER        DASH              */
  1138. X/*                                           */
  1139. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  1140. X/*********************************************/
  1141. X
  1142. X#include <stdio.h>
  1143. X#include <X11/Xlib.h>
  1144. X#include <X11/keysym.h>
  1145. X#include <X11/Xutil.h>
  1146. X#include <errno.h>
  1147. X#include <sys/time.h>
  1148. X#include <sys/timeb.h>
  1149. X#include "xbd.h"
  1150. X
  1151. X/* Manufaction a 32x32 graphics cursor used in a XFill... operation. */
  1152. XGC
  1153. Xmakegc(func, bits)
  1154. X  int             func;        /* Drawing function such as GXcopy or GXor. */
  1155. X  char            bits[];    /* Bits describing fill pattern.  Produced in
  1156. X                 * an X11 */
  1157. X/* bitmap file usually. */
  1158. X{
  1159. X  static XGCValues gcv;
  1160. X  Pixmap          pmap;
  1161. X
  1162. X  /* Build X11 bitmap from data in bits */
  1163. X  pmap = XCreatePixmapFromBitmapData(disp, wind, bits, 32, 32, BlackPixel(disp, 0),
  1164. X                   WhitePixel(disp, 0), DisplayPlanes(disp, 0));
  1165. X  /* Assign the graphics cursor parameters */
  1166. X  gcv.function = func;
  1167. X  gcv.foreground = BlackPixel(disp, 0);
  1168. X  gcv.background = WhitePixel(disp, 0);
  1169. X  gcv.tile = pmap;
  1170. X  gcv.fill_style = FillTiled;
  1171. X  /* Return the created graphics cursor */
  1172. X  return (XCreateGC(disp, wind, GCFunction | GCForeground | GCBackground |
  1173. X            GCTile | GCFillStyle, &gcv));
  1174. X}
  1175. X
  1176. Xvoid
  1177. Xmake_gcs()
  1178. X{
  1179. X  pgc = makegc(GXcopy, player_bits);
  1180. X  pgc1 = makegc(GXcopy, player_bits);
  1181. X  pgc2 = makegc(GXcopy, player2_bits);
  1182. X  wgc = makegc(GXcopy, wall_bits);
  1183. X  Wgc = makegc(GXcopy, wall_bits);
  1184. X  Wgc2 = makegc(GXcopy, wall2_bits);
  1185. X  sgc = makegc(GXcopy, space_bits);
  1186. X  ggc = makegc(GXcopy, grass_bits);
  1187. X  dgc = makegc(GXcopy, diamond_bits);
  1188. X  dgc1 = makegc(GXcopy, diamond_bits);
  1189. X  dgc2 = makegc(GXcopy, diamond2_bits);
  1190. X  Sgc = makegc(GXcopy, steel_bits);
  1191. X  bgc = makegc(GXcopy, boulder_bits);
  1192. X  xgc = makegc(GXand, explosion_bits);
  1193. X  lgc = makegc(GXcopy, lmonster_bits);
  1194. X  lgc1 = makegc(GXcopy, lmonster_bits);
  1195. X  lgc2 = makegc(GXcopy, lmonster2_bits);
  1196. X  rgc = makegc(GXcopy, rmonster_bits);
  1197. X  rgc1 = makegc(GXcopy, rmonster_bits);
  1198. X  rgc2 = makegc(GXcopy, rmonster2_bits);
  1199. X  egc = makegc(GXcopy, eater_bits);
  1200. X  egc1 = makegc(GXcopy, eater_bits);
  1201. X  egc2 = makegc(GXcopy, eater2_bits);
  1202. X  Egc = makegc(GXcopy, steel_bits);
  1203. X  Egc1 = makegc(GXcopy, steel_bits);
  1204. X  Egc2 = makegc(GXcopy, exit2_bits);
  1205. X  ngc = makegc(GXcopy, nucbal_bits);
  1206. X  Bgc = makegc(GXcopy, blob_bits);
  1207. X  Bgc1 = makegc(GXcopy, blob_bits);
  1208. X  Bgc2 = makegc(GXcopy, blob2_bits);
  1209. X  tgc = makegc(GXcopy, wall_bits);
  1210. X  tgc1 = makegc(GXcopy, wall_bits);
  1211. X  tgc2 = makegc(GXcopy, tinkle1_bits);
  1212. X  tgc3 = makegc(GXcopy, tinkle2_bits);
  1213. X}
  1214. X
  1215. Xvoid
  1216. Xinit_level(levelnum)
  1217. X  int             levelnum;
  1218. X{
  1219. X
  1220. X  FILE           *levelfile;
  1221. X  char            buf[300], *ptr;
  1222. X  extern char    *getenv();
  1223. X
  1224. X  Egc = Egc1;            /* don't blink EXIT */
  1225. X  blobcollapse = False;
  1226. X  blobcells = 0;
  1227. X  scoreobs = True;
  1228. X  tinkact = False;
  1229. X  levincreased = False;
  1230. X  strcpy(levname, "No_name_for_this_level_yet");
  1231. X
  1232. X  /* Manufaction the file name by starting with the world name and */
  1233. X  /* appending the level number to it. */
  1234. X  if (ptr = getenv("XBDLIB"))
  1235. X    strcpy(filename, ptr);
  1236. X  else
  1237. X    strcpy(filename, LIB);
  1238. X  strcat(filename, "/");
  1239. X  strcat(filename, LEVELPREFIX);
  1240. X  sprintf(filename + strlen(filename), "%03d", levelnum);
  1241. X  /* Open level file for reading */
  1242. X  levelfile = fopen(filename, "r");
  1243. X  /* If level file does not exist, use the default level file. */
  1244. X  if (levelfile == NULL)
  1245. X  {
  1246. X    /* Build the default level name */
  1247. X    if (ptr = getenv("XBDLIB"))
  1248. X      strcpy(buf, ptr);
  1249. X    else
  1250. X      strcpy(buf, LIB);
  1251. X    strcat(buf, "/");
  1252. X    strcat(buf, "/default");
  1253. X    /* Open default level file for reading */
  1254. X    levelfile = fopen(buf, "r");
  1255. X    if (levelfile == NULL)
  1256. X    {
  1257. X      perror(LEVELPREFIX);
  1258. X      exit(1);
  1259. X    }
  1260. X  }
  1261. X  /* Load the first line of the level file */
  1262. X  if (fgets(buf, 300, levelfile) == NULL)
  1263. X  {
  1264. X    x = w;
  1265. X    y = h;
  1266. X    speed = 15;
  1267. X    diareq = 12;
  1268. X    diapoints = 0;
  1269. X    extradiapoints = 0;
  1270. X    blobbreak = 200;
  1271. X    time = 1000;
  1272. X  } else
  1273. X  {
  1274. X    /* Extract the level parameters */
  1275. X    sscanf(buf, "%d %d %d %d %d %d %d %d %d %s", &y, &x, &speed, &diareq,
  1276. X     &diapoints, &extradiapoints, &blobbreak, &tinkdur, &time, levname);
  1277. X  }
  1278. X
  1279. X  if (xin && yin)
  1280. X  {
  1281. X    x = xin;
  1282. X    y = yin;
  1283. X  }                /* read in from editor command line */
  1284. X  /*
  1285. X   * if (x > w) x = w; if (y > h) y = h; if (x < 2) x = 2; if (y < 1) y = 1;
  1286. X   * 
  1287. X  /*
  1288. X   * Iterate through each horizontal line
  1289. X   */
  1290. X  for (i = 0; i < y; ++i)
  1291. X  {
  1292. X    /* Load the next line from the file */
  1293. X    if (fgets(buf, 300, levelfile) != NULL)
  1294. X    {
  1295. X      /* Go through each horizontal position and copy the data into */
  1296. X      /* the level array. */
  1297. X      for (j = 0; j < x; ++j)
  1298. X      {
  1299. X    /* Break out if line ends prematurely */
  1300. X    if (buf[j] == '\n' || buf[j] == '\0')
  1301. X      field[i][j].content = STEEL;    /* break; */
  1302. X    field[i][j].content = buf[j];
  1303. X    field[i][j].changed = True;
  1304. X    field[i][j].dir = N;
  1305. X    field[i][j].speed = 0;
  1306. X    field[i][j].stage = 0;
  1307. X    field[i][j].caught = True;
  1308. X    field[i][j].checked = False;
  1309. X      }
  1310. X    } else
  1311. X      j = 0;
  1312. X    for (; j < x; ++j)
  1313. X      field[i][j].content = STEEL;
  1314. X  }
  1315. X  /* Close the level file */
  1316. X  fclose(levelfile);
  1317. X}
  1318. X
  1319. X/* Draw the score and level number */
  1320. Xvoid
  1321. Xdraw_score()
  1322. X{
  1323. X  char            buf[200];
  1324. X
  1325. X  /* Build the output string */
  1326. X  sprintf(buf, "sc:%d lv:%d ls:%d ds:%d dp:%d ti:%d       %s", score, levelnum,
  1327. X      lives, diareq, diapoints, time / 10, levname);
  1328. X  /* Clear the current score line */
  1329. X  XFillRectangle(disp, wind, whitegc, 0, y << 5, x << 5, SCORESIZE);
  1330. X  /* Actually draw the text */
  1331. X  XDrawString(disp, wind, scoregc, 0, (y << 5) + SCORESIZE - 1, buf,
  1332. X          strlen(buf));
  1333. X  scoreobs = False;
  1334. X}
  1335. X
  1336. Xvoid
  1337. Xxstart(evmask)
  1338. X  long            evmask;    /* Event mask which will be used in
  1339. X                 * XSelectInput */
  1340. X{
  1341. X  XGCValues       xgcv;
  1342. X  XWMHints        wmhints;
  1343. X
  1344. X  /* create X window */
  1345. X  disp = XOpenDisplay(NULL);
  1346. X  /* Check to see if the open display succeeded */
  1347. X  if (disp == NULL)
  1348. X  {
  1349. X    fprintf(stderr, "Display open failed.  Check DISPLAY environment variable.\n"
  1350. X      );
  1351. X    exit(-1);
  1352. X  }
  1353. X  wind = XCreateSimpleWindow(disp, DefaultRootWindow(disp), 0, 1,
  1354. X                 x << 5, (y << 5) + SCORESIZE, 1,
  1355. X                 WhitePixel(disp, 0), BlackPixel(disp, 0));
  1356. X  /* Check to see if the open window succeeded */
  1357. X  if (wind == 0)
  1358. X  {
  1359. X    fprintf(stderr, "Window open failed.\n");
  1360. X    XCloseDisplay(disp);
  1361. X    exit(-1);
  1362. X  }
  1363. X  /* Load in the font used to display the score */
  1364. X  scorefont = XLoadFont(disp, SCOREFONT);
  1365. X  /* Create GC which will be used from drawing score */
  1366. X  xgcv.function = GXcopy;
  1367. X  xgcv.font = scorefont;
  1368. X  xgcv.foreground = BlackPixel(disp, 0);
  1369. X  xgcv.background = WhitePixel(disp, 0);
  1370. X  scoregc = XCreateGC(disp, wind,
  1371. X              GCFunction | GCFont | GCForeground | GCBackground,
  1372. X              &xgcv);
  1373. X  /* Create GC which will be used for clearing score line */
  1374. X  xgcv.function = GXcopy;
  1375. X  scorefont = XLoadFont(disp, SCOREFONT);
  1376. X  xgcv.foreground = WhitePixel(disp, 0);
  1377. X  xgcv.background = BlackPixel(disp, 0);
  1378. X  whitegc = XCreateGC(disp, wind,
  1379. X              GCFunction | GCForeground | GCBackground,
  1380. X              &xgcv);
  1381. X  wmhints.flags = InputHint;
  1382. X  wmhints.input = True;
  1383. X  XSetWMHints(disp, wind, &wmhints);
  1384. X
  1385. X  XSelectInput(disp, wind, evmask);
  1386. X  XMapRaised(disp, wind);
  1387. X  XWarpPointer(disp, None, wind, 0, 0, 0, 0, 11, 1);
  1388. X}
  1389. X
  1390. X/* Gracefully shut X windows down.  It is not strictly necessary to */
  1391. X/* call this function. */
  1392. Xvoid
  1393. Xxend()
  1394. X{
  1395. X  gamestop = True;        /* tricky; prevent ticker function from using
  1396. X                 * Xlib fcts */
  1397. X  XUnloadFont(disp, scorefont);
  1398. X  XUnmapWindow(disp, wind);
  1399. X  XDestroyWindow(disp, wind);
  1400. X  XCloseDisplay(disp);
  1401. X}
  1402. X
  1403. Xvoid
  1404. Xdraw_field(redrawall)
  1405. X  short           redrawall;
  1406. X{
  1407. X  char            c;
  1408. X
  1409. X  /* Iterate through each horizontal line */
  1410. X  for (i = y - 1; i >= 0; --i)
  1411. X  {
  1412. X    for (j = 0; j < x; ++j)
  1413. X    {
  1414. X      if (field[i][j].changed || redrawall)    /* only redraw changed cells */
  1415. X      {
  1416. X    c = field[i][j].content;
  1417. X    switch (c)
  1418. X    {
  1419. X    case GRASS:
  1420. X      XFillRectangle(disp, wind, ggc, j << 5, i << 5, 32, 32);
  1421. X      break;
  1422. X    case SPACE:
  1423. X      XFillRectangle(disp, wind, sgc, j << 5, i << 5, 32, 32);
  1424. X      break;
  1425. X    case PLAYER:
  1426. X      XFillRectangle(disp, wind, pgc, j << 5, i << 5, 32, 32);
  1427. X      break;
  1428. X    case WALL:
  1429. X      XFillRectangle(disp, wind, wgc, j << 5, i << 5, 32, 32);
  1430. X      break;
  1431. X    case MAGICWALL:
  1432. X      XFillRectangle(disp, wind, Wgc, j << 5, i << 5, 32, 32);
  1433. X      break;
  1434. X    case DIAMOND:
  1435. X      XFillRectangle(disp, wind, dgc, j << 5, i << 5, 32, 32);
  1436. X      break;
  1437. X    case BOULDER:
  1438. X      XFillRectangle(disp, wind, bgc, j << 5, i << 5, 32, 32);
  1439. X      break;
  1440. X    case EXPLOSION:
  1441. X      XFillRectangle(disp, wind, xgc, j << 5, i << 5, 32, 32);
  1442. X      break;
  1443. X    case LMONSTER:
  1444. X      XFillRectangle(disp, wind, lgc, j << 5, i << 5, 32, 32);
  1445. X      break;
  1446. X    case RMONSTER:
  1447. X      XFillRectangle(disp, wind, rgc, j << 5, i << 5, 32, 32);
  1448. X      break;
  1449. X    case NUCBAL:
  1450. X      XFillRectangle(disp, wind, ngc, j << 5, i << 5, 32, 32);
  1451. X      break;
  1452. X    case BLOB:
  1453. X      XFillRectangle(disp, wind, Bgc, j << 5, i << 5, 32, 32);
  1454. X      break;
  1455. X    case TINKLE:
  1456. X      XFillRectangle(disp, wind, tgc, j << 5, i << 5, 32, 32);
  1457. X      break;
  1458. X    case EATER:
  1459. X      XFillRectangle(disp, wind, egc, j << 5, i << 5, 32, 32);
  1460. X      break;
  1461. X    case EXIT:
  1462. X      XFillRectangle(disp, wind, Egc, j << 5, i << 5, 32, 32);
  1463. X      break;
  1464. X    case STEEL:
  1465. X    default:
  1466. X      field[i][j].content = STEEL;
  1467. X      XFillRectangle(disp, wind, Sgc, j << 5, i << 5, 32, 32);
  1468. X      break;
  1469. X    }
  1470. X    field[i][j].changed = False;
  1471. X      }
  1472. X    }
  1473. X  }
  1474. X  if (scoreobs)
  1475. X    draw_score();
  1476. X}
  1477. X
  1478. Xvoid
  1479. Xset_cell(i, j, content)
  1480. X  int             i, j;
  1481. X  char            content;
  1482. X{
  1483. X  field[i][j].content = content;
  1484. X  field[i][j].speed = 0;
  1485. X  field[i][j].changed = True;
  1486. X  field[i][j].stage = 0;
  1487. X  field[i][j].caught = True;
  1488. X  field[i][j].checked = False;
  1489. X}
  1490. END_OF_FILE
  1491.   if test 9674 -ne `wc -c <'xbd/shared.c'`; then
  1492.     echo shar: \"'xbd/shared.c'\" unpacked with wrong size!
  1493.   fi
  1494.   # end of 'xbd/shared.c'
  1495. fi
  1496. if test -f 'xbd/xbd.c' -a "${1}" != "-c" ; then 
  1497.   echo shar: Will not clobber existing file \"'xbd/xbd.c'\"
  1498. else
  1499.   echo shar: Extracting \"'xbd/xbd.c'\" \(6013 characters\)
  1500.   sed "s/^X//" >'xbd/xbd.c' <<'END_OF_FILE'
  1501. X/*********************************************/
  1502. X/* you just keep on pushing my luck over the */
  1503. X/*          BOULDER        DASH              */
  1504. X/*                                           */
  1505. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  1506. X/*********************************************/
  1507. X
  1508. X#include <stdio.h>
  1509. X#include <X11/Xlib.h>
  1510. X#include <X11/keysym.h>
  1511. X#include <X11/Xutil.h>
  1512. X#include <signal.h>
  1513. X#include <sys/time.h>
  1514. X#include <sys/timeb.h>
  1515. X#include "xbd.h"
  1516. X
  1517. Xvoid
  1518. Xdie(display, event)
  1519. X  Display        *display;
  1520. X  XErrorEvent    *event;
  1521. X{
  1522. X  char            buffer[BUFSIZ];
  1523. X  XGetErrorText(display, event->error_code, buffer, BUFSIZ);
  1524. X  (void) fprintf(stderr, "Display %s: Error %s\n",
  1525. X         XDisplayName(display), buffer);
  1526. X  seteuid(getuid());
  1527. X  do
  1528. X  {
  1529. X    (void) fprintf(stderr, "(R)eturn (D)ump Core (E)xit:");
  1530. X    switch (fgetc(stdin))
  1531. X    {
  1532. X    case 'R':
  1533. X    case 'r':
  1534. X      return;
  1535. X    case 'E':
  1536. X    case 'e':
  1537. X      exit(1);
  1538. X      break;
  1539. X    case 'D':
  1540. X    case 'd':
  1541. X      kill(0, 3);
  1542. X      break;
  1543. X    default:
  1544. X      break;
  1545. X    }
  1546. X  } while (1);
  1547. X}
  1548. X
  1549. Xvoid
  1550. Xinit_vars()
  1551. X{
  1552. X  blobbreak = 100;
  1553. X  critical = 100;
  1554. X  blobcells = 0;
  1555. X  curorder = STAND;
  1556. X  gamestop = True;
  1557. X  scoreobs = True;
  1558. X  stoplevel = False;
  1559. X  levelnum = 1;
  1560. X  speed = 1;
  1561. X  lives = 4;
  1562. X  xin = 0;
  1563. X  yin = 0;
  1564. X  players = 1;
  1565. X}
  1566. X
  1567. Xstruct itimerval cycletime;    /* Structure used when setting up timer */
  1568. Xvoid
  1569. Xadapt_timer()
  1570. X{
  1571. X  long            period;
  1572. X
  1573. X  if (speed <= 0)
  1574. X    speed = 1;
  1575. X  period = (long) 3 *(long) 625000 / speed;
  1576. X  cycletime.it_interval.tv_sec = period / 1000000;
  1577. X  cycletime.it_interval.tv_usec = period % 1000000;
  1578. X  cycletime.it_value = cycletime.it_interval;
  1579. X  setitimer(ITIMER_REAL, &cycletime, (struct itimerval *) NULL);
  1580. X}
  1581. X
  1582. X/* Handle a key stroke by the user. */
  1583. Xvoid
  1584. Xhandle_key(keyhit)
  1585. X  KeySym          keyhit;    /* Key symbol for key stroke provided by X
  1586. X                 * windows */
  1587. X{
  1588. X  if (players <= 0)
  1589. X  {
  1590. X    init_level(levelnum);
  1591. X    adapt_timer();
  1592. X    XResizeWindow(disp, wind, x << 5, (y << 5) + SCORESIZE);
  1593. X    stoplevel = False;
  1594. X    draw_field(True);
  1595. X    gamestop = True;
  1596. X    players = 1;
  1597. X    return;
  1598. X  }
  1599. X  switch (keyhit)
  1600. X  {
  1601. X  case XK_question:
  1602. X  case XK_slash:
  1603. X    puts("Control the player using keyboard keys.");
  1604. X    puts("CTRL key - steal instead of go");
  1605. X    puts("h,left arrow -  left");
  1606. X    puts("l,right arrow -  right");
  1607. X    puts("k,up arrow -  up");
  1608. X    puts("j,down arrow -  down");
  1609. X    puts("\nSPACE - pause/continue game");
  1610. X    puts("^C - kill the game");
  1611. X    puts("^D - give Dutch act");
  1612. X    puts("^R - redraw the screen");
  1613. X    break;
  1614. X  case XK_space:
  1615. X  case XK_R11:
  1616. X    gamestop = !gamestop;
  1617. X    break;
  1618. X  case XK_Left:
  1619. X  case XK_H:
  1620. X  case XK_h:
  1621. X    curorder = LEFT;
  1622. X    gamestop = False;
  1623. X    break;
  1624. X  case XK_Up:
  1625. X  case XK_K:
  1626. X  case XK_k:
  1627. X    curorder = UP;
  1628. X    gamestop = False;
  1629. X    break;
  1630. X  case XK_Down:
  1631. X  case XK_J:
  1632. X  case XK_j:
  1633. X    curorder = DOWN;
  1634. X    gamestop = False;
  1635. X    break;
  1636. X  case XK_Right:
  1637. X  case XK_L:
  1638. X  case XK_l:
  1639. X    curorder = RIGHT;
  1640. X    gamestop = False;
  1641. X    break;
  1642. X  }
  1643. X}
  1644. X
  1645. X/**** Timer  procedures  ****/
  1646. X
  1647. X/* Function which is called whenever the timer signal goes off */
  1648. Xvoid
  1649. Xticker(sig)
  1650. X  int             sig;
  1651. X{
  1652. X  signal(SIGALRM, SIG_IGN);
  1653. X  /* Ignore any signal which is not an alarm.  Ignore alarm signals */
  1654. X  /* after a new level has been drawn until a key is hit. */
  1655. X  if (sig != SIGALRM)
  1656. X    return;
  1657. X  if (time)
  1658. X    time--;
  1659. X  if (tinkact)
  1660. X    tinkdur--;
  1661. X  if (time % 10 == 1)
  1662. X    scoreobs = True;
  1663. X
  1664. X  if (!gamestop)
  1665. X  {
  1666. X    calculate_field();
  1667. X    draw_field(0);
  1668. X    XFlush(disp);
  1669. X  }
  1670. X  if (stoplevel)
  1671. X  {
  1672. X    init_level(levelnum);
  1673. X    adapt_timer();
  1674. X    XResizeWindow(disp, wind, x << 5, (y << 5) + SCORESIZE);
  1675. X    XFlush(disp);
  1676. X    gamestop = True;
  1677. X    stoplevel = False;
  1678. X  }
  1679. X  signal(SIGALRM, ticker);
  1680. X}
  1681. X/**** End timer procedures ****/
  1682. X
  1683. Xvoid
  1684. Xmain(argc, argv)
  1685. X  int             argc;
  1686. X  char          **argv;
  1687. X{
  1688. X  long            period;
  1689. X  KeySym          keyhit;
  1690. X  char            buf[50];
  1691. X  static XEvent   xev;
  1692. X  int             keycount, i;
  1693. X
  1694. X  printf("type ? for help.\n");
  1695. X
  1696. X  init_vars();
  1697. X
  1698. X  /* scan the command line for executing parameters and flags */
  1699. X  for (i = 1; i < argc; ++i)
  1700. X  {
  1701. X    if (argv[i][0] == '-')
  1702. X    {
  1703. X      if (argv[i][1] == 'l')
  1704. X      {
  1705. X    if (argv[i][2] == '\0' && i + 1 < argc)
  1706. X    {
  1707. X      sscanf(argv[i + 1], "%d", &levelnum);
  1708. X      i++;
  1709. X    } else
  1710. X      sscanf(argv[i] + 2, "%d", &levelnum);
  1711. X      } else
  1712. X      {
  1713. X    printf("usage: xbd [-l <level>] \n");
  1714. X    exit(1);
  1715. X      }
  1716. X    }
  1717. X  }
  1718. X
  1719. X  levelstart = levelnum;
  1720. X  init_level(levelnum);
  1721. X  xstart(EVMASK);
  1722. X  XSetErrorHandler(die);
  1723. X  XStoreName(disp, wind, "BOULDER DASH ?");
  1724. X  make_gcs();
  1725. X  draw_field(True);
  1726. X  draw_score();
  1727. X
  1728. X  /* initialize timer structure according to speed */
  1729. X  if (speed <= 0)
  1730. X    speed = 1;
  1731. X  period = (long) 3 *(long) 625000 / speed;
  1732. X  cycletime.it_interval.tv_sec = period / 1000000;
  1733. X  cycletime.it_interval.tv_usec = period % 1000000;
  1734. X  cycletime.it_value = cycletime.it_interval;
  1735. X  /* start the system timer.  the timer signal catcher will be set */
  1736. X  /* after the first x event is received. */
  1737. X  signal(SIGALRM, SIG_IGN);
  1738. X  setitimer(ITIMER_REAL, &cycletime, (struct itimerval *) NULL);
  1739. X
  1740. X  while (lives > 0)        /* MAIN LOOP */
  1741. X  {
  1742. X    XWindowEvent(disp, wind, EVMASK, &xev);
  1743. X    signal(SIGALRM, SIG_IGN);
  1744. X    if ((xev.type == Expose && xev.xexpose.count == 0))
  1745. X    {
  1746. X      draw_field(True);
  1747. X      draw_score();
  1748. X    } else if (xev.type == KeyPress)
  1749. X    {
  1750. X      keycount = XLookupString(&xev, buf, 50, &keyhit, (XComposeStatus *) NULL);
  1751. X      if (steal = (xev.xkey.state & ControlMask))
  1752. X    switch (keyhit)
  1753. X    {
  1754. X      /* ^C, ^U kill the game */
  1755. X    case XK_C:
  1756. X    case XK_U:
  1757. X    case XK_c:
  1758. X    case XK_u:
  1759. X    case XK_backslash:
  1760. X      goto game_over;
  1761. X      /* ^D Kill; commit suicide */
  1762. X    case XK_D:
  1763. X    case XK_d:
  1764. X      curorder = KILL;
  1765. X      /* ^R redraws the level */
  1766. X    case XK_R:
  1767. X    case XK_r:
  1768. X      draw_field(True);
  1769. X      break;
  1770. X    default:
  1771. X      handle_key(keyhit);
  1772. X      break;
  1773. X    }
  1774. X      else
  1775. X    handle_key(keyhit);
  1776. X    }
  1777. X    if (!gamestop)
  1778. X    {
  1779. X      XSync(disp, False);
  1780. X      signal(SIGALRM, ticker);
  1781. X    }
  1782. X  }
  1783. Xgame_over:
  1784. X  XSync(disp, False);
  1785. X  xend();
  1786. X  add_score();
  1787. X}
  1788. END_OF_FILE
  1789.   if test 6013 -ne `wc -c <'xbd/xbd.c'`; then
  1790.     echo shar: \"'xbd/xbd.c'\" unpacked with wrong size!
  1791.   fi
  1792.   # end of 'xbd/xbd.c'
  1793. fi
  1794. if test -f 'xbd/xbd.h' -a "${1}" != "-c" ; then 
  1795.   echo shar: Will not clobber existing file \"'xbd/xbd.h'\"
  1796. else
  1797.   echo shar: Extracting \"'xbd/xbd.h'\" \(4426 characters\)
  1798.   sed "s/^X//" >'xbd/xbd.h' <<'END_OF_FILE'
  1799. X/*********************************************/
  1800. X/* you just keep on pushing my luck over the */
  1801. X/*           BOULDER        DASH             */
  1802. X/*                                           */
  1803. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  1804. X/*********************************************/
  1805. X
  1806. X/* define bit maps */
  1807. X#include "bitmap/player.bits"
  1808. X#include "bitmap/player2.bits"
  1809. X#include "bitmap/wall.bits"
  1810. X#include "bitmap/wall2.bits"
  1811. X#include "bitmap/tinkle1.bits"
  1812. X#include "bitmap/tinkle2.bits"
  1813. X#include "bitmap/space.bits"
  1814. X#include "bitmap/grass.bits"
  1815. X#include "bitmap/diamond.bits"
  1816. X#include "bitmap/diamond2.bits"
  1817. X#include "bitmap/steel.bits"
  1818. X#include "bitmap/boulder.bits"
  1819. X#include "bitmap/explosion.bits"
  1820. X#include "bitmap/rmonster.bits"
  1821. X#include "bitmap/rmonster2.bits"
  1822. X#include "bitmap/lmonster.bits"
  1823. X#include "bitmap/lmonster2.bits"
  1824. X#include "bitmap/nucbal.bits"
  1825. X#include "bitmap/blob.bits"
  1826. X#include "bitmap/blob2.bits"
  1827. X#include "bitmap/eater.bits"
  1828. X#include "bitmap/eater2.bits"
  1829. X#include "bitmap/exit2.bits"
  1830. X
  1831. X#define w 35
  1832. X#define h 26
  1833. X#define LEVELPREFIX "xbdlev"
  1834. X
  1835. X#define SCOREFONT "-adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1"
  1836. X#define SCORESIZE 18
  1837. X
  1838. X#define EVMASK KeyPressMask | ExposureMask | ButtonPressMask | PointerMotionMask | FocusChangeMask
  1839. X
  1840. X/* direction masks */
  1841. X#define N 0
  1842. X#define E 1
  1843. X#define S 2
  1844. X#define W 3
  1845. X#define NODIR 4
  1846. X
  1847. X#define SPACEEXPLO 0
  1848. X#define BOULDEXPLO 10
  1849. X#define DIAEXPLO 20
  1850. X#define PROPAGATED 10
  1851. X
  1852. X#define PLAYER              'p'
  1853. X#define SPACE               ' '
  1854. X#define LMONSTER            'l'    /* Right turning monster */
  1855. X#define RMONSTER            'r'
  1856. X#define GRASS               'g'
  1857. X#define WALL                'w'
  1858. X#define MAGICWALL           'W'    /* Expanding wall */
  1859. X#define DIAMOND             'd'
  1860. X#define STEEL               'S'
  1861. X#define BOULDER             'b'
  1862. X#define EXPLOSION           'x'
  1863. X#define EXIT                'E'
  1864. X#define EATER               'e'
  1865. X#define NUCBAL              'n'    /* Nuclear ballon */
  1866. X#define BLOB                'B'    /* lava */
  1867. X#define TINKLE              't'    /* Tinkle wall */
  1868. X
  1869. XFont            scorefont;    /* Font used to display score */
  1870. XGC              whitegc, scoregc, gc, Bgc, Bgc1, Bgc2, ngc, egc, egc1,
  1871. X                egc2, Egc1, Wgc, Wgc2, Egc2, Egc, lgc, lgc1, lgc2, rgc,
  1872. X                rgc1, rgc2, xgc, Sgc, bgc
  1873. X               ,dgc, dgc1, dgc2, wgc, pgc, pgc1, pgc2, sgc, ggc, tgc, tgc1,
  1874. X                tgc2, tgc3;
  1875. Xchar            filename[300];    /* Current file name of this level */
  1876. Xchar            levname[64];    /* Levelname */
  1877. Xint             i, j, ii, jj, jjj;
  1878. Xint             blobbreak;
  1879. Xint             critical;
  1880. Xint             time;        /* Current clock tick number */
  1881. Xint             blobcells;
  1882. Xint             tinkdur;    /* Tinkle duration */
  1883. XBool            tinkact;    /* Tinkle active   */
  1884. XBool            levincreased;
  1885. Xint             x, y, xin, yin, players, lives, levelnum, levelstart, speed,
  1886. X                diareq, diapoints, extradiapoints;
  1887. XBool            steal;        /* steal instead of go */
  1888. XBool            stoplevel, blobcollapse;
  1889. Xenum directs
  1890. X{
  1891. X  STAND, UP, DOWN, LEFT, RIGHT, KILL
  1892. X};
  1893. X
  1894. Xenum directs    curorder;    /* Current order which player has */
  1895. X/* typed at the keyboard. */
  1896. Xstruct cell
  1897. X{
  1898. X  char            content;
  1899. X  Bool            changed;    /* has cell changed since last drawing */
  1900. X  Bool            caught;    /* for BLOB */
  1901. X  Bool            checked;    /* for BLOB algorithm */
  1902. X  char            dir;
  1903. X  short           speed;
  1904. X  short           stage;    /* painting stage for blinking etc. */
  1905. X}               field[h][w];
  1906. X
  1907. XBool            gamestop;
  1908. XBool            scoreobs;    /* is score line obsolete ? */
  1909. Xint             levelnum;    /* Current level number */
  1910. Xint             lives;        /* Current number of lives */
  1911. Xint             score;        /* Total score */
  1912. Xint             speed;        /* Speed of game.  1 is slowest, 15 is
  1913. X                 * default */
  1914. Xchar            filename[300];    /* Current file name of this level */
  1915. X
  1916. XDisplay        *disp;        /* X11 display of client */
  1917. XWindow          wind;        /* X11 window where game is displayed */
  1918. X
  1919. XGC              makegc();
  1920. Xvoid            make_gcs();
  1921. Xvoid            init_level();
  1922. Xvoid            draw_score();
  1923. Xvoid            xstart();
  1924. Xvoid            xend();
  1925. Xvoid            draw_field();
  1926. Xvoid            set_cell();
  1927. Xvoid            move_cell();
  1928. Xvoid            explode();
  1929. XBool            move_monster();
  1930. XBool            search_destroy();
  1931. Xvoid            calculate_field();
  1932. Xvoid            add_score();
  1933. END_OF_FILE
  1934.   if test 4426 -ne `wc -c <'xbd/xbd.h'`; then
  1935.     echo shar: \"'xbd/xbd.h'\" unpacked with wrong size!
  1936.   fi
  1937.   # end of 'xbd/xbd.h'
  1938. fi
  1939. if test -f 'xbd/xbd.man' -a "${1}" != "-c" ; then 
  1940.   echo shar: Will not clobber existing file \"'xbd/xbd.man'\"
  1941. else
  1942.   echo shar: Extracting \"'xbd/xbd.man'\" \(3347 characters\)
  1943.   sed "s/^X//" >'xbd/xbd.man' <<'END_OF_FILE'
  1944. X.TH Boulder-dash l "April 1 1990"
  1945. X.UC 4
  1946. X.SH NAME
  1947. XBoulder-dash (v1.2) - Collect diamonds, kill monsters, close in blob etc. etc.
  1948. X.SH SYNOPSIS
  1949. X.B xbd
  1950. X[
  1951. X.B \-l
  1952. X.I level
  1953. X]
  1954. X.br
  1955. X.B xbde
  1956. X.B \-l
  1957. X.I level
  1958. X[
  1959. X.B \-w
  1960. X.I width
  1961. X]
  1962. X[
  1963. X.B \-h
  1964. X.I height
  1965. X]
  1966. X.SH DESCRIPTION
  1967. X.PP
  1968. X.I xbd
  1969. Xis a game designed for X windows (originally a similar game with the same name
  1970. Xran on CBM64).
  1971. X.I xbde
  1972. Xis used to create and edit new levels which can be used by
  1973. X.I Boulder-dash.
  1974. X.PP
  1975. XThe goal in
  1976. X.I Boulder-dash
  1977. Xis to collect a certain number
  1978. X.I (ds)
  1979. Xof diamonds per level
  1980. X.I (lv)
  1981. Xand then enter the next level by moving to the blinking exit-field, thus incrementing your number of lives
  1982. X.I (ls).
  1983. XA diamond is worth
  1984. X.I (dp)
  1985. Xpoints. Normally extra diamonds are worth more.
  1986. X.SH OPTIONS
  1987. XThe
  1988. X.B "\-l"
  1989. Xoption sets the level number for editing or for starting the game.
  1990. XThis may be any integer greater than 0.  By default, the game starts
  1991. Xat level 1. The
  1992. X.B "\-w"
  1993. Xand
  1994. X.B "\-h"
  1995. Xoptions set the width and height of a newly created level.
  1996. X.SH USAGE
  1997. XWhen playing
  1998. X.I Boulder-dash
  1999. Xthe following keyboard commands may be used:
  2000. X.PP
  2001. XSPACE,R11        \-         stop
  2002. X.br
  2003. Xh,left arrow     \-         move left
  2004. X.br
  2005. Xl,right arrow     \-         move right
  2006. X.br
  2007. Xk,up arrow     \-         move up
  2008. X.br
  2009. Xj,down arrow     \-        move down
  2010. X.PP
  2011. X.br
  2012. X?            \-        help
  2013. X.PP
  2014. XWhen used in combination with the 
  2015. X.I control key,
  2016. Xthe direction keys make the player 
  2017. X.I 'steal'
  2018. Xinstead of 
  2019. X.I 'go'.
  2020. XIn addition, some other control key combinations can be used:
  2021. X.PP
  2022. X^C        \-         kill the game
  2023. X.br
  2024. X^D        \-        give dutch act
  2025. X.br
  2026. X^R         \-         redraw the level
  2027. X.PP
  2028. XThe mouse must be placed in the game window to use the keyboard
  2029. Xcommands.  When the game starts or a level is finished , everything is frozen, and any key will
  2030. Xstart/continue the game.
  2031. X.PP
  2032. X.I xbde
  2033. Xcan be used to edit levels.  Levels are stored in ASCII files. The
  2034. Xfirst line in a level file contains level specific parameters that
  2035. Xshould be edited by hand. The parameters are:
  2036. X
  2037. X.br
  2038. Xheight width speed 
  2039. X.I dp
  2040. X.I extra-dp
  2041. Xblob-brake
  2042. Xtinkle-dur
  2043. X.I ti name
  2044. X
  2045. X.br
  2046. XWhere blob-brake indicates how strongly blob propagation is slowed down.
  2047. Xtink-dur is the time tinkle-walls will keep their magic power. 
  2048. X.I ti 
  2049. Xis the time permitted to complete this level. 
  2050. X.I name
  2051. Xis the name of the level.
  2052. X.br
  2053. XBlocks are painted by pressing the left mouse button.  Spaces are 
  2054. Xpainted by pressing the right mouse button.  A new block type is 
  2055. Xselected by one of the following keys:
  2056. X.PP
  2057. X<space> \- draw spaces
  2058. X.br
  2059. Xb \- draw boulder
  2060. X.br
  2061. Xd \- draw diamond
  2062. X.br
  2063. Xe \- draw eater (initial speed: 0)
  2064. X.br
  2065. Xg \- draw grass
  2066. X.br
  2067. Xl \- draw left-monster (initial direction: NORTH)
  2068. X.br
  2069. Xp \- draw player
  2070. X.br
  2071. Xr \- draw right-monster (initial direction: NORTH)
  2072. X.br
  2073. Xt \- draw tinkle wall
  2074. X.br
  2075. Xw \- draw wall
  2076. X.br
  2077. Xx \- draw explosion (SPACEEXPLO)
  2078. X.br
  2079. XB \- draw blob
  2080. X.br
  2081. XE \- draw exit
  2082. X.br
  2083. XN \- draw nuclear balloon
  2084. X.br
  2085. XS \- draw steel
  2086. X.br
  2087. XW \- draw magic wall
  2088. X.PP
  2089. X.br
  2090. XOther commands are:
  2091. X.PP
  2092. X.br
  2093. X^c \- Quit
  2094. X.br
  2095. X^E \- Erase level
  2096. X.br
  2097. X^w \- Save level and quit
  2098. X.SH AUTHOR
  2099. XJeroen Houttuin, Informatikdienste, ETH Zurich 1990.
  2100. X.SH CREDITS
  2101. XCBM64 for the idea. Alexander Siegel (Cornell University)
  2102. Xfor example X-programming in 
  2103. X.I 'golddig'.
  2104. XChristos S. Zoulas (Cornell University) for Imakefile and bug fixes.
  2105. X.SH FILES
  2106. Xxbd - Boulder-dash executable
  2107. X.br
  2108. Xxbde - Boulder-dash editor executable
  2109. X.br
  2110. Xscores - high score list
  2111. X.br
  2112. Xdefault - default level
  2113. X.br
  2114. Xxbdlev### - levels
  2115. END_OF_FILE
  2116.   if test 3347 -ne `wc -c <'xbd/xbd.man'`; then
  2117.     echo shar: \"'xbd/xbd.man'\" unpacked with wrong size!
  2118.   fi
  2119.   # end of 'xbd/xbd.man'
  2120. fi
  2121. if test -f 'xbd/xbde.c' -a "${1}" != "-c" ; then 
  2122.   echo shar: Will not clobber existing file \"'xbd/xbde.c'\"
  2123. else
  2124.   echo shar: Extracting \"'xbd/xbde.c'\" \(5575 characters\)
  2125.   sed "s/^X//" >'xbd/xbde.c' <<'END_OF_FILE'
  2126. X/*********************************************/
  2127. X/* you just keep on pushing my luck over the */
  2128. X/*           BOULDER        DASH             */
  2129. X/*                                           */
  2130. X/*     Jeroen Houttuin, ETH Zurich, 1990     */
  2131. X/*********************************************/
  2132. X
  2133. X#include <stdio.h>
  2134. X#include <X11/Xlib.h>
  2135. X#include <X11/keysym.h>
  2136. X#include <X11/Xutil.h>
  2137. X#include "xbd.h"
  2138. X
  2139. Xchar            curchar;
  2140. XGC              drawgc;
  2141. X
  2142. Xvoid
  2143. Xinit_vars()
  2144. X{
  2145. X  levelnum = -1;
  2146. X  xin = 0;
  2147. X  yin = 0;
  2148. X}
  2149. X
  2150. X/* Save the current level back into a file.  The global variable */
  2151. X/* filename is used to determine the file name. */
  2152. Xvoid
  2153. Xsave_level()
  2154. X{
  2155. X  FILE           *levelfile;
  2156. X  char            buf[300];
  2157. X  register int    i, j;
  2158. X
  2159. X  /* Open the data file */
  2160. X  levelfile = fopen(filename, "w");
  2161. X  if (levelfile == NULL)
  2162. X  {
  2163. X    exit(1);
  2164. X  }
  2165. X  /* Write out the size of the level.  Normal text is used so that */
  2166. X  /* levels can be easily copied across architectures. */
  2167. X  fprintf(levelfile, "%d %d %d %d %d %d %d %d %d %s\n", y, x,
  2168. X      speed, diareq, diapoints, extradiapoints, blobbreak, tinkdur, time, levname);
  2169. X  /* Terminate the lines for writing out the horizontal level lines */
  2170. X  buf[x] = '\n';
  2171. X  buf[x + 1] = '\0';
  2172. X  /* Iterate through each vertical position */
  2173. X  for (i = 0; i < y; ++i)
  2174. X  {
  2175. X    /* Copy each horizontal line into the output buffer */
  2176. X    for (j = 0; j < x; ++j)
  2177. X      buf[j] = field[i][j].content;
  2178. X    /* Write the line out to the file */
  2179. X    fputs(buf, levelfile);
  2180. X  }
  2181. X  /* Close the data file */
  2182. X  fclose(levelfile);
  2183. X}
  2184. X
  2185. X/* Main routine for editing levels */
  2186. Xvoid
  2187. Xmain(argc, argv)
  2188. X  int             argc;
  2189. X  char          **argv;
  2190. X{
  2191. X  register int    i, j;
  2192. X  static XEvent   xev;
  2193. X  KeySym          keyhit;
  2194. X  int             keycount;
  2195. X  int             tmp;
  2196. X  char            buf[50];
  2197. X
  2198. X  init_vars();
  2199. X
  2200. X  /* Read in command line options */
  2201. X  for (i = 1; i < argc; ++i)
  2202. X  {
  2203. X    if (argv[i][0] == '-')
  2204. X    {
  2205. X      /* -w sets the level width */
  2206. X      if (argv[i][1] == 'w')
  2207. X      {
  2208. X    if (argv[i][2] == '\0' && i + 1 < argc)
  2209. X    {
  2210. X      sscanf(argv[i + 1], "%d", &xin);
  2211. X      i++;
  2212. X    } else
  2213. X      sscanf(argv[i] + 2, "%d", &xin);
  2214. X      }
  2215. X      /* -h sets the level height */
  2216. X      else if (argv[i][1] == 'h')
  2217. X      {
  2218. X    if (argv[i][2] == '\0' && i + 1 < argc)
  2219. X    {
  2220. X      sscanf(argv[i + 1], "%d", &yin);
  2221. X      i++;
  2222. X    } else
  2223. X      sscanf(argv[i] + 2, "%d", &yin);
  2224. X      }
  2225. X      /* -l sets the level number */
  2226. X      else if (argv[i][1] == 'l')
  2227. X      {
  2228. X    if (argv[i][2] == '\0' && i + 1 < argc)
  2229. X    {
  2230. X      sscanf(argv[i + 1], "%d", &levelnum);
  2231. X      i++;
  2232. X    } else
  2233. X      sscanf(argv[i] + 2, "%d", &levelnum);
  2234. X      } else
  2235. X      {
  2236. X    printf("usage: xbde [-h <height>] [-w <width>] -l <level> \n");
  2237. X    exit(1);
  2238. X      }
  2239. X    }
  2240. X  }
  2241. X  /* Make sure some value was chosen for the level number.  This */
  2242. X  /* discourages everybody editing the same level all the time. */
  2243. X  if (levelnum == -1)
  2244. X  {
  2245. X    printf("usage: editor [-h <height>] [-w <width>] -l <level> \n");
  2246. X    exit(1);
  2247. X  }
  2248. X  /* Load in level data from file. */
  2249. X  init_level(levelnum);
  2250. X
  2251. X  printf("Welcome.  Type h for help.\n");
  2252. X
  2253. X  /* Start up X windows and create all graphics cursors */
  2254. X  xstart(EVMASK);
  2255. X  /* Set the name of the output window */
  2256. X  XStoreName(disp, wind, "BOULDER DASH - LEVEL EDITOR");
  2257. X  XFlush(disp);            /* initializing flush */
  2258. X  make_gcs();
  2259. X  Egc = Egc2;
  2260. X  Wgc = Wgc2;
  2261. X  tgc = tgc3;
  2262. X  drawgc = pgc;
  2263. X  draw_field(True);
  2264. X
  2265. X  /* Main event loop */
  2266. X  do
  2267. X  {
  2268. X    /* Get the next X window event */
  2269. X    XWindowEvent(disp, wind, EVMASK, &xev);
  2270. X
  2271. X    /* If it was an expose event, redraw everything */
  2272. X    if (xev.type == Expose)
  2273. X    {
  2274. X      draw_field(True);
  2275. X      draw_score();
  2276. X    } else if (xev.type == KeyPress)
  2277. X    {
  2278. X      keycount = XLookupString(&xev, buf, 50, &keyhit, (XComposeStatus *) NULL);
  2279. X      /* If the 'h', '?' or '/' key was hit, print out the text */
  2280. X      /* descriptions of each block type */
  2281. X      if (keyhit == XK_H || keyhit == XK_h || keyhit == XK_question ||
  2282. X      keyhit == XK_slash)
  2283. X      {
  2284. X    puts("^w - finish editing and save the level.");
  2285. X    puts("^c - quit editing.");
  2286. X    puts("^E - erase level.");
  2287. X    puts("Use the left mouse button to paint blocks.");
  2288. X    puts("Use the right mouse button to erase blocks.");
  2289. X    putchar('\n');
  2290. X      }
  2291. X      /* A ^E erases the entire level */
  2292. X      else if ((keyhit == XK_E) &&
  2293. X           (xev.xkey.state & ControlMask))
  2294. X      {
  2295. X    /* Replace level contents with space */
  2296. X    for (i = 0; i < y; ++i)
  2297. X      for (j = 0; j < x; ++j)
  2298. X        if ((i == 0) || (i == y - 1) || (j == 0) || (j == x - 1))
  2299. X          set_cell(i, j, STEEL);
  2300. X        else
  2301. X          set_cell(i, j, SPACE);
  2302. X    /* Redraw empty level */
  2303. X    draw_field(False);
  2304. X      } else
  2305. X    curchar = keyhit;
  2306. X    }
  2307. X    /* If the mouse moves with the button pressed, or the button is */
  2308. X    /* pressed, draw the current block at that position */
  2309. X    else if (xev.type == MotionNotify)
  2310. X    {
  2311. X      if (xev.xmotion.state & Button3Mask)
  2312. X    set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, SPACE);
  2313. X      else if (xev.xmotion.state & Button1Mask)
  2314. X    set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, curchar);
  2315. X    } else if (xev.type == ButtonPress)
  2316. X    {
  2317. X      if (xev.xbutton.button == Button3)
  2318. X    set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, SPACE);
  2319. X      else
  2320. X    set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, curchar);
  2321. X    }
  2322. X    draw_field(False);
  2323. X    XFlush(disp);
  2324. X    /* Loop until a control key is pressed */
  2325. X  } while (xev.type != KeyPress ||
  2326. X       (keyhit != XK_C && keyhit != XK_c &&
  2327. X        keyhit != XK_W && keyhit != XK_w) ||
  2328. X       !(xev.xkey.state & ControlMask));
  2329. X
  2330. X  /* Save level to data file */
  2331. X  if (keyhit == XK_W || keyhit == XK_w)
  2332. X    save_level();
  2333. X  xend();
  2334. X  exit(0);
  2335. X}
  2336. END_OF_FILE
  2337.   if test 5575 -ne `wc -c <'xbd/xbde.c'`; then
  2338.     echo shar: \"'xbd/xbde.c'\" unpacked with wrong size!
  2339.   fi
  2340.   # end of 'xbd/xbde.c'
  2341. fi
  2342. echo shar: End of archive.
  2343. exit 0
  2344.  
  2345. dan
  2346. ----------------------------------------------------
  2347. O'Reilly && Associates   argv@sun.com / argv@ora.com
  2348. Opinions expressed reflect those of the author only.
  2349.