v06i070: plumbing, Part01/01

Terry Weissman weissman at wsl.dec.com
Thu Apr 12 17:45:30 AEST 1990


Submitted-by: Terry Weissman <weissman at wsl.dec.com>
Posting-number: Volume 6, Issue 70
Archive-name: xplumb/part01

This is plumbing, an X11 implementation of the game Pipe Dreams, which was
created by Lucasfilm and is distributed by Electronic Arts for Amigas
and probably other personal computers.  It requires C++ and X11R4.

- Terry Weissman	(weissman at wsl.dec.com)


#! /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 shell archive."
# Contents:  README plumbing.6 Makefile plumbing.h board.C flow.C
#   init.C level.C main.C piece.C queue.C score.C screen.C timer.C
# Wrapped by weissman at gilroy.pa.dec.com on Tue Apr 10 13:52:17 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(799 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Plumbing is an X implementation of the game Pipe Dreams, which was
created by Lucasfilm and is distributed by Electronic Arts for Amigas
and probably other personal computers.  If you own a personal
computer, I urge you to go out and buy Pipe Dreams; it's a much better
game than Plumbing.
X
Note that this game requires C++ and X11R4.  If you don't have them,
you might as well give up now.
X
To build, first edit the Makefile to point to your X11R4 server tree,
and change the definition of SCOREFILE in plumbing.h to point to a
file to use for storing high scores.  Then just type Make.
X
I have built this game only on Ultrix machines (both VAXen and
DECstation 3100s) using CFront 1.2.  I tried to keep things portable,
but I probably failed somewhere (most likely, the high score code,
score.C).
END_OF_FILE
if test 799 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'plumbing.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'plumbing.6'\"
else
echo shar: Extracting \"'plumbing.6'\" \(4642 characters\)
sed "s/^X//" >'plumbing.6' <<'END_OF_FILE'
X.\"Man page for plumbing, by Terry Weissman.
X.TH plumbing 6 "02 March 1990"
X.SH NAME
X\fIplumbing\fR - Keep ahead of the flow
X.SH SYNOPSIS
X.B plumbing
X[-display display:number]
X.SH DESCRIPTION
X.I plumbing
is an X implementation of the game
X.I Pipe Dreams,
which was created by Lucasfilm and is distributed by Electronic Arts for 
Amigas and probably other personal computers.  If you own a personal computer,
I urge you to go out and buy 
X.I Pipe Dreams;
it's a much better game than
X.I plumbing.
X
X.SH PLAYING PLUMBING
Initially, you are presented with a start up screen which gives a
minimal amount of instructions, and the high scores.  Click with the
mouse to begin a game.
X
When the game has started, you'll be presented with the game grid.
XEach spot on the grid can hold one piece of plumbing.  Initially, they
are all empty (marked with an X) except one place which has a starting
section of pipe.  On the right edge of the window is a queue of pipe
sections. 
X
To place a section of pipe, just click on an empty spot in the game
grid.  The bottommost section in the queue will be placed on the spot
you select, and the queue will shift down.
X
You may also place a section of pipe on top of an already existing
piece.  The piece will be replaced, but the replacement operation
takes some time, and it costs you points.  You may not replace the
starting section of pipe or any section that has flow in it.
X
After an initial delay (which is indicated as a countdown on the
bottom of the window), the flow will begin.  It starts in the starting
section of pipe and flows through adjacent pieces.  (It always flows
straight through the cross-shaped pieces.)  The "Needs" display on
the bottom of the window indicates how many more sections you must
flow through to survive the level.   The level ends when the flow has
no place to go.  The game ends when you end the level and the "Needs"
display is positive.
X
At any point in the level, you may press the 'F' key (or hit the right
mouse button), and the flow will go much faster.  You will not be
allowed to place any more pieces, but scoring will increase.
X
X.SH SCORING
X
You receive 100 points for each section of pipe that the flow goes
through.  You receive 500 points each time the flow crosses itself in a
cross-shaped piece.  You lose 100 points each time you replace a
piece.  And, at the end of the level, you lose 100 points for each
piece that was placed that does not have flow going through it.
X
After making the flow go fast (by pressing 'F' or the right mouse
button), scoring will double.  That is, you'll receive 200 points for
each section of pipe the flow goes through, and 1000 points each time
it crosses itself.  You still only lose 100 points for each piece
placed without flow through it.
X
X.SH OTHER COMMANDS
X
At any point, you may pause the screen by hitting 'P'.  You may quit
the game entirely at any time by hitting 'Q'.
X
X.SH BUGS
X
Needs an icon.
X
Needs color support.
X
Does not look at any resources at all.  That is, your .Xdefaults file
will be ignored.
X
When you iconify it, it should automatically pause.
X
Could use some tuning.
X
Lots of the code is horrid.
X
The high-score code is truly horrendous.  If you have a good
high-score library (which is fast, handles locking, and keeps the same
information I keep), I'd love to get a copy to merge in.
X
X.SH COPYRIGHT
X
X
Copyright 1990 Digital Equipment Corporation
X
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital Equipment
Corporation not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.  Digital Equipment Corporation makes no representations
about the suitability of this software for any purpose.  It is
provided "as is" without express or implied warranty.
X
DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
XFITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X
X
X.SH AUTHOR
X
Terry Weissman
X.br
Western Software Laboratory
X.br
Digital Equipment Corporation
X.br
weissman at wsl.dec.com
END_OF_FILE
if test 4642 -ne `wc -c <'plumbing.6'`; then
    echo shar: \"'plumbing.6'\" unpacked with wrong size!
