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