home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!ssbell!kent@ssbell.uu.net
- From: kent@ssbell.uu.net (Kent Landfield)
- Newsgroups: comp.sources.x
- Subject: v05i047: golddig2 -- A game for X11, Part03/04
- Message-ID: <596@ssbell.uu.net>
- Date: 14 Dec 89 03:18:07 GMT
- Sender: kent@ssbell.uu.net
- Lines: 1458
- Approved: kent@ssbell.uu.net (Kent Landfield)
-
- Submitted-by: Alexander Siegel <siegel@cs.cornell.edu>
- Posting-number: Volume 5, Issue 47
- Archive-name: golddig2/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- # Contents: golddig2/badguy.c golddig2/movement.c golddig2/shared.c
- # Wrapped by kent@ssbell on Wed Dec 13 20:36:59 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'golddig2/badguy.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'golddig2/badguy.c'\"
- else
- echo shar: Extracting \"'golddig2/badguy.c'\" \(16560 characters\)
- sed "s/^X//" >'golddig2/badguy.c' <<'END_OF_FILE'
- X/* This program was written by Alexander Siegel in September of 1989 */
- X/* at Cornell University. It may may copied freely for private use or */
- X/* public dispersion provided that this comment is not removed. This */
- X/* program, any portion of this program, or any derivative of this */
- X/* program may not be sold or traded for financial gain. */
- X
- X#include <stdio.h>
- X#include <X11/Xlib.h>
- X#include <X11/keysym.h>
- X#include "golddig.h"
- X
- Xextern char badguy_bits[];
- X#include "bitmap/badguy2.bits"
- X#include "bitmap/badguy3.bits"
- X
- Xlong random();
- X
- X#define MAXBADGUY 30 /* Maximum number of bad guys */
- X#define MAXBADSCORE 20 /* Maximum amount of score given for */
- X /* killing bad guys */
- Xint numbadguy = 0; /* Total number of bad guys. */
- Xstruct thing_s badguys[MAXBADGUY]; /* Array describing state of all */
- X /* bad guys */
- Xchar movetree[MAXLEVEL]; /* Direction that badguy should go at each location */
- Xint badscore; /* Score given during current level due to */
- X /* killing bad guys */
- X
- X/* Graphics cursors for drawing the possible states of the badguys */
- XGC badguy1gc,badguy2gc,badguy3gc;
- X
- X/* Initialize graphics cursors for bad guys */
- Xvoid init_badguy()
- X{
- X int gcfunc;
- X
- X /* Decide whether to use GXand or GXor depending on screen type */
- X if((BlackPixel(disp,0) & WhitePixel(disp,0)) == BlackPixel(disp,0))
- X gcfunc = GXand;
- X else
- X gcfunc = GXor;
- X /* Generate graphics cursors for drawing bad guy */
- X badguy1gc = makegc(gcfunc,badguy_bits);
- X badguy2gc = makegc(gcfunc,badguy2_bits);
- X badguy3gc = makegc(gcfunc,badguy3_bits);
- X}
- X
- X/* Initialize data structure for bad guys from level data */
- Xvoid start_badguy()
- X{
- X register int x,y,pos;
- X
- X /* Reset the limit on bad guy score given */
- X badscore = 0;
- X /* Initialize number of bad guys to 0 */
- X numbadguy = 0;
- X pos = 0;
- X /* Iterate through each position in level array */
- X for(x=0;x<xsize;++x)
- X for(y=0;y<ysize;++y) {
- X /* Check if level holds a bad guys block at that position */
- X if(level[pos] == BADGUY) {
- X /* Replace bad guys block with space */
- X level[pos] = SPACE;
- X if(numbadguy < MAXBADGUY) {
- X /* Add bad guy to global array. Note the multiplication by */
- X /* 2 when producing position. */
- X badguys[numbadguy].xstart = badguys[numbadguy].xpos = x << 1;
- X badguys[numbadguy].ystart = badguys[numbadguy].ypos = y << 1;
- X badguys[numbadguy].dir = STAND;
- X /* Bad guys start holding nothing */
- X badguys[numbadguy].hold = SPACE;
- X numbadguy ++;
- X }
- X }
- X pos ++;
- X }
- X}
- X
- X/* Draw all the bad guys out to the game window */
- Xvoid draw_badguys()
- X{
- X register int i;
- X GC drawgc;
- X
- X /* Iterate through each bad guy */
- X for(i=0;i<numbadguy;++i) {
- X /* If bad guy is horizontally offset, use the second graphics */
- X /* cursor */
- X if(badguys[i].xpos & 1)
- X drawgc = badguy2gc;
- X /* If bad guy is vertically offset, use the third graphics cursor */
- X else if(badguys[i].ypos & 1)
- X drawgc = badguy3gc;
- X /* Otherwise use the normal graphics cursor */
- X else
- X drawgc = badguy1gc;
- X /* Fill rectangle surrounding bad guy */
- X XFillRectangle(disp,wind,drawgc,badguys[i].xpos << 3,
- X badguys[i].ypos << 3,16,16);
- X }
- X}
- X
- X/* Return 1 if the specified position overlaps a bad guy, 0 otherwise. */
- X/* Another parameter is provided so that this routine can ignore one */
- X/* bad guy. */
- Xint overlap_badguy(x,y,num)
- Xregister int x,y; /* Position which will be checked for overlap. */
- Xregister int num; /* Number of bad guy to ignore. Use a -1 for no */
- X /* ignoring. */
- X{
- X register int i,d;
- X
- X /* Iterate through each bad guy */
- X for(i=0;i<numbadguy;++i) {
- X /* If this bad guy is the one that I am supposed to ignore, */
- X /* continue to the next */
- X if(i == num)
- X continue;
- X /* Compute horizontal distance between position and bad guy and */
- X /* check it. Things are two positions wide in each direction */
- X d = x - badguys[i].xpos;
- X if(d < -1 || d > 1)
- X continue;
- X /* Check vertical distance */
- X d = y - badguys[i].ypos;
- X if(d < -1 || d > 1)
- X continue;
- X /* Found overlap, return a 1 */
- X return(1);
- X }
- X /* Could not find overlap */
- X return(0);
- X}
- X
- X/* Erase and redraw all badguys who have moved in the previous */
- X/* movement. Movement is detected when (xpos,ypos) is different from */
- X/* (xold,yold). */
- Xvoid drawmove_badguys()
- X{
- X register int x,y,i;
- X GC drawgc;
- X
- X /* iterate through each bad guy */
- X for(i=0;i<numbadguy;++i) {
- X /* do not erase bad guys who did not move */
- X if(! badguys[i].redraw)
- X continue;
- X /* get position of bad guy in normal coordinates */
- X x = badguys[i].xold >> 1;
- X y = badguys[i].yold >> 1;
- X /* draw block underneath bad guy */
- X draw_block(x,y);
- X /* if horizontally offset, draw block to the right */
- X if(badguys[i].xold & 1)
- X draw_block(x + 1,y);
- X /* if vertically offset, draw block below */
- X if(badguys[i].yold & 1)
- X draw_block(x,y + 1);
- X }
- X
- X /* iterate through each bad guy */
- X for(i=0;i<numbadguy;++i) {
- X /* do not draw bad guys who did not move */
- X if(! badguys[i].redraw)
- X continue;
- X /* Put badguy coordinates in registers */
- X x = badguys[i].xpos;
- X y = badguys[i].ypos;
- X /* if bad guy is horizontally offset, use the second graphics */
- X /* cursor */
- X if(x & 1)
- X drawgc = badguy2gc;
- X /* If bad guy is vertically offset, use the third graphics cursor */
- X else if(y & 1)
- X drawgc = badguy3gc;
- X /* Otherwise use the normal graphics cursor */
- X else
- X drawgc = badguy1gc;
- X /* Fill rectangle surrounding bad guy */
- X XFillRectangle(disp,wind,drawgc,x << 3,y << 3,16,16);
- X }
- X}
- X
- X/* Maximum size for FIFO queue used by breadth first search algorithm */
- X#define QSIZE 1000
- X
- X/* Regenerate the movement tree used by bad guys when determining */
- X/* movement. The basic algorithm is a breadth first search of the */
- X/* graph produced by interpreting the moveallow array as a directed */
- X/* graph. The root of the tree is the player position. The result of */
- X/* this algorithm is that the shortest path from each position to the */
- X/* player is described by the directions in the movement tree. */
- Xvoid regen_tree()
- X{
- X register int head,tail,lpos,dist;
- X /* This array is used for the queue of graph nodes. The head and */
- X /* tail variables describe the head and tail of the queue in the */
- X /* array. */
- X struct goals_s {
- X short x,y,dir;
- X } goals[QSIZE];
- X
- X /* Do a fast pre-initialization of the movement tree */
- X dist = xsize * ysize;
- X for(lpos=0;lpos<dist;++lpos) {
- X /* Zero out each position. A 0 in a position signifies that the */
- X /* direction of movement for that position is unknown. */
- X movetree[lpos] = 0;
- X /* If can only move in one direction, set movetree value */
- X /* immediately. Do not set it if is a force into a STOPBAD space */
- X /* to allow bad guys to try to run over holes. This loop screws up the */
- X /* search algorithm and the result is that bad guys will not jump */
- X /* off of things. It makes the search run much faster, and the */
- X /* bad guys were too smart otherwise. */
- X if((moveallow[lpos] & FORCEDOWN) &&
- X ! (fast_lookup[level[lpos + 1]].code & STOPBAD))
- X movetree[lpos] = MOVEDOWN;
- X if((moveallow[lpos] & FORCEUP) &&
- X ! (fast_lookup[level[lpos - 1]].code & STOPBAD))
- X movetree[lpos] = MOVEUP;
- X if((moveallow[lpos] & FORCERIGHT) &&
- X ! (fast_lookup[level[lpos + ysize]].code & STOPBAD))
- X movetree[lpos] = MOVERIGHT;
- X if((moveallow[lpos] & FORCELEFT) &&
- X ! (fast_lookup[level[lpos - ysize]].code & STOPBAD))
- X movetree[lpos] = MOVELEFT;
- X /* If no movement is possible, set a -1 in the movement tree. */
- X if(moveallow[lpos] == 0)
- X movetree[lpos] = -1;
- X }
- X /* Initialize the head and tail of the FIFO queue. */
- X head = 0;
- X tail = 1;
- X /* Set the first goal node to be the player */
- X goals[0].x = player.xpos >> 1;
- X goals[0].y = player.ypos >> 1;
- X goals[0].dir = -1; /* Make sure every direction is possible */
- X /* While there are still goal nodes, continue */
- X while(head != tail) {
- X /* Compute position of position of goal */
- X lpos = goals[head].x * ysize + goals[head].y;
- X /* If the suggested movement direction is valid and the movement */
- X /* has for that position has not been set, set it. */
- X if(movetree[lpos] == 0 && (moveallow[lpos] & goals[head].dir) != 0) {
- X movetree[lpos] = goals[head].dir;
- X /* Suggest that the block to the left has to rightward pointer */
- X if(goals[head].x > 0 && movetree[lpos - ysize] == 0)
- X
- X/* Add a suggested movement direction to the FIFO queue */
- X#define ADDGOAL(dx,dy,ndir) { goals[tail].x = goals[head].x + dx; \
- X goals[tail].y = goals[head].y + dy; \
- X goals[tail++].dir = ndir; \
- X if(tail == QSIZE) tail = 0; }
- X
- X ADDGOAL(-1,0,MOVERIGHT)
- X /* Suggest that the block to the right has a leftware pointer */
- X if(goals[head].x < xsize - 1 && movetree[lpos + ysize] == 0)
- X ADDGOAL(1,0,MOVELEFT)
- X /* Suggest that the block above has a downward pointer */
- X if(goals[head].y > 0 && movetree[lpos - 1] == 0)
- X ADDGOAL(0,-1,MOVEDOWN)
- X /* Suggest that the block below has an upward pointer */
- X if(goals[head].y < ysize - 1 && movetree[lpos + 1] == 0)
- X ADDGOAL(0,1,MOVEUP)
- X }
- X /* Remove current goal node from head of queue */
- X head ++;
- X if(head == QSIZE)
- X head = 0;
- X }
- X}
- X
- X/* Move all the bad guys one position */
- Xvoid move_badguys()
- X{
- X int i,x,y,allow;
- X register int lpos;
- X enum directs dir;
- X register char curchar,below;
- X
- X /* Iterate through all the bad guys */
- X for(i=0;i<numbadguy;++i) {
- X /* Get old position for bad guys */
- X x = badguys[i].xold = badguys[i].xpos;
- X y = badguys[i].yold = badguys[i].ypos;
- X /* Initially assume that the badguy does not need to be redrawn */
- X badguys[i].redraw = 0;
- X /* Get the character underneath the bad guy */
- X lpos = (x >> 1)*ysize + (y >> 1);
- X curchar = level[lpos];
- X /* Get the character below the bad guy. If it is off the level, */
- X /* assume it is a stone */
- X if(y < (ysize - 1) << 1)
- X below = level[lpos + 1];
- X else
- X below = STONE;
- X
- X /* If the current character is a killer block, move the bad guy to */
- X /* its starting position */
- X if(fast_lookup[curchar].code & KILLIN) {
- X /* Prevent getting too many points from kill bad guys on a */
- X /* single level */
- X if(badscore < MAXBADSCORE) {
- X /* Increment the score */
- X score += 2;
- X badscore += 2;
- X }
- X /* Redraw the score line */
- X draw_score();
- X /* Move the bad guy back to its start */
- X badguys[i].xpos = badguys[i].xstart;
- X badguys[i].ypos = badguys[i].ystart;
- X lpos = (badguys[i].xpos >> 1)*ysize + (badguys[i].ypos >> 1);
- X /* Prevent a bad guy from forming on top of another */
- X while(overlap_badguy(badguys[i].xpos,badguys[i].ypos,i) ||
- X level[lpos] != SPACE) {
- X badguys[i].xpos = random() % xsize;
- X badguys[i].ypos = random() % ysize;
- X lpos = (badguys[i].xpos >> 1)*ysize + (badguys[i].ypos >> 1);
- X }
- X /* Redraw bad guy */
- X badguys[i].redraw = 1;
- X /* Destroy whatever the bad guy was holding */
- X if(badguys[i].hold != SPACE) {
- X if(fast_lookup[badguys[i].hold].code & TREASURE) {
- X goldleft --;
- X /* If that was the last gold piece, escape ladder and other */
- X /* stuff may need to appear. */
- X if(goldleft == 0) {
- X regen_allow(); /* Regenerate the allowable movement array */
- X redrawall(); /* Refresh the entire screen */
- X }
- X }
- X badguys[i].hold = SPACE;
- X }
- X /* Continue to the next bad guy */
- X continue;
- X }
- X
- X /* If the bad guy is stuck in a STOPBAD block, do not move him */
- X if((x & 1) == 0 && (y & 1) == 0 &&
- X (fast_lookup[curchar].code & STOPBAD)) {
- X /* Redraw bad guy since underlying block gets redrawn occasionally */
- X badguys[i].redraw = 1;
- X continue;
- X }
- X
- X /* Check if the bad guy is above a hole. */
- X if((x & 1) == 0 && (y & 1) == 0 && fast_lookup[below].code & STOPBAD) {
- X /* If the hole is premature, fill it */
- X if(below >= HOLE1 && below <= HOLE1+2)
- X fill_hole(x >> 1,(y >> 1) + 1);
- X }
- X
- X /* Complete previous movement */
- X if((x & 1) != 0 || (y & 1) != 0)
- X dir = badguys[i].dir;
- X
- X /* Can only drop things when at a non-offset position and when */
- X /* there is space underneath */
- X else if(curchar == SPACE && badguys[i].hold != SPACE &&
- X /* Drop stuff with a 1 in 20 chance */
- X random() % 20 == 0)
- X dir = PUTDOWN;
- X
- X /* Compute next hopeful direction of movement, since badguy is at */
- X /* an even spot */
- X else {
- X /* Get allowable movement direction */
- X allow = moveallow[lpos];
- X /* Prevent bad guy from spontaneously switching direction */
- X if(badguys[i].dir == UP)
- X allow &= ~MOVEDOWN;
- X else if(badguys[i].dir == DOWN)
- X allow &= ~MOVEUP;
- X else if(badguys[i].dir == LEFT)
- X allow &= ~MOVERIGHT;
- X else if(badguys[i].dir == RIGHT)
- X allow &= ~MOVELEFT;
- X
- X /* Prevent bad guy from trying to run into somebody else */
- X if((allow & MOVEUP) &&
- X overlap_badguy(badguys[i].xpos,badguys[i].ypos - 2,i))
- X allow &= ~MOVEUP;
- X /* Prevent bad guy from trying to run into somebody else */
- X if((allow & MOVEDOWN) &&
- X overlap_badguy(badguys[i].xpos,badguys[i].ypos + 2,i))
- X allow &= ~MOVEDOWN;
- X /* Prevent bad guy from trying to run into somebody else */
- X if((allow & MOVELEFT) &&
- X overlap_badguy(badguys[i].xpos - 2,badguys[i].ypos,i))
- X allow &= ~MOVELEFT;
- X /* Prevent bad guy from trying to run into somebody else */
- X if((allow & MOVERIGHT) &&
- X overlap_badguy(badguys[i].xpos + 2,badguys[i].ypos,i))
- X allow &= ~MOVERIGHT;
- X
- X /* Try to move according to movement tree */
- X if((allow & MOVEUP) && movetree[lpos] == MOVEUP)
- X dir = UP;
- X else if((allow & MOVEDOWN) && movetree[lpos] == MOVEDOWN)
- X dir = DOWN;
- X else if((allow & MOVELEFT) && movetree[lpos] == MOVELEFT)
- X dir = LEFT;
- X else if((allow & MOVERIGHT) && movetree[lpos] == MOVERIGHT)
- X dir = RIGHT;
- X
- X /* Try circling clockwise around player */
- X else if((allow & MOVEUP) && badguys[i].xpos < player.xpos)
- X dir = UP;
- X else if((allow & MOVEDOWN) && badguys[i].xpos > player.xpos)
- X dir = DOWN;
- X else if((allow & MOVELEFT) && badguys[i].ypos > player.ypos)
- X dir = LEFT;
- X else if((allow & MOVERIGHT) && badguys[i].ypos < player.ypos)
- X dir = RIGHT;
- X
- X /* Try approaching player */
- X else if((allow & MOVEUP) && badguys[i].ypos > player.ypos)
- X dir = UP;
- X else if((allow & MOVEDOWN) && badguys[i].ypos < player.ypos)
- X dir = DOWN;
- X else if((allow & MOVELEFT) && badguys[i].xpos > player.xpos)
- X dir = LEFT;
- X else if((allow & MOVERIGHT) && badguys[i].xpos < player.xpos)
- X dir = RIGHT;
- X
- X /* Try moving in any possible direction */
- X else if(allow & MOVEUP)
- X dir = UP;
- X else if(allow & MOVEDOWN)
- X dir = DOWN;
- X else if(allow & MOVELEFT)
- X dir = LEFT;
- X else if(allow & MOVERIGHT)
- X dir = RIGHT;
- X
- X /* If totally stuck, just stand in place */
- X else
- X dir = STAND;
- X }
- X
- X /* Reverse bad guys direction is REVERSE item is held by player */
- X if((fast_lookup[player.hold].code & REVERSE) &&
- X (x & 1) == 0 && (y & 1) == 0)
- X switch(dir) {
- X case LEFT: dir = RIGHT; break;
- X case RIGHT: dir = LEFT; break;
- X case UP: dir = DOWN; break;
- X case DOWN: dir = UP; break;
- X }
- X
- X /* Execute computed movement. */
- X if(movething(&(badguys[i]),dir,i) == 3) {
- X /* If the bad guy dropped something, the block will have been */
- X /* overwritten and now the bad guy needs to be redrawn */
- X badguys[i].redraw = 1;
- X break;
- X }
- X
- X /* Redraw bad guy if it has moved */
- X if(x != badguys[i].xpos || y != badguys[i].ypos)
- X badguys[i].redraw = 1;
- X }
- X /* Redraw bad guys in new positions */
- X drawmove_badguys();
- X}
- END_OF_FILE
- if test 16560 -ne `wc -c <'golddig2/badguy.c'`; then
- echo shar: \"'golddig2/badguy.c'\" unpacked with wrong size!
- fi
- # end of 'golddig2/badguy.c'
- fi
- if test -f 'golddig2/movement.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'golddig2/movement.c'\"
- else
- echo shar: Extracting \"'golddig2/movement.c'\" \(15801 characters\)
- sed "s/^X//" >'golddig2/movement.c' <<'END_OF_FILE'
- X/* This program was written by Alexander Siegel in September of 1989 */
- X/* at Cornell University. It may may copied freely for private use or */
- X/* public dispersion provided that this comment is not removed. This */
- X/* program, any portion of this program, or any derivative of this */
- X/* program may not be sold or traded for financial gain. */
- X
- X#include <stdio.h>
- X#include <X11/Xlib.h>
- X#include <X11/keysym.h>
- X#include "golddig.h"
- X
- Xlong random();
- X
- X#define MAXHOLE 100 /* Maximum number of holes at once */
- X
- Xint holedecay[] = {2,4,6,62,66,70,74}; /* Number of ticks after which */
- X /* hole will change form. */
- Xint numholes; /* Total number of holes */
- X/* Structure to describe a hole */
- Xstruct {
- X int x,y; /* Position of hole */
- X int ticmade; /* Value of curtick when hole was created. Used to */
- X /* time hole transitions. */
- X} holes[MAXHOLE]; /* Array for holes. */
- X
- X/* Compute the allowable directions of movement out of a block. The */
- X/* value in the moveallow array is updated at that position. */
- Xvoid allow_posit(x,y)
- Xregister int x,y; /* Position of block which is to be checked */
- X{
- X register int pos,code,code2,allow;
- X
- X /* Get position of block in level array */
- X pos = x*ysize + y;
- X /* Initially assume that all directions of movement are acceptable */
- X allow = MOVEUP | MOVEDOWN | MOVELEFT | MOVERIGHT;
- X /* Prevent movement off of the level into nowhere land */
- X if(x == 0)
- X allow &= ~MOVELEFT;
- X if(y == 0)
- X allow &= ~MOVEUP;
- X if(x == xsize - 1)
- X allow &= ~MOVERIGHT;
- X if(y == ysize - 1)
- X allow &= ~MOVEDOWN;
- X
- X /* Get the control code for the block at the position */
- X code = fast_lookup[level[pos]].code;
- X /* Use the control code for space if the block is inactive */
- X if((code & INACTIVE) && goldleft > 0)
- X code = fast_lookup[SPACE].code;
- X /* Use the control bits for the block to reduce the allowable */
- X /* movement directions */
- X if(! (code & ULEAVE))
- X allow &= ~MOVEUP;
- X if(! (code & DLEAVE))
- X allow &= ~MOVEDOWN;
- X if(! (code & LLEAVE))
- X allow &= ~MOVELEFT;
- X if(! (code & RLEAVE))
- X allow &= ~MOVERIGHT;
- X
- X /* Check block to the left to make sure that it is possible to enter */
- X /* that block from the current position. */
- X if(x > 0) {
- X /* Put control code for block to the left into register */
- X code2 = fast_lookup[level[pos - ysize]].code;
- X if((code2 & INACTIVE) && goldleft > 0)
- X code2 = fast_lookup[SPACE].code;
- X /* Determine if it possible to enter */
- X if(! (code2 & HENTER))
- X allow &= ~MOVELEFT;
- X /* Prevent falling back into it if something can walk back from it */
- X if((code2 & RLEAVE) && ! (code2 & CANFALL))
- X code &= ~LFALL;
- X }
- X /* Check block to the right */
- X if(x < xsize - 1) {
- X code2 = fast_lookup[level[pos + ysize]].code;
- X if((code2 & INACTIVE) && goldleft > 0)
- X code2 = fast_lookup[SPACE].code;
- X /* Determine if it possible to enter */
- X if(! (code2 & HENTER))
- X allow &= ~MOVERIGHT;
- X /* Prevent falling back into it if something can walk back from it */
- X if((code2 & LLEAVE) && ! (code2 & CANFALL))
- X code &= ~RFALL;
- X }
- X /* Check block above */
- X if(y > 0) {
- X code2 = fast_lookup[level[pos - 1]].code;
- X if((code2 & INACTIVE) && goldleft > 0)
- X code2 = fast_lookup[SPACE].code;
- X /* Determine if it possible to enter */
- X if(! (code2 & VENTER))
- X allow &= ~MOVEUP;
- X /* Prevent falling back into it if something can walk back from it */
- X if((code2 & DLEAVE) && ! (code2 & CANFALL))
- X code &= ~UFALL;
- X }
- X /* Check block below */
- X if(y < ysize - 1) {
- X code2 = fast_lookup[level[pos + 1]].code;
- X if((code2 & INACTIVE) && goldleft > 0)
- X code2 = fast_lookup[SPACE].code;
- X /* Determine if it possible to enter */
- X if(! (code2 & VENTER))
- X allow &= ~MOVEDOWN;
- X /* Prevent falling back into it if something can walk back from it */
- X /* Note that things will stick up if there is upward gravity */
- X /* pointing into downward gravity. */
- X if(code2 & ULEAVE)
- X code &= ~DFALL;
- X }
- X
- X /* Add gravity force */
- X if((code & DFALL) && (allow & MOVEDOWN))
- X allow |= FORCEDOWN;
- X if((code & UFALL) && (allow & MOVEUP))
- X allow |= FORCEUP;
- X if((code & LFALL) && (allow & MOVELEFT))
- X allow |= FORCELEFT;
- X if((code & RFALL) && (allow & MOVERIGHT))
- X allow |= FORCERIGHT;
- X
- X /* Store value back into moveallow array */
- X moveallow[pos] = allow;
- X}
- X
- X/* Call allow_posit on a position and all surrounding positions */
- Xvoid allow_area(x,y)
- Xint x,y; /* Position to call allow_posit at */
- X{
- X allow_posit(x,y);
- X if(x < xsize - 1)
- X allow_posit(x+1,y);
- X if(x > 0)
- X allow_posit(x-1,y);
- X if(y < ysize - 1)
- X allow_posit(x,y+1);
- X if(y > 0)
- X allow_posit(x,y-1);
- X}
- X
- X/* Regenerate entire moveallow array */
- Xvoid regen_allow()
- X{
- X int x,y;
- X
- X /* Iterate through every possible position and call allow_posit on */
- X /* it. */
- X for(x=0;x<xsize;++x)
- X for(y=0;y<ysize;++y)
- X allow_posit(x,y);
- X}
- X
- X/* Form a hole. */
- Xvoid make_hole(x,y,code)
- Xint x,y; /* Position where hole is to be formed */
- Xlong code; /* Code of item held while digging */
- X{
- X register int pos;
- X
- X /* Compute position in level array where hole is to be created */
- X pos = x*ysize + y;
- X /* Make sure that the position is inside the level array */
- X if(x < 0 || x >= xsize || y < 1 || y >= ysize)
- X return;
- X /* Check for reverse shovel */
- X if(code & RSHOVEL) {
- X /* Make sure that there is space is the specified position */
- X if(level[pos] != SPACE)
- X return;
- X /* Replace space with brick */
- X setchar(x,y,BRICK);
- X }
- X else {
- X /* Make sure that the block can be dug */
- X if(! (fast_lookup[level[pos]].code & CANDIG) ||
- X /* Make sure that the block above it allows for digging */
- X /* underneath. */
- X ! (fast_lookup[level[pos - 1]].code & DIGUND))
- X return;
- X
- X /* Check for power shovel */
- X if(code & PSHOVEL)
- X setchar(x,y,SPACE);
- X else {
- X /* Prevent the creation of too many holes */
- X if(numholes >= MAXHOLE)
- X return;
- X /* Replace the character at the position with the first hole block */
- X setchar(x,y,HOLE1);
- X /* Add that hole to the hole array */
- X holes[numholes].x = x;
- X holes[numholes].y = y;
- X holes[numholes].ticmade = curtick;
- X numholes ++;
- X }
- X }
- X /* Recompute the allowable movement direction for that position and */
- X /* all surrounding positions */
- X allow_area(x,y);
- X}
- X
- X/* Fill up a hole with brick */
- Xvoid fill_hole(x,y)
- Xint x,y; /* Position specifying hole */
- X{
- X register int i;
- X
- X /* Look through all the holes until the right one is found */
- X for(i=0;i<numholes;++i)
- X if(holes[i].x == x && holes[i].y == y) {
- X /* Change the block to a brick */
- X setchar(holes[i].x,holes[i].y,BRICK);
- X /* Recompute the allowable movement for the specified position */
- X /* and all surrounding positions. */
- X allow_area(holes[i].x,holes[i].y);
- X /* Remove the hole from the holes array */
- X holes[i] = holes[numholes - 1];
- X numholes --;
- X return;
- X }
- X}
- X
- X/* Age all holes by one clock tick */
- Xvoid change_holes()
- X{
- X register int i,j;
- X
- X /* Look for decaying holes. Iterate through each hole. */
- X for(i=0;i<numholes;++i) {
- X /* Check if the hole is exactly at any transition point */
- X for(j=0;j<7;++j)
- X if(holes[i].ticmade + holedecay[j] == curtick) {
- X /* If it is a normal transition point, just change the block */
- X /* type */
- X if(j < 6)
- X setchar(holes[i].x,holes[i].y,(char) (HOLE1 + j + 1));
- X /* If it is the last transition point, fill the hole in */
- X else {
- X fill_hole(holes[i].x,holes[i].y);
- X /* Back up one hole since the hole that was at this position */
- X /* has now been replaced by another. */
- X i --;
- X }
- X break;
- X }
- X }
- X}
- X
- X/* Try to move a thing (player or bad guy) in a given direction. The */
- X/* structure describing the things is updated in place with the new */
- X/* position and apparent active command. A code value is returned */
- X/* describing what type of movement actually occurred. */
- Xint movething(thing,newdir,num)
- Xregister struct thing_s *thing; /* Pointer to struct describing */
- X /* current state of thing */
- Xenum directs newdir; /* New command being attempted */
- Xint num; /* Number of bad guy or -1 for */
- X /* player */
- X{
- X register int lpos,code;
- X int nx,ny;
- X
- X /* Compute useful local values */
- X lpos = (thing->xpos >> 1)*ysize + (thing->ypos >> 1);
- X code = fast_lookup[level[lpos]].code;
- X if((code & INACTIVE) && goldleft > 0)
- X code = fast_lookup[SPACE].code;
- X
- X /* Complete previous initiated movement */
- X if((thing->xpos & 1) || (thing->ypos & 1)) {
- X /* Allow partial horizontal movement to complete */
- X if(thing->xpos & 1) {
- X /* Continue in old direction */
- X switch(thing->dir) {
- X case LEFT:
- X thing->xpos -= 1;
- X thing->dir = LEFT;
- X break;
- X default:
- X thing->xpos += 1;
- X thing->dir = RIGHT;
- X break;
- X }
- X }
- X
- X /* Allow partial vertical movement to complete */
- X if(thing->ypos & 1) {
- X /* Continue in old direction */
- X switch(thing->dir) {
- X case UP:
- X thing->ypos -= 1;
- X thing->dir = UP;
- X break;
- X default:
- X thing->ypos += 1;
- X thing->dir = DOWN;
- X break;
- X }
- X }
- X
- X /* Pickup things which are laying around */
- X lpos = (thing->xpos >> 1)*ysize + (thing->ypos >> 1);
- X code = fast_lookup[level[lpos]].code;
- X if(newdir != PUTDOWN && (code & PICKUP) && thing->hold == SPACE) {
- X thing->hold = level[lpos];
- X setchar(thing->xpos >> 1,thing->ypos >> 1,SPACE);
- X allow_area(thing->xpos >> 1,thing->ypos >> 1);
- X }
- X
- X /* Activate teleporter if standing on one and not holding an */
- X /* anchor */
- X if((code & TELEPORT) &&
- X ! (fast_lookup[thing->hold].code & ANCHOR)) {
- X do {
- X lpos ++;
- X thing->ypos += 2;
- X if(thing->ypos >> 1 == ysize) {
- X thing->ypos = 0;
- X thing->xpos += 2;
- X if(thing->xpos >> 1 == xsize) {
- X lpos = 0;
- X thing->xpos = 0;
- X }
- X }
- X } while(! (fast_lookup[level[lpos]].code & TELEPORT));
- X }
- X
- X /* Activate jump pad if standing on one and not holding an anchor */
- X if((code & UPTWO) &&
- X ! (fast_lookup[thing->hold].code & ANCHOR)) {
- X thing->ypos -= 4;
- X if(thing->ypos < 0)
- X thing->ypos = 0;
- X }
- X
- X /* Activate super jump pad */
- X if(code & UPALL) {
- X thing->ypos -= 4;
- X /* Jump to the top of screen if not holding an anchor */
- X if(thing->ypos < 0 ||
- X ! (fast_lookup[thing->hold].code & ANCHOR))
- X thing->ypos = 0;
- X }
- X
- X return(1);
- X }
- X
- X /* Allow creature to fall */
- X if((moveallow[lpos] & FORCEALL) &&
- X ! (fast_lookup[thing->hold].code & STOPFALL)) {
- X /* Compute position offset in direction of fall */
- X nx = ny = 0;
- X if(moveallow[lpos] & FORCEDOWN) {
- X ny = 1;
- X thing->dir = DOWN;
- X }
- X if(moveallow[lpos] & FORCEUP) {
- X ny = -1;
- X thing->dir = UP;
- X }
- X if(moveallow[lpos] & FORCERIGHT) {
- X nx = 1;
- X thing->dir = RIGHT;
- X }
- X if(moveallow[lpos] & FORCELEFT) {
- X nx = -1;
- X thing->dir = LEFT;
- X }
- X
- X /* Prevent falling into another thing */
- X if(! overlap_badguy(thing->xpos + nx + nx,thing->ypos + ny + ny,num)) {
- X /* Drop item behind if falling into a hole */
- X if(level[lpos] == SPACE && thing->hold != SPACE) {
- X /* Compute level position of space that thing is falling into */
- X lpos = ((thing->xpos >> 1)+nx)*ysize +
- X ((thing->ypos >> 1)+ny);
- X /* Check to see if next position is a hole */
- X if(fast_lookup[level[lpos]].code & STOPBAD) {
- X setchar(thing->xpos >> 1,thing->ypos >> 1,thing->hold);
- X thing->hold = SPACE;
- X allow_area(thing->xpos >> 1,thing->ypos >> 1);
- X }
- X }
- X
- X /* Increment position */
- X thing->xpos += nx;
- X thing->ypos += ny;
- X return(2);
- X }
- X }
- X
- X /* Slow movement down if holding an anchor */
- X if((fast_lookup[thing->hold].code & ANCHOR) && (random() % 4 != 0))
- X newdir = STAND;
- X
- X /* Continue previous movement if it was at right angles to intended */
- X /* movement, and intended movement is impossible */
- X switch(newdir) {
- X /* Check for possible upward movement. */
- X case UP:
- X if(! (moveallow[lpos] & MOVEUP)) {
- X if(thing->dir == LEFT || thing->dir == RIGHT)
- X newdir = thing->dir;
- X }
- X break;
- X /* Check for possible downward movement. */
- X case DOWN:
- X if(! (moveallow[lpos] & MOVEDOWN)) {
- X if(thing->dir == LEFT || thing->dir == RIGHT)
- X newdir = thing->dir;
- X }
- X break;
- X /* Check for possible left movement. */
- X case LEFT:
- X if(! (moveallow[lpos] & MOVELEFT)) {
- X if(thing->dir == UP || thing->dir == DOWN)
- X newdir = thing->dir;
- X }
- X break;
- X /* Check for possible right movement. */
- X case RIGHT:
- X if(! (moveallow[lpos] & MOVERIGHT)) {
- X if(thing->dir == UP || thing->dir == DOWN)
- X newdir = thing->dir;
- X }
- X break;
- X }
- X
- X /* By default, the thing is standing in place */
- X thing->dir = STAND;
- X /* Try to execute the intended movement */
- X switch(newdir) {
- X /* Put something down if that is the order */
- X case PUTDOWN:
- X if(level[lpos] == SPACE && thing->hold != SPACE) {
- X setchar(thing->xpos >> 1,thing->ypos >> 1,thing->hold);
- X thing->hold = SPACE;
- X allow_area(thing->xpos >> 1,thing->ypos >> 1);
- X }
- X return(3);
- X /* Dig holes left or right if that is the command. The make_hole */
- X /* command will fail if it is impossible to dig a hole at the */
- X /* specified location. */
- X case DIGLEFT:
- X make_hole((thing->xpos >> 1) - 1,(thing->ypos >> 1) + 1,
- X fast_lookup[thing->hold].code);
- X if(fast_lookup[thing->hold].code & NSHOVEL) {
- X make_hole((thing->xpos >> 1) - 2,(thing->ypos >> 1) + 1,
- X fast_lookup[thing->hold].code);
- X make_hole((thing->xpos >> 1) - 1,(thing->ypos >> 1) + 2,
- X fast_lookup[thing->hold].code);
- X make_hole((thing->xpos >> 1) - 2,(thing->ypos >> 1) + 2,
- X fast_lookup[thing->hold].code);
- X }
- X return(4);
- X case DIGRIGHT:
- X make_hole((thing->xpos >> 1) + 1,(thing->ypos >> 1) + 1,
- X fast_lookup[thing->hold].code);
- X if(fast_lookup[thing->hold].code & NSHOVEL) {
- X make_hole((thing->xpos >> 1) + 2,(thing->ypos >> 1) + 1,
- X fast_lookup[thing->hold].code);
- X make_hole((thing->xpos >> 1) + 1,(thing->ypos >> 1) + 2,
- X fast_lookup[thing->hold].code);
- X make_hole((thing->xpos >> 1) + 2,(thing->ypos >> 1) + 2,
- X fast_lookup[thing->hold].code);
- X }
- X return(4);
- X /* Since the thing is not falling or completing a previous movement, */
- X /* it can start off in a new direction. The moveallow array is used */
- X /* to determine which directions are possible. */
- X /* Check for possible upward movement. */
- X case UP:
- X if(moveallow[lpos] & MOVEUP) {
- X thing->ypos -= 1;
- X thing->dir = UP;
- X }
- X break;
- X /* Check for possible downward movement. */
- X case DOWN:
- X if(moveallow[lpos] & MOVEDOWN) {
- X thing->ypos += 1;
- X thing->dir = DOWN;
- X }
- X break;
- X /* Check for possible left movement. */
- X case LEFT:
- X if(moveallow[lpos] & MOVELEFT) {
- X thing->xpos -= 1;
- X thing->dir = LEFT;
- X }
- X break;
- X /* Check for possible right movement. */
- X case RIGHT:
- X if(moveallow[lpos] & MOVERIGHT) {
- X thing->xpos += 1;
- X thing->dir = RIGHT;
- X }
- X break;
- X }
- X return(0);
- X}
- END_OF_FILE
- if test 15801 -ne `wc -c <'golddig2/movement.c'`; then
- echo shar: \"'golddig2/movement.c'\" unpacked with wrong size!
- fi
- # end of 'golddig2/movement.c'
- fi
- if test -f 'golddig2/shared.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'golddig2/shared.c'\"
- else
- echo shar: Extracting \"'golddig2/shared.c'\" \(14143 characters\)
- sed "s/^X//" >'golddig2/shared.c' <<'END_OF_FILE'
- X/* This program was written by Alexander Siegel in September of 1989 */
- X/* at Cornell University. It may may copied freely for private use or */
- X/* public dispersion provided that this comment is not removed. This */
- X/* program, any portion of this program, or any derivative of this */
- X/* program may not be sold or traded for financial gain. */
- 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 <string.h>
- X#include "golddig.h"
- X
- X/* Include all the bitmaps for the terrain blocks */
- X#include "bitmap/player.bits"
- X#include "bitmap/badguy.bits"
- X#include "bitmap/ladder.bits"
- X#include "bitmap/space.bits"
- X#include "bitmap/wall.bits"
- X#include "bitmap/hole1.bits"
- X#include "bitmap/hole2.bits"
- X#include "bitmap/hole3.bits"
- X#include "bitmap/hole4.bits"
- X#include "bitmap/hole5.bits"
- X#include "bitmap/hole6.bits"
- X#include "bitmap/hole7.bits"
- X#include "bitmap/stone.bits"
- X#include "bitmap/ghost.bits"
- X#include "bitmap/gold.bits"
- X#include "bitmap/escape.bits"
- X#include "bitmap/rope.bits"
- X#include "bitmap/uplevel.bits"
- X#include "bitmap/invis.bits"
- X#include "bitmap/steplad.bits"
- X#include "bitmap/tube.bits"
- X#include "bitmap/chute.bits"
- X#include "bitmap/vrope.bits"
- X#include "bitmap/teleport.bits"
- X#include "bitmap/armor.bits"
- X#include "bitmap/parac.bits"
- X#include "bitmap/nshovel.bits"
- X#include "bitmap/hourgl.bits"
- X#include "bitmap/reverse.bits"
- X#include "bitmap/portable.bits"
- X#include "bitmap/larrow.bits"
- X#include "bitmap/rarrow.bits"
- X#include "bitmap/darrow.bits"
- X#include "bitmap/uarrow.bits"
- X#include "bitmap/kill.bits"
- X#include "bitmap/jump.bits"
- X#include "bitmap/anchor.bits"
- X#include "bitmap/sjump.bits"
- X#include "bitmap/speed.bits"
- X#include "bitmap/pshovel.bits"
- X#include "bitmap/rshovel.bits"
- X#include "bitmap/fog.bits"
- X#include "bitmap/window.bits"
- X#include "bitmap/anti.bits"
- X
- Xchar *sprintf(); /* UNIX brain damage */
- X
- X/* All in and out movements except up */
- X#define NOUPBITS DLEAVE | LLEAVE | RLEAVE | HENTER | VENTER
- X/* All in and out movements */
- X#define MOVEBITS NOUPBITS | ULEAVE
- X/* Standard bit pattern for empty space */
- X#define SPACEBITS NOUPBITS | DIGUND | DFALL
- X/* Generic item which can be picked up */
- X#define ITEMBITS SPACEBITS | PICKUP
- X/* Bit pattern used for dug holes */
- X#define HOLEBITS SPACEBITS | STOPBAD | NODRAW
- X
- X/* Structure describing all the characteristics of all blocks. Refer */
- X/* to the defines and structure definition in golddig.h. */
- Xstruct symbs_s symbs[] =
- X {{SPACE,SPACE,"space",space_bits,SPACEBITS,XK_space,0},
- X {'!','|',"escape",escape_bits,MOVEBITS | DIGUND | INACTIVE,XK_exclam,XK_1},
- X {BRICK,BRICK,"wall",wall_bits,CANDIG | KILLIN,XK_3,XK_numbersign},
- X {'$','$',"gold",gold_bits,ITEMBITS | TREASURE,XK_4,XK_dollar},
- X {'-','-',"rope",rope_bits,NOUPBITS | DIGUND,XK_minus,0},
- X {HOLE1,HOLE1,"hole1",hole1_bits,HOLEBITS,0,0},
- X {HOLE1+1,HOLE1+1,"hole2",hole2_bits,HOLEBITS,0,0},
- X {HOLE1+2,HOLE1+2,"hole3",hole3_bits,HOLEBITS,0,0},
- X {HOLE1+3,HOLE1+3,"hole4",hole4_bits,HOLEBITS,0,0},
- X {HOLE1+4,HOLE1+4,"hole5",hole5_bits,HOLEBITS,0,0},
- X {HOLE1+5,HOLE1+5,"hole6",hole6_bits,HOLEBITS,0,0},
- X {HOLE1+6,HOLE1+6,"hole7",hole7_bits,HOLEBITS,0,0},
- X {'<','<',"left arrow",larrow_bits,LLEAVE | HENTER | VENTER | LFALL | DIGUND,
- X XK_comma,XK_less},
- X {'=','=',"tube",tube_bits,RLEAVE | LLEAVE | HENTER,XK_equal,0},
- X {'>','>',"right arrow",rarrow_bits,RLEAVE | HENTER | VENTER | RFALL |
- X DIGUND,XK_period,XK_greater},
- X {STONE,STONE,"stone",stone_bits,KILLIN,XK_2,XK_at},
- X {'^','^',"anti-space",anti_bits,ULEAVE | LLEAVE | RLEAVE | HENTER |
- X VENTER | DIGUND | UFALL,XK_6,XK_asciicircum},
- X {'a','a',"armor",armor_bits,ITEMBITS | ARMOR,XK_A,XK_a},
- X {BADGUY,BADGUY,"bad guy",badguy_bits,SPACEBITS,XK_B,XK_b},
- X {'c','c',"chute",chute_bits,DLEAVE | DFALL | VENTER,XK_C,XK_c},
- X {'d','d',"down arrow",darrow_bits,DLEAVE | HENTER | VENTER | DIGUND |
- X DFALL,XK_D,XK_d},
- X {'e','e',"reverse monster",reverse_bits,ITEMBITS | REVERSE, XK_E,XK_e},
- X {'f','f',"up arrow",uarrow_bits,ULEAVE | HENTER | VENTER | UFALL |
- X DIGUND,XK_F,XK_f},
- X {'g',BRICK,"ghost brick",ghost_bits,(SPACEBITS) & ~HENTER,XK_G,XK_g},
- X {'i',SPACE,"invisible block",invis_bits,KILLIN,XK_I,XK_i},
- X {'j','j',"jump pad",jump_bits,NOUPBITS | UPTWO,XK_J,XK_j},
- X {'k','k',"kill zone",kill_bits,HENTER | VENTER | DIGUND |
- X KILLIN,XK_K,XK_k},
- X {'l','l',"power shovel",pshovel_bits,ITEMBITS | PSHOVEL,XK_L,XK_l},
- X {'m','m',"super jump pad",sjump_bits,NOUPBITS | UPALL,XK_M,XK_m},
- X {'n','n',"nuclear shovel",nshovel_bits,ITEMBITS | NSHOVEL,XK_N,XK_n},
- X {'o','o',"anchor",anchor_bits,ITEMBITS | ANCHOR,XK_O,XK_o},
- X {PLAYER,PLAYER,"player",player_bits,SPACEBITS,XK_P,XK_p},
- X {'q','q',"speed boot",speed_bits,ITEMBITS | SPEED,XK_Q,XK_q},
- X {'r','r',"parachute",parac_bits,ITEMBITS | STOPFALL,XK_R,XK_r},
- X {'s','s',"step ladder",steplad_bits,MOVEBITS | PICKUP,XK_S,XK_s},
- X {'t','t',"teleporter",teleport_bits,SPACEBITS | TELEPORT,XK_T,XK_t},
- X {'u','u',"leave level",uplevel_bits,SPACEBITS | UPLEVEL |
- X INACTIVE,XK_U,XK_u},
- X {'v','v',"vertical rope",vrope_bits,ULEAVE | DLEAVE |
- X HENTER | VENTER,XK_V,XK_v},
- X {'w','w',"window",window_bits,SPACEBITS | UPLEVEL,XK_W,XK_w},
- X {'x','x',"extra brick",rshovel_bits,ITEMBITS | RSHOVEL,XK_X,XK_x},
- X {'y','y',"heavy fog",fog_bits,SPACEBITS,XK_Y,XK_y},
- X {'z','z',"time stop",hourgl_bits,ITEMBITS | TIMESTOP,XK_Z,XK_z},
- X {'|','|',"ladder",ladder_bits,MOVEBITS,XK_backslash,XK_bar},
- X {'~','-',"portable rope",portable_bits,NOUPBITS | DIGUND |
- X PICKUP,XK_asciitilde,XK_quoteleft},
- X
- X /* List terminator */
- X {'\0','\0',(char *) 0,(char *) 0,0,0,0}};
- X
- XFont scorefont; /* Font used to display score */
- XGC scoregc; /* GC used to draw score */
- XGC blackgc; /* Simple black foreground GC */
- X
- X/* Manufaction a 16x16 graphics cursor used in a XFill... operation. */
- XGC makegc(func,bits)
- Xint func; /* Drawing function such as GXcopy or GXor. */
- Xchar bits[]; /* Bits describing fill pattern. Produced in 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,16,16,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
- X/* Start X11 and do some basic initialization */
- Xvoid xstart(evmask)
- Xlong evmask; /* Event mask which will be used in XSelectInput */
- X{
- X register int i;
- X XGCValues xgcv;
- X XWMHints wmhints;
- X
- X /* Open up the display */
- X disp = XOpenDisplay(NULL);
- X /* Check to see if the open display succeeded */
- X if(disp == NULL) {
- X fprintf(stderr,"Display open failed. Check DISPLAY environment variable.\n");
- X exit(-1);
- X }
- X
- X /* Create the game window */
- X wind = XCreateSimpleWindow(disp,DefaultRootWindow(disp),20,20,
- X 50 << 4,(30 << 4) + SCORESIZE,
- X 2,WhitePixel(disp,0),BlackPixel(disp,0));
- X /* Check to see if the open window succeeded */
- X if(wind == 0) {
- X fprintf(stderr,"Window open failed.\n");
- X XCloseDisplay(disp);
- X exit(-1);
- X }
- X
- X /* Clear fast block type lookup table */
- X for(i=0;i<256;++i) {
- X fast_lookup[i].gc = NULL;
- X /* Everything starts out looking like a space */
- X fast_lookup[i].code = SPACEBITS;
- X }
- X /* Generate block type lookup table from symbs array defined above. */
- X /* After this the symbs array will be used very rarely. */
- X for(i=0;symbs[i].symb != '\0';++i) {
- X fast_lookup[symbs[i].symb].gc =
- X makegc(GXcopy,symbs[i].bits);
- X fast_lookup[symbs[i].symb].code = symbs[i].code;
- 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 = WhitePixel(disp,0);
- X xgcv.background = BlackPixel(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 xgcv.foreground = BlackPixel(disp,0);
- X xgcv.background = WhitePixel(disp,0);
- X blackgc = XCreateGC(disp,wind,
- X GCFunction | GCForeground | GCBackground,
- X &xgcv);
- X
- X /* Tell the WM that we want input... */
- X wmhints.input = True;
- X wmhints.flags = InputHint;
- X XSetWMHints(disp, wind, &wmhints);
- X
- X /* Select the interesting window events */
- X XSelectInput(disp,wind,evmask);
- X
- X /* Name and raise the window */
- X XMapRaised(disp,wind);
- X
- X /* Flush and synchronize the server */
- X XFlush(disp);
- X XSync(disp,False);
- X}
- X
- X/* Gracefully shut X windows down. It is not strictly necessary to */
- X/* call this function. */
- Xvoid xend()
- X{
- X XUnloadFont(disp,scorefont);
- X XUnmapWindow(disp,wind);
- X XDestroyWindow(disp,wind);
- X XCloseDisplay(disp);
- X}
- X
- X/* Draw a block from the level array in the output window. */
- Xvoid draw_block(x,y)
- Xint x,y; /* Position of block in array */
- X{
- X register char curchar;
- X GC drawgc;
- X
- X /* Get the block character out of the level array */
- X curchar = level[x*ysize + y];
- X /* If there is gold left and this block is inactive, replace it with */
- X /* a space. */
- X if(goldleft > 0 && (fast_lookup[curchar].code & INACTIVE))
- X curchar = SPACE;
- X /* Get the graphics cursor */
- X drawgc = fast_lookup[curchar].gc;
- X /* Replace questionable characters with spaces */
- X if(drawgc == NULL)
- X drawgc = fast_lookup[SPACE].gc;
- X /* Fill the block */
- X XFillRectangle(disp,wind,drawgc,x << 4,y << 4,16,16);
- X}
- X
- X/* Change a block character in the level array. The block is redrawn. */
- Xvoid setchar(x,y,ch)
- Xint x,y; /* Position of block character to change. */
- Xchar ch; /* Character to change it to */
- X{
- X if(level[x*ysize + y] != ch) {
- X level[x*ysize + y] = ch;
- X draw_block(x,y);
- X }
- X}
- X
- X/* Draw the score and level number */
- Xvoid draw_score()
- X{
- X char buf[50];
- X
- X /* Build the output string */
- X sprintf(buf,"score: %d level: %d speed: %d",score,levelnum,speed);
- X /* Clear the current score line */
- X XFillRectangle(disp,wind,blackgc,0,ysize << 4,xsize << 4,SCORESIZE);
- X /* Actually draw the text */
- X XDrawString(disp,wind,scoregc,0,(ysize << 4) + SCORESIZE - 1,buf,
- X strlen(buf));
- X}
- X
- X/* Redraw the entire level */
- Xvoid draw_level()
- X{
- X int x,y;
- X
- X /* Change the window size */
- X XResizeWindow(disp,wind,xsize << 4,(ysize << 4) + SCORESIZE);
- X /* Draw the score and level number */
- X draw_score();
- X /* Iterate through each block position and draw it */
- X for(x=0;x < xsize;++x)
- X for(y=0;y < ysize;++y)
- X draw_block(x,y);
- X}
- X
- X/* Load a level out of a file. The global variables worldname and */
- X/* levelnum are used to produce the file name which is stored in */
- X/* filename. */
- Xvoid load_level()
- X{
- X FILE *levelfile;
- X register int i,j;
- X int x,y;
- X char buf[300];
- X
- X /* Manufaction the file name by starting with the world name and */
- X /* appending the level number to it. */
- X strcpy(filename,LIB);
- X strcat(filename,"/");
- X strcat(filename,worldname);
- 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 /* Build the default level name */
- X strcpy(buf,LIB);
- X strcat(buf,"/default");
- X /* Open default level file for reading */
- X levelfile = fopen(buf,"r");
- X if(levelfile == NULL) {
- X perror(worldname);
- X exit(1);
- X }
- X }
- X
- X /* Load the first line of the level file */
- X if(fgets(buf,300,levelfile) == NULL) {
- X x = 50;
- X y = 30;
- X }
- X else {
- X /* Extract the level size */
- X sscanf(buf,"%d %d",&x,&y);
- X }
- X /* Change level size only if it is necessary */
- X if(xsize == -1)
- X xsize = x;
- X if(ysize == -1)
- X ysize = y;
- X /* Carefully check the sanity of the size parameters */
- X if(xsize < 5)
- X xsize = 5;
- X if(xsize > 250)
- X xsize = 250;
- X if(ysize < 5)
- X ysize = 5;
- X if(ysize > 250)
- X ysize = 250;
- X if(xsize * ysize > MAXLEVEL) {
- X if(xsize > ysize)
- X xsize = MAXLEVEL / ysize;
- X else
- X ysize = MAXLEVEL / xsize;
- X }
- X /* Iterate through each horizontal line */
- X for(i=0;i<ysize;++i) {
- X /* Load the next line from the file */
- X if(fgets(buf,300,levelfile) != NULL) {
- X /* Go through each horizontal position and copy the data into */
- X /* the level array. */
- X for(j=0;j<xsize;++j) {
- X /* Break out if line ends prematurely */
- X if(buf[j] == '\n' || buf[j] == '\0')
- X break;
- X level[j*ysize + i] = buf[j];
- X }
- X }
- X else
- X j = 0;
- X /* Fill in rest of premature lines with spaces */
- X for(;j<xsize;++j)
- X level[j*ysize + i] = SPACE;
- X }
- X /* Close the level file */
- X fclose(levelfile);
- X}
- X
- X/* Save the current level back into a file. The global variable */
- X/* filename is used to determine the file name. */
- Xvoid save_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 perror(worldname);
- 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\n",xsize,ysize);
- X /* Terminate the lines for writing out the horizontal level lines */
- X buf[xsize] = '\n';
- X buf[xsize+1] = '\0';
- X /* Iterate through each vertical position */
- X for(i=0;i<ysize;++i) {
- X /* Copy each horizontal line into the output buffer */
- X for(j=0;j<xsize;++j)
- X buf[j] = level[j*ysize + i];
- X /* Write the line out to the file */
- X fputs(buf,levelfile);
- X }
- X /* Close the data file */
- X fclose(levelfile);
- X}
- X
- X
- END_OF_FILE
- if test 14143 -ne `wc -c <'golddig2/shared.c'`; then
- echo shar: \"'golddig2/shared.c'\" unpacked with wrong size!
- fi
- # end of 'golddig2/shared.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-