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