fi
# end of 'plumbing.6'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(602 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Hopefully, the only thing you'll need to change here is TOP, which should
X# point to the top of your X11 source tree.  If you want to build based on 
X# installed binaries, then you can remove the definition for INCLUDES, and
X# make LIBX be "-lX11".
X
TOP = /a12c/X11R4-$$arch
INCLUDES = -I$(TOP)/mit
LIBX = $(TOP)/mit/lib/X/libX11.a
DEFINES = -Dvolatile= -Dsigned=
X
OBJS = main.o init.o screen.o timer.o board.o score.o queue.o piece.o \
X	level.o flow.o
X
X
X.SUFFIXES: $(.SUFFIXES) .C
X
X.C.o: $*.C
X	CC -c -g $(INCLUDES) $(DEFINES) $*.C
X
X
plumbing: $(OBJS)
X	rm -f plumbing
X	CC -o plumbing $(OBJS) $(LIBX)
END_OF_FILE
if test 602 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'plumbing.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'plumbing.h'\"
else
echo shar: Extracting \"'plumbing.h'\" \(6554 characters\)
sed "s/^X//" >'plumbing.h' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#define NeedFunctionPrototypes 1
X#include <X11/Xlib.h>
X
X#ifndef NULL
X#define	NULL 0
X#endif NULL
X
X#define SCOREFILE "/wsl/share/lib/plumbing/scores"
X
const int MAXSCREENS = 1;
X
const int VSQUARES = 7;
const int HSQUARES = 10;
X
const int QUEUELENGTH = 5;
X
const int BESTSSIZE = 50;
const int MINSSIZE = 15;
X
const int INTBORDERWIDTH = 20;	// Size of border between queue and playing
const int SCOREHEIGHT = 50;	// Height of score area at bottom
X
class ScrnRec;
typedef class ScrnRec *Scrn;
X
const int MAXPIECES = 20;	// Maximum number of kinds of pieces to alloc
X				// space for.
X
X
X
enum Direction {Up = 0,
X		Down = 3,
X		Left = 1,
X		Right = 2,
X		BadDir = -1};
X
enum Mode {ModePlaying, ModePaused, ModeEndOfLevel, ModeEndOfGame,
X	   ModeGameOver};
X
X
typedef void (*PieceRecFunc)(Scrn, Display *, Pixmap, int ssize, GC foregc);
class PieceRec {
X    Direction out[4];		// What direction to go out given going
X				// in this dir.
X    int id;			// Unique numerical number of this piece type.
X    PieceRecFunc func;
X  public:
X    PieceRec(Direction updir, Direction downdir,
X	     Direction leftdir, Direction rightdir, PieceRecFunc painter);
X    void Paint(Scrn, int, int);	// Takes window coords.
X    Direction GetOutDir(Direction indir) {return out[indir];}
X    int GetId() {return id;}
X};
X
typedef class PieceRec *Piece;
X
X
X
X
class BoardRec {
X    friend void BoardInit();
X    friend void DoPaintMe(void *);
X    Piece piece;
X    Bool removable;
X    int bx, by;			// Where this piece of the board is.
X  public:
X    BoardRec() {
X	piece = NULL;
X	removable = True;
X    }
X    void Clear();
X    void SetPiece(Piece);
X    Piece GetPiece() {return piece;}
X    void ButtonDown();
X    void Repaint(Scrn);
X    void Repaint();
X    void ClearRemovable() {
X	removable = False;
X    }
X    Bool GetRemovable() {
X	return removable;
X    }
X};
X
typedef class BoardRec *Board;
X
X
X
class QueueRec {
X    Piece piece[QUEUELENGTH];
X  public:
X    QueueRec();
X    void Repaint(Scrn);
X    void Repaint();
X    Piece Pop();
X};
X
typedef class QueueRec *Queue;
X
X
class ScoreRec {
X    int score;
X    int countdown;
X  public:
X    ScoreRec();
X    void Repaint(Scrn);
X    void Repaint();
X    void SetCountDown(int);
X    int GetCountDown() {return countdown;}
X    void AddScore(int);
X    int GetScore() {return score;}
X    void ClearScore() {score = 0;}
X    void RecordScore();
X};
X
typedef class ScoreRec *Score;
X
X
class HighlightRec;
typedef class HighlightRec *Highlight;
X
class ScrnRec {
X    Display *dpy;
X    Window toplevel;
X    int twidth, theight;
X    int ssize;			// Pixels on a side of a square.
X    int flowwidth;		// How many pixels wide the flow is; figured
X				// from ssize.
X    Highlight highlight;
X    Pixmap piececache[MAXPIECES];
X    GC copygc, backgc, foregc;
X  public:
X    ScrnRec(Display *);
X    void RefigureSizes();
X    int GetFlowWidth() {return flowwidth;}
X    int GetHighlightColor();
X    int GetForegroundColor();
X    int GetBackgroundColor();
X    GC GetBackgroundGC() {return backgc;}
X    GC GetForegroundGC() {return foregc;}
X    GC GetCopyGC() {return copygc;}
X    GC GetFlowGC() {return foregc;}
X    void HandleEvent(XEvent *);
X    Display *GetDpy() {return dpy;}
X    Window GetWindow() {return toplevel;}
X    int GetWidth() {return twidth;}
X    int GetSSize() {return ssize;}
X    Pixmap GetPieceCache(Piece);
X    void SetPieceCache(Piece, Pixmap);
X    int GetBoardX();
X    int GetBoardY();
X    int GetScoreX();
X    int GetScoreY();
X    int GetQueueX();
X    int GetQueueY();
X};
X
X
extern long random();
static inline int Random(int i) {
X    return random() % i;
X}
static inline int Min(int x, int y) {
X    return (x < y) ? x : y;
X}
static inline int Max(int x, int y) {
X    return (x > y) ? x : y;
X}
static inline Direction OppositeDirection(Direction d) {
X    return 3 - d;
X}
X
X
X
extern void Punt(char *);
X
X
extern void TimerAddTimeout(int msec, void (*func)(void *), void *closure);
extern struct timeval *TimerGetInterval();
extern void TimerHandleTimeout();
extern void TimerClearAll();
extern void TimerPause();
extern void TimerContinue();
extern void TimerSleep(int msec);
extern void TimerInit();
X
extern int LevelCountDown();
extern int LevelTimePerPiece();
extern int LevelReplaceDelay();
extern int LevelFlowScore();
extern int LevelExtraScore();
extern int LevelReplaceScore();
extern int LevelCrossOverScore();
extern int LevelNumToGet();
X
extern void FlowRepaint();
extern void FlowRefigureDeltas();
extern void FlowStart();
extern void FlowFast();
X
extern void InitLevel();
extern void InitializeGame();
X
extern void ScoreInit();
extern void ScoreGetHighScores(char *buf[10], int *);
X
extern void GameOver();
X
extern void BoardInit();
X
extern void PieceInit();
X
extern void QueueInit();
X
X#ifdef MAIN
X#define global
X#else
X#define global extern
X#endif
X
global BoardRec board[HSQUARES][VSQUARES];
X
global char *progname;
X
global Scrn screen[MAXSCREENS];
X
global int numscreens;
X
global Score score;
X
global Queue queue;
X
global int startx, starty;
X
global Direction startdir;
X
global int level;
X
global Piece PieceStart[4];
X
global Piece piecelist[MAXPIECES];
X
global Piece PieceNone, PieceHBar, PieceCross, PieceVBar, PieceUL, PieceUR;
global Piece PieceDL, PieceDR;
X
global Mode mode;
X
global Bool fastflow;
X
global int numtoget;
X
global int prevscore;
END_OF_FILE
if test 6554 -ne `wc -c <'plumbing.h'`; then
    echo shar: \"'plumbing.h'\" unpacked with wrong size!
fi
# end of 'plumbing.h'
fi
if test -f 'board.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'board.C'\"
else
echo shar: Extracting \"'board.C'\" \(2719 characters\)
sed "s/^X//" >'board.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
X
static Piece newpiece = NULL;
static Board newboard;
X
X
void BoardRec::SetPiece(Piece p) {
X    piece = p;
X    Repaint();
X}
X
void BoardRec::Clear() {
X    removable = True;
X    newpiece = NULL;
X    SetPiece(PieceNone);
X}
X
X
void BoardRec::Repaint(Scrn scrn) {
X    int ssize = scrn->GetSSize();
X    piece->Paint(scrn, scrn->GetBoardX() + bx * ssize,
X		 scrn->GetBoardY() + by * ssize);
X}
X
void BoardRec::Repaint() {
X    int i;
X    for (i=0 ; i<numscreens ; i++) Repaint(screen[i]);
X}
X
X
static void DoReplace(void *) {
X    if (newpiece) {
X	newboard->SetPiece(newpiece);
X	newpiece = NULL;
X    }
X}
X
static void DoPaintMe(void *closure) {
X    Piece piece = (Piece) closure;
X    if (newpiece) {
X	newboard->SetPiece(piece);
X	newboard->piece = PieceNone;
X	TimerAddTimeout(200, DoPaintMe, closure);
X    }
X}
X    
X
void BoardRec::ButtonDown() {
X    if (!removable || newpiece || fastflow) return;
X    if (piece == PieceNone) {
X	piece = queue->Pop();
X	Repaint();
X    } else {
X	newpiece = queue->Pop();
X	newboard = this;
X	TimerAddTimeout(LevelReplaceDelay(), DoReplace, NULL);
X	TimerAddTimeout(100, DoPaintMe, (void *) newpiece);
X	TimerAddTimeout(200, DoPaintMe, (void *) piece);
X	piece = PieceNone;
X	score->AddScore(LevelReplaceScore());
X    }
X}
X
X
void BoardInit() {
X    int x, y;
X    for (x=0 ; x<HSQUARES ; x++) {
X	for (y=0 ; y<VSQUARES ; y++) {
X	    board[x][y].bx = x;
X	    board[x][y].by = y;
X	}
X    }
X}
END_OF_FILE
if test 2719 -ne `wc -c <'board.C'`; then
    echo shar: \"'board.C'\" unpacked with wrong size!
