[comp.sources.x] v03i091: Dragon -- Game of Mah-Jongg, Part02/10

argv@island.uu.net (Dan Heller) (04/30/89)

Submitted-by: Gary E. Barnes <igor!amber!geb>
Posting-number: Volume 3, Issue 91
Archive-name: dragon/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 2 (of 10)."
# Contents:  board.c.aa dragon.man ic/eight_20x24.ic tile.c
# Wrapped by argv@island on Sun Apr 30 00:17:51 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'board.c.aa' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'board.c.aa'\"
else
echo shar: Extracting \"'board.c.aa'\" \(27384 characters\)
sed "s/^X//" >'board.c.aa' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* board.c - Deals with the Mah-Jongg board.  Setup and execution.
X******************************************************************************/
X
X#include "main.h"
X
X#define BLACKSIDES	1
X
Xextern long random();
Xextern int  srandom();
Xextern long time();
X
Xstatic void Board_Expose();
Xextern void Button_Configure();
Xextern void Button_Expose();
Xextern void Button_Press();
Xextern void Button_Release();
Xextern void Do_Button_Configuration();
Xextern void Draw_Text();
Xextern void Draw_Score();
X
Xextern void Draw_Spring();
Xextern void Draw_Summer();
Xextern void Draw_Fall();
Xextern void Draw_Winter();
Xextern void Draw_Bamboo();
Xextern void Draw_Mum();
Xextern void Draw_Orchid();
Xextern void Draw_Plum();
Xextern void Draw_GDragon();
Xextern void Draw_RDragon();
Xextern void Draw_WDragon();
Xextern void Draw_East();
Xextern void Draw_West();
Xextern void Draw_North();
Xextern void Draw_South();
Xextern void Draw_Bam1();
Xextern void Draw_Bam2();
Xextern void Draw_Bam3();
Xextern void Draw_Bam4();
Xextern void Draw_Bam5();
Xextern void Draw_Bam6();
Xextern void Draw_Bam7();
Xextern void Draw_Bam8();
Xextern void Draw_Bam9();
Xextern void Draw_Dot1();
Xextern void Draw_Dot2();
Xextern void Draw_Dot3();
Xextern void Draw_Dot4();
Xextern void Draw_Dot5();
Xextern void Draw_Dot6();
Xextern void Draw_Dot7();
Xextern void Draw_Dot8();
Xextern void Draw_Dot9();
Xextern void Draw_Crak1();
Xextern void Draw_Crak2();
Xextern void Draw_Crak3();
Xextern void Draw_Crak4();
Xextern void Draw_Crak5();
Xextern void Draw_Crak6();
Xextern void Draw_Crak7();
Xextern void Draw_Crak8();
Xextern void Draw_Crak9();
X
X#define NFACES	42		/* number of distinct tile faces */
X#define NTILES	((NFACES-8) * 4 + 8) /* number of distinct tiles in game */
X#define NROWS	8		/* number of rows in game */
X#define NCOLS	16		/* number of columns in game */
X#define NO_TILE	0		/* tile codes are 1..NFACES */
X
X/*--Size of the Board. */
X
Xint		Board_Width	= 29 * 15 + 1 + 8;
Xint		Board_Height	= 33 * 10 + 1 + 8;
Xint		Score		= NTILES;
X
X/*--X/Y coordinate of a tile at coord 0,0 of the playing surface. */
X
Xint		Board_Tile0_X	= 4;
Xint		Board_Tile0_Y	= 4 + 2 * 33;
X
X/*--Actual size of a tile, not counting the border around it. */
X
Xunsigned int	Tile_Width	= 28;
Xunsigned int	Tile_Height	= 32;
X
X/*--X depth and Y width of a shadowed area above/to-the-right-of a tile. */
X
Xint		Shadow_X	= 28 / 8;
Xint		Shadow_Y	= 32 / 8;
X
X/*--X depth and Y width of tile edge below/to-the-left-of a tile. */
X
Xint		Side_X		= (28 / 10) & ~1;
Xint		Side_Y		= (32 / 10) & ~1;
X
X/*--Each playing tile position is represented by one of these. */
X
Xtypedef struct _Board_Position {
X    char		tiles[4];	/* at most 4 tiles at one position */
X    Boolean		draw;		/* TRUE if needs drawing */
X    int			level;		/* how many tiles do we have */
X    int			x;		/* x coord of tile */
X    int			y;		/* x coord of tile */
X} Board_Position_Rec, *Board_Position;
X
X#define Board_Position_NULL	((Board_Position)0)
X
XBoard_Position_Rec	Board_Tiles[NROWS][NCOLS];
X
X#define SPEC1		0][14		/* farthest right odd tile */
X#define SPEC1row	0		/* farthest right odd tile */
X#define SPEC1col	14		/* farthest right odd tile */
X#define SPEC2		2][14		/* next farthest right odd tile */
X#define SPEC2row	2		/* next farthest right odd tile */
X#define SPEC2col	14		/* next farthest right odd tile */
X#define SPEC3		4][14		/* farthest left odd tile */
X#define SPEC3row	4		/* farthest left odd tile */
X#define SPEC3col	14		/* farthest left odd tile */
X#define SPEC4		6][14		/* center piece tile */
X#define SPEC4row	6		/* center piece tile */
X#define SPEC4col	14		/* center piece tile */
X
X/*--Index into this array using a tile number in order to get the procedure
X *  that knows how to draw the face of that tile. */
X
Xtypedef void (*Draw_Xyz)();
X
Xvoid Draw_Error() { fprintf( stderr, "Drew tile face 0??\n" ); return; }
X
XDraw_Xyz	Faces[1+NFACES] = {
X    Draw_Error,
X
X    Draw_Spring,  Draw_Summer,  Draw_Fall,    Draw_Winter,
X
X    Draw_Bamboo,  Draw_Mum,     Draw_Orchid,  Draw_Plum,
X
X    Draw_GDragon, Draw_RDragon, Draw_WDragon,
X
X    Draw_East,    Draw_West,    Draw_North,   Draw_South,
X
X    Draw_Bam1,    Draw_Bam2,    Draw_Bam3,    Draw_Bam4,     Draw_Bam5,
X    Draw_Bam6,    Draw_Bam7,    Draw_Bam8,    Draw_Bam9,
X
X    Draw_Dot1,    Draw_Dot2,    Draw_Dot3,    Draw_Dot4,     Draw_Dot5,
X    Draw_Dot6,    Draw_Dot7,    Draw_Dot8,    Draw_Dot9,
X
X    Draw_Crak1,   Draw_Crak2,   Draw_Crak3,   Draw_Crak4,    Draw_Crak5,
X    Draw_Crak6,   Draw_Crak7,   Draw_Crak8,   Draw_Crak9
X};
X
X/*--Record tile clicks and watch for double clicks. */
X
XBoolean			One_Button_Hint = FALSE;
XBoard_Position		Click1 = Board_Position_NULL;
Xint			Click1_Row;
Xint			Click1_Col;
XBoard_Position		Click2 = Board_Position_NULL;
Xint			Click2_Row;
Xint			Click2_Col;
XTime			Click2_Time;
X
X
Xvoid Write_Game( file )
X     FILE	*file;
X/******************************************************************************
X*   file    - Specifies a file open for write
X*
X* Called to write out the current game context for later rereading.
X******************************************************************************/
X{
X
X    fwrite( (char*)&Score, 1, sizeof(Score), file );
X    fwrite( (char*)&Board_Tiles[0][0], 1, sizeof(Board_Tiles), file );
X
X} /* Write_Game */
X
X
Xvoid Read_Game( file )
X     FILE	*file;
X/******************************************************************************
X*   file    - Specifies a file open for reading
X*
X* Called to read in a new current game context.
X******************************************************************************/
X{
X
X    Click1 = Board_Position_NULL;
X    Click2 = Board_Position_NULL;
X    fread( (char*)&Score, 1, sizeof(Score), file );
X    fread( (char*)&Board_Tiles[0][0], 1, sizeof(Board_Tiles), file );
X
X} /* Read_Game */
X
X
Xstatic int Pick_Tile( Avail )
X     char	*Avail;
X/******************************************************************************
X*   Avail	- Specifies an [NTILES] array of available tiles.  Unavailable
X*		  slots contain NO_TILE.
X*
X* Called to pick a random tile from the Available tiles.
X******************************************************************************/
X{
X    register char	*t;
X    register int	k;
X
X/*--Pick a random starting place. */
X
X    k = (int)random() % NTILES;
X    t = &Avail[k];
X
X/*--Search until we find a non-NO_TILE slot. */
X
X    while (*t == NO_TILE) {
X	++t;
X	if (++k == NTILES) {
X	    t = &Avail[0];
X	    k = 0;
X	}
X    }
X
X/*--Return the tile we found and zap the slot. */
X
X    k = *t;
X    *t = NO_TILE;
X    return k;
X
X} /* Pick_Tile */
X
X
Xstatic void Set_Tile_Controls()
X/******************************************************************************
X* Called whenever the board has been reset or resized.  We recalculate all of
X* the drawing controls for the tiles.
X******************************************************************************/
X{
X    register Board_Position	bp;
X    int				row, col;
X
X/*--Now set up the control information for all of the tiles.  The special
X *  tiles are easy. */
X
X    DEBUG_CALL(Set_Tile_Controls);
X    if (Board_Tiles[SPEC4].level > 0) {
X	Board_Tiles[SPEC4].x	 	= Board_Tile0_X + 6 * (Tile_Width + 1)
X	  				  + (Tile_Width + 1) / 2 + 4 * Side_X;
X	Board_Tiles[SPEC4].y	 	= Board_Tile0_Y + 3 * (Tile_Height + 1)
X					  + (Tile_Height + 1) / 2 - 3 * Side_Y;
X    }
X
X    if (Board_Tiles[SPEC3].level > 0) {
X	Board_Tiles[SPEC3].x	 	= Board_Tile0_X + 0 * (Tile_Width + 1);
X	Board_Tiles[SPEC3].y	 	= Board_Tile0_Y + 3 * (Tile_Height + 1)
X					  + (Tile_Height + 1) / 2;
X    }
X
X    if (Board_Tiles[SPEC2].level > 0) {
X	Board_Tiles[SPEC2].x	 	= Board_Tile0_X + 13 * (Tile_Width+1);
X	Board_Tiles[SPEC2].y	 	= Board_Tile0_Y +  3 * (Tile_Height+1)
X					  + (Tile_Height + 1) / 2;
X    }
X
X    if (Board_Tiles[SPEC1].level > 0) {
X	Board_Tiles[SPEC1].x	 	= Board_Tile0_X + 14 * (Tile_Width+1);
X	Board_Tiles[SPEC1].y	 	= Board_Tile0_Y +  3 * (Tile_Height+1)
X	      				  + (Tile_Height + 1) / 2;
X    }
X
X/*--Do the more regular tiles. */
X
X    for (row = 0; row <= 7; ++row) {
X	for (col = 12; col >= 1; --col) {
X	    bp = &Board_Tiles[row][col];
X
X/*--Skip any tiles that don't exist. */
X
X	    if (bp->level == 0) { continue; }
X
X/*--Set up the face x/y coordinates. */
X
X	    bp->x = Board_Tile0_X + col * (Tile_Width + 1);
X	    bp->y = Board_Tile0_Y + row * (Tile_Height + 1);
X
X	}
X    }
X    DEBUG_RETURN(Set_Tile_Controls);
X
X} /* Set_Tile_Controls */
X
X
Xstatic void Pick1( bp, Avail )
X     register Board_Position	 bp;
X     char			*Avail;
X{
X    bp->tiles[0] = Pick_Tile( Avail );
X    bp->level = 1;
X}
X
Xstatic void Pick2( bp, Avail )
X     register Board_Position	 bp;
X     char			*Avail;
X{
X    bp->tiles[0] = Pick_Tile( Avail );
X    bp->tiles[1] = Pick_Tile( Avail );
X    bp->level = 2;
X}
X
Xstatic void Pick3( bp, Avail )
X     register Board_Position	 bp;
X     char			*Avail;
X{
X    bp->tiles[0] = Pick_Tile( Avail );
X    bp->tiles[1] = Pick_Tile( Avail );
X    bp->tiles[2] = Pick_Tile( Avail );
X    bp->level = 3;
X}
X
Xstatic void Pick4( bp, Avail )
X     register Board_Position	 bp;
X     char			*Avail;
X{
X    bp->tiles[0] = Pick_Tile( Avail );
X    bp->tiles[1] = Pick_Tile( Avail );
X    bp->tiles[2] = Pick_Tile( Avail );
X    bp->tiles[3] = Pick_Tile( Avail );
X    bp->level = 4;
X}
X
X
Xvoid Setup_New_Game()
X/******************************************************************************
X* Called to generate an all-new game.
X******************************************************************************/
X{
X    register Board_Position	bp;
X    char			Avail[NTILES];
X    int				row, col, i;
X
X/*--Clear the board. */
X
X    DEBUG_CALL(Setup_New_Game);
X    bp = &Board_Tiles[0][0];
X    for (row = 0; row < NROWS; ++row) {
X	for (col = 0; col < NCOLS; ++col) {
X	    bp->tiles[0] = NO_TILE;
X	    bp->tiles[1] = NO_TILE;
X	    bp->tiles[2] = NO_TILE;
X	    bp->tiles[3] = NO_TILE;
X	    bp->level = 0;
X	}
X    }
X
X/*--Mark all tiles as available. */
X
X    i = 0;
X    for (row = 0; row < 4; ++row) {
X	Avail[i++] = row + 1;
X	Avail[i++] = row + 5;
X	for (col = 8; col < NFACES; ++col) {
X	    Avail[i++] = 1 + col % NFACES;
X	}
X    }
X    if (i != NTILES) { fprintf( stderr, "NTILES gak!\n" ); }
X
X/*--Fill in the "odd" tile slots. */
X
X    Pick1( &Board_Tiles[SPEC1], Avail );
X    Pick1( &Board_Tiles[SPEC2], Avail );
X    Pick1( &Board_Tiles[SPEC3], Avail );
X    Pick1( &Board_Tiles[SPEC4], Avail );
X
X    for (col = 1; col <= 12; ++col) {
X	Pick1( &Board_Tiles[0][col], Avail );
X	Pick1( &Board_Tiles[7][col], Avail );
X    }
X    for (row = 1; row <= 6; ++row) {
X	Pick1( &Board_Tiles[row][ 3], Avail );
X	Pick1( &Board_Tiles[row][10], Avail );
X    }
X    for (row = 2; row <= 5; ++row) {
X	Pick1( &Board_Tiles[row][ 2], Avail );
X	Pick1( &Board_Tiles[row][11], Avail );
X    }
X    for (row = 3; row <= 4; ++row) {
X	Pick1( &Board_Tiles[row][ 1], Avail );
X	Pick1( &Board_Tiles[row][12], Avail );
X    }
X
X/*--Now do the next square at level 2. */
X
X    for (col = 4; col <= 9; ++col) {
X	Pick2( &Board_Tiles[1][col], Avail );
X	Pick2( &Board_Tiles[6][col], Avail );
X    }
X    for (row = 2; row <= 5; ++row) {
X	Pick2( &Board_Tiles[row][4], Avail );
X	Pick2( &Board_Tiles[row][9], Avail );
X    }
X
X/*--Now do the next square at level 3. */
X
X    for (col = 5; col <= 8; ++col) {
X	Pick3( &Board_Tiles[2][col], Avail );
X	Pick3( &Board_Tiles[5][col], Avail );
X    }
X    for (row = 3; row <= 4; ++row) {
X	Pick3( &Board_Tiles[row][5], Avail );
X	Pick3( &Board_Tiles[row][8], Avail );
X    }
X
X/*--Now do the final square at level 4. */
X
X    for (row = 3; row <= 4; ++row) {
X	for (col = 6; col <= 7; ++col) {
X	    Pick4( &Board_Tiles[row][col], Avail );
X	}
X    }
X
X/*--Now set up the control information for all of the tiles. */
X
X    Set_Tile_Controls();
X    Score = NTILES;
X    DEBUG_RETURN(Setup_New_Game);
X
X} /* Setup_New_Game */
X
X
X/*ARGSUSED*/
Xvoid Restart_Game( w, event, params, num_params )
X     Widget	w;
X     XEvent	*event;
X     String	*params;
X     Cardinal	*num_params;
X/******************************************************************************
X* Called when the RESTART button is pressed.  Restart the game.
X******************************************************************************/
X{
X    int				row;
X    int				col;
X    register Board_Position	bp;
X
X/*--Reset levels and remove hilites. */
X
X    DEBUG_CALL(Restart_Game);
X    Click1 = Board_Position_NULL;
X    Click2 = Board_Position_NULL;
X    Score = NTILES;
X    bp = &Board_Tiles[0][0];
X    for (row = 0; row < NROWS; ++row) {
X	for (col = 0; col < NCOLS; ++bp,++col) {
X	    if      (bp->tiles[3] != NO_TILE) { bp->level = 4; }
X	    else if (bp->tiles[2] != NO_TILE) { bp->level = 3; }
X	    else if (bp->tiles[1] != NO_TILE) { bp->level = 2; }
X	    else if (bp->tiles[0] != NO_TILE) { bp->level = 1; }
X	    else { bp->level = 0; }
X	}
X    }
X
X/*--Finish setting up and then redraw everything. */
X
X    Set_Tile_Controls();
X    XClearArea( XtDisplay(Board), XtWindow(Board), 0, 0, 0, 0, TRUE );
X    DEBUG_RETURN(Restart_Game);
X
X} /* Restart_Game */
X
X
Xstatic void Hilite_Tile( row, col )
X/******************************************************************************
X*   row	- Specifies the row of the tile to hilite
X*   col - specifies the column of the tile to hilite
X*
X* Called to hilite a tile face.
X******************************************************************************/
X{
X    register Board_Position	bp = &Board_Tiles[row][col];
X    XPoint	pnts[20];
X    int		pnti = 0;
X    int		x, y, w, h;
X    int		left, bottom, left_bottom;
X
X#define PNT(X,Y) \
X    if (pnti >= XtNumber(pnts)) {fprintf(stderr,"HT pnts overflow!\n");} \
X    pnts[pnti].x = X;     pnts[pnti].y = Y;  ++pnti
X    ;
X
X/*--See if we are one of the very special tiles on top. */
X
X    DEBUG_CALL(Hilite_Tile);
X    if (Board_Tiles[SPEC4].level > 0) {
X	if (row == 3) {
X	    if (col == 6) {
X		x = bp->x + Side_X * 4 + 1;
X		y = bp->y - Side_Y * 4 + 1;
X		w = Tile_Width / 2;
X		h = Tile_Height / 2;
X		PNT( x,			y );
X		PNT( Tile_Width,	0 );
X		PNT( 0,			h-1 );
X		PNT( -(w+1),		 0 );
X		PNT( 0,			h+1 );
X		PNT( -(w-1),		0 );
X		PNT( 0,			-Tile_Height );
X		goto Hilite;
X	    } else if (col == 7) {
X		x = bp->x + Side_X * 4 + 1;
X		y = bp->y - Side_Y * 4 + 1;
X		w = Board_Tiles[3][7].x - Board_Tiles[SPEC4].x + 3 * Side_X;
X		h = Tile_Height / 2;
X		PNT( x,			y );
X		PNT( Tile_Width,	0 );
X		PNT( 0,			Tile_Height );
X		PNT( -w,		0 );
X		PNT( 0,			-(h+1) );
X		PNT( -(Tile_Width-w),	 0 );
X		PNT( 0,			-(h-1) );
X		goto Hilite;
X	    }
X	} else if (row == 4) {
X	    if (col == 6) {
X		x = bp->x + Side_X * 4 + 1;
X		y = bp->y - Side_Y * 4 + 1;
X		w = Tile_Width / 2;
X		h = Tile_Height / 2;
X		PNT( x,			y );
X		PNT( w-1,		0 );
X		PNT( 0,			h + Side_Y );
X		PNT( w+1,		0 );
X		PNT( 0,			h - Side_Y );
X		PNT( -Tile_Width,	0 );
X		PNT( 0,			-Tile_Height );
X		goto Hilite;
X	    } else if (col == 7) {
X		x = bp->x + Side_X * 4 + 1;
X		y = bp->y - Side_Y * 4 + 1;
X		w = Board_Tiles[4][7].x - Board_Tiles[SPEC4].x + 3 * Side_X;
X		h = Tile_Height / 2;
X		PNT( x + Tile_Width - w,	y );
X		PNT( w,				0 );
X		PNT( 0,				Tile_Height );
X		PNT( -Tile_Width,		0 );
X		PNT( 0,				-(h - Side_Y) );
X		PNT( Tile_Width - w,		0 );
X		PNT( 0,				-(h + Side_Y) );
X		goto Hilite;
X	    }
X	}
X    }
X
X/*--We are a normal tile that may be partially overlapped by some other
X *  normal tile. */
X
X    x = bp->x + Side_X * bp->level + 1;
X    y = bp->y - Side_Y * bp->level + 1;
X    w = Tile_Width;
X    h = Tile_Height;
X    if (col > 0) {
X	left = Board_Tiles[row][col-1].level - bp->level;
X	if (left < 0) { left = 0; }
X	if (row < 7) {
X	    left_bottom = Board_Tiles[row+1][col-1].level - bp->level;
X	    if (left_bottom < 0) { left_bottom = 0; }
X	} else {
X	    left_bottom = 0;
X	}
X    } else {
X	left = 0;
X	left_bottom = 0;
X    }
X    if (row < 7) {
X	bottom = Board_Tiles[row+1][col].level - bp->level;
X	if (bottom < 0) { bottom = 0; }
X    } else {
X	bottom = 0;
X    }
X    if (bottom > left_bottom && Tile_Width == 28) { left_bottom = bottom; }
X    if (left > 0) {
X	w = left * Side_X;
X    } else {
X	w = 0;
X    }
X    PNT( x + w, y );
X    PNT( Tile_Width - w, 0 );
X    if (bottom > 0) {
X	h = bottom * Side_Y;
X    } else {
X	h = 0;
X    }
X    PNT( 0, Tile_Height - h );
X    if (left_bottom <= left && left_bottom <= bottom) {
X	PNT( -(Tile_Width - bottom*Side_X), 0 );
X	if (left != bottom) {
X	    PNT( (left-bottom)*Side_X, (bottom-left)*Side_Y );
X	}
X	PNT( 0, -(Tile_Height - h) );
X    } else if (left_bottom <= left) {	/* left_bottom > bottom */
X	PNT( -(Tile_Width - left_bottom*Side_X), 0 );
X	if (left_bottom != left ) {
X	    PNT( 0, (bottom-left_bottom)*Side_Y );
X	    PNT( (left-left_bottom)*Side_X, (left_bottom-left)*Side_Y );
X	    PNT( 0, -(Tile_Height - left * Side_Y) );
X	} else {
X	    PNT( 0, -(Tile_Height - h) );
X	}
X    } else if (left_bottom <= bottom) {	/* left_bottom > left */
X	if (left_bottom == bottom) {
X	    PNT( -(Tile_Width-w), 0 );
X	    PNT( 0, -(Tile_Height-h) );
X	} else {
X	    PNT( -(Tile_Width - bottom * Side_X), 0 );
X	    PNT( (left_bottom-bottom)*Side_X, (bottom-left_bottom)*Side_Y );
X	    PNT( -left_bottom*Side_X, 0 );
X	    PNT( 0, -(Tile_Height - left_bottom * Side_Y) );
X	}
X    } else {		/* left_bottom > bottom && left_bottom > left */
X	PNT( -(Tile_Width - left_bottom * Side_X), 0 );
X	PNT( 0, (bottom-left_bottom)*Side_Y );
X	PNT( (left-left_bottom)*Side_X, 0 );
X	PNT( 0, -(Tile_Height - left_bottom * Side_Y) );
X    }
X
X/*--Now do it. */
X
X  Hilite :
X    XFillPolygon( XtDisplay(Board), XtWindow(Board), Xor_GC,
X		  pnts, (Cardinal)pnti, Convex, CoordModePrevious );
X    DEBUG_RETURN(Hilite_Tile);
X
X} /* Hilite_Tile */
X
X
Xstatic void Clear_Tile( bp, left, bottom )
X     register Board_Position	bp;
X     int			left;
X     int			bottom;
X/******************************************************************************
X*   bp	    - Specifies the Board_Position to draw
X*   left    - Specifies the level of the tile on the left of this thile
X*   bottom  - Specifies the level of the tile at the bottom of this tile
X*
X* We clear (make totally white) the space occupied by the image of this tile.
X* We clear the face and the left and bottom sides.  Any shadowing caused by
X* the last drawing of this tile is the responsibility of the caller.
X******************************************************************************/
X{
X    XPoint	Poly[10];
X    int		Polyi;
X
X#undef PNT
X#define PNT(XX,YY) \
X    if (Polyi >= XtNumber(Poly)){fprintf(stderr,"Tile: Poly overflow!!\n");} \
X    Poly[Polyi].x = (XX); \
X    Poly[Polyi].y = (YY); \
X    ++Polyi
X    ;
X
X/*--We will circle the tile outline clockwise. */
X
X    DEBUG_CALL(Clear_Tile);
X    Polyi = 0;
X
X/*--Start with the upper left corner of the tile side. This is the "bottom"
X *  of that tile side if it has one. Leave x/y at the upper-left corner of the
X *  tile face. */
X
X    if (left >= bp->level) {
X	left = bp->level;
X	PNT( bp->x + Side_X * bp->level, bp->y - Side_Y * bp->level );
X    } else {
X	PNT( bp->x + Side_X * left, bp->y - Side_Y * left );
X	PNT( Side_X * (bp->level - left), - Side_Y * (bp->level - left) );
X    }
X
X/*--Cross the top and the right side of the tile. */
X
X    PNT( Tile_Width + 1, 0 );
X    PNT( 0, Tile_Height + 1 );
X
X/*--Now do the bottom side of the tile. */
X
X    if (bottom < bp->level) {
X	PNT( - Side_X * (bp->level - bottom), Side_Y * (bp->level - bottom) );
X    } else {
X	bottom = bp->level;
X    }
X    PNT( -(Tile_Width + 1), 0 );
X
X/*--Now go up the left side of the tile. */
X
X    if (left != bottom) {
X	PNT( Side_X * (left - bottom), - Side_Y * (left - bottom) );
X    }
X    PNT( 0, -(Tile_Height + 1) );
X
X/*--Do the actual clearing. */
X
X    XFillPolygon( XtDisplay(Board), XtWindow(Board), Reverse_GC,
X		  Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
X    DEBUG_RETURN(Clear_Tile);
X
X} /* Clear_Tile */
X
X
Xstatic void Tile( row, col )
X     int		row;
X     int		col;
X/******************************************************************************
X*   row		  - Specifies the tile to draw
X*   col		  - Specifies the tile to draw
X*
X* Called to draw a tile.  We draw the face, the sides, and the shadow.
X******************************************************************************/
X{
X    register Board_Position	bp= &Board_Tiles[row][col];
X    XPoint			Poly[100];
X    int				Polyi;
X    int				left;
X    int				bottom;
X    int				curx;
X    int				cury;
X    int				sidex;
X    int				sidey;
X    int				i, j, k, l, m;
X
X#undef PNT
X#define PNT(XX,YY) \
X    if (Polyi >= XtNumber(Poly)){fprintf(stderr,"Tile: Poly overflow!!\n");} \
X    Poly[Polyi].x = (XX); \
X    Poly[Polyi].y = (YY); \
X    ++Polyi
X    ;
X
X/*--This tile no longer needs drawing. */
X
X    DEBUG_CALL(Tile);
X    bp->draw = FALSE;
X
X/*--Determine the level of the tile on the left of this tile. */
X
X    if (col > 0) {
X	if (col == SPEC1col && row == SPEC1row) {
X	    left = Board_Tiles[SPEC2].level;
X	} else if (col == SPEC2col && row == SPEC2row) {
X	    if (Board_Tiles[3][12].level == 0 ||
X		Board_Tiles[4][12].level == 0) {
X		left = 0;
X	    } else {
X		left = 1;
X	    }
X	} else {
X	    left = Board_Tiles[row][col-1].level;
X	}
X    } else {
X	left = 0;
X    }
X
X/*--Determine the level of the tile at the bottom of this tile. */
X
X    if (row < 7) {
X	bottom = Board_Tiles[row+1][col].level;
X    } else {
X	bottom = 0;
X    }
X
X/*--Clear the area that will be covered by this tile. */
X
X    Clear_Tile( bp, left, bottom );
X
X/*--Draw the tile face. */
X
X    (*(Faces[bp->tiles[bp->level-1]]))( bp->x + bp->level * Side_X + 1,
X				        bp->y - bp->level * Side_Y + 1 );
X
X/*--Now draw the tile edges. */
X
X    if (Tile_Control & BLACKSIDE) {
X
X/*--We want black/gray sides. */
X
X	XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		        bp->x + bp->level * Side_X,
X		        bp->y - bp->level * Side_Y,
X		        Tile_Width + 1, Tile_Height + 1 );
X
X	if (left < bp->level) {
X	    Polyi = 0;
X	    PNT( bp->x + left * Side_X, bp->y - left * Side_Y );
X	    PNT( (bp->level - left) * Side_X, (left - bp->level) * Side_Y );
X	    PNT( 0, Tile_Height + 1 );
X	    PNT( (left - bp->level) * Side_X, (bp->level - left) * Side_Y );
X	    PNT( 0, -(Tile_Height + 1) );
X	    XFillPolygon( XtDisplay(Board), XtWindow(Board),
X			  ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
X			  Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
X	    XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		       Poly, (Cardinal)Polyi, CoordModePrevious );
X	}
X	if (bottom < bp->level) {
X	    Polyi = 0;
X	    PNT( bp->x + bp->level * Side_X,
X		 bp->y - bp->level * Side_Y + Tile_Height + 1 );
X	    PNT( Tile_Width + 1, 0 );
X	    PNT( (bottom - bp->level) * Side_X, (bp->level - bottom) * Side_Y);
X	    PNT( -(Tile_Width + 1), 0 );
X	    PNT( (bp->level - bottom) * Side_X, (bottom - bp->level) * Side_Y);
X	    XFillPolygon( XtDisplay(Board), XtWindow(Board),
X			  ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
X			  Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
X	    XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
X		        Poly, (Cardinal)Polyi, CoordModePrevious );
X	}
X
X/*--We want line'ed sides. */
X
X    } else {
X
X	Polyi = 0;
X	if (left >= bp->level) {
X	    PNT( bp->x + Side_X * bp->level, bp->y - Side_Y * bp->level );
X	} else {
X
X/*--First we draw the left side.  We leave x/y at the bottom left corner of
X *  the tile face when we are done. */
X
X#define LSEGS 7 /* keep this an odd number */
X
X	    sidex = Side_X * (bp->level - left);
X	    sidey = Side_Y * (bp->level - left);
X	    j = sidex;
X	    if (Tile_Width == 28 && bp->level - left == 1) {
X		PNT( bp->x + Side_X * left, bp->y - Side_Y * left - sidey );
X		PNT( 0, Tile_Height + 1 + sidey );
X		k = 0;
X	    } else {
X		PNT( bp->x + Side_X * left, bp->y - Side_Y * left );
X		PNT(0, Tile_Height + 1 );
X		k = sidey;
X	    }
X	    PNT( sidex, -sidey );
X	    i = Tile_Height / (LSEGS+1);
X	    m = Tile_Height - i * (LSEGS+1);
X	    for (l = LSEGS; l > 0; --l) {
X		cury = -i;
X		if (m > 0) { cury -= 1; --m; }
X		PNT( 0, cury );
X		PNT( -j, k );
X		j = -j;
X		k = -k;
X	    }
X	    PNT( 0, -i-1 );
X	    PNT( sidex, k );
X	}
X	PNT( 0, Tile_Height + 1 );
X
X/*--Draw the left edge of the tile and then draw the bottom side of the tile.
X *  We leave x/y at the bottom right corner of the tile face when we are done.
X */
X
X#define RSEGS 6	/* keep this an even number */
X
X	if (bottom < bp->level) {
X	    sidex = Side_X * (bp->level - bottom);
X	    sidey = Side_Y * (bp->level - bottom);
X	    i = Tile_Width / (RSEGS+1);
X	    m = Tile_Width - i * (RSEGS+1);
X	    if (Tile_Width == 28 && bp->level - bottom == 1) {
X		j = 0;
X	    } else {
X		j = sidex;
X	    }
X	    k = sidey;
X	    for (l = RSEGS; l > 0; --l) {
X		curx = i;
X		if (m > 0) { curx += 1; --m; }
X		PNT( curx, 0 );
X		PNT( -j, k );
X		j = -j;
X		k = -k;
X	    }
X	    PNT( i+1, 0 );
X	    PNT( -j, sidey );
X	    PNT( -(Tile_Width + 1 + sidex - j), 0 );
X	    PNT( sidex, -sidey );
X	}
X	PNT( Tile_Width + 1, 0 );
X
X/*--Draw the right side. */
X
X	PNT( 0, -(Tile_Height + 1) );
X
X/*--Draw the top side. */
X
X	PNT( -(Tile_Width + 1), 0 );
X
X/*--Draw all of those edges. */
X
X	XDrawLines( XtDisplay(Board), XtWindow(Board),
X		    ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
X		    Poly, (Cardinal)Polyi, CoordModePrevious );
X    }
X
X/*--Now draw the tile shadow. */
X
X    if (Tile_Control & SHADOW) {
X	int	top, right;
X	Boolean	top_right;
X
X/*--Determine the level of the tile on the right of this tile. */
X
X	if (col == SPEC1col) {
X	    if (row == SPEC2row) {
X		right = Board_Tiles[SPEC1].level;
X	    } else if (row == SPEC3row) {
X		right = 0;
X	    } else {
X		right = 0;
X	    }
X	} else {
X	    right = Board_Tiles[row][col+1].level;
X	}
X
X/*--Determine the level of the tile at the top of this tile. */
X
X	if (row > 0) {
X	    top = Board_Tiles[row-1][col].level;
X	} else {
X	    top = 0;
X	}
X
X/*--Do we have an upper-right tile? */
X
X	if (row > 0 &&
X	    Board_Tiles[row-1][col+1].level >= bp->level) {
X	    top_right = TRUE;
X	} else if (row == SPEC3row && col == SPEC3col &&
X		   Board_Tiles[3][1].level > 0) {
X	    top_right = TRUE;
X	} else if (row == 4 && col == 12 &&
X		   Board_Tiles[SPEC2].level > 0) {
X	    top_right = TRUE;
X	} else {
X	    top_right = FALSE;
X	}
X
X/*--Draw the upper shadow if necessary. */
X
X	if (top < bp->level) {
X	    Polyi = 0;
X	    PNT( bp->x + bp->level * Side_X - 1,
X		 bp->y - bp->level * Side_Y );
X	    PNT( Shadow_X, -Shadow_Y );
X	    if (top_right) {
X		i = Shadow_X;
X	    } else {
X		i = 0;
X	    }
X	    PNT( Tile_Width + 3 - i, 0 );
X	    PNT( -(Shadow_X - i), Shadow_Y );
X	    PNT( -(Tile_Width + 3), 0 );
X	    XFillPolygon( XtDisplay(Board), XtWindow(Board), Over_GC,
X			  Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
X	}
X
X/*--Now work on the right shadow.  It may need to be drawn in pieces. */
X
X	Polyi = 0;
X
X/*--If SPEC3 has both neighbors then don't draw the right shadow. */
X
X	if (row == SPEC3row && col == SPEC3col) {
X	    if (Board_Tiles[3][1].level > 0) {
X		if (Board_Tiles[4][1].level > 0) {
X		    right = bp->level;
X
X/*--If SPEC3 has only the upper neighbor then draw just the lower shadow. */
X
X		} else {
X		    i = bp->y - Board_Tiles[3][1].y;
X		    PNT( Board_Tiles[4][1].x + Side_X, Board_Tiles[4][1].y );
X		    PNT( Shadow_X, 0 );
X		    PNT( 0, i - Shadow_Y);
X		    PNT( -Shadow_X, Shadow_Y );
X		    PNT( 0, -i );
X		    right = bp->level;
X		}
X
X/*--If SPEC3 has only the lower neighbor then draw just the upper shadow. */
X
X	    } else if (Board_Tiles[4][1].level > 0) {
X		i = Board_Tiles[4][1].y - bp->y;
X		PNT( bp->x + bp->level * Side_X + Tile_Width + 1 + 1,
X		     bp->y - bp->level * Side_Y );
X		PNT( Shadow_X, -Shadow_Y );
X		PNT( 0, i + Shadow_Y );
X		PNT( -Shadow_X, 0 );
END_OF_FILE
if test 27384 -ne `wc -c <'board.c.aa'`; then
    echo shar: \"'board.c.aa'\" unpacked with wrong size!
fi
# end of 'board.c.aa'
fi
if test -f 'dragon.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dragon.man'\"
else
echo shar: Extracting \"'dragon.man'\" \(7439 characters\)
sed "s/^X//" >'dragon.man' <<'END_OF_FILE'
X.TH DRAGON 1 "18 April 1989" "X Version 11R3"
X.SH NAME
Xdragon \- Mah-Jongg game
X.SH SYNOPSIS
X.B dragon
X[-cursor name]
X[-double interval]
X[-icongeometry geometry]
X[-/+iconic]
X[-iconname name]
X[-/+reverse]
X[-/+shadows]
X[-sides type]
X.SH DESCRIPTION
X\fIDragon\fP plays a version of the game of Mah-Jongg.
X
XMah-Jongg is played with a set of tiles.  The tiles are set out in a
Xparticular pattern and the object of the game is to eliminate all of
Xthe tiles.  \fIDragon\fP plays with the tile pattern known as "The
XDragon".  This pattern has 5 levels of tiles.  From above, this
Xpattern somewhat resembles a sleeping dragon.
X
XTiles are removed from the game two at a time.  The two tiles removed
Xmust "match" and they must both be "free".
X
XA tile is "free" if on the left or on the right side there is no tile
Xthat is on the same stacking level as this tile.  There may be tiles
Xthat are at a lower level than this tile but not one at the same or
Xhigher level.  To select a free tile for removal just click on it.
X\fIDragon\fP will refuse to select a tile that is not free.  To remove
Xa pair of tiles simply double-click on one of the tiles.  You have the
Xoption of selecting one tile and then double-clicking on the second or
Xelse selecting both tiles and then double-clicking upon either tile.
X
XTwo tiles match if a) they both have the same picture upon their
Xfaces, b) they are both flowers, or c) if they are both seasons.
X
XThere are seven types of tile.
X
XFlowers - There are four tiles that represent flowers.  These are the
XOrchid, the Plum, the Mum, and the Bamboo tiles.  Any two flowers match.
X
XSeasons - There are four tiles that represent the four seasons.  These
Xare the Spring, Summer, Autumn, and Winter tiles.  Any two seasons match.
X
XDragons - There are three types of dragons and there are four each of
Xthe dragons.  There is the Red dragon, the White dragon, and the Green
Xdragon.  Only two dragons of the same type match each other.
X
XWinds - There are four each of the four winds.  These are the East,
XWest, North, and South tiles.  Only two winds from the same direction
Xmatch each other.
X
XBams, Dots, and Craks - These tiles are numbered 1 through 9.  There
Xare four each of each numbered tile.  Only two tiles of the same type
Xwith the same number match each other.
X
X.SH OPTIONS
XThe \fIdragon\fP program accepts all of the standard X Toolkit command
Xline options along with the additional options listed below:
X.TP 8
X.B \-help
XThis produces a verbose message describing the command line options.
X.TP 8
X.B \-cursor name
XNormally \fIdragon\fP uses the "hand2" cursor.  Use this option to
Xuse your favorite cursor instead.
X.TP 8
X.B \-double interval
XIn order to play the game you must double-click upon tiles.  This
Xoption allows you to set the maximum time interval between clicks that
Xseparate the two clicks that make up a double click.  The default is
X250 milliseconds.  Clicks further apart than this will be treated as
Xseparate single clicks instead of one double click.
X.TP 8
X.B \-icongeometry geometry
XUse this option to specify the geometry to be used for the
X\fIdragon\fP icon.  There are two sizes that \fIdragon\fP prefers,
X32x32 and 64x64.
X.TP 8
X.B \-iconic
XUse this option and \fIdragon\fP will first appear as an icon.  Use
Xthe \fB+iconic\fP form and \fIdragon\fP will \fBnot\fP first appear as
Xan icon.
X.TP 8
X.B \-iconname name
XUse this option to set the name of \fIdragon's\fP icon.
X.TP 8
X.B \-reverse
XUse this option for reverse-video and use the \fB+reverse\fP option
Xfor normal-video.
X.TP 8
X.B \-shadows
XUse this option and tiles will not have 3-D shadows and use
Xthe \fB+shadows\fP and tiles will have (the default) 3-D shadows.
X.TP 8
X.B \-sides type
XThis option can be used to specify the way that tile sides are drawn.
XThere are four possiblities.  "gray" (the default), "black", and "line".
X.SH MOUSE BUTTONS
XClick button 1 on any tile to select it.  Click on any menu button to activate
Xit.
X
XClick button 2 to obtain a (next) hint on a possible move.  See the Hint menu
Xbutton below for more information.
X
XClick button 3 to remove two selected tiles from the game.
X.SH MENU BUTTONS
XThere are several buttons visible in \fIdragon's\fP window and there
Xare two sets of buttons.  The inital set includes:
X.TP 8
X.B "New Game"
XPress this button to reshuffle the tiles and start a new game.
X.TP 8
X.B "Restart"
XPress this button to restart the current game.  This gives you a
Xchance to try again.
X.TP 8
X.B "Save"
XPress this button to save the current game into the file
X$HOME/.dragon-save.  The current game is saved at the current point
Xfor later resumption.
X.TP 8
X.B "Other"
XPress this button to get to the other set of buttons.
X.TP 8
X.B "Hint"
XThis button can be used in two ways.  First, if you are stuck for a
Xmove then just press this button repeatedly and \fIdragon\fP will show
Xsuccessive possible moves.  Of course, there may not be any.  Second,
Xif you want to remove a particular tile but you cannot see any
Xmatching free tiles then select the tile and then press this button to
Xsee if \fIdragon\fP agrees with you that there aren't any matching
Xfree tiles.
X.TP 8
X.B "Restore"
XPress this button to read the $HOME/.dragon-save file and to resume a
Xsaved game.
X.TP 8
X.B "Quit"
XPress this button to exit the game.
X.PP
XThe other set of buttons include:
X.TP 8
X.B "Redraw"
XPress this to cause the board to be redrawn.
X.TP 8
X.B "Sides"
XPress this repeatedly to cycle through the available set of drawing
Xoptions for the tiles.
X.TP8
X.B "Samples"
XPress this to display the full set of tiles.  Press it again to get back to
Xthe game.
X.TP 8
X.B "Other"
XPress this to get back to the first set of buttons.
X.TP 8
X.B "Cheat"
XPress this button to toggle Cheating mode.  When this is turned on you
Xcan remove any two arbitrary tiles.  Don't cheat!
X.TP 8
X.B "Sync"
XPress this button to turn on synchronous mode.  This makes
X\fIdragon\fP synchronize everything with the X Server; it is typically
Xused only for debugging.
X.SH "X DEFAULTS"
X\fIDragon's\fP name is usually "dragon" and its class is "Dragon".  It
Xunderstands all of the core X Toolkit resource names and classes as
Xwell as:
X.TP 8
X.B "cursor (\fPclass\fB Cursor)"
XSpecifies the name of the cursor to use.  The default is "hand2".
X.TP 8
X.B "doubleClick (\fPclass\fB DoubleClick)"
XSpecifies the maximum time to allow between the two clicks that form a
Xdouble-click.  The default is 250.
X.TP 8
X.B "iconGeometry (\fPclass\fB IconGeometry)"
XSpecifies the geometry of the \fIdragon\fB icon.  Preferred sizes are
X32x32 and 64x64.  The default is "64x64".
X.TP 8
X.B "iconic (\fPclass\fB Iconic)"
XSpecifies TRUE to cause an iconic startup and FALSE for a normal
Xstartup.  The default is FALSE.
X.TP 8
X.B "iconName (\fPclass\fB IconName)"
XSpecifies the name for the icon.  The default is NULL.
X.TP 8
X.B "reverseVideo (\fPclass\fB ReverseVideo)"
XSpecifies TRUE for reverse-video effects and FALSE for normal-video.
XThe default is FALSE.
X.TP 8
X.B "tileShadows (\fPclass\fB TileShadows)"
XSpecifies TRUE if tiles are to have 3-D shadows and FALSE if not.  The
Xdefault is TRUE.
X.TP 8
X.B "tileSides (\fPclass\fB TileSides)"
XSpecifies the type of sides to use when drawing tiles.  The default is
X"gray" for gray sides.  The other options are "black" for black sides
Xand "line" for sides with lines.
X.SH "SEE ALSO"
XX(1)
X.SH BUGS
X.LP
XNo known bugs.  Send bug reports to geb@rational.com.
X.SH COPYRIGHT
XNone; have fun.
X.SH AUTHOR
XGary E. Barnes (Rational; geb@rational.com)
X.br
END_OF_FILE
if test 7439 -ne `wc -c <'dragon.man'`; then
    echo shar: \"'dragon.man'\" unpacked with wrong size!
fi
# end of 'dragon.man'
fi
if test -f 'ic/eight_20x24.ic' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ic/eight_20x24.ic'\"
else
echo shar: Extracting \"'ic/eight_20x24.ic'\" \(603 characters\)
sed "s/^X//" >'ic/eight_20x24.ic' <<'END_OF_FILE'
X#define eight_20x24_width 20
X#define eight_20x24_height 24
X#define eight_20x24_x_hot -1
X#define eight_20x24_y_hot -1
Xstatic char eight_20x24_bits[] = {
X   0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0xf8, 0xff, 0x01, 0x1c, 0x80, 0x03,
X   0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03,
X   0x0c, 0x00, 0x03, 0x1c, 0x80, 0x03, 0x18, 0x80, 0x01, 0xf0, 0xff, 0x00,
X   0xf0, 0xff, 0x00, 0x18, 0x80, 0x01, 0x1c, 0x80, 0x03, 0x0c, 0x00, 0x03,
X   0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03,
X   0x1c, 0x80, 0x03, 0xf8, 0xff, 0x01, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00};
END_OF_FILE
if test 603 -ne `wc -c <'ic/eight_20x24.ic'`; then
    echo shar: \"'ic/eight_20x24.ic'\" unpacked with wrong size!
fi
# end of 'ic/eight_20x24.ic'
fi
if test -f 'tile.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tile.c'\"
else
echo shar: Extracting \"'tile.c'\" \(16657 characters\)
sed "s/^X//" >'tile.c' <<'END_OF_FILE'
X/******************************************************************************
X* Dragon - a version of Mah-Jongg for X Windows
X*
X* Author: Gary E. Barnes	March 1989
X*
X* tile.c - Deals with the individual Mah-Jongg tiles.
X******************************************************************************/
X
X#include "main.h"
X
X/*--SEASONS */
X
Xextern XImage	spring;
Xextern XImage	summer;
Xextern XImage	fall;
Xextern XImage	winter;
X
X/*--FLOWERS */
X
Xextern XImage	bamboo;
Xextern XImage	mum;
Xextern XImage	orchid;
Xextern XImage	plum;
X
X/*--DRAGONS */
X
Xextern XImage	gdragon;
Xextern XImage	rdragon;
Xextern XImage	wdragon;
X
X/*--WINDS */
X
Xextern XImage	east;
Xextern XImage	west;
Xextern XImage	north;
Xextern XImage	south;
X
X/*--NUMBERS */
X
Xextern XImage	one;
Xextern XImage	two;
Xextern XImage	three;
Xextern XImage	four;
Xextern XImage	five;
Xextern XImage	six;
Xextern XImage	seven;
Xextern XImage	eight;
Xextern XImage	nine;
X
X/*--OTHER */
X
Xextern XImage	bam;
Xextern XImage	crak;
Xextern XImage	dot;
X
Xextern XImage_Init Sizes[5][28];
X
Xstatic int	Tile_X11	= 28 / 2;		/* one column */
Xstatic int	Tile_X21	= 28 / 3;		/* two columns */
Xstatic int	Tile_X22	= 28 * 2 / 3;
Xstatic int	Tile_X31	= 28 / 4;		/* three columns */
Xstatic int	Tile_X32	= 28 * 2 / 4;
Xstatic int	Tile_X33	= 28 * 3 / 4;
X
Xstatic int	Tile_Y11	= 32 / 2;		/* one row */
Xstatic int	Tile_Y21	= 32 / 3;		/* two rows */
Xstatic int	Tile_Y22	= 32 * 2 / 3;
Xstatic int	Tile_Y31	= 32 / 5;		/* three rows */
Xstatic int	Tile_Y32	= 32 * 2 / 5;
Xstatic int	Tile_Y33	= 32 * 3 / 5;
X
Xstatic int	Number_X	= 28 - 7;
Xstatic int	Number_Y	= 0;
Xstatic int	SubTile_X	= 7 / 2;
Xstatic int	SubTile_Y	= 8 / 2;
X
X
Xstatic void Setup_Image( image, bits, width, height )
X     XImage	*image;
X     char	*bits;
X     int	 width;
X     int	 height;
X/******************************************************************************
X*   image	- Specifies the XImage object to initialize
X*   bits	- Specifies the image data
X*   width	- Specifies the width of the image
X*   height	- Specifies the height of the image
X*
X* Called to init an XImage so that it points at a particular bitmap image.
X******************************************************************************/
X{
X
X    image->width = width;
X    image->height = height;
X    image->depth = 1;
X    image->xoffset = 0;
X    image->format = XYBitmap;
X    image->data = bits;
X    image->byte_order = LSBFirst;
X    image->bitmap_bit_order = LSBFirst;
X    image->bitmap_unit = 8;
X    image->bitmap_pad = 8;
X    image->bytes_per_line = (width + 7) / 8;
X
X} /* Setup_Image */
X
X
Xvoid Configure_Tiles( size )
X     int	size;
X/******************************************************************************
X*   size	- Specifies the tile size to use; 1..5
X*
X* Called when the Board receives a ConfigureNotify event.  We check to see if
X* the size of the board/tiles have changed.  If so then we reconfigure the
X* images of the tiles.
X******************************************************************************/
X{
X    XImage_Init	*table;
X    int		 w;
X    int		 h;
X
X/*--Make sure that our caller is rational. */
X
X    if (size < 1 || size > 5) {
X	fprintf( stderr, "Bad size given to Configure_Tiles in tile.c [%d].\n",
X		 size );
X	size = 1;
X    }
X
X/*--Set up all of the various images. */
X
X    for (table = &Sizes[size-1][0]; table->image != (XImage*)NULL; ++table) {
X	Setup_Image( table->image, table->bits, table->width, table->height );
X    }
X
X/*--Set up the sub-tile positions. */
X
X    w = spring.width;
X    h = spring.height;
X
X    Tile_X11	= w / 2;		/* one column */
X    Tile_X21	= w / 3;		/* two columns */
X    Tile_X22	= w - Tile_X21;
X    Tile_X31	= w / 4;		/* three columns */
X    while (Tile_X31 + bam.width/2 + bam.width*2 >= spring.width) {
X	--Tile_X31;
X    }
X    Tile_X32	= Tile_X31 + bam.width;
X    Tile_X33	= Tile_X32 + bam.width;
X
X    Tile_Y11	= h / 2;		/* one row */
X    Tile_Y21	= h / 3;		/* two rows */
X    Tile_Y22	= h - Tile_Y21;
X    Tile_Y31	= h * 2 / 5;		/* three rows */
X    while (Tile_Y31 + bam.height/2 + bam.height*2 >= spring.height) {
X	--Tile_Y31;
X    }
X    Tile_Y32	= Tile_Y31 + bam.height;
X    Tile_Y33	= Tile_Y32 + bam.height;
X
X    Number_X	= w - one.width - 1;
X    Number_Y	= 1;
X    SubTile_X	= bam.width  / 2;
X    SubTile_Y	= bam.height / 2;
X
X} /* Configure_Tiles */
X
X
Xstatic void Draw_Image( image, x, y )
X     XImage	*image;
X     int	 x;
X     int	 y;
X/******************************************************************************
X* Do an XPutImage on the image.
X******************************************************************************/
X{
X    XPutImage( XtDisplay(Board), XtWindow(Board), Normal_GC, image,
X	       0, 0, x, y,
X	       (unsigned int)image->width, (unsigned int)image->height );
X} /* Draw_Image */
X
X
Xstatic void Draw_Blank( x, y )
X     int	 x;
X     int	 y;
X/******************************************************************************
X* Draw an empty tile; our caller will fill it in with little images.
X******************************************************************************/
X{
X    XFillRectangle( XtDisplay(Board), XtWindow(Board), Reverse_GC,
X		    x, y,
X		    (unsigned int)spring.width, (unsigned int)spring.height );
X} /* Draw_Blank */
X
X
Xstatic void Draw_Number( image, x, y )
X     XImage	*image;
X     int	 x;
X     int	 y;
X/******************************************************************************
X* Called to draw the number in the upper right corner of a numbered tile.
X******************************************************************************/
X{
X    XPutImage( XtDisplay(Board), XtWindow(Board), Over_GC, image,
X	       0, 0, x + Number_X, y + Number_Y,
X	       (unsigned int)image->width, (unsigned int)image->height );
X} /* Draw_Number */
X
X
Xvoid Draw_Spring( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &spring, x, y );
X} /* Draw_Spring */
X
Xvoid Draw_Summer( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &summer, x, y );
X} /* Draw_Summer */
X
Xvoid Draw_Fall( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &fall, x, y );
X} /* Draw_Fall */
X
Xvoid Draw_Winter( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &winter, x, y );
X} /* Draw_Winter */
X
X
Xvoid Draw_Bamboo( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &bamboo, x, y );
X} /* Draw_Bamboo */
X
Xvoid Draw_Mum( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &mum, x, y );
X} /* Draw_Mum */
X
Xvoid Draw_Orchid( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &orchid, x, y );
X} /* Draw_Orchid */
X
Xvoid Draw_Plum( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &plum, x, y );
X} /* Draw_Plum */
X
X
Xvoid Draw_GDragon( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &gdragon, x, y );
X} /* Draw_GDragon */
X
Xvoid Draw_RDragon( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &rdragon, x, y );
X} /* Draw_RDragon */
X
Xvoid Draw_WDragon( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &wdragon, x, y );
X} /* Draw_WDragon */
X
X
Xvoid Draw_East( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &east, x, y );
X} /* Draw_East */
X
Xvoid Draw_West( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &west, x, y );
X} /* Draw_West */
X
Xvoid Draw_North( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &north, x, y );
X} /* Draw_North */
X
Xvoid Draw_South( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &south, x, y );
X} /* Draw_South */
X
X
Xvoid Draw_Bam1( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X11, by + Tile_Y11 );
X
X    Draw_Number( &one, x, y );
X
X} /* Draw_Bam1 */
X
Xvoid Draw_Bam2( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X11, by + Tile_Y21 );
X    Draw_Image( &bam, bx + Tile_X11, by + Tile_Y22 );
X
X    Draw_Number( &two, x, y );
X
X} /* Draw_Bam2 */
X
Xvoid Draw_Bam3( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X11, by + Tile_Y21 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y22 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y22 );
X
X    Draw_Number( &three, x, y );
X
X} /* Draw_Bam3 */
X
Xvoid Draw_Bam4( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y21 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y21 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y22 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y22 );
X
X    Draw_Number( &four, x, y );
X
X} /* Draw_Bam4 */
X
Xvoid Draw_Bam5( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X11, by + Tile_Y31 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y33 );
X
X    Draw_Number( &five, x, y );
X
X} /* Draw_Bam5 */
X
Xvoid Draw_Bam6( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y33 );
X
X    Draw_Number( &six, x, y );
X
X} /* Draw_Bam6 */
X
Xvoid Draw_Bam7( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &seven, x, y );
X
X} /* Draw_Bam7 */
X
Xvoid Draw_Bam8( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &bam, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y32 );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &eight, x, y );
X
X} /* Draw_Bam8 */
X
Xvoid Draw_Bam9( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y31 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y31 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y31 );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y32 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y32 );
X
X    Draw_Image( &bam, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &bam, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &nine, x, y );
X
X} /* Draw_Bam9 */
X
X
Xvoid Draw_Dot1( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X11, by + Tile_Y11 );
X
X    Draw_Number( &one, x, y );
X
X} /* Draw_Dot1 */
X
Xvoid Draw_Dot2( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X11, by + Tile_Y21 );
X    Draw_Image( &dot, bx + Tile_X11, by + Tile_Y22 );
X
X    Draw_Number( &two, x, y );
X
X} /* Draw_Dot2 */
X
Xvoid Draw_Dot3( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X11, by + Tile_Y21 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y22 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y22 );
X
X    Draw_Number( &three, x, y );
X
X} /* Draw_Dot3 */
X
Xvoid Draw_Dot4( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y21 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y21 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y22 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y22 );
X
X    Draw_Number( &four, x, y );
X
X} /* Draw_Dot4 */
X
Xvoid Draw_Dot5( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X11, by + Tile_Y31 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y33 );
X
X    Draw_Number( &five, x, y );
X
X} /* Draw_Dot5 */
X
Xvoid Draw_Dot6( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y33 );
X
X    Draw_Number( &six, x, y );
X
X} /* Draw_Dot6 */
X
Xvoid Draw_Dot7( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y32 );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &seven, x, y );
X
X} /* Draw_Dot7 */
X
Xvoid Draw_Dot8( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X21, by + Tile_Y31 );
X    Draw_Image( &dot, bx + Tile_X22, by + Tile_Y31 );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y32 );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &eight, x, y );
X
X} /* Draw_Dot8 */
X
Xvoid Draw_Dot9( x, y )
X     int	x;
X     int	y;
X{
X    int		bx = x - SubTile_X;
X    int		by = y - SubTile_Y;
X
X    Draw_Blank( x, y );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y31 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y31 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y31 );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y32 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y32 );
X
X    Draw_Image( &dot, bx + Tile_X31, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X32, by + Tile_Y33 );
X    Draw_Image( &dot, bx + Tile_X33, by + Tile_Y33 );
X
X    Draw_Number( &nine, x, y );
X
X} /* Draw_Dot9 */
X
X
Xvoid Draw_Crak1( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &one, x, y );
X} /* Draw_Crak1 */
X
Xvoid Draw_Crak2( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &two, x, y );
X} /* Draw_Crak2 */
X
Xvoid Draw_Crak3( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &three, x, y );
X} /* Draw_Crak3 */
X
Xvoid Draw_Crak4( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &four, x, y );
X} /* Draw_Crak4 */
X
Xvoid Draw_Crak5( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &five, x, y );
X} /* Draw_Crak5 */
X
Xvoid Draw_Crak6( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &six, x, y );
X} /* Draw_Crak6 */
X
Xvoid Draw_Crak7( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &seven, x, y );
X} /* Draw_Crak7 */
X
Xvoid Draw_Crak8( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &eight, x, y );
X} /* Draw_Crak8 */
X
Xvoid Draw_Crak9( x, y )
X     int	x;
X     int	y;
X{
X    Draw_Image( &crak, x, y );
X    Draw_Number( &nine, x, y );
X} /* Draw_Crak9 */
X
END_OF_FILE
if test 16657 -ne `wc -c <'tile.c'`; then
    echo shar: \"'tile.c'\" unpacked with wrong size!
fi
# end of 'tile.c'
fi
echo shar: End of archive 2 \(of 10\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0