1 #ifndef _global_h
2 #	include "global.h"
3 #endif
4 #ifndef _puzzle_h
5 #	include "puzzle.H"
6 #endif
7 
Grid(int w,int h)8 Grid::Grid(int w, int h) {
9 	width  = w;
10 	height = h;
11 
12 	p = new Vec2[width*height];
13 }
14 
~Grid()15 Grid::~Grid() {
16 	delete [] p;
17 }
18 
Reset(int x,int y)19 void Grid::Reset(int x, int y) {
20 		P(x,y) = Vec2( x*max_width/(width-1), y*max_height/(height-1) );
21 }
22 
Init(int maxx,int maxy)23 void Grid::Init(int maxx, int maxy) {
24 int	x,y;
25 
26 	max_width  = maxx;
27 	max_height = maxy;
28 	for (x=0;x<width;x++) {
29 		for (y=0;y<height;y++) {
30 			Reset(x,y);
31 		}
32 	}
33 }
34 
Randomize(int percent)35 void Grid::Randomize(int percent) {
36 int	x,y;
37 
38 	for (x=1;x<width-1;x++) {
39 		for (y=1;y<height-1;y++) {
40 			Vec2	off( ((max_width/(width-1))/10000.0*percent) * (my_rand()%100)
41 			, ((max_height/(height-1))/10000.0*percent) * (my_rand()%100) );
42 			P(x,y) = Vec2( x*max_width/(width-1), y*max_height/(height-1) ) + off;
43 		}
44 	}
45 }
46 
Puzzle()47 Puzzle::Puzzle() {
48 	g=0;
49 	p=0;
50 	tiles_left=0;
51 }
52 
~Puzzle()53 Puzzle::~Puzzle() {
54 	if (g)		delete g;
55 	if (p) {
56 		for (int i=0;i<width*height;i++)
57 			if (p[i])	delete p[i];
58 		delete [] p;
59 	}
60 }
61 
Init(int img_width,int img_height,int dx,int dy,const char * sfx)62 void Puzzle::Init(int img_width, int img_height, int dx, int dy, const char *sfx ) {
63 int x,y;
64 PieceFrameSetup	*pfs;
65 Vec2					*pos;
66 #define	PFS(x,y)	(pfs[(x)+width*(y)])
67 
68 	width  = dx;
69 	height = dy;
70 	tiles_left=width*height;
71 
72 	// create and initialize the grid
73 	// check for special effect extension and reset the desired Dots
74 	g = new Grid(width+1,height+1);
75 	g->Init(img_width,img_height);
76 	g->Randomize(distortion);
77 	if (sfx) {
78 		int dir,len;
79 		const char *sfx_p=sfx;
80 		while( *sfx_p ) {
81 			if (sscanf( sfx_p, "%02x%02x%01x%01x", &x, &y, &len, &dir )!=4) {
82 				fprintf( stderr, "*** image error in extension 0x12\n" );
83 				exit(0);
84 			}
85 			g->Reset(x,y);
86 			while( len-- ) {
87 				switch(dir) {
88 				case 0:	x++; break;
89 				case 1:	y++; break;
90 				case 2:	x--; break;
91 				case 3:	y--; break;
92 				}
93 				g->Reset(x,y);
94 			}
95 			sfx_p+=6;
96 		}
97 	}
98 
99 	// create and initialize setup-structures for all pieces
100 	pfs = new PieceFrameSetup[width*height];
101 	pos = new Vec2[width*height];
102 
103 	// setup corner information
104 	for (x=0;x<width;x++) {
105 		for (y=0;y<height;y++) {
106 			PFS(x,y).Init(g->P(x,y),g->P(x+1,y),g->P(x+1,y+1),g->P(x,y+1));
107 			pos[x+width*y]=g->P(x,y)+Vec2(offx*(x+1)+img_width/dx/2,offy*(y+1)+img_height/dy/2);
108 		}
109 	}
110 
111 	// setup pin information
112 	for (x=0;x<width-1;x++) {
113 		for (y=0;y<height;y++) {
114 			// Real	off = (my_rand()%100)/500.0+0.4;
115 			Real	off = (my_rand()%100)/250.0+0.3;
116 			int	left=my_rand()%2;
117 
118 			PFS(x,y).SetPin(1,left,off);
119 			PFS(x+1,y).SetPin(3,1-left,1.0-off);
120 		}
121 	}
122 	for (y=0;y<height-1;y++) {
123 		for (x=0;x<width;x++) {
124 			Real	off = (my_rand()%100)/500.0+0.4;
125 			int	left=my_rand()%2;
126 
127 			PFS(x,y).SetPin(2,left,off);
128 			PFS(x,y+1).SetPin(0,1-left,1.0-off);
129 		}
130 	}
131 
132 	// override Pin-Information for special effects
133 	if (sfx) {
134 		int dir,len;
135 		const char *sfx_p=sfx;
136 		while( *sfx_p ) {
137 			if (sscanf( sfx_p, "%02x%02x%01x%01x", &x, &y, &len, &dir )!=4) {
138 				fprintf( stderr, "*** image error in extension 0x12\n" );
139 				exit(0);
140 			}
141 			while( len-- ) {
142 				switch(dir) {
143 				case 0:	PFS(x,y-1).SetPin(2,0,0); PFS(x,y).SetPin(0,0,0); x++; break;
144 				case 1:	PFS(x-1,y).SetPin(1,0,0); PFS(x,y).SetPin(3,0,0); y++; break;
145 				case 2:	x--; PFS(x,y-1).SetPin(2,0,0); PFS(x,y).SetPin(0,0,0); break;
146 				case 3:	y--; PFS(x-1,y).SetPin(1,0,0); PFS(x,y).SetPin(3,0,0); break;
147 				}
148 			}
149 			sfx_p+=6;
150 		}
151 	}
152 
153 	if (shuffle&2) {
154 		for (x=0;x<width*height;x++) {
155 			int	i=rand()%(width*height);
156 			Vec2	swap(pos[i]);
157 			pos[i]=pos[x];
158 			pos[x]=swap;
159 		}
160 	}
161 	if (shuffle&4) {
162 		for (x=0;x<width*height;x++) {
163 			pos[x]=Vec2(offx,offy)+Vec2(rand()%(img_width+offx*width-offx),rand()%(img_height+offy*height-offy));
164 		}
165 	}
166 
167 	// create pieces and let them be initialized with the setup structure
168 	p = new Piece*[width*height];
169 	for (x=0;x<width;x++) {
170 		for (y=0;y<height;y++) {
171 			p[x+width*y]=new Piece;
172 			P(x,y).Init(PFS(x,y));
173 			if (straight_setup>=0) {
174 				int	row=y;
175 				int	col=x;
176 
177 					// query the offset of the center from the grid edge in the original piece
178 				Vec2	org_offset(P(x,y).Center()-Vec2(x*img_width/width,y*img_height/height));
179 					// compute the piece edge in the 'straight' position
180 				Vec2	new_pos( col*img_width/width+col*straight_setup, row*img_height/height+row*straight_setup );
181 				P(x,y).SetPos( new_pos+org_offset );
182 			}
183 			else {
184 				P(x,y).SetPos(pos[x+y*width]);
185 			}
186 			if (shuffle&1)		P(x,y).SetDir( ((rand()%(int)(maxang*2))-maxang) + (rand()%4)*90 );
187 			else					P(x,y).SetDir(angle*(x+y));
188 
189 			if (side_lock<0) {
190 				if (rand()&2)		P(x,y).FlipPage();
191 			}
192 			else {
193 				if (side_lock==1)	P(x,y).FlipPage();
194 			}
195 			stk->Append( &P(x,y) );
196 		}
197 	}
198 
199 	delete [] pos;
200 	delete [] pfs;
201 #undef PFS
202 }
203 
Redraw()204 void Puzzle::Redraw() {
205 	for (int i=0;i<width*height;i++)
206 		if (p[i])	p[i]->Redraw();
207 }
208 
CheckForJoin(Piece * pi,int depth)209 int Puzzle::CheckForJoin( Piece *pi, int depth ) {
210 int i,j,s;
211 
212 	for (i=0;i<width*height;i++)
213 		if (p[i]&&p[i]!=pi) {
214 		DBG1("=== %d\n",i);
215 			if (p[i]->CheckForJoin(pi)) {
216 				if ((s=p[i]->FindStartForJoin(pi))>=0) {
217 					// start double buffering
218 
219 					p[i]->StoreExtent();
220 					pi->JoinExtent();
221 
222 					p[i]->DoJoin(pi,s,(depth>0)?((p[i]->join_count>=pi->join_count)?0:1):0);
223 					// The part was join, so it can be deleted ...
224 					for (j=width*height-1;j>=0;j--) {
225 						if (p[j]==pi)	break;
226 					}
227 					if (j>=0)	DropTile(j);
228 
229 					p[i]->UpdateExtent();
230 					if (depth<maxsnapretries)
231 						CheckForJoin(p[i],depth+1);	// recursive call to connect parts
232 					return 1;
233 				}
234 				else {
235 				}
236 			}
237 		}
238 	return 0;
239 }
240 
Rotation()241 void Puzzle::Rotation() {
242 #if (0)
243 Real	tangle;
244 
245 	for (tangle=0;tangle<360;tangle+=10) {
246 		for (int x=0;x<width;x++) {
247 			for (int y=0;y<height;y++) {
248 				P(x,y).Turn(tangle+angle*(x+y));
249 			}
250 		}
251 	}
252 #else
253 	for (int i=0;i<32;i++) {
254 		int x=rand()%width;
255 		int y=rand()%height;
256 		stk->Raise(&P(x,y));
257 		Vec2	dir((rand()%7)-3,(rand()%7)-3);
258 		for (int j=0;j<18;j++) {
259 				P(x,y).MoveTurn(P(x,y).GetPos()+dir,P(x,y).GetDir()+5.0);
260 				if (quit)	return;
261 		}
262 	}
263 #endif
264 }
265 
266