fi
# end of 'board.C'
fi
if test -f 'flow.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flow.C'\"
else
echo shar: Extracting \"'flow.C'\" \(5102 characters\)
sed "s/^X//" >'flow.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
static int fx, fy;
static Direction indir, outdir;
static int perc;		// Percentage through * 100.
static int deltaperc;
static int deltatime;
X
static int DirX[4] = {0, -1, 1, 0};
static int DirY[4] = {-1, 0, 0, 1};
X
static void Paint(int fx, int fy, Direction indir, Direction outdir,
X		  int perc) {
X    Scrn scrn;
X    Display *dpy;
X    Window window;
X    int i, ssize, flowwidth, lssize, hssize, numpix, ipix, opix, x0, y0;
X    GC gc;
X    for (i=0 ; i<numscreens ; i++) {
X	scrn = screen[i];
X	dpy = scrn->GetDpy();
X	window = scrn->GetWindow();
X	ssize = scrn->GetSSize();
X	flowwidth = scrn->GetFlowWidth();
X	x0 = scrn->GetBoardX() + ssize * fx;
X	y0 = scrn->GetBoardY() + ssize * fy;
X	lssize = (ssize - flowwidth) / 2;
X	hssize = (ssize + flowwidth) / 2;
X	gc = scrn->GetFlowGC();
X	numpix = perc * ssize / 10000;
X	if (numpix <= 0) continue;
X	ipix = Min(numpix, hssize);
X	if (fx != startx || fy != starty) {
X	    switch (indir) {
X	    case Up:
X		XFillRectangle(dpy, window, gc, x0 + lssize, y0 + 0,
X			       flowwidth, ipix);
X		break;
X	    case Down:
X		XFillRectangle(dpy, window, gc, x0 + lssize, y0 + ssize - ipix,
X			       flowwidth, ipix);
X		break;
X	    case Left:
X		XFillRectangle(dpy, window, gc, x0 + 0, y0 + lssize,
X			       ipix, flowwidth);
X		break;
X	    case Right:
X		XFillRectangle(dpy, window, gc, x0 + ssize - ipix, y0 + lssize,
X			       ipix, flowwidth);
X		break;
X	    case BadDir:
X		Punt("Bad in direction in Paint!");
X	    }
X	}
X	opix = numpix - ipix;
X	if (opix <= 0) continue;
X	switch(outdir) {
X	  case Up:
X	    XFillRectangle(dpy, window, gc, x0 + lssize, y0 + lssize - opix,
X			   flowwidth, opix);
X	    break;
X	  case Down:
X	    XFillRectangle(dpy, window, gc, x0 + lssize, y0 + hssize,
X			   flowwidth, opix);
X	    break;
X	  case Left:
X	    XFillRectangle(dpy, window, gc, x0 + lssize - opix, y0 + lssize,
X			   opix, flowwidth);
X	    break;
X	  case Right:
X	    XFillRectangle(dpy, window, gc, x0 + hssize, y0 + lssize,
X			   opix, flowwidth);
X	    break;
X	  case BadDir:
X	    Punt("Bad out direction in Paint!");
X	}
X    }
X}
X
X
static void TripFlow(void *) {
X    TimerAddTimeout(deltatime, TripFlow, NULL);
X    perc += deltaperc;
X    if (perc >= 10000) {
X	Paint(fx, fy, indir, outdir, 10000);
X	perc -= 10000;
X	fx += DirX[outdir];
X	fy += DirY[outdir];
X	if (fx < 0 || fx >= HSQUARES || fy < 0 || fy >= VSQUARES) {
X	    GameOver();
X	    return;
X	}
X	indir = OppositeDirection(outdir);
X	outdir = board[fx][fy].GetPiece()->GetOutDir(indir);
X	if (outdir == BadDir) {
X	    GameOver();
X	    return;
X	}
X	if (numtoget > 0) numtoget--;
X	score->AddScore(LevelFlowScore());
X	if (!board[fx][fy].GetRemovable()) {
X	    score->AddScore(LevelCrossOverScore());
X	}
X	board[fx][fy].ClearRemovable();
X    }
X    Paint(fx, fy, indir, outdir, perc);
X}
X
X
void FlowRefigureDeltas() {
X    int i;
X    int ssize = MINSSIZE ;
X    for (i=0 ; i<numscreens ; i++) {
X	if (ssize < screen[i]->GetSSize())
X	    ssize = screen[i]->GetSSize();
X    }
X    deltaperc = 10000 / ssize;
X    deltatime = (fastflow ? 250 : LevelTimePerPiece()) / ssize;
X}
X
X
X
void FlowRepaint() {
X    int x = startx;
X    int y = starty;
X    Direction in = startdir;
X    Direction out = startdir;
X    while (x != fx || y != fy || in != indir || out != outdir) {
X	Paint(x, y, in, out, 10000);
X	x += DirX[out];
X	y += DirY[out];
X	if (x < 0 || y < 0 || x >= HSQUARES || y >= VSQUARES) return;
X	in = OppositeDirection(out);
X	out = board[x][y].GetPiece()->GetOutDir(in);
X    }
X    Paint(fx, fy, indir, outdir, perc);
X}
X
X
X
void FlowFast() {
X    if (score->GetCountDown() > 0) {
X	score->SetCountDown(0);
X    }
X    fastflow = True;
X    FlowRefigureDeltas();
X}
X
X
void FlowStart() {
X    fx = startx;
X    fy = starty;
X    indir = outdir = startdir;
X    perc = 5000;
X    fastflow = False;
X    FlowRefigureDeltas();
X    TripFlow(NULL);
X}
END_OF_FILE
if test 5102 -ne `wc -c <'flow.C'`; then
    echo shar: \"'flow.C'\" unpacked with wrong size!
