news@sun.Eng.Sun.COM (news) (11/01/90)
Submitted-by: ethz!houttuin (Jeroen Houttuin) Posting-number: Volume 10, Issue 47 Archive-name: xbd/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: xbd/Imakefile xbd/Makefile.orig xbd/README xbd/README.1.2 # xbd/bitmap xbd/default xbd/field.c xbd/patchlevel.h xbd/scores # xbd/scores.c xbd/shared.c xbd/xbd.c xbd/xbd.h xbd/xbd.man # xbd/xbde.c # Wrapped by houttuin@ural on Fri Oct 26 10:16:13 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive."' if test -f 'xbd/Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/Imakefile'\" else echo shar: Extracting \"'xbd/Imakefile'\" \(2153 characters\) sed "s/^X//" >'xbd/Imakefile' <<'END_OF_FILE' X#/*********************************************/ X#/* you just keep on pushing my luck over the */ X#/* BOULDER DASH */ X#/* */ X#/*Imakefile:christos@guillemin.EE.CORNELL.edu*/ X#/*********************************************/ X XGAME = xbd XEDITOR = xbde XPROGRAMS = ${GAME} ${EDITOR} XCDEBUGFLAGS = -O XSCOREFONT = -adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1 XSCORESIZE = 18 XMANDIR = /usr/local/man/man6 XBINDIR = /usr/local/games XLIBDIR = /usr/local/games/lib/xbd XDEFINES = -DLIB=\"${LIBDIR}\" \ X -DSCOREFONT=\"${SCOREFONT}\" \ X -DSCORESIZE=${SCORESIZE} XLOCAL_LIBRARIES = $(XLIB) XSYS_LIBRARIES = -lm XLEVELS = xbdlev001 xbdlev002 xbdlev003 xbdlev004 xbdlev005 \ X xbdlev006 xbdlev007 xbdlev008 xbdlev009 xbdlev010 \ X xbdlev011 xbdlev012 xbdlev013 xbdlev014 xbdlev015 \ X xbdlev016 xbdlev017 xbdlev018 xbdlev019 xbdlev020 \ X xbdlev021 xbdlev022 xbdlev023 xbdlev024 xbdlev025 \ X xbdlev026 xbdlev027 xbdlev028 xbdlev029 xbdlev030 \ X xbdlev031 xbdlev032 xbdlev033 xbdlev034 xbdlev035 \ X xbdlev036 xbdlev037 xbdlev038 X XOBJS1 = xbd.o shared.o field.o scores.o XOBJS2 = xbde.o shared.o X XSRCS1 = xbd.o shared.o field.o scores.o XSRCS2 = xbde.o shared.o X XAllTarget(${PROGRAMS}) XNormalProgramTarget(${GAME},${OBJS1},,$(LOCAL_LIBRARIES),) XNormalProgramTarget(${EDITOR},${OBJS2},,$(LOCAL_LIBRARIES),) XInstallProgramWithFlags(${GAME},${BINDIR}/${GAME},-s -m 4755 -o games) XInstallProgramWithFlags(${EDITOR},${BINDIR}/${EDITOR},-s -o games) X Xinstall.man:: xbd.man X ${INSTALL} -c -m 0444 xbd.man ${MANDIR}/xbd.6 X Xinstall:: ${PROGRAMS} X -mkdir ${LIBDIR} X chown games ${LIBDIR} X touch ${LIBDIR}/scores X chown games ${LIBDIR}/scores X (cp ${LEVELS} ${LIBDIR}) X cp default ${LIBDIR} X (cd ${LIBDIR}; \ X chown games ${LEVELS} default scores; \ X chmod 644 ${LEVELS} default scores;) END_OF_FILE if test 2153 -ne `wc -c <'xbd/Imakefile'`; then echo shar: \"'xbd/Imakefile'\" unpacked with wrong size! fi # end of 'xbd/Imakefile' fi if test -f 'xbd/Makefile.orig' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/Makefile.orig'\" else echo shar: Extracting \"'xbd/Makefile.orig'\" \(1033 characters\) sed "s/^X//" >'xbd/Makefile.orig' <<'END_OF_FILE' X#/* you just keep on pushing my luck over the */ X#/* BOULDER DASH */ X XGAME = xbd XEDITOR = xbde X X#BIN = /usr/local/bin XBIN = ${HOME}/xbd XLIB = ${HOME}/xbd X X# manual pages XMAN = /usr/man X XSCOREFONT = -adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1 XSCORESIZE = 18 X XCC = cc X XCFLAGS = -g XLDFLAGS = -g X Xall: ${GAME} ${EDITOR} X Xinstall: all X -mkdir ${LIB} X cp ${GAME} ${EDITOR} ${BIN} X chmod 4755 ${BIN}/${GAME} X touch ${LIB}/scores X chmod 644 ${LIB}/xbdlev* X chmod 644 ${LIB}/default X chmod 644 ${LIB}/scores X cp xbd.man ${MAN} X Xupdate: all X cp ${GAME} ${EDITOR} ${BIN} X chmod 4755 ${BIN}/${GAME} X Xclean: X rm -f *.o core ${GAME} ${EDITOR} X XSRCS = xbd.c shared.c field.c scores.c XOBJS = xbd.o shared.o field.o scores.o X Xlint: X lint -DLIB=\"${LIB}\" -DSCOREFONT=\"${SCOREFONT}\" \ X -DSCORESIZE=${SCORESIZE} ${SRCS} X X${GAME}: ${OBJS} X ${CC} ${LDFLAGS} -o ${GAME} ${OBJS} -lX11 X X${EDITOR}: xbde.o shared.o X ${CC} ${LDFLAGS} -o ${EDITOR} xbde.o shared.o -lX11 X X.c.o: X ${CC} ${CFLAGS} -c -DLIB=\"${LIB}\" $< END_OF_FILE if test 1033 -ne `wc -c <'xbd/Makefile.orig'`; then echo shar: \"'xbd/Makefile.orig'\" unpacked with wrong size! fi chmod +x 'xbd/Makefile.orig' # end of 'xbd/Makefile.orig' fi if test -f 'xbd/README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/README'\" else echo shar: Extracting \"'xbd/README'\" \(414 characters\) sed "s/^X//" >'xbd/README' <<'END_OF_FILE' XBoulder-dash is still in an experimental phase. Mail your Xbug reports, interesting new levels, ideas to the author Xor to xbd@ks.id.ethz.ch. X X X X X XDON'T DISTRIBUTE ANY MODIFIED VERSIONS ! X X X X XJeroen Houttuin XInformatikdienste-Kommunikationssysteme XETH Zentrum RZ-H7 XCH-8092 Zurich Xtel +41-1-2565837 Xfax +41-1-2615389 Xe-mail: houttuin@ks.id.ethz.ch XX.400 : C=CH;ADMD=ARCOM;PRMD=SWITCH;O=ETHZ;OU=id;OU=ks;S=houttuin END_OF_FILE if test 414 -ne `wc -c <'xbd/README'`; then echo shar: \"'xbd/README'\" unpacked with wrong size! fi # end of 'xbd/README' fi if test -f 'xbd/README.1.2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/README.1.2'\" else echo shar: Extracting \"'xbd/README.1.2'\" \(842 characters\) sed "s/^X//" >'xbd/README.1.2' <<'END_OF_FILE' X-Time limits per level are implemented. X-Every level has a name now. X-You can now also DRAW blocks in the editor. X-People can now create levels by setting the environment variable XBDLIB X to point to a directory that they can write to. X-Tinkle walls were implemented (character 't'). Every level has a tinkle X duration parameter. X X-For new ideas, levels etc. a distribution list has been created: X xbd@ks.id.ethz.ch X X-Thanks for improvements: X Tad.Davis@Central.Sun.com X Fernando Mira da Silva <fcr@joyce.inesc.pt> X Josh Siegel <siegel@Sun.com> X ccsteve@cc.uq.oz.au X George Ferguson <ferguson@cs.rochester.edu> X Charles D. Farnum <farnum@cypress.Berkeley.edu> X Lloyd Taylor <lloyd@aplcen.apl.jhu.edu> X Michael Glad <glad@daimi.aau.dk> X X-Special thanks for Imakefile and most bug fixes : X Christos S. Zoulas <christos@hyperion.EE.CORNELL.edu> END_OF_FILE if test 842 -ne `wc -c <'xbd/README.1.2'`; then echo shar: \"'xbd/README.1.2'\" unpacked with wrong size! fi # end of 'xbd/README.1.2' fi if test ! -d 'xbd/bitmap' ; then echo shar: Creating directory \"'xbd/bitmap'\" mkdir 'xbd/bitmap' fi if test -f 'xbd/default' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/default'\" else echo shar: Extracting \"'xbd/default'\" \(979 characters\) sed "s/^X//" >'xbd/default' <<'END_OF_FILE' X26 35 15 12 0 0 200 200 1000 Default_level XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS XS b e bp S XS www www w w w ww www www S XS wrw wrw w w w w w w wrw S XS www w w w w w w w ww www nS XS wrw wpw wBwrw wrw w wwe S XS wwwlwww www www ww www wnw S XS S XS bd bd S XS gwww wwwww wwwww w w S XS wl w w w wdbb w w S XS w w w w w w w S XS wB wg wwEBw w w w S XS wBB wg ww Bw w w w S XS wBB wg ww Bw w w w S XSgbg wBB wg ww Bw w d wp w S XSglg wBBBwg wwwww wtttw w W nS XSglg wBBBwg w w w w w S XSggg w wg w w w w w S XSglg w wg w w w w w nS XSgeg w w w w w w w S XSgbg we w w w w w w S XSg g gwww rw w twwtw w w S XSg g S XSgeg n e ES XSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS END_OF_FILE if test 979 -ne `wc -c <'xbd/default'`; then echo shar: \"'xbd/default'\" unpacked with wrong size! fi # end of 'xbd/default' fi if test -f 'xbd/field.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/field.c'\" else echo shar: Extracting \"'xbd/field.c'\" \(13876 characters\) sed "s/^X//" >'xbd/field.c' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/keysym.h> X#include <X11/Xutil.h> X#include <signal.h> X#include <sys/time.h> X#include <sys/timeb.h> X#include "xbd.h" X Xvoid Xblink(i, j) X int i, j; X{ X field[i][j].changed = True; X} X Xvoid Xmove_cell(i, j, ii, jj) X int i, j, ii, jj; X{ X field[ii][jj] = field[i][j]; X field[ii][jj].speed = 1; X field[ii][jj].changed = True; X field[ii][jj].dir = ((ii - i) == 1) ? S : ((i - ii) == 1) ? N : ((jj - j) == 1) ? E : W; X set_cell(i, j, SPACE); X} X Xvoid Xexplode(a, b, stage) X int a, b, stage; X{ X if (field[a][b].content != STEEL) X { X set_cell(a, b, EXPLOSION); X field[a][b].stage = stage; /* dirty fix, not what stage was meant for */ X } X} X XBool Xmove_nucbal(i, j, t) X int i, j, t; X{ X ii = (!t) ? (i + y - 1) % y : i; X if (!t) X jj = j; X else X switch (field[i][j].dir) X { X case E: X jj = (t == 1) ? (j + x - 1) % x : (j + 1) % x; X break; X case W: X default: X jj = (t == 2) ? (j + x - 1) % x : (j + 1) % x; X break; X } X switch (field[ii][jj].content) X { X case SPACE: X move_cell(i, j, ii, jj); X return (True); X case NUCBAL: X explode(i, j, DIAEXPLO); X explode(ii, jj, DIAEXPLO); X return (True); X default: X if (field[i][j].dir == N) X field[i][j].dir = E; X else X field[i][j].dir = ((field[i][j].dir + 2) % 4); /* turn around */ X return (False); X } X} X XBool Xmove_monster(content, direction) X char content, direction; X{ X switch (direction) X { X case N: X ii = (i + y - 1) % y; X jj = j; X break; X case E: X jj = (j + 1) % x; X ii = i; X break; X case S: X ii = (i + 1) % y; X jj = j; X break; X default: X jj = (j + x - 1) % x; X ii = i; X break; /* default must be SOMEthing, West */ X } X switch (field[ii][jj].content) X { X case SPACE: X if (!field[ii][jj].changed) X { X move_cell(i, j, ii, jj); X field[ii][jj].dir = direction; X return (True); X } else X return (False); X break; X case BOULDER: X case DIAMOND: X if ((direction == N) && (field[ii][jj].speed != 0)) X if (content == RMONSTER) X { X explode(i, j, DIAEXPLO); X return (True); X } else if (content == LMONSTER) X { X explode(i, j, SPACEEXPLO); X return (True); X } else X return (False); X else X return (False); X break; X default: X return (False); X break; X } X return (False); X} X XBool Xsearch_destroy(content) X char content; X{ X ii = (i + y - 1) % y; X jj = (j + x - 1) % x; X if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB) X { X set_cell(i, j, SPACE); X if (field[i][jj].content == PLAYER) X { X lives--; X scoreobs = True; X } X if (content == RMONSTER) X explode(i, jj, DIAEXPLO); X else X explode(i, jj, SPACEEXPLO); X return (True); X } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB) X { X set_cell(i, j, SPACE); X if (field[ii][j].content == PLAYER) X { X lives--; X scoreobs = True; X } X if (content == RMONSTER) X explode(ii, j, DIAEXPLO); X else X explode(ii, j, SPACEEXPLO); X return (True); X } else X { X ii = (i + 1) % y; X jj = (j + 1) % x; X if (field[i][jj].content == PLAYER || field[i][jj].content == BLOB) X { X set_cell(i, j, SPACE); X if (field[i][jj].content == PLAYER) X { X lives--; X scoreobs = True; X } X if (content == RMONSTER) X explode(i, jj, DIAEXPLO); X else X explode(i, jj, SPACEEXPLO); X return (True); X } else if (field[ii][j].content == PLAYER || field[ii][j].content == BLOB) X { X set_cell(i, j, SPACE); X if (field[ii][j].content == PLAYER) X { X lives--; X scoreobs = True; X } X if (content == RMONSTER) X explode(ii, j, DIAEXPLO); X else X explode(ii, j, SPACEEXPLO); X return (True); X } else X return (False); X } X} X Xvoid Xpropagate(i, j, dias) X int i, j; X Bool dias; X{ X int t, it, jt; X if (dias) X set_cell(i, j, DIAMOND); X else X { X field[i][j].checked = PROPAGATED; X field[i][j].caught = True; X } X for (t = 0; (t < 4); ++t) X { X it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i; /* neigbour X * right,up,left,down */ X jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j; /* neigbour X * right,up,left,down */ X switch (field[it][jt].content) X { X case BLOB: X if (field[it][jt].checked != PROPAGATED) X propagate(it, jt, dias); X break; X case SPACE: X case GRASS: X if (!(rand() % (blobbreak + 1))) X { X set_cell(it, jt, BLOB); X field[it][jt].checked = PROPAGATED; X field[it][jt].caught = True; X } X break; X default: X break; X } X } X} X XBool Xcaught(i, j) X int i, j; X{ X Bool Free; X int t, it, jt; X X field[i][j].checked = 1; X Free = False; X X for (t = 0; ((t < 4) && !Free); ++t) X { X it = (t == 1) ? (i + y - 1) % y : (t == 3) ? (i + 1) % y : i; /* neigbour X * right,up,left,down */ X jt = (t == 2) ? (j + x - 1) % x : (t == 0) ? (j + 1) % x : j; /* neigbour X * right,up,left,down */ X X switch (field[it][jt].content) X { X case SPACE: X case GRASS: X case RMONSTER: X case LMONSTER: X case EATER: X Free = True; X break; X case BLOB: X Free = (Free || ((field[it][jt].checked == 1) ? !field[i][j].caught X : !caught(it, jt) X ) X ); X break; X default: X break; X } X } X field[i][j].caught != Free; X return (!Free); X} X Xvoid Xdiaboulderproc(i, j) X int i, j; X{ X if (field[i][j].content == DIAMOND) X blink(i, j); X ii = (ii + 1) % y; X field[i][j].dir = NODIR; X switch (field[ii][j].content) X { X case SPACE: /* directly underneath */ X move_cell(i, j, ii, j); X field[ii][j].speed = 1; X break; X case PLAYER: X if (field[i][j].speed) X { X set_cell(i, j, SPACE); X explode(ii, j, SPACEEXPLO); X lives--; X scoreobs = True; X } X break; X case LMONSTER: X case EATER: X if (field[i][j].speed) X { X set_cell(i, j, SPACE); X explode(ii, j, SPACEEXPLO); X } X break; X case RMONSTER: X if (field[i][j].speed) X { X set_cell(i, j, SPACE); X explode(ii, j, DIAEXPLO); X } X break; X case TINKLE: X if (field[i][j].speed) X { X tinkact = True; X field[ii][j].stage = field[i][j].content; X field[ii][j].speed = 1; X set_cell(i, j, SPACE); X break; X } X break; X case WALL: X case BOULDER: X case DIAMOND: X case EXPLOSION: X jj = (j + 1) % x; X if (field[i][jj].content == SPACE && field[ii][jj].content == SPACE) X { X move_cell(i, j, i, jj); X field[i][jj].speed = 0; X } else X { X jj = (j - 1) % x; X if (field[i][jj].content == SPACE X && field[ii][jj].content == SPACE) X { X move_cell(i, j, i, jj); X field[i][jj].speed = 0; X } else X field[i][j].speed = 0; X } X break; X default: X field[i][j].speed = 0; X break; X } X} X Xvoid Xcalculate_field() X{ X players = 0; X /* Iterate through each horizontal line */ X if (!time) X curorder = KILL; X for (i = y - 1; i >= 0; --i) X { X for (j = 0; j < x; ++j) X { X if (!(field[i][j].changed)) X { X ii = i; X jj = j; X switch (field[i][j].content) X { X case PLAYER: X players++; X switch (curorder) /* find cell player wants to go to */ X { X case STAND: X break; X case UP: X ii = (i + y - 1) % y; X break; X case DOWN: X ii = (i + 1) % y; X break; X case LEFT: X jj = (j + x - 1) % x; X break; X case RIGHT: X jj = (j + 1) % x; X break; X } X if (!(curorder == STAND) && !(field[i][j].changed)) X { X if (curorder == KILL) X { X set_cell(i, j, EXPLOSION); X lives--; X scoreobs = True; X break; X } X switch (field[ii][jj].content) /* check cell player wants to X * go to */ X { X case SPACE: X case GRASS: X case DIAMOND: X if (field[ii][jj].content == DIAMOND) X { X if (curorder == UP && field[ii][jj].speed) X break; X score += diapoints; X if (diareq) X diareq--; X scoreobs = True; X } X if (steal) X set_cell(ii, jj, SPACE); X else X move_cell(i, j, ii, jj); X break; X case BOULDER: X jjj = (2 * jj - j + x) % x; /* the cell behind the X * boulder */ X if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) && X !(field[ii][jj].dir == E)) X { X move_cell(i, jj, i, jjj); X field[i][jjj].speed = 0; X if (!steal) X { X move_cell(i, j, i, jj); X } X } X break; X case EXIT: X if (diareq < 1) X { X if (!steal) X move_cell(i, j, ii, jj); X else X set_cell(ii, jj, SPACE); X if (!levincreased) X { X levelnum++; X lives++; X levincreased = True; X for (jj = time / 10; jj > 0; --jj) X { X score += 10; X draw_score(); X XFlush(disp); X } X } X gamestop = True; X stoplevel = True; X } X break; X } X } X blink(i, j); X break; X case DIAMOND: X case BOULDER: X diaboulderproc(i, j); X break; X case EATER: X if (!field[i][j].speed) X { X for (jjj = 0; ((!field[i][j].changed) && (jjj < 4)); ++jjj) X { X ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i; X jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j; X switch (field[ii][jj].content) X { X case PLAYER: X lives--; X scoreobs = True; X case DIAMOND: X if (field[ii][jj].speed && (ii == i - 1) && (jj == j)) X break; X case BLOB: X case LMONSTER: X case RMONSTER: X case NUCBAL: X move_cell(i, j, ii, jj); X break; X default: X break; X } X } X } else X { X jjj = field[i][j].dir; X ii = (jjj == 2) ? (i + 1) % y : (jjj == 0) ? (i + y - 1) % y : i; X jj = (jjj == 1) ? (j + 1) % x : (jjj == 3) ? (j + x - 1) % x : j; X switch (field[ii][jj].content) X { X case LMONSTER: X case BLOB: X case SPACE: X case GRASS: X case DIAMOND: X case RMONSTER: X case PLAYER: X case NUCBAL: X if (field[ii][jj].content == PLAYER) X { X lives--; X scoreobs = True; X } X move_cell(i, j, ii, jj); X break; X case BOULDER: X jjj = (2 * jj - j + x) % x; /* the cell behind the X * boulder */ X if (field[i][jjj].content == SPACE && ((rand() % 2) == 0) && !(field[ii][jj].dir == E)) X { X move_cell(i, jj, i, jjj); X move_cell(i, j, i, jj); X } else X field[i][j].speed = 0; X break; X default: X field[i][j].speed = 0; X break; X } X } X blink(i, j); X break; X case RMONSTER: X blink(i, j); X if (search_destroy(RMONSTER)) X break; X jjj = 3; X while (jjj >= 0 && !move_monster(RMONSTER, (field[i][j].dir + jjj + 2) % 4)) X jjj--; X break; X case LMONSTER: X blink(i, j); X if (search_destroy(LMONSTER)) X break; X jjj = 0; X while (jjj <= 4 && !move_monster(LMONSTER, (field[i][j].dir + jjj + 3) % 4)) X jjj++; X break; X case EXPLOSION: X jjj = field[i][j].stage; X if (!(jjj % 5)) /* this is the initiating explosion */ X { X jjj++; /* use jjj for setting new stage */ X ii = (i + 1) % y; X jj = (j + 1) % x; X explode(i, j, jjj); X explode(i, jj, jjj); X explode(ii, j, jjj); X explode(ii, jj, jjj); X ii = (i + y - 1) % y; X explode(ii, j, jjj); X explode(ii, jj, jjj); X jj = (j + x - 1) % x; X explode(ii, jj, jjj); X explode(i, jj, jjj); X ii = (i + 1) % y; X explode(ii, jj, jjj); X } else X { X if (jjj % 10 < 3) X field[i][j].stage++; X else if (jjj > DIAEXPLO) X { X set_cell(i, j, DIAMOND); X } else if (jjj > BOULDEXPLO) X { X set_cell(i, j, BOULDER); X } else if (jjj > SPACEEXPLO) X { X set_cell(i, j, SPACE); X } else X field[i][j].stage++; X } X break; X case EXIT: X blink(i, j); X break; X case BLOB: X blobcells++; X if (blobcollapse) X set_cell(i, j, BOULDER); X else X { X if (blobcells > critical) X blobcollapse = True; X else X { X if (!field[i][j].checked) X { X if (caught(i, j)) X propagate(i, j, DIAMOND); X else X propagate(i, j, False); X } X field[i][j].checked = False; X field[i][j].caught = True; X } X } X blink(i, j); X break; X case NUCBAL: X for (jjj = 0; ((jjj < 3) && !move_nucbal(i, j, jjj)); ++jjj); X blink(i, j); X break; X case MAGICWALL: X jj = (j + x - 1) % x; X if (field[i][jj].content == SPACE) X set_cell(i, jj, MAGICWALL); X jj = (j + 1) % x; X if (field[i][jj].content == SPACE) X set_cell(i, jj, MAGICWALL); X break; X case TINKLE: X if (tinkact) X { X blink(i, j); X if (tinkdur > 0) X { X switch (field[i][j].stage) X { X case BOULDER: X { X field[i][j].content = DIAMOND; X diaboulderproc(i, j); X break; X } X case DIAMOND: X { X field[i][j].content = BOULDER; X diaboulderproc(i, j); X break; X } X default: X break; X } X } X } X set_cell(i, j, TINKLE); /* reset to empty tinkle wall */ X break; X default: X break; X } X } X } X } X curorder = STAND; /* reset orders */ X blobcells = 0; X pgc = (pgc == pgc1) ? ((rand() % 22) == 0) ? pgc2 : pgc1 : X pgc1; X dgc = (dgc == dgc1) ? dgc2 : dgc1; X lgc = (lgc == lgc1) ? lgc2 : lgc1; X rgc = (rgc == rgc1) ? rgc2 : rgc1; X egc = (egc == egc1) ? egc2 : egc1; X Bgc = (Bgc == Bgc1) ? Bgc2 : Bgc1; X if (tinkact) X tgc = (tgc == tgc1) ? tgc2 : tgc1; X if (!diareq) X { X Egc = (Egc == Egc1) ? Egc2 : Egc1; X if (diareq == 0) X { X diapoints = extradiapoints; X scoreobs = True; X } X } X} END_OF_FILE if test 13876 -ne `wc -c <'xbd/field.c'`; then echo shar: \"'xbd/field.c'\" unpacked with wrong size! fi # end of 'xbd/field.c' fi if test -f 'xbd/patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/patchlevel.h'\" else echo shar: Extracting \"'xbd/patchlevel.h'\" \(21 characters\) sed "s/^X//" >'xbd/patchlevel.h' <<'END_OF_FILE' X#define PATCHLEVEL 0 END_OF_FILE if test 21 -ne `wc -c <'xbd/patchlevel.h'`; then echo shar: \"'xbd/patchlevel.h'\" unpacked with wrong size! fi # end of 'xbd/patchlevel.h' fi if test -f 'xbd/scores' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/scores'\" else echo shar: Extracting \"'xbd/scores'\" \(405 characters\) sed "s/^X//" >'xbd/scores' <<'END_OF_FILE' X2800 27 30 houttuin X1833 12 14 houttuin X1770 22 23 houttuin X1690 15 16 houttuin X1680 37 38 houttuin X1626 27 29 houttuin X1350 36 36 houttuin X1302 2 4 houttuin X1284 17 18 houttuin X1160 37 37 houttuin X1120 77 78 houttuin X1110 2 3 houttuin X1020 77 77 houttuin X960 25 25 houttuin X955 2 3 houttuin X950 36 36 houttuin X934 13 14 houttuin X930 16 16 houttuin X902 2 3 houttuin X883 33 34 houttuin END_OF_FILE if test 405 -ne `wc -c <'xbd/scores'`; then echo shar: \"'xbd/scores'\" unpacked with wrong size! fi # end of 'xbd/scores' fi if test -f 'xbd/scores.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/scores.c'\" else echo shar: Extracting \"'xbd/scores.c'\" \(3472 characters\) sed "s/^X//" >'xbd/scores.c' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/keysym.h> X#include "xbd.h" X Xchar *getenv(); X X#define NUMHIGH 20 /* Number of high scores that will be X * remembered */ X X/* Add a high score to the high score list */ Xvoid Xadd_score() X{ X /* Structure containing top game results */ X struct X { X int score; /* Final score */ X int slev, elev; /* Starting and ending level */ X char desc[80]; /* Text description */ X } tops[NUMHIGH], next; X FILE *sfile; /* High score file */ X char buf[200]; X register int i; X int numscore, cur, numgame; X X /* Generate name of high score file */ X sprintf(buf, "%s/scores", LIB); X /* Open high score file */ X sfile = fopen(buf, "r"); X /* Set default values for number of games and high scores */ X numscore = 0; X numgame = 0; X /* If file is readable, load in old high score list */ X if (sfile != NULL) X { X /* Extract score information from line */ X while (fgets(buf, 200, sfile) && numscore < NUMHIGH) X { X sscanf(buf, "%d %d %d %[^\n]", &(next.score), &(next.slev), &(next.elev), X next.desc); X tops[numscore] = next; X numscore++; X } X fclose(sfile); X } X /* Contruct the structure containing the score for this game */ X next.score = score; X next.slev = levelstart; X next.elev = levelnum; X#ifndef hpux X sprintf(next.desc, "%s ", getenv("USER")); X#else X sprintf(next.desc, "%s ", getenv("LOGNAME")); X#endif X cur = -1; X /* Insert new score in old high score list */ X if (numscore < NUMHIGH || tops[NUMHIGH - 1].score < next.score) X { X /* Iterate through high score list */ X for (i = (numscore >= NUMHIGH ? NUMHIGH - 2 : numscore - 1); i >= 0; i--) X { X /* Look for place for insertion */ X if (next.score > tops[i].score) X tops[i + 1] = tops[i]; /* Move old scores down one place in list */ X else X break; /* Found spot for insertion */ X } X tops[i + 1] = next; /* Overwrite entry in high score list */ X cur = i + 1; /* Remember where new high score was inserted */ X /* Increment the number of high scores */ X if (numscore < NUMHIGH) X numscore++; X } X /* Increment and print the number of games played */ X /* Print out new high score list */ X for (i = 0; i < numscore; ++i) X { X /* Flag new high score with a leading > */ X if (i == cur) X putchar('*'); X else X putchar(' '); X printf("%-16s- Died on level %3d. Started on level %3d. Score: %8d.\n", X tops[i].desc, tops[i].elev, tops[i].slev, tops[i].score); X } X /* If current game did not make it to the high score list, print it */ X /* afterwords */ X if (cur == -1) X { X puts("You are quite disappointing:"); X printf("*%-16s- Died on level %3d. Started on level %3d. Score: %8d.\n", X next.desc, next.elev, next.slev, next.score); X } X /* Save new high score list to score file */ X sprintf(buf, "%s/scores", LIB); X sfile = fopen(buf, "w"); X if (sfile == NULL) X { X perror(buf); X return; X } X for (i = 0; i < numscore; ++i) X fprintf(sfile, "%d %d %d %s\n", tops[i].score, tops[i].slev, X tops[i].elev, tops[i].desc); X fclose(sfile); X} END_OF_FILE if test 3472 -ne `wc -c <'xbd/scores.c'`; then echo shar: \"'xbd/scores.c'\" unpacked with wrong size! fi # end of 'xbd/scores.c' fi if test -f 'xbd/shared.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/shared.c'\" else echo shar: Extracting \"'xbd/shared.c'\" \(9674 characters\) sed "s/^X//" >'xbd/shared.c' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/keysym.h> X#include <X11/Xutil.h> X#include <errno.h> X#include <sys/time.h> X#include <sys/timeb.h> X#include "xbd.h" X X/* Manufaction a 32x32 graphics cursor used in a XFill... operation. */ XGC Xmakegc(func, bits) X int func; /* Drawing function such as GXcopy or GXor. */ X char bits[]; /* Bits describing fill pattern. Produced in X * an X11 */ X/* bitmap file usually. */ X{ X static XGCValues gcv; X Pixmap pmap; X X /* Build X11 bitmap from data in bits */ X pmap = XCreatePixmapFromBitmapData(disp, wind, bits, 32, 32, BlackPixel(disp, 0), X WhitePixel(disp, 0), DisplayPlanes(disp, 0)); X /* Assign the graphics cursor parameters */ X gcv.function = func; X gcv.foreground = BlackPixel(disp, 0); X gcv.background = WhitePixel(disp, 0); X gcv.tile = pmap; X gcv.fill_style = FillTiled; X /* Return the created graphics cursor */ X return (XCreateGC(disp, wind, GCFunction | GCForeground | GCBackground | X GCTile | GCFillStyle, &gcv)); X} X Xvoid Xmake_gcs() X{ X pgc = makegc(GXcopy, player_bits); X pgc1 = makegc(GXcopy, player_bits); X pgc2 = makegc(GXcopy, player2_bits); X wgc = makegc(GXcopy, wall_bits); X Wgc = makegc(GXcopy, wall_bits); X Wgc2 = makegc(GXcopy, wall2_bits); X sgc = makegc(GXcopy, space_bits); X ggc = makegc(GXcopy, grass_bits); X dgc = makegc(GXcopy, diamond_bits); X dgc1 = makegc(GXcopy, diamond_bits); X dgc2 = makegc(GXcopy, diamond2_bits); X Sgc = makegc(GXcopy, steel_bits); X bgc = makegc(GXcopy, boulder_bits); X xgc = makegc(GXand, explosion_bits); X lgc = makegc(GXcopy, lmonster_bits); X lgc1 = makegc(GXcopy, lmonster_bits); X lgc2 = makegc(GXcopy, lmonster2_bits); X rgc = makegc(GXcopy, rmonster_bits); X rgc1 = makegc(GXcopy, rmonster_bits); X rgc2 = makegc(GXcopy, rmonster2_bits); X egc = makegc(GXcopy, eater_bits); X egc1 = makegc(GXcopy, eater_bits); X egc2 = makegc(GXcopy, eater2_bits); X Egc = makegc(GXcopy, steel_bits); X Egc1 = makegc(GXcopy, steel_bits); X Egc2 = makegc(GXcopy, exit2_bits); X ngc = makegc(GXcopy, nucbal_bits); X Bgc = makegc(GXcopy, blob_bits); X Bgc1 = makegc(GXcopy, blob_bits); X Bgc2 = makegc(GXcopy, blob2_bits); X tgc = makegc(GXcopy, wall_bits); X tgc1 = makegc(GXcopy, wall_bits); X tgc2 = makegc(GXcopy, tinkle1_bits); X tgc3 = makegc(GXcopy, tinkle2_bits); X} X Xvoid Xinit_level(levelnum) X int levelnum; X{ X X FILE *levelfile; X char buf[300], *ptr; X extern char *getenv(); X X Egc = Egc1; /* don't blink EXIT */ X blobcollapse = False; X blobcells = 0; X scoreobs = True; X tinkact = False; X levincreased = False; X strcpy(levname, "No_name_for_this_level_yet"); X X /* Manufaction the file name by starting with the world name and */ X /* appending the level number to it. */ X if (ptr = getenv("XBDLIB")) X strcpy(filename, ptr); X else X strcpy(filename, LIB); X strcat(filename, "/"); X strcat(filename, LEVELPREFIX); X sprintf(filename + strlen(filename), "%03d", levelnum); X /* Open level file for reading */ X levelfile = fopen(filename, "r"); X /* If level file does not exist, use the default level file. */ X if (levelfile == NULL) X { X /* Build the default level name */ X if (ptr = getenv("XBDLIB")) X strcpy(buf, ptr); X else X strcpy(buf, LIB); X strcat(buf, "/"); X strcat(buf, "/default"); X /* Open default level file for reading */ X levelfile = fopen(buf, "r"); X if (levelfile == NULL) X { X perror(LEVELPREFIX); X exit(1); X } X } X /* Load the first line of the level file */ X if (fgets(buf, 300, levelfile) == NULL) X { X x = w; X y = h; X speed = 15; X diareq = 12; X diapoints = 0; X extradiapoints = 0; X blobbreak = 200; X time = 1000; X } else X { X /* Extract the level parameters */ X sscanf(buf, "%d %d %d %d %d %d %d %d %d %s", &y, &x, &speed, &diareq, X &diapoints, &extradiapoints, &blobbreak, &tinkdur, &time, levname); X } X X if (xin && yin) X { X x = xin; X y = yin; X } /* read in from editor command line */ X /* X * if (x > w) x = w; if (y > h) y = h; if (x < 2) x = 2; if (y < 1) y = 1; X * X /* X * Iterate through each horizontal line X */ X for (i = 0; i < y; ++i) X { X /* Load the next line from the file */ X if (fgets(buf, 300, levelfile) != NULL) X { X /* Go through each horizontal position and copy the data into */ X /* the level array. */ X for (j = 0; j < x; ++j) X { X /* Break out if line ends prematurely */ X if (buf[j] == '\n' || buf[j] == '\0') X field[i][j].content = STEEL; /* break; */ X field[i][j].content = buf[j]; X field[i][j].changed = True; X field[i][j].dir = N; X field[i][j].speed = 0; X field[i][j].stage = 0; X field[i][j].caught = True; X field[i][j].checked = False; X } X } else X j = 0; X for (; j < x; ++j) X field[i][j].content = STEEL; X } X /* Close the level file */ X fclose(levelfile); X} X X/* Draw the score and level number */ Xvoid Xdraw_score() X{ X char buf[200]; X X /* Build the output string */ X sprintf(buf, "sc:%d lv:%d ls:%d ds:%d dp:%d ti:%d %s", score, levelnum, X lives, diareq, diapoints, time / 10, levname); X /* Clear the current score line */ X XFillRectangle(disp, wind, whitegc, 0, y << 5, x << 5, SCORESIZE); X /* Actually draw the text */ X XDrawString(disp, wind, scoregc, 0, (y << 5) + SCORESIZE - 1, buf, X strlen(buf)); X scoreobs = False; X} X Xvoid Xxstart(evmask) X long evmask; /* Event mask which will be used in X * XSelectInput */ X{ X XGCValues xgcv; X XWMHints wmhints; X X /* create X window */ X disp = XOpenDisplay(NULL); X /* Check to see if the open display succeeded */ X if (disp == NULL) X { X fprintf(stderr, "Display open failed. Check DISPLAY environment variable.\n" X ); X exit(-1); X } X wind = XCreateSimpleWindow(disp, DefaultRootWindow(disp), 0, 1, X x << 5, (y << 5) + SCORESIZE, 1, X WhitePixel(disp, 0), BlackPixel(disp, 0)); X /* Check to see if the open window succeeded */ X if (wind == 0) X { X fprintf(stderr, "Window open failed.\n"); X XCloseDisplay(disp); X exit(-1); X } X /* Load in the font used to display the score */ X scorefont = XLoadFont(disp, SCOREFONT); X /* Create GC which will be used from drawing score */ X xgcv.function = GXcopy; X xgcv.font = scorefont; X xgcv.foreground = BlackPixel(disp, 0); X xgcv.background = WhitePixel(disp, 0); X scoregc = XCreateGC(disp, wind, X GCFunction | GCFont | GCForeground | GCBackground, X &xgcv); X /* Create GC which will be used for clearing score line */ X xgcv.function = GXcopy; X scorefont = XLoadFont(disp, SCOREFONT); X xgcv.foreground = WhitePixel(disp, 0); X xgcv.background = BlackPixel(disp, 0); X whitegc = XCreateGC(disp, wind, X GCFunction | GCForeground | GCBackground, X &xgcv); X wmhints.flags = InputHint; X wmhints.input = True; X XSetWMHints(disp, wind, &wmhints); X X XSelectInput(disp, wind, evmask); X XMapRaised(disp, wind); X XWarpPointer(disp, None, wind, 0, 0, 0, 0, 11, 1); X} X X/* Gracefully shut X windows down. It is not strictly necessary to */ X/* call this function. */ Xvoid Xxend() X{ X gamestop = True; /* tricky; prevent ticker function from using X * Xlib fcts */ X XUnloadFont(disp, scorefont); X XUnmapWindow(disp, wind); X XDestroyWindow(disp, wind); X XCloseDisplay(disp); X} X Xvoid Xdraw_field(redrawall) X short redrawall; X{ X char c; X X /* Iterate through each horizontal line */ X for (i = y - 1; i >= 0; --i) X { X for (j = 0; j < x; ++j) X { X if (field[i][j].changed || redrawall) /* only redraw changed cells */ X { X c = field[i][j].content; X switch (c) X { X case GRASS: X XFillRectangle(disp, wind, ggc, j << 5, i << 5, 32, 32); X break; X case SPACE: X XFillRectangle(disp, wind, sgc, j << 5, i << 5, 32, 32); X break; X case PLAYER: X XFillRectangle(disp, wind, pgc, j << 5, i << 5, 32, 32); X break; X case WALL: X XFillRectangle(disp, wind, wgc, j << 5, i << 5, 32, 32); X break; X case MAGICWALL: X XFillRectangle(disp, wind, Wgc, j << 5, i << 5, 32, 32); X break; X case DIAMOND: X XFillRectangle(disp, wind, dgc, j << 5, i << 5, 32, 32); X break; X case BOULDER: X XFillRectangle(disp, wind, bgc, j << 5, i << 5, 32, 32); X break; X case EXPLOSION: X XFillRectangle(disp, wind, xgc, j << 5, i << 5, 32, 32); X break; X case LMONSTER: X XFillRectangle(disp, wind, lgc, j << 5, i << 5, 32, 32); X break; X case RMONSTER: X XFillRectangle(disp, wind, rgc, j << 5, i << 5, 32, 32); X break; X case NUCBAL: X XFillRectangle(disp, wind, ngc, j << 5, i << 5, 32, 32); X break; X case BLOB: X XFillRectangle(disp, wind, Bgc, j << 5, i << 5, 32, 32); X break; X case TINKLE: X XFillRectangle(disp, wind, tgc, j << 5, i << 5, 32, 32); X break; X case EATER: X XFillRectangle(disp, wind, egc, j << 5, i << 5, 32, 32); X break; X case EXIT: X XFillRectangle(disp, wind, Egc, j << 5, i << 5, 32, 32); X break; X case STEEL: X default: X field[i][j].content = STEEL; X XFillRectangle(disp, wind, Sgc, j << 5, i << 5, 32, 32); X break; X } X field[i][j].changed = False; X } X } X } X if (scoreobs) X draw_score(); X} X Xvoid Xset_cell(i, j, content) X int i, j; X char content; X{ X field[i][j].content = content; X field[i][j].speed = 0; X field[i][j].changed = True; X field[i][j].stage = 0; X field[i][j].caught = True; X field[i][j].checked = False; X} END_OF_FILE if test 9674 -ne `wc -c <'xbd/shared.c'`; then echo shar: \"'xbd/shared.c'\" unpacked with wrong size! fi # end of 'xbd/shared.c' fi if test -f 'xbd/xbd.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/xbd.c'\" else echo shar: Extracting \"'xbd/xbd.c'\" \(6013 characters\) sed "s/^X//" >'xbd/xbd.c' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/keysym.h> X#include <X11/Xutil.h> X#include <signal.h> X#include <sys/time.h> X#include <sys/timeb.h> X#include "xbd.h" X Xvoid Xdie(display, event) X Display *display; X XErrorEvent *event; X{ X char buffer[BUFSIZ]; X XGetErrorText(display, event->error_code, buffer, BUFSIZ); X (void) fprintf(stderr, "Display %s: Error %s\n", X XDisplayName(display), buffer); X seteuid(getuid()); X do X { X (void) fprintf(stderr, "(R)eturn (D)ump Core (E)xit:"); X switch (fgetc(stdin)) X { X case 'R': X case 'r': X return; X case 'E': X case 'e': X exit(1); X break; X case 'D': X case 'd': X kill(0, 3); X break; X default: X break; X } X } while (1); X} X Xvoid Xinit_vars() X{ X blobbreak = 100; X critical = 100; X blobcells = 0; X curorder = STAND; X gamestop = True; X scoreobs = True; X stoplevel = False; X levelnum = 1; X speed = 1; X lives = 4; X xin = 0; X yin = 0; X players = 1; X} X Xstruct itimerval cycletime; /* Structure used when setting up timer */ Xvoid Xadapt_timer() X{ X long period; X X if (speed <= 0) X speed = 1; X period = (long) 3 *(long) 625000 / speed; X cycletime.it_interval.tv_sec = period / 1000000; X cycletime.it_interval.tv_usec = period % 1000000; X cycletime.it_value = cycletime.it_interval; X setitimer(ITIMER_REAL, &cycletime, (struct itimerval *) NULL); X} X X/* Handle a key stroke by the user. */ Xvoid Xhandle_key(keyhit) X KeySym keyhit; /* Key symbol for key stroke provided by X X * windows */ X{ X if (players <= 0) X { X init_level(levelnum); X adapt_timer(); X XResizeWindow(disp, wind, x << 5, (y << 5) + SCORESIZE); X stoplevel = False; X draw_field(True); X gamestop = True; X players = 1; X return; X } X switch (keyhit) X { X case XK_question: X case XK_slash: X puts("Control the player using keyboard keys."); X puts("CTRL key - steal instead of go"); X puts("h,left arrow - left"); X puts("l,right arrow - right"); X puts("k,up arrow - up"); X puts("j,down arrow - down"); X puts("\nSPACE - pause/continue game"); X puts("^C - kill the game"); X puts("^D - give Dutch act"); X puts("^R - redraw the screen"); X break; X case XK_space: X case XK_R11: X gamestop = !gamestop; X break; X case XK_Left: X case XK_H: X case XK_h: X curorder = LEFT; X gamestop = False; X break; X case XK_Up: X case XK_K: X case XK_k: X curorder = UP; X gamestop = False; X break; X case XK_Down: X case XK_J: X case XK_j: X curorder = DOWN; X gamestop = False; X break; X case XK_Right: X case XK_L: X case XK_l: X curorder = RIGHT; X gamestop = False; X break; X } X} X X/**** Timer procedures ****/ X X/* Function which is called whenever the timer signal goes off */ Xvoid Xticker(sig) X int sig; X{ X signal(SIGALRM, SIG_IGN); X /* Ignore any signal which is not an alarm. Ignore alarm signals */ X /* after a new level has been drawn until a key is hit. */ X if (sig != SIGALRM) X return; X if (time) X time--; X if (tinkact) X tinkdur--; X if (time % 10 == 1) X scoreobs = True; X X if (!gamestop) X { X calculate_field(); X draw_field(0); X XFlush(disp); X } X if (stoplevel) X { X init_level(levelnum); X adapt_timer(); X XResizeWindow(disp, wind, x << 5, (y << 5) + SCORESIZE); X XFlush(disp); X gamestop = True; X stoplevel = False; X } X signal(SIGALRM, ticker); X} X/**** End timer procedures ****/ X Xvoid Xmain(argc, argv) X int argc; X char **argv; X{ X long period; X KeySym keyhit; X char buf[50]; X static XEvent xev; X int keycount, i; X X printf("type ? for help.\n"); X X init_vars(); X X /* scan the command line for executing parameters and flags */ X for (i = 1; i < argc; ++i) X { X if (argv[i][0] == '-') X { X if (argv[i][1] == 'l') X { X if (argv[i][2] == '\0' && i + 1 < argc) X { X sscanf(argv[i + 1], "%d", &levelnum); X i++; X } else X sscanf(argv[i] + 2, "%d", &levelnum); X } else X { X printf("usage: xbd [-l <level>] \n"); X exit(1); X } X } X } X X levelstart = levelnum; X init_level(levelnum); X xstart(EVMASK); X XSetErrorHandler(die); X XStoreName(disp, wind, "BOULDER DASH ?"); X make_gcs(); X draw_field(True); X draw_score(); X X /* initialize timer structure according to speed */ X if (speed <= 0) X speed = 1; X period = (long) 3 *(long) 625000 / speed; X cycletime.it_interval.tv_sec = period / 1000000; X cycletime.it_interval.tv_usec = period % 1000000; X cycletime.it_value = cycletime.it_interval; X /* start the system timer. the timer signal catcher will be set */ X /* after the first x event is received. */ X signal(SIGALRM, SIG_IGN); X setitimer(ITIMER_REAL, &cycletime, (struct itimerval *) NULL); X X while (lives > 0) /* MAIN LOOP */ X { X XWindowEvent(disp, wind, EVMASK, &xev); X signal(SIGALRM, SIG_IGN); X if ((xev.type == Expose && xev.xexpose.count == 0)) X { X draw_field(True); X draw_score(); X } else if (xev.type == KeyPress) X { X keycount = XLookupString(&xev, buf, 50, &keyhit, (XComposeStatus *) NULL); X if (steal = (xev.xkey.state & ControlMask)) X switch (keyhit) X { X /* ^C, ^U kill the game */ X case XK_C: X case XK_U: X case XK_c: X case XK_u: X case XK_backslash: X goto game_over; X /* ^D Kill; commit suicide */ X case XK_D: X case XK_d: X curorder = KILL; X /* ^R redraws the level */ X case XK_R: X case XK_r: X draw_field(True); X break; X default: X handle_key(keyhit); X break; X } X else X handle_key(keyhit); X } X if (!gamestop) X { X XSync(disp, False); X signal(SIGALRM, ticker); X } X } Xgame_over: X XSync(disp, False); X xend(); X add_score(); X} END_OF_FILE if test 6013 -ne `wc -c <'xbd/xbd.c'`; then echo shar: \"'xbd/xbd.c'\" unpacked with wrong size! fi # end of 'xbd/xbd.c' fi if test -f 'xbd/xbd.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/xbd.h'\" else echo shar: Extracting \"'xbd/xbd.h'\" \(4426 characters\) sed "s/^X//" >'xbd/xbd.h' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X/* define bit maps */ X#include "bitmap/player.bits" X#include "bitmap/player2.bits" X#include "bitmap/wall.bits" X#include "bitmap/wall2.bits" X#include "bitmap/tinkle1.bits" X#include "bitmap/tinkle2.bits" X#include "bitmap/space.bits" X#include "bitmap/grass.bits" X#include "bitmap/diamond.bits" X#include "bitmap/diamond2.bits" X#include "bitmap/steel.bits" X#include "bitmap/boulder.bits" X#include "bitmap/explosion.bits" X#include "bitmap/rmonster.bits" X#include "bitmap/rmonster2.bits" X#include "bitmap/lmonster.bits" X#include "bitmap/lmonster2.bits" X#include "bitmap/nucbal.bits" X#include "bitmap/blob.bits" X#include "bitmap/blob2.bits" X#include "bitmap/eater.bits" X#include "bitmap/eater2.bits" X#include "bitmap/exit2.bits" X X#define w 35 X#define h 26 X#define LEVELPREFIX "xbdlev" X X#define SCOREFONT "-adobe-times-bold-r-normal--18-180-75-75-p-99-iso8859-1" X#define SCORESIZE 18 X X#define EVMASK KeyPressMask | ExposureMask | ButtonPressMask | PointerMotionMask | FocusChangeMask X X/* direction masks */ X#define N 0 X#define E 1 X#define S 2 X#define W 3 X#define NODIR 4 X X#define SPACEEXPLO 0 X#define BOULDEXPLO 10 X#define DIAEXPLO 20 X#define PROPAGATED 10 X X#define PLAYER 'p' X#define SPACE ' ' X#define LMONSTER 'l' /* Right turning monster */ X#define RMONSTER 'r' X#define GRASS 'g' X#define WALL 'w' X#define MAGICWALL 'W' /* Expanding wall */ X#define DIAMOND 'd' X#define STEEL 'S' X#define BOULDER 'b' X#define EXPLOSION 'x' X#define EXIT 'E' X#define EATER 'e' X#define NUCBAL 'n' /* Nuclear ballon */ X#define BLOB 'B' /* lava */ X#define TINKLE 't' /* Tinkle wall */ X XFont scorefont; /* Font used to display score */ XGC whitegc, scoregc, gc, Bgc, Bgc1, Bgc2, ngc, egc, egc1, X egc2, Egc1, Wgc, Wgc2, Egc2, Egc, lgc, lgc1, lgc2, rgc, X rgc1, rgc2, xgc, Sgc, bgc X ,dgc, dgc1, dgc2, wgc, pgc, pgc1, pgc2, sgc, ggc, tgc, tgc1, X tgc2, tgc3; Xchar filename[300]; /* Current file name of this level */ Xchar levname[64]; /* Levelname */ Xint i, j, ii, jj, jjj; Xint blobbreak; Xint critical; Xint time; /* Current clock tick number */ Xint blobcells; Xint tinkdur; /* Tinkle duration */ XBool tinkact; /* Tinkle active */ XBool levincreased; Xint x, y, xin, yin, players, lives, levelnum, levelstart, speed, X diareq, diapoints, extradiapoints; XBool steal; /* steal instead of go */ XBool stoplevel, blobcollapse; Xenum directs X{ X STAND, UP, DOWN, LEFT, RIGHT, KILL X}; X Xenum directs curorder; /* Current order which player has */ X/* typed at the keyboard. */ Xstruct cell X{ X char content; X Bool changed; /* has cell changed since last drawing */ X Bool caught; /* for BLOB */ X Bool checked; /* for BLOB algorithm */ X char dir; X short speed; X short stage; /* painting stage for blinking etc. */ X} field[h][w]; X XBool gamestop; XBool scoreobs; /* is score line obsolete ? */ Xint levelnum; /* Current level number */ Xint lives; /* Current number of lives */ Xint score; /* Total score */ Xint speed; /* Speed of game. 1 is slowest, 15 is X * default */ Xchar filename[300]; /* Current file name of this level */ X XDisplay *disp; /* X11 display of client */ XWindow wind; /* X11 window where game is displayed */ X XGC makegc(); Xvoid make_gcs(); Xvoid init_level(); Xvoid draw_score(); Xvoid xstart(); Xvoid xend(); Xvoid draw_field(); Xvoid set_cell(); Xvoid move_cell(); Xvoid explode(); XBool move_monster(); XBool search_destroy(); Xvoid calculate_field(); Xvoid add_score(); END_OF_FILE if test 4426 -ne `wc -c <'xbd/xbd.h'`; then echo shar: \"'xbd/xbd.h'\" unpacked with wrong size! fi # end of 'xbd/xbd.h' fi if test -f 'xbd/xbd.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/xbd.man'\" else echo shar: Extracting \"'xbd/xbd.man'\" \(3347 characters\) sed "s/^X//" >'xbd/xbd.man' <<'END_OF_FILE' X.TH Boulder-dash l "April 1 1990" X.UC 4 X.SH NAME XBoulder-dash (v1.2) - Collect diamonds, kill monsters, close in blob etc. etc. X.SH SYNOPSIS X.B xbd X[ X.B \-l X.I level X] X.br X.B xbde X.B \-l X.I level X[ X.B \-w X.I width X] X[ X.B \-h X.I height X] X.SH DESCRIPTION X.PP X.I xbd Xis a game designed for X windows (originally a similar game with the same name Xran on CBM64). X.I xbde Xis used to create and edit new levels which can be used by X.I Boulder-dash. X.PP XThe goal in X.I Boulder-dash Xis to collect a certain number X.I (ds) Xof diamonds per level X.I (lv) Xand then enter the next level by moving to the blinking exit-field, thus incrementing your number of lives X.I (ls). XA diamond is worth X.I (dp) Xpoints. Normally extra diamonds are worth more. X.SH OPTIONS XThe X.B "\-l" Xoption sets the level number for editing or for starting the game. XThis may be any integer greater than 0. By default, the game starts Xat level 1. The X.B "\-w" Xand X.B "\-h" Xoptions set the width and height of a newly created level. X.SH USAGE XWhen playing X.I Boulder-dash Xthe following keyboard commands may be used: X.PP XSPACE,R11 \- stop X.br Xh,left arrow \- move left X.br Xl,right arrow \- move right X.br Xk,up arrow \- move up X.br Xj,down arrow \- move down X.PP X.br X? \- help X.PP XWhen used in combination with the X.I control key, Xthe direction keys make the player X.I 'steal' Xinstead of X.I 'go'. XIn addition, some other control key combinations can be used: X.PP X^C \- kill the game X.br X^D \- give dutch act X.br X^R \- redraw the level X.PP XThe mouse must be placed in the game window to use the keyboard Xcommands. When the game starts or a level is finished , everything is frozen, and any key will Xstart/continue the game. X.PP X.I xbde Xcan be used to edit levels. Levels are stored in ASCII files. The Xfirst line in a level file contains level specific parameters that Xshould be edited by hand. The parameters are: X X.br Xheight width speed X.I dp X.I extra-dp Xblob-brake Xtinkle-dur X.I ti name X X.br XWhere blob-brake indicates how strongly blob propagation is slowed down. Xtink-dur is the time tinkle-walls will keep their magic power. X.I ti Xis the time permitted to complete this level. X.I name Xis the name of the level. X.br XBlocks are painted by pressing the left mouse button. Spaces are Xpainted by pressing the right mouse button. A new block type is Xselected by one of the following keys: X.PP X<space> \- draw spaces X.br Xb \- draw boulder X.br Xd \- draw diamond X.br Xe \- draw eater (initial speed: 0) X.br Xg \- draw grass X.br Xl \- draw left-monster (initial direction: NORTH) X.br Xp \- draw player X.br Xr \- draw right-monster (initial direction: NORTH) X.br Xt \- draw tinkle wall X.br Xw \- draw wall X.br Xx \- draw explosion (SPACEEXPLO) X.br XB \- draw blob X.br XE \- draw exit X.br XN \- draw nuclear balloon X.br XS \- draw steel X.br XW \- draw magic wall X.PP X.br XOther commands are: X.PP X.br X^c \- Quit X.br X^E \- Erase level X.br X^w \- Save level and quit X.SH AUTHOR XJeroen Houttuin, Informatikdienste, ETH Zurich 1990. X.SH CREDITS XCBM64 for the idea. Alexander Siegel (Cornell University) Xfor example X-programming in X.I 'golddig'. XChristos S. Zoulas (Cornell University) for Imakefile and bug fixes. X.SH FILES Xxbd - Boulder-dash executable X.br Xxbde - Boulder-dash editor executable X.br Xscores - high score list X.br Xdefault - default level X.br Xxbdlev### - levels END_OF_FILE if test 3347 -ne `wc -c <'xbd/xbd.man'`; then echo shar: \"'xbd/xbd.man'\" unpacked with wrong size! fi # end of 'xbd/xbd.man' fi if test -f 'xbd/xbde.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xbd/xbde.c'\" else echo shar: Extracting \"'xbd/xbde.c'\" \(5575 characters\) sed "s/^X//" >'xbd/xbde.c' <<'END_OF_FILE' X/*********************************************/ X/* you just keep on pushing my luck over the */ X/* BOULDER DASH */ X/* */ X/* Jeroen Houttuin, ETH Zurich, 1990 */ X/*********************************************/ X X#include <stdio.h> X#include <X11/Xlib.h> X#include <X11/keysym.h> X#include <X11/Xutil.h> X#include "xbd.h" X Xchar curchar; XGC drawgc; X Xvoid Xinit_vars() X{ X levelnum = -1; X xin = 0; X yin = 0; X} X X/* Save the current level back into a file. The global variable */ X/* filename is used to determine the file name. */ Xvoid Xsave_level() X{ X FILE *levelfile; X char buf[300]; X register int i, j; X X /* Open the data file */ X levelfile = fopen(filename, "w"); X if (levelfile == NULL) X { X exit(1); X } X /* Write out the size of the level. Normal text is used so that */ X /* levels can be easily copied across architectures. */ X fprintf(levelfile, "%d %d %d %d %d %d %d %d %d %s\n", y, x, X speed, diareq, diapoints, extradiapoints, blobbreak, tinkdur, time, levname); X /* Terminate the lines for writing out the horizontal level lines */ X buf[x] = '\n'; X buf[x + 1] = '\0'; X /* Iterate through each vertical position */ X for (i = 0; i < y; ++i) X { X /* Copy each horizontal line into the output buffer */ X for (j = 0; j < x; ++j) X buf[j] = field[i][j].content; X /* Write the line out to the file */ X fputs(buf, levelfile); X } X /* Close the data file */ X fclose(levelfile); X} X X/* Main routine for editing levels */ Xvoid Xmain(argc, argv) X int argc; X char **argv; X{ X register int i, j; X static XEvent xev; X KeySym keyhit; X int keycount; X int tmp; X char buf[50]; X X init_vars(); X X /* Read in command line options */ X for (i = 1; i < argc; ++i) X { X if (argv[i][0] == '-') X { X /* -w sets the level width */ X if (argv[i][1] == 'w') X { X if (argv[i][2] == '\0' && i + 1 < argc) X { X sscanf(argv[i + 1], "%d", &xin); X i++; X } else X sscanf(argv[i] + 2, "%d", &xin); X } X /* -h sets the level height */ X else if (argv[i][1] == 'h') X { X if (argv[i][2] == '\0' && i + 1 < argc) X { X sscanf(argv[i + 1], "%d", &yin); X i++; X } else X sscanf(argv[i] + 2, "%d", &yin); X } X /* -l sets the level number */ X else if (argv[i][1] == 'l') X { X if (argv[i][2] == '\0' && i + 1 < argc) X { X sscanf(argv[i + 1], "%d", &levelnum); X i++; X } else X sscanf(argv[i] + 2, "%d", &levelnum); X } else X { X printf("usage: xbde [-h <height>] [-w <width>] -l <level> \n"); X exit(1); X } X } X } X /* Make sure some value was chosen for the level number. This */ X /* discourages everybody editing the same level all the time. */ X if (levelnum == -1) X { X printf("usage: editor [-h <height>] [-w <width>] -l <level> \n"); X exit(1); X } X /* Load in level data from file. */ X init_level(levelnum); X X printf("Welcome. Type h for help.\n"); X X /* Start up X windows and create all graphics cursors */ X xstart(EVMASK); X /* Set the name of the output window */ X XStoreName(disp, wind, "BOULDER DASH - LEVEL EDITOR"); X XFlush(disp); /* initializing flush */ X make_gcs(); X Egc = Egc2; X Wgc = Wgc2; X tgc = tgc3; X drawgc = pgc; X draw_field(True); X X /* Main event loop */ X do X { X /* Get the next X window event */ X XWindowEvent(disp, wind, EVMASK, &xev); X X /* If it was an expose event, redraw everything */ X if (xev.type == Expose) X { X draw_field(True); X draw_score(); X } else if (xev.type == KeyPress) X { X keycount = XLookupString(&xev, buf, 50, &keyhit, (XComposeStatus *) NULL); X /* If the 'h', '?' or '/' key was hit, print out the text */ X /* descriptions of each block type */ X if (keyhit == XK_H || keyhit == XK_h || keyhit == XK_question || X keyhit == XK_slash) X { X puts("^w - finish editing and save the level."); X puts("^c - quit editing."); X puts("^E - erase level."); X puts("Use the left mouse button to paint blocks."); X puts("Use the right mouse button to erase blocks."); X putchar('\n'); X } X /* A ^E erases the entire level */ X else if ((keyhit == XK_E) && X (xev.xkey.state & ControlMask)) X { X /* Replace level contents with space */ X for (i = 0; i < y; ++i) X for (j = 0; j < x; ++j) X if ((i == 0) || (i == y - 1) || (j == 0) || (j == x - 1)) X set_cell(i, j, STEEL); X else X set_cell(i, j, SPACE); X /* Redraw empty level */ X draw_field(False); X } else X curchar = keyhit; X } X /* If the mouse moves with the button pressed, or the button is */ X /* pressed, draw the current block at that position */ X else if (xev.type == MotionNotify) X { X if (xev.xmotion.state & Button3Mask) X set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, SPACE); X else if (xev.xmotion.state & Button1Mask) X set_cell(xev.xmotion.y >> 5, xev.xmotion.x >> 5, curchar); X } else if (xev.type == ButtonPress) X { X if (xev.xbutton.button == Button3) X set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, SPACE); X else X set_cell(xev.xbutton.y >> 5, xev.xbutton.x >> 5, curchar); X } X draw_field(False); X XFlush(disp); X /* Loop until a control key is pressed */ X } while (xev.type != KeyPress || X (keyhit != XK_C && keyhit != XK_c && X keyhit != XK_W && keyhit != XK_w) || X !(xev.xkey.state & ControlMask)); X X /* Save level to data file */ X if (keyhit == XK_W || keyhit == XK_w) X save_level(); X xend(); X exit(0); X} END_OF_FILE if test 5575 -ne `wc -c <'xbd/xbde.c'`; then echo shar: \"'xbd/xbde.c'\" unpacked with wrong size! fi # end of 'xbd/xbde.c' fi echo shar: End of archive. exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.