1 //
2 // XMover: Modul zur Optimierten Ball-Darstellung unter XWindows
3 // - flackerfreies Bewegen der B�lle durch Hilfspixmaps
4 // - Beleuchtungseffekt durch Raytracing-Bitmaps
5 // - Darstellung halber Kugeln durch vorberechnete Pixmaps
6 //
7 
8 #ifndef _vec3_h
9 #	include "vec3.h"
10 #endif
11 
12 #define	LEFT_RIGHT_OPT
13 #define	USE_STUFFER
14 
15 /*----------------------------------------------------------------------------*/
16 
PixmapCache()17 PixmapCache::PixmapCache() {
18 	count = 0;
19 }
20 
~PixmapCache()21 PixmapCache::~PixmapCache() {
22 }
23 
Lock(int id_in,int size_in)24 Pixmap PixmapCache::Lock( int id_in, int size_in ) {
25 	for (int i=0;i<count;i++) {
26 		if (id_in==id[i]&&size_in==size[i]) {
27 			lockcount[i]++;
28 			return pmap[i];
29 		}
30 	}
31 	return 0;
32 }
33 
Unlock(Display * dpy,Pixmap pix)34 void PixmapCache::Unlock( Display *dpy, Pixmap pix ) {
35 //
36 // free the given pixmap, if nobody else will use it.
37 //
38 	for (int i=0;i<count;i++) {
39 		if (pix==pmap[i]) {
40 			if (--lockcount[i]==0) {
41 				XFreePixmap(dpy,pix);
42 				count--;
43 				while( i<count ) {
44 					pmap[i]      = pmap[i+1];
45 					size[i]      = size[i+1];
46 					id[i]        = id[i+1];
47 					lockcount[i] = lockcount[i+1];
48 					i++;
49 				}
50 			}
51 			return;
52 		}
53 	}
54 }
55 
InsertAndLock(Display *,Pixmap pix,int id_in,int size_in)56 void PixmapCache::InsertAndLock( Display * /*dpy*/, Pixmap pix, int id_in, int size_in ) {
57 	if (Lock(id_in,size_in)) {
58 		fprintf(stderr,"internal error 1 in PixmapCache::InsertAndLock\n" );
59 		return;
60 	}
61 	if (count>=PCACHE_MAX) {
62 		fprintf(stderr,"internal error 2 in PixmapCache::InsertAndLock\n" );
63 		return;
64 	}
65 	pmap[count]      = pix;
66 	size[count]      = size_in;
67 	id[count]        = id_in;
68 	lockcount[count] = 1;
69 	count++;
70 }
71 
72 PixmapCache PixmapCache::pcache;
73 
74 /*----------------------------------------------------------------------------*/
75 
76 //
77 // Klasse zur Komprimierung der RingState-Felder
78 //
79 class Stuffer {
80 	public:
Stuffer()81 		Stuffer() : ws(0), wl(sizeof(RingState))			{}
82 
Init(int ws_in,int wl_in)83 		void Init( int ws_in, int wl_in ) {
84 				ws = ws_in;
85 				if (wl!=wl_in) {
86 					printf( "ERROR: Stuffer used with illegal input size !\n" );
87 					exit(0);
88 				}
89 		}
90 		void Shrink( RingState *addr, int len );
91 		void Expand( RingState *addr, int len );
SSize(int len)92 		int  SSize( int len )
93 #ifdef USE_STUFFER
94 		{		return ((len*ws+7)/8);	}
95 #else
96 		{		return ((len*wl+7)/8);	}
97 #endif
LSize(int len)98 		int  LSize( int len )
99 		{		return ((len*wl+7)/8);	}
100 
101 	private:
102 		int	ws;	// Bits klein
103 		const int	wl;	// Bits gross
104 		static int mtab[9];
105 };
106 
107 int Stuffer::mtab[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
108 
109 #ifdef USE_STUFFER
Shrink(RingState * addr,int len)110 void Stuffer::Shrink( RingState *addr, int len ) {
111 RingState		*r_p;
112 RingState		r_val;
113 int				r_len;
114 unsigned char	*w_p;
115 unsigned char	w_val;
116 int	w_space;
117 
118 	r_p     = addr;
119 	w_p     = (unsigned char*)addr;
120 	w_space = 8;
121 	w_val   = 0;
122 	while( len-- ) {
123 		r_val = *r_p++;
124 		r_len = ws;
125 
126 		while (r_len>=w_space) {
127 			w_val  |= ((unsigned char)r_val)&mtab[w_space];
128 			*w_p++  = w_val;
129 			w_val   = 0;
130 			r_val >>= w_space;
131 			r_len  -= w_space;
132 			w_space = 8;
133 		}
134 
135 		if (r_len) {
136 			w_val   |= (((unsigned char)r_val)&mtab[w_space])<<(w_space-r_len);
137 			w_space -= r_len;
138 		}
139 	}
140 	*w_p++ = w_val;
141 }
142 
Expand(RingState * addr,int len)143 void Stuffer::Expand( RingState *addr, int len ) {
144 RingState	*w_p;						// Schreibzeiger - expandiertes Ende
145 RingState	w_val;
146 int	w_space;							// fehlende Bits zum Gesamtwort
147 unsigned char	*r_p;					// Lesezeiger - komprimiertes Ende
148 unsigned char	r_val;				// gueltige Bits
149 int	r_len;							// Zahl gueltige Bits an Lesezeigerposition
150 
151 	r_p     = (unsigned char*)addr + len*ws/8;		// Adresse des letzten Byte
152 	r_len   = (len*ws)%8;			// g�ltige Bits im letzen Byte
153 	if (r_len)	r_val = *r_p;		// letzte Bits holen
154 	else {		r_val = *--r_p;
155 					r_len = 8;
156 	}
157 	w_p     = addr + len;
158 
159 	while( len-- ) {
160 		w_space = ws;
161 		w_val   =  0;
162 		while( r_len<=w_space ) {
163 			w_val <<= r_len;
164 			w_val  |= r_val>>(8-r_len);
165 			w_space-= r_len;
166 			r_val   = *--r_p;			// ABR: liest 1 Byte ueber die Untergrenze
167 			r_len   = 8;
168 		}
169 		if (w_space) {
170 			w_val   <<= w_space;
171 			w_val    |= r_val&mtab[w_space];
172 			r_len    -= w_space;
173 		}
174 		*--w_p  = w_val;
175 	}
176 }
177 
178 #else
Shrink(RingState *,int)179 void Stuffer::Shrink( RingState *, int ) {}
Expand(RingState *,int)180 void Stuffer::Expand( RingState *, int ) {}
181 #endif
182 
183 /*----------------------------------------------------------------------------*/
184 
185 class Bitmap {
186 public:
Clear()187 	void Clear()	{	memset( bits, 0, bytes_per_line*height ); }
188 
Init(int w,int h,char * bmap)189 	void Init( int w, int h, char *bmap ) {
190 		width				= w;
191 		bytes_per_line = (width+7)/8;
192 		height 			= h;
193 		bits 				= bmap;
194 	}
Bitmap(int w,int h,char * bmap)195 	Bitmap( int w, int h, char *bmap )	{ Init(w,h,bmap); }
Bitmap()196 	Bitmap()										{}
197 
GetPixel(int x,int y)198 	int GetPixel( int x, int y ) {
199 		if ((x<0)||(x>=width)||(y<0)||(y>=height))		return 0;
200 		else {
201 			unsigned char mask = 1<<(x&7);
202 			return (bits[bytes_per_line*y+(x>>3)]&mask)?1:0;
203 		}
204 	}
SetPixel(int x,int y)205 	void SetPixel( int x, int y ) {
206 		unsigned char mask = 1<<(x&7);
207 		bits[bytes_per_line*y+(x>>3)] |= mask;
208 	}
ClrPixel(int x,int y)209 	void ClrPixel( int x, int y ) {
210 		unsigned char mask = 1<<(x&7);
211 		bits[bytes_per_line*y+(x>>3)] &= ~mask;
212 	}
213 
214 
Create()215 	Pixmap Create() {
216 		return XCreatePixmapFromBitmapData(dpy,win,bits,width,height,1,0,1 );
217 	}
218 	void Print();
219 
220 	int	width;
221 	int	height;
222 protected:
223 	int	bytes_per_line;
224 	char *bits;
225 };
226 
227 class LocBitmap : public Bitmap {
228 public:
Init(int w,int h)229 	void Init( int w, int h ) {
230 		Bitmap::Init(w,h,0);
231 		bits 				= new char[bytes_per_line*height];
232 		Clear();
233 	}
Init(int w,int h,FILE * fp)234 	void Init( int w, int h,  FILE *fp ) {
235 		Bitmap::Init(w,h,0);
236 		bits 				= new char[bytes_per_line*height];
237 		fread(bits,sizeof(char),bytes_per_line*height,fp);
238 	}
Write(FILE * fp)239 	void Write( FILE *fp ) {
240 		fwrite(bits,sizeof(char),bytes_per_line*height,fp);
241 	}
LocBitmap(int w,int h)242 	LocBitmap( int w, int h )		{ Init(w,h); }
243 
LocBitmap()244 	LocBitmap()		{}
~LocBitmap()245 	~LocBitmap()		{ delete bits; }
246 
247 	// change for a sun sparc-station runing 4.1.3 that thinks:
248 	// xmover.c:463: no non-hidden member function 'LocBitmap::create' defined
Create()249 	Pixmap Create() { return Bitmap::Create(); }
250 };
251 
252 
Print()253 void Bitmap::Print() {
254 	for(int y=0;y<height;y++) {
255 		for(int x=0;x<width;x++)	printf( "%d", GetPixel(x,y) );
256 		printf( "\n" );
257 	}
258 }
259 
260 /*----------------------------------------------------------------------------*/
261 
262 #ifdef STATISTICS
263 unsigned long	BallMover::moves = 0l;
264 #endif
265 
BallMover(const Real & r_in)266 BallMover::BallMover( const Real &r_in ) {
267 	r = (int)(r_in*w2n);	// Radius als Member festhalten
268 	d = 2*r;					// Bem: Durchmesser immer gerade
269 
270 	bpix = help = 0;
271 }
272 
273 
~BallMover()274 BallMover::~BallMover() {
275 	if (help)	XFreePixmap( dpy, help );
276 	if (bpix)	XFreePixmap( dpy, bpix );
277 }
278 
279 
Init()280 void BallMover::Init() {
281 LocBitmap	*bit;			// Kugelbitmap
282 int		x,y;
283 double	dr=r-0.5;		// tats�chlicher (Welt-)Radius
284 
285 	bit = new LocBitmap( d, d );
286 	max_rad  = r-0.25+EPS;
287 	max_rad2 = max_rad * max_rad;
288 	for (y=0;y<d;y++) {
289 		for (x=0;x<d;x++) {
290 			double dx = x-dr;								// X-Abstand zur Kreismitte
291 			double dy = y-dr;								// Y-Abstand zur Kreismitte
292 			double dist2 = dx*dx + dy*dy;
293 			if (dist2<max_rad2) {
294 				bit->SetPixel(x,y);
295 			}
296 		}
297 	}
298 
299 	bpix = bit->Create();
300 
301 	d_help	= 2*d-1;
302 	help		= XCreatePixmap(dpy,win,d_help,d_help,DefaultDepth(dpy,0));
303 
304 	delete bit;
305 }
306 
DrawBallAt(int x,int y,int col_x)307 void BallMover::DrawBallAt( int x, int y, int col_x )
308 {
309 #ifndef NODRAW
310 	XFillRectangle(dpy,help,gc_bclear,0,0,d,d);
311 	XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,0,0,1);
312 	Pixmap	shadow = GetShadowMap(x,y);
313 	if (shadow)	XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,0,0,1);
314 	XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
315 #endif
316 }
317 
318 
MoveBallOnScreen(int oldx,int oldy,int newx,int newy,int col_x)319 void BallMover::MoveBallOnScreen( int oldx, int oldy, int newx, int newy, int col_x ) {
320 
321 int	dx = newx-oldx;
322 int	dy = newy-oldy;
323 int absx = (dx>0)?dx:-dx;
324 int absy = (dy>0)?dy:-dy;
325 
326 #ifndef NODRAW
327 	if ( (absx<d_help-d) && (absy<d_help-d) ) {
328 		Pixmap	shadow;
329 
330 		int	width = d+absx;		// tats�chlicher Ausschnittgr��e der Pixmap
331 		int	height= d+absy;
332 		int	ox = (dx>0)?0:absx;	// relativer Abstand alte Position
333 		int	oy = (dy>0)?0:absy;
334 		int	nx = (dx>0)?absx:0;	// relativer Abstand neue Position
335 		int	ny = (dy>0)?absy:0;
336 
337 		XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
338 
339 		XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,ox,oy,1);
340 		shadow = GetShadowMap(oldx,oldy);
341 		if (shadow)	XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,ox,oy,1);
342 
343 		XCopyPlane(dpy,bpix,help,gc_ball[col_x],0,0,d,d,nx,ny,1);
344 		shadow = GetShadowMap(newx,newy);
345 		if (shadow)	XCopyPlane(dpy,shadow,help,gc_lay2,0,0,d,d,nx,ny,1);
346 
347 		XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
348 	}
349 	else {
350 		DrawBallAt(oldx,oldy,col_x);
351 		DrawBallAt(newx,newy,col_x);
352 	}
353 #endif
354 
355 #ifdef STATISTICS
356 	moves++;
357 #endif
358 }
359 
GetShadowMap(int,int)360 Pixmap BallMover::GetShadowMap( int /*x*/, int /*y*/ )		{ return 0; }
361 
362 // -------------------------------------------------------------------------
363 
DiscMover(const Real & r)364 DiscMover::DiscMover( const Real &r ) :
365 	BallMover( r )
366 {
367 	lpix = 0;
368 }
369 
~DiscMover()370 DiscMover::~DiscMover()
371 {
372 	if (lpix)	XFreePixmap(dpy,lpix);
373 }
374 
Init()375 void DiscMover::Init() {
376 LocBitmap	*lbit;		// Kreisbitmap
377 int		x,y;
378 double	dr=r-0.5;		// tats�chlicher (Welt-)Radius
379 
380 	BallMover::Init();
381 
382 	lbit	= new LocBitmap( d, d );
383 double	shade_rad	= 1.2;			// Pixelbreite in WS-umgerechnet
384 double	inner1		= r*1/4;
385 double	inner2		= r*2/4;
386 
387 	for (y=0;y<d;y++) {
388 		for (x=0;x<d;x++) {
389 			double dx = x-dr;								// X-Abstand zur Kreismitte
390 			double dy = y-dr;								// Y-Abstand zur Kreismitte
391 			double dist = sqrt(dx*dx + dy*dy);
392 			if (dist<max_rad) {
393 				if (  (dist>max_rad-shade_rad)
394 					|| (dist>inner1-shade_rad)&&(dist<inner1)
395 					|| (dist>inner2-shade_rad)&&(dist<inner2) ) {
396 					lbit->SetPixel(x,y);
397 				}
398 			}
399 		}
400 	}
401 
402 	lpix = lbit->Create();
403 	delete lbit;
404 }
405 
GetShadowMap(int,int)406 Pixmap DiscMover::GetShadowMap( int /*x*/, int /*y*/ )		{ return lpix; }
407 
408 // -------------------------------------------------------------------------
409 
ShadedBallMover(const Real & r)410 ShadedBallMover::ShadedBallMover( const Real &r ) :
411 	BallMover( r )
412 {
413 	lpix=0;
414 }
415 
~ShadedBallMover()416 ShadedBallMover::~ShadedBallMover()
417 {
418 	if (lpix) {
419 		for (int i=0;i<lpixs_all;i++) {
420 			XFreePixmap( dpy, lpix[i] );
421 		}
422 		delete [] lpix;
423 		lpix = 0;
424 	}
425 }
426 
427 #if (0)
428 const	double circ_x	=  -50.0;
429 const	double circ_y	=  -50.0;
430 const	double circ_r1 =  150.0;
431 const	double circ_r2 =  300.0;
432 #endif
433 
434 
Init()435 void ShadedBallMover::Init() {
436 int			x,y,i;
437 
438 LocBitmap	*lbit;	// Feld der Hilfbitmaps
439 
440 double	dr=r-0.5;		// tats�chlicher (Welt-)Radius
441 
442 int		ncircs;			// number of lamps
443 double	circ_z;			// hight of lamps
444 struct lightdata {
445 	double	x,y;			// position of lamps
446 	double	r1, r2;		// size (inner/outer) of lamps
447 }			circ[3];
448 
449 	BallMover::Init();
450 
451 	if (light_flag) {
452 		lpixs_x = 24;     							// Zahl der Bitmaps in X-Richtung
453 		lpixs_y = 12;									// Zahl der Bitmaps in Y-Richtung
454 	}
455 	else {
456 		lpixs_x = 0;
457 		lpixs_y = 0;
458 	}
459 	lpixs_all = lpixs_x * lpixs_y;			// Gesamtzahl
460 	distx = max_x / lpixs_x;					// Weltkoordinatenraster X
461 	disty = max_y / lpixs_y;					// Weltkoordinatenraster Y
462 	lbit = new LocBitmap[lpixs_all];			// Anlegen der Bitmaps
463 	for (i=0;i<lpixs_all;i++) 	lbit[i].Init(d,d);
464 
465 	if (light_flag<=1) {
466 		ncircs = 1;								// single light, far far away
467 		circ_z = 2000.0;
468 		circ[0].x= -50.0; circ[0].y= -50.0; circ[0].r1= 150.0; circ[0].r2 = 300.0;
469 	}
470 	else {
471 		ncircs = 3;
472 		circ_z = MaxX() * 2.0 / 3.0;		// einfach 'mal so angenommen
473 		for (int l=0;l<ncircs;l++) {
474 			circ[l].x  = MaxX() * (double)(l+1) / 4.0;
475 			circ[l].y  = MaxY() /  2.0;
476 			circ[l].r1 = MaxX() / 16.0;
477 			circ[l].r2 = MaxX() /  8.0;
478 		}
479 	}
480 
481 
482 	DBG1( UnixTrace, "Starting image processing with ball size %d pixel:\n", d );
483 	DBG1( UnixTrace, "BitmapData: >%d bytes\n", (d+7)/8*d*lpixs_all );
484 
485 	for (y=0;y<d;y++) {							// F�r alle Punkte der Bitmaps
486 		for (x=0;x<d;x++) {
487 			double dx = x-dr;								// X-Abstand zur Kreismitte
488 			double dy = y-dr;								// Y-Abstand zur Kreismitte
489 			double dist2 = dx*dx + dy*dy;
490 			if (dist2<max_rad2) {
491 
492 				double dz = dr*dr-dist2;				// quadratischer Z-Abstand
493 				if (dz>=0) {
494 					double f = circ_z/sqrt(dz);		// Multiplikator zur Decke
495 					dx *= f;									//	XPos an Decke
496 					dy *= f;									// YPos an Decke
497 
498 					for (int px=0;px<lpixs_x;px++) {	// f�r alle Bitmaps
499 						for (int py=0;py<lpixs_y;py++) {
500 							int	lflag=0;		// 0-dark, 1-medium, 2-light
501 							for (int l=0;l<ncircs;l++) {
502 							// Weltposition relativ zu Kreislicht
503 								double wx = (px*distx+(distx>>1)+dx)/w2n-circ[l].x;
504 								double wy = (py*disty+(disty>>1)+dy)/w2n-circ[l].y;
505 								double d = wx*wx+wy*wy;
506 								if (d<circ[l].r2*circ[l].r2) {
507 									if (d<circ[l].r1*circ[l].r1) {
508 										// inner circle
509 											lflag=2; break;
510 									}
511 									else	lflag=1;
512 								}
513 							}
514 							if ( (lflag==2) || (lflag&&((x^y)&1)) ) {
515 								lbit[px+py*lpixs_x].SetPixel(x,y);
516 							}
517 						}
518 					}
519 				}
520 			}
521 		}
522 	}
523 
524 	lpix = new Pixmap[lpixs_all];
525 	for (i=0;i<lpixs_all;i++) {
526 		lpix[i] = lbit[i].Create();
527 	}
528 	delete [] lbit;
529 }
530 
531 
GetShadowMap(int x,int y)532 Pixmap ShadedBallMover::GetShadowMap( int x, int y ) {
533 int	xp = x/distx;
534 	if (xp<0)			xp=0;
535 	if (xp>=lpixs_x)	xp=lpixs_x-1;
536 int	yp = y/disty;
537 	if (yp<0)			yp=0;
538 	if (yp>=lpixs_y)	yp=lpixs_y-1;
539 
540 	return lpix[xp+yp*lpixs_x];
541 }
542 
543 
CreateLightWindow()544 void ShadedBallMover::CreateLightWindow() {
545 Window	help;
546 const int o=2;
547 
548 	help=CreateWindow( "Beleuchtung", lpixs_x*(d+o)+1 , lpixs_y*(d+o)+1 );
549 	for (int px=0;px<lpixs_x;px++) {
550 		for (int py=0;py<lpixs_y;py++) {
551 			XCopyPlane(dpy,bpix,help,gc_ball[2],0,0,d,d,o/2+px*(d+o),o/2+py*(d+o),1);
552 			XCopyPlane(dpy,lpix[px+py*lpixs_x],help,gc_lay2,0,0,d,d,o/2+px*(d+o),o/2+py*(d+o),1);
553 
554 		}
555 	}
556 }
557 
558 // -------------------------------------------------------------------------
559 
560 const int HalfBallMover::o=4;
561 
HalfBallMover(const Real & r,int mode_in)562 HalfBallMover::HalfBallMover( const Real &r, int mode_in ) :
563 	ShadedBallMover( r )
564 {
565 	rpix	= 0;		// Ring-Pixmap-Feld
566 	nbpix = 0;		// negative Pixmap zum Debuggen
567 	tw		= 0;
568 	mode	= mode_in;
569 
570 	right = left = up = down = 0;
571 }
572 
Create(const Real & r,int mode_in)573 HalfBallMover* HalfBallMover::Create( const Real &r, int mode_in ) {
574 	switch (enhanced_mover) {
575 	case 2:		return new HiEnhancedHalfBallMover(r,mode_in);
576 	case 1:		return new LoEnhancedHalfBallMover(r,mode_in);
577 	default:		return new HalfBallMover(r,mode_in);
578 	}
579 }
580 
~HalfBallMover()581 HalfBallMover::~HalfBallMover()
582 {
583 	if (rpix) {
584 		for (int i=0;i<rpixs_all;i++) {
585 			XFreePixmap( dpy, rpix[i] );
586 		}
587 		delete [] rpix;
588 		rpix = 0;
589 	}
590 	if (nbpix)		XFreePixmap( dpy, nbpix );
591 
592 	if (right)		delete [] right;
593 	if (left)		delete [] left;
594 	if (up)			delete [] up;
595 	if (down)		delete [] down;
596 }
597 
Init()598 void HalfBallMover::Init() {
599 int			x,y,i,l,b;
600 
601 LocBitmap	*rbit;	// Feld der Ring-Bitmaps
602 Vec3			*pv;		// Vec2 zum Pol der Kugel der entsprechenden Bitmap
603 
604 	ShadedBallMover::Init();
605 
606 //
607 // Zahl der Pixmap's, Gr��e der Felder bestimmen
608 //
609 	sym = (mode>1)?2.0:1.0;
610 	//sym = 1.0;
611 
612 	if (mode) {
613 		rpixs_l   = (int)(3.14*d/sym);   // Zahl der Bitmaps in L�ngen-Richtung
614 		rpixs_b   = (int)(3.14*d/2.0);	// Zahl der Bitmaps in Breiten-Richtung
615 		mult	= 6;								// Internes Raster
616 	}
617 	else {
618 		rpixs_l = rpixs_b = 1;
619 		mult = 1;
620 	}
621 	mult2 = mult/2;
622 	rpixs_all = rpixs_l * rpixs_b;		// Gesamtzahl
623 
624 	vecs_l    = rpixs_l * mult;			// Hilfsraster feiner als Bitmap-Raster
625 	vecs_b    = rpixs_b * mult;
626 
627 	vecs_all  = vecs_l * vecs_b;			// Gesamtgr��e des Rasters
628 	for (i=0;i<(int)sizeof(RingState);i++)	vecs_all/=256;
629 	if (vecs_all>0) {
630 		printf( "too many RingStates (%d) -> switch type to unsigned long (in xmover.h)\n",
631 					vecs_l * vecs_b );
632 		exit(0);
633 	}
634 	vecs_all  = vecs_l * vecs_b;			// Gesamtgr��e des Rasters
635 
636 char	fname[80];
637 	sprintf(fname,"%s/fly%d-%d.dta",DATA_DIRECTORY,mode,d);
638 FILE	*fp;
639 
640 #ifdef DEBUG
641 	fp = (debug&ForceCalc)?0:fopen( fname, "r" );
642 #else
643 	fp = fopen( fname, "r" );
644 #endif
645 
646 	rbit = new LocBitmap[rpixs_all];		// Anlegen der Bitmaps
647 	for (l=0;l<rpixs_l;l++) {				// f�r alle Bitmaps
648 		for (b=0;b<rpixs_b;b++) {
649 			if (!fp)	rbit[PixIndex(l,b)].Init(d,d);
650 			else		rbit[PixIndex(l,b)].Init(d,d,fp);
651 		}
652 	}
653 
654 	pv   = new Vec3[d*d];
655 	for (y=0;y<d;y++) {
656 		for (x=0;x<d;x++) {
657 			double dx = x-r+0.5;								// X-Abstand zur Kreismitte
658 			double dy = y-r+0.5;								// Y-Abstand zur Kreismitte
659 			double dist2 = dx*dx + dy*dy;					// Dist. zur sichtbaren Mitte
660 			if (dist2<max_rad2) {
661 		//		double dzr = sqrt(dr*dr-dy*dy);		// Kugel-Radius auf H�he z
662 		//		double dz  = sqrt(dzr*dzr-dx*dx);	// fehlende Tiefenkoordinate
663 				double dz  = sqrt(r*r-dist2);
664 				pv[x+y*d] = Vec3( dx, dz, dy );
665 			}
666 			else {
667 				pv[x+y*d] = Vec3( 0.0, 0.0, 0.0 );
668 			}
669 		}
670 	}
671 
672 #ifdef DEBUG
673 double	start_time = GetCurrentTime();
674 #endif
675 
676 	if (!fp) {
677 		DBG3( UnixTrace, "Rings need %dx%d=%d Bitmaps\n",rpixs_l,rpixs_b,rpixs_all);
678 		DBG1( UnixTrace, "BitmapData:   >%7d Bytes\n", (d+7)/8*d*rpixs_all );
679 		DBG1( UnixTrace, "+ temporary:  >%7d Bytes\n",
680 					 d*d*(sizeof(Vec3)+sizeof(Bitmap)+(d*(d+7)/8) ) );
681 
682 //
683 // Bitmaps ausrechen
684 //
685 		printf( "image processing: 00%%" ); fflush(stdout);
686 
687 		for (l=0;l<rpixs_l;l++) {	// f�r alle Bitmaps
688 			printf( "\b\b\b%02d%%", (int)100*l/rpixs_l ); fflush(stdout);
689 			for (b=0;b<rpixs_b;b++) {
690 				Vec3	v = Vec3( lToDeg(l*mult+mult2), bToDeg(b*mult+mult2) )*Real(r);
691 				switch(mode) {
692 				case 1:	for (y=0;y<d;y++) {		// Volle Kugeln
693 								for (x=0;x<d;x++) {
694 									if (!pv[x+y*d].IsZero()) {
695 										Real	ang = v.AngleRadTo( pv[x+y*d] );
696 										if (ang>0.35)	rbit[PixIndex(l,b)].SetPixel(x,y);
697 									}
698 								}
699 							}
700 							break;
701 				case 2:	for (y=0;y<d;y++) {		// Halbe Kugeln
702 								for (x=0;x<d;x++) {
703 									if (!pv[x+y*d].IsZero()) {
704 										Real	ang = v.AngleRadTo( pv[x+y*d] );
705 										if (ang>1.0708 && ang<2.0708)
706 											rbit[PixIndex(l,b)].SetPixel(x,y);
707 									}
708 								}
709 							}
710 							break;
711 				case 3:	for (y=0;y<d;y++) {		// Volle Kugeln 2
712 								for (x=0;x<d;x++) {
713 									if (!pv[x+y*d].IsZero()) {
714 										Real	ang = v.AngleRadTo( pv[x+y*d] );
715 										if (ang>0.35)	rbit[PixIndex(l,b)].SetPixel(x,y);
716 									}
717 								}
718 							}
719 							break;
720 				case 4:	for (y=0;y<d;y++) {		// Halbe Kugeln 2
721 								for (x=0;x<d;x++) {
722 									if (!pv[x+y*d].IsZero()) {
723 										Real	ang = v.AngleRadTo( pv[x+y*d] );
724 										if ((ang>0.35&&ang<1.27)||(ang>1.87&&ang<2.79))
725 											rbit[PixIndex(l,b)].SetPixel(x,y);
726 									}
727 								}
728 							}
729 							break;
730 				default:	for (y=0;y<d;y++) {
731 								for (x=0;x<d;x++) {
732 									if (!pv[x+y*d].IsZero()) {
733 										rbit[PixIndex(l,b)].SetPixel(x,y);
734 									}
735 								}
736 							}
737 							break;
738 				}
739 			}
740 		}
741 
742 		printf( "\b\b\bdone\n" );
743 	}
744 
745 
746 
747 //
748 // RingState-Felder anfordern und initialisieren
749 // - zu jeder Pixmap existiert dabei in ein Eintrage mit einer
750 //   Folgepixmap in Feldern zu jeder Himmelsrichtung.
751 //
752 	DBG4( UnixTrace, "RingStateData:>%7d Bytes (for %dx%d=%d States)\n",
753 				 4*vecs_all*sizeof(RingState), vecs_l, vecs_b, vecs_all );
754 
755 	right	= new RingState[vecs_all];
756 	left	= new RingState[vecs_all];
757 	up		= new RingState[vecs_all];
758 	down	= new RingState[vecs_all];
759 
760 //
761 // Stuffer anlegen und initialisieren
762 //
763 Stuffer	stuff;
764 	for (i=0,l=vecs_all;l;l>>=1)	i++;		// Bits in vecs_all zaehlen
765 	stuff.Init(i,sizeof(RingState));
766 
767 	if (fp) {
768 		printf( "reading %s\n", fname );
769 
770 #ifndef LEFT_RIGHT_OPT
771 		fread( right,1,stuff.SSize(vecs_all), fp );
772 		stuff.Expand( right, vecs_all );
773 		fread( left, 1,stuff.SSize(vecs_all), fp );
774 		stuff.Expand( left, vecs_all );
775 #endif
776 		fread( up,   1,stuff.SSize(vecs_all), fp );
777 		stuff.Expand( up, vecs_all );
778 		fread( down, 1,stuff.SSize(vecs_all), fp );
779 		stuff.Expand( down, vecs_all );
780 	}
781 	else {
782 Real	b_ang = (double)mult*M_PI/vecs_b;	// Rotationswinkel pro Pixel
783 
784 		printf( "state processing: 00%%" ); fflush(stdout);
785 
786 		for (l=0;l<vecs_l;l++) {
787 			printf( "\b\b\b%02d%%", (int)100*l/vecs_l ); fflush(stdout);
788 
789 			for (int b=0;b<vecs_b;b++) {
790 				RingState	st = AngVec2St(l,b);				// aktueller Index
791 				RingState	nst;									// auszurechnender State
792 				Real	newl, newb;
793 
794 				Vec3	v( lToDeg(l), bToDeg(b) );
795 
796 				v.XTurnAngleRad(b_ang).GetPolarRad(&newl,&newb);
797 				nst = AngRad2St( newl, newb );
798 				if (st==nst)	DBG2( Loops, "Loop-Warning Up:    %03d/%03d\n",l,b );
799 				up[st] = nst;
800 
801 
802 				v.XTurnAngleRad(-b_ang).GetPolarRad(&newl,&newb);
803 				nst = AngRad2St( newl, newb );
804 				if (st==nst)	DBG2( Loops, "Loop-Warning Down:  %03d/%03d\n",l,b );
805 				down[st] = nst;
806 
807 #ifndef LEFT_RIGHT_OPT
808 				v.ZTurnAngleRad(-b_ang).GetPolarRad(&newl,&newb);
809 				nst = AngRad2St( newl, newb );
810 				if (st==nst)	DBG2( Loops, "Loop-Warning Right: %03d/%03d\n",l,b );
811 				right[st] = nst;
812 
813 				v.ZTurnAngleRad(b_ang).GetPolarRad(&newl,&newb);
814 				nst = AngRad2St( newl, newb );
815 				if (st==nst)	DBG2( Loops, "Loop-Warning Left:  %03d/%03d\n",l,b );
816 				left[st] = nst;
817 #endif
818 			}
819 		}
820 
821 		printf( "\b\b\bdone\n" );
822 
823 		DBG1( UnixTrace, "Time: %g secs.\n", GetCurrentTime()-start_time );
824 	}
825 
826 #ifdef LEFT_RIGHT_OPT
827 	for (l=0;l<vecs_l;l++) {
828 		for (int b=0;b<vecs_b;b++) {
829 			RingState	st = AngVec2St(l,b);				// aktueller Index
830 			right[st] = AngVec2StBnd((l+(vecs_l*(int)sym)-mult)%(vecs_l*(int)sym),b);
831 			left[st]  = AngVec2StBnd((l+mult)%(vecs_l*(int)sym),b);
832 		}
833 	}
834 #endif
835 
836 #ifdef DEBUG
837 	if (debug&ShowRings) {
838 		//
839 		// Eine spezielle Pixmap wird erzeugt, die eine Negation der Balldarstellung
840 		// ist, um in dem Trace-Window einzelne Pixmap's herzuheben.
841 		//
842 		nbpix	= XCreatePixmap(dpy,bpix,d+o,d+o,1);
843 		GC	gc = XCreateGC( dpy, nbpix, 0, 0l );
844 		XSetFunction(dpy,gc,GXset);
845 		XFillRectangle(dpy,nbpix,gc,0,0,d+o,d+o);			// alle Pixmap setzen
846 		XSetFunction(dpy,gc,GXxor);
847 		XCopyArea(dpy,bpix,nbpix,gc,0,0,d,d,o/2,o/2);	// Ball l�schen
848 		XFreeGC(dpy,gc);
849 	}
850 #endif
851 
852 	if (fp) {
853 		fclose(fp);
854 		fp = 0;
855 	}
856 	else {
857 		fp = fopen( fname, "w" );
858 	}
859 //
860 // Bitmaps in Pixmaps wandeln und interne Strukturen freigeben
861 //
862 	rpix = new Pixmap[rpixs_all];
863 	for (i=0;i<rpixs_all;i++) {
864 		rpix[i] = rbit[i].Create();
865 		if (fp) rbit[i].Write( fp );
866 	}
867 	delete [] rbit;
868 	delete [] pv;
869 
870 	if (fp) {
871 		printf( "writing %s\n", fname );
872 
873 #ifndef LEFT_RIGHT_OPT
874 		stuff.Shrink( right, vecs_all );
875 		fwrite( right,1,stuff.SSize(vecs_all), fp );
876 		stuff.Expand( right, vecs_all );
877 		stuff.Shrink( left, vecs_all );
878 		fwrite( left, 1,stuff.SSize(vecs_all), fp );
879 		stuff.Expand( left, vecs_all );
880 #endif
881 		stuff.Shrink( up, vecs_all );
882 		fwrite( up,   1,stuff.SSize(vecs_all), fp );
883 		stuff.Expand( up, vecs_all );
884 		stuff.Shrink( down, vecs_all );
885 		fwrite( down, 1,stuff.SSize(vecs_all), fp );
886 		stuff.Expand( down, vecs_all );
887 		fclose(fp);
888 	}
889 }
890 
891 
892 
CreateRingWindow()893 void HalfBallMover::CreateRingWindow() {
894 	tw=CreateWindow( "Ringverteilung", rpixs_l*(d+o)+1 , rpixs_b*(d+o)+1 );
895 	for (int l=0;l<rpixs_l;l++) {
896 		for (int b=0;b<rpixs_b;b++) {
897 			XCopyPlane(dpy,bpix,tw,gc_ballwhite,0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
898 			XCopyPlane(dpy,lpix[(l*lpixs_x/rpixs_l)+(b*lpixs_y/rpixs_b)*lpixs_x],tw,gc_lay2,0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
899 			XCopyPlane(dpy,rpix[PixIndex(rpixs_l-1-l,b)],tw,gc_ball[7],0,0,d,d,o/2+l*(d+o),o/2+b*(d+o),1);
900 		}
901 	}
902 #ifdef DEBUG
903 	if (debug&xwd) {
904 		char command[200];
905 		XSync(dpy,0);
906 		sprintf( command, "/usr/bin/X11/xwd -id %ld -frame > XWD/rings", tw );
907 		system(command);
908 	}
909 #endif
910 }
911 
912 
913 #define _INFO
914 
CreateTurnWindow()915 void HalfBallMover::CreateTurnWindow() {
916 Window	win;
917 
918 	win=CreateWindow( "Senkrecht-Rotation", rpixs_b*(d+o)+1,2*rpixs_b*(d+o)+1 );
919 	for (int b=0;b<rpixs_b;b++) {
920 #ifdef INFO
921 		printf( "Row %d: angle: %f\n", b, (double)bToDeg(b*mult+mult2) );
922 #endif
923 		RingState	st = AngPix2St(0,b);
924 		for (int y=0;y<2*rpixs_b;y++) {
925 #ifdef INFO
926 		int lp,bp;
927 		int lv,bv;
928 	//
929 	// Ausgabe der Tabellenerte
930 	//
931 		St2AngVec(st,&lv,&bv);
932 		St2AngPix(st,&lp,&bp);
933 		printf( "  Line %2d: Vec2: %03d/%03d, Pixmap: %02d/%02d",
934 			y, lv, bv, lp, bp );
935 
936 	//
937 	// Berechnung der direkten Werte zum Vergleich
938 	//
939 		Real	b_ang=(double)mult*M_PI/vecs_b;   // Rotationswinkel pro Pixel
940 		Vec3	v( lToDeg(mult2), bToDeg(b*mult+mult2) );
941 		Real	newl, newb;
942 		v.XTurnAngleRad((y*b_ang)).GetPolarRad(&newl,&newb);
943 		RingState nst = AngRad2St( newl, newb );
944 	// Ausgabe
945 		St2AngVec(nst,&lv,&bv);
946 		St2AngPix(nst,&lp,&bp);
947 		printf( " <=> Vec2: %03d/%03d, Pixmap: %02d/%02d\n",
948 			lv, bv, lp, bp );
949 
950 		if (((b^y)&1)) {
951 			XCopyPlane(dpy,bpix,win,gc_ballwhite,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
952 			XCopyPlane(dpy,lpix[(b*lpixs_x/rpixs_b)+(y/2*lpixs_y/rpixs_b)*lpixs_x],win,gc_lay2,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
953 			XCopyPlane(dpy,rpix[PixIndex(nst)],win,gc_ball[7],0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
954 		}
955 		else
956 #endif
957 		{
958 			XCopyPlane(dpy,bpix,win,gc_ballwhite,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
959 			XCopyPlane(dpy,lpix[(b*lpixs_x/rpixs_b)+(y/2*lpixs_y/rpixs_b)*lpixs_x],win,gc_lay2,0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
960 			XCopyPlane(dpy,rpix[PixIndex(st)],win,gc_ball[8],0,0,d,d,o/2+b*(d+o),o/2+y*(d+o),1);
961 		}
962 			st = Turn(st,0,1);
963 		}
964 	}
965 #ifdef DEBUG
966 	if (debug&xwd) {
967 		char command[200];
968 		XSync(dpy,0);
969 		sprintf( command, "/usr/bin/X11/xwd -id %ld -frame > XWD/turns", win );
970 		system(command);
971 	}
972 #endif
973 }
974 
975 
976 
977 #if (1)
978 
979 #define	LINE(DY,YDEC,YADDOP,YTAB,DX,XLESS,XTAB) \
980 	int	dy_c = DY; \
981 	int	c    = 0; \
982 	while(DY) { \
983 		st = YTAB [st]; \
984 		DY YDEC; \
985 		c -= DX;	\
986 		if (c XLESS 0) {	\
987 			c YADDOP dy_c;	\
988 			st = XTAB [st];	\
989 		};	\
990 	}
991 
992 
Turn(RingState st,int dx,int dy)993 RingState HalfBallMover::Turn( RingState st, int dx, int dy ) {
994 
995 	if (dx>0) {
996 		if (dy>0) {
997 			if (dy>dx)	{ LINE(dy,--,+=,up,   dx,<,right);	}
998 			else			{ LINE(dx,--,+=,right,dy,<,up);		}
999 		}
1000 		else {				// dy negativ => alle DY-Parameter umkehren
1001 			if (-dy>dx)	{ LINE(dy,++,-=,down, dx,<,right);	}
1002 			else			{ LINE(dx,--,+=,right,dy,>,down);	}
1003 		}
1004 	}
1005 	else {				// dx negativ => alle DX-Parameter umkehren
1006 		if (dy>0) {
1007 			if (dy>-dx)	{ LINE(dy,--,+=,up,   dx,>,left);	}
1008 			else			{ LINE(dx,++,-=,left ,dy,<,up);		}
1009 		}
1010 		else {				// dy negativ => alle DY-Parameter umkehren
1011 			if (-dy>-dx){ LINE(dy,++,-=,down, dx,>,left);	}
1012 			else			{ LINE(dx,++,-=,left ,dy,>,down);	}
1013 		}
1014 	}
1015 
1016 	return st;
1017 }
1018 
1019 #else
Turn(RingState st,int dx,int dy)1020 RingState HalfBallMover::Turn( RingState st, int dx, int dy ) {
1021 	while( dx && dy ) {
1022 		if (dx>0)				{	dx--; st = right[st];	}
1023 		else if (dx<0)			{	dx++; st = left[st]; }
1024 		if (dy>0)				{	dy--;	st = up[st];	}
1025 		else if (dy<0)			{	dy++;	st = down[st];	}
1026 	}
1027 	if (dx>0)				{ while(dx--)		st = right[st]; }
1028 	else if (dx<0)			{ while(dx++)		st = left[st]; }
1029 	if (dy>0)				{ while(dy--)		st = up[st]; }
1030 	else if (dy<0)			{ while(dy++)		st = down[st]; }
1031 	return st;
1032 }
1033 #endif
1034 
1035 
1036 #ifdef DEBUG
ShowDebugRing(RingState st,int col_x)1037 void HalfBallMover::ShowDebugRing(RingState st, int col_x) {
1038 	int	l,b;
1039 	St2AngPix(st,&l,&b);
1040 	XCopyPlane(dpy,nbpix,tw,gc_ballwhite,  0,0,d+o,d+o,(rpixs_l-1-l)*(d+o),b*(d+o),1);
1041 	XCopyPlane(dpy,nbpix,tw,gc_ball[col_x],0,0,d+o,d+o,(rpixs_l-1-l)*(d+o),b*(d+o),1);
1042 }
1043 #endif
1044 
RollBallAt(int x,int y,RingState st,int col_x)1045 void HalfBallMover::RollBallAt( int x, int y, RingState st, int col_x )
1046 {
1047 #ifndef NODRAW
1048 	XFillRectangle(dpy,help,gc_bclear,0,0,d,d);
1049 	XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,0,0,1);
1050 	XCopyPlane(dpy,GetShadowMap(x,y),help,gc_lay2,0,0,d,d,0,0,1);
1051 	XCopyPlane(dpy,rpix[PixIndex(st)],help,gc_ball[col_x],0,0,d,d,0,0,1);
1052 	XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
1053 
1054 #ifdef DEBUG
1055 	if ((tw)&&(debug&ShowRings))		ShowDebugRing(st,col_x);
1056 #endif
1057 #endif
1058 }
1059 
1060 
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1061 void HalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1062 				int newx, int newy, RingState *nst, int col_x ) {
1063 
1064 int	dx = newx-oldx;
1065 int	dy = newy-oldy;
1066 
1067 		*nst = Turn( ost, dx, dy );
1068 
1069 int absx = (dx>0)?dx:-dx;
1070 int absy = (dy>0)?dy:-dy;
1071 
1072 #ifndef NODRAW
1073 	if ( (absx<d_help-d) && (absy<d_help-d) ) {
1074 		int	width = d+absx;		// tats�chlicher Ausschnittgr��e der Pixmap
1075 		int	height= d+absy;
1076 		int	ox = (dx>0)?0:absx;	// relativer Abstand alte Position
1077 		int	oy = (dy>0)?0:absy;
1078 		int	nx = (dx>0)?absx:0;	// relativer Abstand neue Position
1079 		int	ny = (dy>0)?absy:0;
1080 
1081 		XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
1082 
1083 		XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,ox,oy,1);
1084 		XCopyPlane(dpy,GetShadowMap(oldx,oldy),help,gc_lay2,0,0,d,d,ox,oy,1);
1085 		XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1086 
1087 		XCopyPlane(dpy,bpix,help,gc_ballwhite,0,0,d,d,nx,ny,1);
1088 		XCopyPlane(dpy,GetShadowMap(newx,newy),help,gc_lay2,0,0,d,d,nx,ny,1);
1089 		XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1090 
1091 		XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1092 
1093 #ifdef DEBUG
1094 		if ((tw)&&(debug&ShowRings)) {
1095 			ShowDebugRing(ost,col_x);
1096 			ShowDebugRing(*nst,col_x);
1097 		}
1098 #endif
1099 
1100 	}
1101 	else {
1102 		RollBallAt(oldx,oldy,ost,col_x);
1103 		RollBallAt(newx,newy,*nst,col_x);
1104 	}
1105 #endif
1106 
1107 #ifdef STATISTICS
1108 	moves++;
1109 #endif
1110 }
1111 
1112 
1113 // ---------------------------------------------------------------------------
1114 //                          LoEnhancedHalfBallMover
1115 // ---------------------------------------------------------------------------
1116 
1117 
LoEnhancedHalfBallMover(const Real & r,int mode_in)1118 LoEnhancedHalfBallMover::LoEnhancedHalfBallMover( const Real &r, int mode_in )
1119 : HalfBallMover( r, mode_in ) {
1120 	lbpix = 0;
1121 	boffset = 0;
1122 	lb_dist = boffset+d;
1123 }
1124 
~LoEnhancedHalfBallMover()1125 LoEnhancedHalfBallMover::~LoEnhancedHalfBallMover() {
1126 	if (lbpix) {
1127 		PixmapCache::pcache.Unlock( dpy, lbpix );
1128 		lbpix = 0;
1129 	}
1130 }
1131 
Init()1132 void LoEnhancedHalfBallMover::Init() {
1133 	HalfBallMover::Init();
1134 
1135 // create initialisation pixmap for all possible shades, which
1136 // can directly be used as presets in the RollBall() functions
1137 // A large Pixmap is created that contains all neccessary background-presets
1138 // in a certain distance, so that a direct copy can be done, which presets
1139 // the whole background help-pixmap.
1140 
1141 	lbpix = PixmapCache::pcache.Lock( d, ENHANCED_LBPIX_ID );
1142 	if (!lbpix ) {
1143 
1144 // create map and clear it
1145 
1146 		DBG1( UnixTrace, "EnhancedData: >%d bytes\n",
1147 					(lb_dist*lpixs_x+d-1)*(lb_dist*lpixs_y+d-1) );
1148 		lbpix = XCreatePixmap(dpy,win,
1149 					lb_dist*lpixs_x+d-1,lb_dist*lpixs_y+d-1,DefaultDepth(dpy,0));
1150 		XFillRectangle(dpy,lbpix,gc_bclear, 0,0,
1151 					lb_dist*lpixs_x+d-1,lb_dist*lpixs_y+d-1);
1152 
1153 // copy the balls & shades into the map
1154 
1155 		for (int x=0;x<lpixs_x;x++) {
1156 			for (int y=0;y<lpixs_y;y++) {
1157 				XCopyPlane(dpy,bpix,   lbpix,gc_ballwhite,
1158 										0,0,d,d,boffset+x*lb_dist,boffset+y*lb_dist,1);
1159 				XCopyPlane(dpy,lpix[x+y*lpixs_x],lbpix,gc_lay2,
1160 										0,0,d,d,boffset+x*lb_dist,boffset+y*lb_dist,1);
1161 			}
1162 		}
1163 		PixmapCache::pcache.InsertAndLock(dpy,lbpix,d,ENHANCED_LBPIX_ID);
1164 	}
1165 }
1166 
1167 
RollBallAt(int x,int y,RingState st,int col_x)1168 void LoEnhancedHalfBallMover::RollBallAt( int x, int y, RingState st, int col_x )
1169 {
1170 #ifdef DEBUG
1171 	if (enhanced_mover<1) {
1172 			HalfBallMover::RollBallAt(x,y,st,col_x);
1173 			return;
1174 	}
1175 #endif
1176 
1177 #ifndef NODRAW
1178 int	xp,yp;
1179 	WC2Index(x,y,&xp,&yp);
1180 	XCopyArea(dpy,lbpix,help,gc_default,boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,0,0);
1181 	XCopyPlane(dpy,rpix[PixIndex(st)],help,gc_ball[col_x],0,0,d,d,0,0,1);
1182 	XCopyArea(dpy,help,win,gc_bxor,0,0,d,d,x-r, y-r );
1183 
1184 #ifdef DEBUG
1185 	if ((tw)&&(debug&ShowRings))		ShowDebugRing(st,col_x);
1186 #endif
1187 #endif
1188 }
1189 
1190 
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1191 void LoEnhancedHalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1192 				int newx, int newy, RingState *nst, int col_x ) {
1193 #ifdef DEBUG
1194 	if (enhanced_mover<1) {
1195 			HalfBallMover::RollBallOnScreen(oldx,oldy,ost,newx,newy,nst,col_x);
1196 			return;
1197 	}
1198 #endif
1199 
1200 int	dx = newx-oldx;
1201 int	dy = newy-oldy;
1202 
1203 		*nst = Turn( ost, dx, dy );
1204 
1205 int absx = (dx>0)?dx:-dx;
1206 int absy = (dy>0)?dy:-dy;
1207 
1208 #ifndef NODRAW
1209 	if ( (absx<d_help-d) && (absy<d_help-d) ) {
1210 		int	width = d+absx;		// tats�chlicher Ausschnittgr��e der Pixmap
1211 		int	height= d+absy;
1212 		int	ox = (dx>0)?0:absx;	// relativer Abstand alte Position
1213 		int	oy = (dy>0)?0:absy;
1214 		int	nx = (dx>0)?absx:0;	// relativer Abstand neue Position
1215 		int	ny = (dy>0)?absy:0;
1216 
1217 		int	xp,yp;
1218 		WC2Index(oldx,oldy,&xp,&yp);
1219 		XFillRectangle(dpy,help,gc_bclear,0,0,width,height);
1220 
1221 		XCopyArea(dpy,lbpix,help,gc_bxor,
1222 					boffset-ox+xp*lb_dist,boffset-oy+yp*lb_dist,d_help,d_help,0,0);
1223 		XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1224 
1225 		WC2Index(newx,newy,&xp,&yp);
1226 		XCopyArea(dpy,lbpix,help,gc_bxor,
1227 					boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,nx,ny);
1228 		XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1229 
1230 		XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1231 
1232 #ifdef DEBUG
1233 		if ((tw)&&(debug&ShowRings)) {
1234 			ShowDebugRing(ost,col_x);
1235 			ShowDebugRing(*nst,col_x);
1236 		}
1237 #endif
1238 	}
1239 	else {
1240 		RollBallAt(oldx,oldy,ost,col_x);
1241 		RollBallAt(newx,newy,*nst,col_x);
1242 	}
1243 #endif
1244 
1245 #ifdef STATISTICS
1246 	moves++;
1247 #endif
1248 }
1249 
1250 // ---------------------------------------------------------------------------
1251 //                          HiEnhancedHalfBallMover
1252 // ---------------------------------------------------------------------------
1253 
1254 
HiEnhancedHalfBallMover(const Real & r,int mode_in)1255 HiEnhancedHalfBallMover::HiEnhancedHalfBallMover( const Real &r, int mode_in )
1256 : LoEnhancedHalfBallMover( r, mode_in ) {
1257 	boffset = d-1;
1258 	lb_dist = 2*d-1;
1259 }
1260 
~HiEnhancedHalfBallMover()1261 HiEnhancedHalfBallMover::~HiEnhancedHalfBallMover() {
1262 }
1263 
RollBallOnScreen(int oldx,int oldy,RingState ost,int newx,int newy,RingState * nst,int col_x)1264 void HiEnhancedHalfBallMover::RollBallOnScreen( int oldx, int oldy, RingState ost,
1265 				int newx, int newy, RingState *nst, int col_x ) {
1266 #ifdef DEBUG
1267 	if (enhanced_mover<2) {
1268 			LoEnhancedHalfBallMover::RollBallOnScreen(oldx,oldy,ost,newx,newy,nst,col_x);
1269 			return;
1270 	}
1271 #endif
1272 
1273 int	dx = newx-oldx;
1274 int	dy = newy-oldy;
1275 
1276 		*nst = Turn( ost, dx, dy );
1277 
1278 int absx = (dx>0)?dx:-dx;
1279 int absy = (dy>0)?dy:-dy;
1280 
1281 #ifndef NODRAW
1282 	if ( (absx<d_help-d) && (absy<d_help-d) ) {
1283 		int	width = d+absx;		// tats�chlicher Ausschnittgr��e der Pixmap
1284 		int	height= d+absy;
1285 		int	ox = (dx>0)?0:absx;	// relativer Abstand alte Position
1286 		int	oy = (dy>0)?0:absy;
1287 		int	nx = (dx>0)?absx:0;	// relativer Abstand neue Position
1288 		int	ny = (dy>0)?absy:0;
1289 
1290 		int	xp,yp;
1291 		WC2Index(oldx,oldy,&xp,&yp);
1292 		XCopyArea(dpy,lbpix,help,gc_default,
1293 					boffset-ox+xp*lb_dist,boffset-oy+yp*lb_dist,d_help,d_help,0,0);
1294 		XCopyPlane(dpy,rpix[PixIndex(ost)],help,gc_ball[col_x],0,0,d,d,ox,oy,1);
1295 
1296 		WC2Index(newx,newy,&xp,&yp);
1297 		XCopyArea(dpy,lbpix,help,gc_bxor,
1298 					boffset+xp*lb_dist,boffset+yp*lb_dist,d,d,nx,ny);
1299 		XCopyPlane(dpy,rpix[PixIndex(*nst)],help,gc_ball[col_x],0,0,d,d,nx,ny,1);
1300 
1301 		XCopyArea(dpy,help,win,gc_bxor,0,0,width,height,oldx-ox-r, oldy-oy-r );
1302 
1303 #ifdef DEBUG
1304 		if ((tw)&&(debug&ShowRings)) {
1305 			ShowDebugRing(ost,col_x);
1306 			ShowDebugRing(*nst,col_x);
1307 		}
1308 #endif
1309 	}
1310 	else {
1311 		RollBallAt(oldx,oldy,ost,col_x);
1312 		RollBallAt(newx,newy,*nst,col_x);
1313 	}
1314 #endif
1315 
1316 #ifdef STATISTICS
1317 	moves++;
1318 #endif
1319 }
1320 
1321