fi
# end of 'flow.C'
fi
if test -f 'init.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'init.C'\"
else
echo shar: Extracting \"'init.C'\" \(2612 characters\)
sed "s/^X//" >'init.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
X
void InitLevel() {
X    int x, y;
X    fastflow = False;
X    numtoget = LevelNumToGet();
X    for (x=0 ; x<HSQUARES ; x++) {
X	for (y=0 ; y<VSQUARES ; y++) {
X	    board[x][y].Clear();
X	}
X    }
X    startx = Random(HSQUARES - 2) + 1;
X    starty = Random(VSQUARES - 2) + 1;
X    startdir = Random(4);
X    board[startx][starty].SetPiece(PieceStart[startdir]);
X    board[startx][starty].ClearRemovable();
X    score->SetCountDown(LevelCountDown());
X}
X
X
void InitializeGame() {
X    level = 1;
X    score->ClearScore();
X    InitLevel();
X}
X
X
void GameOver() {
X    int i, x, y;
X    Display *dpy;
X    XEvent event;
X    TimerClearAll();
X    for (y=0 ; y<VSQUARES ; y++) {
X	for (x=0 ; x<HSQUARES ; x++) {
X	    if (board[x][y].GetPiece() != PieceNone &&
X		  board[x][y].GetRemovable()) {
X		board[x][y].SetPiece(PieceNone);
X		score->AddScore(LevelExtraScore());
X		for (i=0 ; i<numscreens ; i++)
X		    XFlush(screen[i]->GetDpy());
X		TimerSleep(200);
X	    }
X	}
X    }
X    mode = (numtoget > 0) ? ModeGameOver : ModeEndOfLevel;
X    if (mode == ModeGameOver) {
X	prevscore = score->GetScore();
X	score->RecordScore();
X    }
X    for (i=0 ; i<numscreens ; i++) {
X	dpy = screen[i]->GetDpy();
X	XClearArea(dpy, screen[i]->GetWindow(), 0, 0, 1, 1, True);
X	while (XCheckMaskEvent(dpy, ButtonPressMask, &event)) ;
X    }
X}
END_OF_FILE
if test 2612 -ne `wc -c <'init.C'`; then
    echo shar: \"'init.C'\" unpacked with wrong size!
fi
# end of 'init.C'
fi
if test -f 'level.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'level.C'\"
else
echo shar: Extracting \"'level.C'\" \(1716 characters\)
sed "s/^X//" >'level.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
int LevelCountDown() {
X    return Max(3, 20 - level);
X}
X
int LevelTimePerPiece() {
X    return Max(500, 5000 - 400 * level);
X}
X
int LevelReplaceDelay() {
X    return 1000;
X}
X
int LevelFlowScore() {
X    return 100;
X}
X
int LevelExtraScore() {
X    return -100;
X}
X
int LevelReplaceScore() {
X    return -100;
X}
X
int LevelCrossOverScore() {
X    return 500;
X}
X
int LevelNumToGet() {
X    return 10;
X}
END_OF_FILE
if test 1716 -ne `wc -c <'level.C'`; then
    echo shar: \"'level.C'\" unpacked with wrong size!
fi
# end of 'level.C'
fi
if test -f 'main.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.C'\"
else
echo shar: Extracting \"'main.C'\" \(2838 characters\)
sed "s/^X//" >'main.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#define MAIN
X
X#include <stream.h>
X#include "plumbing.h"
X#include <sys/time.h>
X#include <string.h>
X
extern int select(int, int *, int *, int *, struct timeval *);
X
static void Usage() {
X    cout << "Usage: " << progname << " [-d display]\n";
X    exit(1);
X}
X
X
X
void Punt(char *str) {
X    cout << progname << ": " << str << "\n";
X    exit(1);
X}
X
main(int argc, char **argv) {
X    char *displayname = NULL;
X    Bool sync = False;
X    int i;
X
X    progname = argv[0];
X
X    for (i=1 ; i<argc ; i++) {
X	if (i < argc - 1 && (strcmp(argv[i], "-d") == 0 ||
X			     strcmp(argv[i], "-display") == 0)) {
X	    displayname = argv[++i];
X	} else if (strcmp(argv[i], "-sync") == 0) {
X	    sync = True;
X	} else {
X	    Usage();
X	}
X    }
X
X    TimerInit();
X
X    numscreens = 0;
X    Display *dpy = XOpenDisplay(displayname);
X    if (!dpy) {
X	Punt("Can't open display.");
X    }
X    XSynchronize(dpy, sync);
X
X    screen[0] = new ScrnRec(dpy);
X    numscreens = 1;
X
X    BoardInit();
X    PieceInit();
X    QueueInit();
X    ScoreInit();
X    prevscore = -1;
X
X    queue = new QueueRec();
X    score = new ScoreRec();
X
X    mode = ModeEndOfGame;
X	
X    struct timeval *timerec;
X    XEvent event;
X    int readmask = 0;
X
X    for (;;) {
X	for (i=0 ; i<numscreens ; i++) {
X	    while (XPending(screen[i]->GetDpy())) {
X		XNextEvent(dpy, &event);
X		screen[i]->HandleEvent(&event);
X	    }
X	    readmask |= (1 << ConnectionNumber(screen[i]->GetDpy()));
X	}
X	timerec = TimerGetInterval();
X	if (select(32, &readmask, NULL, NULL, timerec) == 0) {
X	    TimerHandleTimeout();
X	}
X    }
X}
END_OF_FILE
if test 2838 -ne `wc -c <'main.C'`; then
    echo shar: \"'main.C'\" unpacked with wrong size!
