[comp.windows.x] Dragon

tml@hemuli (Tor Lillqvist) (05/04/89)

I have installed ``dragon'' that recently appeared in comp.sources.x
on an HP9000/840, displaying on an HP9000/318 running HP's product X11
server.  The 318 is monochrome, but has window depth 8.  The following patch
was necessary to get dragon running:


*** orig/main.c	Tue May  2 17:35:29 1989
--- main.c	Tue May  2 17:57:11 1989
***************
*** 169,176 ****
  {
      XImage ximage;
      Pixmap pix;
  
!     pix = XCreatePixmap( display, d, width, height, 1 );
      if (pix == (Pixmap)0) return (Pixmap)0;
  
      ximage.height = height;
--- 169,179 ----
  {
      XImage ximage;
      Pixmap pix;
+     XWindowAttributes wa;
+     
+     if (XGetWindowAttributes( display, d, &wa) == 0) return (Pixmap)0;
  
!     pix = XCreatePixmap( display, d, width, height, wa.depth );
      if (pix == (Pixmap)0) return (Pixmap)0;
  
      ximage.height = height;


However, there is still something wrong.  From reading the code, I
assume that the program should hilight selected tiles by calling
XFillPolygon with Xor_GC.  I don't get any hilight...  Also, I don't
get any numbers in the corners of the bam, dot or crak tiles.  The
other texts are visible.

An then, the game seems too simple... I mean, more or less randomly
selecting tiles to remove with no strategy I ``win'' every time.

Any clues?

Tor Lillqvist
Technical Research Centre of Finland, Computing Services (VTT/ATK)
tml%hemuli.uucp@santra.hut.fi

dougl@ism780c.isc.com (Doug Leavitt) (05/05/89)

In article <8905031837.AA07741@hemuli.atk.vtt.fi> tml@hemuli (Tor Lillqvist) writes:
....
>An then, the game seems too simple... I mean, more or less randomly
>selecting tiles to remove with no strategy I ``win'' every time.
>
>Any clues?

I too brought up the game today and noticed the same problems.
Having had some experience in playing Mah-Jongg at home (on my amiga),
I think I can shed some light on what's going on.  The code that
checks for legal tile removal seems to be broken.  The main problem
as I see it is that the program currently allows the second chosen
tile to always be moved even when it is located in an illegal position.

I currently do not know how often the code will fail, but I was able to
remove a Crak and a bamboo at the same time.  Something that is definitely
illegal in the game.  I was also able to pull pieces out from the center
of the playing field.

If I can solve the problems before the author can make the appropriate
bug fixes, I'll pass them along.  If we can get the nit's cleaned up,
I'm sure the game could be at least as addicting as xconq...

		Doug Leavitt
		Interactive Systems Corp.
		dougl@ism780c.isc.com

nobody@tekecs.GWD.TEK.COM (-for inetd server command) (05/05/89)

In article <8905031837.AA07741@hemuli.atk.vtt.fi> tml@hemuli (Tor Lillqvist) writes:
>I have installed ``dragon'' that recently appeared in comp.sources.x
>on an HP9000/840, displaying on an HP9000/318 running HP's product X11
>server.  The 318 is monochrome, but has window depth 8.  The following patch
>was necessary to get dragon running:
		...
>However, there is still something wrong.  From reading the code, I
>assume that the program should hilight selected tiles by calling
>XFillPolygon with Xor_GC.  I don't get any hilight...  Also, I don't
>get any numbers in the corners of the bam, dot or crak tiles.  The
>other texts are visible.
		...
>Any clues?
>
>Tor Lillqvist
>Technical Research Centre of Finland, Computing Services (VTT/ATK)
>tml%hemuli.uucp@santra.hut.fi

I had the same problems with my Tektronix 4319 (color, depth 8).  The dragon
program as posted assumes that DefaultWhitePixel is 0 and DefaultBlackPixel
is something nonzero (e.g. 1).  In order to reverse a tile, it draws over it
in foreground (black) with XOR.  In order to overlay a tile's shadow on
another image, it draws over it in black with OR.  Both of these operations
fail on machines like mine where DefaultBlackPixel is 0 and DefaultWhitePixel
is 1.

To fix this, change Xor_GC to:
	foreground = black ^ white;	/* toggle bits that are different */
	background = 0;			/* leave the rest alone */
	mode = xor;

and change Over_GC to:
	foreground = black;
	background = white;
	stipple = shadow bitmap;
	mode = copy + stipple;

There's also a bug in tile.c, which attempts to draw the corner numbers using
Over_GC instead of Normal_GC.  The diffs here fix both sets of problems
and include Tor's fix for the background pixmap depth.

Now, does anyone have a fix for the intermittent core dumps in Remove_Tile
with Click2 == NULL?  I worked around them by rewriting the multiple-click
code in Tile_Press and Touch_Tile, but there must be a simpler explanation.

Steve Tarr
Tektronix, Inc.
stevet@hammer.WV.TEK.COM

=========== cut here for context diffs ==========

*** tile_old.c	Thu May  4 18:15:10 1989
--- tile.c	Thu May  4 18:16:17 1989
***************
*** 201,207 ****
  * Called to draw the number in the upper right corner of a numbered tile.
  ******************************************************************************/
  {
!     XPutImage( XtDisplay(Board), XtWindow(Board), Over_GC, image,
  	       0, 0, x + Number_X, y + Number_Y,
  	       (unsigned int)image->width, (unsigned int)image->height );
  } /* Draw_Number */
--- 201,207 ----
  * Called to draw the number in the upper right corner of a numbered tile.
  ******************************************************************************/
  {
!     XPutImage( XtDisplay(Board), XtWindow(Board), Normal_GC, image,
  	       0, 0, x + Number_X, y + Number_Y,
  	       (unsigned int)image->width, (unsigned int)image->height );
  } /* Draw_Number */
***************
*** 755,758 ****
--- 755,759 ----
      Draw_Image( &crak, x, y );
      Draw_Number( &nine, x, y );
  } /* Draw_Crak9 */
+ 
  

*** main_old.c	Thu May  4 17:45:17 1989
--- main.c	Thu May  4 17:42:44 1989
***************
*** 162,183 ****
       Drawable	     d;
       char	    *data;
       unsigned int    width, height;
  /******************************************************************************
  * Converted form of XCreatePixmapFromBitmapData.  Use our GC and don't bother
  * the Server for another one.
  ******************************************************************************/
  {
      XImage ximage;
      Pixmap pix;
  
!     pix = XCreatePixmap( display, d, width, height, 1 );
      if (pix == (Pixmap)0) return (Pixmap)0;
  
      ximage.height = height;
      ximage.width = width;
      ximage.depth = 1;
      ximage.xoffset = 0;
      ximage.format = XYBitmap;
      ximage.data = data;
      ximage.byte_order = LSBFirst;
      ximage.bitmap_unit = 8;
--- 162,186 ----
       Drawable	     d;
       char	    *data;
       unsigned int    width, height;
  /******************************************************************************
  * Converted form of XCreatePixmapFromBitmapData.  Use our GC and don't bother
  * the Server for another one.
  ******************************************************************************/
  {
      XImage ximage;
      Pixmap pix;
+     XWindowAttributes wa;
  
!     if (XGetWindowAttributes( display, d, &wa ) == 0) return (Pixmap)0;
! 
!     pix = XCreatePixmap( display, d, width, height, wa.depth );
      if (pix == (Pixmap)0) return (Pixmap)0;
  
      ximage.height = height;
      ximage.width = width;
      ximage.depth = 1;
      ximage.xoffset = 0;
      ximage.format = XYBitmap;
      ximage.data = data;
      ximage.byte_order = LSBFirst;
      ximage.bitmap_unit = 8;
***************
*** 189,268 ****
      return pix;
  } /* XCreateTile */
  
  
  static void GC_Setup()
  /******************************************************************************
  * Set up the GC's that we will be using for drawing.
  ******************************************************************************/
  {
      XGCValues	gcv;
!     Pixel	pix;
  
! /*--Xor_GC - fg = black, bg = white, func = xor */
  
!     gcv.function = GXxor;
!     gcv.foreground = BlackPixelOfScreen(XtScreen(Dragon));
!     gcv.background = WhitePixelOfScreen(XtScreen(Dragon));
!     Xor_GC = XtGetGC( Dragon,
! 		      GCFunction|GCForeground|GCBackground,
! 		      &gcv );
  
  /*--Normal_GC - fg = black, bg = white, func = copy */
  
-     gcv.function = GXcopy;
      if (Dragon_Resources.Reverse_Video) {
! 	gcv.background = BlackPixelOfScreen(XtScreen(Dragon));
! 	gcv.foreground = WhitePixelOfScreen(XtScreen(Dragon));
      }
!     Normal_GC = XtGetGC( Dragon, GCFunction|GCForeground|GCBackground, &gcv );
  
  /*--Gray_GC - fg = black, bg = white, func = copy, tile = Gray */
  
      gcv.tile = XCreateTile( XtDisplay(Board), XtWindow(Board),
  			    gray_bits, gray_width, gray_height );
      if (gcv.tile == None) {
  	fprintf( stderr, "Can't allocate gray pixmap.\n" );
  	exit(1);
      }
      gcv.fill_style = FillTiled;
      Gray_GC = XtGetGC( Dragon,
! 		       GCFunction|GCForeground|GCBackground|GCTile|GCFillStyle,
  		       &gcv );
  
! /*--Over_GC - fg = black, bg = white, func = or */
  
!     if (Dragon_Resources.Reverse_Video) {
! 	gcv.function = GXand;
!     } else {
! 	gcv.function = GXor;
!     }
!     gcv.tile =
!       XCreateTile( XtDisplay(Board), XtWindow(Board),
  		   shadow_bits, shadow_width, shadow_height );
!     if (gcv.tile == None) {
! 	fprintf( stderr, "Can't allocate shadow pixmap.\n" );
  	exit(1);
      }
!     gcv.fill_style = FillTiled;
      Over_GC = XtGetGC( Dragon,
! 		       GCFunction|GCForeground|GCBackground|GCTile|GCFillStyle,
  		       &gcv );
  
! /*--Reverse_GC - fg = white, bg = black, func = copy */
  
      gcv.function = GXcopy;
!     pix = gcv.background;
!     gcv.background = gcv.foreground;
!     gcv.foreground = pix;
!     Reverse_GC = XtGetGC( Dragon, GCFunction|GCForeground|GCBackground, &gcv );
  
  } /* GC_Setup */
  
  
  int main (argc, argv)
       int	 argc;
       String	*argv;
  /******************************************************************************
  * Our Main-Line Code.
  ******************************************************************************/
  {
--- 192,287 ----
      return pix;
  } /* XCreateTile */
  
  
  static void GC_Setup()
  /******************************************************************************
  * Set up the GC's that we will be using for drawing.
  ******************************************************************************/
  {
      XGCValues	gcv;
!    Pixel	black, white;
  
! /* The drawing code used to assume black == 1, white == 0.
!    It should now work on other systems. */
  
!     black = BlackPixelOfScreen(XtScreen(Dragon));
!     white = WhitePixelOfScreen(XtScreen(Dragon));
  
  /*--Normal_GC - fg = black, bg = white, func = copy */
  
      if (Dragon_Resources.Reverse_Video) {
! 	gcv.background = black;
! 	gcv.foreground = white;
!     } else {
! 	gcv.foreground = black;
! 	gcv.background = white;
      }
!     gcv.function = GXcopy;
!     Normal_GC = XtGetGC( Dragon,
! 			 GCFunction|GCForeground|GCBackground,
! 			 &gcv );
  
  /*--Gray_GC - fg = black, bg = white, func = copy, tile = Gray */
  
      gcv.tile = XCreateTile( XtDisplay(Board), XtWindow(Board),
  			    gray_bits, gray_width, gray_height );
      if (gcv.tile == None) {
  	fprintf( stderr, "Can't allocate gray pixmap.\n" );
  	exit(1);
      }
      gcv.fill_style = FillTiled;
      Gray_GC = XtGetGC( Dragon,
! 		       GCFunction|GCForeground|GCBackground|
! 			 GCTile|GCFillStyle,
  		       &gcv );
  
! /*--Over_GC - fg = black, bg = white, func = copy, stipple = Shadow */
  
!     gcv.stipple =
!       XCreateBitmapFromData( XtDisplay(Board), XtWindow(Board),
  		   shadow_bits, shadow_width, shadow_height );
!     if (gcv.stipple == None) {
! 	fprintf( stderr, "Can't allocate shadow bitmap.\n" );
  	exit(1);
      }
!     gcv.fill_style = FillStippled;
      Over_GC = XtGetGC( Dragon,
! 		       GCFunction|GCForeground|GCBackground|
! 			 GCStipple|GCFillStyle,
  		       &gcv );
  
! /*--Reverse_GC - fg = white, bg = black, func = copy
!     (used with XFillRect for erase) */
  
+     if (Dragon_Resources.Reverse_Video) {
+ 	gcv.foreground = black;
+ 	gcv.background = white;
+     } else {
+ 	gcv.background = black;
+ 	gcv.foreground = white;
+     }
      gcv.function = GXcopy;
!     Reverse_GC = XtGetGC( Dragon,
! 			  GCFunction|GCForeground|GCBackground,
! 			  &gcv );
  
+ /*--Xor_GC - fg = black ^ white, bg = 0, func = xor
+     (used with XFillPoly to invert area) */
+ 
+     gcv.foreground = black ^ white;
+     gcv.background = (Pixel) 0;
+     gcv.function = GXxor;
+     Xor_GC = XtGetGC( Dragon,
+ 		      GCFunction|GCForeground|GCBackground,
+ 		      &gcv );
+ 
  } /* GC_Setup */
  
  
  int main (argc, argv)
       int	 argc;
       String	*argv;
  /******************************************************************************
  * Our Main-Line Code.
  ******************************************************************************/
  {
***************
*** 369,388 ****
--- 388,408 ----
  
      {	Pixmap	pix;
  	pix = XCreateTile( XtDisplay(Board), XtWindow(Board),
  			   background_bits, background_width,
  			   background_height);
  	if (pix == None) {
  	    fprintf( stderr, "Can't allocate background pixmap.\n" );
  	    exit(1);
  	}
  	XSetWindowBackgroundPixmap( XtDisplay(Board), XtWindow(Board), pix );
+ 	XClearWindow( XtDisplay(Board), XtWindow(Board) );
      }
  
  /*--Now do the real thing. */
  
      DEBUG_OTHER(main,XtMainLoop);
      XtMainLoop();
  
  } /* main */
  
  #if 0

myoung@b11.ingr.com (Mark Young) (05/10/89)

in article <8905031837.AA07741@hemuli.atk.vtt.fi>, tml@hemuli (Tor Lillqvist) says:
> However, there is still something wrong.  From reading the code, I
> assume that the program should hilight selected tiles by calling
> XFillPolygon with Xor_GC.  I don't get any hilight...  Also, I don't
> get any numbers in the corners of the bam, dot or crak tiles.  The
> other texts are visible.

We had the same problem.  If I remember correctly (since I'm too busy to
go chase this down) it had something to do with the GC named "Over_GC".
I believe that the programmer made an assumption on the values of
Whitepixel and Blackpixel when he set the gc function.  I think that 
you can hack it by reversing the functions.  I didn't spend the time
to consider a more proper fix.

> An then, the game seems too simple... I mean, more or less randomly
> selecting tiles to remove with no strategy I ``win'' every time.

I just thought I didn't understand the rules.  and those that I did
understand didn't seem to be enforced to harshly.

	...m (myoung@ingr.com or uunet!ingr!myoung) young