home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-29 | 26.7 KB | 1,001 lines |
- /******************************************************************************
- * Dragon - a version of Mah-Jongg for X Windows
- *
- * Author: Gary E. Barnes March 1989
- *
- * board.c - Deals with the Mah-Jongg board. Setup and execution.
- ******************************************************************************/
-
- #include "main.h"
-
- #define BLACKSIDES 1
-
- extern long random();
- extern int srandom();
- extern long time();
-
- static void Board_Expose();
- extern void Button_Configure();
- extern void Button_Expose();
- extern void Button_Press();
- extern void Button_Release();
- extern void Do_Button_Configuration();
- extern void Draw_Text();
- extern void Draw_Score();
-
- extern void Draw_Spring();
- extern void Draw_Summer();
- extern void Draw_Fall();
- extern void Draw_Winter();
- extern void Draw_Bamboo();
- extern void Draw_Mum();
- extern void Draw_Orchid();
- extern void Draw_Plum();
- extern void Draw_GDragon();
- extern void Draw_RDragon();
- extern void Draw_WDragon();
- extern void Draw_East();
- extern void Draw_West();
- extern void Draw_North();
- extern void Draw_South();
- extern void Draw_Bam1();
- extern void Draw_Bam2();
- extern void Draw_Bam3();
- extern void Draw_Bam4();
- extern void Draw_Bam5();
- extern void Draw_Bam6();
- extern void Draw_Bam7();
- extern void Draw_Bam8();
- extern void Draw_Bam9();
- extern void Draw_Dot1();
- extern void Draw_Dot2();
- extern void Draw_Dot3();
- extern void Draw_Dot4();
- extern void Draw_Dot5();
- extern void Draw_Dot6();
- extern void Draw_Dot7();
- extern void Draw_Dot8();
- extern void Draw_Dot9();
- extern void Draw_Crak1();
- extern void Draw_Crak2();
- extern void Draw_Crak3();
- extern void Draw_Crak4();
- extern void Draw_Crak5();
- extern void Draw_Crak6();
- extern void Draw_Crak7();
- extern void Draw_Crak8();
- extern void Draw_Crak9();
-
- #define NFACES 42 /* number of distinct tile faces */
- #define NTILES ((NFACES-8) * 4 + 8) /* number of distinct tiles in game */
- #define NROWS 8 /* number of rows in game */
- #define NCOLS 16 /* number of columns in game */
- #define NO_TILE 0 /* tile codes are 1..NFACES */
-
- /*--Size of the Board. */
-
- int Board_Width = 29 * 15 + 1 + 8;
- int Board_Height = 33 * 10 + 1 + 8;
- int Score = NTILES;
-
- /*--X/Y coordinate of a tile at coord 0,0 of the playing surface. */
-
- int Board_Tile0_X = 4;
- int Board_Tile0_Y = 4 + 2 * 33;
-
- /*--Actual size of a tile, not counting the border around it. */
-
- unsigned int Tile_Width = 28;
- unsigned int Tile_Height = 32;
-
- /*--X depth and Y width of a shadowed area above/to-the-right-of a tile. */
-
- int Shadow_X = 28 / 8;
- int Shadow_Y = 32 / 8;
-
- /*--X depth and Y width of tile edge below/to-the-left-of a tile. */
-
- int Side_X = (28 / 10) & ~1;
- int Side_Y = (32 / 10) & ~1;
-
- /*--Each playing tile position is represented by one of these. */
-
- typedef struct _Board_Position {
- char tiles[4]; /* at most 4 tiles at one position */
- Boolean draw; /* TRUE if needs drawing */
- int level; /* how many tiles do we have */
- int x; /* x coord of tile */
- int y; /* x coord of tile */
- } Board_Position_Rec, *Board_Position;
-
- #define Board_Position_NULL ((Board_Position)0)
-
- Board_Position_Rec Board_Tiles[NROWS][NCOLS];
-
- #define SPEC1 0][14 /* farthest right odd tile */
- #define SPEC1row 0 /* farthest right odd tile */
- #define SPEC1col 14 /* farthest right odd tile */
- #define SPEC2 2][14 /* next farthest right odd tile */
- #define SPEC2row 2 /* next farthest right odd tile */
- #define SPEC2col 14 /* next farthest right odd tile */
- #define SPEC3 4][14 /* farthest left odd tile */
- #define SPEC3row 4 /* farthest left odd tile */
- #define SPEC3col 14 /* farthest left odd tile */
- #define SPEC4 6][14 /* center piece tile */
- #define SPEC4row 6 /* center piece tile */
- #define SPEC4col 14 /* center piece tile */
-
- /*--Index into this array using a tile number in order to get the procedure
- * that knows how to draw the face of that tile. */
-
- typedef void (*Draw_Xyz)();
-
- void Draw_Error() { fprintf( stderr, "Drew tile face 0??\n" ); return; }
-
- Draw_Xyz Faces[1+NFACES] = {
- Draw_Error,
-
- Draw_Spring, Draw_Summer, Draw_Fall, Draw_Winter,
-
- Draw_Bamboo, Draw_Mum, Draw_Orchid, Draw_Plum,
-
- Draw_GDragon, Draw_RDragon, Draw_WDragon,
-
- Draw_East, Draw_West, Draw_North, Draw_South,
-
- Draw_Bam1, Draw_Bam2, Draw_Bam3, Draw_Bam4, Draw_Bam5,
- Draw_Bam6, Draw_Bam7, Draw_Bam8, Draw_Bam9,
-
- Draw_Dot1, Draw_Dot2, Draw_Dot3, Draw_Dot4, Draw_Dot5,
- Draw_Dot6, Draw_Dot7, Draw_Dot8, Draw_Dot9,
-
- Draw_Crak1, Draw_Crak2, Draw_Crak3, Draw_Crak4, Draw_Crak5,
- Draw_Crak6, Draw_Crak7, Draw_Crak8, Draw_Crak9
- };
-
- /*--Record tile clicks and watch for double clicks. */
-
- Boolean One_Button_Hint = FALSE;
- Board_Position Click1 = Board_Position_NULL;
- int Click1_Row;
- int Click1_Col;
- Board_Position Click2 = Board_Position_NULL;
- int Click2_Row;
- int Click2_Col;
- Time Click2_Time;
-
-
- void Write_Game( file )
- FILE *file;
- /******************************************************************************
- * file - Specifies a file open for write
- *
- * Called to write out the current game context for later rereading.
- ******************************************************************************/
- {
-
- fwrite( (char*)&Score, 1, sizeof(Score), file );
- fwrite( (char*)&Board_Tiles[0][0], 1, sizeof(Board_Tiles), file );
-
- } /* Write_Game */
-
-
- void Read_Game( file )
- FILE *file;
- /******************************************************************************
- * file - Specifies a file open for reading
- *
- * Called to read in a new current game context.
- ******************************************************************************/
- {
-
- Click1 = Board_Position_NULL;
- Click2 = Board_Position_NULL;
- fread( (char*)&Score, 1, sizeof(Score), file );
- fread( (char*)&Board_Tiles[0][0], 1, sizeof(Board_Tiles), file );
-
- } /* Read_Game */
-
-
- static int Pick_Tile( Avail )
- char *Avail;
- /******************************************************************************
- * Avail - Specifies an [NTILES] array of available tiles. Unavailable
- * slots contain NO_TILE.
- *
- * Called to pick a random tile from the Available tiles.
- ******************************************************************************/
- {
- register char *t;
- register int k;
-
- /*--Pick a random starting place. */
-
- k = (int)random() % NTILES;
- t = &Avail[k];
-
- /*--Search until we find a non-NO_TILE slot. */
-
- while (*t == NO_TILE) {
- ++t;
- if (++k == NTILES) {
- t = &Avail[0];
- k = 0;
- }
- }
-
- /*--Return the tile we found and zap the slot. */
-
- k = *t;
- *t = NO_TILE;
- return k;
-
- } /* Pick_Tile */
-
-
- static void Set_Tile_Controls()
- /******************************************************************************
- * Called whenever the board has been reset or resized. We recalculate all of
- * the drawing controls for the tiles.
- ******************************************************************************/
- {
- register Board_Position bp;
- int row, col;
-
- /*--Now set up the control information for all of the tiles. The special
- * tiles are easy. */
-
- DEBUG_CALL(Set_Tile_Controls);
- if (Board_Tiles[SPEC4].level > 0) {
- Board_Tiles[SPEC4].x = Board_Tile0_X + 6 * (Tile_Width + 1)
- + (Tile_Width + 1) / 2 + 4 * Side_X;
- Board_Tiles[SPEC4].y = Board_Tile0_Y + 3 * (Tile_Height + 1)
- + (Tile_Height + 1) / 2 - 3 * Side_Y;
- }
-
- if (Board_Tiles[SPEC3].level > 0) {
- Board_Tiles[SPEC3].x = Board_Tile0_X + 0 * (Tile_Width + 1);
- Board_Tiles[SPEC3].y = Board_Tile0_Y + 3 * (Tile_Height + 1)
- + (Tile_Height + 1) / 2;
- }
-
- if (Board_Tiles[SPEC2].level > 0) {
- Board_Tiles[SPEC2].x = Board_Tile0_X + 13 * (Tile_Width+1);
- Board_Tiles[SPEC2].y = Board_Tile0_Y + 3 * (Tile_Height+1)
- + (Tile_Height + 1) / 2;
- }
-
- if (Board_Tiles[SPEC1].level > 0) {
- Board_Tiles[SPEC1].x = Board_Tile0_X + 14 * (Tile_Width+1);
- Board_Tiles[SPEC1].y = Board_Tile0_Y + 3 * (Tile_Height+1)
- + (Tile_Height + 1) / 2;
- }
-
- /*--Do the more regular tiles. */
-
- for (row = 0; row <= 7; ++row) {
- for (col = 12; col >= 1; --col) {
- bp = &Board_Tiles[row][col];
-
- /*--Skip any tiles that don't exist. */
-
- if (bp->level == 0) { continue; }
-
- /*--Set up the face x/y coordinates. */
-
- bp->x = Board_Tile0_X + col * (Tile_Width + 1);
- bp->y = Board_Tile0_Y + row * (Tile_Height + 1);
-
- }
- }
- DEBUG_RETURN(Set_Tile_Controls);
-
- } /* Set_Tile_Controls */
-
-
- static void Pick1( bp, Avail )
- register Board_Position bp;
- char *Avail;
- {
- bp->tiles[0] = Pick_Tile( Avail );
- bp->level = 1;
- }
-
- static void Pick2( bp, Avail )
- register Board_Position bp;
- char *Avail;
- {
- bp->tiles[0] = Pick_Tile( Avail );
- bp->tiles[1] = Pick_Tile( Avail );
- bp->level = 2;
- }
-
- static void Pick3( bp, Avail )
- register Board_Position bp;
- char *Avail;
- {
- bp->tiles[0] = Pick_Tile( Avail );
- bp->tiles[1] = Pick_Tile( Avail );
- bp->tiles[2] = Pick_Tile( Avail );
- bp->level = 3;
- }
-
- static void Pick4( bp, Avail )
- register Board_Position bp;
- char *Avail;
- {
- bp->tiles[0] = Pick_Tile( Avail );
- bp->tiles[1] = Pick_Tile( Avail );
- bp->tiles[2] = Pick_Tile( Avail );
- bp->tiles[3] = Pick_Tile( Avail );
- bp->level = 4;
- }
-
-
- void Setup_New_Game()
- /******************************************************************************
- * Called to generate an all-new game.
- ******************************************************************************/
- {
- register Board_Position bp;
- char Avail[NTILES];
- int row, col, i;
-
- /*--Clear the board. */
-
- DEBUG_CALL(Setup_New_Game);
- bp = &Board_Tiles[0][0];
- for (row = 0; row < NROWS; ++row) {
- for (col = 0; col < NCOLS; ++col) {
- bp->tiles[0] = NO_TILE;
- bp->tiles[1] = NO_TILE;
- bp->tiles[2] = NO_TILE;
- bp->tiles[3] = NO_TILE;
- bp->level = 0;
- }
- }
-
- /*--Mark all tiles as available. */
-
- i = 0;
- for (row = 0; row < 4; ++row) {
- Avail[i++] = row + 1;
- Avail[i++] = row + 5;
- for (col = 8; col < NFACES; ++col) {
- Avail[i++] = 1 + col % NFACES;
- }
- }
- if (i != NTILES) { fprintf( stderr, "NTILES gak!\n" ); }
-
- /*--Fill in the "odd" tile slots. */
-
- Pick1( &Board_Tiles[SPEC1], Avail );
- Pick1( &Board_Tiles[SPEC2], Avail );
- Pick1( &Board_Tiles[SPEC3], Avail );
- Pick1( &Board_Tiles[SPEC4], Avail );
-
- for (col = 1; col <= 12; ++col) {
- Pick1( &Board_Tiles[0][col], Avail );
- Pick1( &Board_Tiles[7][col], Avail );
- }
- for (row = 1; row <= 6; ++row) {
- Pick1( &Board_Tiles[row][ 3], Avail );
- Pick1( &Board_Tiles[row][10], Avail );
- }
- for (row = 2; row <= 5; ++row) {
- Pick1( &Board_Tiles[row][ 2], Avail );
- Pick1( &Board_Tiles[row][11], Avail );
- }
- for (row = 3; row <= 4; ++row) {
- Pick1( &Board_Tiles[row][ 1], Avail );
- Pick1( &Board_Tiles[row][12], Avail );
- }
-
- /*--Now do the next square at level 2. */
-
- for (col = 4; col <= 9; ++col) {
- Pick2( &Board_Tiles[1][col], Avail );
- Pick2( &Board_Tiles[6][col], Avail );
- }
- for (row = 2; row <= 5; ++row) {
- Pick2( &Board_Tiles[row][4], Avail );
- Pick2( &Board_Tiles[row][9], Avail );
- }
-
- /*--Now do the next square at level 3. */
-
- for (col = 5; col <= 8; ++col) {
- Pick3( &Board_Tiles[2][col], Avail );
- Pick3( &Board_Tiles[5][col], Avail );
- }
- for (row = 3; row <= 4; ++row) {
- Pick3( &Board_Tiles[row][5], Avail );
- Pick3( &Board_Tiles[row][8], Avail );
- }
-
- /*--Now do the final square at level 4. */
-
- for (row = 3; row <= 4; ++row) {
- for (col = 6; col <= 7; ++col) {
- Pick4( &Board_Tiles[row][col], Avail );
- }
- }
-
- /*--Now set up the control information for all of the tiles. */
-
- Set_Tile_Controls();
- Score = NTILES;
- DEBUG_RETURN(Setup_New_Game);
-
- } /* Setup_New_Game */
-
-
- /*ARGSUSED*/
- void Restart_Game( w, event, params, num_params )
- Widget w;
- XEvent *event;
- String *params;
- Cardinal *num_params;
- /******************************************************************************
- * Called when the RESTART button is pressed. Restart the game.
- ******************************************************************************/
- {
- int row;
- int col;
- register Board_Position bp;
-
- /*--Reset levels and remove hilites. */
-
- DEBUG_CALL(Restart_Game);
- Click1 = Board_Position_NULL;
- Click2 = Board_Position_NULL;
- Score = NTILES;
- bp = &Board_Tiles[0][0];
- for (row = 0; row < NROWS; ++row) {
- for (col = 0; col < NCOLS; ++bp,++col) {
- if (bp->tiles[3] != NO_TILE) { bp->level = 4; }
- else if (bp->tiles[2] != NO_TILE) { bp->level = 3; }
- else if (bp->tiles[1] != NO_TILE) { bp->level = 2; }
- else if (bp->tiles[0] != NO_TILE) { bp->level = 1; }
- else { bp->level = 0; }
- }
- }
-
- /*--Finish setting up and then redraw everything. */
-
- Set_Tile_Controls();
- XClearArea( XtDisplay(Board), XtWindow(Board), 0, 0, 0, 0, TRUE );
- DEBUG_RETURN(Restart_Game);
-
- } /* Restart_Game */
-
-
- static void Hilite_Tile( row, col )
- /******************************************************************************
- * row - Specifies the row of the tile to hilite
- * col - specifies the column of the tile to hilite
- *
- * Called to hilite a tile face.
- ******************************************************************************/
- {
- register Board_Position bp = &Board_Tiles[row][col];
- XPoint pnts[20];
- int pnti = 0;
- int x, y, w, h;
- int left, bottom, left_bottom;
-
- #define PNT(X,Y) \
- if (pnti >= XtNumber(pnts)) {fprintf(stderr,"HT pnts overflow!\n");} \
- pnts[pnti].x = X; pnts[pnti].y = Y; ++pnti
- ;
-
- /*--See if we are one of the very special tiles on top. */
-
- DEBUG_CALL(Hilite_Tile);
- if (Board_Tiles[SPEC4].level > 0) {
- if (row == 3) {
- if (col == 6) {
- x = bp->x + Side_X * 4 + 1;
- y = bp->y - Side_Y * 4 + 1;
- w = Tile_Width / 2;
- h = Tile_Height / 2;
- PNT( x, y );
- PNT( Tile_Width, 0 );
- PNT( 0, h-1 );
- PNT( -(w+1), 0 );
- PNT( 0, h+1 );
- PNT( -(w-1), 0 );
- PNT( 0, -Tile_Height );
- goto Hilite;
- } else if (col == 7) {
- x = bp->x + Side_X * 4 + 1;
- y = bp->y - Side_Y * 4 + 1;
- w = Board_Tiles[3][7].x - Board_Tiles[SPEC4].x + 3 * Side_X;
- h = Tile_Height / 2;
- PNT( x, y );
- PNT( Tile_Width, 0 );
- PNT( 0, Tile_Height );
- PNT( -w, 0 );
- PNT( 0, -(h+1) );
- PNT( -(Tile_Width-w), 0 );
- PNT( 0, -(h-1) );
- goto Hilite;
- }
- } else if (row == 4) {
- if (col == 6) {
- x = bp->x + Side_X * 4 + 1;
- y = bp->y - Side_Y * 4 + 1;
- w = Tile_Width / 2;
- h = Tile_Height / 2;
- PNT( x, y );
- PNT( w-1, 0 );
- PNT( 0, h + Side_Y );
- PNT( w+1, 0 );
- PNT( 0, h - Side_Y );
- PNT( -Tile_Width, 0 );
- PNT( 0, -Tile_Height );
- goto Hilite;
- } else if (col == 7) {
- x = bp->x + Side_X * 4 + 1;
- y = bp->y - Side_Y * 4 + 1;
- w = Board_Tiles[4][7].x - Board_Tiles[SPEC4].x + 3 * Side_X;
- h = Tile_Height / 2;
- PNT( x + Tile_Width - w, y );
- PNT( w, 0 );
- PNT( 0, Tile_Height );
- PNT( -Tile_Width, 0 );
- PNT( 0, -(h - Side_Y) );
- PNT( Tile_Width - w, 0 );
- PNT( 0, -(h + Side_Y) );
- goto Hilite;
- }
- }
- }
-
- /*--We are a normal tile that may be partially overlapped by some other
- * normal tile. */
-
- x = bp->x + Side_X * bp->level + 1;
- y = bp->y - Side_Y * bp->level + 1;
- w = Tile_Width;
- h = Tile_Height;
- if (col > 0) {
- left = Board_Tiles[row][col-1].level - bp->level;
- if (left < 0) { left = 0; }
- if (row < 7) {
- left_bottom = Board_Tiles[row+1][col-1].level - bp->level;
- if (left_bottom < 0) { left_bottom = 0; }
- } else {
- left_bottom = 0;
- }
- } else {
- left = 0;
- left_bottom = 0;
- }
- if (row < 7) {
- bottom = Board_Tiles[row+1][col].level - bp->level;
- if (bottom < 0) { bottom = 0; }
- } else {
- bottom = 0;
- }
- if (bottom > left_bottom && Tile_Width == 28) { left_bottom = bottom; }
- if (left > 0) {
- w = left * Side_X;
- } else {
- w = 0;
- }
- PNT( x + w, y );
- PNT( Tile_Width - w, 0 );
- if (bottom > 0) {
- h = bottom * Side_Y;
- } else {
- h = 0;
- }
- PNT( 0, Tile_Height - h );
- if (left_bottom <= left && left_bottom <= bottom) {
- PNT( -(Tile_Width - bottom*Side_X), 0 );
- if (left != bottom) {
- PNT( (left-bottom)*Side_X, (bottom-left)*Side_Y );
- }
- PNT( 0, -(Tile_Height - h) );
- } else if (left_bottom <= left) { /* left_bottom > bottom */
- PNT( -(Tile_Width - left_bottom*Side_X), 0 );
- if (left_bottom != left ) {
- PNT( 0, (bottom-left_bottom)*Side_Y );
- PNT( (left-left_bottom)*Side_X, (left_bottom-left)*Side_Y );
- PNT( 0, -(Tile_Height - left * Side_Y) );
- } else {
- PNT( 0, -(Tile_Height - h) );
- }
- } else if (left_bottom <= bottom) { /* left_bottom > left */
- if (left_bottom == bottom) {
- PNT( -(Tile_Width-w), 0 );
- PNT( 0, -(Tile_Height-h) );
- } else {
- PNT( -(Tile_Width - bottom * Side_X), 0 );
- PNT( (left_bottom-bottom)*Side_X, (bottom-left_bottom)*Side_Y );
- PNT( -left_bottom*Side_X, 0 );
- PNT( 0, -(Tile_Height - left_bottom * Side_Y) );
- }
- } else { /* left_bottom > bottom && left_bottom > left */
- PNT( -(Tile_Width - left_bottom * Side_X), 0 );
- PNT( 0, (bottom-left_bottom)*Side_Y );
- PNT( (left-left_bottom)*Side_X, 0 );
- PNT( 0, -(Tile_Height - left_bottom * Side_Y) );
- }
-
- /*--Now do it. */
-
- Hilite :
- XFillPolygon( XtDisplay(Board), XtWindow(Board), Xor_GC,
- pnts, (Cardinal)pnti, Convex, CoordModePrevious );
- DEBUG_RETURN(Hilite_Tile);
-
- } /* Hilite_Tile */
-
-
- static void Clear_Tile( bp, left, bottom )
- register Board_Position bp;
- int left;
- int bottom;
- /******************************************************************************
- * bp - Specifies the Board_Position to draw
- * left - Specifies the level of the tile on the left of this thile
- * bottom - Specifies the level of the tile at the bottom of this tile
- *
- * We clear (make totally white) the space occupied by the image of this tile.
- * We clear the face and the left and bottom sides. Any shadowing caused by
- * the last drawing of this tile is the responsibility of the caller.
- ******************************************************************************/
- {
- XPoint Poly[10];
- int Polyi;
-
- #undef PNT
- #define PNT(XX,YY) \
- if (Polyi >= XtNumber(Poly)){fprintf(stderr,"Tile: Poly overflow!!\n");} \
- Poly[Polyi].x = (XX); \
- Poly[Polyi].y = (YY); \
- ++Polyi
- ;
-
- /*--We will circle the tile outline clockwise. */
-
- DEBUG_CALL(Clear_Tile);
- Polyi = 0;
-
- /*--Start with the upper left corner of the tile side. This is the "bottom"
- * of that tile side if it has one. Leave x/y at the upper-left corner of the
- * tile face. */
-
- if (left >= bp->level) {
- left = bp->level;
- PNT( bp->x + Side_X * bp->level, bp->y - Side_Y * bp->level );
- } else {
- PNT( bp->x + Side_X * left, bp->y - Side_Y * left );
- PNT( Side_X * (bp->level - left), - Side_Y * (bp->level - left) );
- }
-
- /*--Cross the top and the right side of the tile. */
-
- PNT( Tile_Width + 1, 0 );
- PNT( 0, Tile_Height + 1 );
-
- /*--Now do the bottom side of the tile. */
-
- if (bottom < bp->level) {
- PNT( - Side_X * (bp->level - bottom), Side_Y * (bp->level - bottom) );
- } else {
- bottom = bp->level;
- }
- PNT( -(Tile_Width + 1), 0 );
-
- /*--Now go up the left side of the tile. */
-
- if (left != bottom) {
- PNT( Side_X * (left - bottom), - Side_Y * (left - bottom) );
- }
- PNT( 0, -(Tile_Height + 1) );
-
- /*--Do the actual clearing. */
-
- XFillPolygon( XtDisplay(Board), XtWindow(Board), Reverse_GC,
- Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
- DEBUG_RETURN(Clear_Tile);
-
- } /* Clear_Tile */
-
-
- static void Tile( row, col )
- int row;
- int col;
- /******************************************************************************
- * row - Specifies the tile to draw
- * col - Specifies the tile to draw
- *
- * Called to draw a tile. We draw the face, the sides, and the shadow.
- ******************************************************************************/
- {
- register Board_Position bp= &Board_Tiles[row][col];
- XPoint Poly[100];
- int Polyi;
- int left;
- int bottom;
- int curx;
- int cury;
- int sidex;
- int sidey;
- int i, j, k, l, m;
-
- #undef PNT
- #define PNT(XX,YY) \
- if (Polyi >= XtNumber(Poly)){fprintf(stderr,"Tile: Poly overflow!!\n");} \
- Poly[Polyi].x = (XX); \
- Poly[Polyi].y = (YY); \
- ++Polyi
- ;
-
- /*--This tile no longer needs drawing. */
-
- DEBUG_CALL(Tile);
- bp->draw = FALSE;
-
- /*--Determine the level of the tile on the left of this tile. */
-
- if (col > 0) {
- if (col == SPEC1col && row == SPEC1row) {
- left = Board_Tiles[SPEC2].level;
- } else if (col == SPEC2col && row == SPEC2row) {
- if (Board_Tiles[3][12].level == 0 ||
- Board_Tiles[4][12].level == 0) {
- left = 0;
- } else {
- left = 1;
- }
- } else {
- left = Board_Tiles[row][col-1].level;
- }
- } else {
- left = 0;
- }
-
- /*--Determine the level of the tile at the bottom of this tile. */
-
- if (row < 7) {
- bottom = Board_Tiles[row+1][col].level;
- } else {
- bottom = 0;
- }
-
- /*--Clear the area that will be covered by this tile. */
-
- Clear_Tile( bp, left, bottom );
-
- /*--Draw the tile face. */
-
- (*(Faces[bp->tiles[bp->level-1]]))( bp->x + bp->level * Side_X + 1,
- bp->y - bp->level * Side_Y + 1 );
-
- /*--Now draw the tile edges. */
-
- if (Tile_Control & BLACKSIDE) {
-
- /*--We want black/gray sides. */
-
- XDrawRectangle( XtDisplay(Board), XtWindow(Board), Normal_GC,
- bp->x + bp->level * Side_X,
- bp->y - bp->level * Side_Y,
- Tile_Width + 1, Tile_Height + 1 );
-
- if (left < bp->level) {
- Polyi = 0;
- PNT( bp->x + left * Side_X, bp->y - left * Side_Y );
- PNT( (bp->level - left) * Side_X, (left - bp->level) * Side_Y );
- PNT( 0, Tile_Height + 1 );
- PNT( (left - bp->level) * Side_X, (bp->level - left) * Side_Y );
- PNT( 0, -(Tile_Height + 1) );
- XFillPolygon( XtDisplay(Board), XtWindow(Board),
- ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
- Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
- XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
- Poly, (Cardinal)Polyi, CoordModePrevious );
- }
- if (bottom < bp->level) {
- Polyi = 0;
- PNT( bp->x + bp->level * Side_X,
- bp->y - bp->level * Side_Y + Tile_Height + 1 );
- PNT( Tile_Width + 1, 0 );
- PNT( (bottom - bp->level) * Side_X, (bp->level - bottom) * Side_Y);
- PNT( -(Tile_Width + 1), 0 );
- PNT( (bp->level - bottom) * Side_X, (bottom - bp->level) * Side_Y);
- XFillPolygon( XtDisplay(Board), XtWindow(Board),
- ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
- Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
- XDrawLines( XtDisplay(Board), XtWindow(Board), Normal_GC,
- Poly, (Cardinal)Polyi, CoordModePrevious );
- }
-
- /*--We want line'ed sides. */
-
- } else {
-
- Polyi = 0;
- if (left >= bp->level) {
- PNT( bp->x + Side_X * bp->level, bp->y - Side_Y * bp->level );
- } else {
-
- /*--First we draw the left side. We leave x/y at the bottom left corner of
- * the tile face when we are done. */
-
- #define LSEGS 7 /* keep this an odd number */
-
- sidex = Side_X * (bp->level - left);
- sidey = Side_Y * (bp->level - left);
- j = sidex;
- if (Tile_Width == 28 && bp->level - left == 1) {
- PNT( bp->x + Side_X * left, bp->y - Side_Y * left - sidey );
- PNT( 0, Tile_Height + 1 + sidey );
- k = 0;
- } else {
- PNT( bp->x + Side_X * left, bp->y - Side_Y * left );
- PNT(0, Tile_Height + 1 );
- k = sidey;
- }
- PNT( sidex, -sidey );
- i = Tile_Height / (LSEGS+1);
- m = Tile_Height - i * (LSEGS+1);
- for (l = LSEGS; l > 0; --l) {
- cury = -i;
- if (m > 0) { cury -= 1; --m; }
- PNT( 0, cury );
- PNT( -j, k );
- j = -j;
- k = -k;
- }
- PNT( 0, -i-1 );
- PNT( sidex, k );
- }
- PNT( 0, Tile_Height + 1 );
-
- /*--Draw the left edge of the tile and then draw the bottom side of the tile.
- * We leave x/y at the bottom right corner of the tile face when we are done.
- */
-
- #define RSEGS 6 /* keep this an even number */
-
- if (bottom < bp->level) {
- sidex = Side_X * (bp->level - bottom);
- sidey = Side_Y * (bp->level - bottom);
- i = Tile_Width / (RSEGS+1);
- m = Tile_Width - i * (RSEGS+1);
- if (Tile_Width == 28 && bp->level - bottom == 1) {
- j = 0;
- } else {
- j = sidex;
- }
- k = sidey;
- for (l = RSEGS; l > 0; --l) {
- curx = i;
- if (m > 0) { curx += 1; --m; }
- PNT( curx, 0 );
- PNT( -j, k );
- j = -j;
- k = -k;
- }
- PNT( i+1, 0 );
- PNT( -j, sidey );
- PNT( -(Tile_Width + 1 + sidex - j), 0 );
- PNT( sidex, -sidey );
- }
- PNT( Tile_Width + 1, 0 );
-
- /*--Draw the right side. */
-
- PNT( 0, -(Tile_Height + 1) );
-
- /*--Draw the top side. */
-
- PNT( -(Tile_Width + 1), 0 );
-
- /*--Draw all of those edges. */
-
- XDrawLines( XtDisplay(Board), XtWindow(Board),
- ((Tile_Control & GRAYSIDE) ? Gray_GC : Normal_GC),
- Poly, (Cardinal)Polyi, CoordModePrevious );
- }
-
- /*--Now draw the tile shadow. */
-
- if (Tile_Control & SHADOW) {
- int top, right;
- Boolean top_right;
-
- /*--Determine the level of the tile on the right of this tile. */
-
- if (col == SPEC1col) {
- if (row == SPEC2row) {
- right = Board_Tiles[SPEC1].level;
- } else if (row == SPEC3row) {
- right = 0;
- } else {
- right = 0;
- }
- } else {
- right = Board_Tiles[row][col+1].level;
- }
-
- /*--Determine the level of the tile at the top of this tile. */
-
- if (row > 0) {
- top = Board_Tiles[row-1][col].level;
- } else {
- top = 0;
- }
-
- /*--Do we have an upper-right tile? */
-
- if (row > 0 &&
- Board_Tiles[row-1][col+1].level >= bp->level) {
- top_right = TRUE;
- } else if (row == SPEC3row && col == SPEC3col &&
- Board_Tiles[3][1].level > 0) {
- top_right = TRUE;
- } else if (row == 4 && col == 12 &&
- Board_Tiles[SPEC2].level > 0) {
- top_right = TRUE;
- } else {
- top_right = FALSE;
- }
-
- /*--Draw the upper shadow if necessary. */
-
- if (top < bp->level) {
- Polyi = 0;
- PNT( bp->x + bp->level * Side_X - 1,
- bp->y - bp->level * Side_Y );
- PNT( Shadow_X, -Shadow_Y );
- if (top_right) {
- i = Shadow_X;
- } else {
- i = 0;
- }
- PNT( Tile_Width + 3 - i, 0 );
- PNT( -(Shadow_X - i), Shadow_Y );
- PNT( -(Tile_Width + 3), 0 );
- XFillPolygon( XtDisplay(Board), XtWindow(Board), Over_GC,
- Poly, (Cardinal)Polyi, Convex, CoordModePrevious );
- }
-
- /*--Now work on the right shadow. It may need to be drawn in pieces. */
-
- Polyi = 0;
-
- /*--If SPEC3 has both neighbors then don't draw the right shadow. */
-
- if (row == SPEC3row && col == SPEC3col) {
- if (Board_Tiles[3][1].level > 0) {
- if (Board_Tiles[4][1].level > 0) {
- right = bp->level;
-
- /*--If SPEC3 has only the upper neighbor then draw just the lower shadow. */
-
- } else {
- i = bp->y - Board_Tiles[3][1].y;
- PNT( Board_Tiles[4][1].x + Side_X, Board_Tiles[4][1].y );
- PNT( Shadow_X, 0 );
- PNT( 0, i - Shadow_Y);
- PNT( -Shadow_X, Shadow_Y );
- PNT( 0, -i );
- right = bp->level;
- }
-
- /*--If SPEC3 has only the lower neighbor then draw just the upper shadow. */
-
- } else if (Board_Tiles[4][1].level > 0) {
- i = Board_Tiles[4][1].y - bp->y;
- PNT( bp->x + bp->level * Side_X + Tile_Width + 1 + 1,
- bp->y - bp->level * Side_Y );
- PNT( Shadow_X, -Shadow_Y );
- PNT( 0, i + Shadow_Y );
- PNT( -Shadow_X, 0 );
-