fi
# end of 'main.C'
fi
if test -f 'piece.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'piece.C'\"
else
echo shar: Extracting \"'piece.C'\" \(6992 characters\)
sed "s/^X//" >'piece.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
static int numpieces = 0;
X
PieceRec::PieceRec(Direction updir, Direction downdir, Direction leftdir,
X		   Direction rightdir, PieceRecFunc painter) {
X    out[Up] = updir;
X    out[Down] = downdir;
X    out[Left] = leftdir;
X    out[Right] = rightdir;
X    func = painter;
X    id = numpieces++;
X    piecelist[id] = this;
X}
X
void PieceRec::Paint(Scrn scrn, int x, int y) {
X    int ssize = scrn->GetSSize();
X    Display *dpy = scrn->GetDpy();
X    Window window = scrn->GetWindow();
X    Pixmap pixmap = scrn->GetPieceCache(this);
X    if (!pixmap) {
X	pixmap = XCreatePixmap(dpy, window, ssize, ssize,
X			       DefaultDepth(dpy, DefaultScreen(dpy)));
X	XFillRectangle(dpy, pixmap, scrn->GetBackgroundGC(), 0, 0,
X		       ssize, ssize);
X	(*func)(scrn, dpy, pixmap, ssize, scrn->GetForegroundGC());
X	scrn->SetPieceCache(this, pixmap);
X    }
X    XCopyArea(dpy, pixmap, window, scrn->GetCopyGC(),
X	      0, 0, ssize, ssize, x, y);
X}
X
X
inline int L(int ssize) {return ssize / 3;}
inline int H(int ssize) {return 2 * ssize / 3;}
X
static void PaintNone(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, 0, ssize, ssize);
X    XDrawLine(dpy, pixmap, gc, 0, ssize, ssize, 0);
X}
X
static void PaintHBar(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, L(ssize), ssize, L(ssize));
X    XDrawLine(dpy, pixmap, gc, 0, H(ssize), ssize, H(ssize));
X}
X
static void PaintCross(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, L(ssize), L(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), L(ssize), L(ssize), 0);
X    XDrawLine(dpy, pixmap, gc, H(ssize), 0, H(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), L(ssize), ssize, L(ssize));
X    XDrawLine(dpy, pixmap, gc, 0, H(ssize), L(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), H(ssize), L(ssize), ssize);
X    XDrawLine(dpy, pixmap, gc, H(ssize), ssize, H(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), H(ssize), ssize, H(ssize));
X}
X
static void PaintVBar(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, L(ssize), 0, L(ssize), ssize);
X    XDrawLine(dpy, pixmap, gc, H(ssize), 0, H(ssize), ssize);
X}
X
static void PaintUL(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, L(ssize), L(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), L(ssize), L(ssize), 0);
X    XDrawLine(dpy, pixmap, gc, 0, H(ssize), H(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), H(ssize), H(ssize), 0);
X}
X
static void PaintUR(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, L(ssize), 0, L(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), H(ssize), ssize, H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), 0, H(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), L(ssize), ssize, L(ssize));
X}
X
static void PaintDL(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, L(ssize), H(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), L(ssize), H(ssize), ssize);
X    XDrawLine(dpy, pixmap, gc, 0, H(ssize), L(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), H(ssize), L(ssize), ssize);
X}
X
static void PaintDR(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, L(ssize), ssize, L(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), L(ssize), ssize, L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), ssize, H(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), H(ssize), ssize, H(ssize));
X}
X
static void PaintSUp(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, L(ssize), 0, L(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), H(ssize), H(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), H(ssize), H(ssize), 0);
X}
X
static void PaintSDown(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, L(ssize), ssize, L(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), L(ssize), H(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), L(ssize), H(ssize), ssize);
X}
X
static void PaintSLeft(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, 0, L(ssize), H(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), L(ssize), H(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, H(ssize), H(ssize), 0, H(ssize));
X}
X
static void PaintSRight(Scrn, Display *dpy, Pixmap pixmap, int ssize, GC gc) {
X    XDrawLine(dpy, pixmap, gc, ssize, L(ssize), L(ssize), L(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), L(ssize), L(ssize), H(ssize));
X    XDrawLine(dpy, pixmap, gc, L(ssize), H(ssize), ssize, H(ssize));
X}
X    
X
void PieceInit() {
X    PieceNone = new PieceRec(BadDir, BadDir, BadDir, BadDir, PaintNone);
X    PieceHBar = new PieceRec(BadDir, BadDir, Right, Left, PaintHBar);
X    PieceVBar = new PieceRec(Down, Up, BadDir, BadDir, PaintVBar);
X    PieceCross = new PieceRec(Down, Up, Right, Left, PaintCross);
X    PieceUL = new PieceRec(Left, BadDir, Up, BadDir, PaintUL);
X    PieceUR = new PieceRec(Right, BadDir, BadDir, Up, PaintUR);
X    PieceDL = new PieceRec(BadDir, Left, Down, BadDir, PaintDL);
X    PieceDR = new PieceRec(BadDir, Right, BadDir, Down, PaintDR);
X    PieceStart[Up] = new PieceRec(BadDir, BadDir, BadDir, BadDir,
X				  PaintSUp);
X    PieceStart[Down] = new PieceRec(BadDir, BadDir, BadDir, BadDir,
X				    PaintSDown);
X    PieceStart[Left] = new PieceRec(BadDir, BadDir, BadDir, BadDir,
X				    PaintSLeft);
X    PieceStart[Right] = new PieceRec(BadDir, BadDir, BadDir, BadDir,
X				     PaintSRight);
X}
END_OF_FILE
if test 6992 -ne `wc -c <'piece.C'`; then
    echo shar: \"'piece.C'\" unpacked with wrong size!
fi
# end of 'piece.C'
fi
if test -f 'queue.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'queue.C'\"
else
echo shar: Extracting \"'queue.C'\" \(2436 characters\)
sed "s/^X//" >'queue.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include "plumbing.h"
X
static Piece queuepieces[MAXPIECES];
X
static int numqueuepieces;
X
QueueRec::QueueRec() {
X    int i;
X    for (i=0 ; i<QUEUELENGTH ; i++)
X	piece[i] = queuepieces[Random(numqueuepieces)];
X}
X
void QueueRec::Repaint(Scrn scrn) {
X    int i;
X    int ssize = scrn->GetSSize();
X    int x0 = scrn->GetQueueX();
X    int y0 = scrn->GetQueueY();
X    for (i=0 ; i<QUEUELENGTH ; i++)
X	piece[i]->Paint(scrn, x0, y0 + (QUEUELENGTH - i - 1) * (ssize + 5));
X}
X
void QueueRec::Repaint() {
X    int i;
X    for (i=0 ; i<numscreens ; i++)
X	Repaint(screen[i]);
X}
X
Piece QueueRec::Pop() {
X    int i;
X    Piece result;
X    result = piece[0];
X    for (i=0 ; i<QUEUELENGTH - 1; i++)
X	piece[i] = piece[i+1];
X    piece[i] = queuepieces[Random(numqueuepieces)];
X    Repaint();
X    return result;
X}
X
X
void QueueInit() {
X    queuepieces[numqueuepieces++] = PieceHBar;
X    queuepieces[numqueuepieces++] = PieceVBar;
X    queuepieces[numqueuepieces++] = PieceCross;
X    queuepieces[numqueuepieces++] = PieceUL;
X    queuepieces[numqueuepieces++] = PieceUR;
X    queuepieces[numqueuepieces++] = PieceDL;
X    queuepieces[numqueuepieces++] = PieceDR;
X}
END_OF_FILE
if test 2436 -ne `wc -c <'queue.C'`; then
    echo shar: \"'queue.C'\" unpacked with wrong size!
