1 /* */
2 /* xemeraldia ----- crack.c */
3 /* */
4
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include "games.h"
10
11 static void fallDownBlocks(void), crushBlocks(void), flushCheckedBlocks(void);
12 static void checkCrack(void), clearCheckBoard(void), setCollisionPoint(void);
13 static void checkShock(int x, int y, cellstatus_t color), checkSameColorBlocks(cellstatus_t selected_color), crackBlocks(int collision_times);
14 static void starComes(void);
15
16 struct CollisionPoint {
17 int x, y;
18 };
19 struct CollisionPoint coll_p[BOARD_WIDTH * BOARD_HEIGHT];
20
21 int coll_num;
22 static int sc_x, sc_y;
23
canMoveDown(void)24 gboolean canMoveDown(void)
25 {
26 return (star_comes || CanItemMove (0, MOVE_DOWN, drop_i.rot))
27 && (!star_comes || CanStarMove (0, MOVE_DOWN));
28 }
29
DropItem()30 gboolean DropItem ()
31 {
32 if (gameover_flag)
33 return FALSE;
34 if (!canMoveDown())
35 {
36 offset_down = 0;
37 printItem ();
38 chain_step = 0;
39 coll_num = 0;
40 if (star_comes)
41 starComes ();
42 else
43 setCollisionPoint ();
44 do
45 {
46 chain_step++;
47 tmp_blocks = 0;
48 checkCrack ();
49 addScore (sc_x, sc_y);
50 coll_num = 0;
51 fallDownBlocks ();
52 } while (coll_num !=0);
53 if (chain_step > 0)
54 {
55 printScore ();
56 printLevel ();
57 }
58 makeNext ();
59 printItem ();
60 } else
61 {
62 if(++offset_down != BLOCK_HEIGHT)
63 {
64 printItem ();
65 return TRUE;
66 }
67 offset_down = 0;
68 moveItem (0, MOVE_DOWN);
69 }
70
71 startTimer();
72 return FALSE;
73 }
74
75
setCollisionPoint()76 static void setCollisionPoint ()
77 {
78 int i;
79
80 for (i = 0; i < 2; i++)
81 {
82 if (board[drop_i.x + iRot_vx[drop_i.rot][iCrChk[drop_i.rot][i]]]
83 [drop_i.y + iRot_vy[drop_i.rot][iCrChk[drop_i.rot][i]] + 1].blk
84 != EMPTY)
85 {
86 coll_num++;
87 coll_p[coll_num].x = drop_i.x
88 + iRot_vx[drop_i.rot][iCrChk[drop_i.rot][i]];
89 coll_p[coll_num].y = drop_i.y
90 + iRot_vy[drop_i.rot][iCrChk[drop_i.rot][i]];
91 }
92 else
93 fallDownBlocks ();
94 }
95 }
96
97
checkCrack()98 static void checkCrack ()
99 {
100 int i;
101
102 for (i = 1; i <= coll_num; i++)
103 {
104 clearCheckBoard ();
105 if (board[coll_p[i].x][coll_p[i].y].blk
106 == board[coll_p[i].x][coll_p[i].y + 1].blk)
107 {
108 if (board[coll_p[i].x][coll_p[i].y].sub == EMPTY_SUB)
109 board[coll_p[i].x][coll_p[i].y].sub = NEW_CRACKED;
110 else
111 {
112 board[coll_p[i].x][coll_p[i].y].sub = DELETE;
113 sc_x = coll_p[i].x; sc_y = coll_p[i].y;
114 }
115 if (board[coll_p[i].x][coll_p[i].y + 1].sub == EMPTY_SUB)
116 board[coll_p[i].x][coll_p[i].y + 1].sub = NEW_CRACKED;
117 else
118 {
119 board[coll_p[i].x][coll_p[i].y + 1].sub = DELETE;
120 sc_x = coll_p[i].x; sc_y = coll_p[i].y;
121 }
122
123 board[coll_p[i].x][coll_p[i].y].chk = CHECKED;
124 board[coll_p[i].x][coll_p[i].y + 1].chk = CHECKED;
125 flushCheckedBlocks ();
126 checkShock (coll_p[i].x, coll_p[i].y,
127 board[coll_p[i].x][coll_p[i].y].blk);
128 checkShock (coll_p[i].x, coll_p[i].y + 1,
129 board[coll_p[i].x][coll_p[i].y].blk);
130 crushBlocks ();
131 crackBlocks (i);
132 }
133 }
134 }
135
136
clearCheckBoard()137 static void clearCheckBoard ()
138 {
139 int x, y;
140
141 for (y = 0; y <= BOARD_HEIGHT - 1; y++)
142 for (x = 1; x <= BOARD_WIDTH; x++)
143 board[x][y].chk = EMPTY;
144 }
145
146
checkShock(int x,int y,cellstatus_t color)147 static void checkShock (int x, int y, cellstatus_t color)
148 {
149 int ix, iy;
150
151 board[x][y].chk = CHECKED;
152
153 for (ix = -1; ix <= 1; ix++)
154 for (iy = -1; iy <= 1; iy++)
155 if ((ix != 0) || (iy != 0))
156 {
157 if ((board[x + ix][y + iy].blk == color)
158 && (board[x + ix][y + iy].chk != CHECKED))
159 {
160 if (board[x + ix][y + iy].sub == EMPTY_SUB)
161 board[x + ix][y + iy].sub = NEW_CRACKED;
162 else
163 if ((board[x + ix][y + iy].sub == CRACKED)
164 ||(board[x + ix][y + iy].sub == NEW_CRACKED))
165 {
166 board[x + ix][y + iy].sub = DELETE;
167 sc_x = x + ix; sc_y = y + iy;
168 }
169 flushCheckedBlocks ();
170 checkShock (x + ix, y + iy, color);
171 }
172 }
173 }
174
175
crackBlocks(int collision_times)176 static void crackBlocks (int collision_times)
177 {
178 int x, y, k, h;
179
180 for (x = 1; x <= BOARD_WIDTH; x++)
181 for (y = 0; y <= BOARD_HEIGHT; y++)
182 {
183 if (board[x][y].sub == NEW_CRACKED)
184 {
185 board[x][y].sub = CRACKED;
186 crack_1_block (x, y);
187 }
188 else
189 if (board[x][y].sub == DELETE)
190 {
191 delete_1_block (x, y);
192 board[x][y].blk = EMPTY;
193 board[x][y].sub = EMPTY_SUB;
194 tmp_blocks++;
195 for (k = collision_times + 1; k <= coll_num; k++)
196 {
197 if ((coll_p[k].x == x) && (coll_p[k].y == y))
198 {
199 for (h = k; h < coll_num; h++)
200 {
201 coll_p[k].x = coll_p[k + 1].x;
202 coll_p[k].y = coll_p[k + 1].y;
203 }
204 coll_num--;
205 k--;
206 }
207 }
208 }
209 }
210 }
211
212
fallDownBlocks()213 static void fallDownBlocks ()
214 {
215 int x, y, wy = BOARD_HEIGHT - 1, wy1, wy2;
216 cellstatus_t lines[BOARD_HEIGHT + 2];
217 cellsubstatus_t sub_lines[BOARD_HEIGHT + 2];
218
219 for (x = 1; x <= BOARD_WIDTH; x++)
220 {
221 while (wy != -1)
222 {
223 if (board[x][wy].blk == EMPTY)
224 {
225 wy1 = wy;
226 while ((wy != -1) && (board[x][wy].blk == EMPTY)) wy--;
227 if (wy != -1)
228 {
229 wy2 = wy - 1;
230 for (y = 0; y <= wy2 + 1; y++)
231 {
232 lines[y] = board[x][y].blk;
233 sub_lines[y] = board[x][y].sub;
234 delete_1_block (x, y);
235 board[x][y].blk = EMPTY;
236 board[x][y].sub = EMPTY_SUB;
237 }
238 for (y = wy1 - wy2 - 1; y <= wy1; y++)
239 {
240 board[x][y].blk = lines[y - wy1 + wy2 + 1];
241 board[x][y].sub = sub_lines[y - wy1 + wy2 + 1];
242 if (board[x][y].blk != EMPTY)
243 printBlock (x, y, board[x][y].blk);
244 }
245 coll_num++;
246 coll_p[coll_num].x = x;
247 coll_p[coll_num].y = wy1;
248 wy = wy1;
249 }
250 }
251 else wy--;
252 }
253 wy = BOARD_HEIGHT - 1;
254 }
255 }
256
257
flushCheckedBlocks()258 static void flushCheckedBlocks ()
259 {
260 int x, y;
261
262 for (x = 1; x <= BOARD_WIDTH; x++)
263 for (y = 0; y <= BOARD_HEIGHT - 1; y++)
264 {
265 if ((board[x][y].sub == NEW_CRACKED)|| (board[x][y].sub == DELETE))
266 delete_1_block (x, y);
267 }
268 gdk_window_process_updates (board_w->window, TRUE);
269 gdk_flush();
270 usleep (28000);
271 for (x = 1; x <= BOARD_WIDTH; x++)
272 for (y = 0; y <= BOARD_HEIGHT - 1; y++)
273 {
274 if ((board[x][y].sub == NEW_CRACKED)|| (board[x][y].sub == DELETE))
275 printBlock (x, y, board[x][y].blk);
276 }
277 gdk_window_process_updates (board_w->window, TRUE);
278 gdk_flush();
279 usleep (28000);
280 }
281
crushBlocks()282 static void crushBlocks ()
283 {
284 int x, y, i;
285
286 for (i = 0; i < CRUSH_ANIME_FRAMES; i++)
287 {
288 for (x = 1; x <= BOARD_WIDTH; x++)
289 for (y = 0; y <= BOARD_HEIGHT - 1; y++)
290 {
291 if (board[x][y].sub == DELETE) crushAnimate (x, y, i);
292 }
293 gdk_window_process_updates (board_w->window, TRUE);
294 gdk_flush();
295 usleep (23000);
296 for (x = 1; x <= BOARD_WIDTH; x++)
297 for (y = 0; y <= BOARD_HEIGHT; y++)
298 {
299 if (board[x][y].sub == DELETE) crushAnimate (x, y, i);
300 }
301 gdk_window_process_updates (board_w->window, TRUE);
302 gdk_flush();
303 usleep (23000);
304 }
305 }
306
307
starComes()308 static void starComes ()
309 {
310 cellstatus_t selected_color = board[drop_i.x][drop_i.y + 1].blk;
311
312 board[drop_i.x][drop_i.y].sub = DELETE;
313 if ((selected_color >= 1) && (selected_color <= BLOCK_VARIETY))
314 checkSameColorBlocks (selected_color);
315
316 crushBlocks ();
317 crackBlocks (0);
318 gdk_window_process_updates (board_w->window, TRUE);
319 gdk_flush();
320 usleep (200000);
321
322 coll_num = 0;
323 fallDownBlocks ();
324 addScore (drop_i.x, drop_i.y + 1);
325 }
326
327
checkSameColorBlocks(cellstatus_t selected_color)328 static void checkSameColorBlocks(cellstatus_t selected_color)
329 {
330 int x, y;
331
332 for (y = 0; y <= BOARD_HEIGHT - 1; y++)
333 for (x = 1; x <= BOARD_WIDTH ; x++)
334 {
335 if (board[x][y].blk == selected_color)
336 {
337 board[x][y].sub = DELETE;
338 board[x][y].chk = CHECKED;
339 flushCheckedBlocks ();
340 }
341 }
342 }
343