fi
# end of 'queue.C'
fi
if test -f 'score.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'score.C'\"
else
echo shar: Extracting \"'score.C'\" \(6329 characters\)
sed "s/^X//" >'score.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include <string.h>
X#include <stdio.h>
X#include "pwd.h"
X#include <time.h>
X#include <malloc.h>
X#include "plumbing.h"
X
extern int geteuid();
X
extern void qsort(char *, int, int, int (*)(void *, void *));
X
static int userid;
static char username[100];
X
X
ScoreRec::ScoreRec() {
X    score = 0;
X    countdown = -1;
X}
X
void ScoreRec::Repaint(Scrn scrn) {
X    Display *dpy = scrn->GetDpy();
X    Window window = scrn->GetWindow();
X    int x0 = scrn->GetScoreX();
X    int y0 = scrn->GetScoreY();
X    char buf[500];
X    if (countdown < 0) {
X	sprintf(buf, "Score: %d    Level: %d    Need: %d",
X		score, level, numtoget);
X    } else {
X	sprintf(buf,
X		"Score: %d    Level: %d    Need: %d     Flow in %d second%s!",
X		score, level, numtoget, countdown,
X		countdown == 1 ? "" : "s");
X    }
X    XFillRectangle(dpy, window, scrn->GetBackgroundGC(), x0, y0,
X		   scrn->GetWidth(), SCOREHEIGHT);
X    XDrawString(dpy, window, scrn->GetForegroundGC(),
X		x0, y0 + SCOREHEIGHT / 2, buf, strlen(buf));
X}
X
void ScoreRec::Repaint() {
X    int i;
X    for (i=0 ; i<numscreens ; i++)
X	Repaint(screen[i]);
X}
X
X
X
static void TripCount(void *closure) {
X    Score score = (Score) closure;
X    score->SetCountDown(score->GetCountDown() - 1);
X}
X
void ScoreRec::SetCountDown(int c) {
X    countdown = c;
X    if (c >= 0) {
X	TimerAddTimeout(1000, TripCount, (void *) this);
X	if (c == 0) FlowStart();
X    }
X    Repaint();
X}
X
X
void ScoreRec::AddScore(int d) {
X    score += d;
X    if (fastflow && d > 0) score += d;
X    if (score < 0) score = 0;
X    Repaint();
X}
X
X
void ScoreRec::RecordScore() {
X    FILE *fid = fopen(SCOREFILE, "a");
X    if (!fid) return;
X    long t = time(NULL);
X    char *tstr = ctime(&t);
X    char *ptr = strchr(tstr, '\n');
X    if (ptr) *ptr = '\0';
X    fprintf(fid, "%s;%d;%d;%d;%s\n", tstr, score, level, userid, username);
X    fclose(fid);
X}
X
X
X
char *NameFromUid(int uid) {
X    static char result[100];
X    char *ptr;
X    extern passwd *getpwuid (int); // Should be in pwd.h, but isn't...
X    struct passwd *password = getpwuid(uid);
X    if (password && password->pw_gecos) {
X	strcpy(result, password->pw_gecos);
X	ptr = strchr(result, ',');
X	if (ptr) *ptr = 0;
X	return result;
X    } else {
X	sprintf(result, "<User %d>", uid);
X	return result;
X    }
X}
X    
X
X
void ScoreInit() {
X    extern void srandom(int);
X    userid = geteuid();
X    strcpy(username, NameFromUid(userid));
X    
X    srandom(time(NULL));	// Silly place to init the random number,
X				// generator, but what the hack...
X}
X
X
struct ScoreInfo {
X    int uid;
X    int score;
X    int level;
X    int numgames;
X};
X
X
static int Comparer(void *a, void *b) {
X    ScoreInfo *p1 = (ScoreInfo *) a;
X    ScoreInfo *p2 = (ScoreInfo *) b;
X    return p2->score - p1->score;
X}
X
X
void ScoreGetHighScores(char *buf[10], int *numgames) {
X    static char result[10][200];
X    char str[500], *ptr;
X    ScoreInfo *list;
X    ScoreInfo mine[10];
X    int nummine = 0;
X    int num = 0;
X    int max = 100;
X    int i, j, low, high, uid, score, level;
X    Bool found;
X    list = (ScoreInfo *) malloc(max * sizeof(ScoreInfo));
X    FILE *fid = fopen(SCOREFILE, "r");
X    *numgames = 0;
X    if (!fid) {
X	buf[0] = NULL;
X	return;
X    }
X    while (fgets(str, 500, fid)) {
X	ptr = strchr(str, ';');
X	if (!ptr) continue;
X	score = atoi(ptr + 1);
X	ptr = strchr(ptr + 1, ';');
X	if (!ptr) continue;
X	level = atoi(ptr + 1);
X	ptr = strchr(ptr + 1, ';');
X	if (!ptr) continue;
X	uid = atoi(ptr + 1);
X	if (uid == userid) {
X	    (*numgames)++;
X	    if (nummine > 0 && score >= mine[nummine - 1].score) {
X		for (i=0 ; i<nummine ; i++) {
X		    if (score >= mine[i].score) {
X			if (nummine < 10) nummine++;
X			for (j=nummine - 1 ; j>i ; j--) {
X			    mine[j] = mine[j-1];
X			}
X			mine[i].score = score;
X			mine[i].level = level;
X			break;
X		    }
X		}
X	    } else if (nummine < 10) {
X		mine[nummine].score = score;
X		mine[nummine].level = level;
X		nummine++;
X	    }
X	}
X	low = 0;
X	high = num;
X	found = False;
X	while (low < high) {
X	    i = (low + high) / 2;
X	    if (list[i].uid == uid) {
X		found = True;
X		break;
X	    } else if (list[i].uid > uid) high = i;
X	    else low = i + 1;
X	}
X	if (found) {
X	    list[i].numgames++;
X	    if (score > list[i].score) {
X		list[i].score = score;
X		list[i].level = level;
X	    }
X	} else {
X	    num++;
X	    if (num >= max) {
X		max += 100;
X		list = (ScoreInfo *) realloc((char *) list,
X					     max * sizeof(ScoreInfo));
X	    }
X	    for (i=num-1 ; i>low ; i--) {
X		list[i] = list[i-1];
X	    }
X	    list[low].uid = uid;
X	    list[low].score = score;
X	    list[low].level = level;
X	    list[low].numgames = 1;
X	}
X    }
X    fclose(fid);
X    qsort((char *) list, num, sizeof(ScoreInfo), Comparer);
X    for (i=0 ; i<10 ; i++) {
X	if (i < nummine) {
X	    sprintf(result[i], "%7d %3d    ", mine[i].score, mine[i].level);
X	} else {
X	    strcpy(result[i], "               ");
X	}
X	if (i < num) {
X	    sprintf(str, "%7d %3d %5d           %s",
X		    list[i].score, list[i].level,
X		    list[i].numgames, NameFromUid(list[i].uid));
X	    strcat(result[i], str);
X	}
X	buf[i] = result[i];
X    }
X    free((char *) list);
X}
END_OF_FILE
if test 6329 -ne `wc -c <'score.C'`; then
    echo shar: \"'score.C'\" unpacked with wrong size!
fi
# end of 'score.C'
fi
if test -f 'screen.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'screen.C'\"
else
echo shar: Extracting \"'screen.C'\" \(10283 characters\)
sed "s/^X//" >'screen.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include <stdio.h>
X#include <string.h>
X#include "plumbing.h"
X#include <X11/Xutil.h>		/* For XLookupString() */
X
extern void exit(int);
X
class HighlightRec {
X    Window window[4];
X    Scrn scrn;
X    int x, y;
X  public:
X    HighlightRec(Scrn);
X    void NewSSize();
X    void Hide();
X    void Move(int, int);
X};
X
HighlightRec::HighlightRec(Scrn s) {
X    int i;
X    scrn = s;
X    Display *dpy = scrn->GetDpy();
X    int valuemask = CWBackPixel;
X    XSetWindowAttributes attributes;
X    attributes.background_pixel = scrn->GetHighlightColor();
X    for (i=0 ; i<4 ; i++) {
X	window[i] = XCreateWindow(dpy, scrn->GetWindow(), -1000, -1000,
X				  1, 1, 0, (int) CopyFromParent,
X				  InputOutput, CopyFromParent,
X				  valuemask, &attributes);
X	XMapWindow(dpy, window[i]);
X    }
X    NewSSize();
X}
X
X
void HighlightRec::NewSSize() {
X    Display *dpy = scrn->GetDpy();
X    int ssize = scrn->GetSSize();
X    XResizeWindow(dpy, window[Up], ssize, 1);
X    XResizeWindow(dpy, window[Down], ssize, 1);
X    XResizeWindow(dpy, window[Left], 1, ssize);
X    XResizeWindow(dpy, window[Right], 1, ssize);
X    x = 1;
X    Hide();
X}
X
X
void HighlightRec::Move(int newx, int newy) {
X    if (x != newx || y != newy) {
X	int ssize = scrn->GetSSize();
X	int x0 = scrn->GetBoardX();
X	int y0 = scrn->GetBoardY();
X	Display *dpy = scrn->GetDpy();
X	x = newx;
X	y = newy;
X	XMoveWindow(dpy, window[Up], x0 + x * ssize, y0 + y * ssize);
X	XMoveWindow(dpy, window[Left], x0 + x * ssize, y0 + y * ssize);
X	XMoveWindow(dpy, window[Right], x0 + x * ssize + ssize,y0 + y * ssize);
X	XMoveWindow(dpy, window[Down], x0 + x * ssize, y0 + y * ssize + ssize);
X    }
X}
X
void HighlightRec::Hide() {
X    Move(-100, -100);
X}
X	
X
ScrnRec::ScrnRec(Display *d) {
X    int i;
X    dpy = d;
X    ssize = BESTSSIZE;
X    for (i=0 ; i<MAXPIECES ; i++) piececache[i] = NULL;
X    twidth = ssize * HSQUARES + INTBORDERWIDTH + ssize;
X    theight = ssize * VSQUARES + INTBORDERWIDTH + SCOREHEIGHT;
X    long valuemask = CWEventMask | CWBitGravity | CWBackingStore | CWBackPixel;
X    XSetWindowAttributes attributes;
X    attributes.event_mask = (ExposureMask | ButtonPressMask | KeyPressMask |
X			     PointerMotionMask | StructureNotifyMask);
X    attributes.bit_gravity = ForgetGravity;
X    attributes.backing_store = WhenMapped;
X    attributes.background_pixel = GetBackgroundColor();
X    toplevel = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0,
X			     twidth, theight, 1, (int) CopyFromParent,
X			     InputOutput, CopyFromParent,
X			     valuemask, &attributes);
X    XSetIconName(dpy, toplevel, "Plumbing");
X    XStoreName(dpy, toplevel, "Plumbing");
X    XMapWindow(dpy, toplevel);
X    XGCValues values;
X    values.foreground = GetForegroundColor();
X    values.background = GetBackgroundColor();
X    foregc = XCreateGC(dpy, toplevel, GCForeground | GCBackground, &values);
X    copygc = foregc;
X    values.foreground = GetBackgroundColor();
X    backgc = XCreateGC(dpy, toplevel, GCForeground, &values);
X    highlight = new HighlightRec(this);
X    RefigureSizes();
X}
X
X
void ScrnRec::RefigureSizes() {
X    int h, v, i;
X    h = (twidth - INTBORDERWIDTH) / (HSQUARES + 1);
X    v = (theight - INTBORDERWIDTH - SCOREHEIGHT) / VSQUARES;
X    ssize = Max(Min(h, v), MINSSIZE);
X    ssize -= (ssize % 1);	// Make ssize always be even.
X    for (i=0 ; i<MAXPIECES ; i++) {
X	if (piececache[i]) {
X	    XFreePixmap(dpy, piececache[i]);
X	    piececache[i] = NULL;
X	}
X    }
X    flowwidth = (ssize / 3) - 4;
X    flowwidth += (flowwidth % 1); // Also always even, and not zero.
X    FlowRefigureDeltas();
X    highlight->NewSSize();
X}
X
Pixmap ScrnRec::GetPieceCache(Piece p) {
X    return piececache[p->GetId()];
X}
X
void ScrnRec::SetPieceCache(Piece p, Pixmap pixmap) {
X    int id = p->GetId();
X    if (piececache[id]) Punt("Duplicate call to ScrnRec::SetPieceCache!");
X    piececache[id] = pixmap;
X}
X
int ScrnRec::GetHighlightColor() {
X    return BlackPixel(dpy, DefaultScreen(dpy));
X}
X
int ScrnRec::GetForegroundColor() {
X    return BlackPixel(dpy, DefaultScreen(dpy));
X}
X
int ScrnRec::GetBackgroundColor() {
X    return WhitePixel(dpy, DefaultScreen(dpy));
X}
X
void ScrnRec::HandleEvent(XEvent *event) {
X    int i, x, y, width, height, firstx, firsty, lastx, lasty;
X    switch (event->type) {
X      case Expose:
X	if (mode != ModePlaying)
X	    highlight->Hide();
X	if (mode == ModeEndOfGame) {
X	    const int lineheight = 14; // %%% Blech!
X	    char *scores[10], buf[100];
X	    int numgames;
X	    static char *msg[] = {
X		"P L U M B I N G    -   by Terry Weissman",
X		"",
X		"(With apologies to Lucasfilm, the creators of Pipe Dreams)",
X		"",
X		"Click to start",
X		"Q = Quit",
X		"P = Pause",
X		"",
X		"F or right button to make flow go fast",
X		"",
X		"           High Scores",
X		"   Personal          System-wide",
X		"  Score Level    Score Level Games played",
X		NULL,
X	    };
X	    XClearWindow(dpy, toplevel);
X	    y = lineheight;
X	    for (i=0 ; msg[i] ; i++) {
X		XDrawString(dpy, toplevel, GetForegroundGC(),
X			    20, y, msg[i], strlen(msg[i]));
X		y += lineheight;
X	    }
X	    XFlush(dpy);
X	    ScoreGetHighScores(scores, &numgames);
X	    for (i=0 ; i<10 && scores[i] ; i++) {
X		XDrawString(dpy, toplevel, GetForegroundGC(),
X			    20, y, scores[i], strlen(scores[i]));
X		y += lineheight;
X	    }
X	    y += lineheight;
X	    if (prevscore >= 0) {
X		sprintf(buf, "Score last game: %d", prevscore);
X		XDrawString(dpy, toplevel, GetForegroundGC(),
X			    20, y, buf, strlen(buf));
X		y += lineheight;
X	    }
X	    sprintf(buf, "You have played %d game%s.",
X		    numgames, (numgames == 1) ? "" : "s");
X	    XDrawString(dpy, toplevel, GetForegroundGC(),
X			20, y, buf, strlen(buf));
X	    y += lineheight;
X	    
X	    break;
X	}
X	if (mode == ModePaused) {
X	    char *msg = " Click to continue ";
X	    XClearWindow(dpy, toplevel);
X	    XDrawString(dpy, toplevel, GetForegroundGC(),
X			     20, theight / 2, msg, strlen(msg));
X	    break;
X	}
X	x = event->xexpose.x;
X	y = event->xexpose.y;
X	width = event->xexpose.width;
X	height = event->xexpose.height;
X	if (x + width > ssize * HSQUARES) queue->Repaint(this);
X	if (y + height > ssize * VSQUARES) score->Repaint(this);
X	firstx = Min(Max(x / ssize, 0), HSQUARES - 1);
X	lastx = Min(Max((x + width + 1) / ssize, 0), HSQUARES - 1);
X	firsty = Min(Max(y / ssize, 0), VSQUARES - 1);
X	lasty = Min(Max((y + height + 1) / ssize, 0), VSQUARES - 1);
X	for (x=firstx ; x<=lastx ; x++) {
X	    for (y=firsty ; y<VSQUARES ; y++) {
X		board[x][y].Repaint(this);
X	    }
X	}
X	if (event->xexpose.count == 0) {
X	    if (score->GetCountDown() < 0)
X		FlowRepaint();
X	    if (mode == ModeEndOfLevel) {
X		char *msg = " Click to start next level ";
X		XDrawImageString(dpy, toplevel, GetForegroundGC(),
X				 20, theight / 2, msg, strlen(msg));
X	    } else if (mode == ModeGameOver) {
X		char *msg = " G A M E   O V E R ";
X		XDrawImageString(dpy, toplevel, GetForegroundGC(),
X				 20, theight / 2, msg, strlen(msg));
X	    }
X	}
X	break;
X
X      case ConfigureNotify:
X	if (twidth != event->xconfigure.width ||
X	      theight != event->xconfigure.height) {
X	    twidth = event->xconfigure.width;
X	    theight = event->xconfigure.height;
X	    RefigureSizes();
X	}
X	break;
X
X      case MotionNotify:
X	while (XCheckMaskEvent(dpy, PointerMotionMask, event)) ;
X	if (mode != ModePlaying) return;
X	// Fall through.
X      case ButtonPress:
X	if (mode == ModePaused) {
X	    mode = ModePlaying;
X	    XClearArea(dpy, toplevel, 0, 0, 0, 0, True);
X	    TimerContinue();
X	    break;
X	}
X	if (mode == ModeEndOfGame) {
X	    mode = ModePlaying;
X	    XClearArea(dpy, toplevel, 0, 0, 0, 0, True);
X	    InitializeGame();
X	    break;
X	}
X	if (mode == ModeEndOfLevel) {
X	    mode = ModePlaying;
X	    XClearArea(dpy, toplevel, 0, 0, 0, 0, True);
X	    level++;
X	    InitLevel();
X	    break;
X	}
X	if (mode == ModeGameOver) {
X	    mode = ModeEndOfGame;
X	    XClearArea(dpy, toplevel, 0, 0, 0, 0, True);
X	    break;
X	}
X	if (event->xbutton.button == 3) {
X	    FlowFast();
X	}
X	    
X	x = (event->xbutton.x - GetBoardX()) / ssize;
X	y = (event->xbutton.y - GetBoardY()) / ssize;
X	if (x >= 0 && y >= 0 && x < HSQUARES && y < VSQUARES) {
X	    highlight->Move(x, y);
X	    if (event->type == ButtonPress)
X		board[x][y].ButtonDown();
X	} else highlight->Hide();
X	break;
X
X      case KeyPress:
X	{
X	    char buf[100];
X	    int length;
X	    length = XLookupString((XKeyEvent *)event, buf, 100, NULL, NULL);
X	    for (i=0 ; i<length ; i++) {
X		switch(buf[i]) {
X		  case 'q':
X		  case 'Q':
X		    exit(0);
X		    
X		  case 'p':
X		  case 'P':
X		    if (mode == ModePlaying) {
X			mode = ModePaused;
X			TimerPause();
X			XClearArea(dpy, toplevel, 0, 0, 0, 0, True);
X		    }
X		    break;
X		    
X		  case 'f':
X		  case 'F':
X		    if (mode == ModePlaying)
X			FlowFast();
X		}
X	    }
X	    break;
X	}
X    }
X}
X
X
int ScrnRec::GetBoardX() {
X    return 0;
X}
X
int ScrnRec::GetBoardY() {
X    return 0;
X}
X
int ScrnRec::GetScoreX() {
X    return 0;
X}
X
int ScrnRec::GetScoreY() {
X    return VSQUARES * ssize + INTBORDERWIDTH;
X}
X
int ScrnRec::GetQueueX() {
X    return HSQUARES * ssize + INTBORDERWIDTH;
X}
X
int ScrnRec::GetQueueY() {
X    return 0;
X}
END_OF_FILE
if test 10283 -ne `wc -c <'screen.C'`; then
    echo shar: \"'screen.C'\" unpacked with wrong size!
fi
# end of 'screen.C'
fi
if test -f 'timer.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'timer.C'\"
else
echo shar: Extracting \"'timer.C'\" \(3274 characters\)
sed "s/^X//" >'timer.C' <<'END_OF_FILE'
X/*
X * Copyright 1990 Digital Equipment Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior
X * permission.  Digital Equipment Corporation makes no representations
X * about the suitability of this software for any purpose.  It is
X * provided "as is" without express or implied warranty.
X *
X * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
X * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
X * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  Terry Weissman
X *          weissman at wsl.dec.com
X */
X
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/timeb.h>
X
extern void ftime(struct timeb *);
X
extern int select(int, int *, int *, int *, struct timeval *);
X
X#ifndef NULL
X#define	NULL 0
X#endif NULL
X
static int starttime;
static int paused = 0;
static int pausetime;
X
struct InfoRec {
X    int when;
X    void (*func)(void *);
X    void *closure;
X    struct InfoRec *next;
X};
X
typedef struct InfoRec *Info;
X
X
static Info first = NULL;
X
X
static inline int GetCurrentTime() {
X    struct timeb t;
X    ftime(&t);
X    return ((t.time - starttime) * 1000 + t.millitm);
X}
X
X
X
void TimerAddTimeout(int msec, void (*func)(void *), void *closure) {
X    Info temp = new InfoRec();
X    temp->when = msec + GetCurrentTime();
X    temp->func = func;
X    temp->closure = closure;
X
X    Info *t;
X
X    t = &first;
X
X    while (*t && (*t)->when <= temp->when) t = &((*t)->next);
X    temp->next = *t;
X    *t = temp;
X}
X
struct timeval *TimerGetInterval() {
X    if (!first || paused) return NULL;
X    static struct timeval result;
X    int msec = first->when - GetCurrentTime();
X    if (msec < 0) msec = 0;
X    result.tv_sec = msec / 1000;
X    result.tv_usec = (msec % 1000) * 1000;
X    return &result;
X}
X
X
void TimerHandleTimeout() {
X    Info temp;
X    if (first) {
X	temp = first;
X	first = first->next;
X	(*temp->func)(temp->closure);
X	delete temp;
X    }
X}
X
X
void TimerClearAll() {
X    Info temp;
X    while (first) {
X	temp = first;
X	first = first->next;
X	delete temp;
X    }
X}
X
X
void TimerPause() {
X    if (!paused) {
X	paused = 1;
X	pausetime = GetCurrentTime();
X    }
X}
X
void TimerContinue() {
X    paused = 0;
X    pausetime -= GetCurrentTime();
X    Info temp;
X    for (temp = first ; temp ; temp = temp->next) {
X	temp->when += pausetime;
X    }
X}
X
X
void TimerSleep(int msec) {
X    struct timeval t;
X    t.tv_sec = msec / 1000;
X    t.tv_usec = (msec % 1000) * 1000;
X    (void) select(1, NULL, NULL, NULL, &t);
X}
X
X
void TimerInit() {
X    struct timeb t;
X    ftime(&t);
X    starttime = t.time;
X}
END_OF_FILE
if test 3274 -ne `wc -c <'timer.C'`; then
    echo shar: \"'timer.C'\" unpacked with wrong size!
fi
# end of 'timer.C'
fi
echo shar: End of shell archive.
exit 0

dan
-----------------------------------------------------------
		    O'Reilly && Associates
		argv at sun.com / argv at ora.com
	   632 Petaluma Ave, Sebastopol, CA 95472 
     800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
    Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list